]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[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{
40381db7 518 if (pi->addpath_rx_id)
7533cad7
QY
519 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
520 pi->peer->host, pi->addpath_rx_id);
d62a17ae 521 else
7533cad7 522 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 523}
9fbdd100 524
da0c0ef7
KM
525
526/*
527 * Get the ultimate path info.
528 */
529struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
530{
531 struct bgp_path_info *bpi_ultimate;
532
533 if (info->sub_type != BGP_ROUTE_IMPORTED)
534 return info;
535
536 for (bpi_ultimate = info;
537 bpi_ultimate->extra && bpi_ultimate->extra->parent;
538 bpi_ultimate = bpi_ultimate->extra->parent)
539 ;
540
541 return bpi_ultimate;
542}
543
d62a17ae 544/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
545 */
18ee8310
DS
546static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
547 struct bgp_path_info *exist, int *paths_eq,
548 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
549 char *pfx_buf, afi_t afi, safi_t safi,
550 enum bgp_path_selection_reason *reason)
d62a17ae 551{
5df26422 552 const struct prefix *new_p;
d62a17ae 553 struct attr *newattr, *existattr;
3061acc2
DA
554 enum bgp_peer_sort new_sort;
555 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
556 uint32_t new_pref;
557 uint32_t exist_pref;
558 uint32_t new_med;
559 uint32_t exist_med;
560 uint32_t new_weight;
561 uint32_t exist_weight;
d62a17ae 562 uint32_t newm, existm;
563 struct in_addr new_id;
564 struct in_addr exist_id;
565 int new_cluster;
566 int exist_cluster;
567 int internal_as_route;
568 int confed_as_route;
04d14c8b 569 int ret = 0;
ee88563a
JM
570 int igp_metric_ret = 0;
571 int peer_sort_ret = -1;
d62a17ae 572 char new_buf[PATH_ADDPATH_STR_BUFFER];
573 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
574 uint32_t new_mm_seq;
575 uint32_t exist_mm_seq;
6d8c603a 576 int nh_cmp;
d071f237
AK
577 esi_t *exist_esi;
578 esi_t *new_esi;
579 bool same_esi;
580 bool old_proxy;
581 bool new_proxy;
33c6e933 582 bool new_origin, exist_origin;
da0c0ef7 583 struct bgp_path_info *bpi_ultimate;
d62a17ae 584
585 *paths_eq = 0;
586
587 /* 0. Null check. */
588 if (new == NULL) {
fdf81fa0 589 *reason = bgp_path_selection_none;
d62a17ae 590 if (debug)
591 zlog_debug("%s: new is NULL", pfx_buf);
592 return 0;
593 }
2ec1e66f 594
da0c0ef7
KM
595 if (debug) {
596 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
597 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 598 sizeof(new_buf));
da0c0ef7 599 }
718e3744 600
d62a17ae 601 if (exist == NULL) {
fdf81fa0 602 *reason = bgp_path_selection_first;
d62a17ae 603 if (debug)
4378495a
DS
604 zlog_debug("%s(%s): %s is the initial bestpath",
605 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 606 return 1;
607 }
2ec1e66f 608
d62a17ae 609 if (debug) {
da0c0ef7
KM
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 612 sizeof(exist_buf));
4378495a
DS
613 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
614 pfx_buf, bgp->name_pretty, new_buf, new->flags,
615 exist_buf, exist->flags);
d62a17ae 616 }
8ff56318 617
d62a17ae 618 newattr = new->attr;
619 existattr = exist->attr;
620
1479ed2f
DA
621 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
622 * Capability" to a neighbor MUST perform the following upon receiving
623 * a route from that neighbor with the "LLGR_STALE" community, or upon
624 * attaching the "LLGR_STALE" community itself per Section 4.2:
625 *
626 * Treat the route as the least-preferred in route selection (see
627 * below). See the Risks of Depreferencing Routes section (Section 5.2)
628 * for a discussion of potential risks inherent in doing this.
629 */
9a706b42
DA
630 if (bgp_attr_get_community(newattr) &&
631 community_include(bgp_attr_get_community(newattr),
632 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
633 if (debug)
634 zlog_debug(
635 "%s: %s wins over %s due to LLGR_STALE community",
636 pfx_buf, new_buf, exist_buf);
637 return 0;
638 }
639
9a706b42
DA
640 if (bgp_attr_get_community(existattr) &&
641 community_include(bgp_attr_get_community(existattr),
642 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
643 if (debug)
644 zlog_debug(
645 "%s: %s loses to %s due to LLGR_STALE community",
646 pfx_buf, new_buf, exist_buf);
647 return 1;
648 }
649
5df26422
NS
650 new_p = bgp_dest_get_prefix(new->net);
651
d62a17ae 652 /* For EVPN routes, we cannot just go by local vs remote, we have to
653 * look at the MAC mobility sequence number, if present.
654 */
5df26422
NS
655 if ((safi == SAFI_EVPN)
656 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 657 /* This is an error condition described in RFC 7432 Section
658 * 15.2. The RFC
659 * states that in this scenario "the PE MUST alert the operator"
660 * but it
661 * does not state what other action to take. In order to provide
662 * some
663 * consistency in this scenario we are going to prefer the path
664 * with the
665 * sticky flag.
666 */
667 if (newattr->sticky != existattr->sticky) {
668 if (!debug) {
5df26422
NS
669 prefix2str(new_p, pfx_buf,
670 sizeof(*pfx_buf)
671 * PREFIX2STR_BUFFER);
18ee8310 672 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
673 new, new_buf, sizeof(new_buf));
674 bgp_path_info_path_with_addpath_rx_str(
675 exist, exist_buf, sizeof(exist_buf));
d62a17ae 676 }
677
678 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 679 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
680 if (debug)
681 zlog_debug(
682 "%s: %s wins over %s due to sticky MAC flag",
683 pfx_buf, new_buf, exist_buf);
d62a17ae 684 return 1;
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 loses to %s due to sticky MAC flag",
692 pfx_buf, new_buf, exist_buf);
d62a17ae 693 return 0;
694 }
695 }
128ea8ab 696
d071f237
AK
697 new_esi = bgp_evpn_attr_get_esi(newattr);
698 exist_esi = bgp_evpn_attr_get_esi(existattr);
699 if (bgp_evpn_is_esi_valid(new_esi) &&
700 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
701 same_esi = true;
702 } else {
703 same_esi = false;
704 }
705
706 /* If both paths have the same non-zero ES and
707 * one path is local it wins.
708 * PS: Note the local path wins even if the remote
709 * has the higher MM seq. The local path's
710 * MM seq will be fixed up to match the highest
711 * rem seq, subsequently.
712 */
713 if (same_esi) {
714 char esi_buf[ESI_STR_LEN];
715
716 if (bgp_evpn_is_path_local(bgp, new)) {
717 *reason = bgp_path_selection_evpn_local_path;
718 if (debug)
719 zlog_debug(
720 "%s: %s wins over %s as ES %s is same and local",
721 pfx_buf, new_buf, exist_buf,
722 esi_to_str(new_esi, esi_buf,
723 sizeof(esi_buf)));
724 return 1;
725 }
726 if (bgp_evpn_is_path_local(bgp, exist)) {
727 *reason = bgp_path_selection_evpn_local_path;
728 if (debug)
729 zlog_debug(
730 "%s: %s loses to %s as ES %s is same and local",
731 pfx_buf, new_buf, exist_buf,
732 esi_to_str(new_esi, esi_buf,
733 sizeof(esi_buf)));
734 return 0;
735 }
736 }
737
d62a17ae 738 new_mm_seq = mac_mobility_seqnum(newattr);
739 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 740
d62a17ae 741 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 742 *reason = bgp_path_selection_evpn_seq;
d62a17ae 743 if (debug)
744 zlog_debug(
745 "%s: %s wins over %s due to MM seq %u > %u",
746 pfx_buf, new_buf, exist_buf, new_mm_seq,
747 exist_mm_seq);
748 return 1;
749 }
8ff56318 750
d62a17ae 751 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 752 *reason = bgp_path_selection_evpn_seq;
d62a17ae 753 if (debug)
754 zlog_debug(
755 "%s: %s loses to %s due to MM seq %u < %u",
756 pfx_buf, new_buf, exist_buf, new_mm_seq,
757 exist_mm_seq);
758 return 0;
759 }
6d8c603a 760
d071f237
AK
761 /* if the sequence numbers and ESI are the same and one path
762 * is non-proxy it wins (over proxy)
763 */
764 new_proxy = bgp_evpn_attr_is_proxy(newattr);
765 old_proxy = bgp_evpn_attr_is_proxy(existattr);
766 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
767 old_proxy != new_proxy) {
768 if (!new_proxy) {
769 *reason = bgp_path_selection_evpn_non_proxy;
770 if (debug)
771 zlog_debug(
772 "%s: %s wins over %s, same seq/es and non-proxy",
773 pfx_buf, new_buf, exist_buf);
774 return 1;
775 }
776
777 *reason = bgp_path_selection_evpn_non_proxy;
778 if (debug)
779 zlog_debug(
780 "%s: %s loses to %s, same seq/es and non-proxy",
781 pfx_buf, new_buf, exist_buf);
782 return 0;
783 }
784
6d8c603a
AK
785 /*
786 * if sequence numbers are the same path with the lowest IP
787 * wins
788 */
789 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
790 if (nh_cmp < 0) {
fdf81fa0 791 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
792 if (debug)
793 zlog_debug(
23d0a753 794 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 795 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 796 &new->attr->nexthop);
6d8c603a
AK
797 return 1;
798 }
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 loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 804 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 805 &new->attr->nexthop);
6d8c603a
AK
806 return 0;
807 }
d62a17ae 808 }
9fbdd100 809
d62a17ae 810 /* 1. Weight check. */
d62a17ae 811 new_weight = newattr->weight;
812 exist_weight = existattr->weight;
8ff56318 813
d62a17ae 814 if (new_weight > exist_weight) {
fdf81fa0 815 *reason = bgp_path_selection_weight;
d62a17ae 816 if (debug)
817 zlog_debug("%s: %s wins over %s due to weight %d > %d",
818 pfx_buf, new_buf, exist_buf, new_weight,
819 exist_weight);
820 return 1;
821 }
718e3744 822
d62a17ae 823 if (new_weight < exist_weight) {
fdf81fa0 824 *reason = bgp_path_selection_weight;
d62a17ae 825 if (debug)
826 zlog_debug("%s: %s loses to %s due to weight %d < %d",
827 pfx_buf, new_buf, exist_buf, new_weight,
828 exist_weight);
829 return 0;
830 }
9fbdd100 831
d62a17ae 832 /* 2. Local preference check. */
833 new_pref = exist_pref = bgp->default_local_pref;
834
835 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
836 new_pref = newattr->local_pref;
837 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
838 exist_pref = existattr->local_pref;
839
840 if (new_pref > exist_pref) {
fdf81fa0 841 *reason = bgp_path_selection_local_pref;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to localpref %d > %d",
845 pfx_buf, new_buf, exist_buf, new_pref,
846 exist_pref);
847 return 1;
848 }
718e3744 849
d62a17ae 850 if (new_pref < exist_pref) {
fdf81fa0 851 *reason = bgp_path_selection_local_pref;
d62a17ae 852 if (debug)
853 zlog_debug(
854 "%s: %s loses to %s due to localpref %d < %d",
855 pfx_buf, new_buf, exist_buf, new_pref,
856 exist_pref);
857 return 0;
858 }
9fbdd100 859
46dbf9d0
DA
860 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
861 * extensions defined in this document, the following step is inserted
862 * after the LOCAL_PREF comparison step in the BGP decision process:
863 * When comparing a pair of routes for a BGP destination, the
864 * route with the ACCEPT_OWN community attached is preferred over
865 * the route that does not have the community.
866 * This extra step MUST only be invoked during the best path selection
867 * process of VPN-IP routes.
868 */
869 if (safi == SAFI_MPLS_VPN &&
870 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
871 CHECK_FLAG(exist->peer->af_flags[afi][safi],
872 PEER_FLAG_ACCEPT_OWN))) {
873 bool new_accept_own = false;
874 bool exist_accept_own = false;
875 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
876
877 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
878 new_accept_own = community_include(
879 bgp_attr_get_community(newattr), accept_own);
880 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
881 exist_accept_own = community_include(
882 bgp_attr_get_community(existattr), accept_own);
883
884 if (new_accept_own && !exist_accept_own) {
885 *reason = bgp_path_selection_accept_own;
886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to accept-own",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
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 loses to %s due to accept-own",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
900 }
901 }
902
97a52c82
DA
903 /* Tie-breaker - AIGP (Metric TLV) attribute */
904 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
905 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
906 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
907 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
908 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
909
910 if (new_aigp < exist_aigp) {
911 *reason = bgp_path_selection_aigp;
912 if (debug)
913 zlog_debug(
914 "%s: %s wins over %s due to AIGP %" PRIu64
915 " < %" PRIu64,
916 pfx_buf, new_buf, exist_buf, new_aigp,
917 exist_aigp);
918 return 1;
919 }
920
921 if (new_aigp > exist_aigp) {
922 *reason = bgp_path_selection_aigp;
923 if (debug)
924 zlog_debug(
925 "%s: %s loses to %s due to AIGP %" PRIu64
926 " > %" PRIu64,
927 pfx_buf, new_buf, exist_buf, new_aigp,
928 exist_aigp);
929 return 0;
930 }
931 }
932
d62a17ae 933 /* 3. Local route check. We prefer:
934 * - BGP_ROUTE_STATIC
935 * - BGP_ROUTE_AGGREGATE
936 * - BGP_ROUTE_REDISTRIBUTE
937 */
33c6e933
DS
938 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
939 new->sub_type == BGP_ROUTE_IMPORTED);
940 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
941 exist->sub_type == BGP_ROUTE_IMPORTED);
942
943 if (new_origin && !exist_origin) {
fdf81fa0 944 *reason = bgp_path_selection_local_route;
d62a17ae 945 if (debug)
946 zlog_debug(
947 "%s: %s wins over %s due to preferred BGP_ROUTE type",
948 pfx_buf, new_buf, exist_buf);
949 return 1;
950 }
718e3744 951
33c6e933 952 if (!new_origin && exist_origin) {
fdf81fa0 953 *reason = bgp_path_selection_local_route;
d62a17ae 954 if (debug)
955 zlog_debug(
956 "%s: %s loses to %s due to preferred BGP_ROUTE type",
957 pfx_buf, new_buf, exist_buf);
958 return 0;
6811845b 959 }
718e3744 960
da0c0ef7
KM
961 /* Here if these are imported routes then get ultimate pi for
962 * path compare.
963 */
964 new = bgp_get_imported_bpi_ultimate(new);
965 exist = bgp_get_imported_bpi_ultimate(exist);
966 newattr = new->attr;
967 existattr = exist->attr;
968
d62a17ae 969 /* 4. AS path length check. */
892fedb6 970 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 971 int exist_hops = aspath_count_hops(existattr->aspath);
972 int exist_confeds = aspath_count_confeds(existattr->aspath);
973
892fedb6 974 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 975 int aspath_hops;
976
977 aspath_hops = aspath_count_hops(newattr->aspath);
978 aspath_hops += aspath_count_confeds(newattr->aspath);
979
980 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 981 *reason = bgp_path_selection_confed_as_path;
d62a17ae 982 if (debug)
983 zlog_debug(
984 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
985 pfx_buf, new_buf, exist_buf,
986 aspath_hops,
987 (exist_hops + exist_confeds));
988 return 1;
989 }
990
991 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 992 *reason = bgp_path_selection_confed_as_path;
d62a17ae 993 if (debug)
994 zlog_debug(
995 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
996 pfx_buf, new_buf, exist_buf,
997 aspath_hops,
998 (exist_hops + exist_confeds));
999 return 0;
1000 }
1001 } else {
1002 int newhops = aspath_count_hops(newattr->aspath);
1003
1004 if (newhops < exist_hops) {
fdf81fa0 1005 *reason = bgp_path_selection_as_path;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to aspath hopcount %d < %d",
1009 pfx_buf, new_buf, exist_buf,
1010 newhops, exist_hops);
1011 return 1;
1012 }
1013
1014 if (newhops > exist_hops) {
fdf81fa0 1015 *reason = bgp_path_selection_as_path;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to aspath hopcount %d > %d",
1019 pfx_buf, new_buf, exist_buf,
1020 newhops, exist_hops);
1021 return 0;
1022 }
1023 }
1024 }
9fbdd100 1025
d62a17ae 1026 /* 5. Origin check. */
1027 if (newattr->origin < existattr->origin) {
fdf81fa0 1028 *reason = bgp_path_selection_origin;
d62a17ae 1029 if (debug)
1030 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1031 pfx_buf, new_buf, exist_buf,
1032 bgp_origin_long_str[newattr->origin],
1033 bgp_origin_long_str[existattr->origin]);
1034 return 1;
1035 }
718e3744 1036
d62a17ae 1037 if (newattr->origin > existattr->origin) {
fdf81fa0 1038 *reason = bgp_path_selection_origin;
d62a17ae 1039 if (debug)
1040 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1041 pfx_buf, new_buf, exist_buf,
1042 bgp_origin_long_str[newattr->origin],
1043 bgp_origin_long_str[existattr->origin]);
1044 return 0;
1045 }
718e3744 1046
d62a17ae 1047 /* 6. MED check. */
1048 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1049 && aspath_count_hops(existattr->aspath) == 0);
1050 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1051 && aspath_count_confeds(existattr->aspath) > 0
1052 && aspath_count_hops(newattr->aspath) == 0
1053 && aspath_count_hops(existattr->aspath) == 0);
1054
892fedb6
DA
1055 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1056 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1057 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1058 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1059 || internal_as_route) {
1060 new_med = bgp_med_value(new->attr, bgp);
1061 exist_med = bgp_med_value(exist->attr, bgp);
1062
1063 if (new_med < exist_med) {
fdf81fa0 1064 *reason = bgp_path_selection_med;
d62a17ae 1065 if (debug)
1066 zlog_debug(
1067 "%s: %s wins over %s due to MED %d < %d",
1068 pfx_buf, new_buf, exist_buf, new_med,
1069 exist_med);
1070 return 1;
1071 }
8ff56318 1072
d62a17ae 1073 if (new_med > exist_med) {
fdf81fa0 1074 *reason = bgp_path_selection_med;
d62a17ae 1075 if (debug)
1076 zlog_debug(
1077 "%s: %s loses to %s due to MED %d > %d",
1078 pfx_buf, new_buf, exist_buf, new_med,
1079 exist_med);
1080 return 0;
1081 }
1082 }
9fbdd100 1083
d62a17ae 1084 /* 7. Peer type check. */
1085 new_sort = new->peer->sort;
1086 exist_sort = exist->peer->sort;
1087
1088 if (new_sort == BGP_PEER_EBGP
1089 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1090 *reason = bgp_path_selection_peer;
d62a17ae 1091 if (debug)
1092 zlog_debug(
1093 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1094 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1095 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1096 return 1;
1097 peer_sort_ret = 1;
d62a17ae 1098 }
718e3744 1099
d62a17ae 1100 if (exist_sort == BGP_PEER_EBGP
1101 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1102 *reason = bgp_path_selection_peer;
d62a17ae 1103 if (debug)
1104 zlog_debug(
1105 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1106 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1107 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1108 return 0;
1109 peer_sort_ret = 0;
d62a17ae 1110 }
8ff56318 1111
d62a17ae 1112 /* 8. IGP metric check. */
1113 newm = existm = 0;
8ff56318 1114
d62a17ae 1115 if (new->extra)
1116 newm = new->extra->igpmetric;
1117 if (exist->extra)
1118 existm = exist->extra->igpmetric;
9fbdd100 1119
d62a17ae 1120 if (newm < existm) {
ee88563a 1121 if (debug && peer_sort_ret < 0)
d62a17ae 1122 zlog_debug(
d588b995 1123 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1124 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1125 igp_metric_ret = 1;
d62a17ae 1126 }
718e3744 1127
d62a17ae 1128 if (newm > existm) {
ee88563a 1129 if (debug && peer_sort_ret < 0)
d62a17ae 1130 zlog_debug(
d588b995 1131 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1132 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1133 igp_metric_ret = 0;
5e242b0d 1134 }
5e242b0d 1135
d62a17ae 1136 /* 9. Same IGP metric. Compare the cluster list length as
1137 representative of IGP hops metric. Rewrite the metric value
1138 pair (newm, existm) with the cluster list length. Prefer the
1139 path with smaller cluster list length. */
1140 if (newm == existm) {
aa53c036
DS
1141 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1142 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1143 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1144 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1145 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1146
1147 if (newm < existm) {
ee88563a 1148 if (debug && peer_sort_ret < 0)
d62a17ae 1149 zlog_debug(
d588b995 1150 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1151 pfx_buf, new_buf, exist_buf,
1152 newm, existm);
ee88563a 1153 igp_metric_ret = 1;
d62a17ae 1154 }
1155
1156 if (newm > existm) {
ee88563a 1157 if (debug && peer_sort_ret < 0)
d62a17ae 1158 zlog_debug(
d588b995 1159 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1160 pfx_buf, new_buf, exist_buf,
1161 newm, existm);
ee88563a 1162 igp_metric_ret = 0;
d62a17ae 1163 }
1164 }
1165 }
31a4638f 1166
d62a17ae 1167 /* 10. confed-external vs. confed-internal */
1168 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1169 if (new_sort == BGP_PEER_CONFED
1170 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1171 *reason = bgp_path_selection_confed;
d62a17ae 1172 if (debug)
1173 zlog_debug(
1174 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1175 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1176 if (!CHECK_FLAG(bgp->flags,
1177 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1178 return 1;
1179 peer_sort_ret = 1;
d62a17ae 1180 }
718e3744 1181
d62a17ae 1182 if (exist_sort == BGP_PEER_CONFED
1183 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1184 *reason = bgp_path_selection_confed;
d62a17ae 1185 if (debug)
1186 zlog_debug(
1187 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1188 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1189 if (!CHECK_FLAG(bgp->flags,
1190 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1191 return 0;
1192 peer_sort_ret = 0;
d62a17ae 1193 }
1194 }
718e3744 1195
d62a17ae 1196 /* 11. Maximum path check. */
1197 if (newm == existm) {
1198 /* If one path has a label but the other does not, do not treat
1199 * them as equals for multipath
1200 */
d2d71b04 1201 int newl, existl;
1202
1203 newl = existl = 0;
1204
1205 if (new->extra)
1206 newl = new->extra->num_labels;
1207 if (exist->extra)
1208 existl = exist->extra->num_labels;
1209 if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
1210 (exist->extra &&
1211 bgp_is_valid_label(&exist->extra->label[0]))) ||
1212 (newl != existl)) {
d62a17ae 1213 if (debug)
1214 zlog_debug(
1215 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1216 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1217 } else if (CHECK_FLAG(bgp->flags,
1218 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1219
1220 /*
1221 * For the two paths, all comparison steps till IGP
1222 * metric
1223 * have succeeded - including AS_PATH hop count. Since
1224 * 'bgp
1225 * bestpath as-path multipath-relax' knob is on, we
1226 * don't need
1227 * an exact match of AS_PATH. Thus, mark the paths are
1228 * equal.
1229 * That will trigger both these paths to get into the
1230 * multipath
1231 * array.
1232 */
1233 *paths_eq = 1;
1234
1235 if (debug)
1236 zlog_debug(
1237 "%s: %s and %s are equal via multipath-relax",
1238 pfx_buf, new_buf, exist_buf);
1239 } else if (new->peer->sort == BGP_PEER_IBGP) {
1240 if (aspath_cmp(new->attr->aspath,
1241 exist->attr->aspath)) {
1242 *paths_eq = 1;
1243
1244 if (debug)
1245 zlog_debug(
1246 "%s: %s and %s are equal via matching aspaths",
1247 pfx_buf, new_buf, exist_buf);
1248 }
1249 } else if (new->peer->as == exist->peer->as) {
1250 *paths_eq = 1;
1251
1252 if (debug)
1253 zlog_debug(
1254 "%s: %s and %s are equal via same remote-as",
1255 pfx_buf, new_buf, exist_buf);
1256 }
1257 } else {
1258 /*
1259 * TODO: If unequal cost ibgp multipath is enabled we can
1260 * mark the paths as equal here instead of returning
1261 */
ee88563a
JM
1262
1263 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1264 * if either step 7 or 10 (peer type checks) yielded a winner,
1265 * that result was returned immediately. Returning from step 10
1266 * ignored the return value computed in steps 8 and 9 (IGP
1267 * metric checks). In order to preserve that behavior, if
1268 * peer_sort_ret is set, return that rather than igp_metric_ret.
1269 */
1270 ret = peer_sort_ret;
1271 if (peer_sort_ret < 0) {
1272 ret = igp_metric_ret;
1273 if (debug) {
1274 if (ret == 1)
1275 zlog_debug(
1276 "%s: %s wins over %s after IGP metric comparison",
1277 pfx_buf, new_buf, exist_buf);
1278 else
1279 zlog_debug(
1280 "%s: %s loses to %s after IGP metric comparison",
1281 pfx_buf, new_buf, exist_buf);
1282 }
1283 *reason = bgp_path_selection_igp_metric;
d62a17ae 1284 }
1285 return ret;
1286 }
718e3744 1287
ee88563a
JM
1288 /*
1289 * At this point, the decision whether to set *paths_eq = 1 has been
1290 * completed. If we deferred returning because of bestpath peer-type
1291 * relax configuration, return now.
1292 */
1293 if (peer_sort_ret >= 0)
1294 return peer_sort_ret;
1295
d62a17ae 1296 /* 12. If both paths are external, prefer the path that was received
1297 first (the oldest one). This step minimizes route-flap, since a
1298 newer path won't displace an older one, even if it was the
1299 preferred route based on the additional decision criteria below. */
892fedb6 1300 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1301 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1302 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1303 *reason = bgp_path_selection_older;
d62a17ae 1304 if (debug)
1305 zlog_debug(
1306 "%s: %s wins over %s due to oldest external",
1307 pfx_buf, new_buf, exist_buf);
1308 return 1;
1309 }
9fbdd100 1310
1defdda8 1311 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1312 *reason = bgp_path_selection_older;
d62a17ae 1313 if (debug)
1314 zlog_debug(
1315 "%s: %s loses to %s due to oldest external",
1316 pfx_buf, new_buf, exist_buf);
1317 return 0;
1318 }
1319 }
718e3744 1320
ce5002c6 1321 /* 13. Router-ID comparison. */
d62a17ae 1322 /* If one of the paths is "stale", the corresponding peer router-id will
1323 * be 0 and would always win over the other path. If originator id is
ce5002c6 1324 * used for the comparison, it will decide which path is better.
d62a17ae 1325 */
1326 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1327 new_id.s_addr = newattr->originator_id.s_addr;
1328 else
1329 new_id.s_addr = new->peer->remote_id.s_addr;
1330 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1331 exist_id.s_addr = existattr->originator_id.s_addr;
1332 else
1333 exist_id.s_addr = exist->peer->remote_id.s_addr;
1334
1335 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1336 *reason = bgp_path_selection_router_id;
d62a17ae 1337 if (debug)
1338 zlog_debug(
1339 "%s: %s wins over %s due to Router-ID comparison",
1340 pfx_buf, new_buf, exist_buf);
1341 return 1;
1342 }
718e3744 1343
d62a17ae 1344 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1345 *reason = bgp_path_selection_router_id;
d62a17ae 1346 if (debug)
1347 zlog_debug(
1348 "%s: %s loses to %s due to Router-ID comparison",
1349 pfx_buf, new_buf, exist_buf);
1350 return 0;
1351 }
9fbdd100 1352
ce5002c6 1353 /* 14. Cluster length comparison. */
d62a17ae 1354 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1355 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1356
1357 if (new_cluster < exist_cluster) {
fdf81fa0 1358 *reason = bgp_path_selection_cluster_length;
d62a17ae 1359 if (debug)
1360 zlog_debug(
1361 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1362 pfx_buf, new_buf, exist_buf, new_cluster,
1363 exist_cluster);
1364 return 1;
1365 }
718e3744 1366
d62a17ae 1367 if (new_cluster > exist_cluster) {
fdf81fa0 1368 *reason = bgp_path_selection_cluster_length;
d62a17ae 1369 if (debug)
1370 zlog_debug(
1371 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1372 pfx_buf, new_buf, exist_buf, new_cluster,
1373 exist_cluster);
1374 return 0;
1375 }
9fbdd100 1376
ce5002c6 1377 /* 15. Neighbor address comparison. */
d62a17ae 1378 /* Do this only if neither path is "stale" as stale paths do not have
1379 * valid peer information (as the connection may or may not be up).
1380 */
1defdda8 1381 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1382 *reason = bgp_path_selection_stale;
d62a17ae 1383 if (debug)
1384 zlog_debug(
1385 "%s: %s wins over %s due to latter path being STALE",
1386 pfx_buf, new_buf, exist_buf);
1387 return 1;
1388 }
0de5153c 1389
1defdda8 1390 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1391 *reason = bgp_path_selection_stale;
d62a17ae 1392 if (debug)
1393 zlog_debug(
1394 "%s: %s loses to %s due to former path being STALE",
1395 pfx_buf, new_buf, exist_buf);
1396 return 0;
1397 }
718e3744 1398
d62a17ae 1399 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1400 if (new->peer->su_remote == NULL) {
1401 *reason = bgp_path_selection_local_configured;
d62a17ae 1402 return 0;
fdf81fa0
DS
1403 }
1404 if (exist->peer->su_remote == NULL) {
1405 *reason = bgp_path_selection_local_configured;
d62a17ae 1406 return 1;
fdf81fa0 1407 }
9fbdd100 1408
d62a17ae 1409 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1410
1411 if (ret == 1) {
fdf81fa0 1412 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1413 if (debug)
1414 zlog_debug(
1415 "%s: %s loses to %s due to Neighor IP comparison",
1416 pfx_buf, new_buf, exist_buf);
1417 return 0;
1418 }
1419
1420 if (ret == -1) {
fdf81fa0 1421 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1422 if (debug)
1423 zlog_debug(
1424 "%s: %s wins over %s due to Neighor IP comparison",
1425 pfx_buf, new_buf, exist_buf);
1426 return 1;
1427 }
9fbdd100 1428
fdf81fa0 1429 *reason = bgp_path_selection_default;
d62a17ae 1430 if (debug)
1431 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1432 pfx_buf, new_buf, exist_buf);
718e3744 1433
d62a17ae 1434 return 1;
718e3744 1435}
1436
d071f237
AK
1437
1438int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1439 struct bgp_path_info *exist, int *paths_eq)
1440{
1441 enum bgp_path_selection_reason reason;
1442 char pfx_buf[PREFIX2STR_BUFFER];
1443
1444 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1445 AFI_L2VPN, SAFI_EVPN, &reason);
1446}
1447
65efcfce
LB
1448/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1449 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1450 * multipath is enabled
65efcfce 1451 * This version is compatible with */
18ee8310
DS
1452int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1453 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1454 afi_t afi, safi_t safi,
1455 enum bgp_path_selection_reason *reason)
d62a17ae 1456{
1457 int paths_eq;
1458 int ret;
18ee8310 1459 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1460 afi, safi, reason);
d62a17ae 1461
1462 if (paths_eq)
1463 ret = 0;
1464 else {
1465 if (ret == 1)
1466 ret = -1;
1467 else
1468 ret = 1;
1469 }
1470 return ret;
65efcfce
LB
1471}
1472
5a1ae2c2
DS
1473static enum filter_type bgp_input_filter(struct peer *peer,
1474 const struct prefix *p,
d62a17ae 1475 struct attr *attr, afi_t afi,
1476 safi_t safi)
718e3744 1477{
d62a17ae 1478 struct bgp_filter *filter;
6401252f 1479 enum filter_type ret = FILTER_PERMIT;
718e3744 1480
d62a17ae 1481 filter = &peer->filter[afi][safi];
718e3744 1482
d62a17ae 1483#define FILTER_EXIST_WARN(F, f, filter) \
1484 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1485 zlog_debug("%s: Could not find configured input %s-list %s!", \
1486 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1487
1488 if (DISTRIBUTE_IN_NAME(filter)) {
1489 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1490
6401252f
QY
1491 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1492 == FILTER_DENY) {
1493 ret = FILTER_DENY;
1494 goto done;
1495 }
d62a17ae 1496 }
1497
1498 if (PREFIX_LIST_IN_NAME(filter)) {
1499 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1500
6401252f
QY
1501 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1502 == PREFIX_DENY) {
1503 ret = FILTER_DENY;
1504 goto done;
1505 }
d62a17ae 1506 }
1507
1508 if (FILTER_LIST_IN_NAME(filter)) {
1509 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1510
1511 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1512 == AS_FILTER_DENY) {
1513 ret = FILTER_DENY;
1514 goto done;
1515 }
d62a17ae 1516 }
1517
6401252f 1518done:
c7bb4f00 1519 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1520 char pfxprint[PREFIX2STR_BUFFER];
1521
1522 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1523 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1524 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1525 }
1526
1527 return ret;
650f76c2 1528#undef FILTER_EXIST_WARN
718e3744 1529}
1530
b8685f9b
DS
1531static enum filter_type bgp_output_filter(struct peer *peer,
1532 const struct prefix *p,
d62a17ae 1533 struct attr *attr, afi_t afi,
1534 safi_t safi)
718e3744 1535{
d62a17ae 1536 struct bgp_filter *filter;
6401252f 1537 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1538
1539 filter = &peer->filter[afi][safi];
1540
1541#define FILTER_EXIST_WARN(F, f, filter) \
1542 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1543 zlog_debug("%s: Could not find configured output %s-list %s!", \
1544 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1545
d62a17ae 1546 if (DISTRIBUTE_OUT_NAME(filter)) {
1547 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1548
6401252f
QY
1549 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1550 == FILTER_DENY) {
1551 ret = FILTER_DENY;
1552 goto done;
1553 }
d62a17ae 1554 }
1555
1556 if (PREFIX_LIST_OUT_NAME(filter)) {
1557 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1558
d62a17ae 1559 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1560 == PREFIX_DENY) {
1561 ret = FILTER_DENY;
1562 goto done;
1563 }
d62a17ae 1564 }
718e3744 1565
d62a17ae 1566 if (FILTER_LIST_OUT_NAME(filter)) {
1567 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1568
d62a17ae 1569 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1570 == AS_FILTER_DENY) {
1571 ret = FILTER_DENY;
1572 goto done;
1573 }
1574 }
1575
c7bb4f00 1576 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1577 char pfxprint[PREFIX2STR_BUFFER];
1578
1579 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1580 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1581 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1582 }
718e3744 1583
6401252f
QY
1584done:
1585 return ret;
650f76c2 1586#undef FILTER_EXIST_WARN
718e3744 1587}
1588
1589/* If community attribute includes no_export then return 1. */
3dc339cd 1590static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1591{
9a706b42 1592 if (bgp_attr_get_community(attr)) {
d62a17ae 1593 /* NO_ADVERTISE check. */
9a706b42
DA
1594 if (community_include(bgp_attr_get_community(attr),
1595 COMMUNITY_NO_ADVERTISE))
3dc339cd 1596 return true;
d62a17ae 1597
1598 /* NO_EXPORT check. */
9a706b42
DA
1599 if (peer->sort == BGP_PEER_EBGP &&
1600 community_include(bgp_attr_get_community(attr),
1601 COMMUNITY_NO_EXPORT))
3dc339cd 1602 return true;
d62a17ae 1603
1604 /* NO_EXPORT_SUBCONFED check. */
1605 if (peer->sort == BGP_PEER_EBGP
1606 || peer->sort == BGP_PEER_CONFED)
9a706b42 1607 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1608 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1609 return true;
d62a17ae 1610 }
3dc339cd 1611 return false;
718e3744 1612}
1613
1614/* Route reflection loop check. */
3dc339cd 1615static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1616{
d62a17ae 1617 struct in_addr cluster_id;
779fee93 1618 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1619
779fee93 1620 if (cluster) {
d62a17ae 1621 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1622 cluster_id = peer->bgp->cluster_id;
1623 else
1624 cluster_id = peer->bgp->router_id;
1625
779fee93 1626 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1627 return true;
d62a17ae 1628 }
3dc339cd 1629 return false;
718e3744 1630}
6b0655a2 1631
d864dd9e
EB
1632static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1633{
1634 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1635 if (peer->local_role == ROLE_PROVIDER ||
1636 peer->local_role == ROLE_RS_SERVER)
1637 return true;
1638 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1639 return true;
1640 return false;
1641 }
1642 if (peer->local_role == ROLE_CUSTOMER ||
1643 peer->local_role == ROLE_PEER ||
1644 peer->local_role == ROLE_RS_CLIENT) {
1645 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1646 attr->otc = peer->as;
1647 }
1648 return false;
1649}
1650
1651static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1652{
1653 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1654 if (peer->local_role == ROLE_CUSTOMER ||
1655 peer->local_role == ROLE_RS_CLIENT ||
1656 peer->local_role == ROLE_PEER)
1657 return true;
1658 return false;
1659 }
1660 if (peer->local_role == ROLE_PROVIDER ||
1661 peer->local_role == ROLE_PEER ||
1662 peer->local_role == ROLE_RS_SERVER) {
1663 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1664 attr->otc = peer->bgp->as;
1665 }
1666 return false;
1667}
1668
5a78f2bc
EB
1669static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1670{
1671 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1672}
1673
5a1ae2c2 1674static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1675 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1676 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1677 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1678{
d62a17ae 1679 struct bgp_filter *filter;
82b692c0
LK
1680 struct bgp_path_info rmap_path = { 0 };
1681 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1682 route_map_result_t ret;
1683 struct route_map *rmap = NULL;
718e3744 1684
d62a17ae 1685 filter = &peer->filter[afi][safi];
718e3744 1686
d62a17ae 1687 /* Apply default weight value. */
1688 if (peer->weight[afi][safi])
1689 attr->weight = peer->weight[afi][safi];
718e3744 1690
d62a17ae 1691 if (rmap_name) {
1692 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1693
d62a17ae 1694 if (rmap == NULL)
1695 return RMAP_DENY;
1696 } else {
1697 if (ROUTE_MAP_IN_NAME(filter)) {
1698 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1699
d62a17ae 1700 if (rmap == NULL)
1701 return RMAP_DENY;
1702 }
1703 }
0b16f239 1704
d62a17ae 1705 /* Route map apply. */
1706 if (rmap) {
6006b807 1707 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1708 /* Duplicate current value to new structure for modification. */
40381db7
DS
1709 rmap_path.peer = peer;
1710 rmap_path.attr = attr;
82b692c0 1711 rmap_path.extra = &extra;
9bcb3eef 1712 rmap_path.net = dest;
196c6b09 1713
82b692c0
LK
1714 extra.num_labels = num_labels;
1715 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1716 memcpy(extra.label, label,
1717 num_labels * sizeof(mpls_label_t));
718e3744 1718
d62a17ae 1719 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1720
d62a17ae 1721 /* Apply BGP route map to the attribute. */
1782514f 1722 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1723
d62a17ae 1724 peer->rmap_type = 0;
0b16f239 1725
1f2263be 1726 if (ret == RMAP_DENYMATCH)
d62a17ae 1727 return RMAP_DENY;
0b16f239 1728 }
d62a17ae 1729 return RMAP_PERMIT;
0b16f239
DS
1730}
1731
5f040085 1732static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1733 struct attr *attr, afi_t afi, safi_t safi,
1734 const char *rmap_name)
0b16f239 1735{
40381db7 1736 struct bgp_path_info rmap_path;
d62a17ae 1737 route_map_result_t ret;
1738 struct route_map *rmap = NULL;
d7c0a89a 1739 uint8_t rmap_type;
0b16f239 1740
b787157a
DS
1741 /*
1742 * So if we get to this point and have no rmap_name
1743 * we want to just show the output as it currently
1744 * exists.
1745 */
1746 if (!rmap_name)
1747 return RMAP_PERMIT;
0b16f239 1748
d62a17ae 1749 /* Apply default weight value. */
1750 if (peer->weight[afi][safi])
1751 attr->weight = peer->weight[afi][safi];
0b16f239 1752
b787157a 1753 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1754
b787157a
DS
1755 /*
1756 * If we have a route map name and we do not find
1757 * the routemap that means we have an implicit
1758 * deny.
1759 */
1760 if (rmap == NULL)
1761 return RMAP_DENY;
0b16f239 1762
6006b807 1763 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1764 /* Route map apply. */
544be979 1765 /* Duplicate current value to new structure for modification. */
40381db7
DS
1766 rmap_path.peer = peer;
1767 rmap_path.attr = attr;
0b16f239 1768
0f672529 1769 rmap_type = peer->rmap_type;
b787157a 1770 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1771
b787157a 1772 /* Apply BGP route map to the attribute. */
1782514f 1773 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1774
0f672529 1775 peer->rmap_type = rmap_type;
b787157a
DS
1776
1777 if (ret == RMAP_DENYMATCH)
1778 /*
1779 * caller has multiple error paths with bgp_attr_flush()
1780 */
1781 return RMAP_DENY;
ac41b2a2 1782
d62a17ae 1783 return RMAP_PERMIT;
718e3744 1784}
6b0655a2 1785
5000f21c 1786/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1787static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1788 struct peer *peer, struct attr *attr)
1789{
1790 if (peer->sort == BGP_PEER_EBGP
1791 && (peer_af_flag_check(peer, afi, safi,
1792 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1793 || peer_af_flag_check(peer, afi, safi,
1794 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1795 || peer_af_flag_check(peer, afi, safi,
1796 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1797 || peer_af_flag_check(peer, afi, safi,
1798 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1799 // Take action on the entire aspath
1800 if (peer_af_flag_check(peer, afi, safi,
1801 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1802 || peer_af_flag_check(peer, afi, safi,
1803 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1804 if (peer_af_flag_check(
1805 peer, afi, safi,
1806 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1807 attr->aspath = aspath_replace_private_asns(
bf26b80e 1808 attr->aspath, bgp->as, peer->as);
d62a17ae 1809
179d5a0e
TA
1810 /*
1811 * Even if the aspath consists of just private ASNs we
1812 * need to walk the AS-Path to maintain all instances
1813 * of the peer's ASN to break possible loops.
1814 */
d62a17ae 1815 else
1816 attr->aspath = aspath_remove_private_asns(
bf26b80e 1817 attr->aspath, peer->as);
d62a17ae 1818 }
1819
1820 // 'all' was not specified so the entire aspath must be private
1821 // ASNs
1822 // for us to do anything
1823 else if (aspath_private_as_check(attr->aspath)) {
1824 if (peer_af_flag_check(
1825 peer, afi, safi,
1826 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1827 attr->aspath = aspath_replace_private_asns(
bf26b80e 1828 attr->aspath, bgp->as, peer->as);
d62a17ae 1829 else
179d5a0e
TA
1830 /*
1831 * Walk the aspath to retain any instances of
1832 * the peer_asn
1833 */
1834 attr->aspath = aspath_remove_private_asns(
1835 attr->aspath, peer->as);
d62a17ae 1836 }
1837 }
5000f21c
DS
1838}
1839
c7122e14 1840/* If this is an EBGP peer with as-override */
d62a17ae 1841static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1842 struct peer *peer, struct attr *attr)
1843{
bbe7bc46
DA
1844 struct aspath *aspath;
1845
9bbdb457 1846 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1847 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1848 if (attr->aspath->refcnt)
1849 aspath = aspath_dup(attr->aspath);
1850 else
1851 aspath = attr->aspath;
1852
1853 attr->aspath = aspath_intern(
1854 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1855
1856 aspath_free(aspath);
1857 }
d62a17ae 1858}
1859
1479ed2f
DA
1860void bgp_attr_add_llgr_community(struct attr *attr)
1861{
1862 struct community *old;
1863 struct community *new;
1864 struct community *merge;
1865 struct community *llgr;
1866
9a706b42 1867 old = bgp_attr_get_community(attr);
1479ed2f
DA
1868 llgr = community_str2com("llgr-stale");
1869
1870 assert(llgr);
1871
1872 if (old) {
1873 merge = community_merge(community_dup(old), llgr);
1874
1875 if (old->refcnt == 0)
1876 community_free(&old);
1877
1878 new = community_uniq_sort(merge);
1879 community_free(&merge);
1880 } else {
1881 new = community_dup(llgr);
1882 }
1883
1884 community_free(&llgr);
1885
9a706b42 1886 bgp_attr_set_community(attr, new);
1479ed2f
DA
1887}
1888
7f323236
DW
1889void bgp_attr_add_gshut_community(struct attr *attr)
1890{
1891 struct community *old;
1892 struct community *new;
1893 struct community *merge;
1894 struct community *gshut;
1895
9a706b42 1896 old = bgp_attr_get_community(attr);
7f323236
DW
1897 gshut = community_str2com("graceful-shutdown");
1898
990f4f91 1899 assert(gshut);
1900
7f323236
DW
1901 if (old) {
1902 merge = community_merge(community_dup(old), gshut);
1903
a4d82a8a 1904 if (old->refcnt == 0)
3c1f53de 1905 community_free(&old);
7f323236
DW
1906
1907 new = community_uniq_sort(merge);
3c1f53de 1908 community_free(&merge);
7f323236
DW
1909 } else {
1910 new = community_dup(gshut);
1911 }
1912
3c1f53de 1913 community_free(&gshut);
9a706b42 1914 bgp_attr_set_community(attr, new);
7f323236
DW
1915
1916 /* When we add the graceful-shutdown community we must also
1917 * lower the local-preference */
1918 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1919 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1920}
1921
1922
e73c112e
MK
1923/* Notify BGP Conditional advertisement scanner process. */
1924void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1925{
e73c112e 1926 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1927 afi_t afi = SUBGRP_AFI(subgrp);
1928 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1929 struct bgp_filter *filter = &peer->filter[afi][safi];
1930
1931 if (!ADVERTISE_MAP_NAME(filter))
1932 return;
1933
52979c3b
DS
1934 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1935 return;
e73c112e 1936
52979c3b 1937 peer->advmap_table_change = true;
e73c112e
MK
1938}
1939
1940
f2ee6d5c 1941void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1942{
960035b2 1943 if (family == AF_INET) {
975a328e
DA
1944 attr->nexthop.s_addr = INADDR_ANY;
1945 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1946 }
d62a17ae 1947 if (family == AF_INET6)
1948 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1949 if (family == AF_EVPN)
1950 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1951}
1952
9bcb3eef 1953bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1954 struct update_subgroup *subgrp,
7f7940e6 1955 const struct prefix *p, struct attr *attr,
51c3a7de 1956 struct attr *post_attr)
d62a17ae 1957{
1958 struct bgp_filter *filter;
1959 struct peer *from;
1960 struct peer *peer;
1961 struct peer *onlypeer;
1962 struct bgp *bgp;
40381db7 1963 struct attr *piattr;
b68885f9 1964 route_map_result_t ret;
d62a17ae 1965 int transparent;
1966 int reflect;
1967 afi_t afi;
1968 safi_t safi;
1969 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1970 bool nh_reset = false;
1971 uint64_t cum_bw;
d62a17ae 1972
1973 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1974 return false;
d62a17ae 1975
1976 afi = SUBGRP_AFI(subgrp);
1977 safi = SUBGRP_SAFI(subgrp);
1978 peer = SUBGRP_PEER(subgrp);
1979 onlypeer = NULL;
1980 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1981 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1982
40381db7 1983 from = pi->peer;
d62a17ae 1984 filter = &peer->filter[afi][safi];
1985 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1986 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1987 : pi->attr;
3f9c7369 1988
d0bf49ec
LS
1989 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1990 peer->pmax_out[afi][safi] != 0 &&
1991 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1992 if (BGP_DEBUG(update, UPDATE_OUT) ||
1993 BGP_DEBUG(update, UPDATE_PREFIX)) {
1994 zlog_debug("%s reached maximum prefix to be send (%u)",
1995 peer->host, peer->pmax_out[afi][safi]);
1996 }
1997 return false;
1998 }
1999
49e5a4a0 2000#ifdef ENABLE_BGP_VNC
d62a17ae 2001 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2002 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2003 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2004
2005 /*
2006 * direct and direct_ext type routes originate internally even
2007 * though they can have peer pointers that reference other
2008 * systems
2009 */
8228a9a7
DS
2010 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2011 __func__, p);
d62a17ae 2012 samepeer_safe = 1;
2013 }
65efcfce
LB
2014#endif
2015
ddb5b488
PZ
2016 if (((afi == AFI_IP) || (afi == AFI_IP6))
2017 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2018 && (pi->type == ZEBRA_ROUTE_BGP)
2019 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2020
2021 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2022
2023 samepeer_safe = 1;
2024 }
2025
d62a17ae 2026 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2027 * pi is valid */
2028 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2029 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2030 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2031 return false;
d62a17ae 2032 }
adbac85e 2033
d62a17ae 2034 /* If this is not the bestpath then check to see if there is an enabled
2035 * addpath
2036 * feature that requires us to advertise it */
8ccee4b8
DA
2037 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2038 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2039 return false;
06370dac 2040
d62a17ae 2041 /* Aggregate-address suppress check. */
4056a5f6
RZ
2042 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2043 return false;
3f9c7369 2044
13b7e7f0
DS
2045 /*
2046 * If we are doing VRF 2 VRF leaking via the import
2047 * statement, we want to prevent the route going
2048 * off box as that the RT and RD created are localy
2049 * significant and globaly useless.
2050 */
40381db7
DS
2051 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2052 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2053 return false;
13b7e7f0 2054
d62a17ae 2055 /* If it's labeled safi, make sure the route has a valid label. */
2056 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2057 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2058 if (!bgp_is_valid_label(&label)) {
2059 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2060 zlog_debug("u%" PRIu64 ":s%" PRIu64
2061 " %pFX is filtered - no label (%p)",
d62a17ae 2062 subgrp->update_group->id, subgrp->id,
8228a9a7 2063 p, &label);
3dc339cd 2064 return false;
d62a17ae 2065 }
2066 }
cd1964ff 2067
d62a17ae 2068 /* Do not send back route to sender. */
2069 if (onlypeer && from == onlypeer) {
3dc339cd 2070 return false;
d62a17ae 2071 }
3f9c7369 2072
d62a17ae 2073 /* Do not send the default route in the BGP table if the neighbor is
2074 * configured for default-originate */
2075 if (CHECK_FLAG(peer->af_flags[afi][safi],
2076 PEER_FLAG_DEFAULT_ORIGINATE)) {
2077 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2078 return false;
d62a17ae 2079 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2080 return false;
d62a17ae 2081 }
4125bb67 2082
d62a17ae 2083 /* Transparency check. */
2084 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2085 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2086 transparent = 1;
2087 else
2088 transparent = 0;
2089
2090 /* If community is not disabled check the no-export and local. */
40381db7 2091 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2092 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2093 zlog_debug("%s: community filter check fail for %pFX",
2094 __func__, p);
3dc339cd 2095 return false;
d62a17ae 2096 }
3f9c7369 2097
d62a17ae 2098 /* If the attribute has originator-id and it is same as remote
2099 peer's id. */
40381db7
DS
2100 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2101 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2102 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2103 zlog_debug(
a9f3f4f5
DA
2104 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2105 onlypeer, p);
3dc339cd 2106 return false;
d62a17ae 2107 }
3f9c7369 2108
d62a17ae 2109 /* ORF prefix-list filter check */
2110 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2111 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2112 || CHECK_FLAG(peer->af_cap[afi][safi],
2113 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2114 if (peer->orf_plist[afi][safi]) {
2115 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2116 == PREFIX_DENY) {
2117 if (bgp_debug_update(NULL, p,
2118 subgrp->update_group, 0))
2119 zlog_debug(
a9f3f4f5
DA
2120 "%pBP [Update:SEND] %pFX is filtered via ORF",
2121 peer, p);
3dc339cd 2122 return false;
d62a17ae 2123 }
2124 }
2125
2126 /* Output filter check. */
40381db7 2127 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2128 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2129 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2130 p);
3dc339cd 2131 return false;
d62a17ae 2132 }
3f9c7369 2133
d62a17ae 2134 /* AS path loop check. */
25851bf0
DA
2135 if (peer->as_path_loop_detection &&
2136 aspath_loop_check(piattr->aspath, peer->as)) {
d62a17ae 2137 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2138 zlog_debug(
a9f3f4f5 2139 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
25851bf0 2140 peer, peer->as);
3dc339cd 2141 return false;
d62a17ae 2142 }
3f9c7369 2143
d62a17ae 2144 /* If we're a CONFED we need to loop check the CONFED ID too */
2145 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2146 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2147 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2148 zlog_debug(
a9f3f4f5
DA
2149 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2150 peer, bgp->confed_id);
3dc339cd 2151 return false;
d62a17ae 2152 }
3f9c7369 2153 }
3f9c7369 2154
d62a17ae 2155 /* Route-Reflect check. */
2156 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2157 reflect = 1;
2158 else
2159 reflect = 0;
2160
2161 /* IBGP reflection check. */
2162 if (reflect && !samepeer_safe) {
2163 /* A route from a Client peer. */
2164 if (CHECK_FLAG(from->af_flags[afi][safi],
2165 PEER_FLAG_REFLECTOR_CLIENT)) {
2166 /* Reflect to all the Non-Client peers and also to the
2167 Client peers other than the originator. Originator
2168 check
2169 is already done. So there is noting to do. */
2170 /* no bgp client-to-client reflection check. */
892fedb6
DA
2171 if (CHECK_FLAG(bgp->flags,
2172 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2173 if (CHECK_FLAG(peer->af_flags[afi][safi],
2174 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2175 return false;
d62a17ae 2176 } else {
2177 /* A route from a Non-client peer. Reflect to all other
2178 clients. */
2179 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2180 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2181 return false;
d62a17ae 2182 }
2183 }
3f9c7369 2184
51c3a7de
DA
2185 /* For modify attribute, copy it to temporary structure.
2186 * post_attr comes from BGP conditional advertisements, where
2187 * attributes are already processed by advertise-map route-map,
2188 * and this needs to be saved instead of overwriting from the
2189 * path attributes.
2190 */
2191 if (post_attr)
2192 *attr = *post_attr;
2193 else
2194 *attr = *piattr;
d62a17ae 2195
2196 /* If local-preference is not set. */
2197 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2198 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2199 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2200 attr->local_pref = bgp->default_local_pref;
3f9c7369 2201 }
3f9c7369 2202
d62a17ae 2203 /* If originator-id is not set and the route is to be reflected,
2204 set the originator id */
2205 if (reflect
2206 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2207 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2208 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2209 }
3f9c7369 2210
d62a17ae 2211 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2212 */
2213 if (peer->sort == BGP_PEER_EBGP
2214 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2215 if (from != bgp->peer_self && !transparent
2216 && !CHECK_FLAG(peer->af_flags[afi][safi],
2217 PEER_FLAG_MED_UNCHANGED))
2218 attr->flag &=
2219 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2220 }
3f9c7369 2221
d62a17ae 2222 /* Since the nexthop attribute can vary per peer, it is not explicitly
2223 * set
2224 * in announce check, only certain flags and length (or number of
2225 * nexthops
2226 * -- for IPv6/MP_REACH) are set here in order to guide the update
2227 * formation
2228 * code in setting the nexthop(s) on a per peer basis in
2229 * reformat_peer().
2230 * Typically, the source nexthop in the attribute is preserved but in
2231 * the
2232 * scenarios where we know it will always be overwritten, we reset the
2233 * nexthop to "0" in an attempt to achieve better Update packing. An
2234 * example of this is when a prefix from each of 2 IBGP peers needs to
2235 * be
2236 * announced to an EBGP peer (and they have the same attributes barring
2237 * their nexthop).
2238 */
2239 if (reflect)
2240 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2241
2242#define NEXTHOP_IS_V6 \
2243 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2244 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2245 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2246 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2247
2248 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2249 * if
2250 * the peer (group) is configured to receive link-local nexthop
2251 * unchanged
c728d027
DA
2252 * and it is available in the prefix OR we're not reflecting the route,
2253 * link-local nexthop address is valid and
d62a17ae 2254 * the peer (group) to whom we're going to announce is on a shared
2255 * network
2256 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2257 * By checking if nexthop LL address is valid we are sure that
2258 * we do not announce LL address as `::`.
d62a17ae 2259 */
2260 if (NEXTHOP_IS_V6) {
2261 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2262 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2263 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2264 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2265 || (!reflect && !transparent
c728d027
DA
2266 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2267 && peer->shared_network
d62a17ae 2268 && (from == bgp->peer_self
2269 || peer->sort == BGP_PEER_EBGP))) {
f7a0eb6a
PG
2270 if (safi == SAFI_MPLS_VPN)
2271 attr->mp_nexthop_len =
2272 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2273 else
2274 attr->mp_nexthop_len =
2275 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 2276 }
3f9c7369 2277
d62a17ae 2278 /* Clear off link-local nexthop in source, whenever it is not
2279 * needed to
2280 * ensure more prefixes share the same attribute for
2281 * announcement.
2282 */
2283 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2284 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2285 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2286 }
3f9c7369 2287
5a78f2bc
EB
2288 if (bgp_check_role_applicability(afi, safi) &&
2289 bgp_otc_egress(peer, attr))
d864dd9e
EB
2290 return false;
2291
d62a17ae 2292 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2293 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2294
0655090c
QY
2295 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2296 filter->advmap.aname &&
2297 route_map_lookup_by_name(filter->advmap.aname)) {
2298 struct bgp_path_info rmap_path = {0};
2299 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2300 struct attr dummy_attr = *attr;
2301
2302 /* Fill temp path_info */
2303 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2304 pi, peer, &dummy_attr);
2305
2306 struct route_map *amap =
2307 route_map_lookup_by_name(filter->advmap.aname);
2308
2309 ret = route_map_apply(amap, p, &rmap_path);
2310
2311 bgp_attr_flush(&dummy_attr);
2312
2313 /*
2314 * The conditional advertisement mode is Withdraw and this
2315 * prefix is a conditional prefix. Don't advertise it
2316 */
2317 if (ret == RMAP_PERMITMATCH)
2318 return false;
2319 }
2320
d62a17ae 2321 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2322 if (!post_attr &&
2323 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2324 struct bgp_path_info rmap_path = {0};
2325 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2326 struct attr dummy_attr = {0};
d62a17ae 2327
e34291b8 2328 /* Fill temp path_info */
9bcb3eef
DS
2329 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2330 pi, peer, attr);
16f7ce2b 2331
d62a17ae 2332 /* don't confuse inbound and outbound setting */
2333 RESET_FLAG(attr->rmap_change_flags);
2334
2335 /*
2336 * The route reflector is not allowed to modify the attributes
2337 * of the reflected IBGP routes unless explicitly allowed.
2338 */
2339 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2340 && !CHECK_FLAG(bgp->flags,
2341 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2342 dummy_attr = *attr;
40381db7 2343 rmap_path.attr = &dummy_attr;
d62a17ae 2344 }
3f9c7369 2345
d62a17ae 2346 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2347
4056a5f6 2348 if (bgp_path_suppressed(pi))
d62a17ae 2349 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2350 &rmap_path);
d62a17ae 2351 else
2352 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2353 &rmap_path);
d62a17ae 2354
7e7639f5 2355 bgp_attr_flush(&dummy_attr);
d62a17ae 2356 peer->rmap_type = 0;
2357
2358 if (ret == RMAP_DENYMATCH) {
778048bf 2359 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2360 zlog_debug(
a9f3f4f5
DA
2361 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2362 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2363 bgp_attr_flush(rmap_path.attr);
3dc339cd 2364 return false;
d62a17ae 2365 }
3f9c7369 2366 }
3f9c7369 2367
9dac9fc8
DA
2368 /* RFC 8212 to prevent route leaks.
2369 * This specification intends to improve this situation by requiring the
2370 * explicit configuration of both BGP Import and Export Policies for any
2371 * External BGP (EBGP) session such as customers, peers, or
2372 * confederation boundaries for all enabled address families. Through
2373 * codification of the aforementioned requirement, operators will
2374 * benefit from consistent behavior across different BGP
2375 * implementations.
2376 */
1d3fdccf 2377 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2378 if (!bgp_outbound_policy_exists(peer, filter)) {
2379 if (monotime_since(&bgp->ebgprequirespolicywarning,
2380 NULL) > FIFTEENMINUTE2USEC ||
2381 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2382 zlog_warn(
2383 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2384 monotime(&bgp->ebgprequirespolicywarning);
2385 }
3dc339cd 2386 return false;
b17826b7 2387 }
9dac9fc8 2388
fb29348a
DA
2389 /* draft-ietf-idr-deprecate-as-set-confed-set
2390 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2391 * Eventually, This document (if approved) updates RFC 4271
2392 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2393 * and obsoletes RFC 6472.
2394 */
7f972cd8 2395 if (peer->bgp->reject_as_sets)
fb29348a 2396 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2397 return false;
fb29348a 2398
8c4d4624 2399 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2400 * SoO extended community and validate against the configured
2401 * one. If they match, do not announce, to prevent routing
2402 * loops.
2403 */
2404 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2405 peer->soo[afi][safi]) {
2406 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2407 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2408
2409 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2410 ECOMMUNITY_SITE_ORIGIN) ||
2411 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2412 ECOMMUNITY_SITE_ORIGIN) ||
2413 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2414 ECOMMUNITY_SITE_ORIGIN)) &&
2415 ecommunity_include(ecomm, ecomm_soo)) {
2416 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2417 zlog_debug(
2418 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2419 peer, p, ecommunity_str(ecomm_soo));
2420 return false;
2421 }
2422 }
2423
33d022bc
DA
2424 /* Codification of AS 0 Processing */
2425 if (aspath_check_as_zero(attr->aspath))
e2369003 2426 return false;
33d022bc 2427
637e5ba4 2428 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2429 if (peer->sort == BGP_PEER_IBGP
2430 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2431 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2432 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2433 } else {
2434 bgp_attr_add_gshut_community(attr);
2435 }
2436 }
2437
1479ed2f
DA
2438 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2439 * Capability" to a neighbor MUST perform the following upon receiving
2440 * a route from that neighbor with the "LLGR_STALE" community, or upon
2441 * attaching the "LLGR_STALE" community itself per Section 4.2:
2442 *
2443 * The route SHOULD NOT be advertised to any neighbor from which the
2444 * Long-lived Graceful Restart Capability has not been received.
2445 */
9a706b42
DA
2446 if (bgp_attr_get_community(attr) &&
2447 community_include(bgp_attr_get_community(attr),
2448 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2449 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2450 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2451 return false;
2452
d62a17ae 2453 /* After route-map has been applied, we check to see if the nexthop to
2454 * be carried in the attribute (that is used for the announcement) can
2455 * be cleared off or not. We do this in all cases where we would be
2456 * setting the nexthop to "ourselves". For IPv6, we only need to
2457 * consider
2458 * the global nexthop here; the link-local nexthop would have been
2459 * cleared
2460 * already, and if not, it is required by the update formation code.
2461 * Also see earlier comments in this function.
2462 */
2463 /*
2464 * If route-map has performed some operation on the nexthop or the peer
2465 * configuration says to pass it unchanged, we cannot reset the nexthop
2466 * here, so only attempt to do it if these aren't true. Note that the
2467 * route-map handler itself might have cleared the nexthop, if for
2468 * example,
2469 * it is configured as 'peer-address'.
2470 */
2471 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2472 piattr->rmap_change_flags)
d62a17ae 2473 && !transparent
2474 && !CHECK_FLAG(peer->af_flags[afi][safi],
2475 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2476 /* We can reset the nexthop, if setting (or forcing) it to
2477 * 'self' */
2478 if (CHECK_FLAG(peer->af_flags[afi][safi],
2479 PEER_FLAG_NEXTHOP_SELF)
2480 || CHECK_FLAG(peer->af_flags[afi][safi],
2481 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2482 if (!reflect
2483 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2484 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2485 subgroup_announce_reset_nhop(
2486 (peer_cap_enhe(peer, afi, safi)
2487 ? AF_INET6
2488 : p->family),
2489 attr);
7b651a32 2490 nh_reset = true;
2491 }
d62a17ae 2492 } else if (peer->sort == BGP_PEER_EBGP) {
2493 /* Can also reset the nexthop if announcing to EBGP, but
2494 * only if
2495 * no peer in the subgroup is on a shared subnet.
2496 * Note: 3rd party nexthop currently implemented for
2497 * IPv4 only.
2498 */
737af885
BS
2499 if ((p->family == AF_INET) &&
2500 (!bgp_subgrp_multiaccess_check_v4(
2501 piattr->nexthop,
7b651a32 2502 subgrp, from))) {
d62a17ae 2503 subgroup_announce_reset_nhop(
2504 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2505 ? AF_INET6
2506 : p->family),
737af885 2507 attr);
7b651a32 2508 nh_reset = true;
2509 }
737af885
BS
2510
2511 if ((p->family == AF_INET6) &&
2512 (!bgp_subgrp_multiaccess_check_v6(
2513 piattr->mp_nexthop_global,
7b651a32 2514 subgrp, from))) {
737af885
BS
2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer, afi, safi)
2517 ? AF_INET6
2518 : p->family),
2519 attr);
7b651a32 2520 nh_reset = true;
2521 }
737af885
BS
2522
2523
2524
40381db7 2525 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2526 /*
2527 * This flag is used for leaked vpn-vrf routes
2528 */
2529 int family = p->family;
2530
2531 if (peer_cap_enhe(peer, afi, safi))
2532 family = AF_INET6;
2533
2534 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2535 zlog_debug(
6cf8a4bf
DA
2536 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2537 __func__, p, family2str(family));
960035b2 2538 subgroup_announce_reset_nhop(family, attr);
7b651a32 2539 nh_reset = true;
d62a17ae 2540 }
63696f1d 2541 }
960035b2 2542
63696f1d 2543 /* If IPv6/MP and nexthop does not have any override and happens
2544 * to
2545 * be a link-local address, reset it so that we don't pass along
2546 * the
2547 * source's link-local IPv6 address to recipients who may not be
2548 * on
2549 * the same interface.
2550 */
2551 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2552 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2553 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2554 nh_reset = true;
2555 }
d62a17ae 2556 }
3f9c7369 2557
7b27cf7b
DA
2558 /* If this is an iBGP, send Origin Validation State (OVS)
2559 * extended community (rfc8097).
2560 */
2561 if (peer->sort == BGP_PEER_IBGP) {
2562 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2563
2564 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2565
2566 if (rpki_state != RPKI_NOT_BEING_USED)
2567 bgp_attr_set_ecommunity(
2568 attr, ecommunity_add_origin_validation_state(
2569 rpki_state,
2570 bgp_attr_get_ecommunity(attr)));
2571 }
2572
7b651a32 2573 /*
2574 * When the next hop is set to ourselves, if all multipaths have
2575 * link-bandwidth announce the cumulative bandwidth as that makes
2576 * the most sense. However, don't modify if the link-bandwidth has
2577 * been explicitly set by user policy.
2578 */
2579 if (nh_reset &&
f7e1c681 2580 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2581 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2582 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2583 bgp_attr_set_ecommunity(
2584 attr,
2585 ecommunity_replace_linkbw(
2586 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2587 CHECK_FLAG(
2588 peer->flags,
2589 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2590
3dc339cd 2591 return true;
3f9c7369
DS
2592}
2593
cc9f21da 2594static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2595{
2596 struct afi_safi_info *info;
2597 afi_t afi;
2598 safi_t safi;
2599 struct bgp *bgp;
2600
2601 info = THREAD_ARG(thread);
2602 afi = info->afi;
2603 safi = info->safi;
2604 bgp = info->bgp;
2605
f009ff26 2606 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2607 XFREE(MTYPE_TMP, info);
2608
2609 /* Best path selection */
cc9f21da 2610 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2611}
2612
9bcb3eef 2613void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2614 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2615 struct bgp_path_info_pair *result, afi_t afi,
2616 safi_t safi)
2617{
2618 struct bgp_path_info *new_select;
2619 struct bgp_path_info *old_select;
40381db7
DS
2620 struct bgp_path_info *pi;
2621 struct bgp_path_info *pi1;
2622 struct bgp_path_info *pi2;
2623 struct bgp_path_info *nextpi = NULL;
d62a17ae 2624 int paths_eq, do_mpath, debug;
2625 struct list mp_list;
2626 char pfx_buf[PREFIX2STR_BUFFER];
2627 char path_buf[PATH_ADDPATH_STR_BUFFER];
2628
2629 bgp_mp_list_init(&mp_list);
2630 do_mpath =
2631 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2632
9bcb3eef 2633 debug = bgp_debug_bestpath(dest);
d62a17ae 2634
2635 if (debug)
9bcb3eef 2636 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2637
9bcb3eef 2638 dest->reason = bgp_path_selection_none;
d62a17ae 2639 /* bgp deterministic-med */
2640 new_select = NULL;
892fedb6 2641 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2642
1defdda8 2643 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2644 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2645 pi1 = pi1->next)
9bcb3eef 2646 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2647 BGP_PATH_DMED_SELECTED);
d62a17ae 2648
9bcb3eef 2649 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2650 pi1 = pi1->next) {
40381db7 2651 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2652 continue;
40381db7 2653 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2654 continue;
de692a4e 2655 if (pi1->peer != bgp->peer_self &&
2656 !CHECK_FLAG(pi1->peer->sflags,
2657 PEER_STATUS_NSF_WAIT)) {
feb17238 2658 if (!peer_established(pi1->peer))
d62a17ae 2659 continue;
de692a4e 2660 }
d62a17ae 2661
40381db7
DS
2662 new_select = pi1;
2663 if (pi1->next) {
2664 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2665 if (CHECK_FLAG(pi2->flags,
1defdda8 2666 BGP_PATH_DMED_CHECK))
d62a17ae 2667 continue;
40381db7 2668 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2669 continue;
ea8b2282 2670 if (pi2->peer != bgp->peer_self
d62a17ae 2671 && !CHECK_FLAG(
ea8b2282
DS
2672 pi2->peer->sflags,
2673 PEER_STATUS_NSF_WAIT))
40381db7 2674 if (pi2->peer->status
d62a17ae 2675 != Established)
2676 continue;
2677
121e245d
DS
2678 if (!aspath_cmp_left(pi1->attr->aspath,
2679 pi2->attr->aspath)
2680 && !aspath_cmp_left_confed(
40381db7 2681 pi1->attr->aspath,
121e245d
DS
2682 pi2->attr->aspath))
2683 continue;
d62a17ae 2684
121e245d
DS
2685 if (bgp_path_info_cmp(
2686 bgp, pi2, new_select,
2687 &paths_eq, mpath_cfg, debug,
fdf81fa0 2688 pfx_buf, afi, safi,
9bcb3eef 2689 &dest->reason)) {
121e245d 2690 bgp_path_info_unset_flag(
9bcb3eef 2691 dest, new_select,
121e245d
DS
2692 BGP_PATH_DMED_SELECTED);
2693 new_select = pi2;
d62a17ae 2694 }
121e245d
DS
2695
2696 bgp_path_info_set_flag(
9bcb3eef 2697 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2698 }
2699 }
9bcb3eef 2700 bgp_path_info_set_flag(dest, new_select,
18ee8310 2701 BGP_PATH_DMED_CHECK);
9bcb3eef 2702 bgp_path_info_set_flag(dest, new_select,
18ee8310 2703 BGP_PATH_DMED_SELECTED);
d62a17ae 2704
2705 if (debug) {
18ee8310 2706 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2707 new_select, path_buf, sizeof(path_buf));
8228a9a7 2708 zlog_debug(
4378495a
DS
2709 "%pBD(%s): %s is the bestpath from AS %u",
2710 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2711 aspath_get_first_as(
2712 new_select->attr->aspath));
d62a17ae 2713 }
2714 }
2715 }
96450faf 2716
d62a17ae 2717 /* Check old selected route and new selected route. */
2718 old_select = NULL;
2719 new_select = NULL;
9bcb3eef 2720 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2721 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2722 enum bgp_path_selection_reason reason;
2723
40381db7
DS
2724 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2725 old_select = pi;
d62a17ae 2726
40381db7 2727 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2728 /* reap REMOVED routes, if needs be
2729 * selected route must stay for a while longer though
2730 */
40381db7
DS
2731 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2732 && (pi != old_select))
9bcb3eef 2733 bgp_path_info_reap(dest, pi);
d62a17ae 2734
ddb5b488 2735 if (debug)
40381db7
DS
2736 zlog_debug("%s: pi %p in holddown", __func__,
2737 pi);
ddb5b488 2738
d62a17ae 2739 continue;
2740 }
96450faf 2741
40381db7
DS
2742 if (pi->peer && pi->peer != bgp->peer_self
2743 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2744 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2745
2746 if (debug)
2747 zlog_debug(
40381db7
DS
2748 "%s: pi %p non self peer %s not estab state",
2749 __func__, pi, pi->peer->host);
ddb5b488 2750
d62a17ae 2751 continue;
ddb5b488 2752 }
9fbdd100 2753
892fedb6 2754 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2755 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2756 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2757 if (debug)
40381db7 2758 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2759 continue;
2760 }
9fbdd100 2761
9bcb3eef 2762 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2763
9bcb3eef 2764 reason = dest->reason;
40381db7 2765 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2766 debug, pfx_buf, afi, safi,
2767 &dest->reason)) {
19ea4cec
DS
2768 if (new_select == NULL &&
2769 reason != bgp_path_selection_none)
9bcb3eef 2770 dest->reason = reason;
40381db7 2771 new_select = pi;
d62a17ae 2772 }
2773 }
718e3744 2774
d62a17ae 2775 /* Now that we know which path is the bestpath see if any of the other
2776 * paths
2777 * qualify as multipaths
2778 */
2779 if (debug) {
2780 if (new_select)
7533cad7
QY
2781 bgp_path_info_path_with_addpath_rx_str(
2782 new_select, path_buf, sizeof(path_buf));
d62a17ae 2783 else
772270f3 2784 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2785 zlog_debug(
4378495a
DS
2786 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2787 dest, bgp->name_pretty, path_buf,
d62a17ae 2788 old_select ? old_select->peer->host : "NONE");
96450faf 2789 }
9fbdd100 2790
d62a17ae 2791 if (do_mpath && new_select) {
9bcb3eef 2792 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2793 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2794
2795 if (debug)
18ee8310 2796 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2797 pi, path_buf, sizeof(path_buf));
d62a17ae 2798
40381db7 2799 if (pi == new_select) {
d62a17ae 2800 if (debug)
2801 zlog_debug(
4378495a
DS
2802 "%pBD(%s): %s is the bestpath, add to the multipath list",
2803 dest, bgp->name_pretty,
2804 path_buf);
40381db7 2805 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2806 continue;
2807 }
2808
40381db7 2809 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2810 continue;
2811
40381db7
DS
2812 if (pi->peer && pi->peer != bgp->peer_self
2813 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2814 PEER_STATUS_NSF_WAIT))
feb17238 2815 if (!peer_established(pi->peer))
d62a17ae 2816 continue;
2817
40381db7 2818 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2819 if (debug)
2820 zlog_debug(
8228a9a7
DS
2821 "%pBD: %s has the same nexthop as the bestpath, skip it",
2822 dest, path_buf);
d62a17ae 2823 continue;
2824 }
2825
40381db7 2826 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2827 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2828 &dest->reason);
d62a17ae 2829
2830 if (paths_eq) {
2831 if (debug)
2832 zlog_debug(
8228a9a7
DS
2833 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2834 dest, path_buf);
40381db7 2835 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2836 }
2837 }
2838 }
fee0f4c6 2839
4378495a 2840 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2841 mpath_cfg);
2842 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2843 bgp_mp_list_clear(&mp_list);
96450faf 2844
9bcb3eef 2845 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2846
d62a17ae 2847 result->old = old_select;
2848 result->new = new_select;
96450faf 2849
d62a17ae 2850 return;
fee0f4c6 2851}
2852
3f9c7369
DS
2853/*
2854 * A new route/change in bestpath of an existing route. Evaluate the path
2855 * for advertisement to the subgroup.
2856 */
3dc339cd
DA
2857void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2858 struct bgp_path_info *selected,
9bcb3eef 2859 struct bgp_dest *dest,
3dc339cd 2860 uint32_t addpath_tx_id)
d62a17ae 2861{
b54892e0 2862 const struct prefix *p;
d62a17ae 2863 struct peer *onlypeer;
2864 struct attr attr;
2865 afi_t afi;
2866 safi_t safi;
a77e2f4b
S
2867 struct bgp *bgp;
2868 bool advertise;
adbac85e 2869
9bcb3eef 2870 p = bgp_dest_get_prefix(dest);
d62a17ae 2871 afi = SUBGRP_AFI(subgrp);
2872 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2873 bgp = SUBGRP_INST(subgrp);
d62a17ae 2874 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2875 : NULL);
2876
2dbe669b
DA
2877 if (BGP_DEBUG(update, UPDATE_OUT))
2878 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2879
d62a17ae 2880 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2881 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2882 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2883 return;
d62a17ae 2884
6006b807 2885 memset(&attr, 0, sizeof(attr));
d62a17ae 2886 /* It's initialized in bgp_announce_check() */
2887
a77e2f4b
S
2888 /* Announcement to the subgroup. If the route is filtered withdraw it.
2889 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2890 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2891 * route
d62a17ae 2892 */
a77e2f4b
S
2893 advertise = bgp_check_advertise(bgp, dest);
2894
d62a17ae 2895 if (selected) {
7f7940e6 2896 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2897 NULL)) {
a77e2f4b
S
2898 /* Route is selected, if the route is already installed
2899 * in FIB, then it is advertised
2900 */
be785e35
DS
2901 if (advertise) {
2902 if (!bgp_check_withdrawal(bgp, dest))
2903 bgp_adj_out_set_subgroup(
2904 dest, subgrp, &attr, selected);
2905 else
2906 bgp_adj_out_unset_subgroup(
2907 dest, subgrp, 1, addpath_tx_id);
2908 }
a77e2f4b 2909 } else
9bcb3eef 2910 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2911 addpath_tx_id);
d62a17ae 2912 }
2913
2914 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2915 else {
9bcb3eef 2916 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2917 }
200df115 2918}
fee0f4c6 2919
3064bf43 2920/*
e1072051 2921 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2922 * This is called at the end of route processing.
3064bf43 2923 */
9bcb3eef 2924void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2925{
40381db7 2926 struct bgp_path_info *pi;
3064bf43 2927
9bcb3eef 2928 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2929 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2930 continue;
40381db7
DS
2931 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2932 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2933 }
3064bf43 2934}
2935
2936/*
2937 * Has the route changed from the RIB's perspective? This is invoked only
2938 * if the route selection returns the same best route as earlier - to
2939 * determine if we need to update zebra or not.
2940 */
9bcb3eef 2941bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2942{
4b7e6066 2943 struct bgp_path_info *mpinfo;
d62a17ae 2944
2bb9eff4
DS
2945 /* If this is multipath, check all selected paths for any nexthop
2946 * change or attribute change. Some attribute changes (e.g., community)
2947 * aren't of relevance to the RIB, but we'll update zebra to ensure
2948 * we handle the case of BGP nexthop change. This is the behavior
2949 * when the best path has an attribute change anyway.
d62a17ae 2950 */
1defdda8 2951 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2952 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2953 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2954 return true;
d62a17ae 2955
2bb9eff4
DS
2956 /*
2957 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2958 */
18ee8310
DS
2959 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2960 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2961 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2962 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2963 return true;
d62a17ae 2964 }
3064bf43 2965
d62a17ae 2966 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2967 return false;
3064bf43 2968}
2969
d62a17ae 2970struct bgp_process_queue {
2971 struct bgp *bgp;
9bcb3eef 2972 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2973#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2974 unsigned int flags;
2975 unsigned int queued;
200df115 2976};
2977
3b0c17e1 2978static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2979 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2980 struct bgp_path_info *new_select,
2981 struct bgp_path_info *old_select)
2982{
9bcb3eef 2983 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2984
2985 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2986 return;
2987
2988 if (advertise_type5_routes(bgp, afi) && new_select
2989 && is_route_injectable_into_evpn(new_select)) {
2990
2991 /* apply the route-map */
2992 if (bgp->adv_cmd_rmap[afi][safi].map) {
2993 route_map_result_t ret;
2994 struct bgp_path_info rmap_path;
2995 struct bgp_path_info_extra rmap_path_extra;
2996 struct attr dummy_attr;
2997
2998 dummy_attr = *new_select->attr;
2999
3000 /* Fill temp path_info */
9bcb3eef 3001 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3002 new_select, new_select->peer,
3003 &dummy_attr);
3004
3005 RESET_FLAG(dummy_attr.rmap_change_flags);
3006
3007 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3008 p, &rmap_path);
3b0c17e1 3009
3010 if (ret == RMAP_DENYMATCH) {
3011 bgp_attr_flush(&dummy_attr);
3012 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3013 safi);
3014 } else
3015 bgp_evpn_advertise_type5_route(
3016 bgp, p, &dummy_attr, afi, safi);
3017 } else {
3018 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3019 afi, safi);
3020 }
3021 } else if (advertise_type5_routes(bgp, afi) && old_select
3022 && is_route_injectable_into_evpn(old_select))
3023 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3024}
3025
bb2ca692
MS
3026/*
3027 * Utility to determine whether a particular path_info should use
3028 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3029 * in a path where we basically _know_ this is a BGP-LU route.
3030 */
3031static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3032{
3033 /* Certain types get imp null; so do paths where the nexthop is
3034 * not labeled.
3035 */
3036 if (new_select->sub_type == BGP_ROUTE_STATIC
3037 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3038 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3039 return true;
3040 else if (new_select->extra == NULL ||
3041 !bgp_is_valid_label(&new_select->extra->label[0]))
3042 /* TODO -- should be configurable? */
3043 return true;
3044 else
3045 return false;
3046}
3047
3103e8d2
DS
3048/*
3049 * old_select = The old best path
3050 * new_select = the new best path
3051 *
3052 * if (!old_select && new_select)
3053 * We are sending new information on.
3054 *
3055 * if (old_select && new_select) {
3056 * if (new_select != old_select)
3057 * We have a new best path send a change
3058 * else
3059 * We've received a update with new attributes that needs
3060 * to be passed on.
3061 * }
3062 *
3063 * if (old_select && !new_select)
3064 * We have no eligible route that we can announce or the rn
3065 * is being removed.
3066 */
9bcb3eef 3067static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3068 afi_t afi, safi_t safi)
d62a17ae 3069{
4b7e6066
DS
3070 struct bgp_path_info *new_select;
3071 struct bgp_path_info *old_select;
3072 struct bgp_path_info_pair old_and_new;
ddb5b488 3073 int debug = 0;
d62a17ae 3074
892fedb6 3075 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3076 if (dest)
3077 debug = bgp_debug_bestpath(dest);
b54892e0 3078 if (debug)
f4c713ae 3079 zlog_debug(
56ca3b5b 3080 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3081 __func__, dest);
f4c713ae
LB
3082 return;
3083 }
d62a17ae 3084 /* Is it end of initial update? (after startup) */
9bcb3eef 3085 if (!dest) {
e36f61b5
DS
3086 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3087 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3088
3089 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3090 FOREACH_AFI_SAFI (afi, safi) {
3091 if (bgp_fibupd_safi(safi))
3092 bgp_zebra_announce_table(bgp, afi, safi);
3093 }
d62a17ae 3094 bgp->main_peers_update_hold = 0;
3095
3096 bgp_start_routeadv(bgp);
aac24838 3097 return;
d62a17ae 3098 }
cb1faec9 3099
9bcb3eef 3100 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3101
9bcb3eef 3102 debug = bgp_debug_bestpath(dest);
b54892e0 3103 if (debug)
4378495a
DS
3104 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3105 dest, bgp->name_pretty, afi2str(afi),
3106 safi2str(safi));
ddb5b488 3107
f009ff26 3108 /* The best path calculation for the route is deferred if
3109 * BGP_NODE_SELECT_DEFER is set
3110 */
9bcb3eef 3111 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3112 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3113 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3114 return;
3115 }
3116
d62a17ae 3117 /* Best path selection. */
9bcb3eef 3118 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3119 afi, safi);
3120 old_select = old_and_new.old;
3121 new_select = old_and_new.new;
3122
3123 /* Do we need to allocate or free labels?
3124 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3125 * necessary to do this upon changes to best path. Exceptions:
3126 * - label index has changed -> recalculate resulting label
3127 * - path_info sub_type changed -> switch to/from implicit-null
3128 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3129 */
318cac96 3130 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3131 if (new_select) {
3132 if (!old_select
3133 || bgp_label_index_differs(new_select, old_select)
57592a53 3134 || new_select->sub_type != old_select->sub_type
9bcb3eef 3135 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3136 /* Enforced penultimate hop popping:
3137 * implicit-null for local routes, aggregate
3138 * and redistributed routes
3139 */
bb2ca692 3140 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3141 if (CHECK_FLAG(
9bcb3eef 3142 dest->flags,
992dd67e
PR
3143 BGP_NODE_REGISTERED_FOR_LABEL)
3144 || CHECK_FLAG(
3145 dest->flags,
3146 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3147 bgp_unregister_for_label(dest);
67f67ba4
DA
3148 dest->local_label = mpls_lse_encode(
3149 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3150 1);
9bcb3eef 3151 bgp_set_valid_label(&dest->local_label);
d62a17ae 3152 } else
9bcb3eef
DS
3153 bgp_register_for_label(dest,
3154 new_select);
d62a17ae 3155 }
9bcb3eef 3156 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3157 BGP_NODE_REGISTERED_FOR_LABEL)
3158 || CHECK_FLAG(dest->flags,
3159 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3160 bgp_unregister_for_label(dest);
318cac96 3161 }
992dd67e
PR
3162 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3163 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3164 bgp_unregister_for_label(dest);
d62a17ae 3165 }
cd1964ff 3166
b54892e0 3167 if (debug)
ddb5b488 3168 zlog_debug(
4378495a
DS
3169 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3170 __func__, dest, bgp->name_pretty, afi2str(afi),
3171 safi2str(safi), old_select, new_select);
ddb5b488 3172
d62a17ae 3173 /* If best route remains the same and this is not due to user-initiated
3174 * clear, see exactly what needs to be done.
3175 */
d62a17ae 3176 if (old_select && old_select == new_select
9bcb3eef 3177 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3178 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3179 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3180 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3181#ifdef ENABLE_BGP_VNC
d62a17ae 3182 vnc_import_bgp_add_route(bgp, p, old_select);
3183 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3184#endif
bb744275 3185 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3186 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3187
be785e35
DS
3188 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3189 && new_select->sub_type == BGP_ROUTE_NORMAL)
3190 SET_FLAG(dest->flags,
3191 BGP_NODE_FIB_INSTALL_PENDING);
3192
ddb5b488
PZ
3193 if (new_select->type == ZEBRA_ROUTE_BGP
3194 && (new_select->sub_type == BGP_ROUTE_NORMAL
3195 || new_select->sub_type
3196 == BGP_ROUTE_IMPORTED))
3197
9bcb3eef 3198 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3199 bgp, afi, safi);
3200 }
d62a17ae 3201 }
d62a17ae 3202
3203 /* If there is a change of interest to peers, reannounce the
3204 * route. */
1defdda8 3205 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3206 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3207 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3208 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3209
3210 /* unicast routes must also be annouced to
3211 * labeled-unicast update-groups */
3212 if (safi == SAFI_UNICAST)
3213 group_announce_route(bgp, afi,
9bcb3eef 3214 SAFI_LABELED_UNICAST, dest,
d62a17ae 3215 new_select);
3216
1defdda8 3217 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3218 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3219 }
fee0f4c6 3220
3b0c17e1 3221 /* advertise/withdraw type-5 routes */
3222 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3223 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3224 bgp_process_evpn_route_injection(
9bcb3eef 3225 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3226
b1875e65 3227 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3228 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3229 bgp_zebra_clear_route_change_flags(dest);
3230 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3231 return;
d62a17ae 3232 }
8ad7271d 3233
d62a17ae 3234 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3235 */
9bcb3eef 3236 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3237
3238 /* bestpath has changed; bump version */
3239 if (old_select || new_select) {
9bcb3eef 3240 bgp_bump_version(dest);
d62a17ae 3241
3242 if (!bgp->t_rmap_def_originate_eval) {
3243 bgp_lock(bgp);
3244 thread_add_timer(
3245 bm->master,
3246 update_group_refresh_default_originate_route_map,
3247 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3248 &bgp->t_rmap_def_originate_eval);
3249 }
3250 }
3f9c7369 3251
d62a17ae 3252 if (old_select)
9bcb3eef 3253 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3254 if (new_select) {
ddb5b488
PZ
3255 if (debug)
3256 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3257 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3258 bgp_path_info_unset_flag(dest, new_select,
3259 BGP_PATH_ATTR_CHANGED);
1defdda8 3260 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3261 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3262 }
338b3424 3263
49e5a4a0 3264#ifdef ENABLE_BGP_VNC
d62a17ae 3265 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3266 if (old_select != new_select) {
3267 if (old_select) {
3268 vnc_import_bgp_exterior_del_route(bgp, p,
3269 old_select);
3270 vnc_import_bgp_del_route(bgp, p, old_select);
3271 }
3272 if (new_select) {
3273 vnc_import_bgp_exterior_add_route(bgp, p,
3274 new_select);
3275 vnc_import_bgp_add_route(bgp, p, new_select);
3276 }
3277 }
3278 }
65efcfce
LB
3279#endif
3280
9bcb3eef 3281 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3282
3283 /* unicast routes must also be annouced to labeled-unicast update-groups
3284 */
3285 if (safi == SAFI_UNICAST)
9bcb3eef 3286 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3287 new_select);
3288
3289 /* FIB update. */
3290 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3291 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3292
d62a17ae 3293 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3294 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3295 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3296 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3297
be785e35
DS
3298 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3299 SET_FLAG(dest->flags,
3300 BGP_NODE_FIB_INSTALL_PENDING);
3301
2b659f33
MK
3302 /* if this is an evpn imported type-5 prefix,
3303 * we need to withdraw the route first to clear
3304 * the nh neigh and the RMAC entry.
3305 */
3306 if (old_select &&
3307 is_route_parent_evpn(old_select))
3308 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3309
9bcb3eef 3310 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3311 } else {
d62a17ae 3312 /* Withdraw the route from the kernel. */
3313 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3314 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3315 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3316 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3317
568e10ca 3318 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3319 }
718e3744 3320 }
3064bf43 3321
9bcb3eef 3322 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3323 old_select);
5424b7ba 3324
d62a17ae 3325 /* Clear any route change flags. */
9bcb3eef 3326 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3327
18ee8310 3328 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3329 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3330 bgp_path_info_reap(dest, old_select);
d62a17ae 3331
9bcb3eef 3332 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3333 return;
718e3744 3334}
3335
f009ff26 3336/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3337void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3338{
9bcb3eef 3339 struct bgp_dest *dest;
f009ff26 3340 int cnt = 0;
3341 struct afi_safi_info *thread_info;
f009ff26 3342
56c226e7
DS
3343 if (bgp->gr_info[afi][safi].t_route_select) {
3344 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3345
3346 thread_info = THREAD_ARG(t);
3347 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3348 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3349 }
f009ff26 3350
3351 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3352 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3353 get_afi_safi_str(afi, safi, false),
26742171 3354 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3355 }
3356
3357 /* Process the route list */
6338d242 3358 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3359 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3360 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3361 dest = bgp_route_next(dest)) {
3362 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3363 continue;
3364
3365 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3366 bgp->gr_info[afi][safi].gr_deferred--;
3367 bgp_process_main_one(bgp, dest, afi, safi);
3368 cnt++;
067ea165
CB
3369 }
3370 /* If iteration stopped before the entire table was traversed then the
3371 * node needs to be unlocked.
3372 */
3373 if (dest) {
3374 bgp_dest_unlock_node(dest);
3375 dest = NULL;
f009ff26 3376 }
3377
9e3b51a7 3378 /* Send EOR message when all routes are processed */
6338d242 3379 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3380 bgp_send_delayed_eor(bgp);
8c48b3b6 3381 /* Send route processing complete message to RIB */
3382 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3383 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3384 return;
9e3b51a7 3385 }
f009ff26 3386
3387 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3388
3389 thread_info->afi = afi;
3390 thread_info->safi = safi;
3391 thread_info->bgp = bgp;
3392
3393 /* If there are more routes to be processed, start the
3394 * selection timer
3395 */
3396 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3397 BGP_ROUTE_SELECT_DELAY,
3398 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3399}
3400
aac24838 3401static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3402{
aac24838
JB
3403 struct bgp_process_queue *pqnode = data;
3404 struct bgp *bgp = pqnode->bgp;
d62a17ae 3405 struct bgp_table *table;
9bcb3eef 3406 struct bgp_dest *dest;
aac24838
JB
3407
3408 /* eoiu marker */
3409 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3410 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3411 /* should always have dedicated wq call */
3412 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3413 return WQ_SUCCESS;
3414 }
3415
ac021f40 3416 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3417 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3418 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3419 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3420 table = bgp_dest_table(dest);
3421 /* note, new DESTs may be added as part of processing */
3422 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3423
9bcb3eef 3424 bgp_dest_unlock_node(dest);
d62a17ae 3425 bgp_table_unlock(table);
3426 }
aac24838
JB
3427
3428 return WQ_SUCCESS;
3429}
3430
3431static void bgp_processq_del(struct work_queue *wq, void *data)
3432{
3433 struct bgp_process_queue *pqnode = data;
3434
3435 bgp_unlock(pqnode->bgp);
3436
3437 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3438}
3439
b6c386bb 3440void bgp_process_queue_init(struct bgp *bgp)
200df115 3441{
b6c386bb
DS
3442 if (!bgp->process_queue) {
3443 char name[BUFSIZ];
3444
3445 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3446 bgp->process_queue = work_queue_new(bm->master, name);
3447 }
3448
3449 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3450 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3451 bgp->process_queue->spec.max_retries = 0;
3452 bgp->process_queue->spec.hold = 50;
d62a17ae 3453 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3454 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3455}
3456
cfe8d15a 3457static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3458{
3459 struct bgp_process_queue *pqnode;
3460
a4d82a8a
PZ
3461 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3462 sizeof(struct bgp_process_queue));
aac24838
JB
3463
3464 /* unlocked in bgp_processq_del */
3465 pqnode->bgp = bgp_lock(bgp);
3466 STAILQ_INIT(&pqnode->pqueue);
3467
aac24838
JB
3468 return pqnode;
3469}
3470
9bcb3eef 3471void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3472{
aac24838 3473#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3474 struct work_queue *wq = bgp->process_queue;
d62a17ae 3475 struct bgp_process_queue *pqnode;
cfe8d15a 3476 int pqnode_reuse = 0;
495f0b13 3477
d62a17ae 3478 /* already scheduled for processing? */
9bcb3eef 3479 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3480 return;
2e02b9b2 3481
f009ff26 3482 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3483 * the workqueue
3484 */
9bcb3eef 3485 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3486 if (BGP_DEBUG(update, UPDATE_OUT))
3487 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3488 dest);
f009ff26 3489 return;
3490 }
3491
46aeabed
LS
3492 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3493 if (BGP_DEBUG(update, UPDATE_OUT))
3494 zlog_debug(
3495 "Soft reconfigure table in progress for route %p",
3496 dest);
3497 return;
3498 }
3499
aac24838 3500 if (wq == NULL)
d62a17ae 3501 return;
3502
aac24838 3503 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3504 limit only if is from the same BGP view and it's not an EOIU marker
3505 */
aac24838
JB
3506 if (work_queue_item_count(wq)) {
3507 struct work_queue_item *item = work_queue_last_item(wq);
3508 pqnode = item->data;
228da428 3509
a4d82a8a
PZ
3510 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3511 || pqnode->bgp != bgp
3512 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3513 pqnode = bgp_processq_alloc(bgp);
3514 else
3515 pqnode_reuse = 1;
aac24838 3516 } else
cfe8d15a 3517 pqnode = bgp_processq_alloc(bgp);
aac24838 3518 /* all unlocked in bgp_process_wq */
9bcb3eef 3519 bgp_table_lock(bgp_dest_table(dest));
aac24838 3520
9bcb3eef
DS
3521 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3522 bgp_dest_lock_node(dest);
aac24838 3523
60466a63 3524 /* can't be enqueued twice */
9bcb3eef
DS
3525 assert(STAILQ_NEXT(dest, pq) == NULL);
3526 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3527 pqnode->queued++;
3528
cfe8d15a
LB
3529 if (!pqnode_reuse)
3530 work_queue_add(wq, pqnode);
3531
d62a17ae 3532 return;
fee0f4c6 3533}
0a486e5f 3534
d62a17ae 3535void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3536{
d62a17ae 3537 struct bgp_process_queue *pqnode;
cb1faec9 3538
b6c386bb 3539 if (bgp->process_queue == NULL)
d62a17ae 3540 return;
2e02b9b2 3541
cfe8d15a 3542 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3543
aac24838 3544 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3545 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3546}
3547
cc9f21da 3548static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3549{
d62a17ae 3550 struct peer *peer;
0a486e5f 3551
d62a17ae 3552 peer = THREAD_ARG(thread);
3553 peer->t_pmax_restart = NULL;
0a486e5f 3554
d62a17ae 3555 if (bgp_debug_neighbor_events(peer))
3556 zlog_debug(
3557 "%s Maximum-prefix restart timer expired, restore peering",
3558 peer->host);
0a486e5f 3559
a9bafa95 3560 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3561 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3562}
3563
9cbd06e0
DA
3564static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3565 safi_t safi)
3566{
3567 uint32_t count = 0;
f41b0459 3568 bool filtered = false;
9cbd06e0
DA
3569 struct bgp_dest *dest;
3570 struct bgp_adj_in *ain;
40bb2ccf 3571 struct attr attr = {};
9cbd06e0
DA
3572 struct bgp_table *table = peer->bgp->rib[afi][safi];
3573
3574 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3575 for (ain = dest->adj_in; ain; ain = ain->next) {
3576 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3577
3578 attr = *ain->attr;
9cbd06e0
DA
3579
3580 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3581 == FILTER_DENY)
f41b0459
DA
3582 filtered = true;
3583
3584 if (bgp_input_modifier(
3585 peer, rn_p, &attr, afi, safi,
3586 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3587 NULL, 0, NULL)
3588 == RMAP_DENY)
3589 filtered = true;
3590
3591 if (filtered)
9cbd06e0 3592 count++;
f41b0459 3593
d498917e 3594 bgp_attr_flush(&attr);
9cbd06e0
DA
3595 }
3596 }
3597
3598 return count;
3599}
3600
3dc339cd
DA
3601bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3602 int always)
718e3744 3603{
d62a17ae 3604 iana_afi_t pkt_afi;
5c525538 3605 iana_safi_t pkt_safi;
9cbd06e0
DA
3606 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3607 PEER_FLAG_MAX_PREFIX_FORCE))
3608 ? bgp_filtered_routes_count(peer, afi, safi)
3609 + peer->pcount[afi][safi]
3610 : peer->pcount[afi][safi];
9cabb64b 3611
d62a17ae 3612 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3613 return false;
e0701b79 3614
9cbd06e0 3615 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3616 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3617 PEER_STATUS_PREFIX_LIMIT)
3618 && !always)
3dc339cd 3619 return false;
e0701b79 3620
d62a17ae 3621 zlog_info(
f70c91dc
DA
3622 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3623 get_afi_safi_str(afi, safi, false), peer, pcount,
3624 peer->pmax[afi][safi]);
d62a17ae 3625 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3626
3627 if (CHECK_FLAG(peer->af_flags[afi][safi],
3628 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3629 return false;
d62a17ae 3630
3631 /* Convert AFI, SAFI to values for packet. */
3632 pkt_afi = afi_int2iana(afi);
3633 pkt_safi = safi_int2iana(safi);
3634 {
d7c0a89a 3635 uint8_t ndata[7];
d62a17ae 3636
3637 ndata[0] = (pkt_afi >> 8);
3638 ndata[1] = pkt_afi;
3639 ndata[2] = pkt_safi;
3640 ndata[3] = (peer->pmax[afi][safi] >> 24);
3641 ndata[4] = (peer->pmax[afi][safi] >> 16);
3642 ndata[5] = (peer->pmax[afi][safi] >> 8);
3643 ndata[6] = (peer->pmax[afi][safi]);
3644
3645 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3646 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3647 BGP_NOTIFY_CEASE_MAX_PREFIX,
3648 ndata, 7);
3649 }
3650
3651 /* Dynamic peers will just close their connection. */
3652 if (peer_dynamic_neighbor(peer))
3dc339cd 3653 return true;
d62a17ae 3654
3655 /* restart timer start */
3656 if (peer->pmax_restart[afi][safi]) {
3657 peer->v_pmax_restart =
3658 peer->pmax_restart[afi][safi] * 60;
3659
3660 if (bgp_debug_neighbor_events(peer))
3661 zlog_debug(
f70c91dc
DA
3662 "%pBP Maximum-prefix restart timer started for %d secs",
3663 peer, peer->v_pmax_restart);
d62a17ae 3664
3665 BGP_TIMER_ON(peer->t_pmax_restart,
3666 bgp_maximum_prefix_restart_timer,
3667 peer->v_pmax_restart);
3668 }
3669
3dc339cd 3670 return true;
d62a17ae 3671 } else
3672 UNSET_FLAG(peer->af_sflags[afi][safi],
3673 PEER_STATUS_PREFIX_LIMIT);
3674
b1823b69
DS
3675 if (pcount
3676 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3677 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3678 PEER_STATUS_PREFIX_THRESHOLD)
3679 && !always)
3dc339cd 3680 return false;
d62a17ae 3681
3682 zlog_info(
f70c91dc
DA
3683 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3684 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3685 peer->pmax[afi][safi]);
d62a17ae 3686 SET_FLAG(peer->af_sflags[afi][safi],
3687 PEER_STATUS_PREFIX_THRESHOLD);
3688 } else
3689 UNSET_FLAG(peer->af_sflags[afi][safi],
3690 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3691 return false;
718e3744 3692}
3693
b40d939b 3694/* Unconditionally remove the route from the RIB, without taking
3695 * damping into consideration (eg, because the session went down)
3696 */
9bcb3eef 3697void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3698 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3699{
f009ff26 3700
3701 struct bgp *bgp = NULL;
3702 bool delete_route = false;
3703
9bcb3eef
DS
3704 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3705 safi);
d62a17ae 3706
f009ff26 3707 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3708 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3709
f009ff26 3710 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3711 * flag
3712 */
3713 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3714 delete_route = true;
9bcb3eef 3715 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3716 delete_route = true;
f009ff26 3717 if (delete_route) {
9bcb3eef
DS
3718 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3719 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3720 bgp = pi->peer->bgp;
26742171 3721 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3722 }
3723 }
3724 }
4a11bf2c 3725
9bcb3eef
DS
3726 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3727 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3728}
3729
9bcb3eef 3730static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3731 struct peer *peer, afi_t afi, safi_t safi,
3732 struct prefix_rd *prd)
3733{
9bcb3eef 3734 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3735
d62a17ae 3736 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3737 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3738 */
b4f7f45b
IR
3739 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3740 && peer->sort == BGP_PEER_EBGP)
3741 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3742 == BGP_DAMP_SUPPRESSED) {
3743 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3744 safi);
3745 return;
d62a17ae 3746 }
3747
49e5a4a0 3748#ifdef ENABLE_BGP_VNC
d62a17ae 3749 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3750 struct bgp_dest *pdest = NULL;
d62a17ae 3751 struct bgp_table *table = NULL;
3752
9bcb3eef
DS
3753 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3754 (struct prefix *)prd);
3755 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3756 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3757
3758 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3759 peer->bgp, prd, table, p, pi);
d62a17ae 3760 }
9bcb3eef 3761 bgp_dest_unlock_node(pdest);
d62a17ae 3762 }
3763 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3764 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3765
b54892e0
DS
3766 vnc_import_bgp_del_route(peer->bgp, p, pi);
3767 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3768 }
65efcfce 3769 }
d62a17ae 3770#endif
128ea8ab 3771
d62a17ae 3772 /* If this is an EVPN route, process for un-import. */
3773 if (safi == SAFI_EVPN)
b54892e0 3774 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3775
9bcb3eef 3776 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3777}
3778
4b7e6066
DS
3779struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3780 struct peer *peer, struct attr *attr,
9bcb3eef 3781 struct bgp_dest *dest)
fb018d25 3782{
4b7e6066 3783 struct bgp_path_info *new;
fb018d25 3784
d62a17ae 3785 /* Make new BGP info. */
4b7e6066 3786 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3787 new->type = type;
3788 new->instance = instance;
3789 new->sub_type = sub_type;
3790 new->peer = peer;
3791 new->attr = attr;
083ec940 3792 new->uptime = monotime(NULL);
9bcb3eef 3793 new->net = dest;
d62a17ae 3794 return new;
fb018d25
DS
3795}
3796
c265ee22 3797/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3798bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3799 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3800 struct bgp_dest *dest)
d62a17ae 3801{
2dbe3fa9 3802 bool ret = false;
b099a5c8
DA
3803 bool is_bgp_static_route =
3804 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3805 : false;
d62a17ae 3806
e8442016
DS
3807 /*
3808 * Only validated for unicast and multicast currently.
3809 * Also valid for EVPN where the nexthop is an IP address.
3810 * If we are a bgp static route being checked then there is
3811 * no need to check to see if the nexthop is martian as
3812 * that it should be ok.
3813 */
3814 if (is_bgp_static_route ||
3815 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3816 return false;
d62a17ae 3817
3818 /* If NEXT_HOP is present, validate it. */
3819 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3820 if (attr->nexthop.s_addr == INADDR_ANY ||
3821 !ipv4_unicast_valid(&attr->nexthop) ||
3822 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3823 return true;
d62a17ae 3824 }
c265ee22 3825
d62a17ae 3826 /* If MP_NEXTHOP is present, validate it. */
3827 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3828 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3829 * it is not an IPv6 link-local address.
0355b41d
DA
3830 *
3831 * If we receive an UPDATE with nexthop length set to 32 bytes
3832 * we shouldn't discard an UPDATE if it's set to (::).
3833 * The link-local (2st) is validated along the code path later.
d62a17ae 3834 */
3835 if (attr->mp_nexthop_len) {
3836 switch (attr->mp_nexthop_len) {
3837 case BGP_ATTR_NHLEN_IPV4:
3838 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3839 ret = (attr->mp_nexthop_global_in.s_addr ==
3840 INADDR_ANY ||
3841 !ipv4_unicast_valid(
3842 &attr->mp_nexthop_global_in) ||
3843 bgp_nexthop_self(bgp, afi, type, stype, attr,
3844 dest));
d62a17ae 3845 break;
3846
3847 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3848 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3849 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3850 &attr->mp_nexthop_global)
d62a17ae 3851 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3852 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3853 &attr->mp_nexthop_global)
3854 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3855 dest));
d62a17ae 3856 break;
0355b41d
DA
3857 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3858 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3859 || IN6_IS_ADDR_MULTICAST(
3860 &attr->mp_nexthop_global)
3861 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3862 dest));
0355b41d 3863 break;
d62a17ae 3864
3865 default:
3dc339cd 3866 ret = true;
d62a17ae 3867 break;
3868 }
3869 }
c265ee22 3870
d62a17ae 3871 return ret;
3872}
3873
aade37d7 3874static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3875{
3876 struct community *old;
3877 struct community *new;
3878 struct community *merge;
aade37d7 3879 struct community *no_export;
2721dd61 3880
9a706b42 3881 old = bgp_attr_get_community(attr);
aade37d7 3882 no_export = community_str2com("no-export");
2721dd61 3883
b4efa101
DA
3884 assert(no_export);
3885
2721dd61 3886 if (old) {
aade37d7 3887 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3888
3889 if (!old->refcnt)
3890 community_free(&old);
3891
3892 new = community_uniq_sort(merge);
3893 community_free(&merge);
3894 } else {
aade37d7 3895 new = community_dup(no_export);
2721dd61
DA
3896 }
3897
aade37d7 3898 community_free(&no_export);
2721dd61 3899
9a706b42 3900 bgp_attr_set_community(attr, new);
2721dd61
DA
3901}
3902
46dbf9d0
DA
3903static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3904 struct attr *attr, const struct prefix *prefix,
3905 int *sub_type)
3906{
3907 struct listnode *node, *nnode;
3908 struct bgp *bgp;
3909 bool accept_own_found = false;
3910
3911 if (safi != SAFI_MPLS_VPN)
3912 return false;
3913
3914 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3915 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3916 return false;
3917
3918 /* The route in question carries the ACCEPT_OWN community */
3919 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3920 struct community *comm = bgp_attr_get_community(attr);
3921
3922 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3923 accept_own_found = true;
3924 }
3925
3926 /* The route in question is targeted to one or more destination VRFs
3927 * on the router (as determined by inspecting the Route Target(s)).
3928 */
3929 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3930 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3931 continue;
3932
3933 if (accept_own_found &&
3934 ecommunity_include(
3935 bgp->vpn_policy[afi]
3936 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3937 bgp_attr_get_ecommunity(attr))) {
3938 if (bgp_debug_update(peer, prefix, NULL, 1))
3939 zlog_debug(
3940 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3941 peer, prefix);
3942
3943 /* Treat this route as imported, because it's leaked
3944 * already from another VRF, and we got an updated
3945 * version from route-reflector with ACCEPT_OWN
3946 * community.
3947 */
3948 *sub_type = BGP_ROUTE_IMPORTED;
3949
3950 return true;
3951 }
3952 }
3953
3954 return false;
3955}
3956
367b458c
DS
3957void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3958 struct attr *attr, afi_t afi, safi_t safi, int type,
3959 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3960 uint32_t num_labels, int soft_reconfig,
3961 struct bgp_route_evpn *evpn)
d62a17ae 3962{
3963 int ret;
3964 int aspath_loop_count = 0;
9bcb3eef 3965 struct bgp_dest *dest;
d62a17ae 3966 struct bgp *bgp;
3967 struct attr new_attr;
3968 struct attr *attr_new;
40381db7 3969 struct bgp_path_info *pi;
819e6767 3970 struct bgp_path_info *new = NULL;
4b7e6066 3971 struct bgp_path_info_extra *extra;
d62a17ae 3972 const char *reason;
3973 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3974 int connected = 0;
3975 int do_loop_check = 1;
3976 int has_valid_label = 0;
7c312383 3977 afi_t nh_afi;
9146341f 3978 bool force_evpn_import = false;
907707db 3979 safi_t orig_safi = safi;
a486300b 3980 bool leak_success = true;
b2ac1d0d 3981 int allowas_in = 0;
949b0f24 3982
c7bb4f00 3983 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3984 char pfxprint[PREFIX2STR_BUFFER];
3985
3986 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3987 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3988 afi, safi, attr);
6401252f
QY
3989 }
3990
49e5a4a0 3991#ifdef ENABLE_BGP_VNC
d62a17ae 3992 int vnc_implicit_withdraw = 0;
65efcfce 3993#endif
d62a17ae 3994 int same_attr = 0;
f8745525 3995 const struct prefix *bgp_nht_param_prefix;
718e3744 3996
907707db
MS
3997 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3998 if (orig_safi == SAFI_LABELED_UNICAST)
3999 safi = SAFI_UNICAST;
4000
6006b807 4001 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4002 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4003 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4004
d62a17ae 4005 bgp = peer->bgp;
9bcb3eef 4006 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4007 /* TODO: Check to see if we can get rid of "is_valid_label" */
4008 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4009 has_valid_label = (num_labels > 0) ? 1 : 0;
4010 else
4011 has_valid_label = bgp_is_valid_label(label);
718e3744 4012
28f66de2
MS
4013 if (has_valid_label)
4014 assert(label != NULL);
4015
66ff6089
AD
4016 /* Update overlay index of the attribute */
4017 if (afi == AFI_L2VPN && evpn)
4018 memcpy(&attr->evpn_overlay, evpn,
4019 sizeof(struct bgp_route_evpn));
4020
d62a17ae 4021 /* When peer's soft reconfiguration enabled. Record input packet in
4022 Adj-RIBs-In. */
4023 if (!soft_reconfig
4024 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4025 && peer != bgp->peer_self)
9bcb3eef 4026 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4027
b2ac1d0d
MS
4028 /* Update permitted loop count */
4029 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4030 allowas_in = peer->allowas_in[afi][safi];
4031
d62a17ae 4032 /* Check previously received route. */
9bcb3eef 4033 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4034 if (pi->peer == peer && pi->type == type
4035 && pi->sub_type == sub_type
4036 && pi->addpath_rx_id == addpath_id)
d62a17ae 4037 break;
4038
4039 /* AS path local-as loop check. */
4040 if (peer->change_local_as) {
b2ac1d0d
MS
4041 if (allowas_in)
4042 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4043 else if (!CHECK_FLAG(peer->flags,
4044 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4045 aspath_loop_count = 1;
4046
4047 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4048 > aspath_loop_count) {
b4d46cc9 4049 peer->stat_pfx_aspath_loop++;
692174a1 4050 reason = "as-path contains our own AS;";
d62a17ae 4051 goto filtered;
4052 }
718e3744 4053 }
718e3744 4054
d62a17ae 4055 /* If the peer is configured for "allowas-in origin" and the last ASN in
4056 * the
4057 * as-path is our ASN then we do not need to call aspath_loop_check
4058 */
4059 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4060 if (aspath_get_last_as(attr->aspath) == bgp->as)
4061 do_loop_check = 0;
4062
f8745525
PG
4063 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4064 bgp_nht_param_prefix = NULL;
4065 else
4066 bgp_nht_param_prefix = p;
4067
d62a17ae 4068 /* AS path loop check. */
4069 if (do_loop_check) {
b0a8f709
FD
4070 if (aspath_loop_check(attr->aspath, bgp->as) >
4071 peer->allowas_in[afi][safi]) {
b4d46cc9 4072 peer->stat_pfx_aspath_loop++;
d62a17ae 4073 reason = "as-path contains our own AS;";
4074 goto filtered;
4075 }
4076 }
aac9ef6c 4077
b0a8f709
FD
4078 /* If we're a CONFED we need to loop check the CONFED ID too */
4079 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4080 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4081 peer->allowas_in[afi][safi]) {
4082 peer->stat_pfx_aspath_loop++;
4083 reason = "as-path contains our own confed AS;";
4084 goto filtered;
4085 }
4086
46dbf9d0
DA
4087 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4088 * enabled, then take care of that too.
4089 */
4090 bool accept_own = false;
4091
d62a17ae 4092 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4093 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4094 accept_own =
4095 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4096 if (!accept_own) {
4097 peer->stat_pfx_originator_loop++;
4098 reason = "originator is us;";
4099 goto filtered;
4100 }
d62a17ae 4101 }
718e3744 4102
d62a17ae 4103 /* Route reflector cluster ID check. */
4104 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4105 peer->stat_pfx_cluster_loop++;
d62a17ae 4106 reason = "reflected from the same cluster;";
4107 goto filtered;
4108 }
718e3744 4109
d62a17ae 4110 /* Apply incoming filter. */
907707db 4111 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4112 peer->stat_pfx_filter++;
d62a17ae 4113 reason = "filter;";
4114 goto filtered;
4115 }
718e3744 4116
a8b72dc6
DA
4117 /* RFC 8212 to prevent route leaks.
4118 * This specification intends to improve this situation by requiring the
4119 * explicit configuration of both BGP Import and Export Policies for any
4120 * External BGP (EBGP) session such as customers, peers, or
4121 * confederation boundaries for all enabled address families. Through
4122 * codification of the aforementioned requirement, operators will
4123 * benefit from consistent behavior across different BGP
4124 * implementations.
4125 */
1d3fdccf 4126 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4127 if (!bgp_inbound_policy_exists(peer,
4128 &peer->filter[afi][safi])) {
4129 reason = "inbound policy missing";
b17826b7
DS
4130 if (monotime_since(&bgp->ebgprequirespolicywarning,
4131 NULL) > FIFTEENMINUTE2USEC ||
4132 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4133 zlog_warn(
4134 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4135 monotime(&bgp->ebgprequirespolicywarning);
4136 }
a8b72dc6
DA
4137 goto filtered;
4138 }
4139
fb29348a
DA
4140 /* draft-ietf-idr-deprecate-as-set-confed-set
4141 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4142 * Eventually, This document (if approved) updates RFC 4271
4143 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4144 * and obsoletes RFC 6472.
4145 */
7f972cd8 4146 if (peer->bgp->reject_as_sets)
fb29348a
DA
4147 if (aspath_check_as_sets(attr->aspath)) {
4148 reason =
4149 "as-path contains AS_SET or AS_CONFED_SET type;";
4150 goto filtered;
4151 }
4152
6f4f49b2 4153 new_attr = *attr;
d62a17ae 4154
4155 /* Apply incoming route-map.
4156 * NB: new_attr may now contain newly allocated values from route-map
4157 * "set"
4158 * commands, so we need bgp_attr_flush in the error paths, until we
4159 * intern
4160 * the attr (which takes over the memory references) */
907707db 4161 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4162 num_labels, dest)
4163 == RMAP_DENY) {
b4d46cc9 4164 peer->stat_pfx_filter++;
d62a17ae 4165 reason = "route-map;";
4166 bgp_attr_flush(&new_attr);
4167 goto filtered;
4168 }
718e3744 4169
05864da7 4170 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4171 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4172 /* remove from RIB previous entry */
4173 bgp_zebra_withdraw(p, pi, bgp, safi);
4174 }
4175
7f323236
DW
4176 if (peer->sort == BGP_PEER_EBGP) {
4177
2721dd61
DA
4178 /* rfc7999:
4179 * A BGP speaker receiving an announcement tagged with the
4180 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4181 * NO_EXPORT community as defined in RFC1997, or a
4182 * similar community, to prevent propagation of the
4183 * prefix outside the local AS. The community to prevent
4184 * propagation SHOULD be chosen according to the operator's
4185 * routing policy.
4186 */
9a706b42
DA
4187 if (bgp_attr_get_community(&new_attr) &&
4188 community_include(bgp_attr_get_community(&new_attr),
4189 COMMUNITY_BLACKHOLE))
aade37d7 4190 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4191
a4d82a8a
PZ
4192 /* If we receive the graceful-shutdown community from an eBGP
4193 * peer we must lower local-preference */
9a706b42
DA
4194 if (bgp_attr_get_community(&new_attr) &&
4195 community_include(bgp_attr_get_community(&new_attr),
4196 COMMUNITY_GSHUT)) {
7f323236
DW
4197 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4198 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4199
4f770cf1
DA
4200 /* If graceful-shutdown is configured globally or
4201 * per neighbor, then add the GSHUT community to
4202 * all paths received from eBGP peers. */
4203 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4204 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4205 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4206 }
4207
d62a17ae 4208 /* next hop check. */
860ad3f9
DS
4209 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4210 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4211 &new_attr, dest)) {
b4d46cc9 4212 peer->stat_pfx_nh_invalid++;
d62a17ae 4213 reason = "martian or self next-hop;";
4214 bgp_attr_flush(&new_attr);
4215 goto filtered;
4216 }
718e3744 4217
5c14a191 4218 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4219 peer->stat_pfx_nh_invalid++;
4e802e66 4220 reason = "self mac;";
4dbf2038 4221 bgp_attr_flush(&new_attr);
4e802e66
DS
4222 goto filtered;
4223 }
4224
5a78f2bc
EB
4225 if (bgp_check_role_applicability(afi, safi) &&
4226 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4227 reason = "failing otc validation";
4228 bgp_attr_flush(&new_attr);
4229 goto filtered;
4230 }
a1b773e2
DS
4231 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4232 * condition :
4233 * Suppress fib is enabled
4234 * BGP_OPT_NO_FIB is not enabled
4235 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4236 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4237 */
4238 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4239 && (sub_type == BGP_ROUTE_NORMAL)
4240 && (!bgp_option_check(BGP_OPT_NO_FIB))
4241 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4242 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4243
01da2d26
DA
4244 /* If neighbor soo is configured, tag all incoming routes with
4245 * this SoO tag and then filter out advertisements in
4246 * subgroup_announce_check() if it matches the configured SoO
4247 * on the other peer.
4248 */
4249 if (peer->soo[afi][safi]) {
4250 struct ecommunity *old_ecomm =
4251 bgp_attr_get_ecommunity(&new_attr);
4252 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4253 struct ecommunity *new_ecomm;
4254
4255 if (old_ecomm) {
4256 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4257 ecomm_soo);
4258
4259 if (!old_ecomm->refcnt)
4260 ecommunity_free(&old_ecomm);
4261 } else {
4262 new_ecomm = ecommunity_dup(ecomm_soo);
4263 }
4264
4265 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4266 }
4267
4dbf2038 4268 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4269
d62a17ae 4270 /* If the update is implicit withdraw. */
40381db7 4271 if (pi) {
083ec940 4272 pi->uptime = monotime(NULL);
40381db7 4273 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4274
9bcb3eef 4275 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4276
d62a17ae 4277 /* Same attribute comes in. */
40381db7 4278 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4279 && same_attr
d62a17ae 4280 && (!has_valid_label
40381db7 4281 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4282 num_labels * sizeof(mpls_label_t))
66ff6089 4283 == 0)) {
b4f7f45b
IR
4284 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4285 BGP_CONFIG_DAMPENING)
d62a17ae 4286 && peer->sort == BGP_PEER_EBGP
40381db7 4287 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4288 if (bgp_debug_update(peer, p, NULL, 1)) {
4289 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4290 afi, safi, prd, p, label,
4291 num_labels, addpath_id ? 1 : 0,
66ff6089 4292 addpath_id, evpn, pfx_buf,
a4d82a8a 4293 sizeof(pfx_buf));
f70c91dc 4294 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4295 pfx_buf);
4296 }
4297
9bcb3eef 4298 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4299 != BGP_DAMP_SUPPRESSED) {
40381db7 4300 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4301 safi);
9bcb3eef 4302 bgp_process(bgp, dest, afi, safi);
d62a17ae 4303 }
4304 } else /* Duplicate - odd */
4305 {
4306 if (bgp_debug_update(peer, p, NULL, 1)) {
4307 if (!peer->rcvd_attr_printed) {
4308 zlog_debug(
f70c91dc
DA
4309 "%pBP rcvd UPDATE w/ attr: %s",
4310 peer,
d62a17ae 4311 peer->rcvd_attr_str);
4312 peer->rcvd_attr_printed = 1;
4313 }
4314
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));
d62a17ae 4320 zlog_debug(
f70c91dc
DA
4321 "%pBP rcvd %s...duplicate ignored",
4322 peer, pfx_buf);
d62a17ae 4323 }
4324
4325 /* graceful restart STALE flag unset. */
40381db7 4326 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4327 bgp_path_info_unset_flag(
9bcb3eef
DS
4328 dest, pi, BGP_PATH_STALE);
4329 bgp_dest_set_defer_flag(dest, false);
4330 bgp_process(bgp, dest, afi, safi);
d62a17ae 4331 }
4332 }
4333
9bcb3eef 4334 bgp_dest_unlock_node(dest);
d62a17ae 4335 bgp_attr_unintern(&attr_new);
4336
367b458c 4337 return;
d62a17ae 4338 }
718e3744 4339
d62a17ae 4340 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4341 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4342 if (bgp_debug_update(peer, p, NULL, 1)) {
4343 bgp_debug_rdpfxpath2str(
a4d82a8a 4344 afi, safi, prd, p, label, num_labels,
66ff6089 4345 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4346 pfx_buf, sizeof(pfx_buf));
d62a17ae 4347 zlog_debug(
f70c91dc
DA
4348 "%pBP rcvd %s, flapped quicker than processing",
4349 peer, pfx_buf);
d62a17ae 4350 }
4351
9bcb3eef 4352 bgp_path_info_restore(dest, pi);
9146341f 4353
4354 /*
4355 * If the BGP_PATH_REMOVED flag is set, then EVPN
4356 * routes would have been unimported already when a
4357 * prior BGP withdraw processing happened. Such routes
4358 * need to be imported again, so flag accordingly.
4359 */
4360 force_evpn_import = true;
704e189e 4361 } else {
4362 /* implicit withdraw, decrement aggregate and pcount
4363 * here. only if update is accepted, they'll increment
4364 * below.
4365 */
4366 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4367 }
718e3744 4368
d62a17ae 4369 /* Received Logging. */
4370 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4371 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4372 num_labels, addpath_id ? 1 : 0,
66ff6089 4373 addpath_id, evpn, pfx_buf,
a4d82a8a 4374 sizeof(pfx_buf));
f70c91dc 4375 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4376 }
718e3744 4377
d62a17ae 4378 /* graceful restart STALE flag unset. */
f009ff26 4379 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4380 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4381 bgp_dest_set_defer_flag(dest, false);
f009ff26 4382 }
d62a17ae 4383
4384 /* The attribute is changed. */
9bcb3eef 4385 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4386
d62a17ae 4387 /* Update bgp route dampening information. */
b4f7f45b 4388 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4389 && peer->sort == BGP_PEER_EBGP) {
4390 /* This is implicit withdraw so we should update
b4f7f45b
IR
4391 dampening
4392 information. */
40381db7 4393 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4394 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4395 }
49e5a4a0 4396#ifdef ENABLE_BGP_VNC
d62a17ae 4397 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4398 struct bgp_dest *pdest = NULL;
d62a17ae 4399 struct bgp_table *table = NULL;
4400
9bcb3eef
DS
4401 pdest = bgp_node_get(bgp->rib[afi][safi],
4402 (struct prefix *)prd);
4403 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4404 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4405
4406 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4407 bgp, prd, table, p, pi);
d62a17ae 4408 }
9bcb3eef 4409 bgp_dest_unlock_node(pdest);
d62a17ae 4410 }
4411 if ((afi == AFI_IP || afi == AFI_IP6)
4412 && (safi == SAFI_UNICAST)) {
40381db7 4413 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4414 /*
4415 * Implicit withdraw case.
4416 */
4417 ++vnc_implicit_withdraw;
40381db7
DS
4418 vnc_import_bgp_del_route(bgp, p, pi);
4419 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4420 }
4421 }
65efcfce 4422#endif
128ea8ab 4423
d62a17ae 4424 /* Special handling for EVPN update of an existing route. If the
4425 * extended community attribute has changed, we need to
4426 * un-import
4427 * the route using its existing extended community. It will be
4428 * subsequently processed for import with the new extended
4429 * community.
4430 */
6f8c9c11
PR
4431 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4432 && !same_attr) {
40381db7 4433 if ((pi->attr->flag
d62a17ae 4434 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4435 && (attr_new->flag
4436 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4437 int cmp;
4438
b53e67a3
DA
4439 cmp = ecommunity_cmp(
4440 bgp_attr_get_ecommunity(pi->attr),
4441 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4442 if (!cmp) {
4443 if (bgp_debug_update(peer, p, NULL, 1))
4444 zlog_debug(
4445 "Change in EXT-COMM, existing %s new %s",
4446 ecommunity_str(
b53e67a3
DA
4447 bgp_attr_get_ecommunity(
4448 pi->attr)),
d62a17ae 4449 ecommunity_str(
b53e67a3
DA
4450 bgp_attr_get_ecommunity(
4451 attr_new)));
6f8c9c11
PR
4452 if (safi == SAFI_EVPN)
4453 bgp_evpn_unimport_route(
4454 bgp, afi, safi, p, pi);
4455 else /* SAFI_MPLS_VPN */
1aa2c93e 4456 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4457 }
4458 }
4459 }
718e3744 4460
d62a17ae 4461 /* Update to new attribute. */
40381db7
DS
4462 bgp_attr_unintern(&pi->attr);
4463 pi->attr = attr_new;
d62a17ae 4464
4465 /* Update MPLS label */
4466 if (has_valid_label) {
40381db7 4467 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4468 if (extra->label != label) {
4469 memcpy(&extra->label, label,
dbd587da 4470 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4471 extra->num_labels = num_labels;
4472 }
b57ba6d2
MK
4473 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4474 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4475 }
718e3744 4476
e496b420
HS
4477 /* Update SRv6 SID */
4478 if (attr->srv6_l3vpn) {
4479 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4480 if (sid_diff(&extra->sid[0].sid,
4481 &attr->srv6_l3vpn->sid)) {
4482 sid_copy(&extra->sid[0].sid,
e496b420
HS
4483 &attr->srv6_l3vpn->sid);
4484 extra->num_sids = 1;
cc8f05df 4485
16f3db2d
RS
4486 extra->sid[0].loc_block_len = 0;
4487 extra->sid[0].loc_node_len = 0;
4488 extra->sid[0].func_len = 0;
4489 extra->sid[0].arg_len = 0;
ea7cd161
RS
4490 extra->sid[0].transposition_len = 0;
4491 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4492
4493 if (attr->srv6_l3vpn->loc_block_len != 0) {
4494 extra->sid[0].loc_block_len =
4495 attr->srv6_l3vpn->loc_block_len;
4496 extra->sid[0].loc_node_len =
4497 attr->srv6_l3vpn->loc_node_len;
4498 extra->sid[0].func_len =
4499 attr->srv6_l3vpn->func_len;
4500 extra->sid[0].arg_len =
4501 attr->srv6_l3vpn->arg_len;
ea7cd161 4502 extra->sid[0].transposition_len =
cc8f05df 4503 attr->srv6_l3vpn
ea7cd161
RS
4504 ->transposition_len;
4505 extra->sid[0].transposition_offset =
cc8f05df 4506 attr->srv6_l3vpn
ea7cd161
RS
4507 ->transposition_offset;
4508 }
e496b420
HS
4509 }
4510 } else if (attr->srv6_vpn) {
4511 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4512 if (sid_diff(&extra->sid[0].sid,
4513 &attr->srv6_vpn->sid)) {
4514 sid_copy(&extra->sid[0].sid,
4515 &attr->srv6_vpn->sid);
e496b420
HS
4516 extra->num_sids = 1;
4517 }
4518 }
4519
49e5a4a0 4520#ifdef ENABLE_BGP_VNC
d62a17ae 4521 if ((afi == AFI_IP || afi == AFI_IP6)
4522 && (safi == SAFI_UNICAST)) {
4523 if (vnc_implicit_withdraw) {
4524 /*
4525 * Add back the route with its new attributes
4526 * (e.g., nexthop).
4527 * The route is still selected, until the route
4528 * selection
4529 * queued by bgp_process actually runs. We have
4530 * to make this
4531 * update to the VNC side immediately to avoid
4532 * racing against
4533 * configuration changes (e.g., route-map
4534 * changes) which
4535 * trigger re-importation of the entire RIB.
4536 */
40381db7
DS
4537 vnc_import_bgp_add_route(bgp, p, pi);
4538 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4539 }
4540 }
65efcfce
LB
4541#endif
4542
d62a17ae 4543 /* Update bgp route dampening information. */
b4f7f45b 4544 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4545 && peer->sort == BGP_PEER_EBGP) {
4546 /* Now we do normal update dampening. */
9bcb3eef 4547 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4548 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4549 bgp_dest_unlock_node(dest);
367b458c 4550 return;
d62a17ae 4551 }
4552 }
128ea8ab 4553
d62a17ae 4554 /* Nexthop reachability check - for unicast and
4555 * labeled-unicast.. */
7c312383
AD
4556 if (((afi == AFI_IP || afi == AFI_IP6)
4557 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4558 || (safi == SAFI_EVPN &&
4559 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4560 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4561 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4562 && !CHECK_FLAG(peer->flags,
4563 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4564 && !CHECK_FLAG(bgp->flags,
4565 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4566 connected = 1;
4567 else
4568 connected = 0;
4569
960035b2
PZ
4570 struct bgp *bgp_nexthop = bgp;
4571
40381db7
DS
4572 if (pi->extra && pi->extra->bgp_orig)
4573 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4574
7c312383
AD
4575 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4576
4577 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4578 safi, pi, NULL, connected,
f8745525
PG
4579 bgp_nht_param_prefix) ||
4580 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4581 bgp_path_info_set_flag(dest, pi,
4582 BGP_PATH_VALID);
d62a17ae 4583 else {
4584 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4585 zlog_debug("%s(%pI4): NH unresolved",
4586 __func__,
4587 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4588 }
9bcb3eef 4589 bgp_path_info_unset_flag(dest, pi,
18ee8310 4590 BGP_PATH_VALID);
d62a17ae 4591 }
46dbf9d0
DA
4592 } else {
4593 if (accept_own)
4594 bgp_path_info_set_flag(dest, pi,
4595 BGP_PATH_ACCEPT_OWN);
4596
9bcb3eef 4597 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4598 }
d62a17ae 4599
49e5a4a0 4600#ifdef ENABLE_BGP_VNC
d62a17ae 4601 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4602 struct bgp_dest *pdest = NULL;
d62a17ae 4603 struct bgp_table *table = NULL;
4604
9bcb3eef
DS
4605 pdest = bgp_node_get(bgp->rib[afi][safi],
4606 (struct prefix *)prd);
4607 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4608 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4609
4610 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4611 bgp, prd, table, p, pi);
d62a17ae 4612 }
9bcb3eef 4613 bgp_dest_unlock_node(pdest);
d62a17ae 4614 }
4615#endif
718e3744 4616
d62a17ae 4617 /* If this is an EVPN route and some attribute has changed,
9146341f 4618 * or we are explicitly told to perform a route import, process
d62a17ae 4619 * route for import. If the extended community has changed, we
4620 * would
4621 * have done the un-import earlier and the import would result
4622 * in the
4623 * route getting injected into appropriate L2 VNIs. If it is
4624 * just
4625 * some other attribute change, the import will result in
4626 * updating
4627 * the attributes for the route in the VNI(s).
4628 */
9146341f 4629 if (safi == SAFI_EVPN &&
4630 (!same_attr || force_evpn_import) &&
7c312383 4631 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4632 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4633
4634 /* Process change. */
40381db7 4635 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4636
9bcb3eef
DS
4637 bgp_process(bgp, dest, afi, safi);
4638 bgp_dest_unlock_node(dest);
558d1fec 4639
ddb5b488
PZ
4640 if (SAFI_UNICAST == safi
4641 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4642 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4643
40381db7 4644 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4645 }
4646 if ((SAFI_MPLS_VPN == safi)
4647 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4648 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4649 }
4650
49e5a4a0 4651#ifdef ENABLE_BGP_VNC
d62a17ae 4652 if (SAFI_MPLS_VPN == safi) {
4653 mpls_label_t label_decoded = decode_label(label);
28070ee3 4654
d62a17ae 4655 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4656 type, sub_type, &label_decoded);
4657 }
4658 if (SAFI_ENCAP == safi) {
4659 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4660 type, sub_type, NULL);
4661 }
28070ee3 4662#endif
a486300b
PG
4663 if ((safi == SAFI_MPLS_VPN) &&
4664 !CHECK_FLAG(bgp->af_flags[afi][safi],
4665 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4666 !leak_success) {
4667 bgp_unlink_nexthop(pi);
4668 bgp_path_info_delete(dest, pi);
4669 }
367b458c 4670 return;
d62a17ae 4671 } // End of implicit withdraw
718e3744 4672
d62a17ae 4673 /* Received Logging. */
4674 if (bgp_debug_update(peer, p, NULL, 1)) {
4675 if (!peer->rcvd_attr_printed) {
f70c91dc 4676 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4677 peer->rcvd_attr_str);
4678 peer->rcvd_attr_printed = 1;
4679 }
718e3744 4680
a4d82a8a 4681 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4682 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4683 pfx_buf, sizeof(pfx_buf));
f70c91dc 4684 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4685 }
718e3744 4686
d62a17ae 4687 /* Make new BGP info. */
9bcb3eef 4688 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4689
d62a17ae 4690 /* Update MPLS label */
4691 if (has_valid_label) {
18ee8310 4692 extra = bgp_path_info_extra_get(new);
8ba71050 4693 if (extra->label != label) {
dbd587da
QY
4694 memcpy(&extra->label, label,
4695 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4696 extra->num_labels = num_labels;
4697 }
b57ba6d2
MK
4698 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4699 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4700 }
718e3744 4701
e496b420
HS
4702 /* Update SRv6 SID */
4703 if (safi == SAFI_MPLS_VPN) {
4704 extra = bgp_path_info_extra_get(new);
4705 if (attr->srv6_l3vpn) {
16f3db2d 4706 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4707 extra->num_sids = 1;
cc8f05df 4708
16f3db2d
RS
4709 extra->sid[0].loc_block_len =
4710 attr->srv6_l3vpn->loc_block_len;
4711 extra->sid[0].loc_node_len =
4712 attr->srv6_l3vpn->loc_node_len;
4713 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4714 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4715 extra->sid[0].transposition_len =
4716 attr->srv6_l3vpn->transposition_len;
4717 extra->sid[0].transposition_offset =
4718 attr->srv6_l3vpn->transposition_offset;
e496b420 4719 } else if (attr->srv6_vpn) {
16f3db2d 4720 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4721 extra->num_sids = 1;
4722 }
4723 }
4724
d62a17ae 4725 /* Nexthop reachability check. */
7c312383
AD
4726 if (((afi == AFI_IP || afi == AFI_IP6)
4727 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4728 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4729 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4730 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4731 && !CHECK_FLAG(peer->flags,
4732 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4733 && !CHECK_FLAG(bgp->flags,
4734 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4735 connected = 1;
4736 else
4737 connected = 0;
4738
7c312383
AD
4739 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4740
4053e952 4741 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4742 connected, bgp_nht_param_prefix) ||
4743 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4744 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4745 else {
07380148
DA
4746 if (BGP_DEBUG(nht, NHT))
4747 zlog_debug("%s(%pI4): NH unresolved", __func__,
4748 &attr_new->nexthop);
9bcb3eef 4749 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4750 }
46dbf9d0
DA
4751 } else {
4752 if (accept_own)
4753 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4754
9bcb3eef 4755 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4756 }
a82478b9 4757
b381ed97
DA
4758 /* If maximum prefix count is configured and current prefix
4759 * count exeed it.
4760 */
4761 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4762 reason = "maximum-prefix overflow";
4763 bgp_attr_flush(&new_attr);
b381ed97
DA
4764 goto filtered;
4765 }
4766
d62a17ae 4767 /* Addpath ID */
4768 new->addpath_rx_id = addpath_id;
4769
4770 /* Increment prefix */
4771 bgp_aggregate_increment(bgp, p, new, afi, safi);
4772
4773 /* Register new BGP information. */
9bcb3eef 4774 bgp_path_info_add(dest, new);
d62a17ae 4775
4776 /* route_node_get lock */
9bcb3eef 4777 bgp_dest_unlock_node(dest);
558d1fec 4778
49e5a4a0 4779#ifdef ENABLE_BGP_VNC
d62a17ae 4780 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4781 struct bgp_dest *pdest = NULL;
d62a17ae 4782 struct bgp_table *table = NULL;
4783
9bcb3eef
DS
4784 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4785 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4786 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4787
4788 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4789 bgp, prd, table, p, new);
4790 }
9bcb3eef 4791 bgp_dest_unlock_node(pdest);
d62a17ae 4792 }
65efcfce
LB
4793#endif
4794
d62a17ae 4795 /* If this is an EVPN route, process for import. */
7c312383 4796 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4797 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4798
9bcb3eef 4799 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4800
d62a17ae 4801 /* Process change. */
9bcb3eef 4802 bgp_process(bgp, dest, afi, safi);
718e3744 4803
ddb5b488
PZ
4804 if (SAFI_UNICAST == safi
4805 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4806 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4807 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4808 }
4809 if ((SAFI_MPLS_VPN == safi)
4810 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4811 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4812 }
49e5a4a0 4813#ifdef ENABLE_BGP_VNC
d62a17ae 4814 if (SAFI_MPLS_VPN == safi) {
4815 mpls_label_t label_decoded = decode_label(label);
28070ee3 4816
d62a17ae 4817 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4818 sub_type, &label_decoded);
4819 }
4820 if (SAFI_ENCAP == safi) {
4821 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4822 sub_type, NULL);
4823 }
28070ee3 4824#endif
a486300b
PG
4825 if ((safi == SAFI_MPLS_VPN) &&
4826 !CHECK_FLAG(bgp->af_flags[afi][safi],
4827 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4828 !leak_success) {
4829 bgp_unlink_nexthop(new);
4830 bgp_path_info_delete(dest, new);
4831 }
28070ee3 4832
367b458c 4833 return;
718e3744 4834
d62a17ae 4835/* This BGP update is filtered. Log the reason then update BGP
4836 entry. */
4837filtered:
819e6767
DA
4838 if (new) {
4839 bgp_unlink_nexthop(new);
4840 bgp_path_info_delete(dest, new);
4841 bgp_path_info_extra_free(&new->extra);
4842 XFREE(MTYPE_BGP_ROUTE, new);
4843 }
4844
9bcb3eef 4845 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4846
d62a17ae 4847 if (bgp_debug_update(peer, p, NULL, 1)) {
4848 if (!peer->rcvd_attr_printed) {
f70c91dc 4849 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4850 peer->rcvd_attr_str);
4851 peer->rcvd_attr_printed = 1;
4852 }
718e3744 4853
a4d82a8a 4854 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4855 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4856 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4857 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4858 peer, pfx_buf, reason);
d62a17ae 4859 }
128ea8ab 4860
40381db7 4861 if (pi) {
d62a17ae 4862 /* If this is an EVPN route, un-import it as it is now filtered.
4863 */
4864 if (safi == SAFI_EVPN)
40381db7 4865 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4866
ddb5b488
PZ
4867 if (SAFI_UNICAST == safi
4868 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4869 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4870
40381db7 4871 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4872 }
4873 if ((SAFI_MPLS_VPN == safi)
4874 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4875
1aa2c93e 4876 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4877 }
4878
9bcb3eef 4879 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4880 }
4881
9bcb3eef 4882 bgp_dest_unlock_node(dest);
558d1fec 4883
49e5a4a0 4884#ifdef ENABLE_BGP_VNC
d62a17ae 4885 /*
4886 * Filtered update is treated as an implicit withdrawal (see
4887 * bgp_rib_remove()
4888 * a few lines above)
4889 */
4890 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4891 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4892 0);
4893 }
97736e32
PZ
4894#endif
4895
367b458c 4896 return;
718e3744 4897}
4898
367b458c 4899void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4900 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4901 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4902 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4903{
d62a17ae 4904 struct bgp *bgp;
4905 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4906 struct bgp_dest *dest;
40381db7 4907 struct bgp_path_info *pi;
718e3744 4908
49e5a4a0 4909#ifdef ENABLE_BGP_VNC
d62a17ae 4910 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4911 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4912 0);
4913 }
28070ee3
PZ
4914#endif
4915
d62a17ae 4916 bgp = peer->bgp;
4917
4918 /* Lookup node. */
9bcb3eef 4919 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4920
4921 /* If peer is soft reconfiguration enabled. Record input packet for
4922 * further calculation.
4923 *
4924 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4925 * routes that are filtered. This tanks out Quagga RS pretty badly due
4926 * to
4927 * the iteration over all RS clients.
4928 * Since we need to remove the entry from adj_in anyway, do that first
4929 * and
4930 * if there was no entry, we don't need to do anything more.
4931 */
4932 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4933 && peer != bgp->peer_self)
9bcb3eef 4934 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4935 peer->stat_pfx_dup_withdraw++;
4936
d62a17ae 4937 if (bgp_debug_update(peer, p, NULL, 1)) {
4938 bgp_debug_rdpfxpath2str(
a4d82a8a 4939 afi, safi, prd, p, label, num_labels,
6c995628
AD
4940 addpath_id ? 1 : 0, addpath_id, NULL,
4941 pfx_buf, sizeof(pfx_buf));
d62a17ae 4942 zlog_debug(
4943 "%s withdrawing route %s not in adj-in",
4944 peer->host, pfx_buf);
4945 }
9bcb3eef 4946 bgp_dest_unlock_node(dest);
367b458c 4947 return;
d62a17ae 4948 }
cd808e74 4949
d62a17ae 4950 /* Lookup withdrawn route. */
9bcb3eef 4951 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4952 if (pi->peer == peer && pi->type == type
4953 && pi->sub_type == sub_type
4954 && pi->addpath_rx_id == addpath_id)
d62a17ae 4955 break;
4956
4957 /* Logging. */
4958 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4959 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4960 addpath_id ? 1 : 0, addpath_id, NULL,
4961 pfx_buf, sizeof(pfx_buf));
f70c91dc 4962 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4963 pfx_buf);
4964 }
718e3744 4965
d62a17ae 4966 /* Withdraw specified route from routing table. */
40381db7 4967 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4968 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4969 if (SAFI_UNICAST == safi
4970 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4971 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4972 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4973 }
4974 if ((SAFI_MPLS_VPN == safi)
4975 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4976
1aa2c93e 4977 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4978 }
4979 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4980 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4981 addpath_id ? 1 : 0, addpath_id, NULL,
4982 pfx_buf, sizeof(pfx_buf));
d62a17ae 4983 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4984 }
718e3744 4985
d62a17ae 4986 /* Unlock bgp_node_get() lock. */
9bcb3eef 4987 bgp_dest_unlock_node(dest);
d62a17ae 4988
367b458c 4989 return;
718e3744 4990}
6b0655a2 4991
d62a17ae 4992void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4993 int withdraw)
718e3744 4994{
d62a17ae 4995 struct update_subgroup *subgrp;
4996 subgrp = peer_subgroup(peer, afi, safi);
4997 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4998}
6182d65b 4999
718e3744 5000
3f9c7369
DS
5001/*
5002 * bgp_stop_announce_route_timer
5003 */
d62a17ae 5004void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5005{
d62a17ae 5006 if (!paf->t_announce_route)
5007 return;
5008
c3aaa89a 5009 THREAD_OFF(paf->t_announce_route);
718e3744 5010}
6b0655a2 5011
3f9c7369
DS
5012/*
5013 * bgp_announce_route_timer_expired
5014 *
5015 * Callback that is invoked when the route announcement timer for a
5016 * peer_af expires.
5017 */
cc9f21da 5018static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5019{
d62a17ae 5020 struct peer_af *paf;
5021 struct peer *peer;
558d1fec 5022
d62a17ae 5023 paf = THREAD_ARG(t);
5024 peer = paf->peer;
718e3744 5025
feb17238 5026 if (!peer_established(peer))
cc9f21da 5027 return;
3f9c7369 5028
d62a17ae 5029 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5030 return;
3f9c7369 5031
d62a17ae 5032 peer_af_announce_route(paf, 1);
c5aec50b
MK
5033
5034 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5035 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5036}
5037
3f9c7369
DS
5038/*
5039 * bgp_announce_route
5040 *
5041 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5042 *
5043 * if force is true we will force an update even if the update
5044 * limiting code is attempted to kick in.
3f9c7369 5045 */
e1a32ec1 5046void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5047{
5048 struct peer_af *paf;
5049 struct update_subgroup *subgrp;
5050
5051 paf = peer_af_find(peer, afi, safi);
5052 if (!paf)
5053 return;
5054 subgrp = PAF_SUBGRP(paf);
5055
5056 /*
5057 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5058 * or a refresh has already been triggered.
5059 */
5060 if (!subgrp || paf->t_announce_route)
5061 return;
5062
e1a32ec1
DS
5063 if (force)
5064 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5065
d62a17ae 5066 /*
5067 * Start a timer to stagger/delay the announce. This serves
5068 * two purposes - announcement can potentially be combined for
5069 * multiple peers and the announcement doesn't happen in the
5070 * vty context.
5071 */
5072 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5073 (subgrp->peer_count == 1)
5074 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5075 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5076 &paf->t_announce_route);
3f9c7369
DS
5077}
5078
5079/*
5080 * Announce routes from all AF tables to a peer.
5081 *
5082 * This should ONLY be called when there is a need to refresh the
5083 * routes to the peer based on a policy change for this peer alone
5084 * or a route refresh request received from the peer.
5085 * The operation will result in splitting the peer from its existing
5086 * subgroups and putting it in new subgroups.
5087 */
d62a17ae 5088void bgp_announce_route_all(struct peer *peer)
718e3744 5089{
d62a17ae 5090 afi_t afi;
5091 safi_t safi;
5092
05c7a1cc 5093 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5094 bgp_announce_route(peer, afi, safi, false);
718e3744 5095}
6b0655a2 5096
46aeabed
LS
5097/* Flag or unflag bgp_dest to determine whether it should be treated by
5098 * bgp_soft_reconfig_table_task.
5099 * Flag if flag is true. Unflag if flag is false.
5100 */
5101static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5102{
5103 struct bgp_dest *dest;
5104 struct bgp_adj_in *ain;
5105
5106 if (!table)
5107 return;
5108
5109 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5110 for (ain = dest->adj_in; ain; ain = ain->next) {
5111 if (ain->peer != NULL)
5112 break;
5113 }
5114 if (flag && ain != NULL && ain->peer != NULL)
5115 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5116 else
5117 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5118 }
5119}
5120
367b458c
DS
5121static void bgp_soft_reconfig_table_update(struct peer *peer,
5122 struct bgp_dest *dest,
5123 struct bgp_adj_in *ain, afi_t afi,
5124 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5125{
5126 struct bgp_path_info *pi;
5127 uint32_t num_labels = 0;
5128 mpls_label_t *label_pnt = NULL;
5129 struct bgp_route_evpn evpn;
5130
5131 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5132 if (pi->peer == peer)
5133 break;
5134
5135 if (pi && pi->extra)
5136 num_labels = pi->extra->num_labels;
5137 if (num_labels)
5138 label_pnt = &pi->extra->label[0];
5139 if (pi)
5140 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5141 sizeof(evpn));
5142 else
5143 memset(&evpn, 0, sizeof(evpn));
5144
367b458c
DS
5145 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5146 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5147 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5148}
5149
d62a17ae 5150static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5151 struct bgp_table *table,
5152 struct prefix_rd *prd)
718e3744 5153{
9bcb3eef 5154 struct bgp_dest *dest;
d62a17ae 5155 struct bgp_adj_in *ain;
718e3744 5156
d62a17ae 5157 if (!table)
5158 table = peer->bgp->rib[afi][safi];
718e3744 5159
9bcb3eef
DS
5160 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5161 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5162 if (ain->peer != peer)
5163 continue;
8692c506 5164
367b458c
DS
5165 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5166 safi, prd);
d62a17ae 5167 }
718e3744 5168}
5169
46aeabed
LS
5170/* Do soft reconfig table per bgp table.
5171 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5172 * when BGP_NODE_SOFT_RECONFIG is set,
5173 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5174 * Schedule a new thread to continue the job.
5175 * Without splitting the full job into several part,
5176 * vtysh waits for the job to finish before responding to a BGP command
5177 */
cc9f21da 5178static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5179{
5180 uint32_t iter, max_iter;
46aeabed
LS
5181 struct bgp_dest *dest;
5182 struct bgp_adj_in *ain;
5183 struct peer *peer;
5184 struct bgp_table *table;
5185 struct prefix_rd *prd;
5186 struct listnode *node, *nnode;
5187
5188 table = THREAD_ARG(thread);
5189 prd = NULL;
5190
5191 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5192 if (table->soft_reconfig_init) {
5193 /* first call of the function with a new srta structure.
5194 * Don't do any treatment this time on nodes
5195 * in order vtysh to respond quickly
5196 */
5197 max_iter = 0;
5198 }
5199
5200 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5201 dest = bgp_route_next(dest)) {
5202 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5203 continue;
5204
5205 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5206
5207 for (ain = dest->adj_in; ain; ain = ain->next) {
5208 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5209 nnode, peer)) {
5210 if (ain->peer != peer)
5211 continue;
5212
367b458c 5213 bgp_soft_reconfig_table_update(
46aeabed
LS
5214 peer, dest, ain, table->afi,
5215 table->safi, prd);
5216 iter++;
46aeabed
LS
5217 }
5218 }
5219 }
5220
5221 /* we're either starting the initial iteration,
5222 * or we're going to continue an ongoing iteration
5223 */
5224 if (dest || table->soft_reconfig_init) {
5225 table->soft_reconfig_init = false;
5226 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5227 table, 0, &table->soft_reconfig_thread);
cc9f21da 5228 return;
46aeabed
LS
5229 }
5230 /* we're done, clean up the background iteration context info and
5231 schedule route annoucement
5232 */
5233 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5234 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5235 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5236 }
5237
5238 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5239}
5240
5241
5242/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5243 * and peer.
5244 * - bgp cannot be NULL
5245 * - if table and peer are NULL, cancel all threads within the bgp instance
5246 * - if table is NULL and peer is not,
5247 * remove peer in all threads within the bgp instance
5248 * - if peer is NULL, cancel all threads matching table within the bgp instance
5249 */
5250void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5251 const struct bgp_table *table,
5252 const struct peer *peer)
5253{
5254 struct peer *npeer;
5255 struct listnode *node, *nnode;
5256 int afi, safi;
5257 struct bgp_table *ntable;
5258
5259 if (!bgp)
5260 return;
5261
5262 FOREACH_AFI_SAFI (afi, safi) {
5263 ntable = bgp->rib[afi][safi];
5264 if (!ntable)
5265 continue;
5266 if (table && table != ntable)
5267 continue;
5268
5269 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5270 npeer)) {
5271 if (peer && peer != npeer)
5272 continue;
5273 listnode_delete(ntable->soft_reconfig_peers, npeer);
5274 }
5275
5276 if (!ntable->soft_reconfig_peers
5277 || !list_isempty(ntable->soft_reconfig_peers))
5278 continue;
5279
5280 list_delete(&ntable->soft_reconfig_peers);
5281 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5282 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5283 }
5284}
5285
89c73443
DS
5286/*
5287 * Returns false if the peer is not configured for soft reconfig in
5288 */
5289bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5290{
9bcb3eef 5291 struct bgp_dest *dest;
d62a17ae 5292 struct bgp_table *table;
46aeabed
LS
5293 struct listnode *node, *nnode;
5294 struct peer *npeer;
5295 struct peer_af *paf;
718e3744 5296
89c73443
DS
5297 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5298 return false;
718e3744 5299
d62a17ae 5300 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5301 && (safi != SAFI_EVPN)) {
5302 table = peer->bgp->rib[afi][safi];
5303 if (!table)
89c73443 5304 return true;
46aeabed
LS
5305
5306 table->soft_reconfig_init = true;
5307
5308 if (!table->soft_reconfig_peers)
5309 table->soft_reconfig_peers = list_new();
5310 npeer = NULL;
5311 /* add peer to the table soft_reconfig_peers if not already
5312 * there
5313 */
5314 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5315 npeer)) {
5316 if (peer == npeer)
5317 break;
5318 }
5319 if (peer != npeer)
5320 listnode_add(table->soft_reconfig_peers, peer);
5321
5322 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5323 * on table would start back at the beginning.
5324 */
5325 bgp_soft_reconfig_table_flag(table, true);
5326
5327 if (!table->soft_reconfig_thread)
5328 thread_add_event(bm->master,
5329 bgp_soft_reconfig_table_task, table, 0,
5330 &table->soft_reconfig_thread);
5331 /* Cancel bgp_announce_route_timer_expired threads.
5332 * bgp_announce_route_timer_expired threads have been scheduled
5333 * to announce routes as soon as the soft_reconfigure process
5334 * finishes.
5335 * In this case, soft_reconfigure is also scheduled by using
5336 * a thread but is planned after the
5337 * bgp_announce_route_timer_expired threads. It means that,
5338 * without cancelling the threads, the route announcement task
5339 * would run before the soft reconfiguration one. That would
5340 * useless and would block vtysh during several seconds. Route
5341 * announcements are rescheduled as soon as the soft_reconfigure
5342 * process finishes.
5343 */
5344 paf = peer_af_find(peer, afi, safi);
5345 if (paf)
5346 bgp_stop_announce_route_timer(paf);
5347 } else
9bcb3eef
DS
5348 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5349 dest = bgp_route_next(dest)) {
5350 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5351
b54892e0
DS
5352 if (table == NULL)
5353 continue;
8692c506 5354
9bcb3eef 5355 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5356 struct prefix_rd prd;
5357
5358 prd.family = AF_UNSPEC;
5359 prd.prefixlen = 64;
5360 memcpy(&prd.val, p->u.val, 8);
5361
5362 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5363 }
89c73443
DS
5364
5365 return true;
718e3744 5366}
6b0655a2 5367
228da428 5368
d62a17ae 5369struct bgp_clear_node_queue {
9bcb3eef 5370 struct bgp_dest *dest;
228da428
CC
5371};
5372
d62a17ae 5373static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5374{
d62a17ae 5375 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5376 struct bgp_dest *dest = cnq->dest;
d62a17ae 5377 struct peer *peer = wq->spec.data;
40381db7 5378 struct bgp_path_info *pi;
3103e8d2 5379 struct bgp *bgp;
9bcb3eef
DS
5380 afi_t afi = bgp_dest_table(dest)->afi;
5381 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5382
9bcb3eef 5383 assert(dest && peer);
3103e8d2 5384 bgp = peer->bgp;
d62a17ae 5385
5386 /* It is possible that we have multiple paths for a prefix from a peer
5387 * if that peer is using AddPath.
5388 */
9bcb3eef 5389 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5390 if (pi->peer != peer)
ea47320b
DL
5391 continue;
5392
5393 /* graceful restart STALE flag set. */
9af52ccf
DA
5394 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5395 && peer->nsf[afi][safi])
5396 || CHECK_FLAG(peer->af_sflags[afi][safi],
5397 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5398 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5399 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5400 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5401 else {
5402 /* If this is an EVPN route, process for
5403 * un-import. */
5404 if (safi == SAFI_EVPN)
9bcb3eef
DS
5405 bgp_evpn_unimport_route(
5406 bgp, afi, safi,
5407 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5408 /* Handle withdraw for VRF route-leaking and L3VPN */
5409 if (SAFI_UNICAST == safi
5410 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5411 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5412 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5413 bgp, pi);
960035b2 5414 }
3103e8d2 5415 if (SAFI_MPLS_VPN == safi &&
960035b2 5416 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5417 vpn_leak_to_vrf_withdraw(pi);
960035b2 5418 }
3103e8d2 5419
9bcb3eef 5420 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5421 }
ea47320b 5422 }
d62a17ae 5423 return WQ_SUCCESS;
200df115 5424}
5425
d62a17ae 5426static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5427{
d62a17ae 5428 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5429 struct bgp_dest *dest = cnq->dest;
5430 struct bgp_table *table = bgp_dest_table(dest);
228da428 5431
9bcb3eef 5432 bgp_dest_unlock_node(dest);
d62a17ae 5433 bgp_table_unlock(table);
5434 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5435}
5436
d62a17ae 5437static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5438{
d62a17ae 5439 struct peer *peer = wq->spec.data;
64e580a7 5440
d62a17ae 5441 /* Tickle FSM to start moving again */
5442 BGP_EVENT_ADD(peer, Clearing_Completed);
5443
5444 peer_unlock(peer); /* bgp_clear_route */
200df115 5445}
718e3744 5446
d62a17ae 5447static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5448{
d62a17ae 5449 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5450
5451 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5452#undef CLEAR_QUEUE_NAME_LEN
5453
0ce1ca80 5454 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5455 peer->clear_node_queue->spec.hold = 10;
5456 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5457 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5458 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5459 peer->clear_node_queue->spec.max_retries = 0;
5460
5461 /* we only 'lock' this peer reference when the queue is actually active
5462 */
5463 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5464}
5465
d62a17ae 5466static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5467 struct bgp_table *table)
65ca75e0 5468{
9bcb3eef 5469 struct bgp_dest *dest;
b6c386bb 5470 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5471
d62a17ae 5472 if (!table)
5473 table = peer->bgp->rib[afi][safi];
dc83d712 5474
d62a17ae 5475 /* If still no table => afi/safi isn't configured at all or smth. */
5476 if (!table)
5477 return;
dc83d712 5478
9bcb3eef 5479 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5480 struct bgp_path_info *pi, *next;
d62a17ae 5481 struct bgp_adj_in *ain;
5482 struct bgp_adj_in *ain_next;
5483
5484 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5485 * queued for every clearing peer, regardless of whether it is
5486 * relevant to the peer at hand.
5487 *
5488 * Overview: There are 3 different indices which need to be
5489 * scrubbed, potentially, when a peer is removed:
5490 *
5491 * 1 peer's routes visible via the RIB (ie accepted routes)
5492 * 2 peer's routes visible by the (optional) peer's adj-in index
5493 * 3 other routes visible by the peer's adj-out index
5494 *
5495 * 3 there is no hurry in scrubbing, once the struct peer is
5496 * removed from bgp->peer, we could just GC such deleted peer's
5497 * adj-outs at our leisure.
5498 *
5499 * 1 and 2 must be 'scrubbed' in some way, at least made
5500 * invisible via RIB index before peer session is allowed to be
5501 * brought back up. So one needs to know when such a 'search' is
5502 * complete.
5503 *
5504 * Ideally:
5505 *
5506 * - there'd be a single global queue or a single RIB walker
5507 * - rather than tracking which route_nodes still need to be
5508 * examined on a peer basis, we'd track which peers still
5509 * aren't cleared
5510 *
5511 * Given that our per-peer prefix-counts now should be reliable,
5512 * this may actually be achievable. It doesn't seem to be a huge
5513 * problem at this time,
5514 *
5515 * It is possible that we have multiple paths for a prefix from
5516 * a peer
5517 * if that peer is using AddPath.
5518 */
9bcb3eef 5519 ain = dest->adj_in;
d62a17ae 5520 while (ain) {
5521 ain_next = ain->next;
5522
6a840fd9 5523 if (ain->peer == peer)
9bcb3eef 5524 bgp_adj_in_remove(dest, ain);
d62a17ae 5525
5526 ain = ain_next;
5527 }
5528
9bcb3eef 5529 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5530 next = pi->next;
5531 if (pi->peer != peer)
d62a17ae 5532 continue;
5533
5534 if (force)
9bcb3eef 5535 bgp_path_info_reap(dest, pi);
d62a17ae 5536 else {
5537 struct bgp_clear_node_queue *cnq;
5538
5539 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5540 bgp_table_lock(bgp_dest_table(dest));
5541 bgp_dest_lock_node(dest);
d62a17ae 5542 cnq = XCALLOC(
5543 MTYPE_BGP_CLEAR_NODE_QUEUE,
5544 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5545 cnq->dest = dest;
d62a17ae 5546 work_queue_add(peer->clear_node_queue, cnq);
5547 break;
5548 }
5549 }
5550 }
5551 return;
5552}
5553
5554void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5555{
9bcb3eef 5556 struct bgp_dest *dest;
d62a17ae 5557 struct bgp_table *table;
5558
5559 if (peer->clear_node_queue == NULL)
5560 bgp_clear_node_queue_init(peer);
5561
5562 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5563 * Idle until it receives a Clearing_Completed event. This protects
5564 * against peers which flap faster than we can we clear, which could
5565 * lead to:
5566 *
5567 * a) race with routes from the new session being installed before
5568 * clear_route_node visits the node (to delete the route of that
5569 * peer)
5570 * b) resource exhaustion, clear_route_node likely leads to an entry
5571 * on the process_main queue. Fast-flapping could cause that queue
5572 * to grow and grow.
5573 */
5574
5575 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5576 * the unlock will happen upon work-queue completion; other wise, the
5577 * unlock happens at the end of this function.
5578 */
5579 if (!peer->clear_node_queue->thread)
5580 peer_lock(peer);
5581
5582 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5583 bgp_clear_route_table(peer, afi, safi, NULL);
5584 else
9bcb3eef
DS
5585 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5586 dest = bgp_route_next(dest)) {
5587 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5588 if (!table)
5589 continue;
5590
5591 bgp_clear_route_table(peer, afi, safi, table);
5592 }
d62a17ae 5593
5594 /* unlock if no nodes got added to the clear-node-queue. */
5595 if (!peer->clear_node_queue->thread)
5596 peer_unlock(peer);
718e3744 5597}
d62a17ae 5598
5599void bgp_clear_route_all(struct peer *peer)
718e3744 5600{
d62a17ae 5601 afi_t afi;
5602 safi_t safi;
718e3744 5603
05c7a1cc
QY
5604 FOREACH_AFI_SAFI (afi, safi)
5605 bgp_clear_route(peer, afi, safi);
65efcfce 5606
49e5a4a0 5607#ifdef ENABLE_BGP_VNC
d62a17ae 5608 rfapiProcessPeerDown(peer);
65efcfce 5609#endif
718e3744 5610}
5611
d62a17ae 5612void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5613{
d62a17ae 5614 struct bgp_table *table;
9bcb3eef 5615 struct bgp_dest *dest;
d62a17ae 5616 struct bgp_adj_in *ain;
5617 struct bgp_adj_in *ain_next;
718e3744 5618
d62a17ae 5619 table = peer->bgp->rib[afi][safi];
718e3744 5620
d62a17ae 5621 /* It is possible that we have multiple paths for a prefix from a peer
5622 * if that peer is using AddPath.
5623 */
9bcb3eef
DS
5624 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5625 ain = dest->adj_in;
43143c8f 5626
d62a17ae 5627 while (ain) {
5628 ain_next = ain->next;
43143c8f 5629
6a840fd9 5630 if (ain->peer == peer)
9bcb3eef 5631 bgp_adj_in_remove(dest, ain);
43143c8f 5632
d62a17ae 5633 ain = ain_next;
5634 }
5635 }
718e3744 5636}
93406d87 5637
1479ed2f
DA
5638/* If any of the routes from the peer have been marked with the NO_LLGR
5639 * community, either as sent by the peer, or as the result of a configured
5640 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5641 * operation of [RFC4271].
5642 */
d62a17ae 5643void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5644{
9bcb3eef 5645 struct bgp_dest *dest;
40381db7 5646 struct bgp_path_info *pi;
d62a17ae 5647 struct bgp_table *table;
5648
9af52ccf 5649 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5650 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5651 dest = bgp_route_next(dest)) {
5652 struct bgp_dest *rm;
d62a17ae 5653
5654 /* look for neighbor in tables */
9bcb3eef 5655 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5656 if (!table)
ea47320b
DL
5657 continue;
5658
5659 for (rm = bgp_table_top(table); rm;
5660 rm = bgp_route_next(rm))
9bcb3eef 5661 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5662 pi = pi->next) {
40381db7 5663 if (pi->peer != peer)
ea47320b 5664 continue;
1479ed2f
DA
5665 if (CHECK_FLAG(
5666 peer->af_sflags[afi][safi],
5667 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5668 bgp_attr_get_community(pi->attr) &&
1479ed2f 5669 !community_include(
9a706b42
DA
5670 bgp_attr_get_community(
5671 pi->attr),
1479ed2f 5672 COMMUNITY_NO_LLGR))
e3015d91 5673 continue;
40381db7 5674 if (!CHECK_FLAG(pi->flags,
1defdda8 5675 BGP_PATH_STALE))
e3015d91 5676 continue;
ea47320b 5677
641065d4
KM
5678 /*
5679 * If this is VRF leaked route
5680 * process for withdraw.
5681 */
5682 if (pi->sub_type ==
5683 BGP_ROUTE_IMPORTED &&
5684 peer->bgp->inst_type ==
5685 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5686 vpn_leak_to_vrf_withdraw(pi);
641065d4 5687
40381db7 5688 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5689 break;
5690 }
d62a17ae 5691 }
5692 } else {
9bcb3eef
DS
5693 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5694 dest = bgp_route_next(dest))
5695 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5696 pi = pi->next) {
40381db7 5697 if (pi->peer != peer)
ea47320b 5698 continue;
1479ed2f
DA
5699 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5700 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5701 bgp_attr_get_community(pi->attr) &&
5702 !community_include(
5703 bgp_attr_get_community(pi->attr),
5704 COMMUNITY_NO_LLGR))
e3015d91 5705 continue;
40381db7 5706 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5707 continue;
641065d4
KM
5708 if (safi == SAFI_UNICAST &&
5709 (peer->bgp->inst_type ==
5710 BGP_INSTANCE_TYPE_VRF ||
5711 peer->bgp->inst_type ==
5712 BGP_INSTANCE_TYPE_DEFAULT))
5713 vpn_leak_from_vrf_withdraw(
5714 bgp_get_default(), peer->bgp,
5715 pi);
5716
9bcb3eef 5717 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5718 break;
5719 }
d62a17ae 5720 }
93406d87 5721}
6b0655a2 5722
9af52ccf
DA
5723void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5724{
5725 struct bgp_dest *dest, *ndest;
5726 struct bgp_path_info *pi;
5727 struct bgp_table *table;
5728
5729 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5730 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5731 dest = bgp_route_next(dest)) {
5732 table = bgp_dest_get_bgp_table_info(dest);
5733 if (!table)
5734 continue;
5735
5736 for (ndest = bgp_table_top(table); ndest;
5737 ndest = bgp_route_next(ndest)) {
5738 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5739 pi = pi->next) {
5740 if (pi->peer != peer)
5741 continue;
5742
5743 if ((CHECK_FLAG(
5744 peer->af_sflags[afi][safi],
5745 PEER_STATUS_ENHANCED_REFRESH))
5746 && !CHECK_FLAG(pi->flags,
5747 BGP_PATH_STALE)
5748 && !CHECK_FLAG(
5749 pi->flags,
5750 BGP_PATH_UNUSEABLE)) {
5751 if (bgp_debug_neighbor_events(
5752 peer))
5753 zlog_debug(
58e111f6
DA
5754 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5755 peer,
9af52ccf
DA
5756 afi2str(afi),
5757 safi2str(safi),
5758 bgp_dest_get_prefix(
5759 ndest));
5760
5761 bgp_path_info_set_flag(
5762 ndest, pi,
5763 BGP_PATH_STALE);
5764 }
5765 }
5766 }
5767 }
5768 } else {
5769 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5770 dest = bgp_route_next(dest)) {
5771 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5772 pi = pi->next) {
5773 if (pi->peer != peer)
5774 continue;
5775
5776 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5777 PEER_STATUS_ENHANCED_REFRESH))
5778 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5779 && !CHECK_FLAG(pi->flags,
5780 BGP_PATH_UNUSEABLE)) {
5781 if (bgp_debug_neighbor_events(peer))
5782 zlog_debug(
58e111f6
DA
5783 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5784 peer, afi2str(afi),
9af52ccf
DA
5785 safi2str(safi),
5786 bgp_dest_get_prefix(
5787 dest));
5788
5789 bgp_path_info_set_flag(dest, pi,
5790 BGP_PATH_STALE);
5791 }
5792 }
5793 }
5794 }
5795}
5796
3dc339cd 5797bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5798{
e0df4c04 5799 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5800 return true;
e0df4c04 5801
9dac9fc8
DA
5802 if (peer->sort == BGP_PEER_EBGP
5803 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5804 || FILTER_LIST_OUT_NAME(filter)
5805 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5806 return true;
5807 return false;
9dac9fc8
DA
5808}
5809
3dc339cd 5810bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5811{
e0df4c04 5812 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5813 return true;
e0df4c04 5814
9dac9fc8
DA
5815 if (peer->sort == BGP_PEER_EBGP
5816 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5817 || FILTER_LIST_IN_NAME(filter)
5818 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5819 return true;
5820 return false;
9dac9fc8
DA
5821}
5822
568e10ca 5823static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5824 safi_t safi)
bb86c601 5825{
9bcb3eef 5826 struct bgp_dest *dest;
40381db7 5827 struct bgp_path_info *pi;
4b7e6066 5828 struct bgp_path_info *next;
bb86c601 5829
9bcb3eef
DS
5830 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5831 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5832 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5833
40381db7 5834 next = pi->next;
1b7bb747
CS
5835
5836 /* Unimport EVPN routes from VRFs */
5837 if (safi == SAFI_EVPN)
5838 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5839 SAFI_EVPN, p, pi);
1b7bb747 5840
40381db7
DS
5841 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5842 && pi->type == ZEBRA_ROUTE_BGP
5843 && (pi->sub_type == BGP_ROUTE_NORMAL
5844 || pi->sub_type == BGP_ROUTE_AGGREGATE
5845 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5846
d62a17ae 5847 if (bgp_fibupd_safi(safi))
b54892e0 5848 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5849 }
9514b37d 5850
9bcb3eef 5851 bgp_path_info_reap(dest, pi);
d62a17ae 5852 }
bb86c601
LB
5853}
5854
718e3744 5855/* Delete all kernel routes. */
d62a17ae 5856void bgp_cleanup_routes(struct bgp *bgp)
5857{
5858 afi_t afi;
9bcb3eef 5859 struct bgp_dest *dest;
67009e22 5860 struct bgp_table *table;
d62a17ae 5861
5862 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5863 if (afi == AFI_L2VPN)
5864 continue;
568e10ca 5865 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5866 SAFI_UNICAST);
d62a17ae 5867 /*
5868 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5869 */
5870 if (afi != AFI_L2VPN) {
5871 safi_t safi;
5872 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5873 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5874 dest = bgp_route_next(dest)) {
5875 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5876 if (table != NULL) {
5877 bgp_cleanup_table(bgp, table, safi);
5878 bgp_table_finish(&table);
9bcb3eef
DS
5879 bgp_dest_set_bgp_table_info(dest, NULL);
5880 bgp_dest_unlock_node(dest);
d62a17ae 5881 }
5882 }
5883 safi = SAFI_ENCAP;
9bcb3eef
DS
5884 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5885 dest = bgp_route_next(dest)) {
5886 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5887 if (table != NULL) {
5888 bgp_cleanup_table(bgp, table, safi);
5889 bgp_table_finish(&table);
9bcb3eef
DS
5890 bgp_dest_set_bgp_table_info(dest, NULL);
5891 bgp_dest_unlock_node(dest);
d62a17ae 5892 }
5893 }
5894 }
5895 }
9bcb3eef
DS
5896 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5897 dest = bgp_route_next(dest)) {
5898 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5899 if (table != NULL) {
5900 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5901 bgp_table_finish(&table);
9bcb3eef
DS
5902 bgp_dest_set_bgp_table_info(dest, NULL);
5903 bgp_dest_unlock_node(dest);
d62a17ae 5904 }
bb86c601 5905 }
718e3744 5906}
5907
d62a17ae 5908void bgp_reset(void)
718e3744 5909{
d62a17ae 5910 vty_reset();
5911 bgp_zclient_reset();
5912 access_list_reset();
5913 prefix_list_reset();
718e3744 5914}
6b0655a2 5915
be92fc9f 5916bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5917{
d62a17ae 5918 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5919 && CHECK_FLAG(peer->af_cap[afi][safi],
5920 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5921}
5922
718e3744 5923/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5924 value. */
d62a17ae 5925int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5926 struct bgp_nlri *packet)
5927{
d7c0a89a
QY
5928 uint8_t *pnt;
5929 uint8_t *lim;
d62a17ae 5930 struct prefix p;
5931 int psize;
d62a17ae 5932 afi_t afi;
5933 safi_t safi;
be92fc9f 5934 bool addpath_capable;
d7c0a89a 5935 uint32_t addpath_id;
d62a17ae 5936
d62a17ae 5937 pnt = packet->nlri;
5938 lim = pnt + packet->length;
5939 afi = packet->afi;
5940 safi = packet->safi;
5941 addpath_id = 0;
be92fc9f 5942 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5943
5944 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5945 syntactic validity. If the field is syntactically incorrect,
5946 then the Error Subcode is set to Invalid Network Field. */
5947 for (; pnt < lim; pnt += psize) {
5948 /* Clear prefix structure. */
6006b807 5949 memset(&p, 0, sizeof(p));
d62a17ae 5950
be92fc9f 5951 if (addpath_capable) {
d62a17ae 5952
5953 /* When packet overflow occurs return immediately. */
761ed665 5954 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5955 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5956
a3a850a1 5957 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5958 addpath_id = ntohl(addpath_id);
d62a17ae 5959 pnt += BGP_ADDPATH_ID_LEN;
5960 }
718e3744 5961
d62a17ae 5962 /* Fetch prefix length. */
5963 p.prefixlen = *pnt++;
5964 /* afi/safi validity already verified by caller,
5965 * bgp_update_receive */
5966 p.family = afi2family(afi);
5967
5968 /* Prefix length check. */
5969 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5970 flog_err(
e50f7cfd 5971 EC_BGP_UPDATE_RCV,
14454c9f 5972 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5973 peer->host, p.prefixlen, packet->afi);
513386b5 5974 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5975 }
6b0655a2 5976
d62a17ae 5977 /* Packet size overflow check. */
5978 psize = PSIZE(p.prefixlen);
5979
5980 /* When packet overflow occur return immediately. */
5981 if (pnt + psize > lim) {
af4c2728 5982 flog_err(
e50f7cfd 5983 EC_BGP_UPDATE_RCV,
d62a17ae 5984 "%s [Error] Update packet error (prefix length %d overflows packet)",
5985 peer->host, p.prefixlen);
513386b5 5986 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5987 }
5988
5989 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5990 * prefix for the v4 and v6 afi's and unicast/multicast */
5991 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5992 flog_err(
e50f7cfd 5993 EC_BGP_UPDATE_RCV,
d62a17ae 5994 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5995 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5996 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5997 }
5998
5999 /* Fetch prefix from NLRI packet. */
a85297a7 6000 memcpy(p.u.val, pnt, psize);
d62a17ae 6001
6002 /* Check address. */
6003 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6004 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6005 /* From RFC4271 Section 6.3:
6006 *
6007 * If a prefix in the NLRI field is semantically
6008 * incorrect
6009 * (e.g., an unexpected multicast IP address),
6010 * an error SHOULD
6011 * be logged locally, and the prefix SHOULD be
6012 * ignored.
a4d82a8a 6013 */
af4c2728 6014 flog_err(
e50f7cfd 6015 EC_BGP_UPDATE_RCV,
23d0a753
DA
6016 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6017 peer->host, &p.u.prefix4);
d62a17ae 6018 continue;
6019 }
6020 }
6021
6022 /* Check address. */
6023 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6024 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6025 flog_err(
e50f7cfd 6026 EC_BGP_UPDATE_RCV,
c0d72166
DS
6027 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6028 peer->host, &p.u.prefix6);
d62a17ae 6029
6030 continue;
6031 }
6032 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6033 flog_err(
e50f7cfd 6034 EC_BGP_UPDATE_RCV,
c0d72166
DS
6035 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6036 peer->host, &p.u.prefix6);
d62a17ae 6037
6038 continue;
6039 }
6040 }
6041
6042 /* Normal process. */
6043 if (attr)
367b458c
DS
6044 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6045 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6046 NULL, 0, 0, NULL);
d62a17ae 6047 else
bf0c6163 6048 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6049 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6050 NULL, 0, NULL);
d62a17ae 6051
513386b5
DA
6052 /* Do not send BGP notification twice when maximum-prefix count
6053 * overflow. */
6054 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6055 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6056 }
6057
6058 /* Packet length consistency check. */
6059 if (pnt != lim) {
af4c2728 6060 flog_err(
e50f7cfd 6061 EC_BGP_UPDATE_RCV,
d62a17ae 6062 "%s [Error] Update packet error (prefix length mismatch with total length)",
6063 peer->host);
513386b5 6064 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6065 }
6b0655a2 6066
513386b5 6067 return BGP_NLRI_PARSE_OK;
718e3744 6068}
6069
d62a17ae 6070static struct bgp_static *bgp_static_new(void)
718e3744 6071{
d62a17ae 6072 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6073}
6074
d62a17ae 6075static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6076{
0a22ddfb 6077 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6078 route_map_counter_decrement(bgp_static->rmap.map);
6079
c1aa9e7f
PG
6080 if (bgp_static->prd_pretty)
6081 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6082 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6083 XFREE(MTYPE_BGP_STATIC, bgp_static);
6084}
6085
5f040085 6086void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6087 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6088{
9bcb3eef 6089 struct bgp_dest *dest;
40381db7 6090 struct bgp_path_info *pi;
4b7e6066 6091 struct bgp_path_info *new;
40381db7 6092 struct bgp_path_info rmap_path;
d62a17ae 6093 struct attr attr;
6094 struct attr *attr_new;
b68885f9 6095 route_map_result_t ret;
49e5a4a0 6096#ifdef ENABLE_BGP_VNC
d62a17ae 6097 int vnc_implicit_withdraw = 0;
65efcfce 6098#endif
fee0f4c6 6099
d62a17ae 6100 assert(bgp_static);
dd8103a9 6101
9bcb3eef 6102 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6103
0f05ea43 6104 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6105
d62a17ae 6106 attr.nexthop = bgp_static->igpnexthop;
6107 attr.med = bgp_static->igpmetric;
6108 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6109
7226bc40
TA
6110 if (afi == AFI_IP)
6111 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6112
97a52c82
DA
6113 if (bgp_static->igpmetric)
6114 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6115
d62a17ae 6116 if (bgp_static->atomic)
6117 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6118
d62a17ae 6119 /* Store label index, if required. */
6120 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6121 attr.label_index = bgp_static->label_index;
6122 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6123 }
718e3744 6124
d62a17ae 6125 /* Apply route-map. */
6126 if (bgp_static->rmap.name) {
6127 struct attr attr_tmp = attr;
80ced710 6128
6006b807 6129 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6130 rmap_path.peer = bgp->peer_self;
6131 rmap_path.attr = &attr_tmp;
fee0f4c6 6132
d62a17ae 6133 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6134
1782514f 6135 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6136
d62a17ae 6137 bgp->peer_self->rmap_type = 0;
718e3744 6138
d62a17ae 6139 if (ret == RMAP_DENYMATCH) {
6140 /* Free uninterned attribute. */
6141 bgp_attr_flush(&attr_tmp);
718e3744 6142
d62a17ae 6143 /* Unintern original. */
6144 aspath_unintern(&attr.aspath);
6145 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6146 bgp_dest_unlock_node(dest);
d62a17ae 6147 return;
6148 }
7f323236 6149
637e5ba4 6150 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6151 bgp_attr_add_gshut_community(&attr_tmp);
6152
d62a17ae 6153 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6154 } else {
6155
637e5ba4 6156 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6157 bgp_attr_add_gshut_community(&attr);
6158
d62a17ae 6159 attr_new = bgp_attr_intern(&attr);
7f323236 6160 }
718e3744 6161
9bcb3eef 6162 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6163 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6164 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6165 break;
6166
40381db7
DS
6167 if (pi) {
6168 if (attrhash_cmp(pi->attr, attr_new)
6169 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6170 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6171 bgp_dest_unlock_node(dest);
d62a17ae 6172 bgp_attr_unintern(&attr_new);
6173 aspath_unintern(&attr.aspath);
6174 return;
6175 } else {
6176 /* The attribute is changed. */
9bcb3eef 6177 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6178
6179 /* Rewrite BGP route information. */
40381db7 6180 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6181 bgp_path_info_restore(dest, pi);
d62a17ae 6182 else
40381db7 6183 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6184#ifdef ENABLE_BGP_VNC
d62a17ae 6185 if ((afi == AFI_IP || afi == AFI_IP6)
6186 && (safi == SAFI_UNICAST)) {
40381db7 6187 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6188 /*
6189 * Implicit withdraw case.
40381db7 6190 * We have to do this before pi is
d62a17ae 6191 * changed
6192 */
6193 ++vnc_implicit_withdraw;
40381db7 6194 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6195 vnc_import_bgp_exterior_del_route(
40381db7 6196 bgp, p, pi);
d62a17ae 6197 }
6198 }
65efcfce 6199#endif
40381db7
DS
6200 bgp_attr_unintern(&pi->attr);
6201 pi->attr = attr_new;
083ec940 6202 pi->uptime = monotime(NULL);
49e5a4a0 6203#ifdef ENABLE_BGP_VNC
d62a17ae 6204 if ((afi == AFI_IP || afi == AFI_IP6)
6205 && (safi == SAFI_UNICAST)) {
6206 if (vnc_implicit_withdraw) {
40381db7 6207 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6208 vnc_import_bgp_exterior_add_route(
40381db7 6209 bgp, p, pi);
d62a17ae 6210 }
6211 }
65efcfce 6212#endif
718e3744 6213
d62a17ae 6214 /* Nexthop reachability check. */
892fedb6 6215 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6216 && (safi == SAFI_UNICAST
6217 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6218
6219 struct bgp *bgp_nexthop = bgp;
6220
40381db7
DS
6221 if (pi->extra && pi->extra->bgp_orig)
6222 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6223
6224 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6225 afi, safi, pi, NULL,
654a5978 6226 0, p))
9bcb3eef 6227 bgp_path_info_set_flag(dest, pi,
18ee8310 6228 BGP_PATH_VALID);
d62a17ae 6229 else {
6230 if (BGP_DEBUG(nht, NHT)) {
6231 char buf1[INET6_ADDRSTRLEN];
6232 inet_ntop(p->family,
6233 &p->u.prefix, buf1,
07380148 6234 sizeof(buf1));
d62a17ae 6235 zlog_debug(
6236 "%s(%s): Route not in table, not advertising",
15569c58 6237 __func__, buf1);
d62a17ae 6238 }
18ee8310 6239 bgp_path_info_unset_flag(
9bcb3eef 6240 dest, pi, BGP_PATH_VALID);
d62a17ae 6241 }
6242 } else {
6243 /* Delete the NHT structure if any, if we're
6244 * toggling between
6245 * enabling/disabling import check. We
6246 * deregister the route
6247 * from NHT to avoid overloading NHT and the
6248 * process interaction
6249 */
40381db7 6250 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6251 bgp_path_info_set_flag(dest, pi,
6252 BGP_PATH_VALID);
d62a17ae 6253 }
6254 /* Process change. */
40381db7 6255 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6256 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6257
6258 if (SAFI_UNICAST == safi
6259 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6260 || bgp->inst_type
6261 == BGP_INSTANCE_TYPE_DEFAULT)) {
6262 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6263 pi);
ddb5b488
PZ
6264 }
6265
9bcb3eef 6266 bgp_dest_unlock_node(dest);
d62a17ae 6267 aspath_unintern(&attr.aspath);
6268 return;
6269 }
718e3744 6270 }
718e3744 6271
d62a17ae 6272 /* Make new BGP info. */
6273 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6274 attr_new, dest);
d62a17ae 6275 /* Nexthop reachability check. */
892fedb6 6276 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6277 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6278 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6279 p))
9bcb3eef 6280 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6281 else {
6282 if (BGP_DEBUG(nht, NHT)) {
6283 char buf1[INET6_ADDRSTRLEN];
07380148 6284
d62a17ae 6285 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6286 sizeof(buf1));
d62a17ae 6287 zlog_debug(
6288 "%s(%s): Route not in table, not advertising",
15569c58 6289 __func__, buf1);
d62a17ae 6290 }
9bcb3eef 6291 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6292 }
6293 } else {
6294 /* Delete the NHT structure if any, if we're toggling between
6295 * enabling/disabling import check. We deregister the route
6296 * from NHT to avoid overloading NHT and the process interaction
6297 */
6298 bgp_unlink_nexthop(new);
6299
9bcb3eef 6300 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6301 }
078430f6 6302
d62a17ae 6303 /* Aggregate address increment. */
6304 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6305
d62a17ae 6306 /* Register new BGP information. */
9bcb3eef 6307 bgp_path_info_add(dest, new);
718e3744 6308
d62a17ae 6309 /* route_node_get lock */
9bcb3eef 6310 bgp_dest_unlock_node(dest);
d62a17ae 6311
6312 /* Process change. */
9bcb3eef 6313 bgp_process(bgp, dest, afi, safi);
d62a17ae 6314
ddb5b488
PZ
6315 if (SAFI_UNICAST == safi
6316 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6317 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6318 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6319 }
6320
d62a17ae 6321 /* Unintern original. */
6322 aspath_unintern(&attr.aspath);
718e3744 6323}
6324
5f040085 6325void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6326 safi_t safi)
718e3744 6327{
9bcb3eef 6328 struct bgp_dest *dest;
40381db7 6329 struct bgp_path_info *pi;
718e3744 6330
9bcb3eef 6331 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6332
d62a17ae 6333 /* Check selected route and self inserted route. */
9bcb3eef 6334 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6335 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6336 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6337 break;
6338
6339 /* Withdraw static BGP route from routing table. */
40381db7 6340 if (pi) {
ddb5b488
PZ
6341 if (SAFI_UNICAST == safi
6342 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6343 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6344 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6345 }
40381db7
DS
6346 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6347 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6348 bgp_path_info_delete(dest, pi);
6349 bgp_process(bgp, dest, afi, safi);
d62a17ae 6350 }
718e3744 6351
d62a17ae 6352 /* Unlock bgp_node_lookup. */
9bcb3eef 6353 bgp_dest_unlock_node(dest);
718e3744 6354}
6355
137446f9
LB
6356/*
6357 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6358 */
5f040085 6359static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6360 afi_t afi, safi_t safi,
6361 struct prefix_rd *prd)
718e3744 6362{
9bcb3eef 6363 struct bgp_dest *dest;
40381db7 6364 struct bgp_path_info *pi;
718e3744 6365
9bcb3eef 6366 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6367
d62a17ae 6368 /* Check selected route and self inserted route. */
9bcb3eef 6369 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6370 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6371 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6372 break;
718e3744 6373
d62a17ae 6374 /* Withdraw static BGP route from routing table. */
40381db7 6375 if (pi) {
49e5a4a0 6376#ifdef ENABLE_BGP_VNC
d62a17ae 6377 rfapiProcessWithdraw(
40381db7 6378 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6379 1); /* Kill, since it is an administrative change */
65efcfce 6380#endif
ddb5b488
PZ
6381 if (SAFI_MPLS_VPN == safi
6382 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6383 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6384 }
40381db7 6385 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6386 bgp_path_info_delete(dest, pi);
6387 bgp_process(bgp, dest, afi, safi);
d62a17ae 6388 }
718e3744 6389
d62a17ae 6390 /* Unlock bgp_node_lookup. */
9bcb3eef 6391 bgp_dest_unlock_node(dest);
718e3744 6392}
6393
5f040085 6394static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6395 struct bgp_static *bgp_static, afi_t afi,
6396 safi_t safi)
137446f9 6397{
9bcb3eef 6398 struct bgp_dest *dest;
4b7e6066 6399 struct bgp_path_info *new;
d62a17ae 6400 struct attr *attr_new;
6401 struct attr attr = {0};
40381db7 6402 struct bgp_path_info *pi;
49e5a4a0 6403#ifdef ENABLE_BGP_VNC
d62a17ae 6404 mpls_label_t label = 0;
65efcfce 6405#endif
d7c0a89a 6406 uint32_t num_labels = 0;
137446f9 6407
d62a17ae 6408 assert(bgp_static);
137446f9 6409
b57ba6d2
MK
6410 if (bgp_static->label != MPLS_INVALID_LABEL)
6411 num_labels = 1;
9bcb3eef
DS
6412 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6413 &bgp_static->prd);
137446f9 6414
0f05ea43 6415 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6416
d62a17ae 6417 attr.nexthop = bgp_static->igpnexthop;
6418 attr.med = bgp_static->igpmetric;
6419 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6420
d62a17ae 6421 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6422 || (safi == SAFI_ENCAP)) {
6423 if (afi == AFI_IP) {
6424 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6425 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6426 }
6427 }
6428 if (afi == AFI_L2VPN) {
b04c1e99
IR
6429 if (bgp_static->gatewayIp.family == AF_INET) {
6430 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6431 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6432 &bgp_static->gatewayIp.u.prefix4,
6433 IPV4_MAX_BYTELEN);
b04c1e99
IR
6434 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6435 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6436 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6437 &bgp_static->gatewayIp.u.prefix6,
6438 IPV6_MAX_BYTELEN);
b04c1e99 6439 }
0a50c248 6440 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6441 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6442 struct bgp_encap_type_vxlan bet;
6006b807 6443 memset(&bet, 0, sizeof(bet));
3714a385 6444 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6445 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6446 }
6447 if (bgp_static->router_mac) {
6448 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6449 }
6450 }
6451 /* Apply route-map. */
6452 if (bgp_static->rmap.name) {
6453 struct attr attr_tmp = attr;
40381db7 6454 struct bgp_path_info rmap_path;
b68885f9 6455 route_map_result_t ret;
137446f9 6456
40381db7
DS
6457 rmap_path.peer = bgp->peer_self;
6458 rmap_path.attr = &attr_tmp;
137446f9 6459
d62a17ae 6460 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6461
1782514f 6462 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6463
d62a17ae 6464 bgp->peer_self->rmap_type = 0;
137446f9 6465
d62a17ae 6466 if (ret == RMAP_DENYMATCH) {
6467 /* Free uninterned attribute. */
6468 bgp_attr_flush(&attr_tmp);
137446f9 6469
d62a17ae 6470 /* Unintern original. */
6471 aspath_unintern(&attr.aspath);
6472 bgp_static_withdraw_safi(bgp, p, afi, safi,
6473 &bgp_static->prd);
bbc52106 6474 bgp_dest_unlock_node(dest);
d62a17ae 6475 return;
6476 }
137446f9 6477
d62a17ae 6478 attr_new = bgp_attr_intern(&attr_tmp);
6479 } else {
6480 attr_new = bgp_attr_intern(&attr);
6481 }
137446f9 6482
9bcb3eef 6483 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6484 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6485 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6486 break;
6487
40381db7 6488 if (pi) {
40381db7 6489 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6490 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6491 bgp_dest_unlock_node(dest);
d62a17ae 6492 bgp_attr_unintern(&attr_new);
6493 aspath_unintern(&attr.aspath);
6494 return;
6495 } else {
6496 /* The attribute is changed. */
9bcb3eef 6497 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6498
6499 /* Rewrite BGP route information. */
40381db7 6500 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6501 bgp_path_info_restore(dest, pi);
d62a17ae 6502 else
40381db7
DS
6503 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6504 bgp_attr_unintern(&pi->attr);
6505 pi->attr = attr_new;
083ec940 6506 pi->uptime = monotime(NULL);
49e5a4a0 6507#ifdef ENABLE_BGP_VNC
40381db7
DS
6508 if (pi->extra)
6509 label = decode_label(&pi->extra->label[0]);
65efcfce 6510#endif
137446f9 6511
d62a17ae 6512 /* Process change. */
40381db7 6513 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6514 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6515
6516 if (SAFI_MPLS_VPN == safi
6517 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6518 vpn_leak_to_vrf_update(bgp, pi,
6519 &bgp_static->prd);
ddb5b488 6520 }
49e5a4a0 6521#ifdef ENABLE_BGP_VNC
40381db7
DS
6522 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6523 pi->attr, afi, safi, pi->type,
6524 pi->sub_type, &label);
65efcfce 6525#endif
9bcb3eef 6526 bgp_dest_unlock_node(dest);
d62a17ae 6527 aspath_unintern(&attr.aspath);
6528 return;
6529 }
6530 }
137446f9
LB
6531
6532
d62a17ae 6533 /* Make new BGP info. */
6534 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6535 attr_new, dest);
1defdda8 6536 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6537 bgp_path_info_extra_get(new);
b57ba6d2
MK
6538 if (num_labels) {
6539 new->extra->label[0] = bgp_static->label;
6540 new->extra->num_labels = num_labels;
6541 }
49e5a4a0 6542#ifdef ENABLE_BGP_VNC
d62a17ae 6543 label = decode_label(&bgp_static->label);
65efcfce 6544#endif
137446f9 6545
d62a17ae 6546 /* Aggregate address increment. */
6547 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6548
d62a17ae 6549 /* Register new BGP information. */
9bcb3eef 6550 bgp_path_info_add(dest, new);
d62a17ae 6551 /* route_node_get lock */
9bcb3eef 6552 bgp_dest_unlock_node(dest);
137446f9 6553
d62a17ae 6554 /* Process change. */
9bcb3eef 6555 bgp_process(bgp, dest, afi, safi);
137446f9 6556
ddb5b488
PZ
6557 if (SAFI_MPLS_VPN == safi
6558 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6559 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6560 }
49e5a4a0 6561#ifdef ENABLE_BGP_VNC
d62a17ae 6562 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6563 safi, new->type, new->sub_type, &label);
65efcfce
LB
6564#endif
6565
d62a17ae 6566 /* Unintern original. */
6567 aspath_unintern(&attr.aspath);
137446f9
LB
6568}
6569
718e3744 6570/* Configure static BGP network. When user don't run zebra, static
6571 route should be installed as valid. */
585f1adc
IR
6572static int bgp_static_set(struct vty *vty, const char *negate,
6573 const char *ip_str, afi_t afi, safi_t safi,
6574 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6575{
585f1adc
IR
6576 VTY_DECLVAR_CONTEXT(bgp, bgp);
6577 int ret;
d62a17ae 6578 struct prefix p;
6579 struct bgp_static *bgp_static;
9bcb3eef 6580 struct bgp_dest *dest;
d7c0a89a 6581 uint8_t need_update = 0;
d62a17ae 6582
585f1adc
IR
6583 /* Convert IP prefix string to struct prefix. */
6584 ret = str2prefix(ip_str, &p);
6585 if (!ret) {
6586 vty_out(vty, "%% Malformed prefix\n");
6587 return CMD_WARNING_CONFIG_FAILED;
6588 }
6589 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6590 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6591 return CMD_WARNING_CONFIG_FAILED;
6592 }
6593
d62a17ae 6594 apply_mask(&p);
718e3744 6595
e2a86ad9 6596 if (negate) {
718e3744 6597
e2a86ad9 6598 /* Set BGP static route configuration. */
9bcb3eef 6599 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6600
9bcb3eef 6601 if (!dest) {
585f1adc
IR
6602 vty_out(vty, "%% Can't find static route specified\n");
6603 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6604 }
6605
9bcb3eef 6606 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6607
e2a86ad9
DS
6608 if ((label_index != BGP_INVALID_LABEL_INDEX)
6609 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6610 vty_out(vty,
6611 "%% label-index doesn't match static route\n");
70d9b134 6612 bgp_dest_unlock_node(dest);
585f1adc 6613 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6614 }
d62a17ae 6615
e2a86ad9
DS
6616 if ((rmap && bgp_static->rmap.name)
6617 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6618 vty_out(vty,
6619 "%% route-map name doesn't match static route\n");
70d9b134 6620 bgp_dest_unlock_node(dest);
585f1adc 6621 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6622 }
718e3744 6623
e2a86ad9
DS
6624 /* Update BGP RIB. */
6625 if (!bgp_static->backdoor)
6626 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6627
e2a86ad9
DS
6628 /* Clear configuration. */
6629 bgp_static_free(bgp_static);
9bcb3eef
DS
6630 bgp_dest_set_bgp_static_info(dest, NULL);
6631 bgp_dest_unlock_node(dest);
6632 bgp_dest_unlock_node(dest);
e2a86ad9 6633 } else {
718e3744 6634
e2a86ad9 6635 /* Set BGP static route configuration. */
9bcb3eef
DS
6636 dest = bgp_node_get(bgp->route[afi][safi], &p);
6637 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6638 if (bgp_static) {
e2a86ad9 6639 /* Configuration change. */
e2a86ad9
DS
6640 /* Label index cannot be changed. */
6641 if (bgp_static->label_index != label_index) {
585f1adc 6642 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6643 bgp_dest_unlock_node(dest);
585f1adc 6644 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6645 }
d62a17ae 6646
e2a86ad9 6647 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6648 if (bgp_static->valid
6649 && bgp_static->backdoor != backdoor)
e2a86ad9 6650 need_update = 1;
718e3744 6651
e2a86ad9 6652 bgp_static->backdoor = backdoor;
718e3744 6653
e2a86ad9 6654 if (rmap) {
0a22ddfb
QY
6655 XFREE(MTYPE_ROUTE_MAP_NAME,
6656 bgp_static->rmap.name);
b4897fa5 6657 route_map_counter_decrement(
6658 bgp_static->rmap.map);
e2a86ad9
DS
6659 bgp_static->rmap.name =
6660 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6661 bgp_static->rmap.map =
6662 route_map_lookup_by_name(rmap);
b4897fa5 6663 route_map_counter_increment(
6664 bgp_static->rmap.map);
e2a86ad9 6665 } else {
0a22ddfb
QY
6666 XFREE(MTYPE_ROUTE_MAP_NAME,
6667 bgp_static->rmap.name);
b4897fa5 6668 route_map_counter_decrement(
6669 bgp_static->rmap.map);
e2a86ad9
DS
6670 bgp_static->rmap.map = NULL;
6671 bgp_static->valid = 0;
6672 }
9bcb3eef 6673 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6674 } else {
6675 /* New configuration. */
6676 bgp_static = bgp_static_new();
6677 bgp_static->backdoor = backdoor;
6678 bgp_static->valid = 0;
6679 bgp_static->igpmetric = 0;
975a328e 6680 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6681 bgp_static->label_index = label_index;
718e3744 6682
e2a86ad9 6683 if (rmap) {
0a22ddfb
QY
6684 XFREE(MTYPE_ROUTE_MAP_NAME,
6685 bgp_static->rmap.name);
b4897fa5 6686 route_map_counter_decrement(
6687 bgp_static->rmap.map);
e2a86ad9
DS
6688 bgp_static->rmap.name =
6689 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6690 bgp_static->rmap.map =
6691 route_map_lookup_by_name(rmap);
b4897fa5 6692 route_map_counter_increment(
6693 bgp_static->rmap.map);
e2a86ad9 6694 }
9bcb3eef 6695 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6696 }
d62a17ae 6697
e2a86ad9
DS
6698 bgp_static->valid = 1;
6699 if (need_update)
6700 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6701
e2a86ad9
DS
6702 if (!bgp_static->backdoor)
6703 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6704 }
d62a17ae 6705
585f1adc 6706 return CMD_SUCCESS;
d62a17ae 6707}
6708
6709void bgp_static_add(struct bgp *bgp)
6710{
6711 afi_t afi;
6712 safi_t safi;
9bcb3eef
DS
6713 struct bgp_dest *dest;
6714 struct bgp_dest *rm;
d62a17ae 6715 struct bgp_table *table;
6716 struct bgp_static *bgp_static;
6717
47fc6261 6718 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6719 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6720 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6721 dest = bgp_route_next(dest)) {
6722 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6723 continue;
ea47320b 6724
05c7a1cc
QY
6725 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6726 || (safi == SAFI_EVPN)) {
9bcb3eef 6727 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6728
6729 for (rm = bgp_table_top(table); rm;
6730 rm = bgp_route_next(rm)) {
a78beeb5 6731 bgp_static =
9bcb3eef 6732 bgp_dest_get_bgp_static_info(
5a8ba9fc 6733 rm);
9bcb3eef
DS
6734 bgp_static_update_safi(
6735 bgp, bgp_dest_get_prefix(rm),
6736 bgp_static, afi, safi);
d62a17ae 6737 }
05c7a1cc 6738 } else {
5a8ba9fc 6739 bgp_static_update(
9bcb3eef
DS
6740 bgp, bgp_dest_get_prefix(dest),
6741 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6742 safi);
ea47320b 6743 }
05c7a1cc 6744 }
47fc6261 6745 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6746}
6747
718e3744 6748/* Called from bgp_delete(). Delete all static routes from the BGP
6749 instance. */
d62a17ae 6750void bgp_static_delete(struct bgp *bgp)
6751{
6752 afi_t afi;
6753 safi_t safi;
9bcb3eef
DS
6754 struct bgp_dest *dest;
6755 struct bgp_dest *rm;
d62a17ae 6756 struct bgp_table *table;
6757 struct bgp_static *bgp_static;
6758
05c7a1cc 6759 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6760 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6761 dest = bgp_route_next(dest)) {
6762 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6763 continue;
ea47320b 6764
05c7a1cc
QY
6765 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6766 || (safi == SAFI_EVPN)) {
9bcb3eef 6767 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6768
6769 for (rm = bgp_table_top(table); rm;
6770 rm = bgp_route_next(rm)) {
a78beeb5 6771 bgp_static =
9bcb3eef 6772 bgp_dest_get_bgp_static_info(
5a8ba9fc 6773 rm);
c7d14ba6
PG
6774 if (!bgp_static)
6775 continue;
6776
05c7a1cc 6777 bgp_static_withdraw_safi(
9bcb3eef 6778 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6779 AFI_IP, safi,
6780 (struct prefix_rd *)
9bcb3eef
DS
6781 bgp_dest_get_prefix(
6782 dest));
ea47320b 6783 bgp_static_free(bgp_static);
811c6797 6784 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6785 NULL);
811c6797 6786 bgp_dest_unlock_node(rm);
d62a17ae 6787 }
05c7a1cc 6788 } else {
9bcb3eef 6789 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6790 bgp_static_withdraw(bgp,
9bcb3eef 6791 bgp_dest_get_prefix(dest),
b54892e0 6792 afi, safi);
05c7a1cc 6793 bgp_static_free(bgp_static);
9bcb3eef
DS
6794 bgp_dest_set_bgp_static_info(dest, NULL);
6795 bgp_dest_unlock_node(dest);
ea47320b 6796 }
05c7a1cc 6797 }
d62a17ae 6798}
6799
6800void bgp_static_redo_import_check(struct bgp *bgp)
6801{
6802 afi_t afi;
6803 safi_t safi;
9bcb3eef
DS
6804 struct bgp_dest *dest;
6805 struct bgp_dest *rm;
d62a17ae 6806 struct bgp_table *table;
6807 struct bgp_static *bgp_static;
6808
6809 /* Use this flag to force reprocessing of the route */
892fedb6 6810 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6811 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6812 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6813 dest = bgp_route_next(dest)) {
6814 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6815 continue;
ea47320b 6816
05c7a1cc
QY
6817 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6818 || (safi == SAFI_EVPN)) {
9bcb3eef 6819 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6820
6821 for (rm = bgp_table_top(table); rm;
6822 rm = bgp_route_next(rm)) {
a78beeb5 6823 bgp_static =
9bcb3eef 6824 bgp_dest_get_bgp_static_info(
5a8ba9fc 6825 rm);
9bcb3eef
DS
6826 bgp_static_update_safi(
6827 bgp, bgp_dest_get_prefix(rm),
6828 bgp_static, afi, safi);
d62a17ae 6829 }
05c7a1cc 6830 } else {
9bcb3eef
DS
6831 bgp_static = bgp_dest_get_bgp_static_info(dest);
6832 bgp_static_update(bgp,
6833 bgp_dest_get_prefix(dest),
6834 bgp_static, afi, safi);
ea47320b 6835 }
05c7a1cc
QY
6836 }
6837 }
892fedb6 6838 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6839}
6840
6841static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6842 safi_t safi)
6843{
6844 struct bgp_table *table;
9bcb3eef 6845 struct bgp_dest *dest;
40381db7 6846 struct bgp_path_info *pi;
d62a17ae 6847
dfb6fd1d
NT
6848 /* Do not install the aggregate route if BGP is in the
6849 * process of termination.
6850 */
892fedb6
DA
6851 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6852 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6853 return;
6854
d62a17ae 6855 table = bgp->rib[afi][safi];
9bcb3eef
DS
6856 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6858 if (pi->peer == bgp->peer_self
6859 && ((pi->type == ZEBRA_ROUTE_BGP
6860 && pi->sub_type == BGP_ROUTE_STATIC)
6861 || (pi->type != ZEBRA_ROUTE_BGP
6862 && pi->sub_type
d62a17ae 6863 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6864 bgp_aggregate_decrement(
6865 bgp, bgp_dest_get_prefix(dest), pi, afi,
6866 safi);
40381db7 6867 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6868 bgp_path_info_delete(dest, pi);
6869 bgp_process(bgp, dest, afi, safi);
d62a17ae 6870 }
6871 }
6872 }
ad4cbda1 6873}
6874
6875/*
6876 * Purge all networks and redistributed routes from routing table.
6877 * Invoked upon the instance going down.
6878 */
d62a17ae 6879void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6880{
d62a17ae 6881 afi_t afi;
6882 safi_t safi;
ad4cbda1 6883
05c7a1cc
QY
6884 FOREACH_AFI_SAFI (afi, safi)
6885 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6886}
6887
137446f9
LB
6888/*
6889 * gpz 110624
6890 * Currently this is used to set static routes for VPN and ENCAP.
6891 * I think it can probably be factored with bgp_static_set.
6892 */
d62a17ae 6893int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6894 const char *ip_str, const char *rd_str,
6895 const char *label_str, const char *rmap_str,
6896 int evpn_type, const char *esi, const char *gwip,
6897 const char *ethtag, const char *routermac)
6898{
6899 VTY_DECLVAR_CONTEXT(bgp, bgp);
6900 int ret;
6901 struct prefix p;
6902 struct prefix_rd prd;
9bcb3eef
DS
6903 struct bgp_dest *pdest;
6904 struct bgp_dest *dest;
d62a17ae 6905 struct bgp_table *table;
6906 struct bgp_static *bgp_static;
6907 mpls_label_t label = MPLS_INVALID_LABEL;
6908 struct prefix gw_ip;
6909
6910 /* validate ip prefix */
6911 ret = str2prefix(ip_str, &p);
6912 if (!ret) {
6913 vty_out(vty, "%% Malformed prefix\n");
6914 return CMD_WARNING_CONFIG_FAILED;
6915 }
6916 apply_mask(&p);
6917 if ((afi == AFI_L2VPN)
6918 && (bgp_build_evpn_prefix(evpn_type,
6919 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6920 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6921 return CMD_WARNING_CONFIG_FAILED;
6922 }
718e3744 6923
d62a17ae 6924 ret = str2prefix_rd(rd_str, &prd);
6925 if (!ret) {
6926 vty_out(vty, "%% Malformed rd\n");
6927 return CMD_WARNING_CONFIG_FAILED;
6928 }
718e3744 6929
d62a17ae 6930 if (label_str) {
6931 unsigned long label_val;
6932 label_val = strtoul(label_str, NULL, 10);
6933 encode_label(label_val, &label);
6934 }
9bedbb1e 6935
d62a17ae 6936 if (safi == SAFI_EVPN) {
6937 if (esi && str2esi(esi, NULL) == 0) {
6938 vty_out(vty, "%% Malformed ESI\n");
6939 return CMD_WARNING_CONFIG_FAILED;
6940 }
6941 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6942 vty_out(vty, "%% Malformed Router MAC\n");
6943 return CMD_WARNING_CONFIG_FAILED;
6944 }
6945 if (gwip) {
6006b807 6946 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6947 ret = str2prefix(gwip, &gw_ip);
6948 if (!ret) {
6949 vty_out(vty, "%% Malformed GatewayIp\n");
6950 return CMD_WARNING_CONFIG_FAILED;
6951 }
6952 if ((gw_ip.family == AF_INET
3714a385 6953 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6954 (struct prefix_evpn *)&p))
6955 || (gw_ip.family == AF_INET6
3714a385 6956 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6957 (struct prefix_evpn *)&p))) {
6958 vty_out(vty,
6959 "%% GatewayIp family differs with IP prefix\n");
6960 return CMD_WARNING_CONFIG_FAILED;
6961 }
6962 }
6963 }
9bcb3eef
DS
6964 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6965 if (!bgp_dest_has_bgp_path_info_data(pdest))
6966 bgp_dest_set_bgp_table_info(pdest,
67009e22 6967 bgp_table_init(bgp, afi, safi));
9bcb3eef 6968 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6969
9bcb3eef 6970 dest = bgp_node_get(table, &p);
d62a17ae 6971
9bcb3eef 6972 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6973 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6974 bgp_dest_unlock_node(dest);
d62a17ae 6975 } else {
6976 /* New configuration. */
6977 bgp_static = bgp_static_new();
6978 bgp_static->backdoor = 0;
6979 bgp_static->valid = 0;
6980 bgp_static->igpmetric = 0;
975a328e 6981 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6982 bgp_static->label = label;
6983 bgp_static->prd = prd;
6984
c1aa9e7f
PG
6985 if (rd_str)
6986 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
d62a17ae 6987 if (rmap_str) {
0a22ddfb 6988 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6989 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6990 bgp_static->rmap.name =
6991 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6992 bgp_static->rmap.map =
6993 route_map_lookup_by_name(rmap_str);
b4897fa5 6994 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6995 }
718e3744 6996
d62a17ae 6997 if (safi == SAFI_EVPN) {
6998 if (esi) {
6999 bgp_static->eth_s_id =
7000 XCALLOC(MTYPE_ATTR,
0a50c248 7001 sizeof(esi_t));
d62a17ae 7002 str2esi(esi, bgp_static->eth_s_id);
7003 }
7004 if (routermac) {
7005 bgp_static->router_mac =
28328ea9 7006 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7007 (void)prefix_str2mac(routermac,
7008 bgp_static->router_mac);
d62a17ae 7009 }
7010 if (gwip)
7011 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7012 }
9bcb3eef 7013 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7014
d62a17ae 7015 bgp_static->valid = 1;
7016 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7017 }
718e3744 7018
d62a17ae 7019 return CMD_SUCCESS;
718e3744 7020}
7021
7022/* Configure static BGP network. */
d62a17ae 7023int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7024 const char *ip_str, const char *rd_str,
7025 const char *label_str, int evpn_type, const char *esi,
7026 const char *gwip, const char *ethtag)
7027{
7028 VTY_DECLVAR_CONTEXT(bgp, bgp);
7029 int ret;
7030 struct prefix p;
7031 struct prefix_rd prd;
9bcb3eef
DS
7032 struct bgp_dest *pdest;
7033 struct bgp_dest *dest;
d62a17ae 7034 struct bgp_table *table;
7035 struct bgp_static *bgp_static;
7036 mpls_label_t label = MPLS_INVALID_LABEL;
7037
7038 /* Convert IP prefix string to struct prefix. */
7039 ret = str2prefix(ip_str, &p);
7040 if (!ret) {
7041 vty_out(vty, "%% Malformed prefix\n");
7042 return CMD_WARNING_CONFIG_FAILED;
7043 }
7044 apply_mask(&p);
7045 if ((afi == AFI_L2VPN)
7046 && (bgp_build_evpn_prefix(evpn_type,
7047 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7048 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7049 return CMD_WARNING_CONFIG_FAILED;
7050 }
7051 ret = str2prefix_rd(rd_str, &prd);
7052 if (!ret) {
7053 vty_out(vty, "%% Malformed rd\n");
7054 return CMD_WARNING_CONFIG_FAILED;
7055 }
718e3744 7056
d62a17ae 7057 if (label_str) {
7058 unsigned long label_val;
7059 label_val = strtoul(label_str, NULL, 10);
7060 encode_label(label_val, &label);
7061 }
718e3744 7062
9bcb3eef
DS
7063 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7064 if (!bgp_dest_has_bgp_path_info_data(pdest))
7065 bgp_dest_set_bgp_table_info(pdest,
67009e22 7066 bgp_table_init(bgp, afi, safi));
d62a17ae 7067 else
9bcb3eef
DS
7068 bgp_dest_unlock_node(pdest);
7069 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7070
9bcb3eef 7071 dest = bgp_node_lookup(table, &p);
6b0655a2 7072
9bcb3eef 7073 if (dest) {
d62a17ae 7074 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7075
9bcb3eef 7076 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7077 bgp_static_free(bgp_static);
9bcb3eef
DS
7078 bgp_dest_set_bgp_static_info(dest, NULL);
7079 bgp_dest_unlock_node(dest);
7080 bgp_dest_unlock_node(dest);
d62a17ae 7081 } else
7082 vty_out(vty, "%% Can't find the route\n");
7083
7084 return CMD_SUCCESS;
7085}
7086
7087static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7088 const char *rmap_name)
7089{
7090 VTY_DECLVAR_CONTEXT(bgp, bgp);
7091 struct bgp_rmap *rmap;
7092
7093 rmap = &bgp->table_map[afi][safi];
7094 if (rmap_name) {
0a22ddfb 7095 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7096 route_map_counter_decrement(rmap->map);
d62a17ae 7097 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7098 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7099 route_map_counter_increment(rmap->map);
d62a17ae 7100 } else {
0a22ddfb 7101 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7102 route_map_counter_decrement(rmap->map);
d62a17ae 7103 rmap->map = NULL;
7104 }
73ac8160 7105
d62a17ae 7106 if (bgp_fibupd_safi(safi))
7107 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7108
d62a17ae 7109 return CMD_SUCCESS;
73ac8160
DS
7110}
7111
d62a17ae 7112static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7113 const char *rmap_name)
73ac8160 7114{
d62a17ae 7115 VTY_DECLVAR_CONTEXT(bgp, bgp);
7116 struct bgp_rmap *rmap;
73ac8160 7117
d62a17ae 7118 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7119 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7120 route_map_counter_decrement(rmap->map);
d62a17ae 7121 rmap->map = NULL;
73ac8160 7122
d62a17ae 7123 if (bgp_fibupd_safi(safi))
7124 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7125
d62a17ae 7126 return CMD_SUCCESS;
73ac8160
DS
7127}
7128
2b791107 7129void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7130 safi_t safi)
73ac8160 7131{
d62a17ae 7132 if (bgp->table_map[afi][safi].name) {
d62a17ae 7133 vty_out(vty, " table-map %s\n",
7134 bgp->table_map[afi][safi].name);
7135 }
73ac8160
DS
7136}
7137
73ac8160
DS
7138DEFUN (bgp_table_map,
7139 bgp_table_map_cmd,
7140 "table-map WORD",
7141 "BGP table to RIB route download filter\n"
7142 "Name of the route map\n")
7143{
d62a17ae 7144 int idx_word = 1;
7145 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7146 argv[idx_word]->arg);
73ac8160
DS
7147}
7148DEFUN (no_bgp_table_map,
7149 no_bgp_table_map_cmd,
7150 "no table-map WORD",
3a2d747c 7151 NO_STR
73ac8160
DS
7152 "BGP table to RIB route download filter\n"
7153 "Name of the route map\n")
7154{
d62a17ae 7155 int idx_word = 2;
7156 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7157 argv[idx_word]->arg);
73ac8160
DS
7158}
7159
585f1adc
IR
7160DEFPY(bgp_network,
7161 bgp_network_cmd,
7162 "[no] network \
7163 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7164 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7165 backdoor$backdoor}]",
7166 NO_STR
7167 "Specify a network to announce via BGP\n"
7168 "IPv4 prefix\n"
7169 "Network number\n"
7170 "Network mask\n"
7171 "Network mask\n"
7172 "Route-map to modify the attributes\n"
7173 "Name of the route map\n"
7174 "Label index to associate with the prefix\n"
7175 "Label index value\n"
7176 "Specify a BGP backdoor route\n")
7177{
7178 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7179
7180 if (address_str) {
7181 int ret;
718e3744 7182
e2a86ad9 7183 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7184 addr_prefix_str,
7185 sizeof(addr_prefix_str));
e2a86ad9
DS
7186 if (!ret) {
7187 vty_out(vty, "%% Inconsistent address and mask\n");
7188 return CMD_WARNING_CONFIG_FAILED;
7189 }
d62a17ae 7190 }
718e3744 7191
585f1adc
IR
7192 return bgp_static_set(
7193 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7194 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7195 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7196}
7197
585f1adc
IR
7198DEFPY(ipv6_bgp_network,
7199 ipv6_bgp_network_cmd,
7200 "[no] network X:X::X:X/M$prefix \
70dd370f 7201 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7202 NO_STR
7203 "Specify a network to announce via BGP\n"
7204 "IPv6 prefix\n"
7205 "Route-map to modify the attributes\n"
7206 "Name of the route map\n"
7207 "Label index to associate with the prefix\n"
7208 "Label index value\n")
37a87b8f 7209{
585f1adc
IR
7210 return bgp_static_set(
7211 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7212 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7213}
7214
d62a17ae 7215static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7216{
d62a17ae 7217 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7218}
7219
d62a17ae 7220static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7221{
365ab2e7
RZ
7222 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7223 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7224 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7225 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7226 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7227}
718e3744 7228
365ab2e7
RZ
7229/**
7230 * Helper function to avoid repeated code: prepare variables for a
7231 * `route_map_apply` call.
7232 *
7233 * \returns `true` on route map match, otherwise `false`.
7234 */
7235static bool aggr_suppress_map_test(struct bgp *bgp,
7236 struct bgp_aggregate *aggregate,
7237 struct bgp_path_info *pi)
7238{
7239 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7240 route_map_result_t rmr = RMAP_DENYMATCH;
7241 struct bgp_path_info rmap_path = {};
7242 struct attr attr = {};
7243
7244 /* No route map entries created, just don't match. */
7245 if (aggregate->suppress_map == NULL)
7246 return false;
7247
7248 /* Call route map matching and return result. */
17571c4a 7249 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7250 rmap_path.peer = bgp->peer_self;
7251 rmap_path.attr = &attr;
7252
7253 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7254 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7255 bgp->peer_self->rmap_type = 0;
7256
7257 bgp_attr_flush(&attr);
afb254d7 7258 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7259
7260 return rmr == RMAP_PERMITMATCH;
7261}
7262
4056a5f6
RZ
7263/** Test whether the aggregation has suppressed this path or not. */
7264static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7265 struct bgp_path_info *pi)
7266{
7267 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7268 return false;
7269
7270 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7271}
7272
7273/**
7274 * Suppress this path and keep the reference.
7275 *
7276 * \returns `true` if needs processing otherwise `false`.
7277 */
7278static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7279 struct bgp_path_info *pi)
7280{
7281 struct bgp_path_info_extra *pie;
7282
7283 /* Path is already suppressed by this aggregation. */
7284 if (aggr_suppress_exists(aggregate, pi))
7285 return false;
7286
7287 pie = bgp_path_info_extra_get(pi);
7288
7289 /* This is the first suppression, allocate memory and list it. */
7290 if (pie->aggr_suppressors == NULL)
7291 pie->aggr_suppressors = list_new();
7292
7293 listnode_add(pie->aggr_suppressors, aggregate);
7294
7295 /* Only mark for processing if suppressed. */
7296 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7297 if (BGP_DEBUG(update, UPDATE_OUT))
7298 zlog_debug("aggregate-address suppressing: %pFX",
7299 bgp_dest_get_prefix(pi->net));
7300
4056a5f6
RZ
7301 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7302 return true;
7303 }
7304
7305 return false;
7306}
7307
7308/**
7309 * Unsuppress this path and remove the reference.
7310 *
7311 * \returns `true` if needs processing otherwise `false`.
7312 */
7313static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7314 struct bgp_path_info *pi)
7315{
7316 /* Path wasn't suppressed. */
7317 if (!aggr_suppress_exists(aggregate, pi))
7318 return false;
7319
7320 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7321
7322 /* Unsuppress and free extra memory if last item. */
7323 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7324 if (BGP_DEBUG(update, UPDATE_OUT))
7325 zlog_debug("aggregate-address unsuppressing: %pFX",
7326 bgp_dest_get_prefix(pi->net));
7327
4056a5f6
RZ
7328 list_delete(&pi->extra->aggr_suppressors);
7329 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7330 return true;
7331 }
7332
7333 return false;
7334}
7335
3dc339cd
DA
7336static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7337 struct aspath *aspath,
7338 struct community *comm,
7339 struct ecommunity *ecomm,
7340 struct lcommunity *lcomm)
eaaf8adb
DS
7341{
7342 static struct aspath *ae = NULL;
17571c4a
PG
7343 enum asnotation_mode asnotation;
7344
7345 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7346
7347 if (!ae)
17571c4a 7348 ae = aspath_empty(asnotation);
eaaf8adb 7349
40381db7 7350 if (!pi)
3dc339cd 7351 return false;
eaaf8adb 7352
40381db7 7353 if (origin != pi->attr->origin)
3dc339cd 7354 return false;
eaaf8adb 7355
40381db7 7356 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7357 return false;
29f7d023 7358
9a706b42 7359 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7360 return false;
eaaf8adb 7361
b53e67a3 7362 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7363 return false;
eaaf8adb 7364
1bcf3a96 7365 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7366 return false;
dd18c5a9 7367
40381db7 7368 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7369 return false;
7ce8a8e0 7370
3dc339cd 7371 return true;
eaaf8adb
DS
7372}
7373
5f040085
DS
7374static void bgp_aggregate_install(
7375 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7376 uint8_t origin, struct aspath *aspath, struct community *community,
7377 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7378 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7379{
9bcb3eef 7380 struct bgp_dest *dest;
c701010e 7381 struct bgp_table *table;
6f94b685 7382 struct bgp_path_info *pi, *orig, *new;
20894f50 7383 struct attr *attr;
c701010e
DS
7384
7385 table = bgp->rib[afi][safi];
7386
9bcb3eef 7387 dest = bgp_node_get(table, p);
eaaf8adb 7388
9bcb3eef 7389 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7390 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7391 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7392 break;
7393
6aabb15d
RZ
7394 /*
7395 * If we have paths with different MEDs, then don't install
7396 * (or uninstall) the aggregate route.
7397 */
7398 if (aggregate->match_med && aggregate->med_mismatched)
7399 goto uninstall_aggregate_route;
7400
c701010e 7401 if (aggregate->count > 0) {
eaaf8adb
DS
7402 /*
7403 * If the aggregate information has not changed
7404 * no need to re-install it again.
7405 */
6f94b685 7406 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7407 ecommunity, lcommunity)) {
9bcb3eef 7408 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7409
7410 if (aspath)
7411 aspath_free(aspath);
7412 if (community)
3c1f53de 7413 community_free(&community);
3da2cc32
DS
7414 if (ecommunity)
7415 ecommunity_free(&ecommunity);
dd18c5a9
DS
7416 if (lcommunity)
7417 lcommunity_free(&lcommunity);
eaaf8adb
DS
7418
7419 return;
7420 }
7421
7422 /*
7423 * Mark the old as unusable
7424 */
40381db7 7425 if (pi)
9bcb3eef 7426 bgp_path_info_delete(dest, pi);
eaaf8adb 7427
20894f50
DA
7428 attr = bgp_attr_aggregate_intern(
7429 bgp, origin, aspath, community, ecommunity, lcommunity,
7430 aggregate, atomic_aggregate, p);
7431
7432 if (!attr) {
8c0044f3 7433 bgp_dest_unlock_node(dest);
20894f50 7434 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7435 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7436 zlog_debug("%s: %pFX null attribute", __func__,
7437 p);
20894f50
DA
7438 return;
7439 }
7440
3da2cc32 7441 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7442 bgp->peer_self, attr, dest);
20894f50 7443
1defdda8 7444 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7445
9bcb3eef
DS
7446 bgp_path_info_add(dest, new);
7447 bgp_process(bgp, dest, afi, safi);
c701010e 7448 } else {
6aabb15d 7449 uninstall_aggregate_route:
6f94b685 7450 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7451 if (pi->peer == bgp->peer_self
7452 && pi->type == ZEBRA_ROUTE_BGP
7453 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7454 break;
7455
7456 /* Withdraw static BGP route from routing table. */
40381db7 7457 if (pi) {
9bcb3eef
DS
7458 bgp_path_info_delete(dest, pi);
7459 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7460 }
7461 }
7462
9bcb3eef 7463 bgp_dest_unlock_node(dest);
c701010e
DS
7464}
7465
6aabb15d
RZ
7466/**
7467 * Check if the current path has different MED than other known paths.
7468 *
7469 * \returns `true` if the MED matched the others else `false`.
7470 */
7471static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7472 struct bgp *bgp, struct bgp_path_info *pi)
7473{
7474 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7475
7476 /* This is the first route being analyzed. */
7477 if (!aggregate->med_initialized) {
7478 aggregate->med_initialized = true;
7479 aggregate->med_mismatched = false;
7480 aggregate->med_matched_value = cur_med;
7481 } else {
7482 /* Check if routes with different MED showed up. */
7483 if (cur_med != aggregate->med_matched_value)
7484 aggregate->med_mismatched = true;
7485 }
7486
7487 return !aggregate->med_mismatched;
7488}
7489
7490/**
7491 * Initializes and tests all routes in the aggregate address path for MED
7492 * values.
7493 *
7494 * \returns `true` if all MEDs are the same otherwise `false`.
7495 */
7496static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7497 struct bgp *bgp, const struct prefix *p,
7498 afi_t afi, safi_t safi)
7499{
7500 struct bgp_table *table = bgp->rib[afi][safi];
7501 const struct prefix *dest_p;
7502 struct bgp_dest *dest, *top;
7503 struct bgp_path_info *pi;
7504 bool med_matched = true;
7505
7506 aggregate->med_initialized = false;
7507
7508 top = bgp_node_get(table, p);
7509 for (dest = bgp_node_get(table, p); dest;
7510 dest = bgp_route_next_until(dest, top)) {
7511 dest_p = bgp_dest_get_prefix(dest);
7512 if (dest_p->prefixlen <= p->prefixlen)
7513 continue;
7514
7515 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7516 if (BGP_PATH_HOLDDOWN(pi))
7517 continue;
7518 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7519 continue;
7520 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7521 med_matched = false;
7522 break;
7523 }
7524 }
7525 if (!med_matched)
7526 break;
7527 }
7528 bgp_dest_unlock_node(top);
7529
7530 return med_matched;
7531}
7532
7533/**
7534 * Toggles the route suppression status for this aggregate address
7535 * configuration.
7536 */
4056a5f6
RZ
7537void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7538 struct bgp *bgp, const struct prefix *p,
7539 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7540{
7541 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7542 const struct prefix *dest_p;
7543 struct bgp_dest *dest, *top;
7544 struct bgp_path_info *pi;
7545 bool toggle_suppression;
7546
7547 /* We've found a different MED we must revert any suppressed routes. */
7548 top = bgp_node_get(table, p);
7549 for (dest = bgp_node_get(table, p); dest;
7550 dest = bgp_route_next_until(dest, top)) {
7551 dest_p = bgp_dest_get_prefix(dest);
7552 if (dest_p->prefixlen <= p->prefixlen)
7553 continue;
7554
7555 toggle_suppression = false;
7556 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7557 if (BGP_PATH_HOLDDOWN(pi))
7558 continue;
7559 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7560 continue;
7561
6aabb15d
RZ
7562 /* We are toggling suppression back. */
7563 if (suppress) {
6aabb15d 7564 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7565 if (aggr_suppress_path(aggregate, pi))
7566 toggle_suppression = true;
6aabb15d
RZ
7567 continue;
7568 }
7569
6aabb15d 7570 /* Install route if there is no more suppression. */
4056a5f6 7571 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7572 toggle_suppression = true;
6aabb15d
RZ
7573 }
7574
7575 if (toggle_suppression)
7576 bgp_process(bgp, dest, afi, safi);
7577 }
7578 bgp_dest_unlock_node(top);
7579}
7580
7581/**
7582 * Aggregate address MED matching incremental test: this function is called
7583 * when the initial aggregation occurred and we are only testing a single
7584 * new path.
7585 *
7586 * In addition to testing and setting the MED validity it also installs back
7587 * suppressed routes (if summary is configured).
7588 *
7589 * Must not be called in `bgp_aggregate_route`.
7590 */
7591static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7592 struct bgp *bgp, const struct prefix *p,
7593 afi_t afi, safi_t safi,
f66624f5 7594 struct bgp_path_info *pi)
6aabb15d
RZ
7595{
7596 /* MED matching disabled. */
7597 if (!aggregate->match_med)
7598 return;
7599
f66624f5
DA
7600 /* Aggregation with different MED, recheck if we have got equal MEDs
7601 * now.
6aabb15d 7602 */
f66624f5
DA
7603 if (aggregate->med_mismatched &&
7604 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7605 aggregate->summary_only)
7606 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7607 true);
7608 else
6aabb15d
RZ
7609 bgp_aggregate_med_match(aggregate, bgp, pi);
7610
7611 /* No mismatches, just quit. */
7612 if (!aggregate->med_mismatched)
7613 return;
7614
7615 /* Route summarization is disabled. */
7616 if (!aggregate->summary_only)
7617 return;
7618
7619 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7620}
7621
b5d58c32 7622/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7623void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7624 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7625{
7626 struct bgp_table *table;
9bcb3eef
DS
7627 struct bgp_dest *top;
7628 struct bgp_dest *dest;
d7c0a89a 7629 uint8_t origin;
d62a17ae 7630 struct aspath *aspath = NULL;
d62a17ae 7631 struct community *community = NULL;
3da2cc32 7632 struct ecommunity *ecommunity = NULL;
dd18c5a9 7633 struct lcommunity *lcommunity = NULL;
40381db7 7634 struct bgp_path_info *pi;
d62a17ae 7635 unsigned long match = 0;
d7c0a89a 7636 uint8_t atomic_aggregate = 0;
d62a17ae 7637
9f822fa2
S
7638 /* If the bgp instance is being deleted or self peer is deleted
7639 * then do not create aggregate route
7640 */
892fedb6
DA
7641 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7642 || (bgp->peer_self == NULL))
9f822fa2
S
7643 return;
7644
6aabb15d
RZ
7645 /* Initialize and test routes for MED difference. */
7646 if (aggregate->match_med)
7647 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7648
4056a5f6
RZ
7649 /*
7650 * Reset aggregate count: we might've been called from route map
7651 * update so in that case we must retest all more specific routes.
7652 *
7653 * \see `bgp_route_map_process_update`.
7654 */
7655 aggregate->count = 0;
7656 aggregate->incomplete_origin_count = 0;
7657 aggregate->incomplete_origin_count = 0;
7658 aggregate->egp_origin_count = 0;
7659
d62a17ae 7660 /* ORIGIN attribute: If at least one route among routes that are
7661 aggregated has ORIGIN with the value INCOMPLETE, then the
7662 aggregated route must have the ORIGIN attribute with the value
7663 INCOMPLETE. Otherwise, if at least one route among routes that
7664 are aggregated has ORIGIN with the value EGP, then the aggregated
7665 route must have the origin attribute with the value EGP. In all
7666 other case the value of the ORIGIN attribute of the aggregated
7667 route is INTERNAL. */
7668 origin = BGP_ORIGIN_IGP;
718e3744 7669
d62a17ae 7670 table = bgp->rib[afi][safi];
718e3744 7671
d62a17ae 7672 top = bgp_node_get(table, p);
9bcb3eef
DS
7673 for (dest = bgp_node_get(table, p); dest;
7674 dest = bgp_route_next_until(dest, top)) {
7675 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7676
9bcb3eef 7677 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7678 continue;
d62a17ae 7679
a77e2f4b
S
7680 /* If suppress fib is enabled and route not installed
7681 * in FIB, skip the route
7682 */
7683 if (!bgp_check_advertise(bgp, dest))
7684 continue;
7685
c2ff8b3e 7686 match = 0;
d62a17ae 7687
9bcb3eef 7688 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7689 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7690 continue;
718e3744 7691
40381db7 7692 if (pi->attr->flag
c2ff8b3e
DS
7693 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7694 atomic_aggregate = 1;
d62a17ae 7695
40381db7 7696 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7697 continue;
d62a17ae 7698
f273fef1
DS
7699 /*
7700 * summary-only aggregate route suppress
7701 * aggregated route announcements.
6aabb15d
RZ
7702 *
7703 * MED matching:
7704 * Don't create summaries if MED didn't match
7705 * otherwise neither the specific routes and the
7706 * aggregation will be announced.
f273fef1 7707 */
6aabb15d
RZ
7708 if (aggregate->summary_only
7709 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7710 if (aggr_suppress_path(aggregate, pi))
7711 match++;
d62a17ae 7712 }
c2ff8b3e 7713
365ab2e7
RZ
7714 /*
7715 * Suppress more specific routes that match the route
7716 * map results.
7717 *
7718 * MED matching:
7719 * Don't suppress routes if MED matching is enabled and
7720 * it mismatched otherwise we might end up with no
7721 * routes for this path.
7722 */
7723 if (aggregate->suppress_map_name
7724 && AGGREGATE_MED_VALID(aggregate)
7725 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7726 if (aggr_suppress_path(aggregate, pi))
7727 match++;
d62a17ae 7728 }
c2ff8b3e
DS
7729
7730 aggregate->count++;
7731
f273fef1
DS
7732 /*
7733 * If at least one route among routes that are
7734 * aggregated has ORIGIN with the value INCOMPLETE,
7735 * then the aggregated route MUST have the ORIGIN
7736 * attribute with the value INCOMPLETE. Otherwise, if
7737 * at least one route among routes that are aggregated
7738 * has ORIGIN with the value EGP, then the aggregated
7739 * route MUST have the ORIGIN attribute with the value
7740 * EGP.
7741 */
fc968841
NT
7742 switch (pi->attr->origin) {
7743 case BGP_ORIGIN_INCOMPLETE:
7744 aggregate->incomplete_origin_count++;
7745 break;
7746 case BGP_ORIGIN_EGP:
7747 aggregate->egp_origin_count++;
7748 break;
7749 default:
7750 /*Do nothing.
7751 */
7752 break;
7753 }
c2ff8b3e
DS
7754
7755 if (!aggregate->as_set)
7756 continue;
7757
f273fef1
DS
7758 /*
7759 * as-set aggregate route generate origin, as path,
7760 * and community aggregation.
7761 */
fc968841
NT
7762 /* Compute aggregate route's as-path.
7763 */
ef51a7d8 7764 bgp_compute_aggregate_aspath_hash(aggregate,
7765 pi->attr->aspath);
c2ff8b3e 7766
fc968841
NT
7767 /* Compute aggregate route's community.
7768 */
9a706b42 7769 if (bgp_attr_get_community(pi->attr))
21fec674 7770 bgp_compute_aggregate_community_hash(
9a706b42
DA
7771 aggregate,
7772 bgp_attr_get_community(pi->attr));
dd18c5a9 7773
fc968841
NT
7774 /* Compute aggregate route's extended community.
7775 */
b53e67a3 7776 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7777 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7778 aggregate,
7779 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7780
7781 /* Compute aggregate route's large community.
7782 */
1bcf3a96 7783 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7784 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7785 aggregate,
7786 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7787 }
c2ff8b3e 7788 if (match)
9bcb3eef 7789 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7790 }
21fec674 7791 if (aggregate->as_set) {
ef51a7d8 7792 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7793 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7794 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7795 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7796 }
7797
f1eb1f05 7798
9bcb3eef 7799 bgp_dest_unlock_node(top);
718e3744 7800
718e3744 7801
fc968841
NT
7802 if (aggregate->incomplete_origin_count > 0)
7803 origin = BGP_ORIGIN_INCOMPLETE;
7804 else if (aggregate->egp_origin_count > 0)
7805 origin = BGP_ORIGIN_EGP;
d62a17ae 7806
229757f1
DA
7807 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7808 origin = aggregate->origin;
7809
fc968841
NT
7810 if (aggregate->as_set) {
7811 if (aggregate->aspath)
7812 /* Retrieve aggregate route's as-path.
7813 */
7814 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7815
fc968841
NT
7816 if (aggregate->community)
7817 /* Retrieve aggregate route's community.
7818 */
7819 community = community_dup(aggregate->community);
3da2cc32 7820
fc968841
NT
7821 if (aggregate->ecommunity)
7822 /* Retrieve aggregate route's ecommunity.
7823 */
7824 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7825
fc968841
NT
7826 if (aggregate->lcommunity)
7827 /* Retrieve aggregate route's lcommunity.
7828 */
7829 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7830 }
718e3744 7831
c701010e 7832 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7833 ecommunity, lcommunity, atomic_aggregate,
7834 aggregate);
718e3744 7835}
7836
5f040085
DS
7837void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7838 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7839{
7840 struct bgp_table *table;
9bcb3eef
DS
7841 struct bgp_dest *top;
7842 struct bgp_dest *dest;
40381db7 7843 struct bgp_path_info *pi;
3b7db173
DS
7844 unsigned long match;
7845
7846 table = bgp->rib[afi][safi];
7847
7848 /* If routes exists below this node, generate aggregate routes. */
7849 top = bgp_node_get(table, p);
9bcb3eef
DS
7850 for (dest = bgp_node_get(table, p); dest;
7851 dest = bgp_route_next_until(dest, top)) {
7852 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7853
9bcb3eef 7854 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7855 continue;
7856 match = 0;
7857
9bcb3eef 7858 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7859 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7860 continue;
7861
40381db7 7862 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7863 continue;
7864
92b175bd
RZ
7865 /*
7866 * This route is suppressed: attempt to unsuppress it.
7867 *
7868 * `aggr_unsuppress_path` will fail if this particular
7869 * aggregate route was not the suppressor.
7870 */
7871 if (pi->extra && pi->extra->aggr_suppressors &&
7872 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7873 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7874 match++;
3b7db173 7875 }
365ab2e7 7876
3b7db173 7877 aggregate->count--;
fc968841
NT
7878
7879 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7880 aggregate->incomplete_origin_count--;
7881 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7882 aggregate->egp_origin_count--;
7883
7884 if (aggregate->as_set) {
7885 /* Remove as-path from aggregate.
7886 */
ef51a7d8 7887 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7888 aggregate,
7889 pi->attr->aspath);
7890
9a706b42 7891 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7892 /* Remove community from aggregate.
7893 */
21fec674 7894 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7895 aggregate,
7896 bgp_attr_get_community(
7897 pi->attr));
fc968841 7898
b53e67a3 7899 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7900 /* Remove ecommunity from aggregate.
7901 */
4edd83f9 7902 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7903 aggregate,
7904 bgp_attr_get_ecommunity(
7905 pi->attr));
fc968841 7906
1bcf3a96 7907 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7908 /* Remove lcommunity from aggregate.
7909 */
f1eb1f05 7910 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7911 aggregate,
7912 bgp_attr_get_lcommunity(
7913 pi->attr));
fc968841 7914 }
3b7db173
DS
7915 }
7916
7917 /* If this node was suppressed, process the change. */
7918 if (match)
9bcb3eef 7919 bgp_process(bgp, dest, afi, safi);
3b7db173 7920 }
f1eb1f05 7921 if (aggregate->as_set) {
ef51a7d8 7922 aspath_free(aggregate->aspath);
7923 aggregate->aspath = NULL;
21fec674 7924 if (aggregate->community)
7925 community_free(&aggregate->community);
4edd83f9 7926 if (aggregate->ecommunity)
7927 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7928 if (aggregate->lcommunity)
7929 lcommunity_free(&aggregate->lcommunity);
7930 }
7931
9bcb3eef 7932 bgp_dest_unlock_node(top);
3b7db173 7933}
718e3744 7934
5f040085
DS
7935static void bgp_add_route_to_aggregate(struct bgp *bgp,
7936 const struct prefix *aggr_p,
fc968841
NT
7937 struct bgp_path_info *pinew, afi_t afi,
7938 safi_t safi,
7939 struct bgp_aggregate *aggregate)
7940{
7941 uint8_t origin;
7942 struct aspath *aspath = NULL;
7943 uint8_t atomic_aggregate = 0;
7944 struct community *community = NULL;
7945 struct ecommunity *ecommunity = NULL;
7946 struct lcommunity *lcommunity = NULL;
7947
a4559740 7948 /* If the bgp instance is being deleted or self peer is deleted
7949 * then do not create aggregate route
7950 */
7951 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7952 || (bgp->peer_self == NULL))
7953 return;
7954
fc968841
NT
7955 /* ORIGIN attribute: If at least one route among routes that are
7956 * aggregated has ORIGIN with the value INCOMPLETE, then the
7957 * aggregated route must have the ORIGIN attribute with the value
7958 * INCOMPLETE. Otherwise, if at least one route among routes that
7959 * are aggregated has ORIGIN with the value EGP, then the aggregated
7960 * route must have the origin attribute with the value EGP. In all
7961 * other case the value of the ORIGIN attribute of the aggregated
7962 * route is INTERNAL.
7963 */
7964 origin = BGP_ORIGIN_IGP;
7965
7966 aggregate->count++;
7967
6aabb15d
RZ
7968 /*
7969 * This must be called before `summary` check to avoid
7970 * "suppressing" twice.
7971 */
7972 if (aggregate->match_med)
7973 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 7974 pinew);
6aabb15d
RZ
7975
7976 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7977 aggr_suppress_path(aggregate, pinew);
fc968841 7978
365ab2e7
RZ
7979 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7980 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7981 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7982
7983 switch (pinew->attr->origin) {
7984 case BGP_ORIGIN_INCOMPLETE:
7985 aggregate->incomplete_origin_count++;
7986 break;
7987 case BGP_ORIGIN_EGP:
7988 aggregate->egp_origin_count++;
7989 break;
7990 default:
7991 /* Do nothing.
7992 */
7993 break;
7994 }
7995
7996 if (aggregate->incomplete_origin_count > 0)
7997 origin = BGP_ORIGIN_INCOMPLETE;
7998 else if (aggregate->egp_origin_count > 0)
7999 origin = BGP_ORIGIN_EGP;
8000
229757f1
DA
8001 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8002 origin = aggregate->origin;
8003
fc968841
NT
8004 if (aggregate->as_set) {
8005 /* Compute aggregate route's as-path.
8006 */
8007 bgp_compute_aggregate_aspath(aggregate,
8008 pinew->attr->aspath);
8009
8010 /* Compute aggregate route's community.
8011 */
9a706b42 8012 if (bgp_attr_get_community(pinew->attr))
fc968841 8013 bgp_compute_aggregate_community(
9a706b42 8014 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8015
8016 /* Compute aggregate route's extended community.
8017 */
b53e67a3 8018 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8019 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8020 aggregate,
8021 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8022
8023 /* Compute aggregate route's large community.
8024 */
1bcf3a96 8025 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8026 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8027 aggregate,
8028 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8029
8030 /* Retrieve aggregate route's as-path.
8031 */
8032 if (aggregate->aspath)
8033 aspath = aspath_dup(aggregate->aspath);
8034
8035 /* Retrieve aggregate route's community.
8036 */
8037 if (aggregate->community)
8038 community = community_dup(aggregate->community);
8039
8040 /* Retrieve aggregate route's ecommunity.
8041 */
8042 if (aggregate->ecommunity)
8043 ecommunity = ecommunity_dup(aggregate->ecommunity);
8044
8045 /* Retrieve aggregate route's lcommunity.
8046 */
8047 if (aggregate->lcommunity)
8048 lcommunity = lcommunity_dup(aggregate->lcommunity);
8049 }
8050
8051 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8052 aspath, community, ecommunity,
8053 lcommunity, atomic_aggregate, aggregate);
8054}
8055
8056static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8057 safi_t safi,
8058 struct bgp_path_info *pi,
8059 struct bgp_aggregate *aggregate,
5f040085 8060 const struct prefix *aggr_p)
fc968841
NT
8061{
8062 uint8_t origin;
8063 struct aspath *aspath = NULL;
8064 uint8_t atomic_aggregate = 0;
8065 struct community *community = NULL;
8066 struct ecommunity *ecommunity = NULL;
8067 struct lcommunity *lcommunity = NULL;
8068 unsigned long match = 0;
8069
a4559740 8070 /* If the bgp instance is being deleted or self peer is deleted
8071 * then do not create aggregate route
8072 */
8073 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8074 || (bgp->peer_self == NULL))
8075 return;
8076
fc968841
NT
8077 if (BGP_PATH_HOLDDOWN(pi))
8078 return;
8079
8080 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8081 return;
8082
4056a5f6
RZ
8083 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8084 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8085 match++;
fc968841 8086
365ab2e7 8087 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8088 && aggr_suppress_map_test(bgp, aggregate, pi))
8089 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8090 match++;
fc968841 8091
6aabb15d 8092 /*
365ab2e7 8093 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8094 * "unsuppressing" twice.
8095 */
8096 if (aggregate->match_med)
f66624f5 8097 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8098
fc968841
NT
8099 if (aggregate->count > 0)
8100 aggregate->count--;
8101
8102 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8103 aggregate->incomplete_origin_count--;
8104 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8105 aggregate->egp_origin_count--;
8106
8107 if (aggregate->as_set) {
8108 /* Remove as-path from aggregate.
8109 */
8110 bgp_remove_aspath_from_aggregate(aggregate,
8111 pi->attr->aspath);
8112
9a706b42 8113 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8114 /* Remove community from aggregate.
8115 */
8116 bgp_remove_community_from_aggregate(
9a706b42 8117 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8118
b53e67a3 8119 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8120 /* Remove ecommunity from aggregate.
8121 */
8122 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8123 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8124
1bcf3a96 8125 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8126 /* Remove lcommunity from aggregate.
8127 */
8128 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8129 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8130 }
8131
8132 /* If this node was suppressed, process the change. */
8133 if (match)
8134 bgp_process(bgp, pi->net, afi, safi);
8135
8136 origin = BGP_ORIGIN_IGP;
8137 if (aggregate->incomplete_origin_count > 0)
8138 origin = BGP_ORIGIN_INCOMPLETE;
8139 else if (aggregate->egp_origin_count > 0)
8140 origin = BGP_ORIGIN_EGP;
8141
229757f1
DA
8142 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8143 origin = aggregate->origin;
8144
fc968841
NT
8145 if (aggregate->as_set) {
8146 /* Retrieve aggregate route's as-path.
8147 */
8148 if (aggregate->aspath)
8149 aspath = aspath_dup(aggregate->aspath);
8150
8151 /* Retrieve aggregate route's community.
8152 */
8153 if (aggregate->community)
8154 community = community_dup(aggregate->community);
8155
8156 /* Retrieve aggregate route's ecommunity.
8157 */
8158 if (aggregate->ecommunity)
8159 ecommunity = ecommunity_dup(aggregate->ecommunity);
8160
8161 /* Retrieve aggregate route's lcommunity.
8162 */
8163 if (aggregate->lcommunity)
8164 lcommunity = lcommunity_dup(aggregate->lcommunity);
8165 }
8166
8167 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8168 aspath, community, ecommunity,
8169 lcommunity, atomic_aggregate, aggregate);
8170}
8171
5a1ae2c2 8172void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8173 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8174{
9bcb3eef
DS
8175 struct bgp_dest *child;
8176 struct bgp_dest *dest;
d62a17ae 8177 struct bgp_aggregate *aggregate;
8178 struct bgp_table *table;
718e3744 8179
d62a17ae 8180 table = bgp->aggregate[afi][safi];
f018db83 8181
d62a17ae 8182 /* No aggregates configured. */
8183 if (bgp_table_top_nolock(table) == NULL)
8184 return;
f018db83 8185
d62a17ae 8186 if (p->prefixlen == 0)
8187 return;
718e3744 8188
40381db7 8189 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8190 return;
718e3744 8191
a77e2f4b
S
8192 /* If suppress fib is enabled and route not installed
8193 * in FIB, do not update the aggregate route
8194 */
8195 if (!bgp_check_advertise(bgp, pi->net))
8196 return;
8197
d62a17ae 8198 child = bgp_node_get(table, p);
718e3744 8199
d62a17ae 8200 /* Aggregate address configuration check. */
9bcb3eef
DS
8201 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8202 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8203
9bcb3eef
DS
8204 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8205 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8206 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8207 aggregate);
d62a17ae 8208 }
b1e62edd 8209 }
9bcb3eef 8210 bgp_dest_unlock_node(child);
718e3744 8211}
8212
5a1ae2c2 8213void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8214 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8215{
9bcb3eef
DS
8216 struct bgp_dest *child;
8217 struct bgp_dest *dest;
d62a17ae 8218 struct bgp_aggregate *aggregate;
8219 struct bgp_table *table;
718e3744 8220
d62a17ae 8221 table = bgp->aggregate[afi][safi];
718e3744 8222
d62a17ae 8223 /* No aggregates configured. */
8224 if (bgp_table_top_nolock(table) == NULL)
8225 return;
718e3744 8226
d62a17ae 8227 if (p->prefixlen == 0)
8228 return;
718e3744 8229
d62a17ae 8230 child = bgp_node_get(table, p);
718e3744 8231
d62a17ae 8232 /* Aggregate address configuration check. */
9bcb3eef
DS
8233 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8234 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8235
9bcb3eef
DS
8236 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8237 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8238 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8239 aggregate, dest_p);
d62a17ae 8240 }
b1e62edd 8241 }
9bcb3eef 8242 bgp_dest_unlock_node(child);
d62a17ae 8243}
718e3744 8244
718e3744 8245/* Aggregate route attribute. */
8246#define AGGREGATE_SUMMARY_ONLY 1
8247#define AGGREGATE_AS_SET 1
fb29348a 8248#define AGGREGATE_AS_UNSET 0
718e3744 8249
229757f1
DA
8250static const char *bgp_origin2str(uint8_t origin)
8251{
8252 switch (origin) {
8253 case BGP_ORIGIN_IGP:
8254 return "igp";
8255 case BGP_ORIGIN_EGP:
8256 return "egp";
8257 case BGP_ORIGIN_INCOMPLETE:
8258 return "incomplete";
8259 }
8260 return "n/a";
8261}
8262
fdeb5a81 8263static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8264{
8265 switch (v_state) {
fdeb5a81
DS
8266 case RPKI_NOT_BEING_USED:
8267 return "not used";
8268 case RPKI_VALID:
b5b99af8 8269 return "valid";
fdeb5a81 8270 case RPKI_NOTFOUND:
b5b99af8 8271 return "not found";
fdeb5a81 8272 case RPKI_INVALID:
b5b99af8 8273 return "invalid";
b5b99af8 8274 }
fdeb5a81
DS
8275
8276 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8277 return "ERROR";
8278}
8279
585f1adc
IR
8280static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8281 afi_t afi, safi_t safi)
718e3744 8282{
585f1adc
IR
8283 VTY_DECLVAR_CONTEXT(bgp, bgp);
8284 int ret;
8285 struct prefix p;
9bcb3eef 8286 struct bgp_dest *dest;
d62a17ae 8287 struct bgp_aggregate *aggregate;
718e3744 8288
585f1adc
IR
8289 /* Convert string to prefix structure. */
8290 ret = str2prefix(prefix_str, &p);
8291 if (!ret) {
8292 vty_out(vty, "Malformed prefix\n");
8293 return CMD_WARNING_CONFIG_FAILED;
8294 }
8295 apply_mask(&p);
a4559740 8296
d62a17ae 8297 /* Old configuration check. */
585f1adc 8298 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8299 if (!dest) {
585f1adc
IR
8300 vty_out(vty,
8301 "%% There is no aggregate-address configuration.\n");
8302 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8303 }
f6269b4f 8304
9bcb3eef 8305 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8306 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8307 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8308 NULL, NULL, 0, aggregate);
d62a17ae 8309
8310 /* Unlock aggregate address configuration. */
9bcb3eef 8311 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8312
8313 if (aggregate->community)
8314 community_free(&aggregate->community);
8315
8316 if (aggregate->community_hash) {
8317 /* Delete all communities in the hash.
8318 */
8319 hash_clean(aggregate->community_hash,
8320 bgp_aggr_community_remove);
8321 /* Free up the community_hash.
8322 */
8323 hash_free(aggregate->community_hash);
8324 }
8325
8326 if (aggregate->ecommunity)
8327 ecommunity_free(&aggregate->ecommunity);
8328
8329 if (aggregate->ecommunity_hash) {
8330 /* Delete all ecommunities in the hash.
8331 */
8332 hash_clean(aggregate->ecommunity_hash,
8333 bgp_aggr_ecommunity_remove);
8334 /* Free up the ecommunity_hash.
8335 */
8336 hash_free(aggregate->ecommunity_hash);
8337 }
8338
8339 if (aggregate->lcommunity)
8340 lcommunity_free(&aggregate->lcommunity);
8341
8342 if (aggregate->lcommunity_hash) {
8343 /* Delete all lcommunities in the hash.
8344 */
8345 hash_clean(aggregate->lcommunity_hash,
8346 bgp_aggr_lcommunity_remove);
8347 /* Free up the lcommunity_hash.
8348 */
8349 hash_free(aggregate->lcommunity_hash);
8350 }
8351
8352 if (aggregate->aspath)
8353 aspath_free(aggregate->aspath);
8354
8355 if (aggregate->aspath_hash) {
8356 /* Delete all as-paths in the hash.
8357 */
8358 hash_clean(aggregate->aspath_hash,
8359 bgp_aggr_aspath_remove);
8360 /* Free up the aspath_hash.
8361 */
8362 hash_free(aggregate->aspath_hash);
8363 }
8364
d62a17ae 8365 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8366 bgp_dest_unlock_node(dest);
8367 bgp_dest_unlock_node(dest);
d62a17ae 8368
585f1adc 8369 return CMD_SUCCESS;
d62a17ae 8370}
8371
585f1adc
IR
8372static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8373 safi_t safi, const char *rmap,
8374 uint8_t summary_only, uint8_t as_set,
8375 uint8_t origin, bool match_med,
8376 const char *suppress_map)
d62a17ae 8377{
585f1adc 8378 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8379 int ret;
585f1adc 8380 struct prefix p;
9bcb3eef 8381 struct bgp_dest *dest;
d62a17ae 8382 struct bgp_aggregate *aggregate;
fb29348a 8383 uint8_t as_set_new = as_set;
d62a17ae 8384
365ab2e7 8385 if (suppress_map && summary_only) {
585f1adc 8386 vty_out(vty,
365ab2e7 8387 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8388 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8389 }
8390
585f1adc
IR
8391 /* Convert string to prefix structure. */
8392 ret = str2prefix(prefix_str, &p);
8393 if (!ret) {
8394 vty_out(vty, "Malformed prefix\n");
8395 return CMD_WARNING_CONFIG_FAILED;
8396 }
8397 apply_mask(&p);
d62a17ae 8398
585f1adc
IR
8399 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8400 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8401 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8402 prefix_str);
8403 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8404 }
8405
d62a17ae 8406 /* Old configuration check. */
585f1adc 8407 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8408 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8409
20894f50 8410 if (aggregate) {
585f1adc 8411 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8412 /* try to remove the old entry */
585f1adc 8413 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8414 if (ret) {
585f1adc 8415 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8416 bgp_dest_unlock_node(dest);
585f1adc 8417 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8418 }
8419 }
718e3744 8420
d62a17ae 8421 /* Make aggregate address structure. */
8422 aggregate = bgp_aggregate_new();
8423 aggregate->summary_only = summary_only;
6aabb15d 8424 aggregate->match_med = match_med;
fb29348a
DA
8425
8426 /* Network operators MUST NOT locally generate any new
8427 * announcements containing AS_SET or AS_CONFED_SET. If they have
8428 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8429 * SHOULD withdraw those routes and re-announce routes for the
8430 * aggregate or component prefixes (i.e., the more-specific routes
8431 * subsumed by the previously aggregated route) without AS_SET
8432 * or AS_CONFED_SET in the updates.
8433 */
7f972cd8 8434 if (bgp->reject_as_sets) {
fb29348a
DA
8435 if (as_set == AGGREGATE_AS_SET) {
8436 as_set_new = AGGREGATE_AS_UNSET;
8437 zlog_warn(
63efca0e 8438 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8439 __func__);
585f1adc 8440 vty_out(vty,
fb29348a
DA
8441 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8442 }
8443 }
8444
8445 aggregate->as_set = as_set_new;
d62a17ae 8446 aggregate->safi = safi;
229757f1
DA
8447 /* Override ORIGIN attribute if defined.
8448 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8449 * to IGP which is not what rfc4271 says.
8450 * This enables the same behavior, optionally.
8451 */
8452 aggregate->origin = origin;
20894f50
DA
8453
8454 if (rmap) {
8455 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8456 route_map_counter_decrement(aggregate->rmap.map);
8457 aggregate->rmap.name =
8458 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8459 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8460 route_map_counter_increment(aggregate->rmap.map);
8461 }
365ab2e7
RZ
8462
8463 if (suppress_map) {
8464 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8465 route_map_counter_decrement(aggregate->suppress_map);
8466
8467 aggregate->suppress_map_name =
8468 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8469 aggregate->suppress_map =
8470 route_map_lookup_by_name(aggregate->suppress_map_name);
8471 route_map_counter_increment(aggregate->suppress_map);
8472 }
8473
9bcb3eef 8474 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8475
d62a17ae 8476 /* Aggregate address insert into BGP routing table. */
585f1adc 8477 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8478
585f1adc 8479 return CMD_SUCCESS;
718e3744 8480}
8481
585f1adc
IR
8482DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8483 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8484 "as-set$as_set_s"
8485 "|summary-only$summary_only"
cacba915 8486 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8487 "|origin <egp|igp|incomplete>$origin_s"
8488 "|matching-MED-only$match_med"
cacba915 8489 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8490 "}]",
8491 NO_STR
8492 "Configure BGP aggregate entries\n"
764402fe
DA
8493 "Aggregate prefix\n"
8494 "Aggregate address\n"
8495 "Aggregate mask\n"
585f1adc
IR
8496 "Generate AS set path information\n"
8497 "Filter more specific routes from updates\n"
8498 "Apply route map to aggregate network\n"
8499 "Route map name\n"
8500 "BGP origin code\n"
8501 "Remote EGP\n"
8502 "Local IGP\n"
8503 "Unknown heritage\n"
8504 "Only aggregate routes with matching MED\n"
8505 "Suppress the selected more specific routes\n"
8506 "Route map with the route selectors\n")
8507{
8508 const char *prefix_s = NULL;
554b3b10 8509 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8510 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8511 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8512 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8513
554b3b10 8514 if (addr_str) {
7533cad7
QY
8515 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8516 sizeof(prefix_buf))
554b3b10
RZ
8517 == 0) {
8518 vty_out(vty, "%% Inconsistent address and mask\n");
8519 return CMD_WARNING_CONFIG_FAILED;
8520 }
585f1adc
IR
8521 prefix_s = prefix_buf;
8522 } else
8523 prefix_s = prefix_str;
37a87b8f 8524
585f1adc
IR
8525 if (origin_s) {
8526 if (strcmp(origin_s, "egp") == 0)
8527 origin = BGP_ORIGIN_EGP;
8528 else if (strcmp(origin_s, "igp") == 0)
8529 origin = BGP_ORIGIN_IGP;
8530 else if (strcmp(origin_s, "incomplete") == 0)
8531 origin = BGP_ORIGIN_INCOMPLETE;
8532 }
90e21f35 8533
585f1adc
IR
8534 if (as_set_s)
8535 as_set = AGGREGATE_AS_SET;
554b3b10 8536
585f1adc 8537 /* Handle configuration removal, otherwise installation. */
554b3b10 8538 if (no)
585f1adc
IR
8539 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8540
8541 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8542 summary_only != NULL, as_set, origin,
8543 match_med != NULL, suppress_map);
8544}
8545
8546DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8547 "[no] aggregate-address X:X::X:X/M$prefix [{"
8548 "as-set$as_set_s"
8549 "|summary-only$summary_only"
cacba915 8550 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8551 "|origin <egp|igp|incomplete>$origin_s"
8552 "|matching-MED-only$match_med"
cacba915 8553 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8554 "}]",
8555 NO_STR
8556 "Configure BGP aggregate entries\n"
8557 "Aggregate prefix\n"
8558 "Generate AS set path information\n"
8559 "Filter more specific routes from updates\n"
8560 "Apply route map to aggregate network\n"
8561 "Route map name\n"
8562 "BGP origin code\n"
8563 "Remote EGP\n"
8564 "Local IGP\n"
8565 "Unknown heritage\n"
8566 "Only aggregate routes with matching MED\n"
8567 "Suppress the selected more specific routes\n"
8568 "Route map with the route selectors\n")
8569{
8570 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8571 int as_set = AGGREGATE_AS_UNSET;
8572
8573 if (origin_s) {
8574 if (strcmp(origin_s, "egp") == 0)
8575 origin = BGP_ORIGIN_EGP;
8576 else if (strcmp(origin_s, "igp") == 0)
8577 origin = BGP_ORIGIN_IGP;
8578 else if (strcmp(origin_s, "incomplete") == 0)
8579 origin = BGP_ORIGIN_INCOMPLETE;
8580 }
8581
8582 if (as_set_s)
8583 as_set = AGGREGATE_AS_SET;
8584
8585 /* Handle configuration removal, otherwise installation. */
554b3b10 8586 if (no)
585f1adc
IR
8587 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8588 SAFI_UNICAST);
554b3b10 8589
585f1adc
IR
8590 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8591 rmap_name, summary_only != NULL, as_set,
8592 origin, match_med != NULL, suppress_map);
718e3744 8593}
8594
718e3744 8595/* Redistribute route treatment. */
d62a17ae 8596void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8597 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8598 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8599 enum blackhole_type bhtype, uint32_t metric,
8600 uint8_t type, unsigned short instance,
8601 route_tag_t tag)
d62a17ae 8602{
4b7e6066 8603 struct bgp_path_info *new;
40381db7
DS
8604 struct bgp_path_info *bpi;
8605 struct bgp_path_info rmap_path;
9bcb3eef 8606 struct bgp_dest *bn;
d62a17ae 8607 struct attr attr;
8608 struct attr *new_attr;
8609 afi_t afi;
b68885f9 8610 route_map_result_t ret;
d62a17ae 8611 struct bgp_redist *red;
8612
8613 /* Make default attribute. */
0f05ea43 8614 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8615 /*
8616 * This must not be NULL to satisfy Coverity SA
8617 */
8618 assert(attr.aspath);
9de1f7ff 8619
a4d82a8a 8620 switch (nhtype) {
9de1f7ff 8621 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8622 switch (p->family) {
8623 case AF_INET:
8624 attr.nexthop.s_addr = INADDR_ANY;
8625 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8626 break;
8627 case AF_INET6:
8628 memset(&attr.mp_nexthop_global, 0,
8629 sizeof(attr.mp_nexthop_global));
8630 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8631 break;
8632 }
9de1f7ff
DS
8633 break;
8634 case NEXTHOP_TYPE_IPV4:
8635 case NEXTHOP_TYPE_IPV4_IFINDEX:
8636 attr.nexthop = nexthop->ipv4;
7226bc40 8637 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8638 break;
8639 case NEXTHOP_TYPE_IPV6:
8640 case NEXTHOP_TYPE_IPV6_IFINDEX:
8641 attr.mp_nexthop_global = nexthop->ipv6;
8642 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8643 break;
8644 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8645 switch (p->family) {
8646 case AF_INET:
9de1f7ff 8647 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8648 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8649 break;
8650 case AF_INET6:
9de1f7ff
DS
8651 memset(&attr.mp_nexthop_global, 0,
8652 sizeof(attr.mp_nexthop_global));
74489921 8653 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8654 break;
74489921 8655 }
0789eb69 8656 attr.bh_type = bhtype;
9de1f7ff 8657 break;
d62a17ae 8658 }
0789eb69 8659 attr.nh_type = nhtype;
74489921 8660 attr.nh_ifindex = ifindex;
f04a80a5 8661
d62a17ae 8662 attr.med = metric;
957f74c3 8663 attr.distance = distance;
d62a17ae 8664 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8665 attr.tag = tag;
718e3744 8666
97a52c82
DA
8667 if (metric)
8668 bgp_attr_set_aigp_metric(&attr, metric);
8669
d62a17ae 8670 afi = family2afi(p->family);
6aeb9e78 8671
d62a17ae 8672 red = bgp_redist_lookup(bgp, afi, type, instance);
8673 if (red) {
8674 struct attr attr_new;
718e3744 8675
d62a17ae 8676 /* Copy attribute for modification. */
6f4f49b2 8677 attr_new = attr;
718e3744 8678
97a52c82 8679 if (red->redist_metric_flag) {
d62a17ae 8680 attr_new.med = red->redist_metric;
97a52c82
DA
8681 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8682 }
718e3744 8683
d62a17ae 8684 /* Apply route-map. */
8685 if (red->rmap.name) {
6006b807 8686 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8687 rmap_path.peer = bgp->peer_self;
8688 rmap_path.attr = &attr_new;
718e3744 8689
d62a17ae 8690 SET_FLAG(bgp->peer_self->rmap_type,
8691 PEER_RMAP_TYPE_REDISTRIBUTE);
8692
1782514f 8693 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8694
8695 bgp->peer_self->rmap_type = 0;
8696
8697 if (ret == RMAP_DENYMATCH) {
8698 /* Free uninterned attribute. */
8699 bgp_attr_flush(&attr_new);
8700
8701 /* Unintern original. */
8702 aspath_unintern(&attr.aspath);
8703 bgp_redistribute_delete(bgp, p, type, instance);
8704 return;
8705 }
8706 }
8707
637e5ba4 8708 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8709 bgp_attr_add_gshut_community(&attr_new);
8710
d62a17ae 8711 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8712 SAFI_UNICAST, p, NULL);
8713
8714 new_attr = bgp_attr_intern(&attr_new);
8715
9bcb3eef 8716 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8717 if (bpi->peer == bgp->peer_self
8718 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8719 break;
8720
40381db7 8721 if (bpi) {
d62a17ae 8722 /* Ensure the (source route) type is updated. */
40381db7
DS
8723 bpi->type = type;
8724 if (attrhash_cmp(bpi->attr, new_attr)
8725 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8726 bgp_attr_unintern(&new_attr);
8727 aspath_unintern(&attr.aspath);
9bcb3eef 8728 bgp_dest_unlock_node(bn);
d62a17ae 8729 return;
8730 } else {
8731 /* The attribute is changed. */
40381db7 8732 bgp_path_info_set_flag(bn, bpi,
18ee8310 8733 BGP_PATH_ATTR_CHANGED);
d62a17ae 8734
8735 /* Rewrite BGP route information. */
40381db7
DS
8736 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8737 bgp_path_info_restore(bn, bpi);
d62a17ae 8738 else
40381db7
DS
8739 bgp_aggregate_decrement(
8740 bgp, p, bpi, afi, SAFI_UNICAST);
8741 bgp_attr_unintern(&bpi->attr);
8742 bpi->attr = new_attr;
083ec940 8743 bpi->uptime = monotime(NULL);
d62a17ae 8744
8745 /* Process change. */
40381db7 8746 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8747 SAFI_UNICAST);
8748 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8749 bgp_dest_unlock_node(bn);
d62a17ae 8750 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8751
8752 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8753 || (bgp->inst_type
8754 == BGP_INSTANCE_TYPE_DEFAULT)) {
8755
8756 vpn_leak_from_vrf_update(
40381db7 8757 bgp_get_default(), bgp, bpi);
ddb5b488 8758 }
d62a17ae 8759 return;
8760 }
8761 }
8762
8763 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8764 bgp->peer_self, new_attr, bn);
1defdda8 8765 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8766
8767 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8768 bgp_path_info_add(bn, new);
9bcb3eef 8769 bgp_dest_unlock_node(bn);
be785e35 8770 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8771 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8772
8773 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8774 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8775
8776 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8777 }
d62a17ae 8778 }
8779
8780 /* Unintern original. */
8781 aspath_unintern(&attr.aspath);
718e3744 8782}
8783
d7c0a89a
QY
8784void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8785 unsigned short instance)
718e3744 8786{
d62a17ae 8787 afi_t afi;
9bcb3eef 8788 struct bgp_dest *dest;
40381db7 8789 struct bgp_path_info *pi;
d62a17ae 8790 struct bgp_redist *red;
718e3744 8791
d62a17ae 8792 afi = family2afi(p->family);
718e3744 8793
d62a17ae 8794 red = bgp_redist_lookup(bgp, afi, type, instance);
8795 if (red) {
9bcb3eef
DS
8796 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8797 SAFI_UNICAST, p, NULL);
d62a17ae 8798
9bcb3eef 8799 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8800 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8801 break;
8802
40381db7 8803 if (pi) {
ddb5b488
PZ
8804 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8805 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8806
8807 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8808 bgp, pi);
ddb5b488 8809 }
40381db7 8810 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8811 bgp_path_info_delete(dest, pi);
8812 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8813 }
9bcb3eef 8814 bgp_dest_unlock_node(dest);
d62a17ae 8815 }
8816}
8817
8818/* Withdraw specified route type's route. */
8819void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8820 unsigned short instance)
d62a17ae 8821{
9bcb3eef 8822 struct bgp_dest *dest;
40381db7 8823 struct bgp_path_info *pi;
d62a17ae 8824 struct bgp_table *table;
8825
8826 table = bgp->rib[afi][SAFI_UNICAST];
8827
9bcb3eef
DS
8828 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8829 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8830 if (pi->peer == bgp->peer_self && pi->type == type
8831 && pi->instance == instance)
d62a17ae 8832 break;
8833
40381db7 8834 if (pi) {
ddb5b488
PZ
8835 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8836 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8837
8838 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8839 bgp, pi);
ddb5b488 8840 }
9bcb3eef 8841 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8842 pi, afi, SAFI_UNICAST);
9bcb3eef 8843 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8844 if (!CHECK_FLAG(bgp->flags,
8845 BGP_FLAG_DELETE_IN_PROGRESS))
8846 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8847 else
8848 bgp_path_info_reap(dest, pi);
d62a17ae 8849 }
718e3744 8850 }
718e3744 8851}
6b0655a2 8852
718e3744 8853/* Static function to display route. */
7d3cae70
DA
8854static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8855 struct vty *vty, json_object *json, bool wide)
718e3744 8856{
be054588 8857 int len = 0;
07380148 8858 char buf[INET6_ADDRSTRLEN];
718e3744 8859
d62a17ae 8860 if (p->family == AF_INET) {
c6462ff4 8861 if (!json) {
8228a9a7 8862 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8863 } else {
8864 json_object_string_add(json, "prefix",
8865 inet_ntop(p->family,
8866 &p->u.prefix, buf,
07380148 8867 sizeof(buf)));
c6462ff4 8868 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8869 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8870 json_object_int_add(json, "version", dest->version);
c6462ff4 8871 }
d62a17ae 8872 } else if (p->family == AF_ETHERNET) {
8228a9a7 8873 len = vty_out(vty, "%pFX", p);
b03b8898 8874 } else if (p->family == AF_EVPN) {
57f7feb6 8875 if (!json)
2dbe669b 8876 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8877 else
60466a63 8878 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8879 } else if (p->family == AF_FLOWSPEC) {
8880 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8881 json ?
8882 NLRI_STRING_FORMAT_JSON_SIMPLE :
8883 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8884 } else {
c6462ff4 8885 if (!json)
8228a9a7 8886 len = vty_out(vty, "%pFX", p);
50e05855
AD
8887 else {
8888 json_object_string_add(json, "prefix",
07380148
DA
8889 inet_ntop(p->family,
8890 &p->u.prefix, buf,
8891 sizeof(buf)));
50e05855 8892 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8893 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8894 json_object_int_add(json, "version", dest->version);
37d4e0df 8895 }
9c92b5f7 8896 }
d62a17ae 8897
9c92b5f7 8898 if (!json) {
ae248832 8899 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8900 if (len < 1)
8901 vty_out(vty, "\n%*s", 20, " ");
8902 else
8903 vty_out(vty, "%*s", len, " ");
8904 }
718e3744 8905}
8906
d62a17ae 8907enum bgp_display_type {
8908 normal_list,
718e3744 8909};
8910
1d7260a1 8911const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8912{
8913 switch (reason) {
8914 case bgp_path_selection_none:
8915 return "Nothing to Select";
8916 case bgp_path_selection_first:
8917 return "First path received";
8918 case bgp_path_selection_evpn_sticky_mac:
8919 return "EVPN Sticky Mac";
8920 case bgp_path_selection_evpn_seq:
8921 return "EVPN sequence number";
8922 case bgp_path_selection_evpn_lower_ip:
8923 return "EVPN lower IP";
8924 case bgp_path_selection_evpn_local_path:
8925 return "EVPN local ES path";
8926 case bgp_path_selection_evpn_non_proxy:
8927 return "EVPN non proxy";
8928 case bgp_path_selection_weight:
8929 return "Weight";
8930 case bgp_path_selection_local_pref:
8931 return "Local Pref";
46dbf9d0
DA
8932 case bgp_path_selection_accept_own:
8933 return "Accept Own";
bbb46eb5
DA
8934 case bgp_path_selection_local_route:
8935 return "Local Route";
97a52c82
DA
8936 case bgp_path_selection_aigp:
8937 return "AIGP";
bbb46eb5
DA
8938 case bgp_path_selection_confed_as_path:
8939 return "Confederation based AS Path";
8940 case bgp_path_selection_as_path:
8941 return "AS Path";
8942 case bgp_path_selection_origin:
8943 return "Origin";
8944 case bgp_path_selection_med:
8945 return "MED";
8946 case bgp_path_selection_peer:
8947 return "Peer Type";
8948 case bgp_path_selection_confed:
8949 return "Confed Peer Type";
8950 case bgp_path_selection_igp_metric:
8951 return "IGP Metric";
8952 case bgp_path_selection_older:
8953 return "Older Path";
8954 case bgp_path_selection_router_id:
8955 return "Router ID";
8956 case bgp_path_selection_cluster_length:
bcab253c 8957 return "Cluster length";
bbb46eb5
DA
8958 case bgp_path_selection_stale:
8959 return "Path Staleness";
8960 case bgp_path_selection_local_configured:
8961 return "Locally configured route";
8962 case bgp_path_selection_neighbor_ip:
8963 return "Neighbor IP";
8964 case bgp_path_selection_default:
8965 return "Nothing left to compare";
8966 }
8967 return "Invalid (internal error)";
8968}
8969
18ee8310 8970/* Print the short form route status for a bgp_path_info */
4b7e6066 8971static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8972 struct bgp_path_info *path,
82c298be 8973 const struct prefix *p,
d62a17ae 8974 json_object *json_path)
718e3744 8975{
82c298be
DA
8976 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8977
d62a17ae 8978 if (json_path) {
b05a1c8b 8979
d62a17ae 8980 /* Route status display. */
9b6d8fcf 8981 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8982 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8983
9b6d8fcf 8984 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8985 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8986
4056a5f6 8987 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8988 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8989
9b6d8fcf
DS
8990 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8991 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8992 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8993
d62a17ae 8994 /* Selected */
9b6d8fcf 8995 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8996 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8997
9b6d8fcf 8998 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8999 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9000
bbb46eb5 9001 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9002 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9003 json_object_string_add(json_path, "selectionReason",
9004 bgp_path_selection_reason2str(
9005 path->net->reason));
9006 }
b05a1c8b 9007
9b6d8fcf 9008 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9009 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9010
d62a17ae 9011 /* Internal route. */
9b6d8fcf
DS
9012 if ((path->peer->as)
9013 && (path->peer->as == path->peer->local_as))
d62a17ae 9014 json_object_string_add(json_path, "pathFrom",
9015 "internal");
9016 else
9017 json_object_string_add(json_path, "pathFrom",
9018 "external");
b05a1c8b 9019
d62a17ae 9020 return;
9021 }
b05a1c8b 9022
82c298be
DA
9023 /* RPKI validation state */
9024 rpki_state =
9025 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9026
9027 if (rpki_state == RPKI_VALID)
9028 vty_out(vty, "V");
9029 else if (rpki_state == RPKI_INVALID)
9030 vty_out(vty, "I");
9031 else if (rpki_state == RPKI_NOTFOUND)
9032 vty_out(vty, "N");
eaeba5e8
WM
9033 else
9034 vty_out(vty, " ");
82c298be 9035
d62a17ae 9036 /* Route status display. */
9b6d8fcf 9037 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9038 vty_out(vty, "R");
9b6d8fcf 9039 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9040 vty_out(vty, "S");
4056a5f6 9041 else if (bgp_path_suppressed(path))
d62a17ae 9042 vty_out(vty, "s");
9b6d8fcf
DS
9043 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9044 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9045 vty_out(vty, "*");
9046 else
9047 vty_out(vty, " ");
9048
9049 /* Selected */
9b6d8fcf 9050 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9051 vty_out(vty, "h");
9b6d8fcf 9052 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9053 vty_out(vty, "d");
9b6d8fcf 9054 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9055 vty_out(vty, ">");
9b6d8fcf 9056 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9057 vty_out(vty, "=");
9058 else
9059 vty_out(vty, " ");
718e3744 9060
d62a17ae 9061 /* Internal route. */
9b6d8fcf
DS
9062 if (path->peer && (path->peer->as)
9063 && (path->peer->as == path->peer->local_as))
d62a17ae 9064 vty_out(vty, "i");
9065 else
9066 vty_out(vty, " ");
b40d939b 9067}
9068
2ba93fd6
DA
9069static char *bgp_nexthop_hostname(struct peer *peer,
9070 struct bgp_nexthop_cache *bnc)
25b5da8d 9071{
892fedb6 9072 if (peer->hostname
aef999a2 9073 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9074 return peer->hostname;
9075 return NULL;
9076}
9077
b40d939b 9078/* called from terminal list command */
bd494ec5 9079void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9080 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9081 json_object *json_paths, bool wide)
d62a17ae 9082{
aef999a2 9083 int len;
515c2602 9084 struct attr *attr = path->attr;
d62a17ae 9085 json_object *json_path = NULL;
9086 json_object *json_nexthops = NULL;
9087 json_object *json_nexthop_global = NULL;
9088 json_object *json_nexthop_ll = NULL;
6f214dd3 9089 json_object *json_ext_community = NULL;
9df8b37c 9090 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9091 bool nexthop_self =
9b6d8fcf 9092 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9093 bool nexthop_othervrf = false;
43089216 9094 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9095 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9096 char *nexthop_hostname =
9097 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9098 char esi_buf[ESI_STR_LEN];
d62a17ae 9099
9100 if (json_paths)
9101 json_path = json_object_new_object();
9102
9103 /* short status lead text */
82c298be 9104 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9105
9106 if (!json_paths) {
9107 /* print prefix and mask */
9108 if (!display)
7d3cae70 9109 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9110 else
ae248832 9111 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9112 } else {
7d3cae70 9113 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9114 }
47fc97cc 9115
9df8b37c
PZ
9116 /*
9117 * If vrf id of nexthop is different from that of prefix,
9118 * set up printable string to append
9119 */
9b6d8fcf 9120 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9121 const char *self = "";
9122
9123 if (nexthop_self)
9124 self = "<";
9125
9126 nexthop_othervrf = true;
9b6d8fcf 9127 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9128
9b6d8fcf 9129 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9130 snprintf(vrf_id_str, sizeof(vrf_id_str),
9131 "@%s%s", VRFID_NONE_STR, self);
9132 else
9133 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9134 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9135
9b6d8fcf
DS
9136 if (path->extra->bgp_orig->inst_type
9137 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9138
9b6d8fcf 9139 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9140 } else {
9141 const char *self = "";
9142
9143 if (nexthop_self)
9144 self = "<";
9145
9146 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9147 }
9148
445c2480
DS
9149 /*
9150 * For ENCAP and EVPN routes, nexthop address family is not
9151 * neccessarily the same as the prefix address family.
9152 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9153 * EVPN routes are also exchanged with a MP nexthop. Currently,
9154 * this
9155 * is only IPv4, the value will be present in either
9156 * attr->nexthop or
9157 * attr->mp_nexthop_global_in
9158 */
9159 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9160 char nexthop[128];
9161 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9162
9163 switch (af) {
9164 case AF_INET:
07380148
DA
9165 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9166 &attr->mp_nexthop_global_in);
445c2480
DS
9167 break;
9168 case AF_INET6:
07380148
DA
9169 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9170 &attr->mp_nexthop_global);
445c2480
DS
9171 break;
9172 default:
772270f3 9173 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9174 break;
d62a17ae 9175 }
d62a17ae 9176
445c2480
DS
9177 if (json_paths) {
9178 json_nexthop_global = json_object_new_object();
9179
515c2602
DA
9180 json_object_string_add(json_nexthop_global, "ip",
9181 nexthop);
9182
939a97f4 9183 if (path->peer->hostname)
515c2602
DA
9184 json_object_string_add(json_nexthop_global,
9185 "hostname",
939a97f4 9186 path->peer->hostname);
515c2602
DA
9187
9188 json_object_string_add(json_nexthop_global, "afi",
9189 (af == AF_INET) ? "ipv4"
9190 : "ipv6");
445c2480
DS
9191 json_object_boolean_true_add(json_nexthop_global,
9192 "used");
aef999a2
DA
9193 } else {
9194 if (nexthop_hostname)
9195 len = vty_out(vty, "%s(%s)%s", nexthop,
9196 nexthop_hostname, vrf_id_str);
9197 else
9198 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9199
ae248832 9200 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9201 if (len < 1)
9202 vty_out(vty, "\n%*s", 36, " ");
9203 else
9204 vty_out(vty, "%*s", len, " ");
9205 }
445c2480
DS
9206 } else if (safi == SAFI_EVPN) {
9207 if (json_paths) {
9208 json_nexthop_global = json_object_new_object();
9209
c949c771 9210 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9211 "%pI4",
9212 &attr->mp_nexthop_global_in);
515c2602 9213
939a97f4 9214 if (path->peer->hostname)
515c2602
DA
9215 json_object_string_add(json_nexthop_global,
9216 "hostname",
939a97f4 9217 path->peer->hostname);
515c2602 9218
a4d82a8a
PZ
9219 json_object_string_add(json_nexthop_global, "afi",
9220 "ipv4");
445c2480
DS
9221 json_object_boolean_true_add(json_nexthop_global,
9222 "used");
aef999a2
DA
9223 } else {
9224 if (nexthop_hostname)
7226bc40
TA
9225 len = vty_out(vty, "%pI4(%s)%s",
9226 &attr->mp_nexthop_global_in,
aef999a2
DA
9227 nexthop_hostname, vrf_id_str);
9228 else
7226bc40
TA
9229 len = vty_out(vty, "%pI4%s",
9230 &attr->mp_nexthop_global_in,
aef999a2
DA
9231 vrf_id_str);
9232
ae248832 9233 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9234 if (len < 1)
9235 vty_out(vty, "\n%*s", 36, " ");
9236 else
9237 vty_out(vty, "%*s", len, " ");
9238 }
d33fc23b 9239 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9240 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9241 if (json_paths) {
9242 json_nexthop_global = json_object_new_object();
515c2602 9243
026b914a
PG
9244 json_object_string_add(json_nexthop_global,
9245 "afi", "ipv4");
c949c771
DA
9246 json_object_string_addf(json_nexthop_global,
9247 "ip", "%pI4",
9248 &attr->nexthop);
515c2602 9249
939a97f4 9250 if (path->peer->hostname)
515c2602
DA
9251 json_object_string_add(
9252 json_nexthop_global, "hostname",
939a97f4 9253 path->peer->hostname);
515c2602 9254
50e05855
AD
9255 json_object_boolean_true_add(
9256 json_nexthop_global,
026b914a
PG
9257 "used");
9258 } else {
aef999a2
DA
9259 if (nexthop_hostname)
9260 len = vty_out(vty, "%pI4(%s)%s",
9261 &attr->nexthop,
9262 nexthop_hostname,
9263 vrf_id_str);
9264 else
9265 len = vty_out(vty, "%pI4%s",
9266 &attr->nexthop,
9267 vrf_id_str);
9268
ae248832 9269 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9270 if (len < 1)
9271 vty_out(vty, "\n%*s", 36, " ");
9272 else
9273 vty_out(vty, "%*s", len, " ");
026b914a
PG
9274 }
9275 }
7226bc40 9276 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9277 if (json_paths) {
9278 json_nexthop_global = json_object_new_object();
d62a17ae 9279
c949c771
DA
9280 json_object_string_addf(json_nexthop_global, "ip",
9281 "%pI4", &attr->nexthop);
515c2602 9282
939a97f4 9283 if (path->peer->hostname)
515c2602
DA
9284 json_object_string_add(json_nexthop_global,
9285 "hostname",
939a97f4 9286 path->peer->hostname);
445c2480 9287
a4d82a8a
PZ
9288 json_object_string_add(json_nexthop_global, "afi",
9289 "ipv4");
445c2480
DS
9290 json_object_boolean_true_add(json_nexthop_global,
9291 "used");
9292 } else {
aef999a2
DA
9293 if (nexthop_hostname)
9294 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9295 nexthop_hostname, vrf_id_str);
9296 else
9297 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9298 vrf_id_str);
9df8b37c 9299
ae248832 9300 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9301 if (len < 1)
9302 vty_out(vty, "\n%*s", 36, " ");
9303 else
9304 vty_out(vty, "%*s", len, " ");
d62a17ae 9305 }
445c2480 9306 }
b05a1c8b 9307
445c2480 9308 /* IPv6 Next Hop */
7226bc40 9309 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9310 if (json_paths) {
9311 json_nexthop_global = json_object_new_object();
c949c771
DA
9312 json_object_string_addf(json_nexthop_global, "ip",
9313 "%pI6",
9314 &attr->mp_nexthop_global);
515c2602 9315
939a97f4 9316 if (path->peer->hostname)
515c2602
DA
9317 json_object_string_add(json_nexthop_global,
9318 "hostname",
939a97f4 9319 path->peer->hostname);
515c2602 9320
a4d82a8a
PZ
9321 json_object_string_add(json_nexthop_global, "afi",
9322 "ipv6");
9323 json_object_string_add(json_nexthop_global, "scope",
9324 "global");
445c2480
DS
9325
9326 /* We display both LL & GL if both have been
9327 * received */
0606039c
DA
9328 if ((attr->mp_nexthop_len
9329 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9330 || (path->peer->conf_if)) {
a4d82a8a 9331 json_nexthop_ll = json_object_new_object();
c949c771
DA
9332 json_object_string_addf(
9333 json_nexthop_ll, "ip", "%pI6",
9334 &attr->mp_nexthop_local);
515c2602 9335
939a97f4 9336 if (path->peer->hostname)
515c2602
DA
9337 json_object_string_add(
9338 json_nexthop_ll, "hostname",
939a97f4 9339 path->peer->hostname);
515c2602 9340
a4d82a8a
PZ
9341 json_object_string_add(json_nexthop_ll, "afi",
9342 "ipv6");
9343 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9344 "link-local");
d62a17ae 9345
a4d82a8a 9346 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9347 &attr->mp_nexthop_local)
9348 != 0)
9349 && !attr->mp_nexthop_prefer_global)
d62a17ae 9350 json_object_boolean_true_add(
a4d82a8a 9351 json_nexthop_ll, "used");
445c2480
DS
9352 else
9353 json_object_boolean_true_add(
a4d82a8a 9354 json_nexthop_global, "used");
445c2480
DS
9355 } else
9356 json_object_boolean_true_add(
9357 json_nexthop_global, "used");
9358 } else {
9359 /* Display LL if LL/Global both in table unless
9360 * prefer-global is set */
2bb8b49c
DS
9361 if (((attr->mp_nexthop_len
9362 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9363 && !attr->mp_nexthop_prefer_global)
9364 || (path->peer->conf_if)) {
9b6d8fcf 9365 if (path->peer->conf_if) {
a4d82a8a 9366 len = vty_out(vty, "%s",
9b6d8fcf 9367 path->peer->conf_if);
ae248832
MK
9368 /* len of IPv6 addr + max len of def
9369 * ifname */
9370 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9371
9372 if (len < 1)
a4d82a8a 9373 vty_out(vty, "\n%*s", 36, " ");
445c2480 9374 else
a4d82a8a 9375 vty_out(vty, "%*s", len, " ");
d62a17ae 9376 } else {
aef999a2
DA
9377 if (nexthop_hostname)
9378 len = vty_out(
9379 vty, "%pI6(%s)%s",
9380 &attr->mp_nexthop_local,
9381 nexthop_hostname,
9382 vrf_id_str);
9383 else
9384 len = vty_out(
9385 vty, "%pI6%s",
9386 &attr->mp_nexthop_local,
9387 vrf_id_str);
9388
ae248832 9389 len = wide ? (41 - len) : (16 - len);
d62a17ae 9390
9391 if (len < 1)
a4d82a8a 9392 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9393 else
a4d82a8a 9394 vty_out(vty, "%*s", len, " ");
d62a17ae 9395 }
445c2480 9396 } else {
aef999a2
DA
9397 if (nexthop_hostname)
9398 len = vty_out(vty, "%pI6(%s)%s",
9399 &attr->mp_nexthop_global,
9400 nexthop_hostname,
9401 vrf_id_str);
9402 else
9403 len = vty_out(vty, "%pI6%s",
9404 &attr->mp_nexthop_global,
9405 vrf_id_str);
9406
ae248832 9407 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9408
9409 if (len < 1)
9410 vty_out(vty, "\n%*s", 36, " ");
9411 else
9412 vty_out(vty, "%*s", len, " ");
d62a17ae 9413 }
9414 }
445c2480 9415 }
718e3744 9416
445c2480
DS
9417 /* MED/Metric */
9418 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9419 if (json_paths)
50e05855 9420 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9421 else if (wide)
9422 vty_out(vty, "%7u", attr->med);
0fbac0b4 9423 else
445c2480 9424 vty_out(vty, "%10u", attr->med);
ae248832
MK
9425 else if (!json_paths) {
9426 if (wide)
9427 vty_out(vty, "%*s", 7, " ");
9428 else
9429 vty_out(vty, "%*s", 10, " ");
9430 }
d62a17ae 9431
445c2480
DS
9432 /* Local Pref */
9433 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9434 if (json_paths)
50e05855 9435 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9436 attr->local_pref);
9437 else
445c2480
DS
9438 vty_out(vty, "%7u", attr->local_pref);
9439 else if (!json_paths)
9440 vty_out(vty, " ");
d62a17ae 9441
445c2480
DS
9442 if (json_paths)
9443 json_object_int_add(json_path, "weight", attr->weight);
9444 else
9445 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9446
47e12884
DA
9447 if (json_paths)
9448 json_object_string_addf(json_path, "peerId", "%pSU",
9449 &path->peer->su);
b05a1c8b 9450
445c2480
DS
9451 /* Print aspath */
9452 if (attr->aspath) {
0fbac0b4 9453 if (json_paths)
50e05855 9454 json_object_string_add(json_path, "path",
0fbac0b4
DA
9455 attr->aspath->str);
9456 else
e678b143 9457 aspath_print_vty(vty, attr->aspath);
d62a17ae 9458 }
f1aa5d8a 9459
445c2480
DS
9460 /* Print origin */
9461 if (json_paths)
a4d82a8a
PZ
9462 json_object_string_add(json_path, "origin",
9463 bgp_origin_long_str[attr->origin]);
445c2480
DS
9464 else
9465 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9466
9df8b37c 9467 if (json_paths) {
d071f237 9468 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9469 json_object_string_add(json_path, "esi",
9470 esi_to_str(&attr->esi,
9471 esi_buf, sizeof(esi_buf)));
9472 }
6f214dd3
CS
9473 if (safi == SAFI_EVPN &&
9474 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9475 json_ext_community = json_object_new_object();
b53e67a3
DA
9476 json_object_string_add(
9477 json_ext_community, "string",
9478 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9479 json_object_object_add(json_path,
9480 "extendedCommunity",
9481 json_ext_community);
9482 }
9483
9df8b37c
PZ
9484 if (nexthop_self)
9485 json_object_boolean_true_add(json_path,
9486 "announceNexthopSelf");
9487 if (nexthop_othervrf) {
9488 json_object_string_add(json_path, "nhVrfName",
9489 nexthop_vrfname);
9490
9491 json_object_int_add(json_path, "nhVrfId",
9492 ((nexthop_vrfid == VRF_UNKNOWN)
9493 ? -1
9494 : (int)nexthop_vrfid));
9495 }
9496 }
9497
d62a17ae 9498 if (json_paths) {
9499 if (json_nexthop_global || json_nexthop_ll) {
9500 json_nexthops = json_object_new_array();
f1aa5d8a 9501
d62a17ae 9502 if (json_nexthop_global)
9503 json_object_array_add(json_nexthops,
9504 json_nexthop_global);
f1aa5d8a 9505
d62a17ae 9506 if (json_nexthop_ll)
9507 json_object_array_add(json_nexthops,
9508 json_nexthop_ll);
f1aa5d8a 9509
d62a17ae 9510 json_object_object_add(json_path, "nexthops",
9511 json_nexthops);
9512 }
9513
9514 json_object_array_add(json_paths, json_path);
9515 } else {
9516 vty_out(vty, "\n");
6f214dd3 9517
b5e140c8 9518 if (safi == SAFI_EVPN) {
d071f237 9519 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9520 /* XXX - add these params to the json out */
b5e140c8 9521 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9522 vty_out(vty, "ESI:%s",
9523 esi_to_str(&attr->esi, esi_buf,
9524 sizeof(esi_buf)));
60605cbc 9525
229587fb 9526 vty_out(vty, "\n");
b5e140c8
AK
9527 }
9528 if (attr->flag &
9529 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9530 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9531 vty_out(vty, "%s\n",
9532 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9533 }
6f214dd3
CS
9534 }
9535
49e5a4a0 9536#ifdef ENABLE_BGP_VNC
d62a17ae 9537 /* prints an additional line, indented, with VNC info, if
9538 * present */
9539 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9540 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9541#endif
d62a17ae 9542 }
9543}
718e3744 9544
9545/* called from terminal list command */
7d3cae70
DA
9546void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9547 const struct prefix *p, struct attr *attr, safi_t safi,
9548 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9549{
9550 json_object *json_status = NULL;
9551 json_object *json_net = NULL;
aef999a2 9552 int len;
d62a17ae 9553 char buff[BUFSIZ];
dc387b0f 9554
d62a17ae 9555 /* Route status display. */
9556 if (use_json) {
9557 json_status = json_object_new_object();
9558 json_net = json_object_new_object();
9559 } else {
146c574b 9560 vty_out(vty, " *");
d62a17ae 9561 vty_out(vty, ">");
9562 vty_out(vty, " ");
9563 }
718e3744 9564
d62a17ae 9565 /* print prefix and mask */
50e05855 9566 if (use_json) {
dc387b0f
LK
9567 if (safi == SAFI_EVPN)
9568 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9569 else if (p->family == AF_INET || p->family == AF_INET6) {
9570 json_object_string_add(
9571 json_net, "addrPrefix",
9572 inet_ntop(p->family, &p->u.prefix, buff,
9573 BUFSIZ));
9574 json_object_int_add(json_net, "prefixLen",
9575 p->prefixlen);
67d7e256 9576 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9577 }
50e05855 9578 } else
7d3cae70 9579 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9580
9581 /* Print attribute */
9582 if (attr) {
9583 if (use_json) {
7226bc40
TA
9584 if (p->family == AF_INET &&
9585 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9586 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9587 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9588 json_object_string_addf(
9589 json_net, "nextHop", "%pI4",
9590 &attr->mp_nexthop_global_in);
d62a17ae 9591 else
c949c771
DA
9592 json_object_string_addf(
9593 json_net, "nextHop", "%pI4",
9594 &attr->nexthop);
7226bc40
TA
9595 } else if (p->family == AF_INET6 ||
9596 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9597 json_object_string_addf(
9598 json_net, "nextHopGlobal", "%pI6",
9599 &attr->mp_nexthop_global);
7226bc40
TA
9600 } else if (p->family == AF_EVPN &&
9601 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9602 json_object_string_addf(
9603 json_net, "nextHop", "%pI4",
9604 &attr->mp_nexthop_global_in);
23d0a753 9605 }
d62a17ae 9606
9607 if (attr->flag
9608 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9609 json_object_int_add(json_net, "metric",
9610 attr->med);
9611
0fbac0b4 9612 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9613 json_object_int_add(json_net, "locPrf",
0fbac0b4 9614 attr->local_pref);
d62a17ae 9615
9616 json_object_int_add(json_net, "weight", attr->weight);
9617
9618 /* Print aspath */
0fbac0b4 9619 if (attr->aspath)
50e05855 9620 json_object_string_add(json_net, "path",
0fbac0b4 9621 attr->aspath->str);
d62a17ae 9622
9623 /* Print origin */
dd426a51
DA
9624#if CONFDATE > 20231208
9625CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9626#endif
d62a17ae 9627 json_object_string_add(json_net, "bgpOriginCode",
9628 bgp_origin_str[attr->origin]);
dd426a51
DA
9629 json_object_string_add(
9630 json_net, "origin",
9631 bgp_origin_long_str[attr->origin]);
d62a17ae 9632 } else {
7226bc40
TA
9633 if (p->family == AF_INET &&
9634 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9635 safi == SAFI_EVPN ||
9636 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9637 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9638 || safi == SAFI_EVPN)
23d0a753
DA
9639 vty_out(vty, "%-16pI4",
9640 &attr->mp_nexthop_global_in);
ae248832 9641 else if (wide)
23d0a753 9642 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9643 else
23d0a753 9644 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9645 } else if (p->family == AF_INET6 ||
9646 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9647 len = vty_out(vty, "%pI6",
9648 &attr->mp_nexthop_global);
ae248832 9649 len = wide ? (41 - len) : (16 - len);
d62a17ae 9650 if (len < 1)
9651 vty_out(vty, "\n%*s", 36, " ");
9652 else
9653 vty_out(vty, "%*s", len, " ");
9654 }
9655 if (attr->flag
9656 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9657 if (wide)
9658 vty_out(vty, "%7u", attr->med);
9659 else
9660 vty_out(vty, "%10u", attr->med);
9661 else if (wide)
9662 vty_out(vty, " ");
d62a17ae 9663 else
9664 vty_out(vty, " ");
718e3744 9665
d62a17ae 9666 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9667 vty_out(vty, "%7u", attr->local_pref);
9668 else
9669 vty_out(vty, " ");
9670
9671 vty_out(vty, "%7u ", attr->weight);
9672
9673 /* Print aspath */
9674 if (attr->aspath)
e678b143 9675 aspath_print_vty(vty, attr->aspath);
d62a17ae 9676
9677 /* Print origin */
9678 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9679 }
9680 }
9681 if (use_json) {
4d65410c
DA
9682 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9683
dd426a51
DA
9684#if CONFDATE > 20231208
9685CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9686#endif
d62a17ae 9687 json_object_boolean_true_add(json_status, "*");
9688 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9689 json_object_boolean_true_add(json_net, "valid");
9690 json_object_boolean_true_add(json_net, "best");
4d65410c 9691
dd426a51 9692 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9693 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9694 json_object_boolean_true_add(json_net, "multipath");
9695 }
d62a17ae 9696 json_object_object_add(json_net, "appliedStatusSymbols",
9697 json_status);
511211bf 9698 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9699 } else
9700 vty_out(vty, "\n");
9701}
9702
bd494ec5 9703void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9704 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9705 json_object *json)
9706{
9707 json_object *json_out = NULL;
9708 struct attr *attr;
9709 mpls_label_t label = MPLS_INVALID_LABEL;
9710
9b6d8fcf 9711 if (!path->extra)
d62a17ae 9712 return;
9713
9714 if (json)
9715 json_out = json_object_new_object();
9716
9717 /* short status lead text */
82c298be 9718 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9719
9720 /* print prefix and mask */
9721 if (json == NULL) {
9722 if (!display)
7d3cae70 9723 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9724 else
9725 vty_out(vty, "%*s", 17, " ");
9726 }
9727
9728 /* Print attribute */
9b6d8fcf 9729 attr = path->attr;
7226bc40
TA
9730 if (((p->family == AF_INET) &&
9731 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9732 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9733 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9734 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9735 || safi == SAFI_EVPN) {
9736 if (json)
c949c771
DA
9737 json_object_string_addf(
9738 json_out, "mpNexthopGlobalIn", "%pI4",
9739 &attr->mp_nexthop_global_in);
05864da7 9740 else
23d0a753
DA
9741 vty_out(vty, "%-16pI4",
9742 &attr->mp_nexthop_global_in);
05864da7
DS
9743 } else {
9744 if (json)
c949c771
DA
9745 json_object_string_addf(json_out, "nexthop",
9746 "%pI4", &attr->nexthop);
05864da7 9747 else
23d0a753 9748 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9749 }
7226bc40
TA
9750 } else if (((p->family == AF_INET6) &&
9751 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9752 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9753 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9754 char buf_a[512];
9755
9756 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9757 if (json)
c949c771
DA
9758 json_object_string_addf(
9759 json_out, "mpNexthopGlobalIn", "%pI6",
9760 &attr->mp_nexthop_global);
05864da7
DS
9761 else
9762 vty_out(vty, "%s",
9763 inet_ntop(AF_INET6,
9764 &attr->mp_nexthop_global,
9765 buf_a, sizeof(buf_a)));
9766 } else if (attr->mp_nexthop_len
9767 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9768 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9769 &attr->mp_nexthop_global,
9770 &attr->mp_nexthop_local);
9771 if (json)
9772 json_object_string_add(json_out,
9773 "mpNexthopGlobalLocal",
9774 buf_a);
9775 else
9776 vty_out(vty, "%s", buf_a);
d62a17ae 9777 }
9778 }
9779
9b6d8fcf 9780 label = decode_label(&path->extra->label[0]);
d62a17ae 9781
9782 if (bgp_is_valid_label(&label)) {
9783 if (json) {
9784 json_object_int_add(json_out, "notag", label);
9785 json_object_array_add(json, json_out);
9786 } else {
9787 vty_out(vty, "notag/%d", label);
9788 vty_out(vty, "\n");
9789 }
700ddfed
PG
9790 } else if (!json)
9791 vty_out(vty, "\n");
d62a17ae 9792}
718e3744 9793
bd494ec5 9794void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9795 struct bgp_path_info *path, int display,
d62a17ae 9796 json_object *json_paths)
718e3744 9797{
d62a17ae 9798 struct attr *attr;
d62a17ae 9799 json_object *json_path = NULL;
14f51eba
LK
9800 json_object *json_nexthop = NULL;
9801 json_object *json_overlay = NULL;
856ca177 9802
9b6d8fcf 9803 if (!path->extra)
d62a17ae 9804 return;
718e3744 9805
14f51eba
LK
9806 if (json_paths) {
9807 json_path = json_object_new_object();
9808 json_overlay = json_object_new_object();
9809 json_nexthop = json_object_new_object();
9810 }
9811
d62a17ae 9812 /* short status lead text */
82c298be 9813 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9814
d62a17ae 9815 /* print prefix and mask */
9816 if (!display)
7d3cae70 9817 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9818 else
9819 vty_out(vty, "%*s", 17, " ");
9820
9821 /* Print attribute */
9b6d8fcf 9822 attr = path->attr;
05864da7 9823 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9824
05864da7
DS
9825 switch (af) {
9826 case AF_INET:
05864da7 9827 if (!json_path) {
db66cf7c 9828 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9829 } else {
db66cf7c
DA
9830 json_object_string_addf(json_nexthop, "ip", "%pI4",
9831 &attr->mp_nexthop_global_in);
14f51eba 9832
05864da7 9833 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9834
05864da7
DS
9835 json_object_object_add(json_path, "nexthop",
9836 json_nexthop);
9837 }
9838 break;
9839 case AF_INET6:
05864da7 9840 if (!json_path) {
db66cf7c
DA
9841 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9842 &attr->mp_nexthop_local);
05864da7 9843 } else {
db66cf7c
DA
9844 json_object_string_addf(json_nexthop, "ipv6Global",
9845 "%pI6",
9846 &attr->mp_nexthop_global);
14f51eba 9847
db66cf7c
DA
9848 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9849 "%pI6",
9850 &attr->mp_nexthop_local);
14f51eba 9851
05864da7 9852 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9853
05864da7
DS
9854 json_object_object_add(json_path, "nexthop",
9855 json_nexthop);
9856 }
9857 break;
9858 default:
9859 if (!json_path) {
9860 vty_out(vty, "?");
9861 } else {
77a2f8e5
DA
9862 json_object_string_add(json_nexthop, "error",
9863 "Unsupported address-family");
d62a17ae 9864 }
05864da7 9865 }
988258b4 9866
6c924775
DS
9867 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9868
05864da7 9869 if (!json_path)
db66cf7c 9870 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9871 else
db66cf7c 9872 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9873
b53e67a3 9874 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9875 char *mac = NULL;
9876 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9877 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9878 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9879
9880 if (routermac)
9881 mac = ecom_mac2str((char *)routermac->val);
9882 if (mac) {
9883 if (!json_path) {
c4efd0f4 9884 vty_out(vty, "/%s", mac);
05864da7
DS
9885 } else {
9886 json_object_string_add(json_overlay, "rmac",
9887 mac);
988258b4 9888 }
05864da7 9889 XFREE(MTYPE_TMP, mac);
988258b4 9890 }
05864da7 9891 }
718e3744 9892
05864da7
DS
9893 if (!json_path) {
9894 vty_out(vty, "\n");
9895 } else {
9896 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9897
05864da7 9898 json_object_array_add(json_paths, json_path);
14f51eba 9899 }
d62a17ae 9900}
718e3744 9901
d62a17ae 9902/* dampening route */
5f040085
DS
9903static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9904 struct bgp_path_info *path, int display,
9905 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9906 json_object *json_paths)
d62a17ae 9907{
e5be8c1d 9908 struct attr *attr = path->attr;
d62a17ae 9909 int len;
9910 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9911 json_object *json_path = NULL;
9912
9913 if (use_json)
9914 json_path = json_object_new_object();
d62a17ae 9915
9916 /* short status lead text */
e5be8c1d 9917 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9918
9919 /* print prefix and mask */
9920 if (!use_json) {
9921 if (!display)
7d3cae70 9922 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9923 else
9924 vty_out(vty, "%*s", 17, " ");
d62a17ae 9925
e5be8c1d
DA
9926 len = vty_out(vty, "%s", path->peer->host);
9927 len = 17 - len;
9928
9929 if (len < 1)
d62a17ae 9930 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9931 else
9932 vty_out(vty, "%*s", len, " ");
d62a17ae 9933
9b6d8fcf
DS
9934 vty_out(vty, "%s ",
9935 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9936 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9937 use_json, NULL));
d62a17ae 9938
e5be8c1d 9939 if (attr->aspath)
e678b143 9940 aspath_print_vty(vty, attr->aspath);
05864da7 9941
05864da7
DS
9942 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9943
d62a17ae 9944 vty_out(vty, "\n");
e5be8c1d
DA
9945 } else {
9946 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9947 safi, use_json, json_path);
9948
9949 if (attr->aspath)
9950 json_object_string_add(json_path, "asPath",
9951 attr->aspath->str);
9952
9953 json_object_string_add(json_path, "origin",
9954 bgp_origin_str[attr->origin]);
9955 json_object_string_add(json_path, "peerHost", path->peer->host);
9956
9957 json_object_array_add(json_paths, json_path);
9958 }
d62a17ae 9959}
718e3744 9960
d62a17ae 9961/* flap route */
5f040085
DS
9962static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9963 struct bgp_path_info *path, int display,
9964 afi_t afi, safi_t safi, bool use_json,
31258046 9965 json_object *json_paths)
784d3a42 9966{
31258046 9967 struct attr *attr = path->attr;
d62a17ae 9968 struct bgp_damp_info *bdi;
9969 char timebuf[BGP_UPTIME_LEN];
9970 int len;
31258046 9971 json_object *json_path = NULL;
784d3a42 9972
9b6d8fcf 9973 if (!path->extra)
d62a17ae 9974 return;
784d3a42 9975
31258046
DA
9976 if (use_json)
9977 json_path = json_object_new_object();
9978
9b6d8fcf 9979 bdi = path->extra->damp_info;
784d3a42 9980
d62a17ae 9981 /* short status lead text */
31258046 9982 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9983
d62a17ae 9984 if (!use_json) {
9985 if (!display)
7d3cae70 9986 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9987 else
9988 vty_out(vty, "%*s", 17, " ");
784d3a42 9989
31258046
DA
9990 len = vty_out(vty, "%s", path->peer->host);
9991 len = 16 - len;
9992 if (len < 1)
d62a17ae 9993 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9994 else
9995 vty_out(vty, "%*s", len, " ");
784d3a42 9996
31258046
DA
9997 len = vty_out(vty, "%d", bdi->flap);
9998 len = 5 - len;
9999 if (len < 1)
d62a17ae 10000 vty_out(vty, " ");
d62a17ae 10001 else
10002 vty_out(vty, "%*s", len, " ");
d62a17ae 10003
996c9314
LB
10004 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10005 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10006
31258046
DA
10007 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10008 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10009 vty_out(vty, "%s ",
9b6d8fcf 10010 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10011 BGP_UPTIME_LEN, afi,
31258046
DA
10012 safi, use_json, NULL));
10013 else
d62a17ae 10014 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10015
31258046 10016 if (attr->aspath)
e678b143 10017 aspath_print_vty(vty, attr->aspath);
05864da7 10018
05864da7
DS
10019 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10020
d62a17ae 10021 vty_out(vty, "\n");
31258046
DA
10022 } else {
10023 json_object_string_add(json_path, "peerHost", path->peer->host);
10024 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10025
10026 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10027 json_path);
10028
10029 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10030 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10031 bgp_damp_reuse_time_vty(vty, path, timebuf,
10032 BGP_UPTIME_LEN, afi, safi,
10033 use_json, json_path);
10034
10035 if (attr->aspath)
10036 json_object_string_add(json_path, "asPath",
10037 attr->aspath->str);
10038
10039 json_object_string_add(json_path, "origin",
10040 bgp_origin_str[attr->origin]);
10041
10042 json_object_array_add(json_paths, json_path);
10043 }
d62a17ae 10044}
10045
10046static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10047 int *first, const char *header,
10048 json_object *json_adv_to)
10049{
d62a17ae 10050 json_object *json_peer = NULL;
10051
10052 if (json_adv_to) {
10053 /* 'advertised-to' is a dictionary of peers we have advertised
10054 * this
10055 * prefix too. The key is the peer's IP or swpX, the value is
10056 * the
10057 * hostname if we know it and "" if not.
10058 */
10059 json_peer = json_object_new_object();
10060
10061 if (peer->hostname)
10062 json_object_string_add(json_peer, "hostname",
10063 peer->hostname);
10064
10065 if (peer->conf_if)
10066 json_object_object_add(json_adv_to, peer->conf_if,
10067 json_peer);
10068 else
47e12884
DA
10069 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10070 &peer->su);
d62a17ae 10071 } else {
10072 if (*first) {
10073 vty_out(vty, "%s", header);
10074 *first = 0;
10075 }
10076
10077 if (peer->hostname
892fedb6 10078 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10079 if (peer->conf_if)
10080 vty_out(vty, " %s(%s)", peer->hostname,
10081 peer->conf_if);
10082 else
47e12884
DA
10083 vty_out(vty, " %s(%pSU)", peer->hostname,
10084 &peer->su);
d62a17ae 10085 } else {
10086 if (peer->conf_if)
10087 vty_out(vty, " %s", peer->conf_if);
10088 else
47e12884 10089 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10090 }
10091 }
784d3a42
PG
10092}
10093
dcc68b5e
MS
10094static void route_vty_out_tx_ids(struct vty *vty,
10095 struct bgp_addpath_info_data *d)
10096{
10097 int i;
10098
10099 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10100 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10101 d->addpath_tx_id[i],
10102 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10103 }
10104}
10105
5e4d4c8a 10106static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10107 struct bgp_path_info *pi,
10108 struct attr *attr,
10109 json_object *json_path)
5e4d4c8a
AK
10110{
10111 char esi_buf[ESI_STR_LEN];
10112 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10113 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10114 ATTR_ES_PEER_ROUTER);
10115 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10116 ATTR_ES_PEER_ACTIVE);
10117 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10118 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10119 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10120 if (json_path) {
10121 json_object *json_es_info = NULL;
10122
10123 json_object_string_add(
10124 json_path, "esi",
10125 esi_buf);
10126 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10127 json_es_info = json_object_new_object();
10128 if (es_local)
10129 json_object_boolean_true_add(
10130 json_es_info, "localEs");
10131 if (peer_active)
10132 json_object_boolean_true_add(
10133 json_es_info, "peerActive");
10134 if (peer_proxy)
10135 json_object_boolean_true_add(
10136 json_es_info, "peerProxy");
10137 if (peer_router)
10138 json_object_boolean_true_add(
10139 json_es_info, "peerRouter");
10140 if (attr->mm_sync_seqnum)
10141 json_object_int_add(
10142 json_es_info, "peerSeq",
10143 attr->mm_sync_seqnum);
10144 json_object_object_add(
10145 json_path, "es_info",
10146 json_es_info);
10147 }
10148 } else {
10149 if (bgp_evpn_attr_is_sync(attr))
10150 vty_out(vty,
10151 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10152 esi_buf,
10153 es_local ? "local-es":"",
10154 peer_proxy ? "proxy " : "",
10155 peer_active ? "active ":"",
10156 peer_router ? "router ":"",
10157 attr->mm_sync_seqnum);
10158 else
10159 vty_out(vty, " ESI %s %s\n",
10160 esi_buf,
10161 es_local ? "local-es":"");
10162 }
10163}
10164
4933eaaf 10165void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10166 const struct prefix *p, struct bgp_path_info *path,
10167 afi_t afi, safi_t safi,
4027d19b
DS
10168 enum rpki_states rpki_curr_state,
10169 json_object *json_paths)
d62a17ae 10170{
10171 char buf[INET6_ADDRSTRLEN];
100290e4 10172 char tag_buf[30];
515c2602 10173 struct attr *attr = path->attr;
d62a17ae 10174 time_t tbuf;
10175 json_object *json_bestpath = NULL;
10176 json_object *json_cluster_list = NULL;
10177 json_object *json_cluster_list_list = NULL;
10178 json_object *json_ext_community = NULL;
10179 json_object *json_last_update = NULL;
7fd077aa 10180 json_object *json_pmsi = NULL;
d62a17ae 10181 json_object *json_nexthop_global = NULL;
10182 json_object *json_nexthop_ll = NULL;
10183 json_object *json_nexthops = NULL;
10184 json_object *json_path = NULL;
10185 json_object *json_peer = NULL;
10186 json_object *json_string = NULL;
10187 json_object *json_adv_to = NULL;
10188 int first = 0;
10189 struct listnode *node, *nnode;
10190 struct peer *peer;
be92fc9f 10191 bool addpath_capable;
d62a17ae 10192 int has_adj;
10193 unsigned int first_as;
1defdda8 10194 bool nexthop_self =
9b6d8fcf 10195 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10196 int i;
2ba93fd6
DA
10197 char *nexthop_hostname =
10198 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10199 uint32_t ttl = 0;
10200 uint32_t bos = 0;
10201 uint32_t exp = 0;
10202 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10203 tag_buf[0] = '\0';
f0cde006
LS
10204 struct bgp_path_info *bpi_ultimate =
10205 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10206
10207 if (json_paths) {
10208 json_path = json_object_new_object();
10209 json_peer = json_object_new_object();
10210 json_nexthop_global = json_object_new_object();
10211 }
10212
8304dabf
AD
10213 if (safi == SAFI_EVPN) {
10214 if (!json_paths)
34c7f35f 10215 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10216 }
10217
44c69747 10218 if (path->extra) {
9b6d8fcf
DS
10219 if (path->extra && path->extra->num_labels) {
10220 bgp_evpn_label2str(path->extra->label,
10221 path->extra->num_labels, tag_buf,
a4d82a8a 10222 sizeof(tag_buf));
d62a17ae 10223 }
d7325ee7 10224 if (safi == SAFI_EVPN) {
44c69747 10225 if (!json_paths) {
44c69747
LK
10226 if (tag_buf[0] != '\0')
10227 vty_out(vty, " VNI %s", tag_buf);
44c69747 10228 } else {
1ce23106 10229 if (tag_buf[0])
77a2f8e5
DA
10230 json_object_string_add(json_path, "vni",
10231 tag_buf);
44c69747 10232 }
d7325ee7 10233 }
d62a17ae 10234 }
d62a17ae 10235
8304dabf
AD
10236 if (safi == SAFI_EVPN
10237 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10238 char gwip_buf[INET6_ADDRSTRLEN];
10239
860e740b
IR
10240 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10241 sizeof(gwip_buf));
8304dabf
AD
10242
10243 if (json_paths)
10244 json_object_string_add(json_path, "gatewayIP",
10245 gwip_buf);
10246 else
10247 vty_out(vty, " Gateway IP %s", gwip_buf);
10248 }
10249
2bf9780b 10250 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10251 vty_out(vty, "\n");
10252
100290e4
SW
10253
10254 if (path->extra && path->extra->parent && !json_paths) {
10255 struct bgp_path_info *parent_ri;
10256 struct bgp_dest *dest, *pdest;
10257
10258 parent_ri = (struct bgp_path_info *)path->extra->parent;
10259 dest = parent_ri->net;
10260 if (dest && dest->pdest) {
10261 pdest = dest->pdest;
10262 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10263 vty_out(vty, " Imported from ");
10264 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10265 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10266 pdest));
10267 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10268 (struct prefix_evpn *)
10269 bgp_dest_get_prefix(dest),
10270 tag_buf);
6012963e 10271 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10272 vty_out(vty, ", L3NHG %s",
6012963e
SW
10273 CHECK_FLAG(
10274 attr->es_flags,
10275 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10276 ? "active"
10277 : "inactive");
10278 vty_out(vty, "\n");
10279
4a8cd6ad
PG
10280 } else {
10281 vty_out(vty, " Imported from ");
10282 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10283 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10284 pdest));
10285 vty_out(vty, ":%pFX\n",
100290e4
SW
10286 (struct prefix_evpn *)
10287 bgp_dest_get_prefix(dest));
4a8cd6ad 10288 }
100290e4
SW
10289 }
10290 }
10291
05864da7
DS
10292 /* Line1 display AS-path, Aggregator */
10293 if (attr->aspath) {
10294 if (json_paths) {
10295 if (!attr->aspath->json)
10296 aspath_str_update(attr->aspath, true);
10297 json_object_lock(attr->aspath->json);
10298 json_object_object_add(json_path, "aspath",
10299 attr->aspath->json);
10300 } else {
10301 if (attr->aspath->segments)
e678b143 10302 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10303 else
05864da7 10304 vty_out(vty, " Local");
d62a17ae 10305 }
05864da7 10306 }
d62a17ae 10307
05864da7
DS
10308 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10309 if (json_paths)
10310 json_object_boolean_true_add(json_path, "removed");
10311 else
10312 vty_out(vty, ", (removed)");
10313 }
d62a17ae 10314
05864da7
DS
10315 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10316 if (json_paths)
10317 json_object_boolean_true_add(json_path, "stale");
10318 else
10319 vty_out(vty, ", (stale)");
10320 }
d62a17ae 10321
05864da7
DS
10322 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10323 if (json_paths) {
10324 json_object_int_add(json_path, "aggregatorAs",
10325 attr->aggregator_as);
c949c771
DA
10326 json_object_string_addf(json_path, "aggregatorId",
10327 "%pI4", &attr->aggregator_addr);
05864da7 10328 } else {
88d495a9
DA
10329 vty_out(vty, ", (aggregated by %u %pI4)",
10330 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10331 }
05864da7 10332 }
d62a17ae 10333
05864da7
DS
10334 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10335 PEER_FLAG_REFLECTOR_CLIENT)) {
10336 if (json_paths)
10337 json_object_boolean_true_add(json_path,
10338 "rxedFromRrClient");
10339 else
10340 vty_out(vty, ", (Received from a RR-client)");
10341 }
d62a17ae 10342
05864da7
DS
10343 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10344 PEER_FLAG_RSERVER_CLIENT)) {
10345 if (json_paths)
10346 json_object_boolean_true_add(json_path,
10347 "rxedFromRsClient");
10348 else
10349 vty_out(vty, ", (Received from a RS-client)");
10350 }
d62a17ae 10351
05864da7
DS
10352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10353 if (json_paths)
10354 json_object_boolean_true_add(json_path,
10355 "dampeningHistoryEntry");
10356 else
10357 vty_out(vty, ", (history entry)");
10358 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path,
10361 "dampeningSuppressed");
10362 else
10363 vty_out(vty, ", (suppressed due to dampening)");
10364 }
d62a17ae 10365
05864da7
DS
10366 if (!json_paths)
10367 vty_out(vty, "\n");
d62a17ae 10368
05864da7
DS
10369 /* Line2 display Next-hop, Neighbor, Router-id */
10370 /* Display the nexthop */
b54892e0 10371
34c7f35f
SW
10372 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10373 p->family == AF_EVPN) &&
7226bc40
TA
10374 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10375 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10376 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10377 || safi == SAFI_EVPN) {
515c2602 10378 if (json_paths) {
c949c771
DA
10379 json_object_string_addf(
10380 json_nexthop_global, "ip", "%pI4",
10381 &attr->mp_nexthop_global_in);
515c2602 10382
939a97f4 10383 if (path->peer->hostname)
515c2602
DA
10384 json_object_string_add(
10385 json_nexthop_global, "hostname",
939a97f4 10386 path->peer->hostname);
aef999a2
DA
10387 } else {
10388 if (nexthop_hostname)
10389 vty_out(vty, " %pI4(%s)",
10390 &attr->mp_nexthop_global_in,
10391 nexthop_hostname);
10392 else
10393 vty_out(vty, " %pI4",
10394 &attr->mp_nexthop_global_in);
10395 }
d62a17ae 10396 } else {
515c2602 10397 if (json_paths) {
c949c771
DA
10398 json_object_string_addf(json_nexthop_global,
10399 "ip", "%pI4",
10400 &attr->nexthop);
515c2602 10401
939a97f4 10402 if (path->peer->hostname)
515c2602
DA
10403 json_object_string_add(
10404 json_nexthop_global, "hostname",
939a97f4 10405 path->peer->hostname);
aef999a2
DA
10406 } else {
10407 if (nexthop_hostname)
10408 vty_out(vty, " %pI4(%s)",
10409 &attr->nexthop,
10410 nexthop_hostname);
10411 else
10412 vty_out(vty, " %pI4",
10413 &attr->nexthop);
10414 }
d62a17ae 10415 }
10416
05864da7
DS
10417 if (json_paths)
10418 json_object_string_add(json_nexthop_global, "afi",
10419 "ipv4");
10420 } else {
10421 if (json_paths) {
c949c771
DA
10422 json_object_string_addf(json_nexthop_global, "ip",
10423 "%pI6",
10424 &attr->mp_nexthop_global);
515c2602 10425
939a97f4 10426 if (path->peer->hostname)
515c2602
DA
10427 json_object_string_add(json_nexthop_global,
10428 "hostname",
939a97f4 10429 path->peer->hostname);
515c2602 10430
05864da7
DS
10431 json_object_string_add(json_nexthop_global, "afi",
10432 "ipv6");
10433 json_object_string_add(json_nexthop_global, "scope",
10434 "global");
10435 } else {
aef999a2
DA
10436 if (nexthop_hostname)
10437 vty_out(vty, " %pI6(%s)",
10438 &attr->mp_nexthop_global,
10439 nexthop_hostname);
10440 else
10441 vty_out(vty, " %pI6",
10442 &attr->mp_nexthop_global);
d62a17ae 10443 }
05864da7 10444 }
d62a17ae 10445
05864da7 10446 /* Display the IGP cost or 'inaccessible' */
f0cde006 10447 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10448 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10449
10450 if (json_paths) {
05864da7
DS
10451 json_object_boolean_false_add(json_nexthop_global,
10452 "accessible");
95ba22d5
DA
10453 json_object_boolean_add(json_nexthop_global,
10454 "importCheckEnabled", import);
10455 } else {
10456 vty_out(vty, " (inaccessible%s)",
10457 import ? ", import-check enabled" : "");
10458 }
05864da7 10459 } else {
f0cde006 10460 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10461 if (json_paths)
f0cde006
LS
10462 json_object_int_add(
10463 json_nexthop_global, "metric",
10464 bpi_ultimate->extra->igpmetric);
d62a17ae 10465 else
05864da7 10466 vty_out(vty, " (metric %u)",
f0cde006 10467 bpi_ultimate->extra->igpmetric);
d62a17ae 10468 }
10469
05864da7 10470 /* IGP cost is 0, display this only for json */
d62a17ae 10471 else {
d62a17ae 10472 if (json_paths)
05864da7
DS
10473 json_object_int_add(json_nexthop_global,
10474 "metric", 0);
d62a17ae 10475 }
d62a17ae 10476
05864da7
DS
10477 if (json_paths)
10478 json_object_boolean_true_add(json_nexthop_global,
10479 "accessible");
10480 }
d62a17ae 10481
05864da7
DS
10482 /* Display peer "from" output */
10483 /* This path was originated locally */
10484 if (path->peer == bgp->peer_self) {
d62a17ae 10485
34c7f35f 10486 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10487 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10488 if (json_paths)
05864da7
DS
10489 json_object_string_add(json_peer, "peerId",
10490 "0.0.0.0");
d62a17ae 10491 else
05864da7
DS
10492 vty_out(vty, " from 0.0.0.0 ");
10493 } else {
d62a17ae 10494 if (json_paths)
05864da7
DS
10495 json_object_string_add(json_peer, "peerId",
10496 "::");
d62a17ae 10497 else
05864da7 10498 vty_out(vty, " from :: ");
d62a17ae 10499 }
d62a17ae 10500
4e9a9863 10501 if (json_paths)
c949c771
DA
10502 json_object_string_addf(json_peer, "routerId", "%pI4",
10503 &bgp->router_id);
4e9a9863 10504 else
23d0a753 10505 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10506 }
d62a17ae 10507
05864da7
DS
10508 /* We RXed this path from one of our peers */
10509 else {
10510
10511 if (json_paths) {
47e12884
DA
10512 json_object_string_addf(json_peer, "peerId", "%pSU",
10513 &path->peer->su);
c949c771
DA
10514 json_object_string_addf(json_peer, "routerId", "%pI4",
10515 &path->peer->remote_id);
05864da7
DS
10516
10517 if (path->peer->hostname)
10518 json_object_string_add(json_peer, "hostname",
10519 path->peer->hostname);
10520
10521 if (path->peer->domainname)
10522 json_object_string_add(json_peer, "domainname",
10523 path->peer->domainname);
10524
10525 if (path->peer->conf_if)
10526 json_object_string_add(json_peer, "interface",
10527 path->peer->conf_if);
10528 } else {
10529 if (path->peer->conf_if) {
10530 if (path->peer->hostname
892fedb6
DA
10531 && CHECK_FLAG(path->peer->bgp->flags,
10532 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10533 vty_out(vty, " from %s(%s)",
10534 path->peer->hostname,
10535 path->peer->conf_if);
d62a17ae 10536 else
05864da7 10537 vty_out(vty, " from %s",
9b6d8fcf 10538 path->peer->conf_if);
d62a17ae 10539 } else {
05864da7 10540 if (path->peer->hostname
892fedb6
DA
10541 && CHECK_FLAG(path->peer->bgp->flags,
10542 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10543 vty_out(vty, " from %s(%s)",
10544 path->peer->hostname,
10545 path->peer->host);
d62a17ae 10546 else
47e12884
DA
10547 vty_out(vty, " from %pSU",
10548 &path->peer->su);
d62a17ae 10549 }
d62a17ae 10550
05864da7 10551 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10552 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10553 else
07380148 10554 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10555 }
05864da7 10556 }
9df8b37c 10557
05864da7
DS
10558 /*
10559 * Note when vrfid of nexthop is different from that of prefix
10560 */
10561 if (path->extra && path->extra->bgp_orig) {
10562 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10563
05864da7
DS
10564 if (json_paths) {
10565 const char *vn;
9df8b37c 10566
05864da7
DS
10567 if (path->extra->bgp_orig->inst_type
10568 == BGP_INSTANCE_TYPE_DEFAULT)
10569 vn = VRF_DEFAULT_NAME;
10570 else
10571 vn = path->extra->bgp_orig->name;
9df8b37c 10572
05864da7 10573 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10574
05864da7
DS
10575 if (nexthop_vrfid == VRF_UNKNOWN) {
10576 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10577 } else {
05864da7
DS
10578 json_object_int_add(json_path, "nhVrfId",
10579 (int)nexthop_vrfid);
9df8b37c 10580 }
05864da7
DS
10581 } else {
10582 if (nexthop_vrfid == VRF_UNKNOWN)
10583 vty_out(vty, " vrf ?");
137147c6
DS
10584 else {
10585 struct vrf *vrf;
10586
10587 vrf = vrf_lookup_by_id(nexthop_vrfid);
10588 vty_out(vty, " vrf %s(%u)",
10589 VRF_LOGNAME(vrf), nexthop_vrfid);
10590 }
9df8b37c 10591 }
05864da7 10592 }
9df8b37c 10593
05864da7
DS
10594 if (nexthop_self) {
10595 if (json_paths) {
10596 json_object_boolean_true_add(json_path,
10597 "announceNexthopSelf");
10598 } else {
10599 vty_out(vty, " announce-nh-self");
9df8b37c 10600 }
05864da7 10601 }
9df8b37c 10602
05864da7
DS
10603 if (!json_paths)
10604 vty_out(vty, "\n");
d62a17ae 10605
05864da7
DS
10606 /* display the link-local nexthop */
10607 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10608 if (json_paths) {
10609 json_nexthop_ll = json_object_new_object();
c949c771
DA
10610 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10611 &attr->mp_nexthop_local);
515c2602 10612
939a97f4 10613 if (path->peer->hostname)
515c2602
DA
10614 json_object_string_add(json_nexthop_ll,
10615 "hostname",
939a97f4 10616 path->peer->hostname);
515c2602 10617
05864da7
DS
10618 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10619 json_object_string_add(json_nexthop_ll, "scope",
10620 "link-local");
d62a17ae 10621
05864da7
DS
10622 json_object_boolean_true_add(json_nexthop_ll,
10623 "accessible");
d62a17ae 10624
2bb8b49c 10625 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10626 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10627 "used");
10628 else
10629 json_object_boolean_true_add(
10630 json_nexthop_global, "used");
10631 } else {
10632 vty_out(vty, " (%s) %s\n",
10633 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10634 buf, INET6_ADDRSTRLEN),
2bb8b49c 10635 attr->mp_nexthop_prefer_global
05864da7
DS
10636 ? "(prefer-global)"
10637 : "(used)");
d62a17ae 10638 }
05864da7
DS
10639 }
10640 /* If we do not have a link-local nexthop then we must flag the
10641 global as "used" */
10642 else {
10643 if (json_paths)
10644 json_object_boolean_true_add(json_nexthop_global,
10645 "used");
10646 }
d62a17ae 10647
b5e140c8 10648 if (safi == SAFI_EVPN &&
5e4d4c8a 10649 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10650 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10651 }
10652
05864da7
DS
10653 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10654 * Int/Ext/Local, Atomic, best */
10655 if (json_paths)
10656 json_object_string_add(json_path, "origin",
10657 bgp_origin_long_str[attr->origin]);
10658 else
10659 vty_out(vty, " Origin %s",
10660 bgp_origin_long_str[attr->origin]);
9df8b37c 10661
05864da7 10662 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10663 if (json_paths)
05864da7 10664 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10665 else
05864da7
DS
10666 vty_out(vty, ", metric %u", attr->med);
10667 }
9df8b37c 10668
05864da7
DS
10669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10670 if (json_paths)
0fbac0b4 10671 json_object_int_add(json_path, "locPrf",
05864da7
DS
10672 attr->local_pref);
10673 else
10674 vty_out(vty, ", localpref %u", attr->local_pref);
10675 }
9df8b37c 10676
97a52c82
DA
10677 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10678 if (json_paths)
10679 json_object_int_add(json_path, "aigpMetric",
10680 bgp_attr_get_aigp_metric(attr));
10681 else
10682 vty_out(vty, ", aigp-metric %" PRIu64,
10683 bgp_attr_get_aigp_metric(attr));
10684 }
10685
05864da7
DS
10686 if (attr->weight != 0) {
10687 if (json_paths)
10688 json_object_int_add(json_path, "weight", attr->weight);
10689 else
10690 vty_out(vty, ", weight %u", attr->weight);
10691 }
9df8b37c 10692
05864da7
DS
10693 if (attr->tag != 0) {
10694 if (json_paths)
10695 json_object_int_add(json_path, "tag", attr->tag);
10696 else
10697 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10698 }
9df8b37c 10699
05864da7
DS
10700 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10701 if (json_paths)
10702 json_object_boolean_false_add(json_path, "valid");
10703 else
10704 vty_out(vty, ", invalid");
10705 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10706 if (json_paths)
10707 json_object_boolean_true_add(json_path, "valid");
10708 else
10709 vty_out(vty, ", valid");
10710 }
9df8b37c 10711
7d3cae70
DA
10712 if (json_paths)
10713 json_object_int_add(json_path, "version", bn->version);
10714
05864da7
DS
10715 if (path->peer != bgp->peer_self) {
10716 if (path->peer->as == path->peer->local_as) {
10717 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10718 if (json_paths)
10719 json_object_string_add(
10720 json_peer, "type",
10721 "confed-internal");
d62a17ae 10722 else
05864da7 10723 vty_out(vty, ", confed-internal");
d62a17ae 10724 } else {
05864da7
DS
10725 if (json_paths)
10726 json_object_string_add(
10727 json_peer, "type", "internal");
10728 else
10729 vty_out(vty, ", internal");
9df8b37c 10730 }
05864da7
DS
10731 } else {
10732 if (bgp_confederation_peers_check(bgp,
10733 path->peer->as)) {
10734 if (json_paths)
10735 json_object_string_add(
10736 json_peer, "type",
10737 "confed-external");
d62a17ae 10738 else
05864da7 10739 vty_out(vty, ", confed-external");
d62a17ae 10740 } else {
05864da7
DS
10741 if (json_paths)
10742 json_object_string_add(
10743 json_peer, "type", "external");
10744 else
10745 vty_out(vty, ", external");
d62a17ae 10746 }
10747 }
05864da7
DS
10748 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10749 if (json_paths) {
10750 json_object_boolean_true_add(json_path, "aggregated");
10751 json_object_boolean_true_add(json_path, "local");
10752 } else {
10753 vty_out(vty, ", aggregated, local");
10754 }
10755 } else if (path->type != ZEBRA_ROUTE_BGP) {
10756 if (json_paths)
10757 json_object_boolean_true_add(json_path, "sourced");
10758 else
10759 vty_out(vty, ", sourced");
10760 } else {
10761 if (json_paths) {
10762 json_object_boolean_true_add(json_path, "sourced");
10763 json_object_boolean_true_add(json_path, "local");
10764 } else {
10765 vty_out(vty, ", sourced, local");
d62a17ae 10766 }
05864da7 10767 }
718e3744 10768
05864da7 10769 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10770 if (json_paths)
05864da7
DS
10771 json_object_boolean_true_add(json_path,
10772 "atomicAggregate");
d62a17ae 10773 else
05864da7
DS
10774 vty_out(vty, ", atomic-aggregate");
10775 }
d62a17ae 10776
d864dd9e
EB
10777 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10778 if (json_paths)
10779 json_object_int_add(json_path, "otc", attr->otc);
10780 else
10781 vty_out(vty, ", otc %u", attr->otc);
10782 }
10783
05864da7
DS
10784 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10785 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10786 && bgp_path_info_mpath_count(path))) {
10787 if (json_paths)
10788 json_object_boolean_true_add(json_path, "multipath");
10789 else
10790 vty_out(vty, ", multipath");
10791 }
50e05855 10792
05864da7
DS
10793 // Mark the bestpath(s)
10794 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10795 first_as = aspath_get_first_as(attr->aspath);
718e3744 10796
05864da7
DS
10797 if (json_paths) {
10798 if (!json_bestpath)
10799 json_bestpath = json_object_new_object();
10800 json_object_int_add(json_bestpath, "bestpathFromAs",
10801 first_as);
10802 } else {
10803 if (first_as)
10804 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10805 else
05864da7 10806 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10807 }
05864da7 10808 }
718e3744 10809
05864da7
DS
10810 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10811 if (json_paths) {
10812 if (!json_bestpath)
10813 json_bestpath = json_object_new_object();
10814 json_object_boolean_true_add(json_bestpath, "overall");
10815 json_object_string_add(
10816 json_bestpath, "selectionReason",
10817 bgp_path_selection_reason2str(bn->reason));
10818 } else {
10819 vty_out(vty, ", best");
10820 vty_out(vty, " (%s)",
10821 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10822 }
05864da7 10823 }
718e3744 10824
4027d19b 10825 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10826 if (json_paths)
10827 json_object_string_add(
10828 json_path, "rpkiValidationState",
4027d19b 10829 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10830 else
1d327209 10831 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10832 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10833 }
10834
05864da7
DS
10835 if (json_bestpath)
10836 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10837
05864da7
DS
10838 if (!json_paths)
10839 vty_out(vty, "\n");
10840
10841 /* Line 4 display Community */
29e72930 10842 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10843 if (json_paths) {
9a706b42
DA
10844 if (!bgp_attr_get_community(attr)->json)
10845 community_str(bgp_attr_get_community(attr),
c0945b78 10846 true, true);
9a706b42
DA
10847 json_object_lock(bgp_attr_get_community(attr)->json);
10848 json_object_object_add(
10849 json_path, "community",
10850 bgp_attr_get_community(attr)->json);
05864da7
DS
10851 } else {
10852 vty_out(vty, " Community: %s\n",
9a706b42 10853 bgp_attr_get_community(attr)->str);
d62a17ae 10854 }
05864da7 10855 }
718e3744 10856
05864da7
DS
10857 /* Line 5 display Extended-community */
10858 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10859 if (json_paths) {
10860 json_ext_community = json_object_new_object();
b53e67a3
DA
10861 json_object_string_add(
10862 json_ext_community, "string",
10863 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10864 json_object_object_add(json_path, "extendedCommunity",
10865 json_ext_community);
d62a17ae 10866 } else {
05864da7 10867 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10868 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10869 }
05864da7 10870 }
718e3744 10871
05864da7
DS
10872 /* Line 6 display Large community */
10873 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10874 if (json_paths) {
1bcf3a96
DA
10875 if (!bgp_attr_get_lcommunity(attr)->json)
10876 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10877 true, true);
1bcf3a96
DA
10878 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10879 json_object_object_add(
10880 json_path, "largeCommunity",
10881 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10882 } else {
10883 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10884 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10885 }
05864da7 10886 }
718e3744 10887
05864da7
DS
10888 /* Line 7 display Originator, Cluster-id */
10889 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10890 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10891 char buf[BUFSIZ] = {0};
10892
05864da7 10893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10894 if (json_paths)
c949c771
DA
10895 json_object_string_addf(json_path,
10896 "originatorId", "%pI4",
10897 &attr->originator_id);
d62a17ae 10898 else
23d0a753
DA
10899 vty_out(vty, " Originator: %pI4",
10900 &attr->originator_id);
d62a17ae 10901 }
856ca177 10902
05864da7 10903 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10904 struct cluster_list *cluster =
10905 bgp_attr_get_cluster(attr);
05864da7 10906 int i;
d62a17ae 10907
10908 if (json_paths) {
05864da7
DS
10909 json_cluster_list = json_object_new_object();
10910 json_cluster_list_list =
10911 json_object_new_array();
10912
779fee93 10913 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10914 json_string = json_object_new_string(
779fee93
DS
10915 inet_ntop(AF_INET,
10916 &cluster->list[i],
10917 buf, sizeof(buf)));
05864da7
DS
10918 json_object_array_add(
10919 json_cluster_list_list,
10920 json_string);
10921 }
718e3744 10922
05864da7
DS
10923 /*
10924 * struct cluster_list does not have
10925 * "str" variable like aspath and community
10926 * do. Add this someday if someone asks
10927 * for it.
10928 * json_object_string_add(json_cluster_list,
779fee93 10929 * "string", cluster->str);
05864da7
DS
10930 */
10931 json_object_object_add(json_cluster_list,
10932 "list",
10933 json_cluster_list_list);
10934 json_object_object_add(json_path, "clusterList",
10935 json_cluster_list);
0dc8ee70 10936 } else {
05864da7
DS
10937 vty_out(vty, ", Cluster list: ");
10938
779fee93 10939 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10940 vty_out(vty, "%pI4 ",
779fee93 10941 &cluster->list[i]);
05864da7 10942 }
0dc8ee70 10943 }
d62a17ae 10944 }
718e3744 10945
d62a17ae 10946 if (!json_paths)
10947 vty_out(vty, "\n");
05864da7 10948 }
d62a17ae 10949
05864da7 10950 if (path->extra && path->extra->damp_info)
b4f7f45b 10951 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10952
05864da7
DS
10953 /* Remote Label */
10954 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10955 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10956 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10957 &bos);
d62a17ae 10958
05864da7
DS
10959 if (json_paths)
10960 json_object_int_add(json_path, "remoteLabel", label);
10961 else
10962 vty_out(vty, " Remote label: %d\n", label);
10963 }
d62a17ae 10964
e496b420
HS
10965 /* Remote SID */
10966 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10967 if (json_paths)
07380148
DA
10968 json_object_string_addf(json_path, "remoteSid", "%pI6",
10969 &path->extra->sid[0].sid);
e496b420 10970 else
07380148
DA
10971 vty_out(vty, " Remote SID: %pI6\n",
10972 &path->extra->sid[0].sid);
e496b420
HS
10973 }
10974
05864da7
DS
10975 /* Label Index */
10976 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10977 if (json_paths)
10978 json_object_int_add(json_path, "labelIndex",
10979 attr->label_index);
10980 else
10981 vty_out(vty, " Label Index: %d\n",
10982 attr->label_index);
10983 }
d62a17ae 10984
05864da7
DS
10985 /* Line 8 display Addpath IDs */
10986 if (path->addpath_rx_id
10987 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10988 if (json_paths) {
10989 json_object_int_add(json_path, "addpathRxId",
10990 path->addpath_rx_id);
d62a17ae 10991
05864da7
DS
10992 /* Keep backwards compatibility with the old API
10993 * by putting TX All's ID in the old field
10994 */
10995 json_object_int_add(
10996 json_path, "addpathTxId",
10997 path->tx_addpath
10998 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10999
05864da7
DS
11000 /* ... but create a specific field for each
11001 * strategy
11002 */
11003 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11004 json_object_int_add(
11005 json_path,
11006 bgp_addpath_names(i)->id_json_name,
11007 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11008 }
05864da7
DS
11009 } else {
11010 vty_out(vty, " AddPath ID: RX %u, ",
11011 path->addpath_rx_id);
d62a17ae 11012
05864da7 11013 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11014 }
05864da7 11015 }
520d5d76 11016
05864da7
DS
11017 /* If we used addpath to TX a non-bestpath we need to display
11018 * "Advertised to" on a path-by-path basis
11019 */
11020 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11021 first = 1;
dcc68b5e 11022
05864da7
DS
11023 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11024 addpath_capable =
11025 bgp_addpath_encode_tx(peer, afi, safi);
11026 has_adj = bgp_adj_out_lookup(
11027 peer, path->net,
11028 bgp_addpath_id_for_peer(peer, afi, safi,
11029 &path->tx_addpath));
11030
11031 if ((addpath_capable && has_adj)
11032 || (!addpath_capable && has_adj
11033 && CHECK_FLAG(path->flags,
11034 BGP_PATH_SELECTED))) {
11035 if (json_path && !json_adv_to)
11036 json_adv_to = json_object_new_object();
dcc68b5e 11037
05864da7
DS
11038 route_vty_out_advertised_to(
11039 vty, peer, &first,
11040 " Advertised to:", json_adv_to);
d62a17ae 11041 }
11042 }
718e3744 11043
05864da7
DS
11044 if (json_path) {
11045 if (json_adv_to) {
11046 json_object_object_add(
11047 json_path, "advertisedTo", json_adv_to);
d62a17ae 11048 }
05864da7
DS
11049 } else {
11050 if (!first) {
11051 vty_out(vty, "\n");
d62a17ae 11052 }
11053 }
05864da7 11054 }
b05a1c8b 11055
05864da7 11056 /* Line 9 display Uptime */
083ec940 11057 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11058 if (json_paths) {
11059 json_last_update = json_object_new_object();
11060 json_object_int_add(json_last_update, "epoch", tbuf);
11061 json_object_string_add(json_last_update, "string",
11062 ctime(&tbuf));
11063 json_object_object_add(json_path, "lastUpdate",
11064 json_last_update);
11065 } else
11066 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11067
05864da7
DS
11068 /* Line 10 display PMSI tunnel attribute, if present */
11069 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11070 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11071 bgp_attr_get_pmsi_tnl_type(attr),
11072 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11073
05864da7
DS
11074 if (json_paths) {
11075 json_pmsi = json_object_new_object();
11076 json_object_string_add(json_pmsi, "tunnelType", str);
11077 json_object_int_add(json_pmsi, "label",
11078 label2vni(&attr->label));
11079 json_object_object_add(json_path, "pmsi", json_pmsi);
11080 } else
11081 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11082 str, label2vni(&attr->label));
d62a17ae 11083 }
f1aa5d8a 11084
848e8cf6
DA
11085 if (path->peer->t_gr_restart &&
11086 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11087 unsigned long gr_remaining =
11088 thread_timer_remain_second(path->peer->t_gr_restart);
11089
11090 if (json_paths) {
11091 json_object_int_add(json_path,
11092 "gracefulRestartSecondsRemaining",
11093 gr_remaining);
11094 } else
11095 vty_out(vty,
11096 " Time until Graceful Restart stale route deleted: %lu\n",
11097 gr_remaining);
11098 }
11099
9a706b42
DA
11100 if (path->peer->t_llgr_stale[afi][safi] &&
11101 bgp_attr_get_community(attr) &&
11102 community_include(bgp_attr_get_community(attr),
11103 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11104 unsigned long llgr_remaining = thread_timer_remain_second(
11105 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11106
48ebba04
DA
11107 if (json_paths) {
11108 json_object_int_add(json_path, "llgrSecondsRemaining",
11109 llgr_remaining);
11110 } else
11111 vty_out(vty,
11112 " Time until Long-lived stale route deleted: %lu\n",
11113 llgr_remaining);
11114 }
11115
92269aa2
DS
11116 /* Output some debug about internal state of the dest flags */
11117 if (json_paths) {
11118 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11119 json_object_boolean_true_add(json_path, "processScheduled");
11120 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11121 json_object_boolean_true_add(json_path, "userCleared");
11122 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11123 json_object_boolean_true_add(json_path, "labelChanged");
11124 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11125 json_object_boolean_true_add(json_path, "registeredForLabel");
11126 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11127 json_object_boolean_true_add(json_path, "selectDefered");
11128 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11129 json_object_boolean_true_add(json_path, "fibInstalled");
11130 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11131 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11132
d62a17ae 11133 if (json_nexthop_global || json_nexthop_ll) {
11134 json_nexthops = json_object_new_array();
f1aa5d8a 11135
d62a17ae 11136 if (json_nexthop_global)
11137 json_object_array_add(json_nexthops,
11138 json_nexthop_global);
f1aa5d8a 11139
d62a17ae 11140 if (json_nexthop_ll)
11141 json_object_array_add(json_nexthops,
11142 json_nexthop_ll);
f1aa5d8a 11143
d62a17ae 11144 json_object_object_add(json_path, "nexthops",
11145 json_nexthops);
11146 }
11147
11148 json_object_object_add(json_path, "peer", json_peer);
11149 json_object_array_add(json_paths, json_path);
05864da7 11150 }
b366b518
BB
11151}
11152
96ade3ed 11153#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11154#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11155#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11156
a4d82a8a 11157static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11158 afi_t afi, safi_t safi, enum bgp_show_type type,
11159 bool use_json);
7f323236
DW
11160static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11161 const char *comstr, int exact, afi_t afi,
96c81f66 11162 safi_t safi, uint16_t show_flags);
d62a17ae 11163
1ae44dfc 11164static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11165 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11166 void *output_arg, const char *rd, int is_last,
96f3485c 11167 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11168 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11169 enum rpki_states rpki_target_state)
d62a17ae 11170{
40381db7 11171 struct bgp_path_info *pi;
9bcb3eef 11172 struct bgp_dest *dest;
2aad8c42
MS
11173 bool header = true;
11174 bool json_detail_header = false;
d62a17ae 11175 int display;
1ae44dfc
LB
11176 unsigned long output_count = 0;
11177 unsigned long total_count = 0;
d62a17ae 11178 struct prefix *p;
d62a17ae 11179 json_object *json_paths = NULL;
11180 int first = 1;
96f3485c
MK
11181 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11182 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11183 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11184 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11185 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11186
1ae44dfc 11187 if (output_cum && *output_cum != 0)
2aad8c42 11188 header = false;
1ae44dfc 11189
9386b588 11190 if (use_json && !*json_header_depth) {
96f3485c
MK
11191 if (all)
11192 *json_header_depth = 1;
11193 else {
11194 vty_out(vty, "{\n");
11195 *json_header_depth = 2;
11196 }
d62a17ae 11197 vty_out(vty,
23d0a753
DA
11198 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11199 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11200 " \"localAS\": ",
a8bf7d9c 11201 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11202 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11203 ? VRF_DEFAULT_NAME
11204 : bgp->name,
11205 table->version, &bgp->router_id,
e84c7c12
PG
11206 bgp->default_local_pref);
11207 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11208 ((bgp->asnotation == ASNOTATION_DOT) &&
11209 (bgp->as < UINT16_MAX)))
11210 vty_out(vty, "%u", bgp->as);
11211 else {
11212 vty_out(vty, "\"");
11213 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11214 vty_out(vty, "\"");
11215 }
11216 vty_out(vty, ",\n \"routes\": { ");
9386b588 11217 if (rd) {
445c2480 11218 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11219 ++*json_header_depth;
11220 }
d62a17ae 11221 }
718e3744 11222
445c2480
DS
11223 if (use_json && rd) {
11224 vty_out(vty, " \"%s\" : { ", rd);
11225 }
11226
2aad8c42 11227 /* Check for 'json detail', where we need header output once per dest */
67799a48 11228 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11229 type != bgp_show_type_damp_neighbor &&
11230 type != bgp_show_type_flap_statistics &&
11231 type != bgp_show_type_flap_neighbor)
11232 json_detail_header = true;
11233
d62a17ae 11234 /* Start processing of routes. */
9bcb3eef
DS
11235 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11236 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11237 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11238 bool json_detail_header_used = false;
b54892e0 11239
9bcb3eef 11240 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11241 if (pi == NULL)
98ce9a06 11242 continue;
d62a17ae 11243
98ce9a06 11244 display = 0;
98ce9a06
DS
11245 if (use_json)
11246 json_paths = json_object_new_array();
11247 else
11248 json_paths = NULL;
d62a17ae 11249
6f94b685 11250 for (; pi; pi = pi->next) {
9a706b42
DA
11251 struct community *picomm = NULL;
11252
11253 picomm = bgp_attr_get_community(pi->attr);
11254
98ce9a06 11255 total_count++;
1e2ce4f1 11256
7d3cae70
DA
11257 if (type == bgp_show_type_prefix_version) {
11258 uint32_t version =
11259 strtoul(output_arg, NULL, 10);
11260 if (dest->version < version)
11261 continue;
11262 }
11263
a70a28a5
DA
11264 if (type == bgp_show_type_community_alias) {
11265 char *alias = output_arg;
11266 char **communities;
11267 int num;
11268 bool found = false;
11269
9a706b42
DA
11270 if (picomm) {
11271 frrstr_split(picomm->str, " ",
11272 &communities, &num);
a70a28a5
DA
11273 for (int i = 0; i < num; i++) {
11274 const char *com2alias =
11275 bgp_community2alias(
11276 communities[i]);
cd9cc0e6
IR
11277 if (!found
11278 && strcmp(alias, com2alias)
11279 == 0)
a70a28a5 11280 found = true;
cd9cc0e6
IR
11281 XFREE(MTYPE_TMP,
11282 communities[i]);
a70a28a5 11283 }
cd9cc0e6 11284 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11285 }
11286
1bcf3a96
DA
11287 if (!found &&
11288 bgp_attr_get_lcommunity(pi->attr)) {
11289 frrstr_split(bgp_attr_get_lcommunity(
11290 pi->attr)
11291 ->str,
a70a28a5
DA
11292 " ", &communities, &num);
11293 for (int i = 0; i < num; i++) {
11294 const char *com2alias =
11295 bgp_community2alias(
11296 communities[i]);
cd9cc0e6
IR
11297 if (!found
11298 && strcmp(alias, com2alias)
11299 == 0)
a70a28a5 11300 found = true;
cd9cc0e6
IR
11301 XFREE(MTYPE_TMP,
11302 communities[i]);
a70a28a5 11303 }
cd9cc0e6 11304 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11305 }
11306
11307 if (!found)
11308 continue;
11309 }
11310
1e2ce4f1
DS
11311 if (type == bgp_show_type_rpki) {
11312 if (dest_p->family == AF_INET
11313 || dest_p->family == AF_INET6)
4027d19b 11314 rpki_curr_state = hook_call(
1e2ce4f1
DS
11315 bgp_rpki_prefix_status,
11316 pi->peer, pi->attr, dest_p);
4027d19b
DS
11317 if (rpki_target_state != RPKI_NOT_BEING_USED
11318 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11319 continue;
11320 }
11321
98ce9a06
DS
11322 if (type == bgp_show_type_flap_statistics
11323 || type == bgp_show_type_flap_neighbor
11324 || type == bgp_show_type_dampend_paths
11325 || type == bgp_show_type_damp_neighbor) {
40381db7 11326 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11327 continue;
11328 }
11329 if (type == bgp_show_type_regexp) {
11330 regex_t *regex = output_arg;
d62a17ae 11331
40381db7 11332 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11333 == REG_NOMATCH)
11334 continue;
11335 }
11336 if (type == bgp_show_type_prefix_list) {
11337 struct prefix_list *plist = output_arg;
d62a17ae 11338
9bcb3eef 11339 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11340 != PREFIX_PERMIT)
11341 continue;
11342 }
ed126382
DA
11343 if (type == bgp_show_type_access_list) {
11344 struct access_list *alist = output_arg;
11345
11346 if (access_list_apply(alist, dest_p) !=
11347 FILTER_PERMIT)
11348 continue;
11349 }
98ce9a06
DS
11350 if (type == bgp_show_type_filter_list) {
11351 struct as_list *as_list = output_arg;
d62a17ae 11352
40381db7 11353 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11354 != AS_FILTER_PERMIT)
11355 continue;
11356 }
11357 if (type == bgp_show_type_route_map) {
11358 struct route_map *rmap = output_arg;
9b6d8fcf 11359 struct bgp_path_info path;
636632c3
DA
11360 struct bgp_path_info_extra extra;
11361 struct attr dummy_attr = {};
b68885f9 11362 route_map_result_t ret;
d62a17ae 11363
6f4f49b2 11364 dummy_attr = *pi->attr;
d62a17ae 11365
636632c3
DA
11366 prep_for_rmap_apply(&path, &extra, dest, pi,
11367 pi->peer, &dummy_attr);
d62a17ae 11368
1782514f 11369 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11370 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11371 if (ret == RMAP_DENYMATCH)
11372 continue;
11373 }
11374 if (type == bgp_show_type_neighbor
11375 || type == bgp_show_type_flap_neighbor
11376 || type == bgp_show_type_damp_neighbor) {
11377 union sockunion *su = output_arg;
11378
40381db7
DS
11379 if (pi->peer == NULL
11380 || pi->peer->su_remote == NULL
11381 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11382 continue;
11383 }
11384 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11385 uint32_t destination;
d62a17ae 11386
9bcb3eef 11387 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11388 if (IN_CLASSC(destination)
9bcb3eef 11389 && dest_p->prefixlen == 24)
98ce9a06
DS
11390 continue;
11391 if (IN_CLASSB(destination)
9bcb3eef 11392 && dest_p->prefixlen == 16)
98ce9a06
DS
11393 continue;
11394 if (IN_CLASSA(destination)
9bcb3eef 11395 && dest_p->prefixlen == 8)
98ce9a06
DS
11396 continue;
11397 }
11398 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11399 p = output_arg;
9bcb3eef 11400 if (!prefix_match(p, dest_p))
98ce9a06
DS
11401 continue;
11402 }
11403 if (type == bgp_show_type_community_all) {
9a706b42 11404 if (!picomm)
98ce9a06
DS
11405 continue;
11406 }
11407 if (type == bgp_show_type_community) {
11408 struct community *com = output_arg;
d62a17ae 11409
9a706b42 11410 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11411 continue;
11412 }
11413 if (type == bgp_show_type_community_exact) {
11414 struct community *com = output_arg;
d62a17ae 11415
9a706b42 11416 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11417 continue;
11418 }
11419 if (type == bgp_show_type_community_list) {
11420 struct community_list *list = output_arg;
d62a17ae 11421
9a706b42 11422 if (!community_list_match(picomm, list))
98ce9a06
DS
11423 continue;
11424 }
a4d82a8a 11425 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11426 struct community_list *list = output_arg;
d62a17ae 11427
9a706b42 11428 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11429 continue;
11430 }
11431 if (type == bgp_show_type_lcommunity) {
11432 struct lcommunity *lcom = output_arg;
d62a17ae 11433
1bcf3a96
DA
11434 if (!bgp_attr_get_lcommunity(pi->attr) ||
11435 !lcommunity_match(
11436 bgp_attr_get_lcommunity(pi->attr),
11437 lcom))
98ce9a06
DS
11438 continue;
11439 }
36a206db 11440
11441 if (type == bgp_show_type_lcommunity_exact) {
11442 struct lcommunity *lcom = output_arg;
11443
1bcf3a96
DA
11444 if (!bgp_attr_get_lcommunity(pi->attr) ||
11445 !lcommunity_cmp(
11446 bgp_attr_get_lcommunity(pi->attr),
11447 lcom))
36a206db 11448 continue;
11449 }
98ce9a06
DS
11450 if (type == bgp_show_type_lcommunity_list) {
11451 struct community_list *list = output_arg;
d62a17ae 11452
1bcf3a96
DA
11453 if (!lcommunity_list_match(
11454 bgp_attr_get_lcommunity(pi->attr),
11455 list))
98ce9a06
DS
11456 continue;
11457 }
36a206db 11458 if (type
11459 == bgp_show_type_lcommunity_list_exact) {
11460 struct community_list *list = output_arg;
11461
11462 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11463 bgp_attr_get_lcommunity(pi->attr),
11464 list))
36a206db 11465 continue;
11466 }
98ce9a06 11467 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11468 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11469 continue;
11470 }
11471 if (type == bgp_show_type_dampend_paths
11472 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11473 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11474 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11475 continue;
11476 }
83856649
KQ
11477 if (type == bgp_show_type_self_originated) {
11478 if (pi->peer != bgp->peer_self)
11479 continue;
11480 }
98ce9a06
DS
11481
11482 if (!use_json && header) {
23d0a753
DA
11483 vty_out(vty,
11484 "BGP table version is %" PRIu64
11485 ", local router ID is %pI4, vrf id ",
11486 table->version, &bgp->router_id);
9df8b37c
PZ
11487 if (bgp->vrf_id == VRF_UNKNOWN)
11488 vty_out(vty, "%s", VRFID_NONE_STR);
11489 else
11490 vty_out(vty, "%u", bgp->vrf_id);
11491 vty_out(vty, "\n");
01eced22
AD
11492 vty_out(vty, "Default local pref %u, ",
11493 bgp->default_local_pref);
e84c7c12
PG
11494 vty_out(vty, "local AS ");
11495 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11496 &bgp->as);
11497 vty_out(vty, "\n");
509d82bd 11498 if (!detail_routes) {
9a1aae2d
DA
11499 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11500 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11501 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11502 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11503 }
d62a17ae 11504 if (type == bgp_show_type_dampend_paths
11505 || type == bgp_show_type_damp_neighbor)
98ce9a06 11506 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11507 else if (type == bgp_show_type_flap_statistics
11508 || type == bgp_show_type_flap_neighbor)
98ce9a06 11509 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11510 else if (!detail_routes)
ae248832
MK
11511 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11512 : BGP_SHOW_HEADER));
2aad8c42
MS
11513 header = false;
11514
d62a17ae 11515 }
98ce9a06
DS
11516 if (rd != NULL && !display && !output_count) {
11517 if (!use_json)
11518 vty_out(vty,
11519 "Route Distinguisher: %s\n",
11520 rd);
d62a17ae 11521 }
98ce9a06
DS
11522 if (type == bgp_show_type_dampend_paths
11523 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11524 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11525 AFI_IP, safi, use_json,
11526 json_paths);
98ce9a06
DS
11527 else if (type == bgp_show_type_flap_statistics
11528 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11529 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11530 AFI_IP, safi, use_json,
11531 json_paths);
f280c93b 11532 else {
27bb782a
DA
11533 if (detail_routes || detail_json) {
11534 const struct prefix_rd *prd = NULL;
9a1aae2d 11535
27bb782a
DA
11536 if (dest->pdest)
11537 prd = bgp_rd_from_dest(
11538 dest->pdest, safi);
9a1aae2d
DA
11539
11540 if (!use_json)
11541 route_vty_out_detail_header(
11542 vty, bgp, dest,
11543 bgp_dest_get_prefix(
11544 dest),
11545 prd, table->afi, safi,
f9f2d188 11546 NULL, false);
9a1aae2d 11547
f280c93b 11548 route_vty_out_detail(
27bb782a 11549 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11550 family2afi(dest_p->family),
11551 safi, RPKI_NOT_BEING_USED,
11552 json_paths);
9a1aae2d 11553 } else {
f280c93b
DA
11554 route_vty_out(vty, dest_p, pi, display,
11555 safi, json_paths, wide);
9a1aae2d 11556 }
f280c93b 11557 }
98ce9a06 11558 display++;
d62a17ae 11559 }
11560
98ce9a06
DS
11561 if (display) {
11562 output_count++;
11563 if (!use_json)
11564 continue;
11565
625d2931 11566 /* encode prefix */
9bcb3eef 11567 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11568 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11569
1840384b 11570
b54892e0
DS
11571 bgp_fs_nlri_get_string(
11572 (unsigned char *)
9bcb3eef
DS
11573 dest_p->u.prefix_flowspec.ptr,
11574 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11575 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11576 family2afi(dest_p->u
11577 .prefix_flowspec.family));
625d2931 11578 if (first)
b54892e0 11579 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11580 dest_p->u.prefix_flowspec
b54892e0 11581 .prefixlen);
625d2931 11582 else
b54892e0 11583 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11584 dest_p->u.prefix_flowspec
b54892e0 11585 .prefixlen);
625d2931 11586 } else {
625d2931 11587 if (first)
1b78780b 11588 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11589 else
1b78780b 11590 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11591 }
f9f2d188
TA
11592
11593 if (json_detail_header && json_paths != NULL) {
11594 const struct prefix_rd *prd;
11595
11596 vty_out(vty, "{\n");
11597
11598 prd = bgp_rd_from_dest(dest, safi);
11599
11600 route_vty_out_detail_header(
11601 vty, bgp, dest,
11602 bgp_dest_get_prefix(dest), prd,
11603 table->afi, safi, json_paths, true);
11604
11605 vty_out(vty, "\"paths\": ");
11606 json_detail_header_used = true;
11607 }
11608
d7c6467b
DS
11609 /*
11610 * We are using no_pretty here because under
11611 * extremely high settings( say lots and lots of
11612 * routes with lots and lots of ways to reach
11613 * that route via different paths ) this can
11614 * save several minutes of output when FRR
11615 * is run on older cpu's or more underperforming
11616 * routers out there
11617 */
11618 vty_json_no_pretty(vty, json_paths);
f9f2d188
TA
11619
11620 if (json_detail_header_used)
11621 vty_out(vty, "} ");
11622
449feb8e 11623 json_paths = NULL;
98ce9a06 11624 first = 0;
1f83ed02
DS
11625 } else
11626 json_object_free(json_paths);
98ce9a06
DS
11627 }
11628
1ae44dfc
LB
11629 if (output_cum) {
11630 output_count += *output_cum;
11631 *output_cum = output_count;
11632 }
11633 if (total_cum) {
11634 total_count += *total_cum;
11635 *total_cum = total_count;
11636 }
d62a17ae 11637 if (use_json) {
9386b588 11638 if (rd) {
a4d82a8a 11639 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11640 }
11641 if (is_last) {
a4d82a8a
PZ
11642 unsigned long i;
11643 for (i = 0; i < *json_header_depth; ++i)
11644 vty_out(vty, " } ");
96f3485c
MK
11645 if (!all)
11646 vty_out(vty, "\n");
9386b588 11647 }
d62a17ae 11648 } else {
1ae44dfc
LB
11649 if (is_last) {
11650 /* No route is displayed */
11651 if (output_count == 0) {
11652 if (type == bgp_show_type_normal)
11653 vty_out(vty,
11654 "No BGP prefixes displayed, %ld exist\n",
11655 total_count);
11656 } else
d62a17ae 11657 vty_out(vty,
1ae44dfc
LB
11658 "\nDisplayed %ld routes and %ld total paths\n",
11659 output_count, total_count);
11660 }
d62a17ae 11661 }
718e3744 11662
d62a17ae 11663 return CMD_SUCCESS;
718e3744 11664}
11665
1ae44dfc
LB
11666int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11667 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11668 enum bgp_show_type type, void *output_arg,
11669 uint16_t show_flags)
1ae44dfc 11670{
9bcb3eef 11671 struct bgp_dest *dest, *next;
1ae44dfc
LB
11672 unsigned long output_cum = 0;
11673 unsigned long total_cum = 0;
9386b588 11674 unsigned long json_header_depth = 0;
67009e22 11675 struct bgp_table *itable;
0136788c 11676 bool show_msg;
27bb782a 11677 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11678
11679 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11680
9bcb3eef
DS
11681 for (dest = bgp_table_top(table); dest; dest = next) {
11682 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11683
9bcb3eef
DS
11684 next = bgp_route_next(dest);
11685 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11686 continue;
67009e22 11687
9bcb3eef 11688 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11689 if (itable != NULL) {
1ae44dfc 11690 struct prefix_rd prd;
06b9f471 11691 char rd[RD_ADDRSTRLEN];
1ae44dfc 11692
9bcb3eef 11693 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11694 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11695 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11696 rd, next == NULL, &output_cum,
11697 &total_cum, &json_header_depth,
1e2ce4f1 11698 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11699 if (next == NULL)
11700 show_msg = false;
1ae44dfc
LB
11701 }
11702 }
0136788c
LB
11703 if (show_msg) {
11704 if (output_cum == 0)
11705 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11706 total_cum);
11707 else
11708 vty_out(vty,
11709 "\nDisplayed %ld routes and %ld total paths\n",
11710 output_cum, total_cum);
0224b329
DA
11711 } else {
11712 if (use_json && output_cum == 0)
11713 vty_out(vty, "{}\n");
0136788c 11714 }
1ae44dfc
LB
11715 return CMD_SUCCESS;
11716}
2aad8c42 11717
d62a17ae 11718static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11719 enum bgp_show_type type, void *output_arg,
96c81f66 11720 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11721{
d62a17ae 11722 struct bgp_table *table;
9386b588 11723 unsigned long json_header_depth = 0;
96f3485c 11724 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11725
d62a17ae 11726 if (bgp == NULL) {
11727 bgp = bgp_get_default();
11728 }
fee0f4c6 11729
d62a17ae 11730 if (bgp == NULL) {
11731 if (!use_json)
11732 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11733 else
11734 vty_out(vty, "{}\n");
d62a17ae 11735 return CMD_WARNING;
11736 }
4dd6177e 11737
cd8c2a27
MS
11738 /* Labeled-unicast routes live in the unicast table. */
11739 if (safi == SAFI_LABELED_UNICAST)
11740 safi = SAFI_UNICAST;
11741
1ae44dfc 11742 table = bgp->rib[afi][safi];
d62a17ae 11743 /* use MPLS and ENCAP specific shows until they are merged */
11744 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11745 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11746 output_arg, show_flags);
d62a17ae 11747 }
dba3c1d3
PG
11748
11749 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11750 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11751 output_arg, use_json,
11752 1, NULL, NULL);
11753 }
fee0f4c6 11754
0adc5bbb
LS
11755 if (safi == SAFI_EVPN)
11756 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11757
96f3485c 11758 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11759 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11760 rpki_target_state);
fee0f4c6 11761}
11762
d62a17ae 11763static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11764 safi_t safi, uint16_t show_flags)
f186de26 11765{
d62a17ae 11766 struct listnode *node, *nnode;
11767 struct bgp *bgp;
11768 int is_first = 1;
9f049418 11769 bool route_output = false;
96f3485c 11770 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11771
d62a17ae 11772 if (use_json)
11773 vty_out(vty, "{\n");
9f689658 11774
d62a17ae 11775 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11776 route_output = true;
d62a17ae 11777 if (use_json) {
11778 if (!is_first)
11779 vty_out(vty, ",\n");
11780 else
11781 is_first = 0;
11782
11783 vty_out(vty, "\"%s\":",
11784 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11785 ? VRF_DEFAULT_NAME
d62a17ae 11786 : bgp->name);
11787 } else {
11788 vty_out(vty, "\nInstance %s:\n",
11789 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11790 ? VRF_DEFAULT_NAME
d62a17ae 11791 : bgp->name);
11792 }
11793 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11794 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11795 }
9f689658 11796
d62a17ae 11797 if (use_json)
11798 vty_out(vty, "}\n");
9f049418
DS
11799 else if (!route_output)
11800 vty_out(vty, "%% BGP instance not found\n");
f186de26 11801}
11802
718e3744 11803/* Header of detailed BGP route information */
d62a17ae 11804void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11805 struct bgp_dest *dest, const struct prefix *p,
11806 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11807 safi_t safi, json_object *json,
11808 bool incremental_print)
d62a17ae 11809{
40381db7 11810 struct bgp_path_info *pi;
d62a17ae 11811 struct peer *peer;
11812 struct listnode *node, *nnode;
06b9f471 11813 char buf1[RD_ADDRSTRLEN];
d62a17ae 11814 int count = 0;
11815 int best = 0;
11816 int suppress = 0;
c5f1e1b2
C
11817 int accept_own = 0;
11818 int route_filter_translated_v4 = 0;
11819 int route_filter_v4 = 0;
11820 int route_filter_translated_v6 = 0;
11821 int route_filter_v6 = 0;
11822 int llgr_stale = 0;
11823 int no_llgr = 0;
11824 int accept_own_nexthop = 0;
11825 int blackhole = 0;
d62a17ae 11826 int no_export = 0;
11827 int no_advertise = 0;
11828 int local_as = 0;
c5f1e1b2 11829 int no_peer = 0;
d62a17ae 11830 int first = 1;
11831 int has_valid_label = 0;
11832 mpls_label_t label = 0;
11833 json_object *json_adv_to = NULL;
67f67ba4
DA
11834 uint32_t ttl = 0;
11835 uint32_t bos = 0;
11836 uint32_t exp = 0;
9bedbb1e 11837
67f67ba4 11838 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11839
67f67ba4 11840 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11841
44c69747 11842 if (safi == SAFI_EVPN) {
44c69747 11843 if (!json) {
2dbe669b 11844 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11845 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11846 bgp->asnotation)
f137734b 11847 : "",
2dbe669b 11848 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11849 } else {
4a8cd6ad
PG
11850 json_object_string_add(
11851 json, "rd",
11852 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11853 bgp->asnotation)
11854 : "");
44c69747
LK
11855 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11856 }
11857 } else {
11858 if (!json) {
9119ef3a
DA
11859 vty_out(vty,
11860 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11861 "\n",
d62a17ae 11862 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11863 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11864 sizeof(buf1),
11865 bgp->asnotation)
8228a9a7 11866 : ""),
9119ef3a
DA
11867 safi == SAFI_MPLS_VPN ? ":" : "", p,
11868 dest->version);
cd1964ff 11869
9119ef3a 11870 } else {
f9f2d188
TA
11871 if (incremental_print) {
11872 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11873 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11874 dest->version);
11875 } else {
11876 json_object_string_addf(json, "prefix", "%pFX",
11877 p);
11878 json_object_int_add(json, "version",
11879 dest->version);
11880 }
9119ef3a 11881 }
44c69747
LK
11882 }
11883
11884 if (has_valid_label) {
f9f2d188
TA
11885 if (json) {
11886 if (incremental_print)
11887 vty_out(vty, "\"localLabel\": \"%u\",\n",
11888 label);
11889 else
11890 json_object_int_add(json, "localLabel", label);
11891 } else
d62a17ae 11892 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11893 }
11894
11895 if (!json)
d62a17ae 11896 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11897 vty_out(vty, "not allocated\n");
718e3744 11898
9bcb3eef 11899 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11900 struct community *picomm = NULL;
11901
11902 picomm = bgp_attr_get_community(pi->attr);
11903
d62a17ae 11904 count++;
40381db7 11905 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11906 best = count;
4056a5f6 11907 if (bgp_path_suppressed(pi))
d62a17ae 11908 suppress = 1;
cee9c031 11909
9a706b42 11910 if (!picomm)
cee9c031
QY
11911 continue;
11912
11913 no_advertise += community_include(
9a706b42
DA
11914 picomm, COMMUNITY_NO_ADVERTISE);
11915 no_export +=
11916 community_include(picomm, COMMUNITY_NO_EXPORT);
11917 local_as +=
11918 community_include(picomm, COMMUNITY_LOCAL_AS);
11919 accept_own +=
11920 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11921 route_filter_translated_v4 += community_include(
9a706b42 11922 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11923 route_filter_translated_v6 += community_include(
9a706b42 11924 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11925 route_filter_v4 += community_include(
9a706b42 11926 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11927 route_filter_v6 += community_include(
9a706b42
DA
11928 picomm, COMMUNITY_ROUTE_FILTER_v6);
11929 llgr_stale +=
11930 community_include(picomm, COMMUNITY_LLGR_STALE);
11931 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11932 accept_own_nexthop += community_include(
11933 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11934 blackhole +=
11935 community_include(picomm, COMMUNITY_BLACKHOLE);
11936 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11937 }
718e3744 11938 }
718e3744 11939
d62a17ae 11940 if (!json) {
11941 vty_out(vty, "Paths: (%d available", count);
11942 if (best) {
11943 vty_out(vty, ", best #%d", best);
b84060bb
PG
11944 if (safi == SAFI_UNICAST) {
11945 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11946 vty_out(vty, ", table %s",
11947 VRF_DEFAULT_NAME);
11948 else
11949 vty_out(vty, ", vrf %s",
11950 bgp->name);
11951 }
d62a17ae 11952 } else
11953 vty_out(vty, ", no best path");
11954
c5f1e1b2
C
11955 if (accept_own)
11956 vty_out(vty,
11957 ", accept own local route exported and imported in different VRF");
11958 else if (route_filter_translated_v4)
11959 vty_out(vty,
11960 ", mark translated RTs for VPNv4 route filtering");
11961 else if (route_filter_v4)
11962 vty_out(vty,
11963 ", attach RT as-is for VPNv4 route filtering");
11964 else if (route_filter_translated_v6)
11965 vty_out(vty,
11966 ", mark translated RTs for VPNv6 route filtering");
11967 else if (route_filter_v6)
11968 vty_out(vty,
11969 ", attach RT as-is for VPNv6 route filtering");
11970 else if (llgr_stale)
11971 vty_out(vty,
1479ed2f 11972 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11973 else if (no_llgr)
11974 vty_out(vty,
11975 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11976 else if (accept_own_nexthop)
11977 vty_out(vty,
11978 ", accept local nexthop");
11979 else if (blackhole)
11980 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11981 else if (no_export)
11982 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11983 else if (no_advertise)
11984 vty_out(vty, ", not advertised to any peer");
d62a17ae 11985 else if (local_as)
11986 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11987 else if (no_peer)
11988 vty_out(vty,
11989 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11990
11991 if (suppress)
11992 vty_out(vty,
11993 ", Advertisements suppressed by an aggregate.");
11994 vty_out(vty, ")\n");
11995 }
718e3744 11996
d62a17ae 11997 /* If we are not using addpath then we can display Advertised to and
11998 * that will
11999 * show what peers we advertised the bestpath to. If we are using
12000 * addpath
12001 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12002 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12003 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12004 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12005 if (json && !json_adv_to)
12006 json_adv_to = json_object_new_object();
12007
12008 route_vty_out_advertised_to(
12009 vty, peer, &first,
12010 " Advertised to non peer-group peers:\n ",
12011 json_adv_to);
12012 }
12013 }
12014
f9f2d188
TA
12015 if (json && json_adv_to) {
12016 if (incremental_print) {
12017 vty_out(vty, "\"advertisedTo\": ");
12018 vty_json(vty, json_adv_to);
12019 vty_out(vty, ",");
12020 } else
d62a17ae 12021 json_object_object_add(json, "advertisedTo",
12022 json_adv_to);
d62a17ae 12023 } else {
f9f2d188 12024 if (!json && first)
d62a17ae 12025 vty_out(vty, " Not advertised to any peer");
12026 vty_out(vty, "\n");
12027 }
12028 }
718e3744 12029}
12030
edfee30d 12031static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12032 struct bgp_dest *bgp_node, struct vty *vty,
12033 struct bgp *bgp, afi_t afi, safi_t safi,
12034 json_object *json, enum bgp_path_type pathtype,
4027d19b 12035 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12036{
12037 struct bgp_path_info *pi;
12038 int header = 1;
44c69747
LK
12039 json_object *json_header = NULL;
12040 json_object *json_paths = NULL;
4933eaaf 12041 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12042
9bcb3eef 12043 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12044 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12045
12046 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12047 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12048 pi->peer, pi->attr, p);
4933eaaf 12049
4027d19b
DS
12050 if (rpki_target_state != RPKI_NOT_BEING_USED
12051 && rpki_curr_state != rpki_target_state)
4933eaaf 12052 continue;
44c69747
LK
12053
12054 if (json && !json_paths) {
12055 /* Instantiate json_paths only if path is valid */
12056 json_paths = json_object_new_array();
c4f64ea9 12057 if (pfx_rd)
44c69747 12058 json_header = json_object_new_object();
c4f64ea9 12059 else
44c69747
LK
12060 json_header = json;
12061 }
12062
12063 if (header) {
12064 route_vty_out_detail_header(
34c7f35f
SW
12065 vty, bgp, bgp_node,
12066 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12067 safi, json_header, false);
44c69747
LK
12068 header = 0;
12069 }
12070 (*display)++;
12071
12072 if (pathtype == BGP_PATH_SHOW_ALL
12073 || (pathtype == BGP_PATH_SHOW_BESTPATH
12074 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12075 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12076 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12077 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12078 route_vty_out_detail(vty, bgp, bgp_node,
12079 bgp_dest_get_prefix(bgp_node), pi,
12080 AFI_IP, safi, rpki_curr_state,
12081 json_paths);
44c69747
LK
12082 }
12083
12084 if (json && json_paths) {
12085 json_object_object_add(json_header, "paths", json_paths);
12086
12087 if (pfx_rd)
4a8cd6ad
PG
12088 json_object_object_addf(
12089 json, json_header,
12090 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12091 }
12092}
12093
2aad8c42
MS
12094/*
12095 * Return rd based on safi
12096 */
46dbf9d0
DA
12097const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12098 safi_t safi)
2aad8c42
MS
12099{
12100 switch (safi) {
12101 case SAFI_MPLS_VPN:
12102 case SAFI_ENCAP:
12103 case SAFI_EVPN:
12104 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12105 case SAFI_UNSPEC:
12106 case SAFI_UNICAST:
12107 case SAFI_MULTICAST:
12108 case SAFI_LABELED_UNICAST:
12109 case SAFI_FLOWSPEC:
12110 case SAFI_MAX:
2aad8c42 12111 return NULL;
2aad8c42 12112 }
58cf0823
DS
12113
12114 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12115}
12116
718e3744 12117/* Display specified route of BGP table. */
d62a17ae 12118static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12119 struct bgp_table *rib, const char *ip_str,
12120 afi_t afi, safi_t safi,
4027d19b 12121 enum rpki_states rpki_target_state,
d62a17ae 12122 struct prefix_rd *prd, int prefix_check,
9f049418 12123 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12124{
12125 int ret;
d62a17ae 12126 int display = 0;
12127 struct prefix match;
9bcb3eef
DS
12128 struct bgp_dest *dest;
12129 struct bgp_dest *rm;
d62a17ae 12130 struct bgp_table *table;
12131 json_object *json = NULL;
12132 json_object *json_paths = NULL;
12133
12134 /* Check IP address argument. */
12135 ret = str2prefix(ip_str, &match);
12136 if (!ret) {
12137 vty_out(vty, "address is malformed\n");
12138 return CMD_WARNING;
12139 }
718e3744 12140
d62a17ae 12141 match.family = afi2family(afi);
b05a1c8b 12142
44c69747 12143 if (use_json)
d62a17ae 12144 json = json_object_new_object();
718e3744 12145
44c69747 12146 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12147 for (dest = bgp_table_top(rib); dest;
12148 dest = bgp_route_next(dest)) {
12149 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12150
9bcb3eef 12151 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12152 continue;
9bcb3eef 12153 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12154 if (!table)
ea47320b 12155 continue;
d62a17ae 12156
4953391b
DA
12157 rm = bgp_node_match(table, &match);
12158 if (rm == NULL)
ea47320b 12159 continue;
d62a17ae 12160
9bcb3eef 12161 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12162 if (prefix_check
b54892e0 12163 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12164 bgp_dest_unlock_node(rm);
ea47320b
DL
12165 continue;
12166 }
d62a17ae 12167
9bcb3eef 12168 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12169 bgp, afi, safi, json, pathtype,
4027d19b 12170 &display, rpki_target_state);
44c69747 12171
9bcb3eef 12172 bgp_dest_unlock_node(rm);
44c69747
LK
12173 }
12174 } else if (safi == SAFI_EVPN) {
9bcb3eef 12175 struct bgp_dest *longest_pfx;
cded3b72 12176 bool is_exact_pfxlen_match = false;
44c69747 12177
9bcb3eef
DS
12178 for (dest = bgp_table_top(rib); dest;
12179 dest = bgp_route_next(dest)) {
12180 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12181
9bcb3eef 12182 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12183 continue;
9bcb3eef 12184 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12185 if (!table)
12186 continue;
12187
12188 longest_pfx = NULL;
cded3b72 12189 is_exact_pfxlen_match = false;
44c69747
LK
12190 /*
12191 * Search through all the prefixes for a match. The
12192 * pfx's are enumerated in ascending order of pfxlens.
12193 * So, the last pfx match is the longest match. Set
12194 * is_exact_pfxlen_match when we get exact pfxlen match
12195 */
12196 for (rm = bgp_table_top(table); rm;
12197 rm = bgp_route_next(rm)) {
b54892e0 12198 const struct prefix *rm_p =
9bcb3eef 12199 bgp_dest_get_prefix(rm);
44c69747
LK
12200 /*
12201 * Get prefixlen of the ip-prefix within type5
12202 * evpn route
12203 */
b54892e0
DS
12204 if (evpn_type5_prefix_match(rm_p, &match)
12205 && rm->info) {
44c69747
LK
12206 longest_pfx = rm;
12207 int type5_pfxlen =
b54892e0
DS
12208 bgp_evpn_get_type5_prefixlen(
12209 rm_p);
44c69747 12210 if (type5_pfxlen == match.prefixlen) {
cded3b72 12211 is_exact_pfxlen_match = true;
9bcb3eef 12212 bgp_dest_unlock_node(rm);
44c69747
LK
12213 break;
12214 }
d62a17ae 12215 }
12216 }
ea47320b 12217
44c69747
LK
12218 if (!longest_pfx)
12219 continue;
12220
12221 if (prefix_check && !is_exact_pfxlen_match)
12222 continue;
12223
12224 rm = longest_pfx;
9bcb3eef 12225 bgp_dest_lock_node(rm);
44c69747 12226
9bcb3eef 12227 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12228 bgp, afi, safi, json, pathtype,
4027d19b 12229 &display, rpki_target_state);
44c69747 12230
9bcb3eef 12231 bgp_dest_unlock_node(rm);
d62a17ae 12232 }
98a9dbc7 12233 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12234 if (use_json)
12235 json_paths = json_object_new_array();
12236
63a0b7a9
PG
12237 display = bgp_flowspec_display_match_per_ip(afi, rib,
12238 &match, prefix_check,
12239 vty,
12240 use_json,
12241 json_paths);
d5f20468
SP
12242 if (use_json) {
12243 if (display)
12244 json_object_object_add(json, "paths",
12245 json_paths);
12246 else
12247 json_object_free(json_paths);
12248 }
d62a17ae 12249 } else {
4953391b
DA
12250 dest = bgp_node_match(rib, &match);
12251 if (dest != NULL) {
9bcb3eef 12252 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12253 if (!prefix_check
9bcb3eef
DS
12254 || dest_p->prefixlen == match.prefixlen) {
12255 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12256 safi, json, pathtype,
4027d19b 12257 &display, rpki_target_state);
d62a17ae 12258 }
12259
9bcb3eef 12260 bgp_dest_unlock_node(dest);
d62a17ae 12261 }
12262 }
e5eee9af 12263
d62a17ae 12264 if (use_json) {
75eeda93 12265 vty_json(vty, json);
d62a17ae 12266 } else {
12267 if (!display) {
12268 vty_out(vty, "%% Network not in table\n");
12269 return CMD_WARNING;
12270 }
12271 }
b05a1c8b 12272
d62a17ae 12273 return CMD_SUCCESS;
718e3744 12274}
12275
fee0f4c6 12276/* Display specified route of Main RIB */
d62a17ae 12277static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12278 afi_t afi, safi_t safi, struct prefix_rd *prd,
12279 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12280 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12281{
9b86009a 12282 if (!bgp) {
d62a17ae 12283 bgp = bgp_get_default();
9b86009a
RW
12284 if (!bgp) {
12285 if (!use_json)
12286 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12287 else
12288 vty_out(vty, "{}\n");
9b86009a
RW
12289 return CMD_WARNING;
12290 }
12291 }
d62a17ae 12292
12293 /* labeled-unicast routes live in the unicast table */
12294 if (safi == SAFI_LABELED_UNICAST)
12295 safi = SAFI_UNICAST;
12296
12297 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12298 afi, safi, rpki_target_state, prd,
8aa22bbb 12299 prefix_check, pathtype, use_json);
d62a17ae 12300}
12301
12302static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12303 struct cmd_token **argv, bool exact, afi_t afi,
12304 safi_t safi, bool uj)
d62a17ae 12305{
12306 struct lcommunity *lcom;
12307 struct buffer *b;
12308 int i;
12309 char *str;
12310 int first = 0;
96c81f66 12311 uint16_t show_flags = 0;
4f28b2b5 12312 int ret;
96f3485c
MK
12313
12314 if (uj)
12315 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12316
12317 b = buffer_new(1024);
12318 for (i = 0; i < argc; i++) {
12319 if (first)
12320 buffer_putc(b, ' ');
12321 else {
12322 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12323 first = 1;
12324 buffer_putstr(b, argv[i]->arg);
12325 }
12326 }
12327 }
12328 buffer_putc(b, '\0');
57d187bc 12329
d62a17ae 12330 str = buffer_getstr(b);
12331 buffer_free(b);
57d187bc 12332
d62a17ae 12333 lcom = lcommunity_str2com(str);
12334 XFREE(MTYPE_TMP, str);
12335 if (!lcom) {
12336 vty_out(vty, "%% Large-community malformed\n");
12337 return CMD_WARNING;
12338 }
57d187bc 12339
4f28b2b5 12340 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12341 (exact ? bgp_show_type_lcommunity_exact
12342 : bgp_show_type_lcommunity),
12343 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12344
12345 lcommunity_free(&lcom);
12346 return ret;
57d187bc
JS
12347}
12348
d62a17ae 12349static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12350 const char *lcom, bool exact, afi_t afi,
12351 safi_t safi, bool uj)
57d187bc 12352{
d62a17ae 12353 struct community_list *list;
96c81f66 12354 uint16_t show_flags = 0;
96f3485c
MK
12355
12356 if (uj)
12357 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12358
57d187bc 12359
e237b0d2 12360 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12361 LARGE_COMMUNITY_LIST_MASTER);
12362 if (list == NULL) {
12363 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12364 lcom);
12365 return CMD_WARNING;
12366 }
57d187bc 12367
36a206db 12368 return bgp_show(vty, bgp, afi, safi,
12369 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12370 : bgp_show_type_lcommunity_list),
1e2ce4f1 12371 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12372}
12373
52951b63
DS
12374DEFUN (show_ip_bgp_large_community_list,
12375 show_ip_bgp_large_community_list_cmd,
77a3a95e 12376 "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
12377 SHOW_STR
12378 IP_STR
12379 BGP_STR
12380 BGP_INSTANCE_HELP_STR
9bedbb1e 12381 BGP_AFI_HELP_STR
4dd6177e 12382 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12383 "Display routes matching the large-community-list\n"
12384 "large-community-list number\n"
12385 "large-community-list name\n"
36a206db 12386 "Exact match of the large-communities\n"
52951b63
DS
12387 JSON_STR)
12388{
d62a17ae 12389 afi_t afi = AFI_IP6;
12390 safi_t safi = SAFI_UNICAST;
12391 int idx = 0;
36a206db 12392 bool exact_match = 0;
4d678463 12393 struct bgp *bgp = NULL;
9f049418 12394 bool uj = use_json(argc, argv);
d62a17ae 12395
ef3364f0
DA
12396 if (uj)
12397 argc--;
4d678463 12398
ef3364f0
DA
12399 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12400 &bgp, uj);
12401 if (!idx)
12402 return CMD_WARNING;
d62a17ae 12403
12404 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12405
12406 const char *clist_number_or_name = argv[++idx]->arg;
12407
12408 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12409 exact_match = 1;
12410
12411 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12412 exact_match, afi, safi, uj);
52951b63
DS
12413}
12414DEFUN (show_ip_bgp_large_community,
12415 show_ip_bgp_large_community_cmd,
36a206db 12416 "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
12417 SHOW_STR
12418 IP_STR
12419 BGP_STR
12420 BGP_INSTANCE_HELP_STR
9bedbb1e 12421 BGP_AFI_HELP_STR
4dd6177e 12422 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12423 "Display routes matching the large-communities\n"
12424 "List of large-community numbers\n"
36a206db 12425 "Exact match of the large-communities\n"
52951b63
DS
12426 JSON_STR)
12427{
d62a17ae 12428 afi_t afi = AFI_IP6;
12429 safi_t safi = SAFI_UNICAST;
12430 int idx = 0;
36a206db 12431 bool exact_match = 0;
4d678463 12432 struct bgp *bgp = NULL;
9f049418 12433 bool uj = use_json(argc, argv);
96c81f66 12434 uint16_t show_flags = 0;
d62a17ae 12435
96f3485c
MK
12436 if (uj) {
12437 argc--;
12438 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12439 }
4d678463 12440
96f3485c
MK
12441 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12442 &bgp, uj);
12443 if (!idx)
12444 return CMD_WARNING;
d62a17ae 12445
36a206db 12446 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12447 if (argv_find(argv, argc, "exact-match", &idx)) {
12448 argc--;
36a206db 12449 exact_match = 1;
1857760c 12450 }
36a206db 12451 return bgp_show_lcommunity(vty, bgp, argc, argv,
12452 exact_match, afi, safi, uj);
12453 } else
d62a17ae 12454 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12455 bgp_show_type_lcommunity_all, NULL, show_flags,
12456 RPKI_NOT_BEING_USED);
52951b63
DS
12457}
12458
71f1613a
DA
12459static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12460 safi_t safi, struct json_object *json_array);
d62a17ae 12461static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12462 safi_t safi, struct json_object *json);
e01ca200 12463
7b2ff250 12464
9ab0cf58
PG
12465DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12467 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12468 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12469{
12470 bool uj = use_json(argc, argv);
12471 struct bgp *bgp = NULL;
ec76a1d1
DA
12472 safi_t safi = SAFI_UNICAST;
12473 afi_t afi = AFI_IP6;
4265b261 12474 int idx = 0;
6c9d22e2
PG
12475 struct json_object *json_all = NULL;
12476 struct json_object *json_afi_safi = NULL;
4265b261
PG
12477
12478 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12479 &bgp, false);
71f1613a 12480 if (!idx)
4265b261 12481 return CMD_WARNING;
6c9d22e2 12482
4265b261 12483 if (uj)
6c9d22e2 12484 json_all = json_object_new_object();
4265b261 12485
9ab0cf58
PG
12486 FOREACH_AFI_SAFI (afi, safi) {
12487 /*
12488 * So limit output to those afi/safi pairs that
12489 * actually have something interesting in them
12490 */
12491 if (strmatch(get_afi_safi_str(afi, safi, true),
12492 "Unknown")) {
12493 continue;
12494 }
12495 if (uj) {
12496 json_afi_safi = json_object_new_array();
12497 json_object_object_add(
12498 json_all,
12499 get_afi_safi_str(afi, safi, true),
12500 json_afi_safi);
12501 } else {
12502 json_afi_safi = NULL;
6c9d22e2 12503 }
9ab0cf58
PG
12504
12505 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12506 }
6c9d22e2 12507
3757f964
DA
12508 if (uj)
12509 vty_json(vty, json_all);
6c9d22e2 12510
4265b261
PG
12511 return CMD_SUCCESS;
12512}
12513
7b2ff250 12514/* BGP route print out function without JSON */
14718643
PG
12515DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12516 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12517 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12518 SHOW_STR
12519 IP_STR
12520 BGP_STR
12521 BGP_INSTANCE_HELP_STR
12522 L2VPN_HELP_STR
12523 EVPN_HELP_STR
12524 "BGP RIB advertisement statistics\n"
12525 JSON_STR)
12526{
ec76a1d1
DA
12527 afi_t afi = AFI_IP6;
12528 safi_t safi = SAFI_UNICAST;
14718643
PG
12529 struct bgp *bgp = NULL;
12530 int idx = 0, ret;
12531 bool uj = use_json(argc, argv);
12532 struct json_object *json_afi_safi = NULL, *json = NULL;
12533
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12535 &bgp, false);
12536 if (!idx)
12537 return CMD_WARNING;
12538
12539 if (uj)
12540 json_afi_safi = json_object_new_array();
12541 else
12542 json_afi_safi = NULL;
12543
12544 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12545
12546 if (uj) {
12547 json = json_object_new_object();
12548 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12549 json_afi_safi);
3757f964 12550 vty_json(vty, json);
14718643
PG
12551 }
12552 return ret;
12553}
12554
893cccd0 12555/* BGP route print out function without JSON */
9ab0cf58
PG
12556DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12557 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12558 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12559 "]]\
893cccd0 12560 statistics [json]",
9ab0cf58
PG
12561 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12562 BGP_SAFI_WITH_LABEL_HELP_STR
12563 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12564{
ec76a1d1
DA
12565 afi_t afi = AFI_IP6;
12566 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12567 struct bgp *bgp = NULL;
12568 int idx = 0, ret;
12569 bool uj = use_json(argc, argv);
6c9d22e2 12570 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12571
12572 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12573 &bgp, false);
12574 if (!idx)
12575 return CMD_WARNING;
6c9d22e2 12576
893cccd0 12577 if (uj)
6c9d22e2
PG
12578 json_afi_safi = json_object_new_array();
12579 else
12580 json_afi_safi = NULL;
12581
12582 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12583
12584 if (uj) {
12585 json = json_object_new_object();
12586 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12587 json_afi_safi);
3757f964 12588 vty_json(vty, json);
893cccd0
PG
12589 }
12590 return ret;
893cccd0 12591}
7b2ff250 12592
fe0f234d 12593DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12594 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12595 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12596 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12597 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12598 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12599 "Display the entries for all address families\n"
9ab0cf58
PG
12600 "Display detailed information about dampening\n"
12601 "Display detail of configured dampening parameters\n"
fe0f234d 12602 JSON_STR)
718e3744 12603{
d62a17ae 12604 afi_t afi = AFI_IP6;
12605 safi_t safi = SAFI_UNICAST;
d62a17ae 12606 struct bgp *bgp = NULL;
12607 int idx = 0;
96c81f66 12608 uint16_t show_flags = 0;
fe0f234d
RW
12609 bool uj = use_json(argc, argv);
12610
12611 if (uj) {
12612 argc--;
12613 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12614 }
96f3485c
MK
12615
12616 /* [<ipv4|ipv6> [all]] */
12617 if (all) {
12618 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12619 if (argv_find(argv, argc, "ipv4", &idx))
12620 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12621
12622 if (argv_find(argv, argc, "ipv6", &idx))
12623 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12624 }
d62a17ae 12625
12626 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12627 &bgp, false);
d62a17ae 12628 if (!idx)
12629 return CMD_WARNING;
12630
fe0f234d 12631 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12632}
12633
fe0f234d
RW
12634/* BGP route print out function */
12635DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12636 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12637 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12638 "]]\
96f3485c 12639 [all$all]\
cf4898bc
QY
12640 [cidr-only\
12641 |dampening <flap-statistics|dampened-paths>\
12642 |community [AA:NN|local-AS|no-advertise|no-export\
12643 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12644 |accept-own|accept-own-nexthop|route-filter-v6\
12645 |route-filter-v4|route-filter-translated-v6\
12646 |route-filter-translated-v4] [exact-match]\
70799983 12647 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12648 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12649 |prefix-list WORD\
ed126382 12650 |access-list ACCESSLIST_NAME\
70dd370f 12651 |route-map RMAP_NAME\
1e2ce4f1 12652 |rpki <invalid|valid|notfound>\
7d3cae70 12653 |version (1-4294967295)\
b4ad2fae 12654 |alias ALIAS_NAME\
39c3c736
RW
12655 |A.B.C.D/M longer-prefixes\
12656 |X:X::X:X/M longer-prefixes\
83856649 12657 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12658 |detail-routes$detail_routes\
67799a48 12659 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12660 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12661 BGP_SAFI_WITH_LABEL_HELP_STR
12662 "Display the entries for all address families\n"
12663 "Display only routes with non-natural netmasks\n"
12664 "Display detailed information about dampening\n"
12665 "Display flap statistics of routes\n"
12666 "Display paths suppressed due to dampening\n"
12667 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12668 "Do not send outside local AS (well-known community)\n"
12669 "Do not advertise to any peer (well-known community)\n"
12670 "Do not export to next AS (well-known community)\n"
12671 "Graceful shutdown (well-known community)\n"
12672 "Do not export to any peer (well-known community)\n"
12673 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12674 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12675 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12676 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12677 "Should accept VPN route with local nexthop (well-known community)\n"
12678 "RT VPNv6 route filtering (well-known community)\n"
12679 "RT VPNv4 route filtering (well-known community)\n"
12680 "RT translated VPNv6 route filtering (well-known community)\n"
12681 "RT translated VPNv4 route filtering (well-known community)\n"
12682 "Exact match of the communities\n"
70799983
RW
12683 "Community-list number\n"
12684 "Community-list name\n"
12685 "Display routes matching the community-list\n"
12686 "Exact match of the communities\n"
a7129347
RW
12687 "Display routes conforming to the filter-list\n"
12688 "Regular expression access list name\n"
6deaf579
RW
12689 "Display routes conforming to the prefix-list\n"
12690 "Prefix-list name\n"
ed126382
DA
12691 "Display routes conforming to the access-list\n"
12692 "Access-list name\n"
bf1a944a
RW
12693 "Display routes matching the route-map\n"
12694 "A route-map to match on\n"
a70a28a5
DA
12695 "RPKI route types\n"
12696 "A valid path as determined by rpki\n"
12697 "A invalid path as determined by rpki\n"
12698 "A path that has no rpki data\n"
12699 "Display prefixes with matching version numbers\n"
12700 "Version number and above\n"
12701 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12702 "BGP community alias\n"
12703 "IPv4 prefix\n"
12704 "Display route and more specific routes\n"
12705 "IPv6 prefix\n"
12706 "Display route and more specific routes\n"
83856649 12707 BGP_SELF_ORIG_HELP_STR
509d82bd 12708 "Display detailed version of all routes\n"
39c3c736 12709 JSON_STR
a70a28a5
DA
12710 "Display detailed version of JSON output\n"
12711 "Increase table width for longer prefixes\n")
7b2ff250
DW
12712{
12713 afi_t afi = AFI_IP6;
12714 safi_t safi = SAFI_UNICAST;
12715 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12716 void *output_arg = NULL;
7b2ff250
DW
12717 struct bgp *bgp = NULL;
12718 int idx = 0;
d0086e8e 12719 int exact_match = 0;
96f3485c
MK
12720 char *community = NULL;
12721 bool first = true;
96c81f66 12722 uint16_t show_flags = 0;
4027d19b 12723 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12724 struct prefix p;
96f3485c
MK
12725
12726 if (uj) {
9f049418 12727 argc--;
96f3485c
MK
12728 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12729 }
12730
67799a48
DA
12731 if (detail_json)
12732 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12733
509d82bd
DA
12734 if (detail_routes)
12735 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12736
96f3485c
MK
12737 /* [<ipv4|ipv6> [all]] */
12738 if (all) {
12739 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12740
12741 if (argv_find(argv, argc, "ipv4", &idx))
12742 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12743
12744 if (argv_find(argv, argc, "ipv6", &idx))
12745 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12746 }
12747
12748 if (wide)
12749 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12750
12751 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12752 &bgp, uj);
7b2ff250
DW
12753 if (!idx)
12754 return CMD_WARNING;
12755
7b2ff250 12756 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12757 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12758
12759 if (argv_find(argv, argc, "dampening", &idx)) {
12760 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12761 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12762 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12763 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12764 }
12765
12766 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12767 char *maybecomm = NULL;
d0086e8e 12768
79bc257a
RW
12769 if (idx + 1 < argc) {
12770 if (argv[idx + 1]->type == VARIABLE_TKN)
12771 maybecomm = argv[idx + 1]->arg;
12772 else
12773 maybecomm = argv[idx + 1]->text;
12774 }
12775
cf4898bc
QY
12776 if (maybecomm && !strmatch(maybecomm, "json")
12777 && !strmatch(maybecomm, "exact-match"))
12778 community = maybecomm;
d0086e8e 12779
cf4898bc
QY
12780 if (argv_find(argv, argc, "exact-match", &idx))
12781 exact_match = 1;
d0086e8e 12782
96f3485c
MK
12783 if (!community)
12784 sh_type = bgp_show_type_community_all;
12785 }
12786
70799983
RW
12787 if (argv_find(argv, argc, "community-list", &idx)) {
12788 const char *clist_number_or_name = argv[++idx]->arg;
12789 struct community_list *list;
12790
12791 if (argv_find(argv, argc, "exact-match", &idx))
12792 exact_match = 1;
12793
12794 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12795 COMMUNITY_LIST_MASTER);
12796 if (list == NULL) {
606d49a4 12797 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12798 clist_number_or_name);
12799 return CMD_WARNING;
12800 }
12801
12802 if (exact_match)
12803 sh_type = bgp_show_type_community_list_exact;
12804 else
12805 sh_type = bgp_show_type_community_list;
12806 output_arg = list;
12807 }
12808
a7129347
RW
12809 if (argv_find(argv, argc, "filter-list", &idx)) {
12810 const char *filter = argv[++idx]->arg;
12811 struct as_list *as_list;
12812
12813 as_list = as_list_lookup(filter);
12814 if (as_list == NULL) {
606d49a4 12815 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12816 filter);
12817 return CMD_WARNING;
12818 }
12819
12820 sh_type = bgp_show_type_filter_list;
12821 output_arg = as_list;
12822 }
12823
6deaf579
RW
12824 if (argv_find(argv, argc, "prefix-list", &idx)) {
12825 const char *prefix_list_str = argv[++idx]->arg;
12826 struct prefix_list *plist;
12827
12828 plist = prefix_list_lookup(afi, prefix_list_str);
12829 if (plist == NULL) {
606d49a4 12830 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12831 prefix_list_str);
12832 return CMD_WARNING;
12833 }
12834
12835 sh_type = bgp_show_type_prefix_list;
12836 output_arg = plist;
12837 }
12838
ed126382
DA
12839 if (argv_find(argv, argc, "access-list", &idx)) {
12840 const char *access_list_str = argv[++idx]->arg;
12841 struct access_list *alist;
12842
12843 alist = access_list_lookup(afi, access_list_str);
12844 if (!alist) {
606d49a4 12845 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12846 access_list_str);
12847 return CMD_WARNING;
12848 }
12849
12850 sh_type = bgp_show_type_access_list;
12851 output_arg = alist;
12852 }
12853
bf1a944a
RW
12854 if (argv_find(argv, argc, "route-map", &idx)) {
12855 const char *rmap_str = argv[++idx]->arg;
12856 struct route_map *rmap;
12857
12858 rmap = route_map_lookup_by_name(rmap_str);
12859 if (!rmap) {
606d49a4 12860 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12861 return CMD_WARNING;
12862 }
12863
12864 sh_type = bgp_show_type_route_map;
12865 output_arg = rmap;
12866 }
12867
1e2ce4f1
DS
12868 if (argv_find(argv, argc, "rpki", &idx)) {
12869 sh_type = bgp_show_type_rpki;
12870 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12871 rpki_target_state = RPKI_VALID;
1e2ce4f1 12872 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12873 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12874 }
12875
7d3cae70
DA
12876 /* Display prefixes with matching version numbers */
12877 if (argv_find(argv, argc, "version", &idx)) {
12878 sh_type = bgp_show_type_prefix_version;
2391833e 12879 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12880 }
12881
a70a28a5
DA
12882 /* Display prefixes with matching BGP community alias */
12883 if (argv_find(argv, argc, "alias", &idx)) {
12884 sh_type = bgp_show_type_community_alias;
2391833e 12885 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12886 }
12887
39c3c736
RW
12888 /* prefix-longer */
12889 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12890 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12891 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12892
12893 if (!str2prefix(prefix_str, &p)) {
12894 vty_out(vty, "%% Malformed Prefix\n");
12895 return CMD_WARNING;
12896 }
12897
12898 sh_type = bgp_show_type_prefix_longer;
12899 output_arg = &p;
a70a28a5
DA
12900 }
12901
83856649
KQ
12902 /* self originated only */
12903 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12904 sh_type = bgp_show_type_self_originated;
12905
96f3485c
MK
12906 if (!all) {
12907 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12908 if (community)
12909 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12910 exact_match, afi, safi,
12911 show_flags);
2391833e 12912 else
a70a28a5 12913 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12914 output_arg, show_flags,
a70a28a5 12915 rpki_target_state);
96f3485c 12916 } else {
fa5ac378
DA
12917 struct listnode *node;
12918 struct bgp *abgp;
96f3485c
MK
12919 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12920 * AFI_IP6 */
12921
12922 if (uj)
12923 vty_out(vty, "{\n");
12924
12925 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12926 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12927 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12928 ? AFI_IP
12929 : AFI_IP6;
fa5ac378
DA
12930 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12931 FOREACH_SAFI (safi) {
12932 if (!bgp_afi_safi_peer_exists(abgp, afi,
12933 safi))
12934 continue;
96f3485c 12935
fa5ac378
DA
12936 if (uj) {
12937 if (first)
12938 first = false;
12939 else
12940 vty_out(vty, ",\n");
12941 vty_out(vty, "\"%s\":{\n",
12942 get_afi_safi_str(afi,
12943 safi,
12944 true));
12945 } else
12946 vty_out(vty,
12947 "\nFor address family: %s\n",
12948 get_afi_safi_str(
12949 afi, safi,
12950 false));
12951
12952 if (community)
12953 bgp_show_community(
12954 vty, abgp, community,
12955 exact_match, afi, safi,
12956 show_flags);
96f3485c 12957 else
fa5ac378
DA
12958 bgp_show(vty, abgp, afi, safi,
12959 sh_type, output_arg,
12960 show_flags,
12961 rpki_target_state);
12962 if (uj)
12963 vty_out(vty, "}\n");
12964 }
96f3485c
MK
12965 }
12966 } else {
12967 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12968 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12969 FOREACH_AFI_SAFI (afi, safi) {
12970 if (!bgp_afi_safi_peer_exists(abgp, afi,
12971 safi))
12972 continue;
96f3485c 12973
fa5ac378
DA
12974 if (uj) {
12975 if (first)
12976 first = false;
12977 else
12978 vty_out(vty, ",\n");
12979
12980 vty_out(vty, "\"%s\":{\n",
12981 get_afi_safi_str(afi,
12982 safi,
12983 true));
12984 } else
12985 vty_out(vty,
12986 "\nFor address family: %s\n",
12987 get_afi_safi_str(
12988 afi, safi,
12989 false));
12990
12991 if (community)
12992 bgp_show_community(
12993 vty, abgp, community,
12994 exact_match, afi, safi,
12995 show_flags);
96f3485c 12996 else
fa5ac378
DA
12997 bgp_show(vty, abgp, afi, safi,
12998 sh_type, output_arg,
12999 show_flags,
13000 rpki_target_state);
13001 if (uj)
13002 vty_out(vty, "}\n");
13003 }
96f3485c
MK
13004 }
13005 }
13006 if (uj)
13007 vty_out(vty, "}\n");
13008 }
13009 return CMD_SUCCESS;
a636c635 13010}
47fc97cc 13011
718e3744 13012DEFUN (show_ip_bgp_route,
13013 show_ip_bgp_route_cmd,
8aa22bbb 13014 "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 13015 SHOW_STR
13016 IP_STR
13017 BGP_STR
a636c635 13018 BGP_INSTANCE_HELP_STR
4f280b15 13019 BGP_AFI_HELP_STR
4dd6177e 13020 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13021 "Network in the BGP routing table to display\n"
0c7b1b01 13022 "IPv4 prefix\n"
8c3deaae 13023 "Network in the BGP routing table to display\n"
0c7b1b01 13024 "IPv6 prefix\n"
4092b06c 13025 "Display only the bestpath\n"
b05a1c8b 13026 "Display only multipaths\n"
8aa22bbb
DS
13027 "Display only paths that match the specified rpki state\n"
13028 "A valid path as determined by rpki\n"
13029 "A invalid path as determined by rpki\n"
13030 "A path that has no rpki data\n"
9973d184 13031 JSON_STR)
4092b06c 13032{
d62a17ae 13033 int prefix_check = 0;
ae19d7dd 13034
d62a17ae 13035 afi_t afi = AFI_IP6;
13036 safi_t safi = SAFI_UNICAST;
13037 char *prefix = NULL;
13038 struct bgp *bgp = NULL;
13039 enum bgp_path_type path_type;
9f049418 13040 bool uj = use_json(argc, argv);
b05a1c8b 13041
d62a17ae 13042 int idx = 0;
ae19d7dd 13043
d62a17ae 13044 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13045 &bgp, uj);
d62a17ae 13046 if (!idx)
13047 return CMD_WARNING;
c41247f5 13048
d62a17ae 13049 if (!bgp) {
13050 vty_out(vty,
13051 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13052 return CMD_WARNING;
13053 }
a636c635 13054
d62a17ae 13055 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13056 if (argv_find(argv, argc, "A.B.C.D", &idx)
13057 || argv_find(argv, argc, "X:X::X:X", &idx))
13058 prefix_check = 0;
13059 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13060 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13061 prefix_check = 1;
13062
13063 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13064 && afi != AFI_IP6) {
13065 vty_out(vty,
13066 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13067 return CMD_WARNING;
13068 }
13069 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13070 && afi != AFI_IP) {
13071 vty_out(vty,
13072 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13073 return CMD_WARNING;
13074 }
13075
13076 prefix = argv[idx]->arg;
13077
13078 /* [<bestpath|multipath>] */
13079 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13080 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13081 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13082 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13083 else
360660c6 13084 path_type = BGP_PATH_SHOW_ALL;
a636c635 13085
d62a17ae 13086 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13087 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13088}
13089
8c3deaae
QY
13090DEFUN (show_ip_bgp_regexp,
13091 show_ip_bgp_regexp_cmd,
3e5b31b3 13092 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13093 SHOW_STR
13094 IP_STR
13095 BGP_STR
b00b230a 13096 BGP_INSTANCE_HELP_STR
4f280b15 13097 BGP_AFI_HELP_STR
4dd6177e 13098 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13099 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13100 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13101 JSON_STR)
8c3deaae 13102{
d62a17ae 13103 afi_t afi = AFI_IP6;
13104 safi_t safi = SAFI_UNICAST;
13105 struct bgp *bgp = NULL;
3e5b31b3
DA
13106 bool uj = use_json(argc, argv);
13107 char *regstr = NULL;
8c3deaae 13108
d62a17ae 13109 int idx = 0;
13110 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13111 &bgp, false);
d62a17ae 13112 if (!idx)
13113 return CMD_WARNING;
8c3deaae 13114
d62a17ae 13115 // get index of regex
3e5b31b3
DA
13116 if (argv_find(argv, argc, "REGEX", &idx))
13117 regstr = argv[idx]->arg;
8c3deaae 13118
5f71d11c 13119 assert(regstr);
3e5b31b3
DA
13120 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13121 bgp_show_type_regexp, uj);
8c3deaae
QY
13122}
13123
ae248832 13124DEFPY (show_ip_bgp_instance_all,
a636c635 13125 show_ip_bgp_instance_all_cmd,
ae248832 13126 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13127 SHOW_STR
a636c635 13128 IP_STR
4092b06c 13129 BGP_STR
a636c635 13130 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13131 BGP_AFI_HELP_STR
4dd6177e 13132 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13133 JSON_STR
13134 "Increase table width for longer prefixes\n")
4092b06c 13135{
54d05dea 13136 afi_t afi = AFI_IP6;
d62a17ae 13137 safi_t safi = SAFI_UNICAST;
13138 struct bgp *bgp = NULL;
d62a17ae 13139 int idx = 0;
96c81f66 13140 uint16_t show_flags = 0;
ae19d7dd 13141
96f3485c 13142 if (uj) {
d62a17ae 13143 argc--;
96f3485c
MK
13144 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13145 }
13146
13147 if (wide)
13148 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13149
9f049418
DS
13150 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13151 &bgp, uj);
13152 if (!idx)
13153 return CMD_WARNING;
13154
96f3485c 13155 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13156 return CMD_SUCCESS;
e3e29b32
LB
13157}
13158
a4d82a8a 13159static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13160 afi_t afi, safi_t safi, enum bgp_show_type type,
13161 bool use_json)
718e3744 13162{
d62a17ae 13163 regex_t *regex;
13164 int rc;
96c81f66 13165 uint16_t show_flags = 0;
96f3485c
MK
13166
13167 if (use_json)
13168 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13169
c3900853 13170 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13171 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13172 regstr);
13173 return CMD_WARNING_CONFIG_FAILED;
13174 }
13175
d62a17ae 13176 regex = bgp_regcomp(regstr);
13177 if (!regex) {
13178 vty_out(vty, "Can't compile regexp %s\n", regstr);
13179 return CMD_WARNING;
13180 }
a636c635 13181
1e2ce4f1
DS
13182 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13183 RPKI_NOT_BEING_USED);
d62a17ae 13184 bgp_regex_free(regex);
13185 return rc;
e3e29b32
LB
13186}
13187
7f323236
DW
13188static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13189 const char *comstr, int exact, afi_t afi,
96c81f66 13190 safi_t safi, uint16_t show_flags)
d62a17ae 13191{
13192 struct community *com;
d62a17ae 13193 int ret = 0;
13194
7f323236 13195 com = community_str2com(comstr);
d62a17ae 13196 if (!com) {
7f323236 13197 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13198 return CMD_WARNING;
13199 }
13200
13201 ret = bgp_show(vty, bgp, afi, safi,
13202 (exact ? bgp_show_type_community_exact
13203 : bgp_show_type_community),
1e2ce4f1 13204 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13205 community_free(&com);
46c3ce83 13206
d62a17ae 13207 return ret;
718e3744 13208}
13209
d62a17ae 13210enum bgp_stats {
13211 BGP_STATS_MAXBITLEN = 0,
13212 BGP_STATS_RIB,
13213 BGP_STATS_PREFIXES,
13214 BGP_STATS_TOTPLEN,
13215 BGP_STATS_UNAGGREGATEABLE,
13216 BGP_STATS_MAX_AGGREGATEABLE,
13217 BGP_STATS_AGGREGATES,
13218 BGP_STATS_SPACE,
13219 BGP_STATS_ASPATH_COUNT,
13220 BGP_STATS_ASPATH_MAXHOPS,
13221 BGP_STATS_ASPATH_TOTHOPS,
13222 BGP_STATS_ASPATH_MAXSIZE,
13223 BGP_STATS_ASPATH_TOTSIZE,
13224 BGP_STATS_ASN_HIGHEST,
13225 BGP_STATS_MAX,
a636c635 13226};
2815e61f 13227
9ab0cf58 13228#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13229#define TABLE_STATS_IDX_JSON 1
13230
13231static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13232 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13233 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13234 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13235 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13236 "unaggregateablePrefixes"},
13237 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13238 "maximumAggregateablePrefixes"},
13239 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13240 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13241 [BGP_STATS_SPACE] = {"Address space advertised",
13242 "addressSpaceAdvertised"},
9ab0cf58
PG
13243 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13244 "advertisementsWithPaths"},
13245 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13246 "longestAsPath"},
13247 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13248 "largestAsPath"},
13249 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13250 "averageAsPathLengthHops"},
13251 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13252 "averageAsPathSizeBytes"},
13253 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13254 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13255};
2815e61f 13256
d62a17ae 13257struct bgp_table_stats {
13258 struct bgp_table *table;
13259 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13260
13261 unsigned long long
13262 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13263 1];
13264
8d0ab76d 13265 double total_space;
ff7924f6
PJ
13266};
13267
9bcb3eef 13268static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13269 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13270{
9bcb3eef 13271 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13272 struct bgp_path_info *pi;
b54892e0 13273 const struct prefix *rn_p;
d62a17ae 13274
9bcb3eef 13275 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13276 return;
d62a17ae 13277
9bcb3eef 13278 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13279 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13280 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13281
0747643e 13282 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13283 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13284 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13285 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13286
9bcb3eef 13287 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13288 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13289 /* announced address space */
13290 if (space)
b54892e0 13291 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13292 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13293 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13294
9c14ec72 13295
9bcb3eef 13296 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13297 ts->counts[BGP_STATS_RIB]++;
13298
05864da7
DS
13299 if (CHECK_FLAG(pi->attr->flag,
13300 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13301 ts->counts[BGP_STATS_AGGREGATES]++;
13302
13303 /* as-path stats */
05864da7 13304 if (pi->attr->aspath) {
9c14ec72
RW
13305 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13306 unsigned int size = aspath_size(pi->attr->aspath);
13307 as_t highest = aspath_highest(pi->attr->aspath);
13308
13309 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13310
13311 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13312 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13313
13314 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13315 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13316
13317 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13318 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13319 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13320 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13321 }
13322 }
13323}
13324
cc9f21da 13325static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13326{
9bcb3eef
DS
13327 struct bgp_dest *dest, *ndest;
13328 struct bgp_dest *top;
9c14ec72
RW
13329 struct bgp_table_stats *ts = THREAD_ARG(t);
13330 unsigned int space = 0;
13331
13332 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13333 return;
9c14ec72
RW
13334
13335 switch (ts->table->afi) {
13336 case AFI_IP:
13337 space = IPV4_MAX_BITLEN;
13338 break;
13339 case AFI_IP6:
13340 space = IPV6_MAX_BITLEN;
13341 break;
3ba7b4af
TA
13342 case AFI_L2VPN:
13343 space = EVPN_ROUTE_PREFIXLEN;
13344 break;
58cf0823
DS
13345 case AFI_UNSPEC:
13346 case AFI_MAX:
cc9f21da 13347 return;
9c14ec72
RW
13348 }
13349
13350 ts->counts[BGP_STATS_MAXBITLEN] = space;
13351
9bcb3eef 13352 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13353 if (ts->table->safi == SAFI_MPLS_VPN
13354 || ts->table->safi == SAFI_ENCAP
13355 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13356 struct bgp_table *table;
13357
9bcb3eef 13358 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13359 if (!table)
13360 continue;
13361
13362 top = bgp_table_top(table);
9bcb3eef
DS
13363 for (ndest = bgp_table_top(table); ndest;
13364 ndest = bgp_route_next(ndest))
13365 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13366 } else {
9bcb3eef 13367 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13368 }
13369 }
2815e61f 13370}
ff7924f6 13371
71f1613a
DA
13372static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13373 struct json_object *json_array)
13374{
13375 struct listnode *node, *nnode;
13376 struct bgp *bgp;
13377
13378 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13379 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13380}
13381
13382static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13383 safi_t safi, struct json_object *json_array)
2815e61f 13384{
d62a17ae 13385 struct bgp_table_stats ts;
13386 unsigned int i;
893cccd0
PG
13387 int ret = CMD_SUCCESS;
13388 char temp_buf[20];
6c9d22e2 13389 struct json_object *json = NULL;
0747643e
AQ
13390 uint32_t bitlen = 0;
13391 struct json_object *json_bitlen;
6c9d22e2
PG
13392
13393 if (json_array)
13394 json = json_object_new_object();
019386c2 13395
d62a17ae 13396 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13397 char warning_msg[50];
13398
13399 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13400 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13401 safi);
6c9d22e2
PG
13402
13403 if (!json)
893cccd0
PG
13404 vty_out(vty, "%s\n", warning_msg);
13405 else
9ab0cf58 13406 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13407
893cccd0
PG
13408 ret = CMD_WARNING;
13409 goto end_table_stats;
d62a17ae 13410 }
019386c2 13411
893cccd0 13412 if (!json)
5290ceab
DA
13413 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13414 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13415 else
13416 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13417
d62a17ae 13418 /* labeled-unicast routes live in the unicast table */
13419 if (safi == SAFI_LABELED_UNICAST)
13420 safi = SAFI_UNICAST;
019386c2 13421
d62a17ae 13422 memset(&ts, 0, sizeof(ts));
13423 ts.table = bgp->rib[afi][safi];
13424 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13425
d62a17ae 13426 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13427 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13428 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13429 continue;
13430
13431 switch (i) {
d62a17ae 13432 case BGP_STATS_ASPATH_TOTHOPS:
13433 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13434 if (!json) {
9ab0cf58
PG
13435 snprintf(
13436 temp_buf, sizeof(temp_buf), "%12.2f",
13437 ts.counts[i]
13438 ? (float)ts.counts[i]
13439 / (float)ts.counts
13440 [BGP_STATS_ASPATH_COUNT]
13441 : 0);
893cccd0 13442 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13443 table_stats_strs[i]
13444 [TABLE_STATS_IDX_VTY],
893cccd0 13445 temp_buf);
9ab0cf58
PG
13446 } else {
13447 json_object_double_add(
13448 json,
13449 table_stats_strs[i]
13450 [TABLE_STATS_IDX_JSON],
13451 ts.counts[i]
13452 ? (double)ts.counts[i]
13453 / (double)ts.counts
d62a17ae 13454 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13455 : 0);
13456 }
d62a17ae 13457 break;
13458 case BGP_STATS_TOTPLEN:
6c9d22e2 13459 if (!json) {
9ab0cf58
PG
13460 snprintf(
13461 temp_buf, sizeof(temp_buf), "%12.2f",
13462 ts.counts[i]
13463 ? (float)ts.counts[i]
13464 / (float)ts.counts
13465 [BGP_STATS_PREFIXES]
13466 : 0);
893cccd0 13467 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13468 table_stats_strs[i]
13469 [TABLE_STATS_IDX_VTY],
893cccd0 13470 temp_buf);
9ab0cf58
PG
13471 } else {
13472 json_object_double_add(
13473 json,
13474 table_stats_strs[i]
13475 [TABLE_STATS_IDX_JSON],
13476 ts.counts[i]
13477 ? (double)ts.counts[i]
13478 / (double)ts.counts
d62a17ae 13479 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13480 : 0);
13481 }
d62a17ae 13482 break;
13483 case BGP_STATS_SPACE:
6c9d22e2
PG
13484 if (!json) {
13485 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13486 ts.total_space);
893cccd0 13487 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13488 table_stats_strs[i]
13489 [TABLE_STATS_IDX_VTY],
893cccd0 13490 temp_buf);
9ab0cf58
PG
13491 } else {
13492 json_object_double_add(
13493 json,
13494 table_stats_strs[i]
13495 [TABLE_STATS_IDX_JSON],
13496 (double)ts.total_space);
13497 }
8d0ab76d 13498 if (afi == AFI_IP6) {
6c9d22e2
PG
13499 if (!json) {
13500 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13501 "%12g",
13502 ts.total_space
13503 * pow(2.0, -128 + 32));
6c9d22e2
PG
13504 vty_out(vty, "%30s: %s\n",
13505 "/32 equivalent %s\n",
13506 temp_buf);
9ab0cf58
PG
13507 } else {
13508 json_object_double_add(
13509 json, "/32equivalent",
13510 (double)(ts.total_space
13511 * pow(2.0,
13512 -128 + 32)));
13513 }
6c9d22e2
PG
13514 if (!json) {
13515 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13516 "%12g",
13517 ts.total_space
13518 * pow(2.0, -128 + 48));
6c9d22e2
PG
13519 vty_out(vty, "%30s: %s\n",
13520 "/48 equivalent %s\n",
13521 temp_buf);
9ab0cf58
PG
13522 } else {
13523 json_object_double_add(
13524 json, "/48equivalent",
13525 (double)(ts.total_space
13526 * pow(2.0,
13527 -128 + 48)));
13528 }
8d0ab76d 13529 } else {
6c9d22e2
PG
13530 if (!json) {
13531 snprintf(temp_buf, sizeof(temp_buf),
13532 "%12.2f",
9ab0cf58
PG
13533 ts.total_space * 100.
13534 * pow(2.0, -32));
6c9d22e2 13535 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13536 "% announced ", temp_buf);
13537 } else {
13538 json_object_double_add(
13539 json, "%announced",
13540 (double)(ts.total_space * 100.
13541 * pow(2.0, -32)));
13542 }
6c9d22e2
PG
13543 if (!json) {
13544 snprintf(temp_buf, sizeof(temp_buf),
13545 "%12.2f",
9ab0cf58
PG
13546 ts.total_space
13547 * pow(2.0, -32 + 8));
6c9d22e2
PG
13548 vty_out(vty, "%30s: %s\n",
13549 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13550 } else {
13551 json_object_double_add(
13552 json, "/8equivalent",
13553 (double)(ts.total_space
13554 * pow(2.0, -32 + 8)));
13555 }
6c9d22e2
PG
13556 if (!json) {
13557 snprintf(temp_buf, sizeof(temp_buf),
13558 "%12.2f",
9ab0cf58
PG
13559 ts.total_space
13560 * pow(2.0, -32 + 24));
6c9d22e2 13561 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13562 "/24 equivalent ", temp_buf);
13563 } else {
13564 json_object_double_add(
13565 json, "/24equivalent",
13566 (double)(ts.total_space
13567 * pow(2.0, -32 + 24)));
13568 }
8d0ab76d 13569 }
d62a17ae 13570 break;
13571 default:
6c9d22e2
PG
13572 if (!json) {
13573 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13574 ts.counts[i]);
893cccd0 13575 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13576 table_stats_strs[i]
13577 [TABLE_STATS_IDX_VTY],
13578 temp_buf);
13579 } else {
13580 json_object_int_add(
13581 json,
13582 table_stats_strs[i]
13583 [TABLE_STATS_IDX_JSON],
13584 ts.counts[i]);
13585 }
d62a17ae 13586 }
893cccd0
PG
13587 if (!json)
13588 vty_out(vty, "\n");
d62a17ae 13589 }
0747643e
AQ
13590
13591 switch (afi) {
13592 case AFI_IP:
13593 bitlen = IPV4_MAX_BITLEN;
13594 break;
13595 case AFI_IP6:
13596 bitlen = IPV6_MAX_BITLEN;
13597 break;
13598 case AFI_L2VPN:
13599 bitlen = EVPN_ROUTE_PREFIXLEN;
13600 break;
58cf0823
DS
13601 case AFI_UNSPEC:
13602 case AFI_MAX:
0747643e
AQ
13603 break;
13604 }
13605
13606 if (json) {
13607 json_bitlen = json_object_new_array();
13608
13609 for (i = 0; i <= bitlen; i++) {
13610 struct json_object *ind_bit = json_object_new_object();
13611
13612 if (!ts.prefix_len_count[i])
13613 continue;
13614
13615 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13616 json_object_int_add(ind_bit, temp_buf,
13617 ts.prefix_len_count[i]);
13618 json_object_array_add(json_bitlen, ind_bit);
13619 }
13620 json_object_object_add(json, "prefixLength", json_bitlen);
13621 }
13622
9ab0cf58 13623end_table_stats:
6c9d22e2
PG
13624 if (json)
13625 json_object_array_add(json_array, json);
893cccd0 13626 return ret;
d62a17ae 13627}
13628
71f1613a
DA
13629static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13630 safi_t safi, struct json_object *json_array)
13631{
13632 if (!bgp) {
13633 bgp_table_stats_all(vty, afi, safi, json_array);
13634 return CMD_SUCCESS;
13635 }
13636
13637 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13638}
13639
d62a17ae 13640enum bgp_pcounts {
13641 PCOUNT_ADJ_IN = 0,
13642 PCOUNT_DAMPED,
13643 PCOUNT_REMOVED,
13644 PCOUNT_HISTORY,
13645 PCOUNT_STALE,
13646 PCOUNT_VALID,
13647 PCOUNT_ALL,
13648 PCOUNT_COUNTED,
7e3d9632 13649 PCOUNT_BPATH_SELECTED,
d62a17ae 13650 PCOUNT_PFCNT, /* the figure we display to users */
13651 PCOUNT_MAX,
a636c635 13652};
718e3744 13653
2b64873d 13654static const char *const pcount_strs[] = {
9d303b37
DL
13655 [PCOUNT_ADJ_IN] = "Adj-in",
13656 [PCOUNT_DAMPED] = "Damped",
13657 [PCOUNT_REMOVED] = "Removed",
13658 [PCOUNT_HISTORY] = "History",
13659 [PCOUNT_STALE] = "Stale",
13660 [PCOUNT_VALID] = "Valid",
13661 [PCOUNT_ALL] = "All RIB",
13662 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13663 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13664 [PCOUNT_PFCNT] = "Useable",
13665 [PCOUNT_MAX] = NULL,
a636c635 13666};
718e3744 13667
d62a17ae 13668struct peer_pcounts {
13669 unsigned int count[PCOUNT_MAX];
13670 const struct peer *peer;
13671 const struct bgp_table *table;
54317cba 13672 safi_t safi;
a636c635 13673};
47fc97cc 13674
9bcb3eef 13675static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13676{
54317cba
JW
13677 const struct bgp_adj_in *ain;
13678 const struct bgp_path_info *pi;
d62a17ae 13679 const struct peer *peer = pc->peer;
13680
54317cba
JW
13681 for (ain = rn->adj_in; ain; ain = ain->next)
13682 if (ain->peer == peer)
13683 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13684
9bcb3eef 13685 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13686
54317cba
JW
13687 if (pi->peer != peer)
13688 continue;
d62a17ae 13689
54317cba 13690 pc->count[PCOUNT_ALL]++;
d62a17ae 13691
54317cba
JW
13692 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13693 pc->count[PCOUNT_DAMPED]++;
13694 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13695 pc->count[PCOUNT_HISTORY]++;
13696 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13697 pc->count[PCOUNT_REMOVED]++;
13698 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13699 pc->count[PCOUNT_STALE]++;
13700 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13701 pc->count[PCOUNT_VALID]++;
13702 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13703 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13704 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13705 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13706
13707 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13708 pc->count[PCOUNT_COUNTED]++;
13709 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13710 flog_err(
13711 EC_LIB_DEVELOPMENT,
13712 "Attempting to count but flags say it is unusable");
13713 } else {
40381db7 13714 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13715 flog_err(
13716 EC_LIB_DEVELOPMENT,
13717 "Not counted but flags say we should");
d62a17ae 13718 }
13719 }
54317cba
JW
13720}
13721
cc9f21da 13722static void bgp_peer_count_walker(struct thread *t)
54317cba 13723{
9bcb3eef 13724 struct bgp_dest *rn, *rm;
54317cba
JW
13725 const struct bgp_table *table;
13726 struct peer_pcounts *pc = THREAD_ARG(t);
13727
13728 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13729 || pc->safi == SAFI_EVPN) {
13730 /* Special handling for 2-level routing tables. */
13731 for (rn = bgp_table_top(pc->table); rn;
13732 rn = bgp_route_next(rn)) {
9bcb3eef 13733 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13734 if (table != NULL)
13735 for (rm = bgp_table_top(table); rm;
13736 rm = bgp_route_next(rm))
13737 bgp_peer_count_proc(rm, pc);
13738 }
13739 } else
13740 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13741 bgp_peer_count_proc(rn, pc);
718e3744 13742}
13743
d62a17ae 13744static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13745 safi_t safi, bool use_json)
856ca177 13746{
d62a17ae 13747 struct peer_pcounts pcounts = {.peer = peer};
13748 unsigned int i;
13749 json_object *json = NULL;
13750 json_object *json_loop = NULL;
856ca177 13751
d62a17ae 13752 if (use_json) {
13753 json = json_object_new_object();
13754 json_loop = json_object_new_object();
13755 }
718e3744 13756
d62a17ae 13757 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13758 || !peer->bgp->rib[afi][safi]) {
13759 if (use_json) {
13760 json_object_string_add(
13761 json, "warning",
13762 "No such neighbor or address family");
13763 vty_out(vty, "%s\n", json_object_to_json_string(json));
13764 json_object_free(json);
d5f20468 13765 json_object_free(json_loop);
d62a17ae 13766 } else
13767 vty_out(vty, "%% No such neighbor or address family\n");
13768
13769 return CMD_WARNING;
13770 }
2a71e9ce 13771
d62a17ae 13772 memset(&pcounts, 0, sizeof(pcounts));
13773 pcounts.peer = peer;
13774 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13775 pcounts.safi = safi;
d62a17ae 13776
13777 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13778 * stats for the thread-walk (i.e. ensure this can't be blamed on
13779 * on just vty_read()).
13780 */
d62a17ae 13781 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13782
13783 if (use_json) {
13784 json_object_string_add(json, "prefixCountsFor", peer->host);
13785 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13786 get_afi_safi_str(afi, safi, true));
d62a17ae 13787 json_object_int_add(json, "pfxCounter",
13788 peer->pcount[afi][safi]);
13789
13790 for (i = 0; i < PCOUNT_MAX; i++)
13791 json_object_int_add(json_loop, pcount_strs[i],
13792 pcounts.count[i]);
13793
13794 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13795
13796 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13797 json_object_string_add(json, "pfxctDriftFor",
13798 peer->host);
13799 json_object_string_add(
13800 json, "recommended",
13801 "Please report this bug, with the above command output");
13802 }
75eeda93 13803 vty_json(vty, json);
d62a17ae 13804 } else {
13805
13806 if (peer->hostname
892fedb6 13807 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13808 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13809 peer->hostname, peer->host,
5cb5f4d0 13810 get_afi_safi_str(afi, safi, false));
d62a17ae 13811 } else {
13812 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13813 get_afi_safi_str(afi, safi, false));
d62a17ae 13814 }
13815
6cde4b45 13816 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13817 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13818
13819 for (i = 0; i < PCOUNT_MAX; i++)
13820 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13821 pcounts.count[i]);
13822
13823 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13824 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13825 vty_out(vty,
13826 "Please report this bug, with the above command output\n");
13827 }
13828 }
13829
13830 return CMD_SUCCESS;
718e3744 13831}
13832
a636c635
DW
13833DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13834 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13835 "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 13836 SHOW_STR
13837 IP_STR
13838 BGP_STR
8386ac43 13839 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13840 BGP_AFI_HELP_STR
13841 BGP_SAFI_HELP_STR
0b16f239
DS
13842 "Detailed information on TCP and BGP neighbor connections\n"
13843 "Neighbor to display information about\n"
13844 "Neighbor to display information about\n"
91d37724 13845 "Neighbor on BGP configured interface\n"
a636c635 13846 "Display detailed prefix count information\n"
9973d184 13847 JSON_STR)
0b16f239 13848{
d62a17ae 13849 afi_t afi = AFI_IP6;
13850 safi_t safi = SAFI_UNICAST;
13851 struct peer *peer;
13852 int idx = 0;
13853 struct bgp *bgp = NULL;
9f049418
DS
13854 bool uj = use_json(argc, argv);
13855
13856 if (uj)
13857 argc--;
856ca177 13858
d62a17ae 13859 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13860 &bgp, uj);
d62a17ae 13861 if (!idx)
13862 return CMD_WARNING;
0b16f239 13863
d62a17ae 13864 argv_find(argv, argc, "neighbors", &idx);
13865 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13866 if (!peer)
13867 return CMD_WARNING;
bb46e94f 13868
29c8d9da 13869 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13870}
0b16f239 13871
d6902373
PG
13872#ifdef KEEP_OLD_VPN_COMMANDS
13873DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13874 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13875 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13876 SHOW_STR
13877 IP_STR
13878 BGP_STR
d6902373 13879 BGP_VPNVX_HELP_STR
91d37724 13880 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13881 "Detailed information on TCP and BGP neighbor connections\n"
13882 "Neighbor to display information about\n"
13883 "Neighbor to display information about\n"
91d37724 13884 "Neighbor on BGP configured interface\n"
a636c635 13885 "Display detailed prefix count information\n"
9973d184 13886 JSON_STR)
a636c635 13887{
d62a17ae 13888 int idx_peer = 6;
13889 struct peer *peer;
9f049418 13890 bool uj = use_json(argc, argv);
a636c635 13891
d62a17ae 13892 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13893 if (!peer)
13894 return CMD_WARNING;
13895
13896 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13897}
13898
d6902373
PG
13899DEFUN (show_ip_bgp_vpn_all_route_prefix,
13900 show_ip_bgp_vpn_all_route_prefix_cmd,
13901 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13902 SHOW_STR
13903 IP_STR
13904 BGP_STR
d6902373 13905 BGP_VPNVX_HELP_STR
91d37724
QY
13906 "Display information about all VPNv4 NLRIs\n"
13907 "Network in the BGP routing table to display\n"
3a2d747c 13908 "Network in the BGP routing table to display\n"
9973d184 13909 JSON_STR)
91d37724 13910{
d62a17ae 13911 int idx = 0;
13912 char *network = NULL;
13913 struct bgp *bgp = bgp_get_default();
13914 if (!bgp) {
13915 vty_out(vty, "Can't find default instance\n");
13916 return CMD_WARNING;
13917 }
87e34b58 13918
d62a17ae 13919 if (argv_find(argv, argc, "A.B.C.D", &idx))
13920 network = argv[idx]->arg;
13921 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13922 network = argv[idx]->arg;
13923 else {
13924 vty_out(vty, "Unable to figure out Network\n");
13925 return CMD_WARNING;
13926 }
87e34b58 13927
d62a17ae 13928 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13929 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13930 use_json(argc, argv));
91d37724 13931}
d6902373 13932#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13933
44c69747
LK
13934DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13935 show_bgp_l2vpn_evpn_route_prefix_cmd,
13936 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13937 SHOW_STR
4c63a661
PG
13938 BGP_STR
13939 L2VPN_HELP_STR
13940 EVPN_HELP_STR
44c69747
LK
13941 "Network in the BGP routing table to display\n"
13942 "Network in the BGP routing table to display\n"
4c63a661
PG
13943 "Network in the BGP routing table to display\n"
13944 "Network in the BGP routing table to display\n"
13945 JSON_STR)
13946{
d62a17ae 13947 int idx = 0;
13948 char *network = NULL;
44c69747 13949 int prefix_check = 0;
a636c635 13950
44c69747
LK
13951 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13952 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13953 network = argv[idx]->arg;
44c69747 13954 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13955 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13956 network = argv[idx]->arg;
44c69747
LK
13957 prefix_check = 1;
13958 } else {
d62a17ae 13959 vty_out(vty, "Unable to figure out Network\n");
13960 return CMD_WARNING;
13961 }
44c69747
LK
13962 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13963 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13964 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13965}
13966
114fc229 13967static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13968 struct bgp_table *table, int *header1,
13969 int *header2, json_object *json,
13970 json_object *json_scode,
e960b4ca
TA
13971 json_object *json_ocode, bool wide,
13972 bool detail)
2f9bc755
DS
13973{
13974 uint64_t version = table ? table->version : 0;
13975
13976 if (*header1) {
13977 if (json) {
13978 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13979 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13980 "%pI4", &peer->bgp->router_id);
2f9bc755 13981 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13982 peer->bgp->default_local_pref);
13983 json_object_int_add(json, "localAS",
13984 peer->change_local_as
13985 ? peer->change_local_as
13986 : peer->local_as);
2f9bc755
DS
13987 json_object_object_add(json, "bgpStatusCodes",
13988 json_scode);
13989 json_object_object_add(json, "bgpOriginCodes",
13990 json_ocode);
13991 } else {
13992 vty_out(vty,
23d0a753
DA
13993 "BGP table version is %" PRIu64
13994 ", local router ID is %pI4, vrf id ",
114fc229
DA
13995 version, &peer->bgp->router_id);
13996 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13997 vty_out(vty, "%s", VRFID_NONE_STR);
13998 else
114fc229 13999 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14000 vty_out(vty, "\n");
14001 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14002 peer->bgp->default_local_pref);
14003 vty_out(vty, "local AS %u\n",
14004 peer->change_local_as ? peer->change_local_as
14005 : peer->local_as);
e960b4ca
TA
14006 if (!detail) {
14007 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14008 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14009 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14010 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14011 }
2f9bc755
DS
14012 }
14013 *header1 = 0;
14014 }
14015 if (*header2) {
e960b4ca 14016 if (!json && !detail)
2f9bc755
DS
14017 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14018 : BGP_SHOW_HEADER));
14019 *header2 = 0;
14020 }
14021}
14022
d9478df0
TA
14023static void
14024show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14025 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14026 const char *rmap_name, json_object *json, json_object *json_ar,
14027 json_object *json_scode, json_object *json_ocode,
96c81f66 14028 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14029 const struct prefix *match, unsigned long *output_count,
14030 unsigned long *filtered_count)
d62a17ae 14031{
3880b4ec
TA
14032 struct bgp_adj_in *ain = NULL;
14033 struct bgp_adj_out *adj = NULL;
9bcb3eef 14034 struct bgp_dest *dest;
d62a17ae 14035 struct bgp *bgp;
d62a17ae 14036 struct attr attr;
14037 int ret;
14038 struct update_subgroup *subgrp;
3880b4ec 14039 struct peer_af *paf = NULL;
f99def61 14040 bool route_filtered;
e960b4ca 14041 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14042 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14043 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14044 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14045 || (safi == SAFI_EVPN))
14046 ? true
14047 : false;
e960b4ca
TA
14048 int display = 0;
14049 json_object *json_net = NULL;
a636c635 14050
d62a17ae 14051 bgp = peer->bgp;
a636c635 14052
3880b4ec
TA
14053 /* If the user supplied a prefix, look for a matching route instead
14054 * of walking the whole table.
14055 */
14056 if (match) {
14057 dest = bgp_node_match(table, match);
14058 if (!dest) {
14059 if (!use_json)
14060 vty_out(vty, "Network not in table\n");
14061 return;
14062 }
14063
14064 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14065
14066 if (rn_p->prefixlen != match->prefixlen) {
14067 if (!use_json)
14068 vty_out(vty, "Network not in table\n");
14069 bgp_dest_unlock_node(dest);
14070 return;
14071 }
14072
14073 if (type == bgp_show_adj_route_received ||
14074 type == bgp_show_adj_route_filtered) {
14075 for (ain = dest->adj_in; ain; ain = ain->next) {
14076 if (ain->peer == peer) {
14077 attr = *ain->attr;
14078 break;
14079 }
14080 }
14081 /* bail out if if adj_out is empty, or
14082 * if the prefix isn't in this peer's
14083 * adj_in
14084 */
14085 if (!ain || ain->peer != peer) {
14086 if (!use_json)
14087 vty_out(vty, "Network not in table\n");
14088 bgp_dest_unlock_node(dest);
14089 return;
14090 }
14091 } else if (type == bgp_show_adj_route_advertised) {
14092 bool peer_found = false;
14093
14094 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14095 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14096 if (paf->peer == peer && adj->attr) {
14097 attr = *adj->attr;
14098 peer_found = true;
14099 break;
14100 }
14101 }
14102 if (peer_found)
14103 break;
14104 }
14105 /* bail out if if adj_out is empty, or
14106 * if the prefix isn't in this peer's
14107 * adj_out
14108 */
14109 if (!paf || !peer_found) {
14110 if (!use_json)
14111 vty_out(vty, "Network not in table\n");
14112 bgp_dest_unlock_node(dest);
14113 return;
14114 }
14115 }
14116
14117 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14118 rmap_name);
14119
14120 if (ret != RMAP_DENY) {
14121 show_adj_route_header(vty, peer, table, header1,
14122 header2, json, json_scode,
14123 json_ocode, wide, detail);
14124
14125 if (use_json)
14126 json_net = json_object_new_object();
14127
14128 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14129 afi, safi, json_net,
14130 BGP_PATH_SHOW_ALL, &display,
14131 RPKI_NOT_BEING_USED);
14132 if (use_json)
14133 json_object_object_addf(json_ar, json_net,
14134 "%pFX", rn_p);
14135 (*output_count)++;
14136 } else
14137 (*filtered_count)++;
14138
14139 bgp_attr_flush(&attr);
14140 bgp_dest_unlock_node(dest);
14141 return;
14142 }
14143
14144
d62a17ae 14145 subgrp = peer_subgroup(peer, afi, safi);
14146
6392aaa6 14147 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14148 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14149 if (use_json) {
14150 json_object_int_add(json, "bgpTableVersion",
14151 table->version);
c949c771
DA
14152 json_object_string_addf(json, "bgpLocalRouterId",
14153 "%pI4", &bgp->router_id);
01eced22
AD
14154 json_object_int_add(json, "defaultLocPrf",
14155 bgp->default_local_pref);
114fc229
DA
14156 json_object_int_add(json, "localAS",
14157 peer->change_local_as
14158 ? peer->change_local_as
14159 : peer->local_as);
d62a17ae 14160 json_object_object_add(json, "bgpStatusCodes",
14161 json_scode);
14162 json_object_object_add(json, "bgpOriginCodes",
14163 json_ocode);
07d0c4ed
DA
14164 json_object_string_add(
14165 json, "bgpOriginatingDefaultNetwork",
14166 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14167 } else {
23d0a753
DA
14168 vty_out(vty,
14169 "BGP table version is %" PRIu64
14170 ", local router ID is %pI4, vrf id ",
14171 table->version, &bgp->router_id);
9df8b37c
PZ
14172 if (bgp->vrf_id == VRF_UNKNOWN)
14173 vty_out(vty, "%s", VRFID_NONE_STR);
14174 else
14175 vty_out(vty, "%u", bgp->vrf_id);
14176 vty_out(vty, "\n");
01eced22
AD
14177 vty_out(vty, "Default local pref %u, ",
14178 bgp->default_local_pref);
114fc229
DA
14179 vty_out(vty, "local AS %u\n",
14180 peer->change_local_as ? peer->change_local_as
14181 : peer->local_as);
e960b4ca
TA
14182 if (!detail) {
14183 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14184 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14185 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14186 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14187 }
d62a17ae 14188
07d0c4ed
DA
14189 vty_out(vty, "Originating default network %s\n\n",
14190 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14191 }
65565c9a 14192 (*output_count)++;
d9478df0 14193 *header1 = 0;
d62a17ae 14194 }
a636c635 14195
9bcb3eef 14196 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14197 if (type == bgp_show_adj_route_received
14198 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14199 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14200 if (ain->peer != peer)
ea47320b 14201 continue;
6392aaa6 14202
114fc229 14203 show_adj_route_header(vty, peer, table, header1,
d9478df0 14204 header2, json, json_scode,
e960b4ca 14205 json_ocode, wide, detail);
d9478df0
TA
14206
14207 if ((safi == SAFI_MPLS_VPN)
14208 || (safi == SAFI_ENCAP)
14209 || (safi == SAFI_EVPN)) {
14210 if (use_json)
14211 json_object_string_add(
14212 json_ar, "rd", rd_str);
14213 else if (show_rd && rd_str) {
14214 vty_out(vty,
14215 "Route Distinguisher: %s\n",
14216 rd_str);
14217 show_rd = false;
14218 }
14219 }
6392aaa6 14220
6f4f49b2 14221 attr = *ain->attr;
f99def61
AD
14222 route_filtered = false;
14223
14224 /* Filter prefix using distribute list,
14225 * filter list or prefix list
14226 */
b54892e0 14227 const struct prefix *rn_p =
9bcb3eef 14228 bgp_dest_get_prefix(dest);
b54892e0
DS
14229 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14230 safi))
14231 == FILTER_DENY)
f99def61
AD
14232 route_filtered = true;
14233
14234 /* Filter prefix using route-map */
b54892e0
DS
14235 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14236 safi, rmap_name, NULL,
14237 0, NULL);
6392aaa6 14238
13c8e163
AD
14239 if (type == bgp_show_adj_route_filtered &&
14240 !route_filtered && ret != RMAP_DENY) {
d498917e 14241 bgp_attr_flush(&attr);
6392aaa6 14242 continue;
d62a17ae 14243 }
6392aaa6 14244
d9478df0
TA
14245 if (type == bgp_show_adj_route_received
14246 && (route_filtered || ret == RMAP_DENY))
14247 (*filtered_count)++;
6392aaa6 14248
e960b4ca
TA
14249 if (detail) {
14250 if (use_json)
14251 json_net =
14252 json_object_new_object();
14253 bgp_show_path_info(
14254 NULL /* prefix_rd */, dest, vty,
14255 bgp, afi, safi, json_net,
14256 BGP_PATH_SHOW_ALL, &display,
14257 RPKI_NOT_BEING_USED);
14258 if (use_json)
14259 json_object_object_addf(
14260 json_ar, json_net,
14261 "%pFX", rn_p);
14262 } else
14263 route_vty_out_tmp(vty, dest, rn_p,
14264 &attr, safi, use_json,
14265 json_ar, wide);
d498917e 14266 bgp_attr_flush(&attr);
d9478df0 14267 (*output_count)++;
d62a17ae 14268 }
6392aaa6 14269 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14270 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14271 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14272 if (paf->peer != peer || !adj->attr)
924c3f6a 14273 continue;
d62a17ae 14274
e960b4ca
TA
14275 show_adj_route_header(
14276 vty, peer, table, header1,
14277 header2, json, json_scode,
14278 json_ocode, wide, detail);
d62a17ae 14279
b54892e0 14280 const struct prefix *rn_p =
9bcb3eef 14281 bgp_dest_get_prefix(dest);
b54892e0 14282
6f4f49b2 14283 attr = *adj->attr;
b755861b 14284 ret = bgp_output_modifier(
b54892e0 14285 peer, rn_p, &attr, afi, safi,
b755861b 14286 rmap_name);
f46d8e1e 14287
b755861b 14288 if (ret != RMAP_DENY) {
d9478df0
TA
14289 if ((safi == SAFI_MPLS_VPN)
14290 || (safi == SAFI_ENCAP)
14291 || (safi == SAFI_EVPN)) {
14292 if (use_json)
14293 json_object_string_add(
14294 json_ar,
14295 "rd",
14296 rd_str);
14297 else if (show_rd
14298 && rd_str) {
14299 vty_out(vty,
14300 "Route Distinguisher: %s\n",
14301 rd_str);
14302 show_rd = false;
14303 }
14304 }
e960b4ca
TA
14305 if (detail) {
14306 if (use_json)
14307 json_net =
14308 json_object_new_object();
14309 bgp_show_path_info(
14310 NULL /* prefix_rd
14311 */
14312 ,
14313 dest, vty, bgp,
14314 afi, safi,
14315 json_net,
14316 BGP_PATH_SHOW_ALL,
14317 &display,
14318 RPKI_NOT_BEING_USED);
14319 if (use_json)
14320 json_object_object_addf(
14321 json_ar,
14322 json_net,
14323 "%pFX",
14324 rn_p);
14325 } else
14326 route_vty_out_tmp(
14327 vty, dest, rn_p,
14328 &attr, safi,
14329 use_json,
14330 json_ar, wide);
d9478df0 14331 (*output_count)++;
b755861b 14332 } else {
d9478df0 14333 (*filtered_count)++;
a2addae8 14334 }
b755861b 14335
d498917e 14336 bgp_attr_flush(&attr);
924c3f6a 14337 }
f20ce998
DS
14338 } else if (type == bgp_show_adj_route_bestpath) {
14339 struct bgp_path_info *pi;
14340
114fc229
DA
14341 show_adj_route_header(vty, peer, table, header1,
14342 header2, json, json_scode,
e960b4ca 14343 json_ocode, wide, detail);
f20ce998 14344
aa9bf57e
TA
14345 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14346
f20ce998
DS
14347 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14348 pi = pi->next) {
14349 if (pi->peer != peer)
14350 continue;
14351
14352 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14353 continue;
14354
aa9bf57e
TA
14355 if (detail) {
14356 if (use_json)
14357 json_net =
14358 json_object_new_object();
14359 bgp_show_path_info(
14360 NULL /* prefix_rd */, dest, vty,
14361 bgp, afi, safi, json_net,
14362 BGP_PATH_SHOW_BESTPATH,
14363 &display, RPKI_NOT_BEING_USED);
14364 if (use_json)
14365 json_object_object_addf(
14366 json_ar, json_net,
14367 "%pFX", rn_p);
14368 } else
14369 route_vty_out_tmp(
14370 vty, dest, rn_p, pi->attr, safi,
14371 use_json, json_ar, wide);
d9478df0 14372 (*output_count)++;
f20ce998 14373 }
d62a17ae 14374 }
14375 }
a636c635 14376}
2a71e9ce 14377
d62a17ae 14378static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14379 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14380 const char *rmap_name, const struct prefix *match,
14381 uint16_t show_flags)
0b16f239 14382{
d9478df0
TA
14383 struct bgp *bgp;
14384 struct bgp_table *table;
d62a17ae 14385 json_object *json = NULL;
d9478df0
TA
14386 json_object *json_scode = NULL;
14387 json_object *json_ocode = NULL;
14388 json_object *json_ar = NULL;
96f3485c 14389 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14390
d9478df0
TA
14391 /* Init BGP headers here so they're only displayed once
14392 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14393 */
14394 int header1 = 1;
14395 int header2 = 1;
14396
14397 /*
14398 * Initialize variables for each RD
14399 * All prefixes under an RD is aggregated within "json_routes"
14400 */
14401 char rd_str[BUFSIZ] = {0};
14402 json_object *json_routes = NULL;
14403
14404
14405 /* For 2-tier tables, prefix counts need to be
14406 * maintained across multiple runs of show_adj_route()
14407 */
14408 unsigned long output_count_per_rd;
14409 unsigned long filtered_count_per_rd;
14410 unsigned long output_count = 0;
14411 unsigned long filtered_count = 0;
14412
14413 if (use_json) {
d62a17ae 14414 json = json_object_new_object();
d9478df0
TA
14415 json_ar = json_object_new_object();
14416 json_scode = json_object_new_object();
14417 json_ocode = json_object_new_object();
dd426a51
DA
14418#if CONFDATE > 20231208
14419CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14420#endif
d9478df0
TA
14421 json_object_string_add(json_scode, "suppressed", "s");
14422 json_object_string_add(json_scode, "damped", "d");
14423 json_object_string_add(json_scode, "history", "h");
14424 json_object_string_add(json_scode, "valid", "*");
14425 json_object_string_add(json_scode, "best", ">");
14426 json_object_string_add(json_scode, "multipath", "=");
14427 json_object_string_add(json_scode, "internal", "i");
14428 json_object_string_add(json_scode, "ribFailure", "r");
14429 json_object_string_add(json_scode, "stale", "S");
14430 json_object_string_add(json_scode, "removed", "R");
14431
dd426a51
DA
14432#if CONFDATE > 20231208
14433CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14434#endif
d9478df0
TA
14435 json_object_string_add(json_ocode, "igp", "i");
14436 json_object_string_add(json_ocode, "egp", "e");
14437 json_object_string_add(json_ocode, "incomplete", "?");
14438 }
0b16f239 14439
d62a17ae 14440 if (!peer || !peer->afc[afi][safi]) {
14441 if (use_json) {
14442 json_object_string_add(
14443 json, "warning",
14444 "No such neighbor or address family");
14445 vty_out(vty, "%s\n", json_object_to_json_string(json));
14446 json_object_free(json);
690c3134
MW
14447 json_object_free(json_ar);
14448 json_object_free(json_scode);
14449 json_object_free(json_ocode);
d62a17ae 14450 } else
14451 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14452
d62a17ae 14453 return CMD_WARNING;
14454 }
14455
6392aaa6
PM
14456 if ((type == bgp_show_adj_route_received
14457 || type == bgp_show_adj_route_filtered)
d62a17ae 14458 && !CHECK_FLAG(peer->af_flags[afi][safi],
14459 PEER_FLAG_SOFT_RECONFIG)) {
14460 if (use_json) {
14461 json_object_string_add(
14462 json, "warning",
14463 "Inbound soft reconfiguration not enabled");
14464 vty_out(vty, "%s\n", json_object_to_json_string(json));
14465 json_object_free(json);
690c3134
MW
14466 json_object_free(json_ar);
14467 json_object_free(json_scode);
14468 json_object_free(json_ocode);
d62a17ae 14469 } else
14470 vty_out(vty,
14471 "%% Inbound soft reconfiguration not enabled\n");
14472
14473 return CMD_WARNING;
14474 }
0b16f239 14475
d9478df0
TA
14476 bgp = peer->bgp;
14477
14478 /* labeled-unicast routes live in the unicast table */
14479 if (safi == SAFI_LABELED_UNICAST)
14480 table = bgp->rib[afi][SAFI_UNICAST];
14481 else
14482 table = bgp->rib[afi][safi];
14483
14484 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14485 || (safi == SAFI_EVPN)) {
14486
14487 struct bgp_dest *dest;
14488
14489 for (dest = bgp_table_top(table); dest;
14490 dest = bgp_route_next(dest)) {
14491 table = bgp_dest_get_bgp_table_info(dest);
14492 if (!table)
14493 continue;
14494
14495 output_count_per_rd = 0;
14496 filtered_count_per_rd = 0;
14497
14498 if (use_json)
14499 json_routes = json_object_new_object();
14500
14501 const struct prefix_rd *prd;
14502 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14503 dest);
14504
4a8cd6ad
PG
14505 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14506 bgp->asnotation);
d9478df0 14507
3880b4ec
TA
14508 show_adj_route(
14509 vty, peer, table, afi, safi, type, rmap_name,
14510 json, json_routes, json_scode, json_ocode,
14511 show_flags, &header1, &header2, rd_str, match,
14512 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14513
14514 /* Don't include an empty RD in the output! */
14515 if (json_routes && (output_count_per_rd > 0))
14516 json_object_object_add(json_ar, rd_str,
14517 json_routes);
14518
14519 output_count += output_count_per_rd;
14520 filtered_count += filtered_count_per_rd;
14521 }
14522 } else
14523 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14524 json, json_ar, json_scode, json_ocode,
3880b4ec 14525 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14526 &output_count, &filtered_count);
14527
14528 if (use_json) {
c1984955
TA
14529 if (type == bgp_show_adj_route_advertised)
14530 json_object_object_add(json, "advertisedRoutes",
14531 json_ar);
14532 else
14533 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14534 json_object_int_add(json, "totalPrefixCounter", output_count);
14535 json_object_int_add(json, "filteredPrefixCounter",
14536 filtered_count);
14537
690c3134
MW
14538 /*
14539 * These fields only give up ownership to `json` when `header1`
14540 * is used (set to zero). See code in `show_adj_route` and
14541 * `show_adj_route_header`.
14542 */
14543 if (header1 == 1) {
d9478df0
TA
14544 json_object_free(json_scode);
14545 json_object_free(json_ocode);
14546 }
14547
75eeda93 14548 vty_json(vty, json);
d9478df0 14549 } else if (output_count > 0) {
3880b4ec 14550 if (!match && filtered_count > 0)
d9478df0
TA
14551 vty_out(vty,
14552 "\nTotal number of prefixes %ld (%ld filtered)\n",
14553 output_count, filtered_count);
14554 else
14555 vty_out(vty, "\nTotal number of prefixes %ld\n",
14556 output_count);
14557 }
0b16f239 14558
d62a17ae 14559 return CMD_SUCCESS;
a636c635 14560}
50ef26d4 14561
f20ce998
DS
14562DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14563 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14564 "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
14565 SHOW_STR
14566 IP_STR
14567 BGP_STR
14568 BGP_INSTANCE_HELP_STR
14569 BGP_AFI_HELP_STR
14570 BGP_SAFI_WITH_LABEL_HELP_STR
14571 "Detailed information on TCP and BGP neighbor connections\n"
14572 "Neighbor to display information about\n"
14573 "Neighbor to display information about\n"
14574 "Neighbor on BGP configured interface\n"
14575 "Display the routes selected by best path\n"
aa9bf57e 14576 "Display detailed version of routes\n"
f20ce998
DS
14577 JSON_STR
14578 "Increase table width for longer prefixes\n")
14579{
14580 afi_t afi = AFI_IP6;
14581 safi_t safi = SAFI_UNICAST;
14582 char *rmap_name = NULL;
14583 char *peerstr = NULL;
14584 struct bgp *bgp = NULL;
14585 struct peer *peer;
14586 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14587 int idx = 0;
96c81f66 14588 uint16_t show_flags = 0;
96f3485c 14589
aa9bf57e
TA
14590 if (detail)
14591 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14592
96f3485c
MK
14593 if (uj)
14594 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14595
14596 if (wide)
14597 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14598
14599 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14600 &bgp, uj);
14601
14602 if (!idx)
14603 return CMD_WARNING;
14604
14605 argv_find(argv, argc, "neighbors", &idx);
14606 peerstr = argv[++idx]->arg;
14607
14608 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14609 if (!peer)
14610 return CMD_WARNING;
14611
3880b4ec 14612 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14613 show_flags);
f20ce998
DS
14614}
14615
e960b4ca
TA
14616DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14617 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14618 "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
14619 SHOW_STR
14620 IP_STR
14621 BGP_STR
14622 BGP_INSTANCE_HELP_STR
14623 BGP_AFI_HELP_STR
14624 BGP_SAFI_WITH_LABEL_HELP_STR
14625 "Display the entries for all address families\n"
14626 "Detailed information on TCP and BGP neighbor connections\n"
14627 "Neighbor to display information about\n"
14628 "Neighbor to display information about\n"
14629 "Neighbor on BGP configured interface\n"
14630 "Display the routes advertised to a BGP neighbor\n"
14631 "Display the received routes from neighbor\n"
14632 "Display the filtered routes received from neighbor\n"
14633 "Route-map to modify the attributes\n"
14634 "Name of the route map\n"
3880b4ec
TA
14635 "IPv4 prefix\n"
14636 "IPv6 prefix\n"
e960b4ca
TA
14637 "Display detailed version of routes\n"
14638 JSON_STR
14639 "Increase table width for longer prefixes\n")
718e3744 14640{
d62a17ae 14641 afi_t afi = AFI_IP6;
14642 safi_t safi = SAFI_UNICAST;
d62a17ae 14643 char *peerstr = NULL;
d62a17ae 14644 struct bgp *bgp = NULL;
14645 struct peer *peer;
6392aaa6 14646 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14647 int idx = 0;
96f3485c 14648 bool first = true;
96c81f66 14649 uint16_t show_flags = 0;
75ce3b14
DA
14650 struct listnode *node;
14651 struct bgp *abgp;
6392aaa6 14652
3880b4ec 14653 if (detail || prefix_str)
e960b4ca
TA
14654 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14655
96f3485c 14656 if (uj) {
d62a17ae 14657 argc--;
96f3485c
MK
14658 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14659 }
14660
14661 if (all) {
14662 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14663 if (argv_find(argv, argc, "ipv4", &idx))
14664 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14665
14666 if (argv_find(argv, argc, "ipv6", &idx))
14667 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14668 }
14669
14670 if (wide)
14671 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14672
9f049418
DS
14673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14674 &bgp, uj);
14675 if (!idx)
14676 return CMD_WARNING;
14677
d62a17ae 14678 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14679 argv_find(argv, argc, "neighbors", &idx);
14680 peerstr = argv[++idx]->arg;
8c3deaae 14681
d62a17ae 14682 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14683 if (!peer)
14684 return CMD_WARNING;
856ca177 14685
d62a17ae 14686 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14687 type = bgp_show_adj_route_advertised;
14688 else if (argv_find(argv, argc, "received-routes", &idx))
14689 type = bgp_show_adj_route_received;
14690 else if (argv_find(argv, argc, "filtered-routes", &idx))
14691 type = bgp_show_adj_route_filtered;
14692
96f3485c 14693 if (!all)
70dd370f 14694 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14695 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14696 if (uj)
14697 vty_out(vty, "{\n");
14698
14699 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14700 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14701 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14702 : AFI_IP6;
75ce3b14
DA
14703 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14704 FOREACH_SAFI (safi) {
14705 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14706 continue;
96f3485c 14707
75ce3b14
DA
14708 if (uj) {
14709 if (first)
14710 first = false;
14711 else
14712 vty_out(vty, ",\n");
14713 vty_out(vty, "\"%s\":",
14714 get_afi_safi_str(afi, safi,
14715 true));
14716 } else
14717 vty_out(vty,
14718 "\nFor address family: %s\n",
14719 get_afi_safi_str(afi, safi,
14720 false));
96f3485c 14721
75ce3b14 14722 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14723 route_map, prefix, show_flags);
75ce3b14 14724 }
96f3485c
MK
14725 }
14726 } else {
75ce3b14
DA
14727 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14728 FOREACH_AFI_SAFI (afi, safi) {
14729 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14730 continue;
96f3485c 14731
75ce3b14
DA
14732 if (uj) {
14733 if (first)
14734 first = false;
14735 else
14736 vty_out(vty, ",\n");
14737 vty_out(vty, "\"%s\":",
14738 get_afi_safi_str(afi, safi,
14739 true));
14740 } else
14741 vty_out(vty,
14742 "\nFor address family: %s\n",
14743 get_afi_safi_str(afi, safi,
14744 false));
96f3485c 14745
75ce3b14 14746 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14747 route_map, prefix, show_flags);
75ce3b14 14748 }
96f3485c
MK
14749 }
14750 }
14751 if (uj)
14752 vty_out(vty, "}\n");
14753
14754 return CMD_SUCCESS;
95cbbd2a
ML
14755}
14756
718e3744 14757DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14758 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14759 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14760 SHOW_STR
14761 IP_STR
14762 BGP_STR
d3120452 14763 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14764 BGP_AF_STR
14765 BGP_AF_STR
14766 BGP_AF_MODIFIER_STR
718e3744 14767 "Detailed information on TCP and BGP neighbor connections\n"
14768 "Neighbor to display information about\n"
14769 "Neighbor to display information about\n"
91d37724 14770 "Neighbor on BGP configured interface\n"
718e3744 14771 "Display information received from a BGP neighbor\n"
856ca177 14772 "Display the prefixlist filter\n"
9973d184 14773 JSON_STR)
718e3744 14774{
d62a17ae 14775 afi_t afi = AFI_IP6;
14776 safi_t safi = SAFI_UNICAST;
14777 char *peerstr = NULL;
d62a17ae 14778 char name[BUFSIZ];
d62a17ae 14779 struct peer *peer;
d3120452 14780 int count;
d62a17ae 14781 int idx = 0;
d3120452
IR
14782 struct bgp *bgp = NULL;
14783 bool uj = use_json(argc, argv);
14784
14785 if (uj)
14786 argc--;
14787
14788 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14789 &bgp, uj);
14790 if (!idx)
14791 return CMD_WARNING;
d62a17ae 14792
d62a17ae 14793 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14794 argv_find(argv, argc, "neighbors", &idx);
14795 peerstr = argv[++idx]->arg;
14796
d3120452
IR
14797 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14798 if (!peer)
14799 return CMD_WARNING;
718e3744 14800
4ced1a2c 14801 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14802 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14803 if (count) {
14804 if (!uj)
14805 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14806 get_afi_safi_str(afi, safi, false));
d62a17ae 14807 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14808 } else {
14809 if (uj)
14810 vty_out(vty, "{}\n");
14811 else
14812 vty_out(vty, "No functional output\n");
14813 }
718e3744 14814
d62a17ae 14815 return CMD_SUCCESS;
14816}
14817
14818static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14819 afi_t afi, safi_t safi,
9f049418 14820 enum bgp_show_type type, bool use_json)
d62a17ae 14821{
96c81f66 14822 uint16_t show_flags = 0;
96f3485c
MK
14823
14824 if (use_json)
14825 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14826
d62a17ae 14827 if (!peer || !peer->afc[afi][safi]) {
14828 if (use_json) {
14829 json_object *json_no = NULL;
14830 json_no = json_object_new_object();
14831 json_object_string_add(
14832 json_no, "warning",
14833 "No such neighbor or address family");
14834 vty_out(vty, "%s\n",
14835 json_object_to_json_string(json_no));
14836 json_object_free(json_no);
14837 } else
14838 vty_out(vty, "%% No such neighbor or address family\n");
14839 return CMD_WARNING;
14840 }
47fc97cc 14841
7daf25a3
TA
14842 /* labeled-unicast routes live in the unicast table */
14843 if (safi == SAFI_LABELED_UNICAST)
14844 safi = SAFI_UNICAST;
14845
1e2ce4f1
DS
14846 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14847 RPKI_NOT_BEING_USED);
718e3744 14848}
14849
dba3c1d3
PG
14850DEFUN (show_ip_bgp_flowspec_routes_detailed,
14851 show_ip_bgp_flowspec_routes_detailed_cmd,
14852 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14853 SHOW_STR
14854 IP_STR
14855 BGP_STR
14856 BGP_INSTANCE_HELP_STR
14857 BGP_AFI_HELP_STR
14858 "SAFI Flowspec\n"
14859 "Detailed information on flowspec entries\n"
14860 JSON_STR)
14861{
458c1475 14862 afi_t afi = AFI_IP6;
dba3c1d3
PG
14863 safi_t safi = SAFI_UNICAST;
14864 struct bgp *bgp = NULL;
14865 int idx = 0;
9f049418 14866 bool uj = use_json(argc, argv);
81dcd881 14867 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14868
96f3485c 14869 if (uj) {
9f049418 14870 argc--;
96f3485c
MK
14871 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14872 }
dba3c1d3
PG
14873
14874 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14875 &bgp, uj);
dba3c1d3
PG
14876 if (!idx)
14877 return CMD_WARNING;
14878
96f3485c 14879 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14880 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14881}
14882
718e3744 14883DEFUN (show_ip_bgp_neighbor_routes,
14884 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14885 "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 14886 SHOW_STR
14887 IP_STR
14888 BGP_STR
8386ac43 14889 BGP_INSTANCE_HELP_STR
4f280b15 14890 BGP_AFI_HELP_STR
4dd6177e 14891 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14892 "Detailed information on TCP and BGP neighbor connections\n"
14893 "Neighbor to display information about\n"
14894 "Neighbor to display information about\n"
91d37724 14895 "Neighbor on BGP configured interface\n"
2525cf39 14896 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14897 "Display the dampened routes received from neighbor\n"
14898 "Display routes learned from neighbor\n"
9973d184 14899 JSON_STR)
718e3744 14900{
d62a17ae 14901 char *peerstr = NULL;
14902 struct bgp *bgp = NULL;
14903 afi_t afi = AFI_IP6;
14904 safi_t safi = SAFI_UNICAST;
14905 struct peer *peer;
14906 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14907 int idx = 0;
9f049418
DS
14908 bool uj = use_json(argc, argv);
14909
14910 if (uj)
14911 argc--;
bb46e94f 14912
d62a17ae 14913 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14914 &bgp, uj);
d62a17ae 14915 if (!idx)
14916 return CMD_WARNING;
c493f2d8 14917
d62a17ae 14918 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14919 argv_find(argv, argc, "neighbors", &idx);
14920 peerstr = argv[++idx]->arg;
8c3deaae 14921
d62a17ae 14922 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14923 if (!peer)
d62a17ae 14924 return CMD_WARNING;
bb46e94f 14925
d62a17ae 14926 if (argv_find(argv, argc, "flap-statistics", &idx))
14927 sh_type = bgp_show_type_flap_neighbor;
14928 else if (argv_find(argv, argc, "dampened-routes", &idx))
14929 sh_type = bgp_show_type_damp_neighbor;
14930 else if (argv_find(argv, argc, "routes", &idx))
14931 sh_type = bgp_show_type_neighbor;
2525cf39 14932
d62a17ae 14933 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14934}
6b0655a2 14935
734b349e 14936struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14937
d62a17ae 14938struct bgp_distance {
14939 /* Distance value for the IP source prefix. */
d7c0a89a 14940 uint8_t distance;
718e3744 14941
d62a17ae 14942 /* Name of the access-list to be matched. */
14943 char *access_list;
718e3744 14944};
14945
4f280b15
LB
14946DEFUN (show_bgp_afi_vpn_rd_route,
14947 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14948 "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
14949 SHOW_STR
14950 BGP_STR
14951 BGP_AFI_HELP_STR
00e6edb9 14952 BGP_AF_MODIFIER_STR
4f280b15
LB
14953 "Display information for a route distinguisher\n"
14954 "Route Distinguisher\n"
a111dd97 14955 "All Route Distinguishers\n"
7395a2c9
DS
14956 "Network in the BGP routing table to display\n"
14957 "Network in the BGP routing table to display\n"
14958 JSON_STR)
4f280b15 14959{
d62a17ae 14960 int ret;
14961 struct prefix_rd prd;
14962 afi_t afi = AFI_MAX;
14963 int idx = 0;
4f280b15 14964
ff6566f3
DS
14965 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14966 vty_out(vty, "%% Malformed Address Family\n");
14967 return CMD_WARNING;
14968 }
14969
a111dd97
TA
14970 if (!strcmp(argv[5]->arg, "all"))
14971 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14972 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14973 RPKI_NOT_BEING_USED,
14974 use_json(argc, argv));
14975
d62a17ae 14976 ret = str2prefix_rd(argv[5]->arg, &prd);
14977 if (!ret) {
14978 vty_out(vty, "%% Malformed Route Distinguisher\n");
14979 return CMD_WARNING;
14980 }
ff6566f3 14981
d62a17ae 14982 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14983 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14984 use_json(argc, argv));
4f280b15
LB
14985}
14986
d62a17ae 14987static struct bgp_distance *bgp_distance_new(void)
718e3744 14988{
d62a17ae 14989 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14990}
14991
d62a17ae 14992static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14993{
d62a17ae 14994 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14995}
14996
585f1adc
IR
14997static int bgp_distance_set(struct vty *vty, const char *distance_str,
14998 const char *ip_str, const char *access_list_str)
718e3744 14999{
d62a17ae 15000 int ret;
585f1adc
IR
15001 afi_t afi;
15002 safi_t safi;
d62a17ae 15003 struct prefix p;
585f1adc 15004 uint8_t distance;
9bcb3eef 15005 struct bgp_dest *dest;
d62a17ae 15006 struct bgp_distance *bdistance;
718e3744 15007
585f1adc
IR
15008 afi = bgp_node_afi(vty);
15009 safi = bgp_node_safi(vty);
15010
d62a17ae 15011 ret = str2prefix(ip_str, &p);
15012 if (ret == 0) {
585f1adc 15013 vty_out(vty, "Malformed prefix\n");
d62a17ae 15014 return CMD_WARNING_CONFIG_FAILED;
15015 }
718e3744 15016
585f1adc
IR
15017 distance = atoi(distance_str);
15018
d62a17ae 15019 /* Get BGP distance node. */
9bcb3eef
DS
15020 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15021 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15022 if (bdistance)
9bcb3eef 15023 bgp_dest_unlock_node(dest);
ca2e160d 15024 else {
d62a17ae 15025 bdistance = bgp_distance_new();
9bcb3eef 15026 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15027 }
718e3744 15028
d62a17ae 15029 /* Set distance value. */
15030 bdistance->distance = distance;
718e3744 15031
d62a17ae 15032 /* Reset access-list configuration. */
e1b36e13 15033 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15034 if (access_list_str)
15035 bdistance->access_list =
15036 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15037
d62a17ae 15038 return CMD_SUCCESS;
718e3744 15039}
15040
585f1adc
IR
15041static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15042 const char *ip_str, const char *access_list_str)
718e3744 15043{
d62a17ae 15044 int ret;
585f1adc
IR
15045 afi_t afi;
15046 safi_t safi;
d62a17ae 15047 struct prefix p;
585f1adc 15048 int distance;
9bcb3eef 15049 struct bgp_dest *dest;
d62a17ae 15050 struct bgp_distance *bdistance;
718e3744 15051
585f1adc
IR
15052 afi = bgp_node_afi(vty);
15053 safi = bgp_node_safi(vty);
15054
d62a17ae 15055 ret = str2prefix(ip_str, &p);
15056 if (ret == 0) {
585f1adc 15057 vty_out(vty, "Malformed prefix\n");
d62a17ae 15058 return CMD_WARNING_CONFIG_FAILED;
15059 }
718e3744 15060
9bcb3eef
DS
15061 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15062 if (!dest) {
585f1adc 15063 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15064 return CMD_WARNING_CONFIG_FAILED;
15065 }
718e3744 15066
9bcb3eef 15067 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15068 distance = atoi(distance_str);
1f9a9fff 15069
d62a17ae 15070 if (bdistance->distance != distance) {
585f1adc 15071 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15072 bgp_dest_unlock_node(dest);
d62a17ae 15073 return CMD_WARNING_CONFIG_FAILED;
15074 }
718e3744 15075
0a22ddfb 15076 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15077 bgp_distance_free(bdistance);
718e3744 15078
9bcb3eef
DS
15079 bgp_dest_set_bgp_path_info(dest, NULL);
15080 bgp_dest_unlock_node(dest);
15081 bgp_dest_unlock_node(dest);
718e3744 15082
d62a17ae 15083 return CMD_SUCCESS;
718e3744 15084}
15085
718e3744 15086/* Apply BGP information to distance method. */
b8685f9b 15087uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15088 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15089{
9bcb3eef 15090 struct bgp_dest *dest;
801bb996 15091 struct prefix q = {0};
d62a17ae 15092 struct peer *peer;
15093 struct bgp_distance *bdistance;
15094 struct access_list *alist;
15095 struct bgp_static *bgp_static;
a04f1c42 15096 struct bgp_path_info *bpi_ultimate;
d62a17ae 15097
15098 if (!bgp)
15099 return 0;
15100
40381db7 15101 peer = pinfo->peer;
d62a17ae 15102
7b7d48e5
DS
15103 if (pinfo->attr->distance)
15104 return pinfo->attr->distance;
15105
a04f1c42
PG
15106 /* get peer origin to calculate appropriate distance */
15107 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15108 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15109 peer = bpi_ultimate->peer;
15110 }
15111
801bb996
CS
15112 /* Check source address.
15113 * Note: for aggregate route, peer can have unspec af type.
15114 */
15115 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15116 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15117 return 0;
15118
9bcb3eef
DS
15119 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15120 if (dest) {
15121 bdistance = bgp_dest_get_bgp_distance_info(dest);
15122 bgp_dest_unlock_node(dest);
d62a17ae 15123
15124 if (bdistance->access_list) {
15125 alist = access_list_lookup(afi, bdistance->access_list);
15126 if (alist
15127 && access_list_apply(alist, p) == FILTER_PERMIT)
15128 return bdistance->distance;
15129 } else
15130 return bdistance->distance;
718e3744 15131 }
718e3744 15132
d62a17ae 15133 /* Backdoor check. */
9bcb3eef
DS
15134 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15135 if (dest) {
15136 bgp_static = bgp_dest_get_bgp_static_info(dest);
15137 bgp_dest_unlock_node(dest);
718e3744 15138
d62a17ae 15139 if (bgp_static->backdoor) {
15140 if (bgp->distance_local[afi][safi])
15141 return bgp->distance_local[afi][safi];
15142 else
15143 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15144 }
718e3744 15145 }
718e3744 15146
d62a17ae 15147 if (peer->sort == BGP_PEER_EBGP) {
15148 if (bgp->distance_ebgp[afi][safi])
15149 return bgp->distance_ebgp[afi][safi];
15150 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15151 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15152 if (bgp->distance_ibgp[afi][safi])
15153 return bgp->distance_ibgp[afi][safi];
15154 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15155 } else {
15156 if (bgp->distance_local[afi][safi])
15157 return bgp->distance_local[afi][safi];
15158 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15159 }
718e3744 15160}
15161
a612fb77
DA
15162/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15163 * we should tell ZEBRA update the routes for a specific
15164 * AFI/SAFI to reflect changes in RIB.
15165 */
585f1adc
IR
15166static void bgp_announce_routes_distance_update(struct bgp *bgp,
15167 afi_t update_afi,
15168 safi_t update_safi)
a612fb77
DA
15169{
15170 afi_t afi;
15171 safi_t safi;
15172
15173 FOREACH_AFI_SAFI (afi, safi) {
15174 if (!bgp_fibupd_safi(safi))
15175 continue;
15176
8b54bc30
DA
15177 if (afi != update_afi && safi != update_safi)
15178 continue;
15179
15180 if (BGP_DEBUG(zebra, ZEBRA))
15181 zlog_debug(
15182 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15183 __func__, afi, safi);
15184 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15185 }
15186}
15187
585f1adc
IR
15188DEFUN (bgp_distance,
15189 bgp_distance_cmd,
15190 "distance bgp (1-255) (1-255) (1-255)",
15191 "Define an administrative distance\n"
15192 "BGP distance\n"
15193 "Distance for routes external to the AS\n"
15194 "Distance for routes internal to the AS\n"
15195 "Distance for local routes\n")
718e3744 15196{
585f1adc 15197 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15198 int idx_number = 2;
15199 int idx_number_2 = 3;
15200 int idx_number_3 = 4;
585f1adc
IR
15201 int distance_ebgp = atoi(argv[idx_number]->arg);
15202 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15203 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15204 afi_t afi;
15205 safi_t safi;
718e3744 15206
d62a17ae 15207 afi = bgp_node_afi(vty);
15208 safi = bgp_node_safi(vty);
718e3744 15209
585f1adc
IR
15210 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15211 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15212 || bgp->distance_local[afi][safi] != distance_local) {
15213 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15214 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15215 bgp->distance_local[afi][safi] = distance_local;
15216 bgp_announce_routes_distance_update(bgp, afi, safi);
15217 }
15218 return CMD_SUCCESS;
15219}
37a87b8f 15220
585f1adc
IR
15221DEFUN (no_bgp_distance,
15222 no_bgp_distance_cmd,
15223 "no distance bgp [(1-255) (1-255) (1-255)]",
15224 NO_STR
15225 "Define an administrative distance\n"
15226 "BGP distance\n"
15227 "Distance for routes external to the AS\n"
15228 "Distance for routes internal to the AS\n"
15229 "Distance for local routes\n")
718e3744 15230{
585f1adc 15231 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15232 afi_t afi;
15233 safi_t safi;
37a87b8f
CS
15234
15235 afi = bgp_node_afi(vty);
15236 safi = bgp_node_safi(vty);
15237
585f1adc
IR
15238 if (bgp->distance_ebgp[afi][safi] != 0
15239 || bgp->distance_ibgp[afi][safi] != 0
15240 || bgp->distance_local[afi][safi] != 0) {
15241 bgp->distance_ebgp[afi][safi] = 0;
15242 bgp->distance_ibgp[afi][safi] = 0;
15243 bgp->distance_local[afi][safi] = 0;
15244 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15245 }
585f1adc
IR
15246 return CMD_SUCCESS;
15247}
37a87b8f 15248
37a87b8f 15249
585f1adc
IR
15250DEFUN (bgp_distance_source,
15251 bgp_distance_source_cmd,
15252 "distance (1-255) A.B.C.D/M",
15253 "Define an administrative distance\n"
15254 "Administrative distance\n"
15255 "IP source prefix\n")
15256{
15257 int idx_number = 1;
15258 int idx_ipv4_prefixlen = 2;
15259 bgp_distance_set(vty, argv[idx_number]->arg,
15260 argv[idx_ipv4_prefixlen]->arg, NULL);
15261 return CMD_SUCCESS;
734b349e
MZ
15262}
15263
585f1adc
IR
15264DEFUN (no_bgp_distance_source,
15265 no_bgp_distance_source_cmd,
15266 "no distance (1-255) A.B.C.D/M",
15267 NO_STR
15268 "Define an administrative distance\n"
15269 "Administrative distance\n"
15270 "IP source prefix\n")
37a87b8f 15271{
585f1adc
IR
15272 int idx_number = 2;
15273 int idx_ipv4_prefixlen = 3;
15274 bgp_distance_unset(vty, argv[idx_number]->arg,
15275 argv[idx_ipv4_prefixlen]->arg, NULL);
15276 return CMD_SUCCESS;
37a87b8f
CS
15277}
15278
585f1adc
IR
15279DEFUN (bgp_distance_source_access_list,
15280 bgp_distance_source_access_list_cmd,
15281 "distance (1-255) A.B.C.D/M WORD",
15282 "Define an administrative distance\n"
15283 "Administrative distance\n"
15284 "IP source prefix\n"
15285 "Access list name\n")
37a87b8f 15286{
585f1adc
IR
15287 int idx_number = 1;
15288 int idx_ipv4_prefixlen = 2;
15289 int idx_word = 3;
15290 bgp_distance_set(vty, argv[idx_number]->arg,
15291 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15292 return CMD_SUCCESS;
15293}
718e3744 15294
585f1adc
IR
15295DEFUN (no_bgp_distance_source_access_list,
15296 no_bgp_distance_source_access_list_cmd,
15297 "no distance (1-255) A.B.C.D/M WORD",
15298 NO_STR
15299 "Define an administrative distance\n"
15300 "Administrative distance\n"
15301 "IP source prefix\n"
15302 "Access list name\n")
15303{
15304 int idx_number = 2;
15305 int idx_ipv4_prefixlen = 3;
15306 int idx_word = 4;
15307 bgp_distance_unset(vty, argv[idx_number]->arg,
15308 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15309 return CMD_SUCCESS;
15310}
37a87b8f 15311
585f1adc
IR
15312DEFUN (ipv6_bgp_distance_source,
15313 ipv6_bgp_distance_source_cmd,
15314 "distance (1-255) X:X::X:X/M",
15315 "Define an administrative distance\n"
15316 "Administrative distance\n"
15317 "IP source prefix\n")
15318{
15319 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15320 return CMD_SUCCESS;
15321}
7ebe9748 15322
585f1adc
IR
15323DEFUN (no_ipv6_bgp_distance_source,
15324 no_ipv6_bgp_distance_source_cmd,
15325 "no distance (1-255) X:X::X:X/M",
15326 NO_STR
15327 "Define an administrative distance\n"
15328 "Administrative distance\n"
15329 "IP source prefix\n")
15330{
15331 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15332 return CMD_SUCCESS;
15333}
37a87b8f 15334
585f1adc
IR
15335DEFUN (ipv6_bgp_distance_source_access_list,
15336 ipv6_bgp_distance_source_access_list_cmd,
15337 "distance (1-255) X:X::X:X/M WORD",
15338 "Define an administrative distance\n"
15339 "Administrative distance\n"
15340 "IP source prefix\n"
15341 "Access list name\n")
15342{
15343 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15344 return CMD_SUCCESS;
718e3744 15345}
15346
585f1adc
IR
15347DEFUN (no_ipv6_bgp_distance_source_access_list,
15348 no_ipv6_bgp_distance_source_access_list_cmd,
15349 "no distance (1-255) X:X::X:X/M WORD",
15350 NO_STR
15351 "Define an administrative distance\n"
15352 "Administrative distance\n"
15353 "IP source prefix\n"
15354 "Access list name\n")
718e3744 15355{
585f1adc
IR
15356 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15357 return CMD_SUCCESS;
15358}
37a87b8f 15359
585f1adc
IR
15360DEFUN (bgp_damp_set,
15361 bgp_damp_set_cmd,
a30fec23 15362 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15363 "BGP Specific commands\n"
15364 "Enable route-flap dampening\n"
15365 "Half-life time for the penalty\n"
15366 "Value to start reusing a route\n"
15367 "Value to start suppressing a route\n"
15368 "Maximum duration to suppress a stable route\n")
15369{
15370 VTY_DECLVAR_CONTEXT(bgp, bgp);
15371 int idx_half_life = 2;
15372 int idx_reuse = 3;
15373 int idx_suppress = 4;
15374 int idx_max_suppress = 5;
37a87b8f
CS
15375 int half = DEFAULT_HALF_LIFE * 60;
15376 int reuse = DEFAULT_REUSE;
15377 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15378 int max = 4 * half;
15379
15380 if (argc == 6) {
15381 half = atoi(argv[idx_half_life]->arg) * 60;
15382 reuse = atoi(argv[idx_reuse]->arg);
15383 suppress = atoi(argv[idx_suppress]->arg);
15384 max = atoi(argv[idx_max_suppress]->arg) * 60;
15385 } else if (argc == 3) {
15386 half = atoi(argv[idx_half_life]->arg) * 60;
15387 max = 4 * half;
15388 }
15389
15390 /*
15391 * These can't be 0 but our SA doesn't understand the
15392 * way our cli is constructed
15393 */
15394 assert(reuse);
15395 assert(half);
15396 if (suppress < reuse) {
15397 vty_out(vty,
15398 "Suppress value cannot be less than reuse value \n");
15399 return 0;
15400 }
15401
15402 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15403 reuse, suppress, max);
15404}
15405
15406DEFUN (bgp_damp_unset,
15407 bgp_damp_unset_cmd,
a30fec23 15408 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15409 NO_STR
15410 "BGP Specific commands\n"
15411 "Enable route-flap dampening\n"
15412 "Half-life time for the penalty\n"
15413 "Value to start reusing a route\n"
15414 "Value to start suppressing a route\n"
15415 "Maximum duration to suppress a stable route\n")
15416{
15417 VTY_DECLVAR_CONTEXT(bgp, bgp);
15418 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15419}
15420
718e3744 15421/* Display specified route of BGP table. */
d62a17ae 15422static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15423 const char *ip_str, afi_t afi, safi_t safi,
15424 struct prefix_rd *prd, int prefix_check)
15425{
15426 int ret;
15427 struct prefix match;
9bcb3eef
DS
15428 struct bgp_dest *dest;
15429 struct bgp_dest *rm;
40381db7
DS
15430 struct bgp_path_info *pi;
15431 struct bgp_path_info *pi_temp;
d62a17ae 15432 struct bgp *bgp;
15433 struct bgp_table *table;
15434
15435 /* BGP structure lookup. */
15436 if (view_name) {
15437 bgp = bgp_lookup_by_name(view_name);
15438 if (bgp == NULL) {
15439 vty_out(vty, "%% Can't find BGP instance %s\n",
15440 view_name);
15441 return CMD_WARNING;
15442 }
15443 } else {
15444 bgp = bgp_get_default();
15445 if (bgp == NULL) {
15446 vty_out(vty, "%% No BGP process is configured\n");
15447 return CMD_WARNING;
15448 }
718e3744 15449 }
718e3744 15450
d62a17ae 15451 /* Check IP address argument. */
15452 ret = str2prefix(ip_str, &match);
15453 if (!ret) {
15454 vty_out(vty, "%% address is malformed\n");
15455 return CMD_WARNING;
15456 }
718e3744 15457
d62a17ae 15458 match.family = afi2family(afi);
15459
15460 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15461 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15462 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15463 dest = bgp_route_next(dest)) {
15464 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15465
9bcb3eef 15466 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15467 continue;
9bcb3eef 15468 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15469 if (!table)
ea47320b 15470 continue;
4953391b
DA
15471 rm = bgp_node_match(table, &match);
15472 if (rm == NULL)
ea47320b 15473 continue;
d62a17ae 15474
9bcb3eef 15475 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15476
ea47320b 15477 if (!prefix_check
b54892e0 15478 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15479 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15480 while (pi) {
15481 if (pi->extra && pi->extra->damp_info) {
15482 pi_temp = pi->next;
ea47320b 15483 bgp_damp_info_free(
19971c9a 15484 pi->extra->damp_info,
5c8846f6 15485 1, afi, safi);
40381db7 15486 pi = pi_temp;
ea47320b 15487 } else
40381db7 15488 pi = pi->next;
d62a17ae 15489 }
ea47320b
DL
15490 }
15491
9bcb3eef 15492 bgp_dest_unlock_node(rm);
d62a17ae 15493 }
15494 } else {
4953391b
DA
15495 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15496 if (dest != NULL) {
9bcb3eef 15497 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15498
d62a17ae 15499 if (!prefix_check
9bcb3eef
DS
15500 || dest_p->prefixlen == match.prefixlen) {
15501 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15502 while (pi) {
15503 if (pi->extra && pi->extra->damp_info) {
15504 pi_temp = pi->next;
d62a17ae 15505 bgp_damp_info_free(
19971c9a 15506 pi->extra->damp_info,
5c8846f6 15507 1, afi, safi);
40381db7 15508 pi = pi_temp;
d62a17ae 15509 } else
40381db7 15510 pi = pi->next;
d62a17ae 15511 }
15512 }
15513
9bcb3eef 15514 bgp_dest_unlock_node(dest);
d62a17ae 15515 }
15516 }
718e3744 15517
d62a17ae 15518 return CMD_SUCCESS;
718e3744 15519}
15520
15521DEFUN (clear_ip_bgp_dampening,
15522 clear_ip_bgp_dampening_cmd,
15523 "clear ip bgp dampening",
15524 CLEAR_STR
15525 IP_STR
15526 BGP_STR
15527 "Clear route flap dampening information\n")
15528{
b4f7f45b 15529 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15530 return CMD_SUCCESS;
718e3744 15531}
15532
15533DEFUN (clear_ip_bgp_dampening_prefix,
15534 clear_ip_bgp_dampening_prefix_cmd,
15535 "clear ip bgp dampening A.B.C.D/M",
15536 CLEAR_STR
15537 IP_STR
15538 BGP_STR
15539 "Clear route flap dampening information\n"
0c7b1b01 15540 "IPv4 prefix\n")
718e3744 15541{
d62a17ae 15542 int idx_ipv4_prefixlen = 4;
15543 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15544 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15545}
15546
15547DEFUN (clear_ip_bgp_dampening_address,
15548 clear_ip_bgp_dampening_address_cmd,
15549 "clear ip bgp dampening A.B.C.D",
15550 CLEAR_STR
15551 IP_STR
15552 BGP_STR
15553 "Clear route flap dampening information\n"
15554 "Network to clear damping information\n")
15555{
d62a17ae 15556 int idx_ipv4 = 4;
15557 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15558 SAFI_UNICAST, NULL, 0);
718e3744 15559}
15560
15561DEFUN (clear_ip_bgp_dampening_address_mask,
15562 clear_ip_bgp_dampening_address_mask_cmd,
15563 "clear ip bgp dampening A.B.C.D A.B.C.D",
15564 CLEAR_STR
15565 IP_STR
15566 BGP_STR
15567 "Clear route flap dampening information\n"
15568 "Network to clear damping information\n"
15569 "Network mask\n")
15570{
d62a17ae 15571 int idx_ipv4 = 4;
15572 int idx_ipv4_2 = 5;
15573 int ret;
15574 char prefix_str[BUFSIZ];
718e3744 15575
d62a17ae 15576 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15577 prefix_str, sizeof(prefix_str));
d62a17ae 15578 if (!ret) {
15579 vty_out(vty, "%% Inconsistent address and mask\n");
15580 return CMD_WARNING;
15581 }
718e3744 15582
d62a17ae 15583 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15584 NULL, 0);
718e3744 15585}
6b0655a2 15586
e3b78da8 15587static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15588{
15589 struct vty *vty = arg;
e3b78da8 15590 struct peer *peer = bucket->data;
825d9834 15591
47e12884 15592 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15593}
15594
2a0e69ae
DS
15595DEFUN (show_bgp_listeners,
15596 show_bgp_listeners_cmd,
15597 "show bgp listeners",
15598 SHOW_STR
15599 BGP_STR
15600 "Display Listen Sockets and who created them\n")
15601{
15602 bgp_dump_listener_info(vty);
15603
15604 return CMD_SUCCESS;
15605}
15606
825d9834
DS
15607DEFUN (show_bgp_peerhash,
15608 show_bgp_peerhash_cmd,
15609 "show bgp peerhash",
15610 SHOW_STR
15611 BGP_STR
15612 "Display information about the BGP peerhash\n")
15613{
15614 struct list *instances = bm->bgp;
15615 struct listnode *node;
15616 struct bgp *bgp;
15617
15618 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15619 vty_out(vty, "BGP: %s\n", bgp->name);
15620 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15621 vty);
15622 }
15623
15624 return CMD_SUCCESS;
15625}
15626
587ff0fd 15627/* also used for encap safi */
2b791107
DL
15628static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15629 afi_t afi, safi_t safi)
d62a17ae 15630{
9bcb3eef
DS
15631 struct bgp_dest *pdest;
15632 struct bgp_dest *dest;
d62a17ae 15633 struct bgp_table *table;
b54892e0 15634 const struct prefix *p;
d62a17ae 15635 struct bgp_static *bgp_static;
15636 mpls_label_t label;
d62a17ae 15637
15638 /* Network configuration. */
9bcb3eef
DS
15639 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15640 pdest = bgp_route_next(pdest)) {
15641 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15642 if (!table)
ea47320b 15643 continue;
d62a17ae 15644
9bcb3eef
DS
15645 for (dest = bgp_table_top(table); dest;
15646 dest = bgp_route_next(dest)) {
15647 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15648 if (bgp_static == NULL)
ea47320b 15649 continue;
d62a17ae 15650
9bcb3eef 15651 p = bgp_dest_get_prefix(dest);
d62a17ae 15652
ea47320b 15653 /* "network" configuration display. */
ea47320b
DL
15654 label = decode_label(&bgp_static->label);
15655
c1aa9e7f
PG
15656 vty_out(vty, " network %pFX rd %s", p,
15657 bgp_static->prd_pretty);
ea47320b
DL
15658 if (safi == SAFI_MPLS_VPN)
15659 vty_out(vty, " label %u", label);
15660
15661 if (bgp_static->rmap.name)
15662 vty_out(vty, " route-map %s",
15663 bgp_static->rmap.name);
e2a86ad9
DS
15664
15665 if (bgp_static->backdoor)
15666 vty_out(vty, " backdoor");
15667
ea47320b
DL
15668 vty_out(vty, "\n");
15669 }
15670 }
d62a17ae 15671}
15672
2b791107
DL
15673static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15674 afi_t afi, safi_t safi)
d62a17ae 15675{
9bcb3eef
DS
15676 struct bgp_dest *pdest;
15677 struct bgp_dest *dest;
d62a17ae 15678 struct bgp_table *table;
b54892e0 15679 const struct prefix *p;
d62a17ae 15680 struct bgp_static *bgp_static;
ff44f570 15681 char buf[PREFIX_STRLEN * 2];
d62a17ae 15682 char buf2[SU_ADDRSTRLEN];
5f933e1e 15683 char esi_buf[ESI_STR_LEN];
d62a17ae 15684
15685 /* Network configuration. */
9bcb3eef
DS
15686 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15687 pdest = bgp_route_next(pdest)) {
15688 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15689 if (!table)
ea47320b 15690 continue;
d62a17ae 15691
9bcb3eef
DS
15692 for (dest = bgp_table_top(table); dest;
15693 dest = bgp_route_next(dest)) {
15694 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15695 if (bgp_static == NULL)
ea47320b 15696 continue;
d62a17ae 15697
ea47320b 15698 char *macrouter = NULL;
d62a17ae 15699
ea47320b
DL
15700 if (bgp_static->router_mac)
15701 macrouter = prefix_mac2str(
15702 bgp_static->router_mac, NULL, 0);
15703 if (bgp_static->eth_s_id)
0a50c248
AK
15704 esi_to_str(bgp_static->eth_s_id,
15705 esi_buf, sizeof(esi_buf));
9bcb3eef 15706 p = bgp_dest_get_prefix(dest);
d62a17ae 15707
ea47320b 15708 /* "network" configuration display. */
197cb530
PG
15709 if (p->u.prefix_evpn.route_type == 5) {
15710 char local_buf[PREFIX_STRLEN];
07380148 15711
3714a385 15712 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15713 struct prefix_evpn *)p)
15714 ? AF_INET
15715 : AF_INET6;
3714a385 15716 inet_ntop(family,
07380148
DA
15717 &p->u.prefix_evpn.prefix_addr.ip.ip
15718 .addr,
15719 local_buf, sizeof(local_buf));
772270f3
QY
15720 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15721 p->u.prefix_evpn.prefix_addr
15722 .ip_prefix_length);
197cb530
PG
15723 } else {
15724 prefix2str(p, buf, sizeof(buf));
15725 }
ea47320b 15726
a4d82a8a
PZ
15727 if (bgp_static->gatewayIp.family == AF_INET
15728 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15729 inet_ntop(bgp_static->gatewayIp.family,
15730 &bgp_static->gatewayIp.u.prefix, buf2,
15731 sizeof(buf2));
ea47320b 15732 vty_out(vty,
c1aa9e7f
PG
15733 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15734 buf, bgp_static->prd_pretty,
15735 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15736 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15737 macrouter);
15738
0a22ddfb 15739 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15740 }
15741 }
3da6fcd5
PG
15742}
15743
718e3744 15744/* Configuration of static route announcement and aggregate
15745 information. */
2b791107
DL
15746void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15747 safi_t safi)
d62a17ae 15748{
9bcb3eef 15749 struct bgp_dest *dest;
b54892e0 15750 const struct prefix *p;
d62a17ae 15751 struct bgp_static *bgp_static;
15752 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15753
2b791107
DL
15754 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15755 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15756 return;
15757 }
d62a17ae 15758
2b791107
DL
15759 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15760 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15761 return;
15762 }
d62a17ae 15763
15764 /* Network configuration. */
9bcb3eef
DS
15765 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15766 dest = bgp_route_next(dest)) {
15767 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15768 if (bgp_static == NULL)
ea47320b 15769 continue;
d62a17ae 15770
9bcb3eef 15771 p = bgp_dest_get_prefix(dest);
d62a17ae 15772
8228a9a7 15773 vty_out(vty, " network %pFX", p);
d62a17ae 15774
ea47320b
DL
15775 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15776 vty_out(vty, " label-index %u",
15777 bgp_static->label_index);
d62a17ae 15778
ea47320b
DL
15779 if (bgp_static->rmap.name)
15780 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15781
15782 if (bgp_static->backdoor)
15783 vty_out(vty, " backdoor");
718e3744 15784
ea47320b
DL
15785 vty_out(vty, "\n");
15786 }
15787
d62a17ae 15788 /* Aggregate-address configuration. */
9bcb3eef
DS
15789 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15790 dest = bgp_route_next(dest)) {
15791 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15792 if (bgp_aggregate == NULL)
ea47320b 15793 continue;
d62a17ae 15794
9bcb3eef 15795 p = bgp_dest_get_prefix(dest);
d62a17ae 15796
8228a9a7 15797 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15798
ea47320b
DL
15799 if (bgp_aggregate->as_set)
15800 vty_out(vty, " as-set");
d62a17ae 15801
ea47320b
DL
15802 if (bgp_aggregate->summary_only)
15803 vty_out(vty, " summary-only");
718e3744 15804
20894f50
DA
15805 if (bgp_aggregate->rmap.name)
15806 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15807
229757f1
DA
15808 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15809 vty_out(vty, " origin %s",
15810 bgp_origin2str(bgp_aggregate->origin));
15811
6aabb15d
RZ
15812 if (bgp_aggregate->match_med)
15813 vty_out(vty, " matching-MED-only");
15814
365ab2e7
RZ
15815 if (bgp_aggregate->suppress_map_name)
15816 vty_out(vty, " suppress-map %s",
15817 bgp_aggregate->suppress_map_name);
15818
ea47320b
DL
15819 vty_out(vty, "\n");
15820 }
d62a17ae 15821}
734b349e 15822
2b791107 15823void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15824 safi_t safi)
d62a17ae 15825{
9bcb3eef 15826 struct bgp_dest *dest;
d62a17ae 15827 struct bgp_distance *bdistance;
15828
15829 /* Distance configuration. */
15830 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15831 && bgp->distance_local[afi][safi]
15832 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15833 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15834 || bgp->distance_local[afi][safi]
15835 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15836 vty_out(vty, " distance bgp %d %d %d\n",
15837 bgp->distance_ebgp[afi][safi],
15838 bgp->distance_ibgp[afi][safi],
15839 bgp->distance_local[afi][safi]);
15840 }
734b349e 15841
9bcb3eef
DS
15842 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15843 dest = bgp_route_next(dest)) {
15844 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15845 if (bdistance != NULL)
56ca3b5b 15846 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15847 bdistance->distance, dest,
d62a17ae 15848 bdistance->access_list ? bdistance->access_list
15849 : "");
ca2e160d 15850 }
718e3744 15851}
15852
15853/* Allocate routing table structure and install commands. */
d62a17ae 15854void bgp_route_init(void)
15855{
15856 afi_t afi;
15857 safi_t safi;
15858
15859 /* Init BGP distance table. */
05c7a1cc 15860 FOREACH_AFI_SAFI (afi, safi)
960035b2 15861 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15862
15863 /* IPv4 BGP commands. */
15864 install_element(BGP_NODE, &bgp_table_map_cmd);
15865 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15866 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15867
554b3b10 15868 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15869
15870 /* IPv4 unicast configuration. */
15871 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15872 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15873 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15874
554b3b10 15875 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15876
15877 /* IPv4 multicast configuration. */
15878 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15879 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15880 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15881 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15882
15883 /* IPv4 labeled-unicast configuration. */
fb985e0c 15884 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15885 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15886
d62a17ae 15887 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15888 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15889 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15890 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15891 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15892 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15893 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15894 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15895
15896 install_element(VIEW_NODE,
15897 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15898 install_element(VIEW_NODE,
15899 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15900 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15901 install_element(VIEW_NODE,
15902 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15903#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15904 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15905#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15906 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15907 install_element(VIEW_NODE,
44c69747 15908 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15909
d62a17ae 15910 /* BGP dampening clear commands */
15911 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15912 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15913
d62a17ae 15914 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15915 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15916
15917 /* prefix count */
15918 install_element(ENABLE_NODE,
15919 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15920#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15921 install_element(ENABLE_NODE,
15922 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15923#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15924
d62a17ae 15925 /* New config IPv6 BGP commands. */
15926 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15927 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15928 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15929
554b3b10 15930 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15931
15932 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15933
fb985e0c
DA
15934 /* IPv6 labeled unicast address family. */
15935 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15936 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15937
d62a17ae 15938 install_element(BGP_NODE, &bgp_distance_cmd);
15939 install_element(BGP_NODE, &no_bgp_distance_cmd);
15940 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15941 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15942 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15943 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15944 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15945 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15946 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15947 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15948 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15949 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15950 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15951 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15952 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15953 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15954 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15955 install_element(BGP_IPV4M_NODE,
15956 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15957 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15958 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15959 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15960 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15961 install_element(BGP_IPV6_NODE,
15962 &ipv6_bgp_distance_source_access_list_cmd);
15963 install_element(BGP_IPV6_NODE,
15964 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15965 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15966 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15967 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15968 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15969 install_element(BGP_IPV6M_NODE,
15970 &ipv6_bgp_distance_source_access_list_cmd);
15971 install_element(BGP_IPV6M_NODE,
15972 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15973
ef5f4b23 15974 /* BGP dampening */
585f1adc
IR
15975 install_element(BGP_NODE, &bgp_damp_set_cmd);
15976 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15977 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15978 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15979 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15980 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15981 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15982 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15983 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15984 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15985 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15986 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15987 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15988 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15989
15990 /* Large Communities */
15991 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15992 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15993
15994 /* show bgp ipv4 flowspec detailed */
15995 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15996
2a0e69ae 15997 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15998 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15999}
16000
16001void bgp_route_finish(void)
16002{
16003 afi_t afi;
16004 safi_t safi;
16005
05c7a1cc
QY
16006 FOREACH_AFI_SAFI (afi, safi) {
16007 bgp_table_unlock(bgp_distance_table[afi][safi]);
16008 bgp_distance_table[afi][safi] = NULL;
16009 }
228da428 16010}