]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd : aggregate-address memory leak fix
[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"
24a58196 23#include "frrevent.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
59d6b4d6
DA
154struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table, safi_t safi,
155 const struct prefix *p,
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)) {
7fd8ca9a
DS
319 if (BGP_DEBUG(update, UPDATE_OUT)) {
320 table = bgp_dest_table(dest);
321 if (table)
322 bgp = table->bgp;
323
36235319 324 zlog_debug(
7fd8ca9a
DS
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest, bgp ? bgp->name_pretty : "(Unknown)");
327 }
b54892e0 328
5f9c1aa2 329 return 0;
330 }
331
9bcb3eef 332 table = bgp_dest_table(dest);
f009ff26 333 if (table) {
334 bgp = table->bgp;
335 afi = table->afi;
336 safi = table->safi;
337 }
338
9bcb3eef 339 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 340 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
341 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
342 continue;
343
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
346 */
36235319
QY
347 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
348 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 349 set_flag = true;
f009ff26 350 } else {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
353 */
354 peer = old_pi->peer;
36235319
QY
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
356 && BGP_PEER_RESTARTING_MODE(peer)
357 && (old_pi
358 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 359 set_flag = true;
f009ff26 360 }
361 }
362 if (set_flag)
363 break;
364 }
365
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
367 * is active
368 */
2ba1fe69 369 if (set_flag && table) {
f009ff26 370 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
371 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
372 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 373 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 374 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest, bgp->name_pretty, dest);
f009ff26 377 return 0;
378 }
379 }
380 return -1;
381}
382
eb473185
DA
383void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
384 struct bgp_path_info *pi)
718e3744 385{
c6b077a5 386 frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
4b7e6066 387 struct bgp_path_info *top;
718e3744 388
9bcb3eef 389 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 390
6f94b685 391 pi->next = top;
40381db7 392 pi->prev = NULL;
d62a17ae 393 if (top)
40381db7 394 top->prev = pi;
9bcb3eef 395 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 396
40381db7 397 bgp_path_info_lock(pi);
9bcb3eef 398 bgp_dest_lock_node(dest);
40381db7 399 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 400 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 401 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 402}
403
d62a17ae 404/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 405 completion callback *only* */
9bcb3eef 406void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 407{
40381db7
DS
408 if (pi->next)
409 pi->next->prev = pi->prev;
410 if (pi->prev)
411 pi->prev->next = pi->next;
d62a17ae 412 else
9bcb3eef 413 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 414
40381db7
DS
415 bgp_path_info_mpath_dequeue(pi);
416 bgp_path_info_unlock(pi);
7fd28dd2 417 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 418 bgp_dest_unlock_node(dest);
718e3744 419}
420
9bcb3eef 421void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 422{
9bcb3eef 423 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 424 /* set of previous already took care of pcount */
40381db7 425 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 426}
427
18ee8310 428/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
9bcb3eef 431void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 432{
9bcb3eef 433 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 434 /* unset of previous already took care of pcount */
40381db7 435 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
436}
437
d62a17ae 438/* Adjust pcount as required */
9bcb3eef 439static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 440{
d62a17ae 441 struct bgp_table *table;
67174041 442
9bcb3eef 443 assert(dest && bgp_dest_table(dest));
40381db7 444 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 445
9bcb3eef 446 table = bgp_dest_table(dest);
67174041 447
40381db7 448 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 449 return;
450
40381db7
DS
451 if (!BGP_PATH_COUNTABLE(pi)
452 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 453
40381db7 454 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 455
456 /* slight hack, but more robust against errors. */
40381db7
DS
457 if (pi->peer->pcount[table->afi][table->safi])
458 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 459 else
450971aa 460 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 461 "Asked to decrement 0 prefix count for peer");
40381db7
DS
462 } else if (BGP_PATH_COUNTABLE(pi)
463 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
464 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
465 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 466 }
1a392d46
PJ
467}
468
40381db7
DS
469static int bgp_label_index_differs(struct bgp_path_info *pi1,
470 struct bgp_path_info *pi2)
28d58fd7 471{
40381db7 472 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 473}
1a392d46 474
18ee8310 475/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
476 * This is here primarily to keep prefix-count in check.
477 */
9bcb3eef 478void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 479 uint32_t flag)
1a392d46 480{
40381db7 481 SET_FLAG(pi->flags, flag);
d62a17ae 482
483 /* early bath if we know it's not a flag that changes countability state
484 */
485 if (!CHECK_FLAG(flag,
1defdda8 486 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 487 return;
488
9bcb3eef 489 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
490}
491
9bcb3eef 492void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 493 uint32_t flag)
1a392d46 494{
40381db7 495 UNSET_FLAG(pi->flags, flag);
d62a17ae 496
497 /* early bath if we know it's not a flag that changes countability state
498 */
499 if (!CHECK_FLAG(flag,
1defdda8 500 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 501 return;
502
9bcb3eef 503 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
504}
505
718e3744 506/* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 508static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 509{
510 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
511 return attr->med;
512 else {
892fedb6 513 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 514 return BGP_MED_MAX;
515 else
516 return 0;
517 }
718e3744 518}
519
7533cad7
QY
520void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
521 size_t buf_len)
2ec1e66f 522{
b1ff5529
PG
523 struct peer *peer;
524
525 if (pi->sub_type == BGP_ROUTE_IMPORTED &&
526 bgp_get_imported_bpi_ultimate(pi))
527 peer = bgp_get_imported_bpi_ultimate(pi)->peer;
528 else
529 peer = pi->peer;
530
40381db7 531 if (pi->addpath_rx_id)
b1ff5529
PG
532 snprintf(buf, buf_len, "path %s (addpath rxid %d)", peer->host,
533 pi->addpath_rx_id);
d62a17ae 534 else
b1ff5529 535 snprintf(buf, buf_len, "path %s", peer->host);
d62a17ae 536}
9fbdd100 537
da0c0ef7
KM
538
539/*
540 * Get the ultimate path info.
541 */
542struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
543{
544 struct bgp_path_info *bpi_ultimate;
545
546 if (info->sub_type != BGP_ROUTE_IMPORTED)
547 return info;
548
549 for (bpi_ultimate = info;
550 bpi_ultimate->extra && bpi_ultimate->extra->parent;
551 bpi_ultimate = bpi_ultimate->extra->parent)
552 ;
553
554 return bpi_ultimate;
555}
556
d62a17ae 557/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
558 */
18ee8310
DS
559static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
560 struct bgp_path_info *exist, int *paths_eq,
561 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
562 char *pfx_buf, afi_t afi, safi_t safi,
563 enum bgp_path_selection_reason *reason)
d62a17ae 564{
5df26422 565 const struct prefix *new_p;
d62a17ae 566 struct attr *newattr, *existattr;
3061acc2
DA
567 enum bgp_peer_sort new_sort;
568 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
569 uint32_t new_pref;
570 uint32_t exist_pref;
571 uint32_t new_med;
572 uint32_t exist_med;
573 uint32_t new_weight;
574 uint32_t exist_weight;
d62a17ae 575 uint32_t newm, existm;
576 struct in_addr new_id;
577 struct in_addr exist_id;
578 int new_cluster;
579 int exist_cluster;
580 int internal_as_route;
581 int confed_as_route;
04d14c8b 582 int ret = 0;
ee88563a
JM
583 int igp_metric_ret = 0;
584 int peer_sort_ret = -1;
d62a17ae 585 char new_buf[PATH_ADDPATH_STR_BUFFER];
586 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
587 uint32_t new_mm_seq;
588 uint32_t exist_mm_seq;
6d8c603a 589 int nh_cmp;
d071f237
AK
590 esi_t *exist_esi;
591 esi_t *new_esi;
592 bool same_esi;
593 bool old_proxy;
594 bool new_proxy;
33c6e933 595 bool new_origin, exist_origin;
da0c0ef7 596 struct bgp_path_info *bpi_ultimate;
cefda028 597 struct peer *peer_new, *peer_exist;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
46dbf9d0
DA
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
882 */
883 if (safi == SAFI_MPLS_VPN &&
884 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
885 CHECK_FLAG(exist->peer->af_flags[afi][safi],
886 PEER_FLAG_ACCEPT_OWN))) {
887 bool new_accept_own = false;
888 bool exist_accept_own = false;
889 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
890
891 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
892 new_accept_own = community_include(
893 bgp_attr_get_community(newattr), accept_own);
894 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
895 exist_accept_own = community_include(
896 bgp_attr_get_community(existattr), accept_own);
897
898 if (new_accept_own && !exist_accept_own) {
899 *reason = bgp_path_selection_accept_own;
900 if (debug)
901 zlog_debug(
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf, new_buf, exist_buf);
904 return 1;
905 }
906
907 if (!new_accept_own && exist_accept_own) {
908 *reason = bgp_path_selection_accept_own;
909 if (debug)
910 zlog_debug(
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf, new_buf, exist_buf);
913 return 0;
914 }
915 }
916
97a52c82
DA
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
919 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
920 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
921 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
922 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
923
924 if (new_aigp < exist_aigp) {
925 *reason = bgp_path_selection_aigp;
926 if (debug)
927 zlog_debug(
928 "%s: %s wins over %s due to AIGP %" PRIu64
929 " < %" PRIu64,
930 pfx_buf, new_buf, exist_buf, new_aigp,
931 exist_aigp);
932 return 1;
933 }
934
935 if (new_aigp > exist_aigp) {
936 *reason = bgp_path_selection_aigp;
937 if (debug)
938 zlog_debug(
939 "%s: %s loses to %s due to AIGP %" PRIu64
940 " > %" PRIu64,
941 pfx_buf, new_buf, exist_buf, new_aigp,
942 exist_aigp);
943 return 0;
944 }
945 }
946
d62a17ae 947 /* 3. Local route check. We prefer:
948 * - BGP_ROUTE_STATIC
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
951 */
33c6e933
DS
952 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
953 new->sub_type == BGP_ROUTE_IMPORTED);
954 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
955 exist->sub_type == BGP_ROUTE_IMPORTED);
956
957 if (new_origin && !exist_origin) {
fdf81fa0 958 *reason = bgp_path_selection_local_route;
d62a17ae 959 if (debug)
960 zlog_debug(
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf, new_buf, exist_buf);
963 return 1;
964 }
718e3744 965
33c6e933 966 if (!new_origin && exist_origin) {
fdf81fa0 967 *reason = bgp_path_selection_local_route;
d62a17ae 968 if (debug)
969 zlog_debug(
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf, new_buf, exist_buf);
972 return 0;
6811845b 973 }
718e3744 974
da0c0ef7
KM
975 /* Here if these are imported routes then get ultimate pi for
976 * path compare.
977 */
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist = bgp_get_imported_bpi_ultimate(exist);
980 newattr = new->attr;
981 existattr = exist->attr;
982
d62a17ae 983 /* 4. AS path length check. */
892fedb6 984 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 985 int exist_hops = aspath_count_hops(existattr->aspath);
986 int exist_confeds = aspath_count_confeds(existattr->aspath);
987
892fedb6 988 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 989 int aspath_hops;
990
991 aspath_hops = aspath_count_hops(newattr->aspath);
992 aspath_hops += aspath_count_confeds(newattr->aspath);
993
994 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 995 *reason = bgp_path_selection_confed_as_path;
d62a17ae 996 if (debug)
997 zlog_debug(
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf, new_buf, exist_buf,
1000 aspath_hops,
1001 (exist_hops + exist_confeds));
1002 return 1;
1003 }
1004
1005 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1006 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1007 if (debug)
1008 zlog_debug(
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf, new_buf, exist_buf,
1011 aspath_hops,
1012 (exist_hops + exist_confeds));
1013 return 0;
1014 }
1015 } else {
1016 int newhops = aspath_count_hops(newattr->aspath);
1017
1018 if (newhops < exist_hops) {
fdf81fa0 1019 *reason = bgp_path_selection_as_path;
d62a17ae 1020 if (debug)
1021 zlog_debug(
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf, new_buf, exist_buf,
1024 newhops, exist_hops);
1025 return 1;
1026 }
1027
1028 if (newhops > exist_hops) {
fdf81fa0 1029 *reason = bgp_path_selection_as_path;
d62a17ae 1030 if (debug)
1031 zlog_debug(
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf, new_buf, exist_buf,
1034 newhops, exist_hops);
1035 return 0;
1036 }
1037 }
1038 }
9fbdd100 1039
d62a17ae 1040 /* 5. Origin check. */
1041 if (newattr->origin < existattr->origin) {
fdf81fa0 1042 *reason = bgp_path_selection_origin;
d62a17ae 1043 if (debug)
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf, new_buf, exist_buf,
1046 bgp_origin_long_str[newattr->origin],
1047 bgp_origin_long_str[existattr->origin]);
1048 return 1;
1049 }
718e3744 1050
d62a17ae 1051 if (newattr->origin > existattr->origin) {
fdf81fa0 1052 *reason = bgp_path_selection_origin;
d62a17ae 1053 if (debug)
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf, new_buf, exist_buf,
1056 bgp_origin_long_str[newattr->origin],
1057 bgp_origin_long_str[existattr->origin]);
1058 return 0;
1059 }
718e3744 1060
d62a17ae 1061 /* 6. MED check. */
1062 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1063 && aspath_count_hops(existattr->aspath) == 0);
1064 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1065 && aspath_count_confeds(existattr->aspath) > 0
1066 && aspath_count_hops(newattr->aspath) == 0
1067 && aspath_count_hops(existattr->aspath) == 0);
1068
892fedb6
DA
1069 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1070 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1071 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1072 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1073 || internal_as_route) {
1074 new_med = bgp_med_value(new->attr, bgp);
1075 exist_med = bgp_med_value(exist->attr, bgp);
1076
1077 if (new_med < exist_med) {
fdf81fa0 1078 *reason = bgp_path_selection_med;
d62a17ae 1079 if (debug)
1080 zlog_debug(
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf, new_buf, exist_buf, new_med,
1083 exist_med);
1084 return 1;
1085 }
8ff56318 1086
d62a17ae 1087 if (new_med > exist_med) {
fdf81fa0 1088 *reason = bgp_path_selection_med;
d62a17ae 1089 if (debug)
1090 zlog_debug(
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf, new_buf, exist_buf, new_med,
1093 exist_med);
1094 return 0;
1095 }
1096 }
9fbdd100 1097
8cd3d070
PG
1098 if (exist->sub_type == BGP_ROUTE_IMPORTED) {
1099 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
1100 peer_exist = bpi_ultimate->peer;
1101 } else
1102 peer_exist = exist->peer;
1103
1104 if (new->sub_type == BGP_ROUTE_IMPORTED) {
1105 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
1106 peer_new = bpi_ultimate->peer;
1107 } else
1108 peer_new = new->peer;
1109
d62a17ae 1110 /* 7. Peer type check. */
8cd3d070
PG
1111 new_sort = peer_new->sort;
1112 exist_sort = peer_exist->sort;
d62a17ae 1113
1114 if (new_sort == BGP_PEER_EBGP
1115 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1116 *reason = bgp_path_selection_peer;
d62a17ae 1117 if (debug)
1118 zlog_debug(
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1121 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1122 return 1;
1123 peer_sort_ret = 1;
d62a17ae 1124 }
718e3744 1125
d62a17ae 1126 if (exist_sort == BGP_PEER_EBGP
1127 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1128 *reason = bgp_path_selection_peer;
d62a17ae 1129 if (debug)
1130 zlog_debug(
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1133 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1134 return 0;
1135 peer_sort_ret = 0;
d62a17ae 1136 }
8ff56318 1137
d62a17ae 1138 /* 8. IGP metric check. */
1139 newm = existm = 0;
8ff56318 1140
d62a17ae 1141 if (new->extra)
1142 newm = new->extra->igpmetric;
1143 if (exist->extra)
1144 existm = exist->extra->igpmetric;
9fbdd100 1145
d62a17ae 1146 if (newm < existm) {
ee88563a 1147 if (debug && peer_sort_ret < 0)
d62a17ae 1148 zlog_debug(
d588b995 1149 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1150 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1151 igp_metric_ret = 1;
d62a17ae 1152 }
718e3744 1153
d62a17ae 1154 if (newm > existm) {
ee88563a 1155 if (debug && peer_sort_ret < 0)
d62a17ae 1156 zlog_debug(
d588b995 1157 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1158 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1159 igp_metric_ret = 0;
5e242b0d 1160 }
5e242b0d 1161
d62a17ae 1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm == existm) {
8cd3d070
PG
1167 if (peer_sort_lookup(peer_new) == BGP_PEER_IBGP &&
1168 peer_sort_lookup(peer_exist) == BGP_PEER_IBGP &&
aa53c036 1169 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1170 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1171 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1172
1173 if (newm < existm) {
ee88563a 1174 if (debug && peer_sort_ret < 0)
d62a17ae 1175 zlog_debug(
d588b995 1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1177 pfx_buf, new_buf, exist_buf,
1178 newm, existm);
ee88563a 1179 igp_metric_ret = 1;
d62a17ae 1180 }
1181
1182 if (newm > existm) {
ee88563a 1183 if (debug && peer_sort_ret < 0)
d62a17ae 1184 zlog_debug(
d588b995 1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1186 pfx_buf, new_buf, exist_buf,
1187 newm, existm);
ee88563a 1188 igp_metric_ret = 0;
d62a17ae 1189 }
1190 }
1191 }
31a4638f 1192
d62a17ae 1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1195 if (new_sort == BGP_PEER_CONFED
1196 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1197 *reason = bgp_path_selection_confed;
d62a17ae 1198 if (debug)
1199 zlog_debug(
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1202 if (!CHECK_FLAG(bgp->flags,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1204 return 1;
1205 peer_sort_ret = 1;
d62a17ae 1206 }
718e3744 1207
d62a17ae 1208 if (exist_sort == BGP_PEER_CONFED
1209 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1210 *reason = bgp_path_selection_confed;
d62a17ae 1211 if (debug)
1212 zlog_debug(
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1215 if (!CHECK_FLAG(bgp->flags,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1217 return 0;
1218 peer_sort_ret = 0;
d62a17ae 1219 }
1220 }
718e3744 1221
d62a17ae 1222 /* 11. Maximum path check. */
1223 if (newm == existm) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1226 */
d2d71b04 1227 int newl, existl;
1228
1229 newl = existl = 0;
1230
1231 if (new->extra)
1232 newl = new->extra->num_labels;
1233 if (exist->extra)
1234 existl = exist->extra->num_labels;
1235 if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
1236 (exist->extra &&
1237 bgp_is_valid_label(&exist->extra->label[0]))) ||
1238 (newl != existl)) {
d62a17ae 1239 if (debug)
1240 zlog_debug(
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1243 } else if (CHECK_FLAG(bgp->flags,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1245
1246 /*
1247 * For the two paths, all comparison steps till IGP
1248 * metric
1249 * have succeeded - including AS_PATH hop count. Since
1250 * 'bgp
1251 * bestpath as-path multipath-relax' knob is on, we
1252 * don't need
1253 * an exact match of AS_PATH. Thus, mark the paths are
1254 * equal.
1255 * That will trigger both these paths to get into the
1256 * multipath
1257 * array.
1258 */
1259 *paths_eq = 1;
1260
1261 if (debug)
1262 zlog_debug(
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf, new_buf, exist_buf);
8cd3d070 1265 } else if (peer_new->sort == BGP_PEER_IBGP) {
d62a17ae 1266 if (aspath_cmp(new->attr->aspath,
1267 exist->attr->aspath)) {
1268 *paths_eq = 1;
1269
1270 if (debug)
1271 zlog_debug(
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf, new_buf, exist_buf);
1274 }
8cd3d070 1275 } else if (peer_new->as == peer_exist->as) {
d62a17ae 1276 *paths_eq = 1;
1277
1278 if (debug)
1279 zlog_debug(
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf, new_buf, exist_buf);
1282 }
1283 } else {
1284 /*
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1287 */
ee88563a
JM
1288
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1295 */
1296 ret = peer_sort_ret;
1297 if (peer_sort_ret < 0) {
1298 ret = igp_metric_ret;
1299 if (debug) {
1300 if (ret == 1)
1301 zlog_debug(
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf, new_buf, exist_buf);
1304 else
1305 zlog_debug(
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf, new_buf, exist_buf);
1308 }
1309 *reason = bgp_path_selection_igp_metric;
d62a17ae 1310 }
1311 return ret;
1312 }
718e3744 1313
ee88563a
JM
1314 /*
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1318 */
1319 if (peer_sort_ret >= 0)
1320 return peer_sort_ret;
1321
d62a17ae 1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
892fedb6 1326 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1327 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1328 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1329 *reason = bgp_path_selection_older;
d62a17ae 1330 if (debug)
1331 zlog_debug(
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf, new_buf, exist_buf);
1334 return 1;
1335 }
9fbdd100 1336
1defdda8 1337 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1338 *reason = bgp_path_selection_older;
d62a17ae 1339 if (debug)
1340 zlog_debug(
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf, new_buf, exist_buf);
1343 return 0;
1344 }
1345 }
718e3744 1346
ce5002c6 1347 /* 13. Router-ID comparison. */
d62a17ae 1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
ce5002c6 1350 * used for the comparison, it will decide which path is better.
d62a17ae 1351 */
1352 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1353 new_id.s_addr = newattr->originator_id.s_addr;
1354 else
8cd3d070 1355 new_id.s_addr = peer_new->remote_id.s_addr;
d62a17ae 1356 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1357 exist_id.s_addr = existattr->originator_id.s_addr;
1358 else
8cd3d070 1359 exist_id.s_addr = peer_exist->remote_id.s_addr;
d62a17ae 1360
1361 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1362 *reason = bgp_path_selection_router_id;
d62a17ae 1363 if (debug)
1364 zlog_debug(
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf, new_buf, exist_buf);
1367 return 1;
1368 }
718e3744 1369
d62a17ae 1370 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1371 *reason = bgp_path_selection_router_id;
d62a17ae 1372 if (debug)
1373 zlog_debug(
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf, new_buf, exist_buf);
1376 return 0;
1377 }
9fbdd100 1378
ce5002c6 1379 /* 14. Cluster length comparison. */
d62a17ae 1380 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1381 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1382
1383 if (new_cluster < exist_cluster) {
fdf81fa0 1384 *reason = bgp_path_selection_cluster_length;
d62a17ae 1385 if (debug)
1386 zlog_debug(
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf, new_buf, exist_buf, new_cluster,
1389 exist_cluster);
1390 return 1;
1391 }
718e3744 1392
d62a17ae 1393 if (new_cluster > exist_cluster) {
fdf81fa0 1394 *reason = bgp_path_selection_cluster_length;
d62a17ae 1395 if (debug)
1396 zlog_debug(
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf, new_buf, exist_buf, new_cluster,
1399 exist_cluster);
1400 return 0;
1401 }
9fbdd100 1402
ce5002c6 1403 /* 15. Neighbor address comparison. */
d62a17ae 1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1406 */
1defdda8 1407 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1408 *reason = bgp_path_selection_stale;
d62a17ae 1409 if (debug)
1410 zlog_debug(
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf, new_buf, exist_buf);
1413 return 1;
1414 }
0de5153c 1415
1defdda8 1416 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1417 *reason = bgp_path_selection_stale;
d62a17ae 1418 if (debug)
1419 zlog_debug(
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf, new_buf, exist_buf);
1422 return 0;
1423 }
718e3744 1424
d62a17ae 1425 /* locally configured routes to advertise do not have su_remote */
8cd3d070 1426 if (peer_new->su_remote == NULL) {
fdf81fa0 1427 *reason = bgp_path_selection_local_configured;
d62a17ae 1428 return 0;
8cd3d070 1429 }
cefda028 1430
8cd3d070 1431 if (peer_exist->su_remote == NULL) {
fdf81fa0 1432 *reason = bgp_path_selection_local_configured;
d62a17ae 1433 return 1;
8cd3d070 1434 }
9fbdd100 1435
cefda028 1436 ret = sockunion_cmp(peer_new->su_remote, peer_exist->su_remote);
d62a17ae 1437
1438 if (ret == 1) {
fdf81fa0 1439 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1440 if (debug)
1441 zlog_debug(
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf, new_buf, exist_buf);
1444 return 0;
1445 }
1446
1447 if (ret == -1) {
fdf81fa0 1448 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1449 if (debug)
1450 zlog_debug(
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf, new_buf, exist_buf);
1453 return 1;
1454 }
9fbdd100 1455
fdf81fa0 1456 *reason = bgp_path_selection_default;
d62a17ae 1457 if (debug)
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf, new_buf, exist_buf);
718e3744 1460
d62a17ae 1461 return 1;
718e3744 1462}
1463
d071f237
AK
1464
1465int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1466 struct bgp_path_info *exist, int *paths_eq)
1467{
1468 enum bgp_path_selection_reason reason;
1469 char pfx_buf[PREFIX2STR_BUFFER];
1470
1471 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1472 AFI_L2VPN, SAFI_EVPN, &reason);
1473}
1474
65efcfce
LB
1475/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1477 * multipath is enabled
65efcfce 1478 * This version is compatible with */
18ee8310
DS
1479int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1480 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1481 afi_t afi, safi_t safi,
1482 enum bgp_path_selection_reason *reason)
d62a17ae 1483{
1484 int paths_eq;
1485 int ret;
18ee8310 1486 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1487 afi, safi, reason);
d62a17ae 1488
1489 if (paths_eq)
1490 ret = 0;
1491 else {
1492 if (ret == 1)
1493 ret = -1;
1494 else
1495 ret = 1;
1496 }
1497 return ret;
65efcfce
LB
1498}
1499
5a1ae2c2
DS
1500static enum filter_type bgp_input_filter(struct peer *peer,
1501 const struct prefix *p,
d62a17ae 1502 struct attr *attr, afi_t afi,
1503 safi_t safi)
718e3744 1504{
d62a17ae 1505 struct bgp_filter *filter;
6401252f 1506 enum filter_type ret = FILTER_PERMIT;
718e3744 1507
d62a17ae 1508 filter = &peer->filter[afi][safi];
718e3744 1509
d62a17ae 1510#define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1514
1515 if (DISTRIBUTE_IN_NAME(filter)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1517
6401252f
QY
1518 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1519 == FILTER_DENY) {
1520 ret = FILTER_DENY;
1521 goto done;
1522 }
d62a17ae 1523 }
1524
1525 if (PREFIX_LIST_IN_NAME(filter)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1527
6401252f
QY
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1529 == PREFIX_DENY) {
1530 ret = FILTER_DENY;
1531 goto done;
1532 }
d62a17ae 1533 }
1534
1535 if (FILTER_LIST_IN_NAME(filter)) {
1536 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1537
1538 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1539 == AS_FILTER_DENY) {
1540 ret = FILTER_DENY;
1541 goto done;
1542 }
d62a17ae 1543 }
1544
6401252f 1545done:
c7bb4f00 1546 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1547 char pfxprint[PREFIX2STR_BUFFER];
1548
1549 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1550 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1551 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1552 }
1553
1554 return ret;
650f76c2 1555#undef FILTER_EXIST_WARN
718e3744 1556}
1557
b8685f9b
DS
1558static enum filter_type bgp_output_filter(struct peer *peer,
1559 const struct prefix *p,
d62a17ae 1560 struct attr *attr, afi_t afi,
1561 safi_t safi)
718e3744 1562{
d62a17ae 1563 struct bgp_filter *filter;
6401252f 1564 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1565
1566 filter = &peer->filter[afi][safi];
1567
1568#define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1572
d62a17ae 1573 if (DISTRIBUTE_OUT_NAME(filter)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1575
6401252f
QY
1576 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1577 == FILTER_DENY) {
1578 ret = FILTER_DENY;
1579 goto done;
1580 }
d62a17ae 1581 }
1582
1583 if (PREFIX_LIST_OUT_NAME(filter)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1585
d62a17ae 1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1587 == PREFIX_DENY) {
1588 ret = FILTER_DENY;
1589 goto done;
1590 }
d62a17ae 1591 }
718e3744 1592
d62a17ae 1593 if (FILTER_LIST_OUT_NAME(filter)) {
1594 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1595
d62a17ae 1596 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1597 == AS_FILTER_DENY) {
1598 ret = FILTER_DENY;
1599 goto done;
1600 }
1601 }
1602
c7bb4f00 1603 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1604 char pfxprint[PREFIX2STR_BUFFER];
1605
1606 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1607 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1608 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1609 }
718e3744 1610
6401252f
QY
1611done:
1612 return ret;
650f76c2 1613#undef FILTER_EXIST_WARN
718e3744 1614}
1615
1616/* If community attribute includes no_export then return 1. */
3dc339cd 1617static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1618{
9a706b42 1619 if (bgp_attr_get_community(attr)) {
d62a17ae 1620 /* NO_ADVERTISE check. */
9a706b42
DA
1621 if (community_include(bgp_attr_get_community(attr),
1622 COMMUNITY_NO_ADVERTISE))
3dc339cd 1623 return true;
d62a17ae 1624
1625 /* NO_EXPORT check. */
9a706b42
DA
1626 if (peer->sort == BGP_PEER_EBGP &&
1627 community_include(bgp_attr_get_community(attr),
1628 COMMUNITY_NO_EXPORT))
3dc339cd 1629 return true;
d62a17ae 1630
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer->sort == BGP_PEER_EBGP
1633 || peer->sort == BGP_PEER_CONFED)
9a706b42 1634 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1635 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1636 return true;
d62a17ae 1637 }
3dc339cd 1638 return false;
718e3744 1639}
1640
1641/* Route reflection loop check. */
3dc339cd 1642static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1643{
d62a17ae 1644 struct in_addr cluster_id;
779fee93 1645 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1646
779fee93 1647 if (cluster) {
d62a17ae 1648 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1649 cluster_id = peer->bgp->cluster_id;
1650 else
1651 cluster_id = peer->bgp->router_id;
1652
779fee93 1653 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1654 return true;
d62a17ae 1655 }
3dc339cd 1656 return false;
718e3744 1657}
6b0655a2 1658
d864dd9e
EB
1659static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1660{
1661 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1662 if (peer->local_role == ROLE_PROVIDER ||
1663 peer->local_role == ROLE_RS_SERVER)
1664 return true;
1665 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1666 return true;
1667 return false;
1668 }
1669 if (peer->local_role == ROLE_CUSTOMER ||
1670 peer->local_role == ROLE_PEER ||
1671 peer->local_role == ROLE_RS_CLIENT) {
1672 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1673 attr->otc = peer->as;
1674 }
1675 return false;
1676}
1677
1678static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1679{
1680 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1681 if (peer->local_role == ROLE_CUSTOMER ||
1682 peer->local_role == ROLE_RS_CLIENT ||
1683 peer->local_role == ROLE_PEER)
1684 return true;
1685 return false;
1686 }
1687 if (peer->local_role == ROLE_PROVIDER ||
1688 peer->local_role == ROLE_PEER ||
1689 peer->local_role == ROLE_RS_SERVER) {
1690 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1691 attr->otc = peer->bgp->as;
1692 }
1693 return false;
1694}
1695
5a78f2bc
EB
1696static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1697{
1698 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1699}
1700
5a1ae2c2 1701static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1702 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1703 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1704 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1705{
d62a17ae 1706 struct bgp_filter *filter;
82b692c0
LK
1707 struct bgp_path_info rmap_path = { 0 };
1708 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1709 route_map_result_t ret;
1710 struct route_map *rmap = NULL;
718e3744 1711
d62a17ae 1712 filter = &peer->filter[afi][safi];
718e3744 1713
d62a17ae 1714 /* Apply default weight value. */
1715 if (peer->weight[afi][safi])
1716 attr->weight = peer->weight[afi][safi];
718e3744 1717
d62a17ae 1718 if (rmap_name) {
1719 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1720
d62a17ae 1721 if (rmap == NULL)
1722 return RMAP_DENY;
1723 } else {
1724 if (ROUTE_MAP_IN_NAME(filter)) {
1725 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1726
d62a17ae 1727 if (rmap == NULL)
1728 return RMAP_DENY;
1729 }
1730 }
0b16f239 1731
d62a17ae 1732 /* Route map apply. */
1733 if (rmap) {
6006b807 1734 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1735 /* Duplicate current value to new structure for modification. */
40381db7
DS
1736 rmap_path.peer = peer;
1737 rmap_path.attr = attr;
82b692c0 1738 rmap_path.extra = &extra;
9bcb3eef 1739 rmap_path.net = dest;
196c6b09 1740
82b692c0
LK
1741 extra.num_labels = num_labels;
1742 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1743 memcpy(extra.label, label,
1744 num_labels * sizeof(mpls_label_t));
718e3744 1745
d62a17ae 1746 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1747
d62a17ae 1748 /* Apply BGP route map to the attribute. */
1782514f 1749 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1750
d62a17ae 1751 peer->rmap_type = 0;
0b16f239 1752
1f2263be 1753 if (ret == RMAP_DENYMATCH)
d62a17ae 1754 return RMAP_DENY;
0b16f239 1755 }
d62a17ae 1756 return RMAP_PERMIT;
0b16f239
DS
1757}
1758
5f040085 1759static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1760 struct attr *attr, afi_t afi, safi_t safi,
1761 const char *rmap_name)
0b16f239 1762{
40381db7 1763 struct bgp_path_info rmap_path;
d62a17ae 1764 route_map_result_t ret;
1765 struct route_map *rmap = NULL;
d7c0a89a 1766 uint8_t rmap_type;
0b16f239 1767
b787157a
DS
1768 /*
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1771 * exists.
1772 */
1773 if (!rmap_name)
1774 return RMAP_PERMIT;
0b16f239 1775
d62a17ae 1776 /* Apply default weight value. */
1777 if (peer->weight[afi][safi])
1778 attr->weight = peer->weight[afi][safi];
0b16f239 1779
b787157a 1780 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1781
b787157a
DS
1782 /*
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1785 * deny.
1786 */
1787 if (rmap == NULL)
1788 return RMAP_DENY;
0b16f239 1789
6006b807 1790 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1791 /* Route map apply. */
544be979 1792 /* Duplicate current value to new structure for modification. */
40381db7
DS
1793 rmap_path.peer = peer;
1794 rmap_path.attr = attr;
0b16f239 1795
0f672529 1796 rmap_type = peer->rmap_type;
b787157a 1797 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1798
b787157a 1799 /* Apply BGP route map to the attribute. */
1782514f 1800 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1801
0f672529 1802 peer->rmap_type = rmap_type;
b787157a
DS
1803
1804 if (ret == RMAP_DENYMATCH)
1805 /*
1806 * caller has multiple error paths with bgp_attr_flush()
1807 */
1808 return RMAP_DENY;
ac41b2a2 1809
d62a17ae 1810 return RMAP_PERMIT;
718e3744 1811}
6b0655a2 1812
5000f21c 1813/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1814static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1815 struct peer *peer, struct attr *attr)
1816{
1817 if (peer->sort == BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer, afi, safi,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1820 || peer_af_flag_check(peer, afi, safi,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1822 || peer_af_flag_check(peer, afi, safi,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1824 || peer_af_flag_check(peer, afi, safi,
1825 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer, afi, safi,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1829 || peer_af_flag_check(peer, afi, safi,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1831 if (peer_af_flag_check(
1832 peer, afi, safi,
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1834 attr->aspath = aspath_replace_private_asns(
bf26b80e 1835 attr->aspath, bgp->as, peer->as);
d62a17ae 1836
179d5a0e
TA
1837 /*
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1841 */
d62a17ae 1842 else
1843 attr->aspath = aspath_remove_private_asns(
bf26b80e 1844 attr->aspath, peer->as);
d62a17ae 1845 }
1846
1847 // 'all' was not specified so the entire aspath must be private
1848 // ASNs
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr->aspath)) {
1851 if (peer_af_flag_check(
1852 peer, afi, safi,
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1854 attr->aspath = aspath_replace_private_asns(
bf26b80e 1855 attr->aspath, bgp->as, peer->as);
d62a17ae 1856 else
179d5a0e
TA
1857 /*
1858 * Walk the aspath to retain any instances of
1859 * the peer_asn
1860 */
1861 attr->aspath = aspath_remove_private_asns(
1862 attr->aspath, peer->as);
d62a17ae 1863 }
1864 }
5000f21c
DS
1865}
1866
c7122e14 1867/* If this is an EBGP peer with as-override */
d62a17ae 1868static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1869 struct peer *peer, struct attr *attr)
1870{
bbe7bc46
DA
1871 struct aspath *aspath;
1872
9bbdb457 1873 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1874 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1875 if (attr->aspath->refcnt)
1876 aspath = aspath_dup(attr->aspath);
1877 else
1878 aspath = attr->aspath;
1879
1880 attr->aspath = aspath_intern(
1881 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1882
1883 aspath_free(aspath);
1884 }
d62a17ae 1885}
1886
1479ed2f
DA
1887void bgp_attr_add_llgr_community(struct attr *attr)
1888{
1889 struct community *old;
1890 struct community *new;
1891 struct community *merge;
1892 struct community *llgr;
1893
9a706b42 1894 old = bgp_attr_get_community(attr);
1479ed2f
DA
1895 llgr = community_str2com("llgr-stale");
1896
1897 assert(llgr);
1898
1899 if (old) {
1900 merge = community_merge(community_dup(old), llgr);
1901
1902 if (old->refcnt == 0)
1903 community_free(&old);
1904
1905 new = community_uniq_sort(merge);
1906 community_free(&merge);
1907 } else {
1908 new = community_dup(llgr);
1909 }
1910
1911 community_free(&llgr);
1912
9a706b42 1913 bgp_attr_set_community(attr, new);
1479ed2f
DA
1914}
1915
7f323236
DW
1916void bgp_attr_add_gshut_community(struct attr *attr)
1917{
1918 struct community *old;
1919 struct community *new;
1920 struct community *merge;
1921 struct community *gshut;
1922
9a706b42 1923 old = bgp_attr_get_community(attr);
7f323236
DW
1924 gshut = community_str2com("graceful-shutdown");
1925
990f4f91 1926 assert(gshut);
1927
7f323236
DW
1928 if (old) {
1929 merge = community_merge(community_dup(old), gshut);
1930
a4d82a8a 1931 if (old->refcnt == 0)
3c1f53de 1932 community_free(&old);
7f323236
DW
1933
1934 new = community_uniq_sort(merge);
3c1f53de 1935 community_free(&merge);
7f323236
DW
1936 } else {
1937 new = community_dup(gshut);
1938 }
1939
3c1f53de 1940 community_free(&gshut);
9a706b42 1941 bgp_attr_set_community(attr, new);
7f323236
DW
1942
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1946 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1947}
1948
1949
e73c112e
MK
1950/* Notify BGP Conditional advertisement scanner process. */
1951void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1952{
e73c112e 1953 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1954 afi_t afi = SUBGRP_AFI(subgrp);
1955 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1956 struct bgp_filter *filter = &peer->filter[afi][safi];
1957
1958 if (!ADVERTISE_MAP_NAME(filter))
1959 return;
1960
52979c3b
DS
1961 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1962 return;
e73c112e 1963
52979c3b 1964 peer->advmap_table_change = true;
e73c112e
MK
1965}
1966
1967
f2ee6d5c 1968void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1969{
960035b2 1970 if (family == AF_INET) {
975a328e
DA
1971 attr->nexthop.s_addr = INADDR_ANY;
1972 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1973 }
d62a17ae 1974 if (family == AF_INET6)
1975 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1976 if (family == AF_EVPN)
1977 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1978}
1979
9bcb3eef 1980bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1981 struct update_subgroup *subgrp,
7f7940e6 1982 const struct prefix *p, struct attr *attr,
51c3a7de 1983 struct attr *post_attr)
d62a17ae 1984{
1985 struct bgp_filter *filter;
1986 struct peer *from;
1987 struct peer *peer;
1988 struct peer *onlypeer;
1989 struct bgp *bgp;
40381db7 1990 struct attr *piattr;
b68885f9 1991 route_map_result_t ret;
d62a17ae 1992 int transparent;
1993 int reflect;
1994 afi_t afi;
1995 safi_t safi;
1996 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1997 bool nh_reset = false;
1998 uint64_t cum_bw;
d62a17ae 1999
2000 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 2001 return false;
d62a17ae 2002
2003 afi = SUBGRP_AFI(subgrp);
2004 safi = SUBGRP_SAFI(subgrp);
2005 peer = SUBGRP_PEER(subgrp);
2006 onlypeer = NULL;
2007 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2008 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2009
40381db7 2010 from = pi->peer;
d62a17ae 2011 filter = &peer->filter[afi][safi];
2012 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2013 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2014 : pi->attr;
3f9c7369 2015
d0bf49ec
LS
2016 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2017 peer->pmax_out[afi][safi] != 0 &&
2018 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2019 if (BGP_DEBUG(update, UPDATE_OUT) ||
2020 BGP_DEBUG(update, UPDATE_PREFIX)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer->host, peer->pmax_out[afi][safi]);
2023 }
2024 return false;
2025 }
2026
49e5a4a0 2027#ifdef ENABLE_BGP_VNC
d62a17ae 2028 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2029 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2030 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2031
2032 /*
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2035 * systems
2036 */
8228a9a7
DS
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2038 __func__, p);
d62a17ae 2039 samepeer_safe = 1;
2040 }
65efcfce
LB
2041#endif
2042
ddb5b488
PZ
2043 if (((afi == AFI_IP) || (afi == AFI_IP6))
2044 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2045 && (pi->type == ZEBRA_ROUTE_BGP)
2046 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2047
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2049
2050 samepeer_safe = 1;
2051 }
2052
d62a17ae 2053 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2054 * pi is valid */
2055 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2056 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2057 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2058 return false;
d62a17ae 2059 }
adbac85e 2060
d62a17ae 2061 /* If this is not the bestpath then check to see if there is an enabled
2062 * addpath
2063 * feature that requires us to advertise it */
8ccee4b8
DA
2064 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2065 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2066 return false;
06370dac 2067
d62a17ae 2068 /* Aggregate-address suppress check. */
4056a5f6
RZ
2069 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2070 return false;
3f9c7369 2071
13b7e7f0
DS
2072 /*
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2077 */
40381db7
DS
2078 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2079 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2080 return false;
13b7e7f0 2081
d62a17ae 2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2084 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2085 if (!bgp_is_valid_label(&label)) {
2086 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2087 zlog_debug("u%" PRIu64 ":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
d62a17ae 2089 subgrp->update_group->id, subgrp->id,
8228a9a7 2090 p, &label);
3dc339cd 2091 return false;
d62a17ae 2092 }
2093 }
cd1964ff 2094
d62a17ae 2095 /* Do not send back route to sender. */
2096 if (onlypeer && from == onlypeer) {
3dc339cd 2097 return false;
d62a17ae 2098 }
3f9c7369 2099
d62a17ae 2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer->af_flags[afi][safi],
2103 PEER_FLAG_DEFAULT_ORIGINATE)) {
2104 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2105 return false;
d62a17ae 2106 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2107 return false;
d62a17ae 2108 }
4125bb67 2109
d62a17ae 2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2112 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2113 transparent = 1;
2114 else
2115 transparent = 0;
2116
2117 /* If community is not disabled check the no-export and local. */
40381db7 2118 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2119 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2120 zlog_debug("%s: community filter check fail for %pFX",
2121 __func__, p);
3dc339cd 2122 return false;
d62a17ae 2123 }
3f9c7369 2124
d62a17ae 2125 /* If the attribute has originator-id and it is same as remote
2126 peer's id. */
40381db7
DS
2127 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2128 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2129 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2130 zlog_debug(
a9f3f4f5
DA
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2132 onlypeer, p);
3dc339cd 2133 return false;
d62a17ae 2134 }
3f9c7369 2135
d62a17ae 2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2138 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2139 || CHECK_FLAG(peer->af_cap[afi][safi],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2141 if (peer->orf_plist[afi][safi]) {
2142 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2143 == PREFIX_DENY) {
2144 if (bgp_debug_update(NULL, p,
2145 subgrp->update_group, 0))
2146 zlog_debug(
a9f3f4f5
DA
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2148 peer, p);
3dc339cd 2149 return false;
d62a17ae 2150 }
2151 }
2152
2153 /* Output filter check. */
40381db7 2154 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2155 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2157 p);
3dc339cd 2158 return false;
d62a17ae 2159 }
3f9c7369 2160
d62a17ae 2161 /* AS path loop check. */
25851bf0
DA
2162 if (peer->as_path_loop_detection &&
2163 aspath_loop_check(piattr->aspath, peer->as)) {
d62a17ae 2164 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2165 zlog_debug(
a9f3f4f5 2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
25851bf0 2167 peer, peer->as);
3dc339cd 2168 return false;
d62a17ae 2169 }
3f9c7369 2170
d62a17ae 2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2173 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2174 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2175 zlog_debug(
a9f3f4f5
DA
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer, bgp->confed_id);
3dc339cd 2178 return false;
d62a17ae 2179 }
3f9c7369 2180 }
3f9c7369 2181
d62a17ae 2182 /* Route-Reflect check. */
2183 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2184 reflect = 1;
2185 else
2186 reflect = 0;
2187
2188 /* IBGP reflection check. */
2189 if (reflect && !samepeer_safe) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from->af_flags[afi][safi],
2192 PEER_FLAG_REFLECTOR_CLIENT)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2195 check
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
892fedb6
DA
2198 if (CHECK_FLAG(bgp->flags,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2200 if (CHECK_FLAG(peer->af_flags[afi][safi],
2201 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2202 return false;
d62a17ae 2203 } else {
2204 /* A route from a Non-client peer. Reflect to all other
2205 clients. */
2206 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2207 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2208 return false;
d62a17ae 2209 }
2210 }
3f9c7369 2211
51c3a7de
DA
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2216 * path attributes.
2217 */
2218 if (post_attr)
2219 *attr = *post_attr;
2220 else
2221 *attr = *piattr;
d62a17ae 2222
2223 /* If local-preference is not set. */
2224 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2225 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2226 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2227 attr->local_pref = bgp->default_local_pref;
3f9c7369 2228 }
3f9c7369 2229
d62a17ae 2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2232 if (reflect
2233 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2234 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2235 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2236 }
3f9c7369 2237
d62a17ae 2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2239 */
2240 if (peer->sort == BGP_PEER_EBGP
2241 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2242 if (from != bgp->peer_self && !transparent
2243 && !CHECK_FLAG(peer->af_flags[afi][safi],
2244 PEER_FLAG_MED_UNCHANGED))
2245 attr->flag &=
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2247 }
3f9c7369 2248
d62a17ae 2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2250 * set
2251 * in announce check, only certain flags and length (or number of
2252 * nexthops
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2254 * formation
2255 * code in setting the nexthop(s) on a per peer basis in
2256 * reformat_peer().
2257 * Typically, the source nexthop in the attribute is preserved but in
2258 * the
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2262 * be
2263 * announced to an EBGP peer (and they have the same attributes barring
2264 * their nexthop).
2265 */
2266 if (reflect)
2267 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2268
2269#define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2274
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2276 * if
2277 * the peer (group) is configured to receive link-local nexthop
2278 * unchanged
c728d027
DA
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
d62a17ae 2281 * the peer (group) to whom we're going to announce is on a shared
2282 * network
2283 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
d62a17ae 2286 */
2287 if (NEXTHOP_IS_V6) {
2288 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2289 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2292 || (!reflect && !transparent
c728d027
DA
2293 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2294 && peer->shared_network
d62a17ae 2295 && (from == bgp->peer_self
2296 || peer->sort == BGP_PEER_EBGP))) {
f7a0eb6a
PG
2297 if (safi == SAFI_MPLS_VPN)
2298 attr->mp_nexthop_len =
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2300 else
2301 attr->mp_nexthop_len =
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 2303 }
3f9c7369 2304
d62a17ae 2305 /* Clear off link-local nexthop in source, whenever it is not
2306 * needed to
2307 * ensure more prefixes share the same attribute for
2308 * announcement.
2309 */
2310 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2312 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2313 }
3f9c7369 2314
5a78f2bc
EB
2315 if (bgp_check_role_applicability(afi, safi) &&
2316 bgp_otc_egress(peer, attr))
d864dd9e
EB
2317 return false;
2318
d62a17ae 2319 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2320 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2321
0655090c
QY
2322 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2323 filter->advmap.aname &&
2324 route_map_lookup_by_name(filter->advmap.aname)) {
2325 struct bgp_path_info rmap_path = {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2327 struct attr dummy_attr = *attr;
2328
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2331 pi, peer, &dummy_attr);
2332
2333 struct route_map *amap =
2334 route_map_lookup_by_name(filter->advmap.aname);
2335
2336 ret = route_map_apply(amap, p, &rmap_path);
2337
2338 bgp_attr_flush(&dummy_attr);
2339
2340 /*
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2343 */
2344 if (ret == RMAP_PERMITMATCH)
2345 return false;
2346 }
2347
d62a17ae 2348 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2349 if (!post_attr &&
2350 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2351 struct bgp_path_info rmap_path = {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2353 struct attr dummy_attr = {0};
d62a17ae 2354
e34291b8 2355 /* Fill temp path_info */
9bcb3eef
DS
2356 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2357 pi, peer, attr);
16f7ce2b 2358
d62a17ae 2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr->rmap_change_flags);
2361
2362 /*
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2365 */
2366 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2367 && !CHECK_FLAG(bgp->flags,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2369 dummy_attr = *attr;
40381db7 2370 rmap_path.attr = &dummy_attr;
d62a17ae 2371 }
3f9c7369 2372
d62a17ae 2373 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2374
4056a5f6 2375 if (bgp_path_suppressed(pi))
d62a17ae 2376 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2377 &rmap_path);
d62a17ae 2378 else
2379 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2380 &rmap_path);
d62a17ae 2381
7e7639f5 2382 bgp_attr_flush(&dummy_attr);
d62a17ae 2383 peer->rmap_type = 0;
2384
2385 if (ret == RMAP_DENYMATCH) {
778048bf 2386 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2387 zlog_debug(
a9f3f4f5 2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
8e8ed2e1
DS
2389 peer, p,
2390 bgp_path_suppressed(pi)
2391 ? UNSUPPRESS_MAP_NAME(filter)
2392 : ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2393 bgp_attr_flush(rmap_path.attr);
3dc339cd 2394 return false;
d62a17ae 2395 }
3f9c7369 2396 }
3f9c7369 2397
9dac9fc8
DA
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2405 * implementations.
2406 */
1d3fdccf 2407 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2408 if (!bgp_outbound_policy_exists(peer, filter)) {
2409 if (monotime_since(&bgp->ebgprequirespolicywarning,
2410 NULL) > FIFTEENMINUTE2USEC ||
2411 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2412 zlog_warn(
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp->ebgprequirespolicywarning);
2415 }
3dc339cd 2416 return false;
b17826b7 2417 }
9dac9fc8 2418
fb29348a
DA
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2424 */
7f972cd8 2425 if (peer->bgp->reject_as_sets)
fb29348a 2426 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2427 return false;
fb29348a 2428
8c4d4624 2429 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2432 * loops.
2433 */
2434 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2435 peer->soo[afi][safi]) {
2436 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2437 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2438
2439 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2440 ECOMMUNITY_SITE_ORIGIN) ||
2441 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2442 ECOMMUNITY_SITE_ORIGIN) ||
2443 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2444 ECOMMUNITY_SITE_ORIGIN)) &&
2445 ecommunity_include(ecomm, ecomm_soo)) {
2446 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2447 zlog_debug(
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer, p, ecommunity_str(ecomm_soo));
2450 return false;
2451 }
2452 }
2453
33d022bc
DA
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr->aspath))
e2369003 2456 return false;
33d022bc 2457
637e5ba4 2458 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2459 if (peer->sort == BGP_PEER_IBGP
2460 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2461 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2462 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2463 } else {
2464 bgp_attr_add_gshut_community(attr);
2465 }
2466 }
2467
1479ed2f
DA
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2472 *
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2475 */
9a706b42
DA
2476 if (bgp_attr_get_community(attr) &&
2477 community_include(bgp_attr_get_community(attr),
2478 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2479 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2480 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2481 return false;
2482
d62a17ae 2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2487 * consider
2488 * the global nexthop here; the link-local nexthop would have been
2489 * cleared
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2492 */
2493 /*
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2498 * example,
2499 * it is configured as 'peer-address'.
2500 */
2501 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2502 piattr->rmap_change_flags)
d62a17ae 2503 && !transparent
2504 && !CHECK_FLAG(peer->af_flags[afi][safi],
2505 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2507 * 'self' */
2508 if (CHECK_FLAG(peer->af_flags[afi][safi],
2509 PEER_FLAG_NEXTHOP_SELF)
2510 || CHECK_FLAG(peer->af_flags[afi][safi],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2512 if (!reflect
2513 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2514 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 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 }
d62a17ae 2522 } else if (peer->sort == BGP_PEER_EBGP) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2524 * only if
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2527 * IPv4 only.
2528 */
737af885
BS
2529 if ((p->family == AF_INET) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2531 piattr->nexthop,
7b651a32 2532 subgrp, from))) {
d62a17ae 2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2535 ? AF_INET6
2536 : p->family),
737af885 2537 attr);
7b651a32 2538 nh_reset = true;
2539 }
737af885
BS
2540
2541 if ((p->family == AF_INET6) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr->mp_nexthop_global,
7b651a32 2544 subgrp, from))) {
737af885
BS
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer, afi, safi)
2547 ? AF_INET6
2548 : p->family),
2549 attr);
7b651a32 2550 nh_reset = true;
2551 }
737af885
BS
2552
2553
2554
40381db7 2555 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2556 /*
2557 * This flag is used for leaked vpn-vrf routes
2558 */
2559 int family = p->family;
2560
2561 if (peer_cap_enhe(peer, afi, safi))
2562 family = AF_INET6;
2563
2564 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2565 zlog_debug(
6cf8a4bf
DA
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__, p, family2str(family));
960035b2 2568 subgroup_announce_reset_nhop(family, attr);
7b651a32 2569 nh_reset = true;
d62a17ae 2570 }
63696f1d 2571 }
960035b2 2572
63696f1d 2573 /* If IPv6/MP and nexthop does not have any override and happens
2574 * to
2575 * be a link-local address, reset it so that we don't pass along
2576 * the
2577 * source's link-local IPv6 address to recipients who may not be
2578 * on
2579 * the same interface.
2580 */
2581 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2582 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2583 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2584 nh_reset = true;
2585 }
d62a17ae 2586 }
3f9c7369 2587
7b27cf7b
DA
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2590 */
2591 if (peer->sort == BGP_PEER_IBGP) {
2592 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2593
2594 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2595
2596 if (rpki_state != RPKI_NOT_BEING_USED)
2597 bgp_attr_set_ecommunity(
2598 attr, ecommunity_add_origin_validation_state(
2599 rpki_state,
2600 bgp_attr_get_ecommunity(attr)));
2601 }
2602
7b651a32 2603 /*
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2608 */
2609 if (nh_reset &&
f7e1c681 2610 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2611 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2612 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2613 bgp_attr_set_ecommunity(
2614 attr,
2615 ecommunity_replace_linkbw(
2616 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2617 CHECK_FLAG(
2618 peer->flags,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2620
3dc339cd 2621 return true;
3f9c7369
DS
2622}
2623
e6685141 2624static void bgp_route_select_timer_expire(struct event *thread)
f009ff26 2625{
2626 struct afi_safi_info *info;
2627 afi_t afi;
2628 safi_t safi;
2629 struct bgp *bgp;
2630
e16d030c 2631 info = EVENT_ARG(thread);
f009ff26 2632 afi = info->afi;
2633 safi = info->safi;
2634 bgp = info->bgp;
2635
f009ff26 2636 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2637 XFREE(MTYPE_TMP, info);
2638
2639 /* Best path selection */
cc9f21da 2640 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2641}
2642
9bcb3eef 2643void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2644 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2645 struct bgp_path_info_pair *result, afi_t afi,
2646 safi_t safi)
2647{
2648 struct bgp_path_info *new_select;
2649 struct bgp_path_info *old_select;
40381db7
DS
2650 struct bgp_path_info *pi;
2651 struct bgp_path_info *pi1;
2652 struct bgp_path_info *pi2;
2653 struct bgp_path_info *nextpi = NULL;
d62a17ae 2654 int paths_eq, do_mpath, debug;
2655 struct list mp_list;
2656 char pfx_buf[PREFIX2STR_BUFFER];
2657 char path_buf[PATH_ADDPATH_STR_BUFFER];
2658
2659 bgp_mp_list_init(&mp_list);
2660 do_mpath =
2661 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2662
9bcb3eef 2663 debug = bgp_debug_bestpath(dest);
d62a17ae 2664
2665 if (debug)
9bcb3eef 2666 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2667
9bcb3eef 2668 dest->reason = bgp_path_selection_none;
d62a17ae 2669 /* bgp deterministic-med */
2670 new_select = NULL;
892fedb6 2671 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2672
1defdda8 2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2674 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2675 pi1 = pi1->next)
9bcb3eef 2676 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2677 BGP_PATH_DMED_SELECTED);
d62a17ae 2678
9bcb3eef 2679 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2680 pi1 = pi1->next) {
40381db7 2681 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2682 continue;
40381db7 2683 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2684 continue;
de692a4e 2685 if (pi1->peer != bgp->peer_self &&
2686 !CHECK_FLAG(pi1->peer->sflags,
2687 PEER_STATUS_NSF_WAIT)) {
feb17238 2688 if (!peer_established(pi1->peer))
d62a17ae 2689 continue;
de692a4e 2690 }
d62a17ae 2691
40381db7
DS
2692 new_select = pi1;
2693 if (pi1->next) {
2694 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2695 if (CHECK_FLAG(pi2->flags,
1defdda8 2696 BGP_PATH_DMED_CHECK))
d62a17ae 2697 continue;
40381db7 2698 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2699 continue;
ea8b2282 2700 if (pi2->peer != bgp->peer_self
d62a17ae 2701 && !CHECK_FLAG(
ea8b2282
DS
2702 pi2->peer->sflags,
2703 PEER_STATUS_NSF_WAIT))
40381db7 2704 if (pi2->peer->status
d62a17ae 2705 != Established)
2706 continue;
2707
121e245d
DS
2708 if (!aspath_cmp_left(pi1->attr->aspath,
2709 pi2->attr->aspath)
2710 && !aspath_cmp_left_confed(
40381db7 2711 pi1->attr->aspath,
121e245d
DS
2712 pi2->attr->aspath))
2713 continue;
d62a17ae 2714
121e245d
DS
2715 if (bgp_path_info_cmp(
2716 bgp, pi2, new_select,
2717 &paths_eq, mpath_cfg, debug,
fdf81fa0 2718 pfx_buf, afi, safi,
9bcb3eef 2719 &dest->reason)) {
121e245d 2720 bgp_path_info_unset_flag(
9bcb3eef 2721 dest, new_select,
121e245d
DS
2722 BGP_PATH_DMED_SELECTED);
2723 new_select = pi2;
d62a17ae 2724 }
121e245d
DS
2725
2726 bgp_path_info_set_flag(
9bcb3eef 2727 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2728 }
2729 }
9bcb3eef 2730 bgp_path_info_set_flag(dest, new_select,
18ee8310 2731 BGP_PATH_DMED_CHECK);
9bcb3eef 2732 bgp_path_info_set_flag(dest, new_select,
18ee8310 2733 BGP_PATH_DMED_SELECTED);
d62a17ae 2734
2735 if (debug) {
18ee8310 2736 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2737 new_select, path_buf, sizeof(path_buf));
8228a9a7 2738 zlog_debug(
4378495a
DS
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2741 aspath_get_first_as(
2742 new_select->attr->aspath));
d62a17ae 2743 }
2744 }
2745 }
96450faf 2746
d62a17ae 2747 /* Check old selected route and new selected route. */
2748 old_select = NULL;
2749 new_select = NULL;
9bcb3eef 2750 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2751 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2752 enum bgp_path_selection_reason reason;
2753
40381db7
DS
2754 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2755 old_select = pi;
d62a17ae 2756
40381db7 2757 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2760 */
40381db7
DS
2761 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2762 && (pi != old_select))
9bcb3eef 2763 bgp_path_info_reap(dest, pi);
d62a17ae 2764
ddb5b488 2765 if (debug)
7fd8ca9a
DS
2766 zlog_debug(
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__, dest, bgp->name_pretty,
2769 pi->peer->host);
ddb5b488 2770
d62a17ae 2771 continue;
2772 }
96450faf 2773
40381db7
DS
2774 if (pi->peer && pi->peer != bgp->peer_self
2775 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2776 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2777
2778 if (debug)
2779 zlog_debug(
7fd8ca9a
DS
2780 "%s: %pBD(%s) non self peer %s not estab state",
2781 __func__, dest,
2782 bgp->name_pretty,
2783 pi->peer->host);
ddb5b488 2784
d62a17ae 2785 continue;
ddb5b488 2786 }
9fbdd100 2787
892fedb6 2788 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2789 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2790 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2791 if (debug)
7fd8ca9a
DS
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
2793 dest, bgp->name_pretty,
2794 pi->peer->host);
d62a17ae 2795 continue;
2796 }
9fbdd100 2797
9bcb3eef 2798 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2799
9bcb3eef 2800 reason = dest->reason;
40381db7 2801 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2802 debug, pfx_buf, afi, safi,
2803 &dest->reason)) {
19ea4cec
DS
2804 if (new_select == NULL &&
2805 reason != bgp_path_selection_none)
9bcb3eef 2806 dest->reason = reason;
40381db7 2807 new_select = pi;
d62a17ae 2808 }
2809 }
718e3744 2810
d62a17ae 2811 /* Now that we know which path is the bestpath see if any of the other
2812 * paths
2813 * qualify as multipaths
2814 */
2815 if (debug) {
2816 if (new_select)
7533cad7
QY
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select, path_buf, sizeof(path_buf));
d62a17ae 2819 else
772270f3 2820 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2821 zlog_debug(
4378495a
DS
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest, bgp->name_pretty, path_buf,
d62a17ae 2824 old_select ? old_select->peer->host : "NONE");
96450faf 2825 }
9fbdd100 2826
d62a17ae 2827 if (do_mpath && new_select) {
9bcb3eef 2828 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2829 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2830
2831 if (debug)
18ee8310 2832 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2833 pi, path_buf, sizeof(path_buf));
d62a17ae 2834
40381db7 2835 if (pi == new_select) {
d62a17ae 2836 if (debug)
2837 zlog_debug(
4378495a
DS
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest, bgp->name_pretty,
2840 path_buf);
40381db7 2841 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2842 continue;
2843 }
2844
40381db7 2845 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2846 continue;
2847
40381db7
DS
2848 if (pi->peer && pi->peer != bgp->peer_self
2849 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2850 PEER_STATUS_NSF_WAIT))
feb17238 2851 if (!peer_established(pi->peer))
d62a17ae 2852 continue;
2853
40381db7 2854 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2855 if (debug)
2856 zlog_debug(
7fd8ca9a
DS
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest, bgp->name_pretty,
2859 path_buf);
d62a17ae 2860 continue;
2861 }
2862
40381db7 2863 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2864 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2865 &dest->reason);
d62a17ae 2866
2867 if (paths_eq) {
2868 if (debug)
2869 zlog_debug(
7fd8ca9a
DS
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest, bgp->name_pretty,
2872 path_buf);
40381db7 2873 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2874 }
2875 }
2876 }
fee0f4c6 2877
4378495a 2878 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2879 mpath_cfg);
2880 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2881 bgp_mp_list_clear(&mp_list);
96450faf 2882
9bcb3eef 2883 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2884
d62a17ae 2885 result->old = old_select;
2886 result->new = new_select;
96450faf 2887
d62a17ae 2888 return;
fee0f4c6 2889}
2890
3f9c7369
DS
2891/*
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2894 */
3dc339cd
DA
2895void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2896 struct bgp_path_info *selected,
9bcb3eef 2897 struct bgp_dest *dest,
3dc339cd 2898 uint32_t addpath_tx_id)
d62a17ae 2899{
b54892e0 2900 const struct prefix *p;
d62a17ae 2901 struct peer *onlypeer;
2902 struct attr attr;
2903 afi_t afi;
2904 safi_t safi;
a77e2f4b
S
2905 struct bgp *bgp;
2906 bool advertise;
adbac85e 2907
9bcb3eef 2908 p = bgp_dest_get_prefix(dest);
d62a17ae 2909 afi = SUBGRP_AFI(subgrp);
2910 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2911 bgp = SUBGRP_INST(subgrp);
d62a17ae 2912 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2913 : NULL);
2914
2dbe669b
DA
2915 if (BGP_DEBUG(update, UPDATE_OUT))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2917
d62a17ae 2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2919 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2920 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2921 return;
d62a17ae 2922
6006b807 2923 memset(&attr, 0, sizeof(attr));
d62a17ae 2924 /* It's initialized in bgp_announce_check() */
2925
a77e2f4b
S
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2929 * route
d62a17ae 2930 */
a77e2f4b
S
2931 advertise = bgp_check_advertise(bgp, dest);
2932
d62a17ae 2933 if (selected) {
7f7940e6 2934 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2935 NULL)) {
a77e2f4b
S
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2938 */
be785e35 2939 if (advertise) {
84ef27fc
DA
2940 if (!bgp_check_withdrawal(bgp, dest)) {
2941 struct attr *adv_attr =
2942 bgp_attr_intern(&attr);
2943
2944 bgp_adj_out_set_subgroup(dest, subgrp,
2945 adv_attr,
2946 selected);
2947 } else
be785e35
DS
2948 bgp_adj_out_unset_subgroup(
2949 dest, subgrp, 1, addpath_tx_id);
2950 }
a77e2f4b 2951 } else
9bcb3eef 2952 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2953 addpath_tx_id);
d62a17ae 2954 }
2955
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2957 else {
9bcb3eef 2958 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2959 }
200df115 2960}
fee0f4c6 2961
3064bf43 2962/*
e1072051 2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
3064bf43 2965 */
9bcb3eef 2966void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2967{
40381db7 2968 struct bgp_path_info *pi;
3064bf43 2969
9bcb3eef 2970 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2971 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2972 continue;
40381db7
DS
2973 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2974 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2975 }
3064bf43 2976}
2977
2978/*
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2982 */
9bcb3eef 2983bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2984{
4b7e6066 2985 struct bgp_path_info *mpinfo;
d62a17ae 2986
2bb9eff4
DS
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
d62a17ae 2992 */
1defdda8 2993 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2994 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2995 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2996 return true;
d62a17ae 2997
2bb9eff4
DS
2998 /*
2999 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 3000 */
18ee8310
DS
3001 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
3002 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3003 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3004 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3005 return true;
d62a17ae 3006 }
3064bf43 3007
d62a17ae 3008 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3009 return false;
3064bf43 3010}
3011
d62a17ae 3012struct bgp_process_queue {
3013 struct bgp *bgp;
9bcb3eef 3014 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3015#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3016 unsigned int flags;
3017 unsigned int queued;
200df115 3018};
3019
3b0c17e1 3020static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3021 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3022 struct bgp_path_info *new_select,
3023 struct bgp_path_info *old_select)
3024{
9bcb3eef 3025 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3026
3027 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3028 return;
3029
3030 if (advertise_type5_routes(bgp, afi) && new_select
3031 && is_route_injectable_into_evpn(new_select)) {
3032
3033 /* apply the route-map */
3034 if (bgp->adv_cmd_rmap[afi][safi].map) {
3035 route_map_result_t ret;
3036 struct bgp_path_info rmap_path;
3037 struct bgp_path_info_extra rmap_path_extra;
3038 struct attr dummy_attr;
3039
3040 dummy_attr = *new_select->attr;
3041
3042 /* Fill temp path_info */
9bcb3eef 3043 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3044 new_select, new_select->peer,
3045 &dummy_attr);
3046
3047 RESET_FLAG(dummy_attr.rmap_change_flags);
3048
3049 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3050 p, &rmap_path);
3b0c17e1 3051
3052 if (ret == RMAP_DENYMATCH) {
3053 bgp_attr_flush(&dummy_attr);
3054 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3055 safi);
3056 } else
3057 bgp_evpn_advertise_type5_route(
3058 bgp, p, &dummy_attr, afi, safi);
3059 } else {
3060 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3061 afi, safi);
3062 }
3063 } else if (advertise_type5_routes(bgp, afi) && old_select
3064 && is_route_injectable_into_evpn(old_select))
3065 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3066}
3067
bb2ca692
MS
3068/*
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3072 */
3073static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3074{
3075 /* Certain types get imp null; so do paths where the nexthop is
3076 * not labeled.
3077 */
3078 if (new_select->sub_type == BGP_ROUTE_STATIC
3079 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3080 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3081 return true;
3082 else if (new_select->extra == NULL ||
3083 !bgp_is_valid_label(&new_select->extra->label[0]))
3084 /* TODO -- should be configurable? */
3085 return true;
3086 else
3087 return false;
3088}
3089
3103e8d2
DS
3090/*
3091 * old_select = The old best path
3092 * new_select = the new best path
3093 *
3094 * if (!old_select && new_select)
3095 * We are sending new information on.
3096 *
3097 * if (old_select && new_select) {
3098 * if (new_select != old_select)
3099 * We have a new best path send a change
3100 * else
3101 * We've received a update with new attributes that needs
3102 * to be passed on.
3103 * }
3104 *
3105 * if (old_select && !new_select)
3106 * We have no eligible route that we can announce or the rn
3107 * is being removed.
3108 */
9bcb3eef 3109static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3110 afi_t afi, safi_t safi)
d62a17ae 3111{
4b7e6066
DS
3112 struct bgp_path_info *new_select;
3113 struct bgp_path_info *old_select;
3114 struct bgp_path_info_pair old_and_new;
ddb5b488 3115 int debug = 0;
d62a17ae 3116
892fedb6 3117 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3118 if (dest)
3119 debug = bgp_debug_bestpath(dest);
b54892e0 3120 if (debug)
f4c713ae 3121 zlog_debug(
7fd8ca9a
DS
3122 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3123 __func__, dest, bgp->name_pretty);
f4c713ae
LB
3124 return;
3125 }
d62a17ae 3126 /* Is it end of initial update? (after startup) */
9bcb3eef 3127 if (!dest) {
e36f61b5
DS
3128 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3129 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3130
3131 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3132 FOREACH_AFI_SAFI (afi, safi) {
3133 if (bgp_fibupd_safi(safi))
3134 bgp_zebra_announce_table(bgp, afi, safi);
3135 }
d62a17ae 3136 bgp->main_peers_update_hold = 0;
3137
3138 bgp_start_routeadv(bgp);
aac24838 3139 return;
d62a17ae 3140 }
cb1faec9 3141
9bcb3eef 3142 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3143
9bcb3eef 3144 debug = bgp_debug_bestpath(dest);
b54892e0 3145 if (debug)
7fd8ca9a 3146 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
4378495a
DS
3147 dest, bgp->name_pretty, afi2str(afi),
3148 safi2str(safi));
ddb5b488 3149
f009ff26 3150 /* The best path calculation for the route is deferred if
3151 * BGP_NODE_SELECT_DEFER is set
3152 */
9bcb3eef 3153 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3154 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
3155 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3156 dest, bgp->name_pretty);
f009ff26 3157 return;
3158 }
3159
d62a17ae 3160 /* Best path selection. */
9bcb3eef 3161 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3162 afi, safi);
3163 old_select = old_and_new.old;
3164 new_select = old_and_new.new;
3165
3166 /* Do we need to allocate or free labels?
3167 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3168 * necessary to do this upon changes to best path. Exceptions:
3169 * - label index has changed -> recalculate resulting label
3170 * - path_info sub_type changed -> switch to/from implicit-null
3171 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3172 */
318cac96 3173 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3174 if (new_select) {
3175 if (!old_select
3176 || bgp_label_index_differs(new_select, old_select)
57592a53 3177 || new_select->sub_type != old_select->sub_type
9bcb3eef 3178 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3179 /* Enforced penultimate hop popping:
3180 * implicit-null for local routes, aggregate
3181 * and redistributed routes
3182 */
bb2ca692 3183 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3184 if (CHECK_FLAG(
9bcb3eef 3185 dest->flags,
992dd67e
PR
3186 BGP_NODE_REGISTERED_FOR_LABEL)
3187 || CHECK_FLAG(
3188 dest->flags,
3189 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3190 bgp_unregister_for_label(dest);
67f67ba4
DA
3191 dest->local_label = mpls_lse_encode(
3192 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3193 1);
9bcb3eef 3194 bgp_set_valid_label(&dest->local_label);
d62a17ae 3195 } else
9bcb3eef
DS
3196 bgp_register_for_label(dest,
3197 new_select);
d62a17ae 3198 }
9bcb3eef 3199 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3200 BGP_NODE_REGISTERED_FOR_LABEL)
3201 || CHECK_FLAG(dest->flags,
3202 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3203 bgp_unregister_for_label(dest);
318cac96 3204 }
992dd67e
PR
3205 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3206 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3207 bgp_unregister_for_label(dest);
d62a17ae 3208 }
cd1964ff 3209
b54892e0 3210 if (debug)
ddb5b488 3211 zlog_debug(
4378495a
DS
3212 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3213 __func__, dest, bgp->name_pretty, afi2str(afi),
3214 safi2str(safi), old_select, new_select);
ddb5b488 3215
d62a17ae 3216 /* If best route remains the same and this is not due to user-initiated
3217 * clear, see exactly what needs to be done.
3218 */
d62a17ae 3219 if (old_select && old_select == new_select
9bcb3eef 3220 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3221 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3222 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3223 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3224#ifdef ENABLE_BGP_VNC
d62a17ae 3225 vnc_import_bgp_add_route(bgp, p, old_select);
3226 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3227#endif
bb744275 3228 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3229 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3230
3231 if (new_select->type == ZEBRA_ROUTE_BGP
3232 && (new_select->sub_type == BGP_ROUTE_NORMAL
3233 || new_select->sub_type
3234 == BGP_ROUTE_IMPORTED))
3235
9bcb3eef 3236 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3237 bgp, afi, safi);
3238 }
d62a17ae 3239 }
d62a17ae 3240
3241 /* If there is a change of interest to peers, reannounce the
3242 * route. */
1defdda8 3243 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3244 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3245 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3246 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3247
3248 /* unicast routes must also be annouced to
3249 * labeled-unicast update-groups */
3250 if (safi == SAFI_UNICAST)
3251 group_announce_route(bgp, afi,
9bcb3eef 3252 SAFI_LABELED_UNICAST, dest,
d62a17ae 3253 new_select);
3254
1defdda8 3255 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3256 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3257 }
fee0f4c6 3258
3b0c17e1 3259 /* advertise/withdraw type-5 routes */
3260 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3261 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3262 bgp_process_evpn_route_injection(
9bcb3eef 3263 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3264
b1875e65 3265 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3266 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3267 bgp_zebra_clear_route_change_flags(dest);
3268 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3269 return;
d62a17ae 3270 }
8ad7271d 3271
d62a17ae 3272 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3273 */
9bcb3eef 3274 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3275
3276 /* bestpath has changed; bump version */
3277 if (old_select || new_select) {
9bcb3eef 3278 bgp_bump_version(dest);
d62a17ae 3279
3280 if (!bgp->t_rmap_def_originate_eval) {
3281 bgp_lock(bgp);
907a2395 3282 event_add_timer(
d62a17ae 3283 bm->master,
3284 update_group_refresh_default_originate_route_map,
3285 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3286 &bgp->t_rmap_def_originate_eval);
3287 }
3288 }
3f9c7369 3289
d62a17ae 3290 if (old_select)
9bcb3eef 3291 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3292 if (new_select) {
ddb5b488
PZ
3293 if (debug)
3294 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3295 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3296 bgp_path_info_unset_flag(dest, new_select,
3297 BGP_PATH_ATTR_CHANGED);
1defdda8 3298 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3299 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3300 }
338b3424 3301
49e5a4a0 3302#ifdef ENABLE_BGP_VNC
d62a17ae 3303 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3304 if (old_select != new_select) {
3305 if (old_select) {
3306 vnc_import_bgp_exterior_del_route(bgp, p,
3307 old_select);
3308 vnc_import_bgp_del_route(bgp, p, old_select);
3309 }
3310 if (new_select) {
3311 vnc_import_bgp_exterior_add_route(bgp, p,
3312 new_select);
3313 vnc_import_bgp_add_route(bgp, p, new_select);
3314 }
3315 }
3316 }
65efcfce
LB
3317#endif
3318
9bcb3eef 3319 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3320
3321 /* unicast routes must also be annouced to labeled-unicast update-groups
3322 */
3323 if (safi == SAFI_UNICAST)
9bcb3eef 3324 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3325 new_select);
3326
3327 /* FIB update. */
3328 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3329 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3330
d62a17ae 3331 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3332 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3333 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3334 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3335
3336 /* if this is an evpn imported type-5 prefix,
3337 * we need to withdraw the route first to clear
3338 * the nh neigh and the RMAC entry.
3339 */
3340 if (old_select &&
3341 is_route_parent_evpn(old_select))
3342 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3343
9bcb3eef 3344 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3345 } else {
d62a17ae 3346 /* Withdraw the route from the kernel. */
3347 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3348 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3349 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3350 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3351
568e10ca 3352 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3353 }
718e3744 3354 }
3064bf43 3355
9bcb3eef 3356 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3357 old_select);
5424b7ba 3358
d62a17ae 3359 /* Clear any route change flags. */
9bcb3eef 3360 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3361
18ee8310 3362 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3363 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3364 bgp_path_info_reap(dest, old_select);
d62a17ae 3365
9bcb3eef 3366 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3367 return;
718e3744 3368}
3369
f009ff26 3370/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3371void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3372{
9bcb3eef 3373 struct bgp_dest *dest;
f009ff26 3374 int cnt = 0;
3375 struct afi_safi_info *thread_info;
f009ff26 3376
56c226e7 3377 if (bgp->gr_info[afi][safi].t_route_select) {
e6685141 3378 struct event *t = bgp->gr_info[afi][safi].t_route_select;
56c226e7 3379
e16d030c 3380 thread_info = EVENT_ARG(t);
56c226e7 3381 XFREE(MTYPE_TMP, thread_info);
e16d030c 3382 EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3383 }
f009ff26 3384
3385 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3386 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3387 get_afi_safi_str(afi, safi, false),
26742171 3388 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3389 }
3390
3391 /* Process the route list */
6338d242 3392 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3393 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3394 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3395 dest = bgp_route_next(dest)) {
3396 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3397 continue;
3398
3399 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3400 bgp->gr_info[afi][safi].gr_deferred--;
3401 bgp_process_main_one(bgp, dest, afi, safi);
3402 cnt++;
067ea165
CB
3403 }
3404 /* If iteration stopped before the entire table was traversed then the
3405 * node needs to be unlocked.
3406 */
3407 if (dest) {
3408 bgp_dest_unlock_node(dest);
3409 dest = NULL;
f009ff26 3410 }
3411
9e3b51a7 3412 /* Send EOR message when all routes are processed */
6338d242 3413 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3414 bgp_send_delayed_eor(bgp);
8c48b3b6 3415 /* Send route processing complete message to RIB */
115ccb9a 3416 bgp_zebra_update(bgp, afi, safi,
36235319 3417 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3418 return;
9e3b51a7 3419 }
f009ff26 3420
3421 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3422
3423 thread_info->afi = afi;
3424 thread_info->safi = safi;
3425 thread_info->bgp = bgp;
3426
3427 /* If there are more routes to be processed, start the
3428 * selection timer
3429 */
907a2395 3430 event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
f009ff26 3431 BGP_ROUTE_SELECT_DELAY,
3432 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3433}
3434
aac24838 3435static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3436{
aac24838
JB
3437 struct bgp_process_queue *pqnode = data;
3438 struct bgp *bgp = pqnode->bgp;
d62a17ae 3439 struct bgp_table *table;
9bcb3eef 3440 struct bgp_dest *dest;
aac24838
JB
3441
3442 /* eoiu marker */
3443 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3444 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3445 /* should always have dedicated wq call */
3446 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3447 return WQ_SUCCESS;
3448 }
3449
ac021f40 3450 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3451 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3452 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3453 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3454 table = bgp_dest_table(dest);
3455 /* note, new DESTs may be added as part of processing */
3456 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3457
9bcb3eef 3458 bgp_dest_unlock_node(dest);
d62a17ae 3459 bgp_table_unlock(table);
3460 }
aac24838
JB
3461
3462 return WQ_SUCCESS;
3463}
3464
3465static void bgp_processq_del(struct work_queue *wq, void *data)
3466{
3467 struct bgp_process_queue *pqnode = data;
3468
3469 bgp_unlock(pqnode->bgp);
3470
3471 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3472}
3473
b6c386bb 3474void bgp_process_queue_init(struct bgp *bgp)
200df115 3475{
b6c386bb
DS
3476 if (!bgp->process_queue) {
3477 char name[BUFSIZ];
3478
3479 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3480 bgp->process_queue = work_queue_new(bm->master, name);
3481 }
3482
3483 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3484 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3485 bgp->process_queue->spec.max_retries = 0;
3486 bgp->process_queue->spec.hold = 50;
d62a17ae 3487 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3488 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3489}
3490
cfe8d15a 3491static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3492{
3493 struct bgp_process_queue *pqnode;
3494
a4d82a8a
PZ
3495 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3496 sizeof(struct bgp_process_queue));
aac24838
JB
3497
3498 /* unlocked in bgp_processq_del */
3499 pqnode->bgp = bgp_lock(bgp);
3500 STAILQ_INIT(&pqnode->pqueue);
3501
aac24838
JB
3502 return pqnode;
3503}
3504
9bcb3eef 3505void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3506{
aac24838 3507#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3508 struct work_queue *wq = bgp->process_queue;
d62a17ae 3509 struct bgp_process_queue *pqnode;
cfe8d15a 3510 int pqnode_reuse = 0;
495f0b13 3511
d62a17ae 3512 /* already scheduled for processing? */
9bcb3eef 3513 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3514 return;
2e02b9b2 3515
f009ff26 3516 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3517 * the workqueue
3518 */
9bcb3eef 3519 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3520 if (BGP_DEBUG(update, UPDATE_OUT))
3521 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3522 dest);
f009ff26 3523 return;
3524 }
3525
46aeabed
LS
3526 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3527 if (BGP_DEBUG(update, UPDATE_OUT))
3528 zlog_debug(
3529 "Soft reconfigure table in progress for route %p",
3530 dest);
3531 return;
3532 }
3533
aac24838 3534 if (wq == NULL)
d62a17ae 3535 return;
3536
aac24838 3537 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3538 limit only if is from the same BGP view and it's not an EOIU marker
3539 */
aac24838
JB
3540 if (work_queue_item_count(wq)) {
3541 struct work_queue_item *item = work_queue_last_item(wq);
3542 pqnode = item->data;
228da428 3543
a4d82a8a
PZ
3544 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3545 || pqnode->bgp != bgp
3546 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3547 pqnode = bgp_processq_alloc(bgp);
3548 else
3549 pqnode_reuse = 1;
aac24838 3550 } else
cfe8d15a 3551 pqnode = bgp_processq_alloc(bgp);
aac24838 3552 /* all unlocked in bgp_process_wq */
9bcb3eef 3553 bgp_table_lock(bgp_dest_table(dest));
aac24838 3554
9bcb3eef
DS
3555 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3556 bgp_dest_lock_node(dest);
aac24838 3557
60466a63 3558 /* can't be enqueued twice */
9bcb3eef
DS
3559 assert(STAILQ_NEXT(dest, pq) == NULL);
3560 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3561 pqnode->queued++;
3562
cfe8d15a
LB
3563 if (!pqnode_reuse)
3564 work_queue_add(wq, pqnode);
3565
d62a17ae 3566 return;
fee0f4c6 3567}
0a486e5f 3568
d62a17ae 3569void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3570{
d62a17ae 3571 struct bgp_process_queue *pqnode;
cb1faec9 3572
b6c386bb 3573 if (bgp->process_queue == NULL)
d62a17ae 3574 return;
2e02b9b2 3575
cfe8d15a 3576 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3577
aac24838 3578 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3579 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3580}
3581
e6685141 3582static void bgp_maximum_prefix_restart_timer(struct event *thread)
0a486e5f 3583{
d62a17ae 3584 struct peer *peer;
0a486e5f 3585
e16d030c 3586 peer = EVENT_ARG(thread);
d62a17ae 3587 peer->t_pmax_restart = NULL;
0a486e5f 3588
d62a17ae 3589 if (bgp_debug_neighbor_events(peer))
3590 zlog_debug(
3591 "%s Maximum-prefix restart timer expired, restore peering",
3592 peer->host);
0a486e5f 3593
a9bafa95 3594 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3595 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3596}
3597
9cbd06e0
DA
3598static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3599 safi_t safi)
3600{
3601 uint32_t count = 0;
f41b0459 3602 bool filtered = false;
9cbd06e0
DA
3603 struct bgp_dest *dest;
3604 struct bgp_adj_in *ain;
40bb2ccf 3605 struct attr attr = {};
9cbd06e0
DA
3606 struct bgp_table *table = peer->bgp->rib[afi][safi];
3607
3608 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3609 for (ain = dest->adj_in; ain; ain = ain->next) {
3610 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3611
3612 attr = *ain->attr;
9cbd06e0
DA
3613
3614 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3615 == FILTER_DENY)
f41b0459
DA
3616 filtered = true;
3617
3618 if (bgp_input_modifier(
3619 peer, rn_p, &attr, afi, safi,
3620 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3621 NULL, 0, NULL)
3622 == RMAP_DENY)
3623 filtered = true;
3624
3625 if (filtered)
9cbd06e0 3626 count++;
f41b0459 3627
d498917e 3628 bgp_attr_flush(&attr);
9cbd06e0
DA
3629 }
3630 }
3631
3632 return count;
3633}
3634
3dc339cd
DA
3635bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3636 int always)
718e3744 3637{
d62a17ae 3638 iana_afi_t pkt_afi;
5c525538 3639 iana_safi_t pkt_safi;
9cbd06e0
DA
3640 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3641 PEER_FLAG_MAX_PREFIX_FORCE))
3642 ? bgp_filtered_routes_count(peer, afi, safi)
3643 + peer->pcount[afi][safi]
3644 : peer->pcount[afi][safi];
9cabb64b 3645
d62a17ae 3646 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3647 return false;
e0701b79 3648
9cbd06e0 3649 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3650 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3651 PEER_STATUS_PREFIX_LIMIT)
3652 && !always)
3dc339cd 3653 return false;
e0701b79 3654
d62a17ae 3655 zlog_info(
f70c91dc
DA
3656 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3657 get_afi_safi_str(afi, safi, false), peer, pcount,
3658 peer->pmax[afi][safi]);
d62a17ae 3659 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3660
3661 if (CHECK_FLAG(peer->af_flags[afi][safi],
3662 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3663 return false;
d62a17ae 3664
3665 /* Convert AFI, SAFI to values for packet. */
3666 pkt_afi = afi_int2iana(afi);
3667 pkt_safi = safi_int2iana(safi);
3668 {
d7c0a89a 3669 uint8_t ndata[7];
d62a17ae 3670
3671 ndata[0] = (pkt_afi >> 8);
3672 ndata[1] = pkt_afi;
3673 ndata[2] = pkt_safi;
3674 ndata[3] = (peer->pmax[afi][safi] >> 24);
3675 ndata[4] = (peer->pmax[afi][safi] >> 16);
3676 ndata[5] = (peer->pmax[afi][safi] >> 8);
3677 ndata[6] = (peer->pmax[afi][safi]);
3678
3679 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3680 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3681 BGP_NOTIFY_CEASE_MAX_PREFIX,
3682 ndata, 7);
3683 }
3684
3685 /* Dynamic peers will just close their connection. */
3686 if (peer_dynamic_neighbor(peer))
3dc339cd 3687 return true;
d62a17ae 3688
3689 /* restart timer start */
3690 if (peer->pmax_restart[afi][safi]) {
3691 peer->v_pmax_restart =
3692 peer->pmax_restart[afi][safi] * 60;
3693
3694 if (bgp_debug_neighbor_events(peer))
3695 zlog_debug(
f70c91dc
DA
3696 "%pBP Maximum-prefix restart timer started for %d secs",
3697 peer, peer->v_pmax_restart);
d62a17ae 3698
3699 BGP_TIMER_ON(peer->t_pmax_restart,
3700 bgp_maximum_prefix_restart_timer,
3701 peer->v_pmax_restart);
3702 }
3703
3dc339cd 3704 return true;
d62a17ae 3705 } else
3706 UNSET_FLAG(peer->af_sflags[afi][safi],
3707 PEER_STATUS_PREFIX_LIMIT);
3708
b1823b69
DS
3709 if (pcount
3710 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3711 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3712 PEER_STATUS_PREFIX_THRESHOLD)
3713 && !always)
3dc339cd 3714 return false;
d62a17ae 3715
3716 zlog_info(
f70c91dc
DA
3717 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3718 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3719 peer->pmax[afi][safi]);
d62a17ae 3720 SET_FLAG(peer->af_sflags[afi][safi],
3721 PEER_STATUS_PREFIX_THRESHOLD);
3722 } else
3723 UNSET_FLAG(peer->af_sflags[afi][safi],
3724 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3725 return false;
718e3744 3726}
3727
b40d939b 3728/* Unconditionally remove the route from the RIB, without taking
3729 * damping into consideration (eg, because the session went down)
3730 */
9bcb3eef 3731void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3732 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3733{
f009ff26 3734
3735 struct bgp *bgp = NULL;
3736 bool delete_route = false;
3737
9bcb3eef
DS
3738 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3739 safi);
d62a17ae 3740
f009ff26 3741 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3742 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3743
f009ff26 3744 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3745 * flag
3746 */
3747 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3748 delete_route = true;
9bcb3eef 3749 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3750 delete_route = true;
f009ff26 3751 if (delete_route) {
9bcb3eef
DS
3752 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3753 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3754 bgp = pi->peer->bgp;
26742171 3755 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3756 }
3757 }
3758 }
4a11bf2c 3759
9bcb3eef
DS
3760 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3761 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3762}
3763
9bcb3eef 3764static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3765 struct peer *peer, afi_t afi, safi_t safi,
3766 struct prefix_rd *prd)
3767{
9bcb3eef 3768 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3769
d62a17ae 3770 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3771 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3772 */
b4f7f45b
IR
3773 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3774 && peer->sort == BGP_PEER_EBGP)
3775 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3776 == BGP_DAMP_SUPPRESSED) {
3777 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3778 safi);
3779 return;
d62a17ae 3780 }
3781
49e5a4a0 3782#ifdef ENABLE_BGP_VNC
d62a17ae 3783 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3784 struct bgp_dest *pdest = NULL;
d62a17ae 3785 struct bgp_table *table = NULL;
3786
9bcb3eef
DS
3787 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3788 (struct prefix *)prd);
3789 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3790 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3791
3792 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3793 peer->bgp, prd, table, p, pi);
d62a17ae 3794 }
9bcb3eef 3795 bgp_dest_unlock_node(pdest);
d62a17ae 3796 }
3797 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3798 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3799
b54892e0
DS
3800 vnc_import_bgp_del_route(peer->bgp, p, pi);
3801 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3802 }
65efcfce 3803 }
d62a17ae 3804#endif
128ea8ab 3805
d62a17ae 3806 /* If this is an EVPN route, process for un-import. */
3807 if (safi == SAFI_EVPN)
b54892e0 3808 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3809
9bcb3eef 3810 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3811}
3812
4b7e6066
DS
3813struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3814 struct peer *peer, struct attr *attr,
9bcb3eef 3815 struct bgp_dest *dest)
fb018d25 3816{
4b7e6066 3817 struct bgp_path_info *new;
fb018d25 3818
d62a17ae 3819 /* Make new BGP info. */
4b7e6066 3820 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3821 new->type = type;
3822 new->instance = instance;
3823 new->sub_type = sub_type;
3824 new->peer = peer;
3825 new->attr = attr;
083ec940 3826 new->uptime = monotime(NULL);
9bcb3eef 3827 new->net = dest;
d62a17ae 3828 return new;
fb018d25
DS
3829}
3830
c265ee22 3831/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3832bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3833 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3834 struct bgp_dest *dest)
d62a17ae 3835{
2dbe3fa9 3836 bool ret = false;
b099a5c8
DA
3837 bool is_bgp_static_route =
3838 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3839 : false;
d62a17ae 3840
e8442016
DS
3841 /*
3842 * Only validated for unicast and multicast currently.
3843 * Also valid for EVPN where the nexthop is an IP address.
3844 * If we are a bgp static route being checked then there is
3845 * no need to check to see if the nexthop is martian as
3846 * that it should be ok.
3847 */
3848 if (is_bgp_static_route ||
3849 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3850 return false;
d62a17ae 3851
3852 /* If NEXT_HOP is present, validate it. */
3853 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3854 if (attr->nexthop.s_addr == INADDR_ANY ||
3855 !ipv4_unicast_valid(&attr->nexthop) ||
3856 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3857 return true;
d62a17ae 3858 }
c265ee22 3859
d62a17ae 3860 /* If MP_NEXTHOP is present, validate it. */
3861 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3862 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3863 * it is not an IPv6 link-local address.
0355b41d
DA
3864 *
3865 * If we receive an UPDATE with nexthop length set to 32 bytes
3866 * we shouldn't discard an UPDATE if it's set to (::).
3867 * The link-local (2st) is validated along the code path later.
d62a17ae 3868 */
3869 if (attr->mp_nexthop_len) {
3870 switch (attr->mp_nexthop_len) {
3871 case BGP_ATTR_NHLEN_IPV4:
3872 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3873 ret = (attr->mp_nexthop_global_in.s_addr ==
3874 INADDR_ANY ||
3875 !ipv4_unicast_valid(
3876 &attr->mp_nexthop_global_in) ||
3877 bgp_nexthop_self(bgp, afi, type, stype, attr,
3878 dest));
d62a17ae 3879 break;
3880
3881 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3882 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3883 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3884 &attr->mp_nexthop_global)
d62a17ae 3885 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3886 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3887 &attr->mp_nexthop_global)
3888 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3889 dest));
d62a17ae 3890 break;
0355b41d
DA
3891 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3892 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3893 || IN6_IS_ADDR_MULTICAST(
3894 &attr->mp_nexthop_global)
3895 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3896 dest));
0355b41d 3897 break;
d62a17ae 3898
3899 default:
3dc339cd 3900 ret = true;
d62a17ae 3901 break;
3902 }
3903 }
c265ee22 3904
d62a17ae 3905 return ret;
3906}
3907
aade37d7 3908static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3909{
3910 struct community *old;
3911 struct community *new;
3912 struct community *merge;
aade37d7 3913 struct community *no_export;
2721dd61 3914
9a706b42 3915 old = bgp_attr_get_community(attr);
aade37d7 3916 no_export = community_str2com("no-export");
2721dd61 3917
b4efa101
DA
3918 assert(no_export);
3919
2721dd61 3920 if (old) {
aade37d7 3921 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3922
3923 if (!old->refcnt)
3924 community_free(&old);
3925
3926 new = community_uniq_sort(merge);
3927 community_free(&merge);
3928 } else {
aade37d7 3929 new = community_dup(no_export);
2721dd61
DA
3930 }
3931
aade37d7 3932 community_free(&no_export);
2721dd61 3933
9a706b42 3934 bgp_attr_set_community(attr, new);
2721dd61
DA
3935}
3936
46dbf9d0
DA
3937static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3938 struct attr *attr, const struct prefix *prefix,
3939 int *sub_type)
3940{
3941 struct listnode *node, *nnode;
3942 struct bgp *bgp;
3943 bool accept_own_found = false;
3944
3945 if (safi != SAFI_MPLS_VPN)
3946 return false;
3947
3948 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3949 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3950 return false;
3951
3952 /* The route in question carries the ACCEPT_OWN community */
3953 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3954 struct community *comm = bgp_attr_get_community(attr);
3955
3956 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3957 accept_own_found = true;
3958 }
3959
3960 /* The route in question is targeted to one or more destination VRFs
3961 * on the router (as determined by inspecting the Route Target(s)).
3962 */
3963 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3964 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3965 continue;
3966
3967 if (accept_own_found &&
3968 ecommunity_include(
3969 bgp->vpn_policy[afi]
3970 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3971 bgp_attr_get_ecommunity(attr))) {
3972 if (bgp_debug_update(peer, prefix, NULL, 1))
3973 zlog_debug(
3974 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3975 peer, prefix);
3976
3977 /* Treat this route as imported, because it's leaked
3978 * already from another VRF, and we got an updated
3979 * version from route-reflector with ACCEPT_OWN
3980 * community.
3981 */
3982 *sub_type = BGP_ROUTE_IMPORTED;
3983
3984 return true;
3985 }
3986 }
3987
3988 return false;
3989}
3990
367b458c
DS
3991void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3992 struct attr *attr, afi_t afi, safi_t safi, int type,
3993 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3994 uint32_t num_labels, int soft_reconfig,
3995 struct bgp_route_evpn *evpn)
d62a17ae 3996{
3997 int ret;
3998 int aspath_loop_count = 0;
9bcb3eef 3999 struct bgp_dest *dest;
d62a17ae 4000 struct bgp *bgp;
4001 struct attr new_attr;
4002 struct attr *attr_new;
40381db7 4003 struct bgp_path_info *pi;
819e6767 4004 struct bgp_path_info *new = NULL;
4b7e6066 4005 struct bgp_path_info_extra *extra;
d62a17ae 4006 const char *reason;
4007 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4008 int connected = 0;
4009 int do_loop_check = 1;
4010 int has_valid_label = 0;
7c312383 4011 afi_t nh_afi;
9146341f 4012 bool force_evpn_import = false;
907707db 4013 safi_t orig_safi = safi;
a486300b 4014 bool leak_success = true;
b2ac1d0d 4015 int allowas_in = 0;
949b0f24 4016
c7bb4f00 4017 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4018 char pfxprint[PREFIX2STR_BUFFER];
4019
4020 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4021 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4022 afi, safi, attr);
6401252f
QY
4023 }
4024
49e5a4a0 4025#ifdef ENABLE_BGP_VNC
d62a17ae 4026 int vnc_implicit_withdraw = 0;
65efcfce 4027#endif
d62a17ae 4028 int same_attr = 0;
f8745525 4029 const struct prefix *bgp_nht_param_prefix;
718e3744 4030
907707db
MS
4031 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4032 if (orig_safi == SAFI_LABELED_UNICAST)
4033 safi = SAFI_UNICAST;
4034
6006b807 4035 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4036 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4037 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4038
d62a17ae 4039 bgp = peer->bgp;
9bcb3eef 4040 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4041 /* TODO: Check to see if we can get rid of "is_valid_label" */
4042 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4043 has_valid_label = (num_labels > 0) ? 1 : 0;
4044 else
4045 has_valid_label = bgp_is_valid_label(label);
718e3744 4046
28f66de2
MS
4047 if (has_valid_label)
4048 assert(label != NULL);
4049
66ff6089
AD
4050 /* Update overlay index of the attribute */
4051 if (afi == AFI_L2VPN && evpn)
4052 memcpy(&attr->evpn_overlay, evpn,
4053 sizeof(struct bgp_route_evpn));
4054
d62a17ae 4055 /* When peer's soft reconfiguration enabled. Record input packet in
4056 Adj-RIBs-In. */
4057 if (!soft_reconfig
4058 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4059 && peer != bgp->peer_self)
9bcb3eef 4060 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4061
b2ac1d0d
MS
4062 /* Update permitted loop count */
4063 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4064 allowas_in = peer->allowas_in[afi][safi];
4065
d62a17ae 4066 /* Check previously received route. */
9bcb3eef 4067 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4068 if (pi->peer == peer && pi->type == type
4069 && pi->sub_type == sub_type
4070 && pi->addpath_rx_id == addpath_id)
d62a17ae 4071 break;
4072
4073 /* AS path local-as loop check. */
4074 if (peer->change_local_as) {
b2ac1d0d
MS
4075 if (allowas_in)
4076 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4077 else if (!CHECK_FLAG(peer->flags,
4078 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4079 aspath_loop_count = 1;
4080
4081 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4082 > aspath_loop_count) {
b4d46cc9 4083 peer->stat_pfx_aspath_loop++;
692174a1 4084 reason = "as-path contains our own AS;";
d62a17ae 4085 goto filtered;
4086 }
718e3744 4087 }
718e3744 4088
d62a17ae 4089 /* If the peer is configured for "allowas-in origin" and the last ASN in
4090 * the
4091 * as-path is our ASN then we do not need to call aspath_loop_check
4092 */
4093 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4094 if (aspath_get_last_as(attr->aspath) == bgp->as)
4095 do_loop_check = 0;
4096
f8745525
PG
4097 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4098 bgp_nht_param_prefix = NULL;
4099 else
4100 bgp_nht_param_prefix = p;
4101
d62a17ae 4102 /* AS path loop check. */
4103 if (do_loop_check) {
b0a8f709
FD
4104 if (aspath_loop_check(attr->aspath, bgp->as) >
4105 peer->allowas_in[afi][safi]) {
b4d46cc9 4106 peer->stat_pfx_aspath_loop++;
d62a17ae 4107 reason = "as-path contains our own AS;";
4108 goto filtered;
4109 }
4110 }
aac9ef6c 4111
b0a8f709
FD
4112 /* If we're a CONFED we need to loop check the CONFED ID too */
4113 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4114 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4115 peer->allowas_in[afi][safi]) {
4116 peer->stat_pfx_aspath_loop++;
4117 reason = "as-path contains our own confed AS;";
4118 goto filtered;
4119 }
4120
46dbf9d0
DA
4121 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4122 * enabled, then take care of that too.
4123 */
4124 bool accept_own = false;
4125
d62a17ae 4126 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4127 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4128 accept_own =
4129 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4130 if (!accept_own) {
4131 peer->stat_pfx_originator_loop++;
4132 reason = "originator is us;";
4133 goto filtered;
4134 }
d62a17ae 4135 }
718e3744 4136
d62a17ae 4137 /* Route reflector cluster ID check. */
4138 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4139 peer->stat_pfx_cluster_loop++;
d62a17ae 4140 reason = "reflected from the same cluster;";
4141 goto filtered;
4142 }
718e3744 4143
d62a17ae 4144 /* Apply incoming filter. */
907707db 4145 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4146 peer->stat_pfx_filter++;
d62a17ae 4147 reason = "filter;";
4148 goto filtered;
4149 }
718e3744 4150
a8b72dc6
DA
4151 /* RFC 8212 to prevent route leaks.
4152 * This specification intends to improve this situation by requiring the
4153 * explicit configuration of both BGP Import and Export Policies for any
4154 * External BGP (EBGP) session such as customers, peers, or
4155 * confederation boundaries for all enabled address families. Through
4156 * codification of the aforementioned requirement, operators will
4157 * benefit from consistent behavior across different BGP
4158 * implementations.
4159 */
1d3fdccf 4160 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4161 if (!bgp_inbound_policy_exists(peer,
4162 &peer->filter[afi][safi])) {
4163 reason = "inbound policy missing";
b17826b7
DS
4164 if (monotime_since(&bgp->ebgprequirespolicywarning,
4165 NULL) > FIFTEENMINUTE2USEC ||
4166 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4167 zlog_warn(
4168 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4169 monotime(&bgp->ebgprequirespolicywarning);
4170 }
a8b72dc6
DA
4171 goto filtered;
4172 }
4173
fb29348a
DA
4174 /* draft-ietf-idr-deprecate-as-set-confed-set
4175 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4176 * Eventually, This document (if approved) updates RFC 4271
4177 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4178 * and obsoletes RFC 6472.
4179 */
7f972cd8 4180 if (peer->bgp->reject_as_sets)
fb29348a
DA
4181 if (aspath_check_as_sets(attr->aspath)) {
4182 reason =
4183 "as-path contains AS_SET or AS_CONFED_SET type;";
4184 goto filtered;
4185 }
4186
6f4f49b2 4187 new_attr = *attr;
d62a17ae 4188
4189 /* Apply incoming route-map.
4190 * NB: new_attr may now contain newly allocated values from route-map
4191 * "set"
4192 * commands, so we need bgp_attr_flush in the error paths, until we
4193 * intern
4194 * the attr (which takes over the memory references) */
907707db 4195 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4196 num_labels, dest)
4197 == RMAP_DENY) {
b4d46cc9 4198 peer->stat_pfx_filter++;
d62a17ae 4199 reason = "route-map;";
4200 bgp_attr_flush(&new_attr);
4201 goto filtered;
4202 }
718e3744 4203
05864da7 4204 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4205 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4206 /* remove from RIB previous entry */
4207 bgp_zebra_withdraw(p, pi, bgp, safi);
4208 }
4209
7f323236
DW
4210 if (peer->sort == BGP_PEER_EBGP) {
4211
2721dd61
DA
4212 /* rfc7999:
4213 * A BGP speaker receiving an announcement tagged with the
4214 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4215 * NO_EXPORT community as defined in RFC1997, or a
4216 * similar community, to prevent propagation of the
4217 * prefix outside the local AS. The community to prevent
4218 * propagation SHOULD be chosen according to the operator's
4219 * routing policy.
4220 */
9a706b42
DA
4221 if (bgp_attr_get_community(&new_attr) &&
4222 community_include(bgp_attr_get_community(&new_attr),
4223 COMMUNITY_BLACKHOLE))
aade37d7 4224 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4225
a4d82a8a
PZ
4226 /* If we receive the graceful-shutdown community from an eBGP
4227 * peer we must lower local-preference */
9a706b42
DA
4228 if (bgp_attr_get_community(&new_attr) &&
4229 community_include(bgp_attr_get_community(&new_attr),
4230 COMMUNITY_GSHUT)) {
7f323236
DW
4231 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4232 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4233
4f770cf1
DA
4234 /* If graceful-shutdown is configured globally or
4235 * per neighbor, then add the GSHUT community to
4236 * all paths received from eBGP peers. */
4237 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4238 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4239 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4240 }
4241
d62a17ae 4242 /* next hop check. */
860ad3f9
DS
4243 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4244 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4245 &new_attr, dest)) {
b4d46cc9 4246 peer->stat_pfx_nh_invalid++;
d62a17ae 4247 reason = "martian or self next-hop;";
4248 bgp_attr_flush(&new_attr);
4249 goto filtered;
4250 }
718e3744 4251
5c14a191 4252 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4253 peer->stat_pfx_nh_invalid++;
4e802e66 4254 reason = "self mac;";
4dbf2038 4255 bgp_attr_flush(&new_attr);
4e802e66
DS
4256 goto filtered;
4257 }
4258
5a78f2bc
EB
4259 if (bgp_check_role_applicability(afi, safi) &&
4260 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4261 reason = "failing otc validation";
4262 bgp_attr_flush(&new_attr);
4263 goto filtered;
4264 }
a1b773e2 4265
01da2d26
DA
4266 /* If neighbor soo is configured, tag all incoming routes with
4267 * this SoO tag and then filter out advertisements in
4268 * subgroup_announce_check() if it matches the configured SoO
4269 * on the other peer.
4270 */
4271 if (peer->soo[afi][safi]) {
4272 struct ecommunity *old_ecomm =
4273 bgp_attr_get_ecommunity(&new_attr);
4274 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4275 struct ecommunity *new_ecomm;
4276
4277 if (old_ecomm) {
4278 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4279 ecomm_soo);
4280
4281 if (!old_ecomm->refcnt)
4282 ecommunity_free(&old_ecomm);
4283 } else {
4284 new_ecomm = ecommunity_dup(ecomm_soo);
4285 }
4286
4287 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4288 }
4289
4dbf2038 4290 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4291
d62a17ae 4292 /* If the update is implicit withdraw. */
40381db7 4293 if (pi) {
083ec940 4294 pi->uptime = monotime(NULL);
40381db7 4295 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4296
9bcb3eef 4297 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4298
d62a17ae 4299 /* Same attribute comes in. */
40381db7 4300 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4301 && same_attr
d62a17ae 4302 && (!has_valid_label
40381db7 4303 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4304 num_labels * sizeof(mpls_label_t))
66ff6089 4305 == 0)) {
b4f7f45b
IR
4306 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4307 BGP_CONFIG_DAMPENING)
d62a17ae 4308 && peer->sort == BGP_PEER_EBGP
40381db7 4309 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4310 if (bgp_debug_update(peer, p, NULL, 1)) {
4311 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4312 afi, safi, prd, p, label,
4313 num_labels, addpath_id ? 1 : 0,
66ff6089 4314 addpath_id, evpn, pfx_buf,
a4d82a8a 4315 sizeof(pfx_buf));
f70c91dc 4316 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4317 pfx_buf);
4318 }
4319
9bcb3eef 4320 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4321 != BGP_DAMP_SUPPRESSED) {
40381db7 4322 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4323 safi);
9bcb3eef 4324 bgp_process(bgp, dest, afi, safi);
d62a17ae 4325 }
4326 } else /* Duplicate - odd */
4327 {
4328 if (bgp_debug_update(peer, p, NULL, 1)) {
4329 if (!peer->rcvd_attr_printed) {
4330 zlog_debug(
f70c91dc
DA
4331 "%pBP rcvd UPDATE w/ attr: %s",
4332 peer,
d62a17ae 4333 peer->rcvd_attr_str);
4334 peer->rcvd_attr_printed = 1;
4335 }
4336
4337 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4338 afi, safi, prd, p, label,
4339 num_labels, addpath_id ? 1 : 0,
66ff6089 4340 addpath_id, evpn, pfx_buf,
a4d82a8a 4341 sizeof(pfx_buf));
d62a17ae 4342 zlog_debug(
f70c91dc
DA
4343 "%pBP rcvd %s...duplicate ignored",
4344 peer, pfx_buf);
d62a17ae 4345 }
4346
4347 /* graceful restart STALE flag unset. */
40381db7 4348 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4349 bgp_path_info_unset_flag(
9bcb3eef
DS
4350 dest, pi, BGP_PATH_STALE);
4351 bgp_dest_set_defer_flag(dest, false);
4352 bgp_process(bgp, dest, afi, safi);
d62a17ae 4353 }
4354 }
4355
9bcb3eef 4356 bgp_dest_unlock_node(dest);
d62a17ae 4357 bgp_attr_unintern(&attr_new);
4358
367b458c 4359 return;
d62a17ae 4360 }
718e3744 4361
d62a17ae 4362 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4363 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4364 if (bgp_debug_update(peer, p, NULL, 1)) {
4365 bgp_debug_rdpfxpath2str(
a4d82a8a 4366 afi, safi, prd, p, label, num_labels,
66ff6089 4367 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4368 pfx_buf, sizeof(pfx_buf));
d62a17ae 4369 zlog_debug(
f70c91dc
DA
4370 "%pBP rcvd %s, flapped quicker than processing",
4371 peer, pfx_buf);
d62a17ae 4372 }
4373
9bcb3eef 4374 bgp_path_info_restore(dest, pi);
9146341f 4375
4376 /*
4377 * If the BGP_PATH_REMOVED flag is set, then EVPN
4378 * routes would have been unimported already when a
4379 * prior BGP withdraw processing happened. Such routes
4380 * need to be imported again, so flag accordingly.
4381 */
4382 force_evpn_import = true;
704e189e 4383 } else {
4384 /* implicit withdraw, decrement aggregate and pcount
4385 * here. only if update is accepted, they'll increment
4386 * below.
4387 */
4388 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4389 }
718e3744 4390
d62a17ae 4391 /* Received Logging. */
4392 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4393 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4394 num_labels, addpath_id ? 1 : 0,
66ff6089 4395 addpath_id, evpn, pfx_buf,
a4d82a8a 4396 sizeof(pfx_buf));
f70c91dc 4397 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4398 }
718e3744 4399
d62a17ae 4400 /* graceful restart STALE flag unset. */
f009ff26 4401 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4402 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4403 bgp_dest_set_defer_flag(dest, false);
f009ff26 4404 }
d62a17ae 4405
4406 /* The attribute is changed. */
9bcb3eef 4407 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4408
d62a17ae 4409 /* Update bgp route dampening information. */
b4f7f45b 4410 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4411 && peer->sort == BGP_PEER_EBGP) {
4412 /* This is implicit withdraw so we should update
b4f7f45b
IR
4413 dampening
4414 information. */
40381db7 4415 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4416 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4417 }
49e5a4a0 4418#ifdef ENABLE_BGP_VNC
d62a17ae 4419 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4420 struct bgp_dest *pdest = NULL;
d62a17ae 4421 struct bgp_table *table = NULL;
4422
9bcb3eef
DS
4423 pdest = bgp_node_get(bgp->rib[afi][safi],
4424 (struct prefix *)prd);
4425 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4426 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4427
4428 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4429 bgp, prd, table, p, pi);
d62a17ae 4430 }
9bcb3eef 4431 bgp_dest_unlock_node(pdest);
d62a17ae 4432 }
4433 if ((afi == AFI_IP || afi == AFI_IP6)
4434 && (safi == SAFI_UNICAST)) {
40381db7 4435 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4436 /*
4437 * Implicit withdraw case.
4438 */
4439 ++vnc_implicit_withdraw;
40381db7
DS
4440 vnc_import_bgp_del_route(bgp, p, pi);
4441 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4442 }
4443 }
65efcfce 4444#endif
128ea8ab 4445
d62a17ae 4446 /* Special handling for EVPN update of an existing route. If the
4447 * extended community attribute has changed, we need to
4448 * un-import
4449 * the route using its existing extended community. It will be
4450 * subsequently processed for import with the new extended
4451 * community.
4452 */
6f8c9c11
PR
4453 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4454 && !same_attr) {
40381db7 4455 if ((pi->attr->flag
d62a17ae 4456 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4457 && (attr_new->flag
4458 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4459 int cmp;
4460
b53e67a3
DA
4461 cmp = ecommunity_cmp(
4462 bgp_attr_get_ecommunity(pi->attr),
4463 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4464 if (!cmp) {
4465 if (bgp_debug_update(peer, p, NULL, 1))
4466 zlog_debug(
4467 "Change in EXT-COMM, existing %s new %s",
4468 ecommunity_str(
b53e67a3
DA
4469 bgp_attr_get_ecommunity(
4470 pi->attr)),
d62a17ae 4471 ecommunity_str(
b53e67a3
DA
4472 bgp_attr_get_ecommunity(
4473 attr_new)));
6f8c9c11
PR
4474 if (safi == SAFI_EVPN)
4475 bgp_evpn_unimport_route(
4476 bgp, afi, safi, p, pi);
4477 else /* SAFI_MPLS_VPN */
1aa2c93e 4478 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4479 }
4480 }
4481 }
718e3744 4482
d62a17ae 4483 /* Update to new attribute. */
40381db7
DS
4484 bgp_attr_unintern(&pi->attr);
4485 pi->attr = attr_new;
d62a17ae 4486
4487 /* Update MPLS label */
4488 if (has_valid_label) {
40381db7 4489 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4490 if (extra->label != label) {
4491 memcpy(&extra->label, label,
dbd587da 4492 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4493 extra->num_labels = num_labels;
4494 }
b57ba6d2
MK
4495 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4496 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4497 }
718e3744 4498
e496b420
HS
4499 /* Update SRv6 SID */
4500 if (attr->srv6_l3vpn) {
4501 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4502 if (sid_diff(&extra->sid[0].sid,
4503 &attr->srv6_l3vpn->sid)) {
4504 sid_copy(&extra->sid[0].sid,
e496b420
HS
4505 &attr->srv6_l3vpn->sid);
4506 extra->num_sids = 1;
cc8f05df 4507
16f3db2d
RS
4508 extra->sid[0].loc_block_len = 0;
4509 extra->sid[0].loc_node_len = 0;
4510 extra->sid[0].func_len = 0;
4511 extra->sid[0].arg_len = 0;
ea7cd161
RS
4512 extra->sid[0].transposition_len = 0;
4513 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4514
4515 if (attr->srv6_l3vpn->loc_block_len != 0) {
4516 extra->sid[0].loc_block_len =
4517 attr->srv6_l3vpn->loc_block_len;
4518 extra->sid[0].loc_node_len =
4519 attr->srv6_l3vpn->loc_node_len;
4520 extra->sid[0].func_len =
4521 attr->srv6_l3vpn->func_len;
4522 extra->sid[0].arg_len =
4523 attr->srv6_l3vpn->arg_len;
ea7cd161 4524 extra->sid[0].transposition_len =
cc8f05df 4525 attr->srv6_l3vpn
ea7cd161
RS
4526 ->transposition_len;
4527 extra->sid[0].transposition_offset =
cc8f05df 4528 attr->srv6_l3vpn
ea7cd161
RS
4529 ->transposition_offset;
4530 }
e496b420
HS
4531 }
4532 } else if (attr->srv6_vpn) {
4533 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4534 if (sid_diff(&extra->sid[0].sid,
4535 &attr->srv6_vpn->sid)) {
4536 sid_copy(&extra->sid[0].sid,
4537 &attr->srv6_vpn->sid);
e496b420
HS
4538 extra->num_sids = 1;
4539 }
4540 }
4541
49e5a4a0 4542#ifdef ENABLE_BGP_VNC
d62a17ae 4543 if ((afi == AFI_IP || afi == AFI_IP6)
4544 && (safi == SAFI_UNICAST)) {
4545 if (vnc_implicit_withdraw) {
4546 /*
4547 * Add back the route with its new attributes
4548 * (e.g., nexthop).
4549 * The route is still selected, until the route
4550 * selection
4551 * queued by bgp_process actually runs. We have
4552 * to make this
4553 * update to the VNC side immediately to avoid
4554 * racing against
4555 * configuration changes (e.g., route-map
4556 * changes) which
4557 * trigger re-importation of the entire RIB.
4558 */
40381db7
DS
4559 vnc_import_bgp_add_route(bgp, p, pi);
4560 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4561 }
4562 }
65efcfce
LB
4563#endif
4564
d62a17ae 4565 /* Update bgp route dampening information. */
b4f7f45b 4566 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4567 && peer->sort == BGP_PEER_EBGP) {
4568 /* Now we do normal update dampening. */
9bcb3eef 4569 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4570 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4571 bgp_dest_unlock_node(dest);
367b458c 4572 return;
d62a17ae 4573 }
4574 }
128ea8ab 4575
d62a17ae 4576 /* Nexthop reachability check - for unicast and
4577 * labeled-unicast.. */
7c312383
AD
4578 if (((afi == AFI_IP || afi == AFI_IP6)
4579 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4580 || (safi == SAFI_EVPN &&
4581 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4582 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4583 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4584 && !CHECK_FLAG(peer->flags,
4585 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4586 && !CHECK_FLAG(bgp->flags,
4587 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4588 connected = 1;
4589 else
4590 connected = 0;
4591
960035b2
PZ
4592 struct bgp *bgp_nexthop = bgp;
4593
40381db7
DS
4594 if (pi->extra && pi->extra->bgp_orig)
4595 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4596
7c312383
AD
4597 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4598
4599 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4600 safi, pi, NULL, connected,
f8745525
PG
4601 bgp_nht_param_prefix) ||
4602 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4603 bgp_path_info_set_flag(dest, pi,
4604 BGP_PATH_VALID);
d62a17ae 4605 else {
4606 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4607 zlog_debug("%s(%pI4): NH unresolved",
4608 __func__,
4609 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4610 }
9bcb3eef 4611 bgp_path_info_unset_flag(dest, pi,
18ee8310 4612 BGP_PATH_VALID);
d62a17ae 4613 }
46dbf9d0
DA
4614 } else {
4615 if (accept_own)
4616 bgp_path_info_set_flag(dest, pi,
4617 BGP_PATH_ACCEPT_OWN);
4618
9bcb3eef 4619 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4620 }
d62a17ae 4621
49e5a4a0 4622#ifdef ENABLE_BGP_VNC
d62a17ae 4623 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4624 struct bgp_dest *pdest = NULL;
d62a17ae 4625 struct bgp_table *table = NULL;
4626
9bcb3eef
DS
4627 pdest = bgp_node_get(bgp->rib[afi][safi],
4628 (struct prefix *)prd);
4629 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4630 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4631
4632 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4633 bgp, prd, table, p, pi);
d62a17ae 4634 }
9bcb3eef 4635 bgp_dest_unlock_node(pdest);
d62a17ae 4636 }
4637#endif
718e3744 4638
d62a17ae 4639 /* If this is an EVPN route and some attribute has changed,
9146341f 4640 * or we are explicitly told to perform a route import, process
d62a17ae 4641 * route for import. If the extended community has changed, we
4642 * would
4643 * have done the un-import earlier and the import would result
4644 * in the
4645 * route getting injected into appropriate L2 VNIs. If it is
4646 * just
4647 * some other attribute change, the import will result in
4648 * updating
4649 * the attributes for the route in the VNI(s).
4650 */
9146341f 4651 if (safi == SAFI_EVPN &&
4652 (!same_attr || force_evpn_import) &&
7c312383 4653 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4654 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4655
4656 /* Process change. */
40381db7 4657 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4658
9bcb3eef
DS
4659 bgp_process(bgp, dest, afi, safi);
4660 bgp_dest_unlock_node(dest);
558d1fec 4661
ddb5b488
PZ
4662 if (SAFI_UNICAST == safi
4663 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4664 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4665
40381db7 4666 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4667 }
4668 if ((SAFI_MPLS_VPN == safi)
4669 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4670 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4671 }
4672
49e5a4a0 4673#ifdef ENABLE_BGP_VNC
d62a17ae 4674 if (SAFI_MPLS_VPN == safi) {
4675 mpls_label_t label_decoded = decode_label(label);
28070ee3 4676
d62a17ae 4677 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4678 type, sub_type, &label_decoded);
4679 }
4680 if (SAFI_ENCAP == safi) {
4681 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4682 type, sub_type, NULL);
4683 }
28070ee3 4684#endif
a486300b
PG
4685 if ((safi == SAFI_MPLS_VPN) &&
4686 !CHECK_FLAG(bgp->af_flags[afi][safi],
4687 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4688 !leak_success) {
4689 bgp_unlink_nexthop(pi);
4690 bgp_path_info_delete(dest, pi);
4691 }
367b458c 4692 return;
d62a17ae 4693 } // End of implicit withdraw
718e3744 4694
d62a17ae 4695 /* Received Logging. */
4696 if (bgp_debug_update(peer, p, NULL, 1)) {
4697 if (!peer->rcvd_attr_printed) {
f70c91dc 4698 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4699 peer->rcvd_attr_str);
4700 peer->rcvd_attr_printed = 1;
4701 }
718e3744 4702
a4d82a8a 4703 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4704 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4705 pfx_buf, sizeof(pfx_buf));
f70c91dc 4706 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4707 }
718e3744 4708
d62a17ae 4709 /* Make new BGP info. */
9bcb3eef 4710 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4711
d62a17ae 4712 /* Update MPLS label */
4713 if (has_valid_label) {
18ee8310 4714 extra = bgp_path_info_extra_get(new);
8ba71050 4715 if (extra->label != label) {
dbd587da
QY
4716 memcpy(&extra->label, label,
4717 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4718 extra->num_labels = num_labels;
4719 }
b57ba6d2
MK
4720 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4721 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4722 }
718e3744 4723
e496b420
HS
4724 /* Update SRv6 SID */
4725 if (safi == SAFI_MPLS_VPN) {
4726 extra = bgp_path_info_extra_get(new);
4727 if (attr->srv6_l3vpn) {
16f3db2d 4728 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4729 extra->num_sids = 1;
cc8f05df 4730
16f3db2d
RS
4731 extra->sid[0].loc_block_len =
4732 attr->srv6_l3vpn->loc_block_len;
4733 extra->sid[0].loc_node_len =
4734 attr->srv6_l3vpn->loc_node_len;
4735 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4736 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4737 extra->sid[0].transposition_len =
4738 attr->srv6_l3vpn->transposition_len;
4739 extra->sid[0].transposition_offset =
4740 attr->srv6_l3vpn->transposition_offset;
e496b420 4741 } else if (attr->srv6_vpn) {
16f3db2d 4742 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4743 extra->num_sids = 1;
4744 }
4745 }
4746
d62a17ae 4747 /* Nexthop reachability check. */
7c312383
AD
4748 if (((afi == AFI_IP || afi == AFI_IP6)
4749 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4750 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4751 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4752 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4753 && !CHECK_FLAG(peer->flags,
4754 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4755 && !CHECK_FLAG(bgp->flags,
4756 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4757 connected = 1;
4758 else
4759 connected = 0;
4760
7c312383
AD
4761 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4762
4053e952 4763 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4764 connected, bgp_nht_param_prefix) ||
4765 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4766 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4767 else {
07380148
DA
4768 if (BGP_DEBUG(nht, NHT))
4769 zlog_debug("%s(%pI4): NH unresolved", __func__,
4770 &attr_new->nexthop);
9bcb3eef 4771 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4772 }
46dbf9d0
DA
4773 } else {
4774 if (accept_own)
4775 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4776
9bcb3eef 4777 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4778 }
a82478b9 4779
b381ed97
DA
4780 /* If maximum prefix count is configured and current prefix
4781 * count exeed it.
4782 */
4783 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4784 reason = "maximum-prefix overflow";
4785 bgp_attr_flush(&new_attr);
b381ed97
DA
4786 goto filtered;
4787 }
4788
d62a17ae 4789 /* Addpath ID */
4790 new->addpath_rx_id = addpath_id;
4791
4792 /* Increment prefix */
4793 bgp_aggregate_increment(bgp, p, new, afi, safi);
4794
4795 /* Register new BGP information. */
9bcb3eef 4796 bgp_path_info_add(dest, new);
d62a17ae 4797
4798 /* route_node_get lock */
9bcb3eef 4799 bgp_dest_unlock_node(dest);
558d1fec 4800
49e5a4a0 4801#ifdef ENABLE_BGP_VNC
d62a17ae 4802 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4803 struct bgp_dest *pdest = NULL;
d62a17ae 4804 struct bgp_table *table = NULL;
4805
9bcb3eef
DS
4806 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4807 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4808 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4809
4810 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4811 bgp, prd, table, p, new);
4812 }
9bcb3eef 4813 bgp_dest_unlock_node(pdest);
d62a17ae 4814 }
65efcfce
LB
4815#endif
4816
d62a17ae 4817 /* If this is an EVPN route, process for import. */
7c312383 4818 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4819 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4820
9bcb3eef 4821 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4822
d62a17ae 4823 /* Process change. */
9bcb3eef 4824 bgp_process(bgp, dest, afi, safi);
718e3744 4825
ddb5b488
PZ
4826 if (SAFI_UNICAST == safi
4827 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4828 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4829 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4830 }
4831 if ((SAFI_MPLS_VPN == safi)
4832 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4833 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4834 }
49e5a4a0 4835#ifdef ENABLE_BGP_VNC
d62a17ae 4836 if (SAFI_MPLS_VPN == safi) {
4837 mpls_label_t label_decoded = decode_label(label);
28070ee3 4838
d62a17ae 4839 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4840 sub_type, &label_decoded);
4841 }
4842 if (SAFI_ENCAP == safi) {
4843 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4844 sub_type, NULL);
4845 }
28070ee3 4846#endif
a486300b
PG
4847 if ((safi == SAFI_MPLS_VPN) &&
4848 !CHECK_FLAG(bgp->af_flags[afi][safi],
4849 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4850 !leak_success) {
4851 bgp_unlink_nexthop(new);
4852 bgp_path_info_delete(dest, new);
4853 }
28070ee3 4854
367b458c 4855 return;
718e3744 4856
d62a17ae 4857/* This BGP update is filtered. Log the reason then update BGP
4858 entry. */
4859filtered:
819e6767
DA
4860 if (new) {
4861 bgp_unlink_nexthop(new);
4862 bgp_path_info_delete(dest, new);
4863 bgp_path_info_extra_free(&new->extra);
4864 XFREE(MTYPE_BGP_ROUTE, new);
4865 }
4866
9bcb3eef 4867 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4868
d62a17ae 4869 if (bgp_debug_update(peer, p, NULL, 1)) {
4870 if (!peer->rcvd_attr_printed) {
f70c91dc 4871 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4872 peer->rcvd_attr_str);
4873 peer->rcvd_attr_printed = 1;
4874 }
718e3744 4875
a4d82a8a 4876 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4877 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4878 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4879 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4880 peer, pfx_buf, reason);
d62a17ae 4881 }
128ea8ab 4882
40381db7 4883 if (pi) {
d62a17ae 4884 /* If this is an EVPN route, un-import it as it is now filtered.
4885 */
4886 if (safi == SAFI_EVPN)
40381db7 4887 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4888
ddb5b488
PZ
4889 if (SAFI_UNICAST == safi
4890 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4891 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4892
40381db7 4893 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4894 }
4895 if ((SAFI_MPLS_VPN == safi)
4896 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4897
1aa2c93e 4898 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4899 }
4900
9bcb3eef 4901 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4902 }
4903
9bcb3eef 4904 bgp_dest_unlock_node(dest);
558d1fec 4905
49e5a4a0 4906#ifdef ENABLE_BGP_VNC
d62a17ae 4907 /*
4908 * Filtered update is treated as an implicit withdrawal (see
4909 * bgp_rib_remove()
4910 * a few lines above)
4911 */
4912 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4913 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4914 0);
4915 }
97736e32
PZ
4916#endif
4917
367b458c 4918 return;
718e3744 4919}
4920
367b458c 4921void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4922 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4923 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4924 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4925{
d62a17ae 4926 struct bgp *bgp;
4927 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4928 struct bgp_dest *dest;
40381db7 4929 struct bgp_path_info *pi;
718e3744 4930
49e5a4a0 4931#ifdef ENABLE_BGP_VNC
d62a17ae 4932 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4933 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4934 0);
4935 }
28070ee3
PZ
4936#endif
4937
d62a17ae 4938 bgp = peer->bgp;
4939
4940 /* Lookup node. */
9bcb3eef 4941 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4942
4943 /* If peer is soft reconfiguration enabled. Record input packet for
4944 * further calculation.
4945 *
4946 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4947 * routes that are filtered. This tanks out Quagga RS pretty badly due
4948 * to
4949 * the iteration over all RS clients.
4950 * Since we need to remove the entry from adj_in anyway, do that first
4951 * and
4952 * if there was no entry, we don't need to do anything more.
4953 */
4954 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4955 && peer != bgp->peer_self)
9bcb3eef 4956 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4957 peer->stat_pfx_dup_withdraw++;
4958
d62a17ae 4959 if (bgp_debug_update(peer, p, NULL, 1)) {
4960 bgp_debug_rdpfxpath2str(
a4d82a8a 4961 afi, safi, prd, p, label, num_labels,
6c995628
AD
4962 addpath_id ? 1 : 0, addpath_id, NULL,
4963 pfx_buf, sizeof(pfx_buf));
d62a17ae 4964 zlog_debug(
4965 "%s withdrawing route %s not in adj-in",
4966 peer->host, pfx_buf);
4967 }
9bcb3eef 4968 bgp_dest_unlock_node(dest);
367b458c 4969 return;
d62a17ae 4970 }
cd808e74 4971
d62a17ae 4972 /* Lookup withdrawn route. */
9bcb3eef 4973 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4974 if (pi->peer == peer && pi->type == type
4975 && pi->sub_type == sub_type
4976 && pi->addpath_rx_id == addpath_id)
d62a17ae 4977 break;
4978
4979 /* Logging. */
4980 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4981 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4982 addpath_id ? 1 : 0, addpath_id, NULL,
4983 pfx_buf, sizeof(pfx_buf));
f70c91dc 4984 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4985 pfx_buf);
4986 }
718e3744 4987
d62a17ae 4988 /* Withdraw specified route from routing table. */
40381db7 4989 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4990 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4991 if (SAFI_UNICAST == safi
4992 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4993 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4994 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4995 }
4996 if ((SAFI_MPLS_VPN == safi)
4997 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4998
1aa2c93e 4999 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
5000 }
5001 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5002 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5003 addpath_id ? 1 : 0, addpath_id, NULL,
5004 pfx_buf, sizeof(pfx_buf));
d62a17ae 5005 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5006 }
718e3744 5007
d62a17ae 5008 /* Unlock bgp_node_get() lock. */
9bcb3eef 5009 bgp_dest_unlock_node(dest);
d62a17ae 5010
367b458c 5011 return;
718e3744 5012}
6b0655a2 5013
d62a17ae 5014void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5015 int withdraw)
718e3744 5016{
d62a17ae 5017 struct update_subgroup *subgrp;
5018 subgrp = peer_subgroup(peer, afi, safi);
5019 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5020}
6182d65b 5021
718e3744 5022
3f9c7369
DS
5023/*
5024 * bgp_stop_announce_route_timer
5025 */
d62a17ae 5026void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5027{
d62a17ae 5028 if (!paf->t_announce_route)
5029 return;
5030
e16d030c 5031 EVENT_OFF(paf->t_announce_route);
718e3744 5032}
6b0655a2 5033
3f9c7369
DS
5034/*
5035 * bgp_announce_route_timer_expired
5036 *
5037 * Callback that is invoked when the route announcement timer for a
5038 * peer_af expires.
5039 */
e6685141 5040static void bgp_announce_route_timer_expired(struct event *t)
718e3744 5041{
d62a17ae 5042 struct peer_af *paf;
5043 struct peer *peer;
558d1fec 5044
e16d030c 5045 paf = EVENT_ARG(t);
d62a17ae 5046 peer = paf->peer;
718e3744 5047
feb17238 5048 if (!peer_established(peer))
cc9f21da 5049 return;
3f9c7369 5050
d62a17ae 5051 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5052 return;
3f9c7369 5053
d62a17ae 5054 peer_af_announce_route(paf, 1);
c5aec50b
MK
5055
5056 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5057 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5058}
5059
3f9c7369
DS
5060/*
5061 * bgp_announce_route
5062 *
5063 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5064 *
5065 * if force is true we will force an update even if the update
5066 * limiting code is attempted to kick in.
3f9c7369 5067 */
e1a32ec1 5068void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5069{
5070 struct peer_af *paf;
5071 struct update_subgroup *subgrp;
5072
5073 paf = peer_af_find(peer, afi, safi);
5074 if (!paf)
5075 return;
5076 subgrp = PAF_SUBGRP(paf);
5077
5078 /*
5079 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5080 * or a refresh has already been triggered.
5081 */
5082 if (!subgrp || paf->t_announce_route)
5083 return;
5084
e1a32ec1
DS
5085 if (force)
5086 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5087
d62a17ae 5088 /*
5089 * Start a timer to stagger/delay the announce. This serves
5090 * two purposes - announcement can potentially be combined for
5091 * multiple peers and the announcement doesn't happen in the
5092 * vty context.
5093 */
907a2395
DS
5094 event_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5095 (subgrp->peer_count == 1)
5096 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5097 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5098 &paf->t_announce_route);
3f9c7369
DS
5099}
5100
5101/*
5102 * Announce routes from all AF tables to a peer.
5103 *
5104 * This should ONLY be called when there is a need to refresh the
5105 * routes to the peer based on a policy change for this peer alone
5106 * or a route refresh request received from the peer.
5107 * The operation will result in splitting the peer from its existing
5108 * subgroups and putting it in new subgroups.
5109 */
d62a17ae 5110void bgp_announce_route_all(struct peer *peer)
718e3744 5111{
d62a17ae 5112 afi_t afi;
5113 safi_t safi;
5114
05c7a1cc 5115 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5116 bgp_announce_route(peer, afi, safi, false);
718e3744 5117}
6b0655a2 5118
46aeabed
LS
5119/* Flag or unflag bgp_dest to determine whether it should be treated by
5120 * bgp_soft_reconfig_table_task.
5121 * Flag if flag is true. Unflag if flag is false.
5122 */
5123static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5124{
5125 struct bgp_dest *dest;
5126 struct bgp_adj_in *ain;
5127
5128 if (!table)
5129 return;
5130
5131 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5132 for (ain = dest->adj_in; ain; ain = ain->next) {
5133 if (ain->peer != NULL)
5134 break;
5135 }
5136 if (flag && ain != NULL && ain->peer != NULL)
5137 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5138 else
5139 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5140 }
5141}
5142
367b458c
DS
5143static void bgp_soft_reconfig_table_update(struct peer *peer,
5144 struct bgp_dest *dest,
5145 struct bgp_adj_in *ain, afi_t afi,
5146 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5147{
5148 struct bgp_path_info *pi;
5149 uint32_t num_labels = 0;
5150 mpls_label_t *label_pnt = NULL;
5151 struct bgp_route_evpn evpn;
5152
5153 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5154 if (pi->peer == peer)
5155 break;
5156
5157 if (pi && pi->extra)
5158 num_labels = pi->extra->num_labels;
5159 if (num_labels)
5160 label_pnt = &pi->extra->label[0];
5161 if (pi)
5162 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5163 sizeof(evpn));
5164 else
5165 memset(&evpn, 0, sizeof(evpn));
5166
367b458c
DS
5167 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5168 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5169 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5170}
5171
d62a17ae 5172static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5173 struct bgp_table *table,
5174 struct prefix_rd *prd)
718e3744 5175{
9bcb3eef 5176 struct bgp_dest *dest;
d62a17ae 5177 struct bgp_adj_in *ain;
718e3744 5178
d62a17ae 5179 if (!table)
5180 table = peer->bgp->rib[afi][safi];
718e3744 5181
9bcb3eef
DS
5182 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5183 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5184 if (ain->peer != peer)
5185 continue;
8692c506 5186
367b458c
DS
5187 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5188 safi, prd);
d62a17ae 5189 }
718e3744 5190}
5191
46aeabed
LS
5192/* Do soft reconfig table per bgp table.
5193 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5194 * when BGP_NODE_SOFT_RECONFIG is set,
5195 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5196 * Schedule a new thread to continue the job.
5197 * Without splitting the full job into several part,
5198 * vtysh waits for the job to finish before responding to a BGP command
5199 */
e6685141 5200static void bgp_soft_reconfig_table_task(struct event *thread)
46aeabed
LS
5201{
5202 uint32_t iter, max_iter;
46aeabed
LS
5203 struct bgp_dest *dest;
5204 struct bgp_adj_in *ain;
5205 struct peer *peer;
5206 struct bgp_table *table;
5207 struct prefix_rd *prd;
5208 struct listnode *node, *nnode;
5209
e16d030c 5210 table = EVENT_ARG(thread);
46aeabed
LS
5211 prd = NULL;
5212
5213 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5214 if (table->soft_reconfig_init) {
5215 /* first call of the function with a new srta structure.
5216 * Don't do any treatment this time on nodes
5217 * in order vtysh to respond quickly
5218 */
5219 max_iter = 0;
5220 }
5221
5222 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5223 dest = bgp_route_next(dest)) {
5224 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5225 continue;
5226
5227 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5228
5229 for (ain = dest->adj_in; ain; ain = ain->next) {
5230 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5231 nnode, peer)) {
5232 if (ain->peer != peer)
5233 continue;
5234
367b458c 5235 bgp_soft_reconfig_table_update(
46aeabed
LS
5236 peer, dest, ain, table->afi,
5237 table->safi, prd);
5238 iter++;
46aeabed
LS
5239 }
5240 }
5241 }
5242
5243 /* we're either starting the initial iteration,
5244 * or we're going to continue an ongoing iteration
5245 */
5246 if (dest || table->soft_reconfig_init) {
5247 table->soft_reconfig_init = false;
907a2395
DS
5248 event_add_event(bm->master, bgp_soft_reconfig_table_task, table,
5249 0, &table->soft_reconfig_thread);
cc9f21da 5250 return;
46aeabed
LS
5251 }
5252 /* we're done, clean up the background iteration context info and
5253 schedule route annoucement
5254 */
5255 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5256 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5257 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5258 }
5259
5260 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5261}
5262
5263
5264/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5265 * and peer.
5266 * - bgp cannot be NULL
5267 * - if table and peer are NULL, cancel all threads within the bgp instance
5268 * - if table is NULL and peer is not,
5269 * remove peer in all threads within the bgp instance
5270 * - if peer is NULL, cancel all threads matching table within the bgp instance
5271 */
5272void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5273 const struct bgp_table *table,
5274 const struct peer *peer)
5275{
5276 struct peer *npeer;
5277 struct listnode *node, *nnode;
5278 int afi, safi;
5279 struct bgp_table *ntable;
5280
5281 if (!bgp)
5282 return;
5283
5284 FOREACH_AFI_SAFI (afi, safi) {
5285 ntable = bgp->rib[afi][safi];
5286 if (!ntable)
5287 continue;
5288 if (table && table != ntable)
5289 continue;
5290
5291 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5292 npeer)) {
5293 if (peer && peer != npeer)
5294 continue;
5295 listnode_delete(ntable->soft_reconfig_peers, npeer);
5296 }
5297
5298 if (!ntable->soft_reconfig_peers
5299 || !list_isempty(ntable->soft_reconfig_peers))
5300 continue;
5301
5302 list_delete(&ntable->soft_reconfig_peers);
5303 bgp_soft_reconfig_table_flag(ntable, false);
e16d030c 5304 EVENT_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5305 }
5306}
5307
89c73443
DS
5308/*
5309 * Returns false if the peer is not configured for soft reconfig in
5310 */
5311bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5312{
9bcb3eef 5313 struct bgp_dest *dest;
d62a17ae 5314 struct bgp_table *table;
46aeabed
LS
5315 struct listnode *node, *nnode;
5316 struct peer *npeer;
5317 struct peer_af *paf;
718e3744 5318
89c73443
DS
5319 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5320 return false;
718e3744 5321
d62a17ae 5322 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5323 && (safi != SAFI_EVPN)) {
5324 table = peer->bgp->rib[afi][safi];
5325 if (!table)
89c73443 5326 return true;
46aeabed
LS
5327
5328 table->soft_reconfig_init = true;
5329
5330 if (!table->soft_reconfig_peers)
5331 table->soft_reconfig_peers = list_new();
5332 npeer = NULL;
5333 /* add peer to the table soft_reconfig_peers if not already
5334 * there
5335 */
5336 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5337 npeer)) {
5338 if (peer == npeer)
5339 break;
5340 }
5341 if (peer != npeer)
5342 listnode_add(table->soft_reconfig_peers, peer);
5343
5344 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5345 * on table would start back at the beginning.
5346 */
5347 bgp_soft_reconfig_table_flag(table, true);
5348
5349 if (!table->soft_reconfig_thread)
907a2395
DS
5350 event_add_event(bm->master,
5351 bgp_soft_reconfig_table_task, table, 0,
5352 &table->soft_reconfig_thread);
46aeabed
LS
5353 /* Cancel bgp_announce_route_timer_expired threads.
5354 * bgp_announce_route_timer_expired threads have been scheduled
5355 * to announce routes as soon as the soft_reconfigure process
5356 * finishes.
5357 * In this case, soft_reconfigure is also scheduled by using
5358 * a thread but is planned after the
5359 * bgp_announce_route_timer_expired threads. It means that,
5360 * without cancelling the threads, the route announcement task
5361 * would run before the soft reconfiguration one. That would
5362 * useless and would block vtysh during several seconds. Route
5363 * announcements are rescheduled as soon as the soft_reconfigure
5364 * process finishes.
5365 */
5366 paf = peer_af_find(peer, afi, safi);
5367 if (paf)
5368 bgp_stop_announce_route_timer(paf);
5369 } else
9bcb3eef
DS
5370 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5371 dest = bgp_route_next(dest)) {
5372 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5373
b54892e0
DS
5374 if (table == NULL)
5375 continue;
8692c506 5376
9bcb3eef 5377 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5378 struct prefix_rd prd;
5379
5380 prd.family = AF_UNSPEC;
5381 prd.prefixlen = 64;
5382 memcpy(&prd.val, p->u.val, 8);
5383
5384 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5385 }
89c73443
DS
5386
5387 return true;
718e3744 5388}
6b0655a2 5389
228da428 5390
d62a17ae 5391struct bgp_clear_node_queue {
9bcb3eef 5392 struct bgp_dest *dest;
228da428
CC
5393};
5394
d62a17ae 5395static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5396{
d62a17ae 5397 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5398 struct bgp_dest *dest = cnq->dest;
d62a17ae 5399 struct peer *peer = wq->spec.data;
40381db7 5400 struct bgp_path_info *pi;
3103e8d2 5401 struct bgp *bgp;
9bcb3eef
DS
5402 afi_t afi = bgp_dest_table(dest)->afi;
5403 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5404
9bcb3eef 5405 assert(dest && peer);
3103e8d2 5406 bgp = peer->bgp;
d62a17ae 5407
5408 /* It is possible that we have multiple paths for a prefix from a peer
5409 * if that peer is using AddPath.
5410 */
9bcb3eef 5411 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5412 if (pi->peer != peer)
ea47320b
DL
5413 continue;
5414
5415 /* graceful restart STALE flag set. */
9af52ccf
DA
5416 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5417 && peer->nsf[afi][safi])
5418 || CHECK_FLAG(peer->af_sflags[afi][safi],
5419 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5420 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5421 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5422 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5423 else {
5424 /* If this is an EVPN route, process for
5425 * un-import. */
5426 if (safi == SAFI_EVPN)
9bcb3eef
DS
5427 bgp_evpn_unimport_route(
5428 bgp, afi, safi,
5429 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5430 /* Handle withdraw for VRF route-leaking and L3VPN */
5431 if (SAFI_UNICAST == safi
5432 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5433 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5434 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5435 bgp, pi);
960035b2 5436 }
3103e8d2 5437 if (SAFI_MPLS_VPN == safi &&
960035b2 5438 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5439 vpn_leak_to_vrf_withdraw(pi);
960035b2 5440 }
3103e8d2 5441
9bcb3eef 5442 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5443 }
ea47320b 5444 }
d62a17ae 5445 return WQ_SUCCESS;
200df115 5446}
5447
d62a17ae 5448static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5449{
d62a17ae 5450 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5451 struct bgp_dest *dest = cnq->dest;
5452 struct bgp_table *table = bgp_dest_table(dest);
228da428 5453
9bcb3eef 5454 bgp_dest_unlock_node(dest);
d62a17ae 5455 bgp_table_unlock(table);
5456 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5457}
5458
d62a17ae 5459static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5460{
d62a17ae 5461 struct peer *peer = wq->spec.data;
64e580a7 5462
d62a17ae 5463 /* Tickle FSM to start moving again */
5464 BGP_EVENT_ADD(peer, Clearing_Completed);
5465
5466 peer_unlock(peer); /* bgp_clear_route */
200df115 5467}
718e3744 5468
d62a17ae 5469static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5470{
d62a17ae 5471 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5472
5473 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5474#undef CLEAR_QUEUE_NAME_LEN
5475
0ce1ca80 5476 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5477 peer->clear_node_queue->spec.hold = 10;
5478 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5479 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5480 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5481 peer->clear_node_queue->spec.max_retries = 0;
5482
5483 /* we only 'lock' this peer reference when the queue is actually active
5484 */
5485 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5486}
5487
d62a17ae 5488static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5489 struct bgp_table *table)
65ca75e0 5490{
9bcb3eef 5491 struct bgp_dest *dest;
b6c386bb 5492 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5493
d62a17ae 5494 if (!table)
5495 table = peer->bgp->rib[afi][safi];
dc83d712 5496
d62a17ae 5497 /* If still no table => afi/safi isn't configured at all or smth. */
5498 if (!table)
5499 return;
dc83d712 5500
9bcb3eef 5501 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5502 struct bgp_path_info *pi, *next;
d62a17ae 5503 struct bgp_adj_in *ain;
5504 struct bgp_adj_in *ain_next;
5505
5506 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5507 * queued for every clearing peer, regardless of whether it is
5508 * relevant to the peer at hand.
5509 *
5510 * Overview: There are 3 different indices which need to be
5511 * scrubbed, potentially, when a peer is removed:
5512 *
5513 * 1 peer's routes visible via the RIB (ie accepted routes)
5514 * 2 peer's routes visible by the (optional) peer's adj-in index
5515 * 3 other routes visible by the peer's adj-out index
5516 *
5517 * 3 there is no hurry in scrubbing, once the struct peer is
5518 * removed from bgp->peer, we could just GC such deleted peer's
5519 * adj-outs at our leisure.
5520 *
5521 * 1 and 2 must be 'scrubbed' in some way, at least made
5522 * invisible via RIB index before peer session is allowed to be
5523 * brought back up. So one needs to know when such a 'search' is
5524 * complete.
5525 *
5526 * Ideally:
5527 *
5528 * - there'd be a single global queue or a single RIB walker
5529 * - rather than tracking which route_nodes still need to be
5530 * examined on a peer basis, we'd track which peers still
5531 * aren't cleared
5532 *
5533 * Given that our per-peer prefix-counts now should be reliable,
5534 * this may actually be achievable. It doesn't seem to be a huge
5535 * problem at this time,
5536 *
5537 * It is possible that we have multiple paths for a prefix from
5538 * a peer
5539 * if that peer is using AddPath.
5540 */
9bcb3eef 5541 ain = dest->adj_in;
d62a17ae 5542 while (ain) {
5543 ain_next = ain->next;
5544
6a840fd9 5545 if (ain->peer == peer)
9bcb3eef 5546 bgp_adj_in_remove(dest, ain);
d62a17ae 5547
5548 ain = ain_next;
5549 }
5550
9bcb3eef 5551 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5552 next = pi->next;
5553 if (pi->peer != peer)
d62a17ae 5554 continue;
5555
5556 if (force)
9bcb3eef 5557 bgp_path_info_reap(dest, pi);
d62a17ae 5558 else {
5559 struct bgp_clear_node_queue *cnq;
5560
5561 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5562 bgp_table_lock(bgp_dest_table(dest));
5563 bgp_dest_lock_node(dest);
d62a17ae 5564 cnq = XCALLOC(
5565 MTYPE_BGP_CLEAR_NODE_QUEUE,
5566 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5567 cnq->dest = dest;
d62a17ae 5568 work_queue_add(peer->clear_node_queue, cnq);
5569 break;
5570 }
5571 }
5572 }
5573 return;
5574}
5575
5576void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5577{
9bcb3eef 5578 struct bgp_dest *dest;
d62a17ae 5579 struct bgp_table *table;
5580
5581 if (peer->clear_node_queue == NULL)
5582 bgp_clear_node_queue_init(peer);
5583
5584 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5585 * Idle until it receives a Clearing_Completed event. This protects
5586 * against peers which flap faster than we can we clear, which could
5587 * lead to:
5588 *
5589 * a) race with routes from the new session being installed before
5590 * clear_route_node visits the node (to delete the route of that
5591 * peer)
5592 * b) resource exhaustion, clear_route_node likely leads to an entry
5593 * on the process_main queue. Fast-flapping could cause that queue
5594 * to grow and grow.
5595 */
5596
5597 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5598 * the unlock will happen upon work-queue completion; other wise, the
5599 * unlock happens at the end of this function.
5600 */
5601 if (!peer->clear_node_queue->thread)
5602 peer_lock(peer);
5603
5604 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5605 bgp_clear_route_table(peer, afi, safi, NULL);
5606 else
9bcb3eef
DS
5607 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5608 dest = bgp_route_next(dest)) {
5609 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5610 if (!table)
5611 continue;
5612
5613 bgp_clear_route_table(peer, afi, safi, table);
5614 }
d62a17ae 5615
5616 /* unlock if no nodes got added to the clear-node-queue. */
5617 if (!peer->clear_node_queue->thread)
5618 peer_unlock(peer);
718e3744 5619}
d62a17ae 5620
5621void bgp_clear_route_all(struct peer *peer)
718e3744 5622{
d62a17ae 5623 afi_t afi;
5624 safi_t safi;
718e3744 5625
05c7a1cc
QY
5626 FOREACH_AFI_SAFI (afi, safi)
5627 bgp_clear_route(peer, afi, safi);
65efcfce 5628
49e5a4a0 5629#ifdef ENABLE_BGP_VNC
d62a17ae 5630 rfapiProcessPeerDown(peer);
65efcfce 5631#endif
718e3744 5632}
5633
d62a17ae 5634void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5635{
d62a17ae 5636 struct bgp_table *table;
9bcb3eef 5637 struct bgp_dest *dest;
d62a17ae 5638 struct bgp_adj_in *ain;
5639 struct bgp_adj_in *ain_next;
718e3744 5640
d62a17ae 5641 table = peer->bgp->rib[afi][safi];
718e3744 5642
d62a17ae 5643 /* It is possible that we have multiple paths for a prefix from a peer
5644 * if that peer is using AddPath.
5645 */
9bcb3eef
DS
5646 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5647 ain = dest->adj_in;
43143c8f 5648
d62a17ae 5649 while (ain) {
5650 ain_next = ain->next;
43143c8f 5651
6a840fd9 5652 if (ain->peer == peer)
9bcb3eef 5653 bgp_adj_in_remove(dest, ain);
43143c8f 5654
d62a17ae 5655 ain = ain_next;
5656 }
5657 }
718e3744 5658}
93406d87 5659
1479ed2f
DA
5660/* If any of the routes from the peer have been marked with the NO_LLGR
5661 * community, either as sent by the peer, or as the result of a configured
5662 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5663 * operation of [RFC4271].
5664 */
d62a17ae 5665void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5666{
9bcb3eef 5667 struct bgp_dest *dest;
40381db7 5668 struct bgp_path_info *pi;
d62a17ae 5669 struct bgp_table *table;
5670
9af52ccf 5671 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5672 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5673 dest = bgp_route_next(dest)) {
5674 struct bgp_dest *rm;
d62a17ae 5675
5676 /* look for neighbor in tables */
9bcb3eef 5677 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5678 if (!table)
ea47320b
DL
5679 continue;
5680
5681 for (rm = bgp_table_top(table); rm;
5682 rm = bgp_route_next(rm))
9bcb3eef 5683 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5684 pi = pi->next) {
40381db7 5685 if (pi->peer != peer)
ea47320b 5686 continue;
1479ed2f
DA
5687 if (CHECK_FLAG(
5688 peer->af_sflags[afi][safi],
5689 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5690 bgp_attr_get_community(pi->attr) &&
1479ed2f 5691 !community_include(
9a706b42
DA
5692 bgp_attr_get_community(
5693 pi->attr),
1479ed2f 5694 COMMUNITY_NO_LLGR))
e3015d91 5695 continue;
40381db7 5696 if (!CHECK_FLAG(pi->flags,
1defdda8 5697 BGP_PATH_STALE))
e3015d91 5698 continue;
ea47320b 5699
641065d4
KM
5700 /*
5701 * If this is VRF leaked route
5702 * process for withdraw.
5703 */
5704 if (pi->sub_type ==
5705 BGP_ROUTE_IMPORTED &&
5706 peer->bgp->inst_type ==
5707 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5708 vpn_leak_to_vrf_withdraw(pi);
641065d4 5709
40381db7 5710 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5711 break;
5712 }
d62a17ae 5713 }
5714 } else {
9bcb3eef
DS
5715 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5716 dest = bgp_route_next(dest))
5717 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5718 pi = pi->next) {
40381db7 5719 if (pi->peer != peer)
ea47320b 5720 continue;
1479ed2f
DA
5721 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5722 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5723 bgp_attr_get_community(pi->attr) &&
5724 !community_include(
5725 bgp_attr_get_community(pi->attr),
5726 COMMUNITY_NO_LLGR))
e3015d91 5727 continue;
40381db7 5728 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5729 continue;
641065d4
KM
5730 if (safi == SAFI_UNICAST &&
5731 (peer->bgp->inst_type ==
5732 BGP_INSTANCE_TYPE_VRF ||
5733 peer->bgp->inst_type ==
5734 BGP_INSTANCE_TYPE_DEFAULT))
5735 vpn_leak_from_vrf_withdraw(
5736 bgp_get_default(), peer->bgp,
5737 pi);
5738
9bcb3eef 5739 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5740 break;
5741 }
d62a17ae 5742 }
93406d87 5743}
6b0655a2 5744
9af52ccf
DA
5745void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5746{
5747 struct bgp_dest *dest, *ndest;
5748 struct bgp_path_info *pi;
5749 struct bgp_table *table;
5750
5751 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5752 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5753 dest = bgp_route_next(dest)) {
5754 table = bgp_dest_get_bgp_table_info(dest);
5755 if (!table)
5756 continue;
5757
5758 for (ndest = bgp_table_top(table); ndest;
5759 ndest = bgp_route_next(ndest)) {
5760 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5761 pi = pi->next) {
5762 if (pi->peer != peer)
5763 continue;
5764
5765 if ((CHECK_FLAG(
5766 peer->af_sflags[afi][safi],
5767 PEER_STATUS_ENHANCED_REFRESH))
5768 && !CHECK_FLAG(pi->flags,
5769 BGP_PATH_STALE)
5770 && !CHECK_FLAG(
5771 pi->flags,
5772 BGP_PATH_UNUSEABLE)) {
5773 if (bgp_debug_neighbor_events(
5774 peer))
5775 zlog_debug(
58e111f6
DA
5776 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5777 peer,
9af52ccf
DA
5778 afi2str(afi),
5779 safi2str(safi),
5780 bgp_dest_get_prefix(
5781 ndest));
5782
5783 bgp_path_info_set_flag(
5784 ndest, pi,
5785 BGP_PATH_STALE);
5786 }
5787 }
5788 }
5789 }
5790 } else {
5791 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5792 dest = bgp_route_next(dest)) {
5793 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5794 pi = pi->next) {
5795 if (pi->peer != peer)
5796 continue;
5797
5798 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5799 PEER_STATUS_ENHANCED_REFRESH))
5800 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5801 && !CHECK_FLAG(pi->flags,
5802 BGP_PATH_UNUSEABLE)) {
5803 if (bgp_debug_neighbor_events(peer))
5804 zlog_debug(
58e111f6
DA
5805 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5806 peer, afi2str(afi),
9af52ccf
DA
5807 safi2str(safi),
5808 bgp_dest_get_prefix(
5809 dest));
5810
5811 bgp_path_info_set_flag(dest, pi,
5812 BGP_PATH_STALE);
5813 }
5814 }
5815 }
5816 }
5817}
5818
3dc339cd 5819bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5820{
e0df4c04 5821 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5822 return true;
e0df4c04 5823
9dac9fc8
DA
5824 if (peer->sort == BGP_PEER_EBGP
5825 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5826 || FILTER_LIST_OUT_NAME(filter)
5827 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5828 return true;
5829 return false;
9dac9fc8
DA
5830}
5831
3dc339cd 5832bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5833{
e0df4c04 5834 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5835 return true;
e0df4c04 5836
9dac9fc8
DA
5837 if (peer->sort == BGP_PEER_EBGP
5838 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5839 || FILTER_LIST_IN_NAME(filter)
5840 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5841 return true;
5842 return false;
9dac9fc8
DA
5843}
5844
568e10ca 5845static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5846 safi_t safi)
bb86c601 5847{
9bcb3eef 5848 struct bgp_dest *dest;
40381db7 5849 struct bgp_path_info *pi;
4b7e6066 5850 struct bgp_path_info *next;
bb86c601 5851
9bcb3eef
DS
5852 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5853 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5854 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5855
40381db7 5856 next = pi->next;
1b7bb747
CS
5857
5858 /* Unimport EVPN routes from VRFs */
5859 if (safi == SAFI_EVPN)
5860 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5861 SAFI_EVPN, p, pi);
1b7bb747 5862
40381db7
DS
5863 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5864 && pi->type == ZEBRA_ROUTE_BGP
5865 && (pi->sub_type == BGP_ROUTE_NORMAL
5866 || pi->sub_type == BGP_ROUTE_AGGREGATE
5867 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5868
d62a17ae 5869 if (bgp_fibupd_safi(safi))
b54892e0 5870 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5871 }
9514b37d 5872
9bcb3eef 5873 bgp_path_info_reap(dest, pi);
d62a17ae 5874 }
bb86c601
LB
5875}
5876
718e3744 5877/* Delete all kernel routes. */
d62a17ae 5878void bgp_cleanup_routes(struct bgp *bgp)
5879{
5880 afi_t afi;
9bcb3eef 5881 struct bgp_dest *dest;
67009e22 5882 struct bgp_table *table;
d62a17ae 5883
5884 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5885 if (afi == AFI_L2VPN)
5886 continue;
568e10ca 5887 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5888 SAFI_UNICAST);
d62a17ae 5889 /*
5890 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5891 */
5892 if (afi != AFI_L2VPN) {
5893 safi_t safi;
5894 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5895 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5896 dest = bgp_route_next(dest)) {
5897 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5898 if (table != NULL) {
5899 bgp_cleanup_table(bgp, table, safi);
5900 bgp_table_finish(&table);
9bcb3eef
DS
5901 bgp_dest_set_bgp_table_info(dest, NULL);
5902 bgp_dest_unlock_node(dest);
d62a17ae 5903 }
5904 }
5905 safi = SAFI_ENCAP;
9bcb3eef
DS
5906 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5907 dest = bgp_route_next(dest)) {
5908 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5909 if (table != NULL) {
5910 bgp_cleanup_table(bgp, table, safi);
5911 bgp_table_finish(&table);
9bcb3eef
DS
5912 bgp_dest_set_bgp_table_info(dest, NULL);
5913 bgp_dest_unlock_node(dest);
d62a17ae 5914 }
5915 }
5916 }
5917 }
9bcb3eef
DS
5918 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5919 dest = bgp_route_next(dest)) {
5920 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5921 if (table != NULL) {
5922 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5923 bgp_table_finish(&table);
9bcb3eef
DS
5924 bgp_dest_set_bgp_table_info(dest, NULL);
5925 bgp_dest_unlock_node(dest);
d62a17ae 5926 }
bb86c601 5927 }
718e3744 5928}
5929
d62a17ae 5930void bgp_reset(void)
718e3744 5931{
d62a17ae 5932 vty_reset();
5933 bgp_zclient_reset();
5934 access_list_reset();
5935 prefix_list_reset();
718e3744 5936}
6b0655a2 5937
be92fc9f 5938bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5939{
d62a17ae 5940 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5941 && CHECK_FLAG(peer->af_cap[afi][safi],
5942 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5943}
5944
718e3744 5945/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5946 value. */
d62a17ae 5947int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5948 struct bgp_nlri *packet)
5949{
d7c0a89a
QY
5950 uint8_t *pnt;
5951 uint8_t *lim;
d62a17ae 5952 struct prefix p;
5953 int psize;
d62a17ae 5954 afi_t afi;
5955 safi_t safi;
be92fc9f 5956 bool addpath_capable;
d7c0a89a 5957 uint32_t addpath_id;
d62a17ae 5958
d62a17ae 5959 pnt = packet->nlri;
5960 lim = pnt + packet->length;
5961 afi = packet->afi;
5962 safi = packet->safi;
5963 addpath_id = 0;
be92fc9f 5964 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5965
5966 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5967 syntactic validity. If the field is syntactically incorrect,
5968 then the Error Subcode is set to Invalid Network Field. */
5969 for (; pnt < lim; pnt += psize) {
5970 /* Clear prefix structure. */
6006b807 5971 memset(&p, 0, sizeof(p));
d62a17ae 5972
be92fc9f 5973 if (addpath_capable) {
d62a17ae 5974
5975 /* When packet overflow occurs return immediately. */
761ed665 5976 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5977 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5978
a3a850a1 5979 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5980 addpath_id = ntohl(addpath_id);
d62a17ae 5981 pnt += BGP_ADDPATH_ID_LEN;
5982 }
718e3744 5983
d62a17ae 5984 /* Fetch prefix length. */
5985 p.prefixlen = *pnt++;
5986 /* afi/safi validity already verified by caller,
5987 * bgp_update_receive */
5988 p.family = afi2family(afi);
5989
5990 /* Prefix length check. */
5991 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5992 flog_err(
e50f7cfd 5993 EC_BGP_UPDATE_RCV,
14454c9f 5994 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5995 peer->host, p.prefixlen, packet->afi);
513386b5 5996 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5997 }
6b0655a2 5998
d62a17ae 5999 /* Packet size overflow check. */
6000 psize = PSIZE(p.prefixlen);
6001
6002 /* When packet overflow occur return immediately. */
6003 if (pnt + psize > lim) {
af4c2728 6004 flog_err(
e50f7cfd 6005 EC_BGP_UPDATE_RCV,
d62a17ae 6006 "%s [Error] Update packet error (prefix length %d overflows packet)",
6007 peer->host, p.prefixlen);
513386b5 6008 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6009 }
6010
6011 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6012 * prefix for the v4 and v6 afi's and unicast/multicast */
6013 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6014 flog_err(
e50f7cfd 6015 EC_BGP_UPDATE_RCV,
d62a17ae 6016 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6017 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6018 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6019 }
6020
6021 /* Fetch prefix from NLRI packet. */
a85297a7 6022 memcpy(p.u.val, pnt, psize);
d62a17ae 6023
6024 /* Check address. */
6025 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6026 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6027 /* From RFC4271 Section 6.3:
6028 *
6029 * If a prefix in the NLRI field is semantically
6030 * incorrect
6031 * (e.g., an unexpected multicast IP address),
6032 * an error SHOULD
6033 * be logged locally, and the prefix SHOULD be
6034 * ignored.
a4d82a8a 6035 */
af4c2728 6036 flog_err(
e50f7cfd 6037 EC_BGP_UPDATE_RCV,
23d0a753
DA
6038 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6039 peer->host, &p.u.prefix4);
d62a17ae 6040 continue;
6041 }
6042 }
6043
6044 /* Check address. */
6045 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6046 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6047 flog_err(
e50f7cfd 6048 EC_BGP_UPDATE_RCV,
c0d72166
DS
6049 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6050 peer->host, &p.u.prefix6);
d62a17ae 6051
6052 continue;
6053 }
6054 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6055 flog_err(
e50f7cfd 6056 EC_BGP_UPDATE_RCV,
c0d72166
DS
6057 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6058 peer->host, &p.u.prefix6);
d62a17ae 6059
6060 continue;
6061 }
6062 }
6063
6064 /* Normal process. */
6065 if (attr)
367b458c
DS
6066 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6067 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6068 NULL, 0, 0, NULL);
d62a17ae 6069 else
bf0c6163 6070 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6071 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6072 NULL, 0, NULL);
d62a17ae 6073
513386b5
DA
6074 /* Do not send BGP notification twice when maximum-prefix count
6075 * overflow. */
6076 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6077 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6078 }
6079
6080 /* Packet length consistency check. */
6081 if (pnt != lim) {
af4c2728 6082 flog_err(
e50f7cfd 6083 EC_BGP_UPDATE_RCV,
d62a17ae 6084 "%s [Error] Update packet error (prefix length mismatch with total length)",
6085 peer->host);
513386b5 6086 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6087 }
6b0655a2 6088
513386b5 6089 return BGP_NLRI_PARSE_OK;
718e3744 6090}
6091
d62a17ae 6092static struct bgp_static *bgp_static_new(void)
718e3744 6093{
d62a17ae 6094 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6095}
6096
d62a17ae 6097static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6098{
0a22ddfb 6099 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6100 route_map_counter_decrement(bgp_static->rmap.map);
6101
c1aa9e7f
PG
6102 if (bgp_static->prd_pretty)
6103 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6104 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6105 XFREE(MTYPE_BGP_STATIC, bgp_static);
6106}
6107
5f040085 6108void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6109 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6110{
9bcb3eef 6111 struct bgp_dest *dest;
40381db7 6112 struct bgp_path_info *pi;
4b7e6066 6113 struct bgp_path_info *new;
40381db7 6114 struct bgp_path_info rmap_path;
d62a17ae 6115 struct attr attr;
6116 struct attr *attr_new;
b68885f9 6117 route_map_result_t ret;
49e5a4a0 6118#ifdef ENABLE_BGP_VNC
d62a17ae 6119 int vnc_implicit_withdraw = 0;
65efcfce 6120#endif
fee0f4c6 6121
d62a17ae 6122 assert(bgp_static);
dd8103a9 6123
9bcb3eef 6124 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6125
0f05ea43 6126 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6127
d62a17ae 6128 attr.nexthop = bgp_static->igpnexthop;
6129 attr.med = bgp_static->igpmetric;
6130 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6131
7226bc40
TA
6132 if (afi == AFI_IP)
6133 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6134
97a52c82
DA
6135 if (bgp_static->igpmetric)
6136 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6137
d62a17ae 6138 if (bgp_static->atomic)
6139 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6140
d62a17ae 6141 /* Store label index, if required. */
6142 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6143 attr.label_index = bgp_static->label_index;
6144 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6145 }
718e3744 6146
d62a17ae 6147 /* Apply route-map. */
6148 if (bgp_static->rmap.name) {
6149 struct attr attr_tmp = attr;
80ced710 6150
6006b807 6151 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6152 rmap_path.peer = bgp->peer_self;
6153 rmap_path.attr = &attr_tmp;
fee0f4c6 6154
d62a17ae 6155 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6156
1782514f 6157 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6158
d62a17ae 6159 bgp->peer_self->rmap_type = 0;
718e3744 6160
d62a17ae 6161 if (ret == RMAP_DENYMATCH) {
6162 /* Free uninterned attribute. */
6163 bgp_attr_flush(&attr_tmp);
718e3744 6164
d62a17ae 6165 /* Unintern original. */
6166 aspath_unintern(&attr.aspath);
6167 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6168 bgp_dest_unlock_node(dest);
d62a17ae 6169 return;
6170 }
7f323236 6171
637e5ba4 6172 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6173 bgp_attr_add_gshut_community(&attr_tmp);
6174
d62a17ae 6175 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6176 } else {
6177
637e5ba4 6178 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6179 bgp_attr_add_gshut_community(&attr);
6180
d62a17ae 6181 attr_new = bgp_attr_intern(&attr);
7f323236 6182 }
718e3744 6183
9bcb3eef 6184 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6185 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6186 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6187 break;
6188
40381db7
DS
6189 if (pi) {
6190 if (attrhash_cmp(pi->attr, attr_new)
6191 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6192 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6193 bgp_dest_unlock_node(dest);
d62a17ae 6194 bgp_attr_unintern(&attr_new);
6195 aspath_unintern(&attr.aspath);
6196 return;
6197 } else {
6198 /* The attribute is changed. */
9bcb3eef 6199 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6200
6201 /* Rewrite BGP route information. */
40381db7 6202 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6203 bgp_path_info_restore(dest, pi);
d62a17ae 6204 else
40381db7 6205 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6206#ifdef ENABLE_BGP_VNC
d62a17ae 6207 if ((afi == AFI_IP || afi == AFI_IP6)
6208 && (safi == SAFI_UNICAST)) {
40381db7 6209 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6210 /*
6211 * Implicit withdraw case.
40381db7 6212 * We have to do this before pi is
d62a17ae 6213 * changed
6214 */
6215 ++vnc_implicit_withdraw;
40381db7 6216 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6217 vnc_import_bgp_exterior_del_route(
40381db7 6218 bgp, p, pi);
d62a17ae 6219 }
6220 }
65efcfce 6221#endif
40381db7
DS
6222 bgp_attr_unintern(&pi->attr);
6223 pi->attr = attr_new;
083ec940 6224 pi->uptime = monotime(NULL);
49e5a4a0 6225#ifdef ENABLE_BGP_VNC
d62a17ae 6226 if ((afi == AFI_IP || afi == AFI_IP6)
6227 && (safi == SAFI_UNICAST)) {
6228 if (vnc_implicit_withdraw) {
40381db7 6229 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6230 vnc_import_bgp_exterior_add_route(
40381db7 6231 bgp, p, pi);
d62a17ae 6232 }
6233 }
65efcfce 6234#endif
718e3744 6235
d62a17ae 6236 /* Nexthop reachability check. */
892fedb6 6237 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6238 && (safi == SAFI_UNICAST
6239 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6240
6241 struct bgp *bgp_nexthop = bgp;
6242
40381db7
DS
6243 if (pi->extra && pi->extra->bgp_orig)
6244 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6245
6246 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6247 afi, safi, pi, NULL,
654a5978 6248 0, p))
9bcb3eef 6249 bgp_path_info_set_flag(dest, pi,
18ee8310 6250 BGP_PATH_VALID);
d62a17ae 6251 else {
6252 if (BGP_DEBUG(nht, NHT)) {
6253 char buf1[INET6_ADDRSTRLEN];
6254 inet_ntop(p->family,
6255 &p->u.prefix, buf1,
07380148 6256 sizeof(buf1));
d62a17ae 6257 zlog_debug(
6258 "%s(%s): Route not in table, not advertising",
15569c58 6259 __func__, buf1);
d62a17ae 6260 }
18ee8310 6261 bgp_path_info_unset_flag(
9bcb3eef 6262 dest, pi, BGP_PATH_VALID);
d62a17ae 6263 }
6264 } else {
6265 /* Delete the NHT structure if any, if we're
6266 * toggling between
6267 * enabling/disabling import check. We
6268 * deregister the route
6269 * from NHT to avoid overloading NHT and the
6270 * process interaction
6271 */
40381db7 6272 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6273 bgp_path_info_set_flag(dest, pi,
6274 BGP_PATH_VALID);
d62a17ae 6275 }
6276 /* Process change. */
40381db7 6277 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6278 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6279
6280 if (SAFI_UNICAST == safi
6281 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6282 || bgp->inst_type
6283 == BGP_INSTANCE_TYPE_DEFAULT)) {
6284 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6285 pi);
ddb5b488
PZ
6286 }
6287
9bcb3eef 6288 bgp_dest_unlock_node(dest);
d62a17ae 6289 aspath_unintern(&attr.aspath);
6290 return;
6291 }
718e3744 6292 }
718e3744 6293
d62a17ae 6294 /* Make new BGP info. */
6295 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6296 attr_new, dest);
d62a17ae 6297 /* Nexthop reachability check. */
892fedb6 6298 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6299 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6300 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6301 p))
9bcb3eef 6302 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6303 else {
6304 if (BGP_DEBUG(nht, NHT)) {
6305 char buf1[INET6_ADDRSTRLEN];
07380148 6306
d62a17ae 6307 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6308 sizeof(buf1));
d62a17ae 6309 zlog_debug(
6310 "%s(%s): Route not in table, not advertising",
15569c58 6311 __func__, buf1);
d62a17ae 6312 }
9bcb3eef 6313 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6314 }
6315 } else {
6316 /* Delete the NHT structure if any, if we're toggling between
6317 * enabling/disabling import check. We deregister the route
6318 * from NHT to avoid overloading NHT and the process interaction
6319 */
6320 bgp_unlink_nexthop(new);
6321
9bcb3eef 6322 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6323 }
078430f6 6324
d62a17ae 6325 /* Aggregate address increment. */
6326 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6327
d62a17ae 6328 /* Register new BGP information. */
9bcb3eef 6329 bgp_path_info_add(dest, new);
718e3744 6330
d62a17ae 6331 /* route_node_get lock */
9bcb3eef 6332 bgp_dest_unlock_node(dest);
d62a17ae 6333
6334 /* Process change. */
9bcb3eef 6335 bgp_process(bgp, dest, afi, safi);
d62a17ae 6336
ddb5b488
PZ
6337 if (SAFI_UNICAST == safi
6338 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6339 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6340 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6341 }
6342
d62a17ae 6343 /* Unintern original. */
6344 aspath_unintern(&attr.aspath);
718e3744 6345}
6346
5f040085 6347void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6348 safi_t safi)
718e3744 6349{
9bcb3eef 6350 struct bgp_dest *dest;
40381db7 6351 struct bgp_path_info *pi;
718e3744 6352
9bcb3eef 6353 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6354
d62a17ae 6355 /* Check selected route and self inserted route. */
9bcb3eef 6356 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6357 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6358 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6359 break;
6360
6361 /* Withdraw static BGP route from routing table. */
40381db7 6362 if (pi) {
ddb5b488
PZ
6363 if (SAFI_UNICAST == safi
6364 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6365 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6366 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6367 }
40381db7
DS
6368 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6369 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6370 bgp_path_info_delete(dest, pi);
6371 bgp_process(bgp, dest, afi, safi);
d62a17ae 6372 }
718e3744 6373
d62a17ae 6374 /* Unlock bgp_node_lookup. */
9bcb3eef 6375 bgp_dest_unlock_node(dest);
718e3744 6376}
6377
137446f9
LB
6378/*
6379 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6380 */
5f040085 6381static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6382 afi_t afi, safi_t safi,
6383 struct prefix_rd *prd)
718e3744 6384{
9bcb3eef 6385 struct bgp_dest *dest;
40381db7 6386 struct bgp_path_info *pi;
718e3744 6387
9bcb3eef 6388 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6389
d62a17ae 6390 /* Check selected route and self inserted route. */
9bcb3eef 6391 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6392 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6393 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6394 break;
718e3744 6395
d62a17ae 6396 /* Withdraw static BGP route from routing table. */
40381db7 6397 if (pi) {
49e5a4a0 6398#ifdef ENABLE_BGP_VNC
d62a17ae 6399 rfapiProcessWithdraw(
40381db7 6400 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6401 1); /* Kill, since it is an administrative change */
65efcfce 6402#endif
ddb5b488
PZ
6403 if (SAFI_MPLS_VPN == safi
6404 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6405 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6406 }
40381db7 6407 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6408 bgp_path_info_delete(dest, pi);
6409 bgp_process(bgp, dest, afi, safi);
d62a17ae 6410 }
718e3744 6411
d62a17ae 6412 /* Unlock bgp_node_lookup. */
9bcb3eef 6413 bgp_dest_unlock_node(dest);
718e3744 6414}
6415
5f040085 6416static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6417 struct bgp_static *bgp_static, afi_t afi,
6418 safi_t safi)
137446f9 6419{
9bcb3eef 6420 struct bgp_dest *dest;
4b7e6066 6421 struct bgp_path_info *new;
d62a17ae 6422 struct attr *attr_new;
6423 struct attr attr = {0};
40381db7 6424 struct bgp_path_info *pi;
49e5a4a0 6425#ifdef ENABLE_BGP_VNC
d62a17ae 6426 mpls_label_t label = 0;
65efcfce 6427#endif
d7c0a89a 6428 uint32_t num_labels = 0;
137446f9 6429
d62a17ae 6430 assert(bgp_static);
137446f9 6431
b57ba6d2
MK
6432 if (bgp_static->label != MPLS_INVALID_LABEL)
6433 num_labels = 1;
9bcb3eef
DS
6434 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6435 &bgp_static->prd);
137446f9 6436
0f05ea43 6437 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6438
d62a17ae 6439 attr.nexthop = bgp_static->igpnexthop;
6440 attr.med = bgp_static->igpmetric;
6441 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6442
d62a17ae 6443 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6444 || (safi == SAFI_ENCAP)) {
6445 if (afi == AFI_IP) {
6446 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6447 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6448 }
6449 }
6450 if (afi == AFI_L2VPN) {
b04c1e99
IR
6451 if (bgp_static->gatewayIp.family == AF_INET) {
6452 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6453 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6454 &bgp_static->gatewayIp.u.prefix4,
6455 IPV4_MAX_BYTELEN);
b04c1e99
IR
6456 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6457 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6458 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6459 &bgp_static->gatewayIp.u.prefix6,
6460 IPV6_MAX_BYTELEN);
b04c1e99 6461 }
0a50c248 6462 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6463 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6464 struct bgp_encap_type_vxlan bet;
6006b807 6465 memset(&bet, 0, sizeof(bet));
3714a385 6466 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6467 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6468 }
6469 if (bgp_static->router_mac) {
6470 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6471 }
6472 }
6473 /* Apply route-map. */
6474 if (bgp_static->rmap.name) {
6475 struct attr attr_tmp = attr;
40381db7 6476 struct bgp_path_info rmap_path;
b68885f9 6477 route_map_result_t ret;
137446f9 6478
40381db7
DS
6479 rmap_path.peer = bgp->peer_self;
6480 rmap_path.attr = &attr_tmp;
137446f9 6481
d62a17ae 6482 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6483
1782514f 6484 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6485
d62a17ae 6486 bgp->peer_self->rmap_type = 0;
137446f9 6487
d62a17ae 6488 if (ret == RMAP_DENYMATCH) {
6489 /* Free uninterned attribute. */
6490 bgp_attr_flush(&attr_tmp);
137446f9 6491
d62a17ae 6492 /* Unintern original. */
6493 aspath_unintern(&attr.aspath);
6494 bgp_static_withdraw_safi(bgp, p, afi, safi,
6495 &bgp_static->prd);
bbc52106 6496 bgp_dest_unlock_node(dest);
d62a17ae 6497 return;
6498 }
137446f9 6499
d62a17ae 6500 attr_new = bgp_attr_intern(&attr_tmp);
6501 } else {
6502 attr_new = bgp_attr_intern(&attr);
6503 }
137446f9 6504
9bcb3eef 6505 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6506 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6507 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6508 break;
6509
40381db7 6510 if (pi) {
40381db7 6511 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6512 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6513 bgp_dest_unlock_node(dest);
d62a17ae 6514 bgp_attr_unintern(&attr_new);
6515 aspath_unintern(&attr.aspath);
6516 return;
6517 } else {
6518 /* The attribute is changed. */
9bcb3eef 6519 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6520
6521 /* Rewrite BGP route information. */
40381db7 6522 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6523 bgp_path_info_restore(dest, pi);
d62a17ae 6524 else
40381db7
DS
6525 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6526 bgp_attr_unintern(&pi->attr);
6527 pi->attr = attr_new;
083ec940 6528 pi->uptime = monotime(NULL);
49e5a4a0 6529#ifdef ENABLE_BGP_VNC
40381db7
DS
6530 if (pi->extra)
6531 label = decode_label(&pi->extra->label[0]);
65efcfce 6532#endif
137446f9 6533
d62a17ae 6534 /* Process change. */
40381db7 6535 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6536 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6537
6538 if (SAFI_MPLS_VPN == safi
6539 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6540 vpn_leak_to_vrf_update(bgp, pi,
6541 &bgp_static->prd);
ddb5b488 6542 }
49e5a4a0 6543#ifdef ENABLE_BGP_VNC
40381db7
DS
6544 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6545 pi->attr, afi, safi, pi->type,
6546 pi->sub_type, &label);
65efcfce 6547#endif
9bcb3eef 6548 bgp_dest_unlock_node(dest);
d62a17ae 6549 aspath_unintern(&attr.aspath);
6550 return;
6551 }
6552 }
137446f9
LB
6553
6554
d62a17ae 6555 /* Make new BGP info. */
6556 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6557 attr_new, dest);
1defdda8 6558 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6559 bgp_path_info_extra_get(new);
b57ba6d2
MK
6560 if (num_labels) {
6561 new->extra->label[0] = bgp_static->label;
6562 new->extra->num_labels = num_labels;
6563 }
49e5a4a0 6564#ifdef ENABLE_BGP_VNC
d62a17ae 6565 label = decode_label(&bgp_static->label);
65efcfce 6566#endif
137446f9 6567
d62a17ae 6568 /* Aggregate address increment. */
6569 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6570
d62a17ae 6571 /* Register new BGP information. */
9bcb3eef 6572 bgp_path_info_add(dest, new);
d62a17ae 6573 /* route_node_get lock */
9bcb3eef 6574 bgp_dest_unlock_node(dest);
137446f9 6575
d62a17ae 6576 /* Process change. */
9bcb3eef 6577 bgp_process(bgp, dest, afi, safi);
137446f9 6578
ddb5b488
PZ
6579 if (SAFI_MPLS_VPN == safi
6580 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6581 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6582 }
49e5a4a0 6583#ifdef ENABLE_BGP_VNC
d62a17ae 6584 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6585 safi, new->type, new->sub_type, &label);
65efcfce
LB
6586#endif
6587
d62a17ae 6588 /* Unintern original. */
6589 aspath_unintern(&attr.aspath);
137446f9
LB
6590}
6591
718e3744 6592/* Configure static BGP network. When user don't run zebra, static
6593 route should be installed as valid. */
585f1adc
IR
6594static int bgp_static_set(struct vty *vty, const char *negate,
6595 const char *ip_str, afi_t afi, safi_t safi,
6596 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6597{
585f1adc
IR
6598 VTY_DECLVAR_CONTEXT(bgp, bgp);
6599 int ret;
d62a17ae 6600 struct prefix p;
6601 struct bgp_static *bgp_static;
9bcb3eef 6602 struct bgp_dest *dest;
d7c0a89a 6603 uint8_t need_update = 0;
d62a17ae 6604
585f1adc
IR
6605 /* Convert IP prefix string to struct prefix. */
6606 ret = str2prefix(ip_str, &p);
6607 if (!ret) {
6608 vty_out(vty, "%% Malformed prefix\n");
6609 return CMD_WARNING_CONFIG_FAILED;
6610 }
6611 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6612 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6613 return CMD_WARNING_CONFIG_FAILED;
6614 }
6615
d62a17ae 6616 apply_mask(&p);
718e3744 6617
e2a86ad9 6618 if (negate) {
718e3744 6619
e2a86ad9 6620 /* Set BGP static route configuration. */
9bcb3eef 6621 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6622
9bcb3eef 6623 if (!dest) {
585f1adc
IR
6624 vty_out(vty, "%% Can't find static route specified\n");
6625 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6626 }
6627
9bcb3eef 6628 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6629
e2a86ad9
DS
6630 if ((label_index != BGP_INVALID_LABEL_INDEX)
6631 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6632 vty_out(vty,
6633 "%% label-index doesn't match static route\n");
70d9b134 6634 bgp_dest_unlock_node(dest);
585f1adc 6635 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6636 }
d62a17ae 6637
e2a86ad9
DS
6638 if ((rmap && bgp_static->rmap.name)
6639 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6640 vty_out(vty,
6641 "%% route-map name doesn't match static route\n");
70d9b134 6642 bgp_dest_unlock_node(dest);
585f1adc 6643 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6644 }
718e3744 6645
e2a86ad9
DS
6646 /* Update BGP RIB. */
6647 if (!bgp_static->backdoor)
6648 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6649
e2a86ad9
DS
6650 /* Clear configuration. */
6651 bgp_static_free(bgp_static);
9bcb3eef
DS
6652 bgp_dest_set_bgp_static_info(dest, NULL);
6653 bgp_dest_unlock_node(dest);
6654 bgp_dest_unlock_node(dest);
e2a86ad9 6655 } else {
718e3744 6656
e2a86ad9 6657 /* Set BGP static route configuration. */
9bcb3eef
DS
6658 dest = bgp_node_get(bgp->route[afi][safi], &p);
6659 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6660 if (bgp_static) {
e2a86ad9 6661 /* Configuration change. */
e2a86ad9
DS
6662 /* Label index cannot be changed. */
6663 if (bgp_static->label_index != label_index) {
585f1adc 6664 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6665 bgp_dest_unlock_node(dest);
585f1adc 6666 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6667 }
d62a17ae 6668
e2a86ad9 6669 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6670 if (bgp_static->valid
6671 && bgp_static->backdoor != backdoor)
e2a86ad9 6672 need_update = 1;
718e3744 6673
e2a86ad9 6674 bgp_static->backdoor = backdoor;
718e3744 6675
e2a86ad9 6676 if (rmap) {
0a22ddfb
QY
6677 XFREE(MTYPE_ROUTE_MAP_NAME,
6678 bgp_static->rmap.name);
b4897fa5 6679 route_map_counter_decrement(
6680 bgp_static->rmap.map);
e2a86ad9
DS
6681 bgp_static->rmap.name =
6682 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6683 bgp_static->rmap.map =
6684 route_map_lookup_by_name(rmap);
b4897fa5 6685 route_map_counter_increment(
6686 bgp_static->rmap.map);
e2a86ad9 6687 } else {
0a22ddfb
QY
6688 XFREE(MTYPE_ROUTE_MAP_NAME,
6689 bgp_static->rmap.name);
b4897fa5 6690 route_map_counter_decrement(
6691 bgp_static->rmap.map);
e2a86ad9
DS
6692 bgp_static->rmap.map = NULL;
6693 bgp_static->valid = 0;
6694 }
9bcb3eef 6695 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6696 } else {
6697 /* New configuration. */
6698 bgp_static = bgp_static_new();
6699 bgp_static->backdoor = backdoor;
6700 bgp_static->valid = 0;
6701 bgp_static->igpmetric = 0;
975a328e 6702 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6703 bgp_static->label_index = label_index;
718e3744 6704
e2a86ad9 6705 if (rmap) {
0a22ddfb
QY
6706 XFREE(MTYPE_ROUTE_MAP_NAME,
6707 bgp_static->rmap.name);
b4897fa5 6708 route_map_counter_decrement(
6709 bgp_static->rmap.map);
e2a86ad9
DS
6710 bgp_static->rmap.name =
6711 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6712 bgp_static->rmap.map =
6713 route_map_lookup_by_name(rmap);
b4897fa5 6714 route_map_counter_increment(
6715 bgp_static->rmap.map);
e2a86ad9 6716 }
9bcb3eef 6717 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6718 }
d62a17ae 6719
e2a86ad9
DS
6720 bgp_static->valid = 1;
6721 if (need_update)
6722 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6723
e2a86ad9
DS
6724 if (!bgp_static->backdoor)
6725 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6726 }
d62a17ae 6727
585f1adc 6728 return CMD_SUCCESS;
d62a17ae 6729}
6730
6731void bgp_static_add(struct bgp *bgp)
6732{
6733 afi_t afi;
6734 safi_t safi;
9bcb3eef
DS
6735 struct bgp_dest *dest;
6736 struct bgp_dest *rm;
d62a17ae 6737 struct bgp_table *table;
6738 struct bgp_static *bgp_static;
6739
47fc6261 6740 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6741 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6742 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6743 dest = bgp_route_next(dest)) {
6744 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6745 continue;
ea47320b 6746
05c7a1cc
QY
6747 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6748 || (safi == SAFI_EVPN)) {
9bcb3eef 6749 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6750
6751 for (rm = bgp_table_top(table); rm;
6752 rm = bgp_route_next(rm)) {
a78beeb5 6753 bgp_static =
9bcb3eef 6754 bgp_dest_get_bgp_static_info(
5a8ba9fc 6755 rm);
9bcb3eef
DS
6756 bgp_static_update_safi(
6757 bgp, bgp_dest_get_prefix(rm),
6758 bgp_static, afi, safi);
d62a17ae 6759 }
05c7a1cc 6760 } else {
5a8ba9fc 6761 bgp_static_update(
9bcb3eef
DS
6762 bgp, bgp_dest_get_prefix(dest),
6763 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6764 safi);
ea47320b 6765 }
05c7a1cc 6766 }
47fc6261 6767 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6768}
6769
718e3744 6770/* Called from bgp_delete(). Delete all static routes from the BGP
6771 instance. */
d62a17ae 6772void bgp_static_delete(struct bgp *bgp)
6773{
6774 afi_t afi;
6775 safi_t safi;
9bcb3eef
DS
6776 struct bgp_dest *dest;
6777 struct bgp_dest *rm;
d62a17ae 6778 struct bgp_table *table;
6779 struct bgp_static *bgp_static;
6780
05c7a1cc 6781 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6782 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6783 dest = bgp_route_next(dest)) {
6784 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6785 continue;
ea47320b 6786
05c7a1cc
QY
6787 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6788 || (safi == SAFI_EVPN)) {
9bcb3eef 6789 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6790
6791 for (rm = bgp_table_top(table); rm;
6792 rm = bgp_route_next(rm)) {
a78beeb5 6793 bgp_static =
9bcb3eef 6794 bgp_dest_get_bgp_static_info(
5a8ba9fc 6795 rm);
c7d14ba6
PG
6796 if (!bgp_static)
6797 continue;
6798
05c7a1cc 6799 bgp_static_withdraw_safi(
9bcb3eef 6800 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6801 AFI_IP, safi,
6802 (struct prefix_rd *)
9bcb3eef
DS
6803 bgp_dest_get_prefix(
6804 dest));
ea47320b 6805 bgp_static_free(bgp_static);
811c6797 6806 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6807 NULL);
811c6797 6808 bgp_dest_unlock_node(rm);
d62a17ae 6809 }
05c7a1cc 6810 } else {
9bcb3eef 6811 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6812 bgp_static_withdraw(bgp,
9bcb3eef 6813 bgp_dest_get_prefix(dest),
b54892e0 6814 afi, safi);
05c7a1cc 6815 bgp_static_free(bgp_static);
9bcb3eef
DS
6816 bgp_dest_set_bgp_static_info(dest, NULL);
6817 bgp_dest_unlock_node(dest);
ea47320b 6818 }
05c7a1cc 6819 }
d62a17ae 6820}
6821
6822void bgp_static_redo_import_check(struct bgp *bgp)
6823{
6824 afi_t afi;
6825 safi_t safi;
9bcb3eef
DS
6826 struct bgp_dest *dest;
6827 struct bgp_dest *rm;
d62a17ae 6828 struct bgp_table *table;
6829 struct bgp_static *bgp_static;
6830
6831 /* Use this flag to force reprocessing of the route */
892fedb6 6832 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6833 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6834 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6835 dest = bgp_route_next(dest)) {
6836 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6837 continue;
ea47320b 6838
05c7a1cc
QY
6839 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6840 || (safi == SAFI_EVPN)) {
9bcb3eef 6841 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6842
6843 for (rm = bgp_table_top(table); rm;
6844 rm = bgp_route_next(rm)) {
a78beeb5 6845 bgp_static =
9bcb3eef 6846 bgp_dest_get_bgp_static_info(
5a8ba9fc 6847 rm);
9bcb3eef
DS
6848 bgp_static_update_safi(
6849 bgp, bgp_dest_get_prefix(rm),
6850 bgp_static, afi, safi);
d62a17ae 6851 }
05c7a1cc 6852 } else {
9bcb3eef
DS
6853 bgp_static = bgp_dest_get_bgp_static_info(dest);
6854 bgp_static_update(bgp,
6855 bgp_dest_get_prefix(dest),
6856 bgp_static, afi, safi);
ea47320b 6857 }
05c7a1cc
QY
6858 }
6859 }
892fedb6 6860 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6861}
6862
6863static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6864 safi_t safi)
6865{
6866 struct bgp_table *table;
9bcb3eef 6867 struct bgp_dest *dest;
40381db7 6868 struct bgp_path_info *pi;
d62a17ae 6869
dfb6fd1d
NT
6870 /* Do not install the aggregate route if BGP is in the
6871 * process of termination.
6872 */
892fedb6
DA
6873 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6874 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6875 return;
6876
d62a17ae 6877 table = bgp->rib[afi][safi];
9bcb3eef
DS
6878 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6879 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6880 if (pi->peer == bgp->peer_self
6881 && ((pi->type == ZEBRA_ROUTE_BGP
6882 && pi->sub_type == BGP_ROUTE_STATIC)
6883 || (pi->type != ZEBRA_ROUTE_BGP
6884 && pi->sub_type
d62a17ae 6885 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6886 bgp_aggregate_decrement(
6887 bgp, bgp_dest_get_prefix(dest), pi, afi,
6888 safi);
40381db7 6889 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6890 bgp_path_info_delete(dest, pi);
6891 bgp_process(bgp, dest, afi, safi);
d62a17ae 6892 }
6893 }
6894 }
ad4cbda1 6895}
6896
6897/*
6898 * Purge all networks and redistributed routes from routing table.
6899 * Invoked upon the instance going down.
6900 */
d62a17ae 6901void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6902{
d62a17ae 6903 afi_t afi;
6904 safi_t safi;
ad4cbda1 6905
05c7a1cc
QY
6906 FOREACH_AFI_SAFI (afi, safi)
6907 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6908}
6909
137446f9
LB
6910/*
6911 * gpz 110624
6912 * Currently this is used to set static routes for VPN and ENCAP.
6913 * I think it can probably be factored with bgp_static_set.
6914 */
d62a17ae 6915int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6916 const char *ip_str, const char *rd_str,
6917 const char *label_str, const char *rmap_str,
6918 int evpn_type, const char *esi, const char *gwip,
6919 const char *ethtag, const char *routermac)
6920{
6921 VTY_DECLVAR_CONTEXT(bgp, bgp);
6922 int ret;
6923 struct prefix p;
6924 struct prefix_rd prd;
9bcb3eef
DS
6925 struct bgp_dest *pdest;
6926 struct bgp_dest *dest;
d62a17ae 6927 struct bgp_table *table;
6928 struct bgp_static *bgp_static;
6929 mpls_label_t label = MPLS_INVALID_LABEL;
6930 struct prefix gw_ip;
6931
6932 /* validate ip prefix */
6933 ret = str2prefix(ip_str, &p);
6934 if (!ret) {
6935 vty_out(vty, "%% Malformed prefix\n");
6936 return CMD_WARNING_CONFIG_FAILED;
6937 }
6938 apply_mask(&p);
6939 if ((afi == AFI_L2VPN)
6940 && (bgp_build_evpn_prefix(evpn_type,
6941 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6942 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6943 return CMD_WARNING_CONFIG_FAILED;
6944 }
718e3744 6945
d62a17ae 6946 ret = str2prefix_rd(rd_str, &prd);
6947 if (!ret) {
6948 vty_out(vty, "%% Malformed rd\n");
6949 return CMD_WARNING_CONFIG_FAILED;
6950 }
718e3744 6951
d62a17ae 6952 if (label_str) {
6953 unsigned long label_val;
6954 label_val = strtoul(label_str, NULL, 10);
6955 encode_label(label_val, &label);
6956 }
9bedbb1e 6957
d62a17ae 6958 if (safi == SAFI_EVPN) {
6959 if (esi && str2esi(esi, NULL) == 0) {
6960 vty_out(vty, "%% Malformed ESI\n");
6961 return CMD_WARNING_CONFIG_FAILED;
6962 }
6963 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6964 vty_out(vty, "%% Malformed Router MAC\n");
6965 return CMD_WARNING_CONFIG_FAILED;
6966 }
6967 if (gwip) {
6006b807 6968 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6969 ret = str2prefix(gwip, &gw_ip);
6970 if (!ret) {
6971 vty_out(vty, "%% Malformed GatewayIp\n");
6972 return CMD_WARNING_CONFIG_FAILED;
6973 }
6974 if ((gw_ip.family == AF_INET
3714a385 6975 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6976 (struct prefix_evpn *)&p))
6977 || (gw_ip.family == AF_INET6
3714a385 6978 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6979 (struct prefix_evpn *)&p))) {
6980 vty_out(vty,
6981 "%% GatewayIp family differs with IP prefix\n");
6982 return CMD_WARNING_CONFIG_FAILED;
6983 }
6984 }
6985 }
9bcb3eef
DS
6986 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6987 if (!bgp_dest_has_bgp_path_info_data(pdest))
6988 bgp_dest_set_bgp_table_info(pdest,
67009e22 6989 bgp_table_init(bgp, afi, safi));
9bcb3eef 6990 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6991
9bcb3eef 6992 dest = bgp_node_get(table, &p);
d62a17ae 6993
9bcb3eef 6994 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6995 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6996 bgp_dest_unlock_node(dest);
d62a17ae 6997 } else {
6998 /* New configuration. */
6999 bgp_static = bgp_static_new();
7000 bgp_static->backdoor = 0;
7001 bgp_static->valid = 0;
7002 bgp_static->igpmetric = 0;
975a328e 7003 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7004 bgp_static->label = label;
7005 bgp_static->prd = prd;
7006
c1aa9e7f
PG
7007 if (rd_str)
7008 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
d62a17ae 7009 if (rmap_str) {
0a22ddfb 7010 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7011 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7012 bgp_static->rmap.name =
7013 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7014 bgp_static->rmap.map =
7015 route_map_lookup_by_name(rmap_str);
b4897fa5 7016 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7017 }
718e3744 7018
d62a17ae 7019 if (safi == SAFI_EVPN) {
7020 if (esi) {
7021 bgp_static->eth_s_id =
7022 XCALLOC(MTYPE_ATTR,
0a50c248 7023 sizeof(esi_t));
d62a17ae 7024 str2esi(esi, bgp_static->eth_s_id);
7025 }
7026 if (routermac) {
7027 bgp_static->router_mac =
28328ea9 7028 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7029 (void)prefix_str2mac(routermac,
7030 bgp_static->router_mac);
d62a17ae 7031 }
7032 if (gwip)
7033 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7034 }
9bcb3eef 7035 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7036
d62a17ae 7037 bgp_static->valid = 1;
7038 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7039 }
718e3744 7040
d62a17ae 7041 return CMD_SUCCESS;
718e3744 7042}
7043
7044/* Configure static BGP network. */
d62a17ae 7045int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7046 const char *ip_str, const char *rd_str,
7047 const char *label_str, int evpn_type, const char *esi,
7048 const char *gwip, const char *ethtag)
7049{
7050 VTY_DECLVAR_CONTEXT(bgp, bgp);
7051 int ret;
7052 struct prefix p;
7053 struct prefix_rd prd;
9bcb3eef
DS
7054 struct bgp_dest *pdest;
7055 struct bgp_dest *dest;
d62a17ae 7056 struct bgp_table *table;
7057 struct bgp_static *bgp_static;
7058 mpls_label_t label = MPLS_INVALID_LABEL;
7059
7060 /* Convert IP prefix string to struct prefix. */
7061 ret = str2prefix(ip_str, &p);
7062 if (!ret) {
7063 vty_out(vty, "%% Malformed prefix\n");
7064 return CMD_WARNING_CONFIG_FAILED;
7065 }
7066 apply_mask(&p);
7067 if ((afi == AFI_L2VPN)
7068 && (bgp_build_evpn_prefix(evpn_type,
7069 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7070 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7071 return CMD_WARNING_CONFIG_FAILED;
7072 }
7073 ret = str2prefix_rd(rd_str, &prd);
7074 if (!ret) {
7075 vty_out(vty, "%% Malformed rd\n");
7076 return CMD_WARNING_CONFIG_FAILED;
7077 }
718e3744 7078
d62a17ae 7079 if (label_str) {
7080 unsigned long label_val;
7081 label_val = strtoul(label_str, NULL, 10);
7082 encode_label(label_val, &label);
7083 }
718e3744 7084
9bcb3eef
DS
7085 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7086 if (!bgp_dest_has_bgp_path_info_data(pdest))
7087 bgp_dest_set_bgp_table_info(pdest,
67009e22 7088 bgp_table_init(bgp, afi, safi));
d62a17ae 7089 else
9bcb3eef
DS
7090 bgp_dest_unlock_node(pdest);
7091 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7092
9bcb3eef 7093 dest = bgp_node_lookup(table, &p);
6b0655a2 7094
9bcb3eef 7095 if (dest) {
d62a17ae 7096 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7097
9bcb3eef 7098 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7099 bgp_static_free(bgp_static);
9bcb3eef
DS
7100 bgp_dest_set_bgp_static_info(dest, NULL);
7101 bgp_dest_unlock_node(dest);
7102 bgp_dest_unlock_node(dest);
d62a17ae 7103 } else
7104 vty_out(vty, "%% Can't find the route\n");
7105
7106 return CMD_SUCCESS;
7107}
7108
7109static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7110 const char *rmap_name)
7111{
7112 VTY_DECLVAR_CONTEXT(bgp, bgp);
7113 struct bgp_rmap *rmap;
7114
7115 rmap = &bgp->table_map[afi][safi];
7116 if (rmap_name) {
0a22ddfb 7117 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7118 route_map_counter_decrement(rmap->map);
d62a17ae 7119 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7120 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7121 route_map_counter_increment(rmap->map);
d62a17ae 7122 } else {
0a22ddfb 7123 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7124 route_map_counter_decrement(rmap->map);
d62a17ae 7125 rmap->map = NULL;
7126 }
73ac8160 7127
d62a17ae 7128 if (bgp_fibupd_safi(safi))
7129 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7130
d62a17ae 7131 return CMD_SUCCESS;
73ac8160
DS
7132}
7133
d62a17ae 7134static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7135 const char *rmap_name)
73ac8160 7136{
d62a17ae 7137 VTY_DECLVAR_CONTEXT(bgp, bgp);
7138 struct bgp_rmap *rmap;
73ac8160 7139
d62a17ae 7140 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7141 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7142 route_map_counter_decrement(rmap->map);
d62a17ae 7143 rmap->map = NULL;
73ac8160 7144
d62a17ae 7145 if (bgp_fibupd_safi(safi))
7146 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7147
d62a17ae 7148 return CMD_SUCCESS;
73ac8160
DS
7149}
7150
2b791107 7151void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7152 safi_t safi)
73ac8160 7153{
d62a17ae 7154 if (bgp->table_map[afi][safi].name) {
d62a17ae 7155 vty_out(vty, " table-map %s\n",
7156 bgp->table_map[afi][safi].name);
7157 }
73ac8160
DS
7158}
7159
73ac8160
DS
7160DEFUN (bgp_table_map,
7161 bgp_table_map_cmd,
7162 "table-map WORD",
7163 "BGP table to RIB route download filter\n"
7164 "Name of the route map\n")
7165{
d62a17ae 7166 int idx_word = 1;
7167 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7168 argv[idx_word]->arg);
73ac8160
DS
7169}
7170DEFUN (no_bgp_table_map,
7171 no_bgp_table_map_cmd,
7172 "no table-map WORD",
3a2d747c 7173 NO_STR
73ac8160
DS
7174 "BGP table to RIB route download filter\n"
7175 "Name of the route map\n")
7176{
d62a17ae 7177 int idx_word = 2;
7178 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7179 argv[idx_word]->arg);
73ac8160
DS
7180}
7181
585f1adc
IR
7182DEFPY(bgp_network,
7183 bgp_network_cmd,
7184 "[no] network \
7185 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7186 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7187 backdoor$backdoor}]",
7188 NO_STR
7189 "Specify a network to announce via BGP\n"
7190 "IPv4 prefix\n"
7191 "Network number\n"
7192 "Network mask\n"
7193 "Network mask\n"
7194 "Route-map to modify the attributes\n"
7195 "Name of the route map\n"
7196 "Label index to associate with the prefix\n"
7197 "Label index value\n"
7198 "Specify a BGP backdoor route\n")
7199{
7200 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7201
7202 if (address_str) {
7203 int ret;
718e3744 7204
e2a86ad9 7205 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7206 addr_prefix_str,
7207 sizeof(addr_prefix_str));
e2a86ad9
DS
7208 if (!ret) {
7209 vty_out(vty, "%% Inconsistent address and mask\n");
7210 return CMD_WARNING_CONFIG_FAILED;
7211 }
d62a17ae 7212 }
718e3744 7213
585f1adc
IR
7214 return bgp_static_set(
7215 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7216 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7217 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7218}
7219
585f1adc
IR
7220DEFPY(ipv6_bgp_network,
7221 ipv6_bgp_network_cmd,
7222 "[no] network X:X::X:X/M$prefix \
70dd370f 7223 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7224 NO_STR
7225 "Specify a network to announce via BGP\n"
7226 "IPv6 prefix\n"
7227 "Route-map to modify the attributes\n"
7228 "Name of the route map\n"
7229 "Label index to associate with the prefix\n"
7230 "Label index value\n")
37a87b8f 7231{
585f1adc
IR
7232 return bgp_static_set(
7233 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7234 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7235}
7236
d62a17ae 7237static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7238{
d62a17ae 7239 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7240}
7241
9bea1b4b 7242void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7243{
365ab2e7
RZ
7244 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7245 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7246 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7247 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7248 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7249}
718e3744 7250
365ab2e7
RZ
7251/**
7252 * Helper function to avoid repeated code: prepare variables for a
7253 * `route_map_apply` call.
7254 *
7255 * \returns `true` on route map match, otherwise `false`.
7256 */
7257static bool aggr_suppress_map_test(struct bgp *bgp,
7258 struct bgp_aggregate *aggregate,
7259 struct bgp_path_info *pi)
7260{
7261 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7262 route_map_result_t rmr = RMAP_DENYMATCH;
7263 struct bgp_path_info rmap_path = {};
7264 struct attr attr = {};
7265
7266 /* No route map entries created, just don't match. */
7267 if (aggregate->suppress_map == NULL)
7268 return false;
7269
7270 /* Call route map matching and return result. */
17571c4a 7271 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7272 rmap_path.peer = bgp->peer_self;
7273 rmap_path.attr = &attr;
7274
7275 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7276 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7277 bgp->peer_self->rmap_type = 0;
7278
7279 bgp_attr_flush(&attr);
afb254d7 7280 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7281
7282 return rmr == RMAP_PERMITMATCH;
7283}
7284
4056a5f6
RZ
7285/** Test whether the aggregation has suppressed this path or not. */
7286static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7287 struct bgp_path_info *pi)
7288{
7289 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7290 return false;
7291
7292 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7293}
7294
7295/**
7296 * Suppress this path and keep the reference.
7297 *
7298 * \returns `true` if needs processing otherwise `false`.
7299 */
7300static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7301 struct bgp_path_info *pi)
7302{
7303 struct bgp_path_info_extra *pie;
7304
7305 /* Path is already suppressed by this aggregation. */
7306 if (aggr_suppress_exists(aggregate, pi))
7307 return false;
7308
7309 pie = bgp_path_info_extra_get(pi);
7310
7311 /* This is the first suppression, allocate memory and list it. */
7312 if (pie->aggr_suppressors == NULL)
7313 pie->aggr_suppressors = list_new();
7314
7315 listnode_add(pie->aggr_suppressors, aggregate);
7316
7317 /* Only mark for processing if suppressed. */
7318 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7319 if (BGP_DEBUG(update, UPDATE_OUT))
7320 zlog_debug("aggregate-address suppressing: %pFX",
7321 bgp_dest_get_prefix(pi->net));
7322
4056a5f6
RZ
7323 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7324 return true;
7325 }
7326
7327 return false;
7328}
7329
7330/**
7331 * Unsuppress this path and remove the reference.
7332 *
7333 * \returns `true` if needs processing otherwise `false`.
7334 */
7335static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7336 struct bgp_path_info *pi)
7337{
7338 /* Path wasn't suppressed. */
7339 if (!aggr_suppress_exists(aggregate, pi))
7340 return false;
7341
7342 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7343
7344 /* Unsuppress and free extra memory if last item. */
7345 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7346 if (BGP_DEBUG(update, UPDATE_OUT))
7347 zlog_debug("aggregate-address unsuppressing: %pFX",
7348 bgp_dest_get_prefix(pi->net));
7349
4056a5f6
RZ
7350 list_delete(&pi->extra->aggr_suppressors);
7351 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7352 return true;
7353 }
7354
7355 return false;
7356}
7357
3dc339cd
DA
7358static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7359 struct aspath *aspath,
7360 struct community *comm,
7361 struct ecommunity *ecomm,
7362 struct lcommunity *lcomm)
eaaf8adb
DS
7363{
7364 static struct aspath *ae = NULL;
17571c4a
PG
7365 enum asnotation_mode asnotation;
7366
7367 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7368
7369 if (!ae)
17571c4a 7370 ae = aspath_empty(asnotation);
eaaf8adb 7371
40381db7 7372 if (!pi)
3dc339cd 7373 return false;
eaaf8adb 7374
40381db7 7375 if (origin != pi->attr->origin)
3dc339cd 7376 return false;
eaaf8adb 7377
40381db7 7378 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7379 return false;
29f7d023 7380
9a706b42 7381 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7382 return false;
eaaf8adb 7383
b53e67a3 7384 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7385 return false;
eaaf8adb 7386
1bcf3a96 7387 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7388 return false;
dd18c5a9 7389
40381db7 7390 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7391 return false;
7ce8a8e0 7392
3dc339cd 7393 return true;
eaaf8adb
DS
7394}
7395
5f040085
DS
7396static void bgp_aggregate_install(
7397 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7398 uint8_t origin, struct aspath *aspath, struct community *community,
7399 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7400 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7401{
9bcb3eef 7402 struct bgp_dest *dest;
c701010e 7403 struct bgp_table *table;
6f94b685 7404 struct bgp_path_info *pi, *orig, *new;
20894f50 7405 struct attr *attr;
c701010e
DS
7406
7407 table = bgp->rib[afi][safi];
7408
9bcb3eef 7409 dest = bgp_node_get(table, p);
eaaf8adb 7410
9bcb3eef 7411 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7412 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7413 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7414 break;
7415
6aabb15d
RZ
7416 /*
7417 * If we have paths with different MEDs, then don't install
7418 * (or uninstall) the aggregate route.
7419 */
7420 if (aggregate->match_med && aggregate->med_mismatched)
7421 goto uninstall_aggregate_route;
7422
c701010e 7423 if (aggregate->count > 0) {
eaaf8adb
DS
7424 /*
7425 * If the aggregate information has not changed
7426 * no need to re-install it again.
7427 */
6f94b685 7428 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7429 ecommunity, lcommunity)) {
9bcb3eef 7430 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7431
7432 if (aspath)
7433 aspath_free(aspath);
7434 if (community)
3c1f53de 7435 community_free(&community);
3da2cc32
DS
7436 if (ecommunity)
7437 ecommunity_free(&ecommunity);
dd18c5a9
DS
7438 if (lcommunity)
7439 lcommunity_free(&lcommunity);
eaaf8adb
DS
7440
7441 return;
7442 }
7443
7444 /*
7445 * Mark the old as unusable
7446 */
40381db7 7447 if (pi)
9bcb3eef 7448 bgp_path_info_delete(dest, pi);
eaaf8adb 7449
20894f50
DA
7450 attr = bgp_attr_aggregate_intern(
7451 bgp, origin, aspath, community, ecommunity, lcommunity,
7452 aggregate, atomic_aggregate, p);
7453
7454 if (!attr) {
e11791f4
DA
7455 aspath_free(aspath);
7456 community_free(&community);
7457 ecommunity_free(&ecommunity);
7458 lcommunity_free(&lcommunity);
8c0044f3 7459 bgp_dest_unlock_node(dest);
20894f50 7460 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7461 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7462 zlog_debug("%s: %pFX null attribute", __func__,
7463 p);
20894f50
DA
7464 return;
7465 }
7466
3da2cc32 7467 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7468 bgp->peer_self, attr, dest);
20894f50 7469
1defdda8 7470 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7471
9bcb3eef
DS
7472 bgp_path_info_add(dest, new);
7473 bgp_process(bgp, dest, afi, safi);
c701010e 7474 } else {
6aabb15d 7475 uninstall_aggregate_route:
6f94b685 7476 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7477 if (pi->peer == bgp->peer_self
7478 && pi->type == ZEBRA_ROUTE_BGP
7479 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7480 break;
7481
7482 /* Withdraw static BGP route from routing table. */
40381db7 7483 if (pi) {
9bcb3eef
DS
7484 bgp_path_info_delete(dest, pi);
7485 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7486 }
7487 }
7488
9bcb3eef 7489 bgp_dest_unlock_node(dest);
c701010e
DS
7490}
7491
6aabb15d
RZ
7492/**
7493 * Check if the current path has different MED than other known paths.
7494 *
7495 * \returns `true` if the MED matched the others else `false`.
7496 */
7497static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7498 struct bgp *bgp, struct bgp_path_info *pi)
7499{
7500 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7501
7502 /* This is the first route being analyzed. */
7503 if (!aggregate->med_initialized) {
7504 aggregate->med_initialized = true;
7505 aggregate->med_mismatched = false;
7506 aggregate->med_matched_value = cur_med;
7507 } else {
7508 /* Check if routes with different MED showed up. */
7509 if (cur_med != aggregate->med_matched_value)
7510 aggregate->med_mismatched = true;
7511 }
7512
7513 return !aggregate->med_mismatched;
7514}
7515
7516/**
7517 * Initializes and tests all routes in the aggregate address path for MED
7518 * values.
7519 *
7520 * \returns `true` if all MEDs are the same otherwise `false`.
7521 */
7522static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7523 struct bgp *bgp, const struct prefix *p,
7524 afi_t afi, safi_t safi)
7525{
7526 struct bgp_table *table = bgp->rib[afi][safi];
7527 const struct prefix *dest_p;
7528 struct bgp_dest *dest, *top;
7529 struct bgp_path_info *pi;
7530 bool med_matched = true;
7531
7532 aggregate->med_initialized = false;
7533
7534 top = bgp_node_get(table, p);
7535 for (dest = bgp_node_get(table, p); dest;
7536 dest = bgp_route_next_until(dest, top)) {
7537 dest_p = bgp_dest_get_prefix(dest);
7538 if (dest_p->prefixlen <= p->prefixlen)
7539 continue;
7540
7541 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7542 if (BGP_PATH_HOLDDOWN(pi))
7543 continue;
7544 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7545 continue;
7546 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7547 med_matched = false;
7548 break;
7549 }
7550 }
7551 if (!med_matched)
7552 break;
7553 }
7554 bgp_dest_unlock_node(top);
7555
7556 return med_matched;
7557}
7558
7559/**
7560 * Toggles the route suppression status for this aggregate address
7561 * configuration.
7562 */
4056a5f6
RZ
7563void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7564 struct bgp *bgp, const struct prefix *p,
7565 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7566{
7567 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7568 const struct prefix *dest_p;
7569 struct bgp_dest *dest, *top;
7570 struct bgp_path_info *pi;
7571 bool toggle_suppression;
7572
7573 /* We've found a different MED we must revert any suppressed routes. */
7574 top = bgp_node_get(table, p);
7575 for (dest = bgp_node_get(table, p); dest;
7576 dest = bgp_route_next_until(dest, top)) {
7577 dest_p = bgp_dest_get_prefix(dest);
7578 if (dest_p->prefixlen <= p->prefixlen)
7579 continue;
7580
7581 toggle_suppression = false;
7582 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7583 if (BGP_PATH_HOLDDOWN(pi))
7584 continue;
7585 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7586 continue;
7587
6aabb15d
RZ
7588 /* We are toggling suppression back. */
7589 if (suppress) {
6aabb15d 7590 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7591 if (aggr_suppress_path(aggregate, pi))
7592 toggle_suppression = true;
6aabb15d
RZ
7593 continue;
7594 }
7595
6aabb15d 7596 /* Install route if there is no more suppression. */
4056a5f6 7597 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7598 toggle_suppression = true;
6aabb15d
RZ
7599 }
7600
7601 if (toggle_suppression)
7602 bgp_process(bgp, dest, afi, safi);
7603 }
7604 bgp_dest_unlock_node(top);
7605}
7606
7607/**
7608 * Aggregate address MED matching incremental test: this function is called
7609 * when the initial aggregation occurred and we are only testing a single
7610 * new path.
7611 *
7612 * In addition to testing and setting the MED validity it also installs back
7613 * suppressed routes (if summary is configured).
7614 *
7615 * Must not be called in `bgp_aggregate_route`.
7616 */
7617static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7618 struct bgp *bgp, const struct prefix *p,
7619 afi_t afi, safi_t safi,
f66624f5 7620 struct bgp_path_info *pi)
6aabb15d
RZ
7621{
7622 /* MED matching disabled. */
7623 if (!aggregate->match_med)
7624 return;
7625
f66624f5
DA
7626 /* Aggregation with different MED, recheck if we have got equal MEDs
7627 * now.
6aabb15d 7628 */
f66624f5
DA
7629 if (aggregate->med_mismatched &&
7630 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7631 aggregate->summary_only)
7632 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7633 true);
7634 else
6aabb15d
RZ
7635 bgp_aggregate_med_match(aggregate, bgp, pi);
7636
7637 /* No mismatches, just quit. */
7638 if (!aggregate->med_mismatched)
7639 return;
7640
7641 /* Route summarization is disabled. */
7642 if (!aggregate->summary_only)
7643 return;
7644
7645 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7646}
7647
b5d58c32 7648/* Update an aggregate as routes are added/removed from the BGP table */
9bea1b4b 7649bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
5f040085 7650 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7651{
7652 struct bgp_table *table;
9bcb3eef
DS
7653 struct bgp_dest *top;
7654 struct bgp_dest *dest;
d7c0a89a 7655 uint8_t origin;
d62a17ae 7656 struct aspath *aspath = NULL;
d62a17ae 7657 struct community *community = NULL;
3da2cc32 7658 struct ecommunity *ecommunity = NULL;
dd18c5a9 7659 struct lcommunity *lcommunity = NULL;
40381db7 7660 struct bgp_path_info *pi;
d62a17ae 7661 unsigned long match = 0;
d7c0a89a 7662 uint8_t atomic_aggregate = 0;
d62a17ae 7663
9f822fa2
S
7664 /* If the bgp instance is being deleted or self peer is deleted
7665 * then do not create aggregate route
7666 */
69a9680a 7667 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
9bea1b4b
DA
7668 bgp->peer_self == NULL)
7669 return false;
9f822fa2 7670
6aabb15d
RZ
7671 /* Initialize and test routes for MED difference. */
7672 if (aggregate->match_med)
7673 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7674
4056a5f6
RZ
7675 /*
7676 * Reset aggregate count: we might've been called from route map
7677 * update so in that case we must retest all more specific routes.
7678 *
7679 * \see `bgp_route_map_process_update`.
7680 */
7681 aggregate->count = 0;
7682 aggregate->incomplete_origin_count = 0;
7683 aggregate->incomplete_origin_count = 0;
7684 aggregate->egp_origin_count = 0;
7685
d62a17ae 7686 /* ORIGIN attribute: If at least one route among routes that are
7687 aggregated has ORIGIN with the value INCOMPLETE, then the
7688 aggregated route must have the ORIGIN attribute with the value
7689 INCOMPLETE. Otherwise, if at least one route among routes that
7690 are aggregated has ORIGIN with the value EGP, then the aggregated
7691 route must have the origin attribute with the value EGP. In all
7692 other case the value of the ORIGIN attribute of the aggregated
7693 route is INTERNAL. */
7694 origin = BGP_ORIGIN_IGP;
718e3744 7695
d62a17ae 7696 table = bgp->rib[afi][safi];
718e3744 7697
d62a17ae 7698 top = bgp_node_get(table, p);
9bcb3eef
DS
7699 for (dest = bgp_node_get(table, p); dest;
7700 dest = bgp_route_next_until(dest, top)) {
7701 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7702
9bcb3eef 7703 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7704 continue;
d62a17ae 7705
a77e2f4b
S
7706 /* If suppress fib is enabled and route not installed
7707 * in FIB, skip the route
7708 */
7709 if (!bgp_check_advertise(bgp, dest))
7710 continue;
7711
c2ff8b3e 7712 match = 0;
d62a17ae 7713
9bcb3eef 7714 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7715 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7716 continue;
718e3744 7717
40381db7 7718 if (pi->attr->flag
c2ff8b3e
DS
7719 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7720 atomic_aggregate = 1;
d62a17ae 7721
40381db7 7722 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7723 continue;
d62a17ae 7724
f273fef1
DS
7725 /*
7726 * summary-only aggregate route suppress
7727 * aggregated route announcements.
6aabb15d
RZ
7728 *
7729 * MED matching:
7730 * Don't create summaries if MED didn't match
7731 * otherwise neither the specific routes and the
7732 * aggregation will be announced.
f273fef1 7733 */
6aabb15d
RZ
7734 if (aggregate->summary_only
7735 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7736 if (aggr_suppress_path(aggregate, pi))
7737 match++;
d62a17ae 7738 }
c2ff8b3e 7739
365ab2e7
RZ
7740 /*
7741 * Suppress more specific routes that match the route
7742 * map results.
7743 *
7744 * MED matching:
7745 * Don't suppress routes if MED matching is enabled and
7746 * it mismatched otherwise we might end up with no
7747 * routes for this path.
7748 */
7749 if (aggregate->suppress_map_name
7750 && AGGREGATE_MED_VALID(aggregate)
7751 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7752 if (aggr_suppress_path(aggregate, pi))
7753 match++;
d62a17ae 7754 }
c2ff8b3e
DS
7755
7756 aggregate->count++;
7757
f273fef1
DS
7758 /*
7759 * If at least one route among routes that are
7760 * aggregated has ORIGIN with the value INCOMPLETE,
7761 * then the aggregated route MUST have the ORIGIN
7762 * attribute with the value INCOMPLETE. Otherwise, if
7763 * at least one route among routes that are aggregated
7764 * has ORIGIN with the value EGP, then the aggregated
7765 * route MUST have the ORIGIN attribute with the value
7766 * EGP.
7767 */
fc968841
NT
7768 switch (pi->attr->origin) {
7769 case BGP_ORIGIN_INCOMPLETE:
7770 aggregate->incomplete_origin_count++;
7771 break;
7772 case BGP_ORIGIN_EGP:
7773 aggregate->egp_origin_count++;
7774 break;
7775 default:
7776 /*Do nothing.
7777 */
7778 break;
7779 }
c2ff8b3e
DS
7780
7781 if (!aggregate->as_set)
7782 continue;
7783
f273fef1
DS
7784 /*
7785 * as-set aggregate route generate origin, as path,
7786 * and community aggregation.
7787 */
fc968841
NT
7788 /* Compute aggregate route's as-path.
7789 */
ef51a7d8 7790 bgp_compute_aggregate_aspath_hash(aggregate,
7791 pi->attr->aspath);
c2ff8b3e 7792
fc968841
NT
7793 /* Compute aggregate route's community.
7794 */
9a706b42 7795 if (bgp_attr_get_community(pi->attr))
21fec674 7796 bgp_compute_aggregate_community_hash(
9a706b42
DA
7797 aggregate,
7798 bgp_attr_get_community(pi->attr));
dd18c5a9 7799
fc968841
NT
7800 /* Compute aggregate route's extended community.
7801 */
b53e67a3 7802 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7803 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7804 aggregate,
7805 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7806
7807 /* Compute aggregate route's large community.
7808 */
1bcf3a96 7809 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7810 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7811 aggregate,
7812 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7813 }
c2ff8b3e 7814 if (match)
9bcb3eef 7815 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7816 }
21fec674 7817 if (aggregate->as_set) {
ef51a7d8 7818 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7819 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7820 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7821 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7822 }
7823
f1eb1f05 7824
9bcb3eef 7825 bgp_dest_unlock_node(top);
718e3744 7826
718e3744 7827
fc968841
NT
7828 if (aggregate->incomplete_origin_count > 0)
7829 origin = BGP_ORIGIN_INCOMPLETE;
7830 else if (aggregate->egp_origin_count > 0)
7831 origin = BGP_ORIGIN_EGP;
d62a17ae 7832
229757f1
DA
7833 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7834 origin = aggregate->origin;
7835
fc968841
NT
7836 if (aggregate->as_set) {
7837 if (aggregate->aspath)
7838 /* Retrieve aggregate route's as-path.
7839 */
7840 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7841
fc968841
NT
7842 if (aggregate->community)
7843 /* Retrieve aggregate route's community.
7844 */
7845 community = community_dup(aggregate->community);
3da2cc32 7846
fc968841
NT
7847 if (aggregate->ecommunity)
7848 /* Retrieve aggregate route's ecommunity.
7849 */
7850 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7851
fc968841
NT
7852 if (aggregate->lcommunity)
7853 /* Retrieve aggregate route's lcommunity.
7854 */
7855 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7856 }
718e3744 7857
c701010e 7858 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7859 ecommunity, lcommunity, atomic_aggregate,
7860 aggregate);
9bea1b4b
DA
7861
7862 return true;
718e3744 7863}
7864
5f040085
DS
7865void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7866 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7867{
7868 struct bgp_table *table;
9bcb3eef
DS
7869 struct bgp_dest *top;
7870 struct bgp_dest *dest;
40381db7 7871 struct bgp_path_info *pi;
3b7db173
DS
7872 unsigned long match;
7873
7874 table = bgp->rib[afi][safi];
7875
7876 /* If routes exists below this node, generate aggregate routes. */
7877 top = bgp_node_get(table, p);
9bcb3eef
DS
7878 for (dest = bgp_node_get(table, p); dest;
7879 dest = bgp_route_next_until(dest, top)) {
7880 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7881
9bcb3eef 7882 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7883 continue;
7884 match = 0;
7885
9bcb3eef 7886 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7887 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7888 continue;
7889
40381db7 7890 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7891 continue;
7892
92b175bd
RZ
7893 /*
7894 * This route is suppressed: attempt to unsuppress it.
7895 *
7896 * `aggr_unsuppress_path` will fail if this particular
7897 * aggregate route was not the suppressor.
7898 */
7899 if (pi->extra && pi->extra->aggr_suppressors &&
7900 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7901 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7902 match++;
3b7db173 7903 }
365ab2e7 7904
3b7db173 7905 aggregate->count--;
fc968841
NT
7906
7907 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7908 aggregate->incomplete_origin_count--;
7909 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7910 aggregate->egp_origin_count--;
7911
7912 if (aggregate->as_set) {
7913 /* Remove as-path from aggregate.
7914 */
ef51a7d8 7915 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7916 aggregate,
7917 pi->attr->aspath);
7918
9a706b42 7919 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7920 /* Remove community from aggregate.
7921 */
21fec674 7922 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7923 aggregate,
7924 bgp_attr_get_community(
7925 pi->attr));
fc968841 7926
b53e67a3 7927 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7928 /* Remove ecommunity from aggregate.
7929 */
4edd83f9 7930 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7931 aggregate,
7932 bgp_attr_get_ecommunity(
7933 pi->attr));
fc968841 7934
1bcf3a96 7935 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7936 /* Remove lcommunity from aggregate.
7937 */
f1eb1f05 7938 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7939 aggregate,
7940 bgp_attr_get_lcommunity(
7941 pi->attr));
fc968841 7942 }
3b7db173
DS
7943 }
7944
7945 /* If this node was suppressed, process the change. */
7946 if (match)
9bcb3eef 7947 bgp_process(bgp, dest, afi, safi);
3b7db173 7948 }
f1eb1f05 7949 if (aggregate->as_set) {
ef51a7d8 7950 aspath_free(aggregate->aspath);
7951 aggregate->aspath = NULL;
21fec674 7952 if (aggregate->community)
7953 community_free(&aggregate->community);
4edd83f9 7954 if (aggregate->ecommunity)
7955 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7956 if (aggregate->lcommunity)
7957 lcommunity_free(&aggregate->lcommunity);
7958 }
7959
9bcb3eef 7960 bgp_dest_unlock_node(top);
3b7db173 7961}
718e3744 7962
5f040085
DS
7963static void bgp_add_route_to_aggregate(struct bgp *bgp,
7964 const struct prefix *aggr_p,
fc968841
NT
7965 struct bgp_path_info *pinew, afi_t afi,
7966 safi_t safi,
7967 struct bgp_aggregate *aggregate)
7968{
7969 uint8_t origin;
7970 struct aspath *aspath = NULL;
7971 uint8_t atomic_aggregate = 0;
7972 struct community *community = NULL;
7973 struct ecommunity *ecommunity = NULL;
7974 struct lcommunity *lcommunity = NULL;
7975
a4559740 7976 /* If the bgp instance is being deleted or self peer is deleted
7977 * then do not create aggregate route
7978 */
7979 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7980 || (bgp->peer_self == NULL))
7981 return;
7982
fc968841
NT
7983 /* ORIGIN attribute: If at least one route among routes that are
7984 * aggregated has ORIGIN with the value INCOMPLETE, then the
7985 * aggregated route must have the ORIGIN attribute with the value
7986 * INCOMPLETE. Otherwise, if at least one route among routes that
7987 * are aggregated has ORIGIN with the value EGP, then the aggregated
7988 * route must have the origin attribute with the value EGP. In all
7989 * other case the value of the ORIGIN attribute of the aggregated
7990 * route is INTERNAL.
7991 */
7992 origin = BGP_ORIGIN_IGP;
7993
7994 aggregate->count++;
7995
6aabb15d
RZ
7996 /*
7997 * This must be called before `summary` check to avoid
7998 * "suppressing" twice.
7999 */
8000 if (aggregate->match_med)
8001 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8002 pinew);
6aabb15d
RZ
8003
8004 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8005 aggr_suppress_path(aggregate, pinew);
fc968841 8006
365ab2e7
RZ
8007 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8008 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8009 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8010
8011 switch (pinew->attr->origin) {
8012 case BGP_ORIGIN_INCOMPLETE:
8013 aggregate->incomplete_origin_count++;
8014 break;
8015 case BGP_ORIGIN_EGP:
8016 aggregate->egp_origin_count++;
8017 break;
8018 default:
8019 /* Do nothing.
8020 */
8021 break;
8022 }
8023
8024 if (aggregate->incomplete_origin_count > 0)
8025 origin = BGP_ORIGIN_INCOMPLETE;
8026 else if (aggregate->egp_origin_count > 0)
8027 origin = BGP_ORIGIN_EGP;
8028
229757f1
DA
8029 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8030 origin = aggregate->origin;
8031
fc968841
NT
8032 if (aggregate->as_set) {
8033 /* Compute aggregate route's as-path.
8034 */
8035 bgp_compute_aggregate_aspath(aggregate,
8036 pinew->attr->aspath);
8037
8038 /* Compute aggregate route's community.
8039 */
9a706b42 8040 if (bgp_attr_get_community(pinew->attr))
fc968841 8041 bgp_compute_aggregate_community(
9a706b42 8042 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8043
8044 /* Compute aggregate route's extended community.
8045 */
b53e67a3 8046 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8047 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8048 aggregate,
8049 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8050
8051 /* Compute aggregate route's large community.
8052 */
1bcf3a96 8053 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8054 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8055 aggregate,
8056 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8057
8058 /* Retrieve aggregate route's as-path.
8059 */
8060 if (aggregate->aspath)
8061 aspath = aspath_dup(aggregate->aspath);
8062
8063 /* Retrieve aggregate route's community.
8064 */
8065 if (aggregate->community)
8066 community = community_dup(aggregate->community);
8067
8068 /* Retrieve aggregate route's ecommunity.
8069 */
8070 if (aggregate->ecommunity)
8071 ecommunity = ecommunity_dup(aggregate->ecommunity);
8072
8073 /* Retrieve aggregate route's lcommunity.
8074 */
8075 if (aggregate->lcommunity)
8076 lcommunity = lcommunity_dup(aggregate->lcommunity);
8077 }
8078
8079 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8080 aspath, community, ecommunity,
8081 lcommunity, atomic_aggregate, aggregate);
8082}
8083
8084static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8085 safi_t safi,
8086 struct bgp_path_info *pi,
8087 struct bgp_aggregate *aggregate,
5f040085 8088 const struct prefix *aggr_p)
fc968841
NT
8089{
8090 uint8_t origin;
8091 struct aspath *aspath = NULL;
8092 uint8_t atomic_aggregate = 0;
8093 struct community *community = NULL;
8094 struct ecommunity *ecommunity = NULL;
8095 struct lcommunity *lcommunity = NULL;
8096 unsigned long match = 0;
8097
a4559740 8098 /* If the bgp instance is being deleted or self peer is deleted
8099 * then do not create aggregate route
8100 */
8101 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8102 || (bgp->peer_self == NULL))
8103 return;
8104
fc968841
NT
8105 if (BGP_PATH_HOLDDOWN(pi))
8106 return;
8107
8108 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8109 return;
8110
4056a5f6
RZ
8111 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8112 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8113 match++;
fc968841 8114
365ab2e7 8115 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8116 && aggr_suppress_map_test(bgp, aggregate, pi))
8117 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8118 match++;
fc968841 8119
6aabb15d 8120 /*
365ab2e7 8121 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8122 * "unsuppressing" twice.
8123 */
8124 if (aggregate->match_med)
f66624f5 8125 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8126
fc968841
NT
8127 if (aggregate->count > 0)
8128 aggregate->count--;
8129
8130 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8131 aggregate->incomplete_origin_count--;
8132 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8133 aggregate->egp_origin_count--;
8134
8135 if (aggregate->as_set) {
8136 /* Remove as-path from aggregate.
8137 */
8138 bgp_remove_aspath_from_aggregate(aggregate,
8139 pi->attr->aspath);
8140
9a706b42 8141 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8142 /* Remove community from aggregate.
8143 */
8144 bgp_remove_community_from_aggregate(
9a706b42 8145 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8146
b53e67a3 8147 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8148 /* Remove ecommunity from aggregate.
8149 */
8150 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8151 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8152
1bcf3a96 8153 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8154 /* Remove lcommunity from aggregate.
8155 */
8156 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8157 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8158 }
8159
8160 /* If this node was suppressed, process the change. */
8161 if (match)
8162 bgp_process(bgp, pi->net, afi, safi);
8163
8164 origin = BGP_ORIGIN_IGP;
8165 if (aggregate->incomplete_origin_count > 0)
8166 origin = BGP_ORIGIN_INCOMPLETE;
8167 else if (aggregate->egp_origin_count > 0)
8168 origin = BGP_ORIGIN_EGP;
8169
229757f1
DA
8170 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8171 origin = aggregate->origin;
8172
fc968841
NT
8173 if (aggregate->as_set) {
8174 /* Retrieve aggregate route's as-path.
8175 */
8176 if (aggregate->aspath)
8177 aspath = aspath_dup(aggregate->aspath);
8178
8179 /* Retrieve aggregate route's community.
8180 */
8181 if (aggregate->community)
8182 community = community_dup(aggregate->community);
8183
8184 /* Retrieve aggregate route's ecommunity.
8185 */
8186 if (aggregate->ecommunity)
8187 ecommunity = ecommunity_dup(aggregate->ecommunity);
8188
8189 /* Retrieve aggregate route's lcommunity.
8190 */
8191 if (aggregate->lcommunity)
8192 lcommunity = lcommunity_dup(aggregate->lcommunity);
8193 }
8194
8195 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8196 aspath, community, ecommunity,
8197 lcommunity, atomic_aggregate, aggregate);
8198}
8199
5a1ae2c2 8200void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8201 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8202{
9bcb3eef
DS
8203 struct bgp_dest *child;
8204 struct bgp_dest *dest;
d62a17ae 8205 struct bgp_aggregate *aggregate;
8206 struct bgp_table *table;
718e3744 8207
d62a17ae 8208 table = bgp->aggregate[afi][safi];
f018db83 8209
d62a17ae 8210 /* No aggregates configured. */
8211 if (bgp_table_top_nolock(table) == NULL)
8212 return;
f018db83 8213
d62a17ae 8214 if (p->prefixlen == 0)
8215 return;
718e3744 8216
40381db7 8217 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8218 return;
718e3744 8219
a77e2f4b
S
8220 /* If suppress fib is enabled and route not installed
8221 * in FIB, do not update the aggregate route
8222 */
8223 if (!bgp_check_advertise(bgp, pi->net))
8224 return;
8225
d62a17ae 8226 child = bgp_node_get(table, p);
718e3744 8227
d62a17ae 8228 /* Aggregate address configuration check. */
9bcb3eef
DS
8229 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8230 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8231
9bcb3eef
DS
8232 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8233 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8234 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8235 aggregate);
d62a17ae 8236 }
b1e62edd 8237 }
9bcb3eef 8238 bgp_dest_unlock_node(child);
718e3744 8239}
8240
5a1ae2c2 8241void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8242 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8243{
9bcb3eef
DS
8244 struct bgp_dest *child;
8245 struct bgp_dest *dest;
d62a17ae 8246 struct bgp_aggregate *aggregate;
8247 struct bgp_table *table;
718e3744 8248
d62a17ae 8249 table = bgp->aggregate[afi][safi];
718e3744 8250
d62a17ae 8251 /* No aggregates configured. */
8252 if (bgp_table_top_nolock(table) == NULL)
8253 return;
718e3744 8254
d62a17ae 8255 if (p->prefixlen == 0)
8256 return;
718e3744 8257
d62a17ae 8258 child = bgp_node_get(table, p);
718e3744 8259
d62a17ae 8260 /* Aggregate address configuration check. */
9bcb3eef
DS
8261 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8262 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8263
9bcb3eef
DS
8264 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8265 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8266 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8267 aggregate, dest_p);
d62a17ae 8268 }
b1e62edd 8269 }
9bcb3eef 8270 bgp_dest_unlock_node(child);
d62a17ae 8271}
718e3744 8272
718e3744 8273/* Aggregate route attribute. */
8274#define AGGREGATE_SUMMARY_ONLY 1
8275#define AGGREGATE_AS_SET 1
fb29348a 8276#define AGGREGATE_AS_UNSET 0
718e3744 8277
229757f1
DA
8278static const char *bgp_origin2str(uint8_t origin)
8279{
8280 switch (origin) {
8281 case BGP_ORIGIN_IGP:
8282 return "igp";
8283 case BGP_ORIGIN_EGP:
8284 return "egp";
8285 case BGP_ORIGIN_INCOMPLETE:
8286 return "incomplete";
8287 }
8288 return "n/a";
8289}
8290
fdeb5a81 8291static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8292{
8293 switch (v_state) {
fdeb5a81
DS
8294 case RPKI_NOT_BEING_USED:
8295 return "not used";
8296 case RPKI_VALID:
b5b99af8 8297 return "valid";
fdeb5a81 8298 case RPKI_NOTFOUND:
b5b99af8 8299 return "not found";
fdeb5a81 8300 case RPKI_INVALID:
b5b99af8 8301 return "invalid";
b5b99af8 8302 }
fdeb5a81
DS
8303
8304 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8305 return "ERROR";
8306}
8307
585f1adc
IR
8308static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8309 afi_t afi, safi_t safi)
718e3744 8310{
585f1adc
IR
8311 VTY_DECLVAR_CONTEXT(bgp, bgp);
8312 int ret;
8313 struct prefix p;
9bcb3eef 8314 struct bgp_dest *dest;
d62a17ae 8315 struct bgp_aggregate *aggregate;
718e3744 8316
585f1adc
IR
8317 /* Convert string to prefix structure. */
8318 ret = str2prefix(prefix_str, &p);
8319 if (!ret) {
8320 vty_out(vty, "Malformed prefix\n");
8321 return CMD_WARNING_CONFIG_FAILED;
8322 }
8323 apply_mask(&p);
a4559740 8324
d62a17ae 8325 /* Old configuration check. */
585f1adc 8326 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8327 if (!dest) {
585f1adc
IR
8328 vty_out(vty,
8329 "%% There is no aggregate-address configuration.\n");
8330 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8331 }
f6269b4f 8332
9bcb3eef 8333 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8334 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8335 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8336 NULL, NULL, 0, aggregate);
d62a17ae 8337
8338 /* Unlock aggregate address configuration. */
9bcb3eef 8339 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841 8340
7a70d990 8341 bgp_free_aggregate_info(aggregate);
9bcb3eef
DS
8342 bgp_dest_unlock_node(dest);
8343 bgp_dest_unlock_node(dest);
d62a17ae 8344
585f1adc 8345 return CMD_SUCCESS;
d62a17ae 8346}
8347
585f1adc
IR
8348static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8349 safi_t safi, const char *rmap,
8350 uint8_t summary_only, uint8_t as_set,
8351 uint8_t origin, bool match_med,
8352 const char *suppress_map)
d62a17ae 8353{
585f1adc 8354 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8355 int ret;
585f1adc 8356 struct prefix p;
9bcb3eef 8357 struct bgp_dest *dest;
d62a17ae 8358 struct bgp_aggregate *aggregate;
fb29348a 8359 uint8_t as_set_new = as_set;
d62a17ae 8360
365ab2e7 8361 if (suppress_map && summary_only) {
585f1adc 8362 vty_out(vty,
365ab2e7 8363 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8364 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8365 }
8366
585f1adc
IR
8367 /* Convert string to prefix structure. */
8368 ret = str2prefix(prefix_str, &p);
8369 if (!ret) {
8370 vty_out(vty, "Malformed prefix\n");
8371 return CMD_WARNING_CONFIG_FAILED;
8372 }
8373 apply_mask(&p);
d62a17ae 8374
585f1adc
IR
8375 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8376 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8377 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8378 prefix_str);
8379 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8380 }
8381
d62a17ae 8382 /* Old configuration check. */
585f1adc 8383 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8384 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8385
20894f50 8386 if (aggregate) {
585f1adc 8387 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8388 /* try to remove the old entry */
585f1adc 8389 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8390 if (ret) {
585f1adc 8391 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8392 bgp_dest_unlock_node(dest);
585f1adc 8393 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8394 }
8395 }
718e3744 8396
d62a17ae 8397 /* Make aggregate address structure. */
8398 aggregate = bgp_aggregate_new();
8399 aggregate->summary_only = summary_only;
6aabb15d 8400 aggregate->match_med = match_med;
fb29348a
DA
8401
8402 /* Network operators MUST NOT locally generate any new
8403 * announcements containing AS_SET or AS_CONFED_SET. If they have
8404 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8405 * SHOULD withdraw those routes and re-announce routes for the
8406 * aggregate or component prefixes (i.e., the more-specific routes
8407 * subsumed by the previously aggregated route) without AS_SET
8408 * or AS_CONFED_SET in the updates.
8409 */
7f972cd8 8410 if (bgp->reject_as_sets) {
fb29348a
DA
8411 if (as_set == AGGREGATE_AS_SET) {
8412 as_set_new = AGGREGATE_AS_UNSET;
8413 zlog_warn(
63efca0e 8414 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8415 __func__);
585f1adc 8416 vty_out(vty,
fb29348a
DA
8417 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8418 }
8419 }
8420
8421 aggregate->as_set = as_set_new;
d62a17ae 8422 aggregate->safi = safi;
229757f1
DA
8423 /* Override ORIGIN attribute if defined.
8424 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8425 * to IGP which is not what rfc4271 says.
8426 * This enables the same behavior, optionally.
8427 */
8428 aggregate->origin = origin;
20894f50
DA
8429
8430 if (rmap) {
8431 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8432 route_map_counter_decrement(aggregate->rmap.map);
8433 aggregate->rmap.name =
8434 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8435 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8436 route_map_counter_increment(aggregate->rmap.map);
8437 }
365ab2e7
RZ
8438
8439 if (suppress_map) {
8440 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8441 route_map_counter_decrement(aggregate->suppress_map);
8442
8443 aggregate->suppress_map_name =
8444 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8445 aggregate->suppress_map =
8446 route_map_lookup_by_name(aggregate->suppress_map_name);
8447 route_map_counter_increment(aggregate->suppress_map);
8448 }
8449
9bcb3eef 8450 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8451
d62a17ae 8452 /* Aggregate address insert into BGP routing table. */
9bea1b4b
DA
8453 if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8454 bgp_aggregate_free(aggregate);
8455 bgp_dest_unlock_node(dest);
8456 }
718e3744 8457
585f1adc 8458 return CMD_SUCCESS;
718e3744 8459}
8460
585f1adc
IR
8461DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8462 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8463 "as-set$as_set_s"
8464 "|summary-only$summary_only"
cacba915 8465 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8466 "|origin <egp|igp|incomplete>$origin_s"
8467 "|matching-MED-only$match_med"
cacba915 8468 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8469 "}]",
8470 NO_STR
8471 "Configure BGP aggregate entries\n"
764402fe
DA
8472 "Aggregate prefix\n"
8473 "Aggregate address\n"
8474 "Aggregate mask\n"
585f1adc
IR
8475 "Generate AS set path information\n"
8476 "Filter more specific routes from updates\n"
8477 "Apply route map to aggregate network\n"
8478 "Route map name\n"
8479 "BGP origin code\n"
8480 "Remote EGP\n"
8481 "Local IGP\n"
8482 "Unknown heritage\n"
8483 "Only aggregate routes with matching MED\n"
8484 "Suppress the selected more specific routes\n"
8485 "Route map with the route selectors\n")
8486{
8487 const char *prefix_s = NULL;
554b3b10 8488 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8489 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8490 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8491 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8492
554b3b10 8493 if (addr_str) {
7533cad7
QY
8494 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8495 sizeof(prefix_buf))
554b3b10
RZ
8496 == 0) {
8497 vty_out(vty, "%% Inconsistent address and mask\n");
8498 return CMD_WARNING_CONFIG_FAILED;
8499 }
585f1adc
IR
8500 prefix_s = prefix_buf;
8501 } else
8502 prefix_s = prefix_str;
37a87b8f 8503
585f1adc
IR
8504 if (origin_s) {
8505 if (strcmp(origin_s, "egp") == 0)
8506 origin = BGP_ORIGIN_EGP;
8507 else if (strcmp(origin_s, "igp") == 0)
8508 origin = BGP_ORIGIN_IGP;
8509 else if (strcmp(origin_s, "incomplete") == 0)
8510 origin = BGP_ORIGIN_INCOMPLETE;
8511 }
90e21f35 8512
585f1adc
IR
8513 if (as_set_s)
8514 as_set = AGGREGATE_AS_SET;
554b3b10 8515
585f1adc 8516 /* Handle configuration removal, otherwise installation. */
554b3b10 8517 if (no)
585f1adc
IR
8518 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8519
8520 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8521 summary_only != NULL, as_set, origin,
8522 match_med != NULL, suppress_map);
8523}
8524
7a70d990
SB
8525void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
8526{
8527 if (aggregate->community)
8528 community_free(&aggregate->community);
8529
8530 hash_clean_and_free(&aggregate->community_hash,
8531 bgp_aggr_community_remove);
8532
8533 if (aggregate->ecommunity)
8534 ecommunity_free(&aggregate->ecommunity);
8535
8536 hash_clean_and_free(&aggregate->ecommunity_hash,
8537 bgp_aggr_ecommunity_remove);
8538
8539 if (aggregate->lcommunity)
8540 lcommunity_free(&aggregate->lcommunity);
8541
8542 hash_clean_and_free(&aggregate->lcommunity_hash,
8543 bgp_aggr_lcommunity_remove);
8544
8545 if (aggregate->aspath)
8546 aspath_free(aggregate->aspath);
8547
8548 hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
8549
8550 bgp_aggregate_free(aggregate);
8551}
8552
585f1adc
IR
8553DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8554 "[no] aggregate-address X:X::X:X/M$prefix [{"
8555 "as-set$as_set_s"
8556 "|summary-only$summary_only"
cacba915 8557 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8558 "|origin <egp|igp|incomplete>$origin_s"
8559 "|matching-MED-only$match_med"
cacba915 8560 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8561 "}]",
8562 NO_STR
8563 "Configure BGP aggregate entries\n"
8564 "Aggregate prefix\n"
8565 "Generate AS set path information\n"
8566 "Filter more specific routes from updates\n"
8567 "Apply route map to aggregate network\n"
8568 "Route map name\n"
8569 "BGP origin code\n"
8570 "Remote EGP\n"
8571 "Local IGP\n"
8572 "Unknown heritage\n"
8573 "Only aggregate routes with matching MED\n"
8574 "Suppress the selected more specific routes\n"
8575 "Route map with the route selectors\n")
8576{
8577 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8578 int as_set = AGGREGATE_AS_UNSET;
8579
8580 if (origin_s) {
8581 if (strcmp(origin_s, "egp") == 0)
8582 origin = BGP_ORIGIN_EGP;
8583 else if (strcmp(origin_s, "igp") == 0)
8584 origin = BGP_ORIGIN_IGP;
8585 else if (strcmp(origin_s, "incomplete") == 0)
8586 origin = BGP_ORIGIN_INCOMPLETE;
8587 }
8588
8589 if (as_set_s)
8590 as_set = AGGREGATE_AS_SET;
8591
8592 /* Handle configuration removal, otherwise installation. */
554b3b10 8593 if (no)
585f1adc
IR
8594 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8595 SAFI_UNICAST);
554b3b10 8596
585f1adc
IR
8597 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8598 rmap_name, summary_only != NULL, as_set,
8599 origin, match_med != NULL, suppress_map);
718e3744 8600}
8601
718e3744 8602/* Redistribute route treatment. */
d62a17ae 8603void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8604 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8605 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8606 enum blackhole_type bhtype, uint32_t metric,
8607 uint8_t type, unsigned short instance,
8608 route_tag_t tag)
d62a17ae 8609{
4b7e6066 8610 struct bgp_path_info *new;
40381db7
DS
8611 struct bgp_path_info *bpi;
8612 struct bgp_path_info rmap_path;
9bcb3eef 8613 struct bgp_dest *bn;
d62a17ae 8614 struct attr attr;
8615 struct attr *new_attr;
8616 afi_t afi;
b68885f9 8617 route_map_result_t ret;
d62a17ae 8618 struct bgp_redist *red;
8619
8620 /* Make default attribute. */
0f05ea43 8621 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8622 /*
8623 * This must not be NULL to satisfy Coverity SA
8624 */
8625 assert(attr.aspath);
9de1f7ff 8626
a4d82a8a 8627 switch (nhtype) {
9de1f7ff 8628 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8629 switch (p->family) {
8630 case AF_INET:
8631 attr.nexthop.s_addr = INADDR_ANY;
8632 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8633 break;
8634 case AF_INET6:
8635 memset(&attr.mp_nexthop_global, 0,
8636 sizeof(attr.mp_nexthop_global));
8637 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8638 break;
8639 }
9de1f7ff
DS
8640 break;
8641 case NEXTHOP_TYPE_IPV4:
8642 case NEXTHOP_TYPE_IPV4_IFINDEX:
8643 attr.nexthop = nexthop->ipv4;
7226bc40 8644 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8645 break;
8646 case NEXTHOP_TYPE_IPV6:
8647 case NEXTHOP_TYPE_IPV6_IFINDEX:
8648 attr.mp_nexthop_global = nexthop->ipv6;
8649 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8650 break;
8651 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8652 switch (p->family) {
8653 case AF_INET:
9de1f7ff 8654 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8655 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8656 break;
8657 case AF_INET6:
9de1f7ff
DS
8658 memset(&attr.mp_nexthop_global, 0,
8659 sizeof(attr.mp_nexthop_global));
74489921 8660 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8661 break;
74489921 8662 }
0789eb69 8663 attr.bh_type = bhtype;
9de1f7ff 8664 break;
d62a17ae 8665 }
0789eb69 8666 attr.nh_type = nhtype;
74489921 8667 attr.nh_ifindex = ifindex;
f04a80a5 8668
d62a17ae 8669 attr.med = metric;
957f74c3 8670 attr.distance = distance;
d62a17ae 8671 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8672 attr.tag = tag;
718e3744 8673
97a52c82
DA
8674 if (metric)
8675 bgp_attr_set_aigp_metric(&attr, metric);
8676
d62a17ae 8677 afi = family2afi(p->family);
6aeb9e78 8678
d62a17ae 8679 red = bgp_redist_lookup(bgp, afi, type, instance);
8680 if (red) {
8681 struct attr attr_new;
718e3744 8682
d62a17ae 8683 /* Copy attribute for modification. */
6f4f49b2 8684 attr_new = attr;
718e3744 8685
97a52c82 8686 if (red->redist_metric_flag) {
d62a17ae 8687 attr_new.med = red->redist_metric;
97a52c82
DA
8688 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8689 }
718e3744 8690
d62a17ae 8691 /* Apply route-map. */
8692 if (red->rmap.name) {
6006b807 8693 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8694 rmap_path.peer = bgp->peer_self;
8695 rmap_path.attr = &attr_new;
718e3744 8696
d62a17ae 8697 SET_FLAG(bgp->peer_self->rmap_type,
8698 PEER_RMAP_TYPE_REDISTRIBUTE);
8699
1782514f 8700 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8701
8702 bgp->peer_self->rmap_type = 0;
8703
8704 if (ret == RMAP_DENYMATCH) {
8705 /* Free uninterned attribute. */
8706 bgp_attr_flush(&attr_new);
8707
8708 /* Unintern original. */
8709 aspath_unintern(&attr.aspath);
8710 bgp_redistribute_delete(bgp, p, type, instance);
8711 return;
8712 }
8713 }
8714
637e5ba4 8715 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8716 bgp_attr_add_gshut_community(&attr_new);
8717
d62a17ae 8718 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8719 SAFI_UNICAST, p, NULL);
8720
8721 new_attr = bgp_attr_intern(&attr_new);
8722
9bcb3eef 8723 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8724 if (bpi->peer == bgp->peer_self
8725 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8726 break;
8727
40381db7 8728 if (bpi) {
d62a17ae 8729 /* Ensure the (source route) type is updated. */
40381db7
DS
8730 bpi->type = type;
8731 if (attrhash_cmp(bpi->attr, new_attr)
8732 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8733 bgp_attr_unintern(&new_attr);
8734 aspath_unintern(&attr.aspath);
9bcb3eef 8735 bgp_dest_unlock_node(bn);
d62a17ae 8736 return;
8737 } else {
8738 /* The attribute is changed. */
40381db7 8739 bgp_path_info_set_flag(bn, bpi,
18ee8310 8740 BGP_PATH_ATTR_CHANGED);
d62a17ae 8741
8742 /* Rewrite BGP route information. */
40381db7
DS
8743 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8744 bgp_path_info_restore(bn, bpi);
d62a17ae 8745 else
40381db7
DS
8746 bgp_aggregate_decrement(
8747 bgp, p, bpi, afi, SAFI_UNICAST);
8748 bgp_attr_unintern(&bpi->attr);
8749 bpi->attr = new_attr;
083ec940 8750 bpi->uptime = monotime(NULL);
d62a17ae 8751
8752 /* Process change. */
40381db7 8753 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8754 SAFI_UNICAST);
8755 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8756 bgp_dest_unlock_node(bn);
d62a17ae 8757 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8758
8759 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8760 || (bgp->inst_type
8761 == BGP_INSTANCE_TYPE_DEFAULT)) {
8762
8763 vpn_leak_from_vrf_update(
40381db7 8764 bgp_get_default(), bgp, bpi);
ddb5b488 8765 }
d62a17ae 8766 return;
8767 }
8768 }
8769
8770 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8771 bgp->peer_self, new_attr, bn);
1defdda8 8772 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8773
8774 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8775 bgp_path_info_add(bn, new);
9bcb3eef 8776 bgp_dest_unlock_node(bn);
be785e35 8777 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8778 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8779
8780 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8781 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8782
8783 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8784 }
d62a17ae 8785 }
8786
8787 /* Unintern original. */
8788 aspath_unintern(&attr.aspath);
718e3744 8789}
8790
d7c0a89a
QY
8791void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8792 unsigned short instance)
718e3744 8793{
d62a17ae 8794 afi_t afi;
9bcb3eef 8795 struct bgp_dest *dest;
40381db7 8796 struct bgp_path_info *pi;
d62a17ae 8797 struct bgp_redist *red;
718e3744 8798
d62a17ae 8799 afi = family2afi(p->family);
718e3744 8800
d62a17ae 8801 red = bgp_redist_lookup(bgp, afi, type, instance);
8802 if (red) {
9bcb3eef
DS
8803 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8804 SAFI_UNICAST, p, NULL);
d62a17ae 8805
9bcb3eef 8806 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8807 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8808 break;
8809
40381db7 8810 if (pi) {
ddb5b488
PZ
8811 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8812 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8813
8814 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8815 bgp, pi);
ddb5b488 8816 }
40381db7 8817 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8818 bgp_path_info_delete(dest, pi);
8819 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8820 }
9bcb3eef 8821 bgp_dest_unlock_node(dest);
d62a17ae 8822 }
8823}
8824
8825/* Withdraw specified route type's route. */
8826void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8827 unsigned short instance)
d62a17ae 8828{
9bcb3eef 8829 struct bgp_dest *dest;
40381db7 8830 struct bgp_path_info *pi;
d62a17ae 8831 struct bgp_table *table;
8832
8833 table = bgp->rib[afi][SAFI_UNICAST];
8834
9bcb3eef
DS
8835 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8836 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8837 if (pi->peer == bgp->peer_self && pi->type == type
8838 && pi->instance == instance)
d62a17ae 8839 break;
8840
40381db7 8841 if (pi) {
ddb5b488
PZ
8842 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8843 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8844
8845 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8846 bgp, pi);
ddb5b488 8847 }
9bcb3eef 8848 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8849 pi, afi, SAFI_UNICAST);
9bcb3eef 8850 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8851 if (!CHECK_FLAG(bgp->flags,
8852 BGP_FLAG_DELETE_IN_PROGRESS))
8853 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8854 else
8855 bgp_path_info_reap(dest, pi);
d62a17ae 8856 }
718e3744 8857 }
718e3744 8858}
6b0655a2 8859
718e3744 8860/* Static function to display route. */
7d3cae70
DA
8861static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8862 struct vty *vty, json_object *json, bool wide)
718e3744 8863{
be054588 8864 int len = 0;
07380148 8865 char buf[INET6_ADDRSTRLEN];
718e3744 8866
d62a17ae 8867 if (p->family == AF_INET) {
c6462ff4 8868 if (!json) {
8228a9a7 8869 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8870 } else {
8871 json_object_string_add(json, "prefix",
8872 inet_ntop(p->family,
8873 &p->u.prefix, buf,
07380148 8874 sizeof(buf)));
c6462ff4 8875 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8876 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8877 json_object_int_add(json, "version", dest->version);
c6462ff4 8878 }
d62a17ae 8879 } else if (p->family == AF_ETHERNET) {
8228a9a7 8880 len = vty_out(vty, "%pFX", p);
b03b8898 8881 } else if (p->family == AF_EVPN) {
57f7feb6 8882 if (!json)
2dbe669b 8883 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8884 else
60466a63 8885 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8886 } else if (p->family == AF_FLOWSPEC) {
8887 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8888 json ?
8889 NLRI_STRING_FORMAT_JSON_SIMPLE :
8890 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8891 } else {
c6462ff4 8892 if (!json)
8228a9a7 8893 len = vty_out(vty, "%pFX", p);
50e05855
AD
8894 else {
8895 json_object_string_add(json, "prefix",
07380148
DA
8896 inet_ntop(p->family,
8897 &p->u.prefix, buf,
8898 sizeof(buf)));
50e05855 8899 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8900 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8901 json_object_int_add(json, "version", dest->version);
37d4e0df 8902 }
9c92b5f7 8903 }
d62a17ae 8904
9c92b5f7 8905 if (!json) {
ae248832 8906 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8907 if (len < 1)
8908 vty_out(vty, "\n%*s", 20, " ");
8909 else
8910 vty_out(vty, "%*s", len, " ");
8911 }
718e3744 8912}
8913
d62a17ae 8914enum bgp_display_type {
8915 normal_list,
718e3744 8916};
8917
1d7260a1 8918const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8919{
8920 switch (reason) {
8921 case bgp_path_selection_none:
8922 return "Nothing to Select";
8923 case bgp_path_selection_first:
8924 return "First path received";
8925 case bgp_path_selection_evpn_sticky_mac:
8926 return "EVPN Sticky Mac";
8927 case bgp_path_selection_evpn_seq:
8928 return "EVPN sequence number";
8929 case bgp_path_selection_evpn_lower_ip:
8930 return "EVPN lower IP";
8931 case bgp_path_selection_evpn_local_path:
8932 return "EVPN local ES path";
8933 case bgp_path_selection_evpn_non_proxy:
8934 return "EVPN non proxy";
8935 case bgp_path_selection_weight:
8936 return "Weight";
8937 case bgp_path_selection_local_pref:
8938 return "Local Pref";
46dbf9d0
DA
8939 case bgp_path_selection_accept_own:
8940 return "Accept Own";
bbb46eb5
DA
8941 case bgp_path_selection_local_route:
8942 return "Local Route";
97a52c82
DA
8943 case bgp_path_selection_aigp:
8944 return "AIGP";
bbb46eb5
DA
8945 case bgp_path_selection_confed_as_path:
8946 return "Confederation based AS Path";
8947 case bgp_path_selection_as_path:
8948 return "AS Path";
8949 case bgp_path_selection_origin:
8950 return "Origin";
8951 case bgp_path_selection_med:
8952 return "MED";
8953 case bgp_path_selection_peer:
8954 return "Peer Type";
8955 case bgp_path_selection_confed:
8956 return "Confed Peer Type";
8957 case bgp_path_selection_igp_metric:
8958 return "IGP Metric";
8959 case bgp_path_selection_older:
8960 return "Older Path";
8961 case bgp_path_selection_router_id:
8962 return "Router ID";
8963 case bgp_path_selection_cluster_length:
bcab253c 8964 return "Cluster length";
bbb46eb5
DA
8965 case bgp_path_selection_stale:
8966 return "Path Staleness";
8967 case bgp_path_selection_local_configured:
8968 return "Locally configured route";
8969 case bgp_path_selection_neighbor_ip:
8970 return "Neighbor IP";
8971 case bgp_path_selection_default:
8972 return "Nothing left to compare";
8973 }
8974 return "Invalid (internal error)";
8975}
8976
18ee8310 8977/* Print the short form route status for a bgp_path_info */
4b7e6066 8978static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8979 struct bgp_path_info *path,
82c298be 8980 const struct prefix *p,
d62a17ae 8981 json_object *json_path)
718e3744 8982{
82c298be
DA
8983 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8984
d62a17ae 8985 if (json_path) {
b05a1c8b 8986
d62a17ae 8987 /* Route status display. */
9b6d8fcf 8988 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8989 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8990
9b6d8fcf 8991 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8992 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8993
4056a5f6 8994 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8995 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8996
9b6d8fcf
DS
8997 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8998 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8999 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9000
d62a17ae 9001 /* Selected */
9b6d8fcf 9002 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9003 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9004
9b6d8fcf 9005 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9006 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9007
bbb46eb5 9008 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9009 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9010 json_object_string_add(json_path, "selectionReason",
9011 bgp_path_selection_reason2str(
9012 path->net->reason));
9013 }
b05a1c8b 9014
9b6d8fcf 9015 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9016 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9017
d62a17ae 9018 /* Internal route. */
9b6d8fcf
DS
9019 if ((path->peer->as)
9020 && (path->peer->as == path->peer->local_as))
d62a17ae 9021 json_object_string_add(json_path, "pathFrom",
9022 "internal");
9023 else
9024 json_object_string_add(json_path, "pathFrom",
9025 "external");
b05a1c8b 9026
d62a17ae 9027 return;
9028 }
b05a1c8b 9029
82c298be
DA
9030 /* RPKI validation state */
9031 rpki_state =
9032 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9033
9034 if (rpki_state == RPKI_VALID)
9035 vty_out(vty, "V");
9036 else if (rpki_state == RPKI_INVALID)
9037 vty_out(vty, "I");
9038 else if (rpki_state == RPKI_NOTFOUND)
9039 vty_out(vty, "N");
eaeba5e8
WM
9040 else
9041 vty_out(vty, " ");
82c298be 9042
d62a17ae 9043 /* Route status display. */
9b6d8fcf 9044 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9045 vty_out(vty, "R");
9b6d8fcf 9046 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9047 vty_out(vty, "S");
4056a5f6 9048 else if (bgp_path_suppressed(path))
d62a17ae 9049 vty_out(vty, "s");
9b6d8fcf
DS
9050 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9051 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9052 vty_out(vty, "*");
9053 else
9054 vty_out(vty, " ");
9055
9056 /* Selected */
9b6d8fcf 9057 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9058 vty_out(vty, "h");
9b6d8fcf 9059 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9060 vty_out(vty, "d");
9b6d8fcf 9061 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9062 vty_out(vty, ">");
9b6d8fcf 9063 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9064 vty_out(vty, "=");
9065 else
9066 vty_out(vty, " ");
718e3744 9067
d62a17ae 9068 /* Internal route. */
9b6d8fcf
DS
9069 if (path->peer && (path->peer->as)
9070 && (path->peer->as == path->peer->local_as))
d62a17ae 9071 vty_out(vty, "i");
9072 else
9073 vty_out(vty, " ");
b40d939b 9074}
9075
2ba93fd6
DA
9076static char *bgp_nexthop_hostname(struct peer *peer,
9077 struct bgp_nexthop_cache *bnc)
25b5da8d 9078{
892fedb6 9079 if (peer->hostname
aef999a2 9080 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9081 return peer->hostname;
9082 return NULL;
9083}
9084
b40d939b 9085/* called from terminal list command */
bd494ec5 9086void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9087 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9088 json_object *json_paths, bool wide)
d62a17ae 9089{
aef999a2 9090 int len;
515c2602 9091 struct attr *attr = path->attr;
d62a17ae 9092 json_object *json_path = NULL;
9093 json_object *json_nexthops = NULL;
9094 json_object *json_nexthop_global = NULL;
9095 json_object *json_nexthop_ll = NULL;
6f214dd3 9096 json_object *json_ext_community = NULL;
9df8b37c 9097 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9098 bool nexthop_self =
9b6d8fcf 9099 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9100 bool nexthop_othervrf = false;
43089216 9101 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9102 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9103 char *nexthop_hostname =
9104 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9105 char esi_buf[ESI_STR_LEN];
d62a17ae 9106
9107 if (json_paths)
9108 json_path = json_object_new_object();
9109
9110 /* short status lead text */
82c298be 9111 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9112
9113 if (!json_paths) {
9114 /* print prefix and mask */
9115 if (!display)
7d3cae70 9116 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9117 else
ae248832 9118 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9119 } else {
7d3cae70 9120 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9121 }
47fc97cc 9122
9df8b37c
PZ
9123 /*
9124 * If vrf id of nexthop is different from that of prefix,
9125 * set up printable string to append
9126 */
9b6d8fcf 9127 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9128 const char *self = "";
9129
9130 if (nexthop_self)
9131 self = "<";
9132
9133 nexthop_othervrf = true;
9b6d8fcf 9134 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9135
9b6d8fcf 9136 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9137 snprintf(vrf_id_str, sizeof(vrf_id_str),
9138 "@%s%s", VRFID_NONE_STR, self);
9139 else
9140 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9141 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9142
9b6d8fcf
DS
9143 if (path->extra->bgp_orig->inst_type
9144 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9145
9b6d8fcf 9146 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9147 } else {
9148 const char *self = "";
9149
9150 if (nexthop_self)
9151 self = "<";
9152
9153 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9154 }
9155
445c2480
DS
9156 /*
9157 * For ENCAP and EVPN routes, nexthop address family is not
9158 * neccessarily the same as the prefix address family.
9159 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9160 * EVPN routes are also exchanged with a MP nexthop. Currently,
9161 * this
9162 * is only IPv4, the value will be present in either
9163 * attr->nexthop or
9164 * attr->mp_nexthop_global_in
9165 */
9166 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9167 char nexthop[128];
9168 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9169
9170 switch (af) {
9171 case AF_INET:
07380148
DA
9172 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9173 &attr->mp_nexthop_global_in);
445c2480
DS
9174 break;
9175 case AF_INET6:
07380148
DA
9176 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9177 &attr->mp_nexthop_global);
445c2480
DS
9178 break;
9179 default:
772270f3 9180 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9181 break;
d62a17ae 9182 }
d62a17ae 9183
445c2480
DS
9184 if (json_paths) {
9185 json_nexthop_global = json_object_new_object();
9186
515c2602
DA
9187 json_object_string_add(json_nexthop_global, "ip",
9188 nexthop);
9189
939a97f4 9190 if (path->peer->hostname)
515c2602
DA
9191 json_object_string_add(json_nexthop_global,
9192 "hostname",
939a97f4 9193 path->peer->hostname);
515c2602
DA
9194
9195 json_object_string_add(json_nexthop_global, "afi",
9196 (af == AF_INET) ? "ipv4"
9197 : "ipv6");
445c2480
DS
9198 json_object_boolean_true_add(json_nexthop_global,
9199 "used");
aef999a2
DA
9200 } else {
9201 if (nexthop_hostname)
9202 len = vty_out(vty, "%s(%s)%s", nexthop,
9203 nexthop_hostname, vrf_id_str);
9204 else
9205 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9206
ae248832 9207 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9208 if (len < 1)
9209 vty_out(vty, "\n%*s", 36, " ");
9210 else
9211 vty_out(vty, "%*s", len, " ");
9212 }
445c2480
DS
9213 } else if (safi == SAFI_EVPN) {
9214 if (json_paths) {
9215 json_nexthop_global = json_object_new_object();
9216
c949c771 9217 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9218 "%pI4",
9219 &attr->mp_nexthop_global_in);
515c2602 9220
939a97f4 9221 if (path->peer->hostname)
515c2602
DA
9222 json_object_string_add(json_nexthop_global,
9223 "hostname",
939a97f4 9224 path->peer->hostname);
515c2602 9225
a4d82a8a
PZ
9226 json_object_string_add(json_nexthop_global, "afi",
9227 "ipv4");
445c2480
DS
9228 json_object_boolean_true_add(json_nexthop_global,
9229 "used");
aef999a2
DA
9230 } else {
9231 if (nexthop_hostname)
7226bc40
TA
9232 len = vty_out(vty, "%pI4(%s)%s",
9233 &attr->mp_nexthop_global_in,
aef999a2
DA
9234 nexthop_hostname, vrf_id_str);
9235 else
7226bc40
TA
9236 len = vty_out(vty, "%pI4%s",
9237 &attr->mp_nexthop_global_in,
aef999a2
DA
9238 vrf_id_str);
9239
ae248832 9240 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9241 if (len < 1)
9242 vty_out(vty, "\n%*s", 36, " ");
9243 else
9244 vty_out(vty, "%*s", len, " ");
9245 }
d33fc23b 9246 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9247 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9248 if (json_paths) {
9249 json_nexthop_global = json_object_new_object();
515c2602 9250
026b914a
PG
9251 json_object_string_add(json_nexthop_global,
9252 "afi", "ipv4");
c949c771
DA
9253 json_object_string_addf(json_nexthop_global,
9254 "ip", "%pI4",
9255 &attr->nexthop);
515c2602 9256
939a97f4 9257 if (path->peer->hostname)
515c2602
DA
9258 json_object_string_add(
9259 json_nexthop_global, "hostname",
939a97f4 9260 path->peer->hostname);
515c2602 9261
50e05855
AD
9262 json_object_boolean_true_add(
9263 json_nexthop_global,
026b914a
PG
9264 "used");
9265 } else {
aef999a2
DA
9266 if (nexthop_hostname)
9267 len = vty_out(vty, "%pI4(%s)%s",
9268 &attr->nexthop,
9269 nexthop_hostname,
9270 vrf_id_str);
9271 else
9272 len = vty_out(vty, "%pI4%s",
9273 &attr->nexthop,
9274 vrf_id_str);
9275
ae248832 9276 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9277 if (len < 1)
9278 vty_out(vty, "\n%*s", 36, " ");
9279 else
9280 vty_out(vty, "%*s", len, " ");
026b914a
PG
9281 }
9282 }
7226bc40 9283 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9284 if (json_paths) {
9285 json_nexthop_global = json_object_new_object();
d62a17ae 9286
c949c771
DA
9287 json_object_string_addf(json_nexthop_global, "ip",
9288 "%pI4", &attr->nexthop);
515c2602 9289
939a97f4 9290 if (path->peer->hostname)
515c2602
DA
9291 json_object_string_add(json_nexthop_global,
9292 "hostname",
939a97f4 9293 path->peer->hostname);
445c2480 9294
a4d82a8a
PZ
9295 json_object_string_add(json_nexthop_global, "afi",
9296 "ipv4");
445c2480
DS
9297 json_object_boolean_true_add(json_nexthop_global,
9298 "used");
9299 } else {
aef999a2
DA
9300 if (nexthop_hostname)
9301 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9302 nexthop_hostname, vrf_id_str);
9303 else
9304 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9305 vrf_id_str);
9df8b37c 9306
ae248832 9307 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9308 if (len < 1)
9309 vty_out(vty, "\n%*s", 36, " ");
9310 else
9311 vty_out(vty, "%*s", len, " ");
d62a17ae 9312 }
445c2480 9313 }
b05a1c8b 9314
445c2480 9315 /* IPv6 Next Hop */
7226bc40 9316 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9317 if (json_paths) {
9318 json_nexthop_global = json_object_new_object();
c949c771
DA
9319 json_object_string_addf(json_nexthop_global, "ip",
9320 "%pI6",
9321 &attr->mp_nexthop_global);
515c2602 9322
939a97f4 9323 if (path->peer->hostname)
515c2602
DA
9324 json_object_string_add(json_nexthop_global,
9325 "hostname",
939a97f4 9326 path->peer->hostname);
515c2602 9327
a4d82a8a
PZ
9328 json_object_string_add(json_nexthop_global, "afi",
9329 "ipv6");
9330 json_object_string_add(json_nexthop_global, "scope",
9331 "global");
445c2480
DS
9332
9333 /* We display both LL & GL if both have been
9334 * received */
0606039c
DA
9335 if ((attr->mp_nexthop_len
9336 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9337 || (path->peer->conf_if)) {
a4d82a8a 9338 json_nexthop_ll = json_object_new_object();
c949c771
DA
9339 json_object_string_addf(
9340 json_nexthop_ll, "ip", "%pI6",
9341 &attr->mp_nexthop_local);
515c2602 9342
939a97f4 9343 if (path->peer->hostname)
515c2602
DA
9344 json_object_string_add(
9345 json_nexthop_ll, "hostname",
939a97f4 9346 path->peer->hostname);
515c2602 9347
a4d82a8a
PZ
9348 json_object_string_add(json_nexthop_ll, "afi",
9349 "ipv6");
9350 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9351 "link-local");
d62a17ae 9352
a4d82a8a 9353 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9354 &attr->mp_nexthop_local)
9355 != 0)
9356 && !attr->mp_nexthop_prefer_global)
d62a17ae 9357 json_object_boolean_true_add(
a4d82a8a 9358 json_nexthop_ll, "used");
445c2480
DS
9359 else
9360 json_object_boolean_true_add(
a4d82a8a 9361 json_nexthop_global, "used");
445c2480
DS
9362 } else
9363 json_object_boolean_true_add(
9364 json_nexthop_global, "used");
9365 } else {
9366 /* Display LL if LL/Global both in table unless
9367 * prefer-global is set */
2bb8b49c
DS
9368 if (((attr->mp_nexthop_len
9369 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9370 && !attr->mp_nexthop_prefer_global)
9371 || (path->peer->conf_if)) {
9b6d8fcf 9372 if (path->peer->conf_if) {
a4d82a8a 9373 len = vty_out(vty, "%s",
9b6d8fcf 9374 path->peer->conf_if);
ae248832
MK
9375 /* len of IPv6 addr + max len of def
9376 * ifname */
9377 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9378
9379 if (len < 1)
a4d82a8a 9380 vty_out(vty, "\n%*s", 36, " ");
445c2480 9381 else
a4d82a8a 9382 vty_out(vty, "%*s", len, " ");
d62a17ae 9383 } else {
aef999a2
DA
9384 if (nexthop_hostname)
9385 len = vty_out(
9386 vty, "%pI6(%s)%s",
9387 &attr->mp_nexthop_local,
9388 nexthop_hostname,
9389 vrf_id_str);
9390 else
9391 len = vty_out(
9392 vty, "%pI6%s",
9393 &attr->mp_nexthop_local,
9394 vrf_id_str);
9395
ae248832 9396 len = wide ? (41 - len) : (16 - len);
d62a17ae 9397
9398 if (len < 1)
a4d82a8a 9399 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9400 else
a4d82a8a 9401 vty_out(vty, "%*s", len, " ");
d62a17ae 9402 }
445c2480 9403 } else {
aef999a2
DA
9404 if (nexthop_hostname)
9405 len = vty_out(vty, "%pI6(%s)%s",
9406 &attr->mp_nexthop_global,
9407 nexthop_hostname,
9408 vrf_id_str);
9409 else
9410 len = vty_out(vty, "%pI6%s",
9411 &attr->mp_nexthop_global,
9412 vrf_id_str);
9413
ae248832 9414 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9415
9416 if (len < 1)
9417 vty_out(vty, "\n%*s", 36, " ");
9418 else
9419 vty_out(vty, "%*s", len, " ");
d62a17ae 9420 }
9421 }
445c2480 9422 }
718e3744 9423
445c2480
DS
9424 /* MED/Metric */
9425 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9426 if (json_paths)
50e05855 9427 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9428 else if (wide)
9429 vty_out(vty, "%7u", attr->med);
0fbac0b4 9430 else
445c2480 9431 vty_out(vty, "%10u", attr->med);
ae248832
MK
9432 else if (!json_paths) {
9433 if (wide)
9434 vty_out(vty, "%*s", 7, " ");
9435 else
9436 vty_out(vty, "%*s", 10, " ");
9437 }
d62a17ae 9438
445c2480
DS
9439 /* Local Pref */
9440 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9441 if (json_paths)
50e05855 9442 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9443 attr->local_pref);
9444 else
445c2480
DS
9445 vty_out(vty, "%7u", attr->local_pref);
9446 else if (!json_paths)
9447 vty_out(vty, " ");
d62a17ae 9448
445c2480
DS
9449 if (json_paths)
9450 json_object_int_add(json_path, "weight", attr->weight);
9451 else
9452 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9453
47e12884
DA
9454 if (json_paths)
9455 json_object_string_addf(json_path, "peerId", "%pSU",
9456 &path->peer->su);
b05a1c8b 9457
445c2480
DS
9458 /* Print aspath */
9459 if (attr->aspath) {
0fbac0b4 9460 if (json_paths)
50e05855 9461 json_object_string_add(json_path, "path",
0fbac0b4
DA
9462 attr->aspath->str);
9463 else
e678b143 9464 aspath_print_vty(vty, attr->aspath);
d62a17ae 9465 }
f1aa5d8a 9466
445c2480
DS
9467 /* Print origin */
9468 if (json_paths)
a4d82a8a
PZ
9469 json_object_string_add(json_path, "origin",
9470 bgp_origin_long_str[attr->origin]);
445c2480
DS
9471 else
9472 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9473
9df8b37c 9474 if (json_paths) {
d071f237 9475 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9476 json_object_string_add(json_path, "esi",
9477 esi_to_str(&attr->esi,
9478 esi_buf, sizeof(esi_buf)));
9479 }
6f214dd3
CS
9480 if (safi == SAFI_EVPN &&
9481 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9482 json_ext_community = json_object_new_object();
b53e67a3
DA
9483 json_object_string_add(
9484 json_ext_community, "string",
9485 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9486 json_object_object_add(json_path,
9487 "extendedCommunity",
9488 json_ext_community);
9489 }
9490
9df8b37c
PZ
9491 if (nexthop_self)
9492 json_object_boolean_true_add(json_path,
9493 "announceNexthopSelf");
9494 if (nexthop_othervrf) {
9495 json_object_string_add(json_path, "nhVrfName",
9496 nexthop_vrfname);
9497
9498 json_object_int_add(json_path, "nhVrfId",
9499 ((nexthop_vrfid == VRF_UNKNOWN)
9500 ? -1
9501 : (int)nexthop_vrfid));
9502 }
9503 }
9504
d62a17ae 9505 if (json_paths) {
9506 if (json_nexthop_global || json_nexthop_ll) {
9507 json_nexthops = json_object_new_array();
f1aa5d8a 9508
d62a17ae 9509 if (json_nexthop_global)
9510 json_object_array_add(json_nexthops,
9511 json_nexthop_global);
f1aa5d8a 9512
d62a17ae 9513 if (json_nexthop_ll)
9514 json_object_array_add(json_nexthops,
9515 json_nexthop_ll);
f1aa5d8a 9516
d62a17ae 9517 json_object_object_add(json_path, "nexthops",
9518 json_nexthops);
9519 }
9520
9521 json_object_array_add(json_paths, json_path);
9522 } else {
9523 vty_out(vty, "\n");
6f214dd3 9524
b5e140c8 9525 if (safi == SAFI_EVPN) {
d071f237 9526 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9527 /* XXX - add these params to the json out */
b5e140c8 9528 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9529 vty_out(vty, "ESI:%s",
9530 esi_to_str(&attr->esi, esi_buf,
9531 sizeof(esi_buf)));
60605cbc 9532
229587fb 9533 vty_out(vty, "\n");
b5e140c8
AK
9534 }
9535 if (attr->flag &
9536 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9537 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9538 vty_out(vty, "%s\n",
9539 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9540 }
6f214dd3
CS
9541 }
9542
49e5a4a0 9543#ifdef ENABLE_BGP_VNC
d62a17ae 9544 /* prints an additional line, indented, with VNC info, if
9545 * present */
9546 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9547 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9548#endif
d62a17ae 9549 }
9550}
718e3744 9551
9552/* called from terminal list command */
7d3cae70
DA
9553void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9554 const struct prefix *p, struct attr *attr, safi_t safi,
9555 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9556{
9557 json_object *json_status = NULL;
9558 json_object *json_net = NULL;
aef999a2 9559 int len;
d62a17ae 9560 char buff[BUFSIZ];
dc387b0f 9561
d62a17ae 9562 /* Route status display. */
9563 if (use_json) {
9564 json_status = json_object_new_object();
9565 json_net = json_object_new_object();
9566 } else {
146c574b 9567 vty_out(vty, " *");
d62a17ae 9568 vty_out(vty, ">");
9569 vty_out(vty, " ");
9570 }
718e3744 9571
d62a17ae 9572 /* print prefix and mask */
50e05855 9573 if (use_json) {
dc387b0f
LK
9574 if (safi == SAFI_EVPN)
9575 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9576 else if (p->family == AF_INET || p->family == AF_INET6) {
9577 json_object_string_add(
9578 json_net, "addrPrefix",
9579 inet_ntop(p->family, &p->u.prefix, buff,
9580 BUFSIZ));
9581 json_object_int_add(json_net, "prefixLen",
9582 p->prefixlen);
67d7e256 9583 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9584 }
50e05855 9585 } else
7d3cae70 9586 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9587
9588 /* Print attribute */
9589 if (attr) {
9590 if (use_json) {
7226bc40
TA
9591 if (p->family == AF_INET &&
9592 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9593 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9594 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9595 json_object_string_addf(
9596 json_net, "nextHop", "%pI4",
9597 &attr->mp_nexthop_global_in);
d62a17ae 9598 else
c949c771
DA
9599 json_object_string_addf(
9600 json_net, "nextHop", "%pI4",
9601 &attr->nexthop);
7226bc40
TA
9602 } else if (p->family == AF_INET6 ||
9603 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9604 json_object_string_addf(
9605 json_net, "nextHopGlobal", "%pI6",
9606 &attr->mp_nexthop_global);
7226bc40
TA
9607 } else if (p->family == AF_EVPN &&
9608 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9609 json_object_string_addf(
9610 json_net, "nextHop", "%pI4",
9611 &attr->mp_nexthop_global_in);
23d0a753 9612 }
d62a17ae 9613
9614 if (attr->flag
9615 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9616 json_object_int_add(json_net, "metric",
9617 attr->med);
9618
0fbac0b4 9619 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9620 json_object_int_add(json_net, "locPrf",
0fbac0b4 9621 attr->local_pref);
d62a17ae 9622
9623 json_object_int_add(json_net, "weight", attr->weight);
9624
9625 /* Print aspath */
0fbac0b4 9626 if (attr->aspath)
50e05855 9627 json_object_string_add(json_net, "path",
0fbac0b4 9628 attr->aspath->str);
d62a17ae 9629
9630 /* Print origin */
dd426a51
DA
9631#if CONFDATE > 20231208
9632CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9633#endif
d62a17ae 9634 json_object_string_add(json_net, "bgpOriginCode",
9635 bgp_origin_str[attr->origin]);
dd426a51
DA
9636 json_object_string_add(
9637 json_net, "origin",
9638 bgp_origin_long_str[attr->origin]);
d62a17ae 9639 } else {
7226bc40
TA
9640 if (p->family == AF_INET &&
9641 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9642 safi == SAFI_EVPN ||
9643 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9644 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9645 || safi == SAFI_EVPN)
23d0a753
DA
9646 vty_out(vty, "%-16pI4",
9647 &attr->mp_nexthop_global_in);
ae248832 9648 else if (wide)
23d0a753 9649 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9650 else
23d0a753 9651 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9652 } else if (p->family == AF_INET6 ||
9653 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9654 len = vty_out(vty, "%pI6",
9655 &attr->mp_nexthop_global);
ae248832 9656 len = wide ? (41 - len) : (16 - len);
d62a17ae 9657 if (len < 1)
9658 vty_out(vty, "\n%*s", 36, " ");
9659 else
9660 vty_out(vty, "%*s", len, " ");
9661 }
9662 if (attr->flag
9663 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9664 if (wide)
9665 vty_out(vty, "%7u", attr->med);
9666 else
9667 vty_out(vty, "%10u", attr->med);
9668 else if (wide)
9669 vty_out(vty, " ");
d62a17ae 9670 else
9671 vty_out(vty, " ");
718e3744 9672
d62a17ae 9673 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9674 vty_out(vty, "%7u", attr->local_pref);
9675 else
9676 vty_out(vty, " ");
9677
9678 vty_out(vty, "%7u ", attr->weight);
9679
9680 /* Print aspath */
9681 if (attr->aspath)
e678b143 9682 aspath_print_vty(vty, attr->aspath);
d62a17ae 9683
9684 /* Print origin */
9685 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9686 }
9687 }
9688 if (use_json) {
4d65410c
DA
9689 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9690
dd426a51
DA
9691#if CONFDATE > 20231208
9692CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9693#endif
d62a17ae 9694 json_object_boolean_true_add(json_status, "*");
9695 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9696 json_object_boolean_true_add(json_net, "valid");
9697 json_object_boolean_true_add(json_net, "best");
4d65410c 9698
dd426a51 9699 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9700 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9701 json_object_boolean_true_add(json_net, "multipath");
9702 }
d62a17ae 9703 json_object_object_add(json_net, "appliedStatusSymbols",
9704 json_status);
511211bf 9705 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9706 } else
9707 vty_out(vty, "\n");
9708}
9709
bd494ec5 9710void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9711 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9712 json_object *json)
9713{
9714 json_object *json_out = NULL;
9715 struct attr *attr;
9716 mpls_label_t label = MPLS_INVALID_LABEL;
9717
9b6d8fcf 9718 if (!path->extra)
d62a17ae 9719 return;
9720
9721 if (json)
9722 json_out = json_object_new_object();
9723
9724 /* short status lead text */
82c298be 9725 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9726
9727 /* print prefix and mask */
9728 if (json == NULL) {
9729 if (!display)
7d3cae70 9730 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9731 else
9732 vty_out(vty, "%*s", 17, " ");
9733 }
9734
9735 /* Print attribute */
9b6d8fcf 9736 attr = path->attr;
7226bc40
TA
9737 if (((p->family == AF_INET) &&
9738 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9739 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9740 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9741 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9742 || safi == SAFI_EVPN) {
9743 if (json)
c949c771
DA
9744 json_object_string_addf(
9745 json_out, "mpNexthopGlobalIn", "%pI4",
9746 &attr->mp_nexthop_global_in);
05864da7 9747 else
23d0a753
DA
9748 vty_out(vty, "%-16pI4",
9749 &attr->mp_nexthop_global_in);
05864da7
DS
9750 } else {
9751 if (json)
c949c771
DA
9752 json_object_string_addf(json_out, "nexthop",
9753 "%pI4", &attr->nexthop);
05864da7 9754 else
23d0a753 9755 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9756 }
7226bc40
TA
9757 } else if (((p->family == AF_INET6) &&
9758 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9759 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9760 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9761 char buf_a[512];
9762
9763 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9764 if (json)
c949c771
DA
9765 json_object_string_addf(
9766 json_out, "mpNexthopGlobalIn", "%pI6",
9767 &attr->mp_nexthop_global);
05864da7
DS
9768 else
9769 vty_out(vty, "%s",
9770 inet_ntop(AF_INET6,
9771 &attr->mp_nexthop_global,
9772 buf_a, sizeof(buf_a)));
9773 } else if (attr->mp_nexthop_len
9774 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9775 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9776 &attr->mp_nexthop_global,
9777 &attr->mp_nexthop_local);
9778 if (json)
9779 json_object_string_add(json_out,
9780 "mpNexthopGlobalLocal",
9781 buf_a);
9782 else
9783 vty_out(vty, "%s", buf_a);
d62a17ae 9784 }
9785 }
9786
9b6d8fcf 9787 label = decode_label(&path->extra->label[0]);
d62a17ae 9788
9789 if (bgp_is_valid_label(&label)) {
9790 if (json) {
9791 json_object_int_add(json_out, "notag", label);
9792 json_object_array_add(json, json_out);
9793 } else {
9794 vty_out(vty, "notag/%d", label);
9795 vty_out(vty, "\n");
9796 }
700ddfed
PG
9797 } else if (!json)
9798 vty_out(vty, "\n");
d62a17ae 9799}
718e3744 9800
bd494ec5 9801void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9802 struct bgp_path_info *path, int display,
d62a17ae 9803 json_object *json_paths)
718e3744 9804{
d62a17ae 9805 struct attr *attr;
d62a17ae 9806 json_object *json_path = NULL;
14f51eba
LK
9807 json_object *json_nexthop = NULL;
9808 json_object *json_overlay = NULL;
856ca177 9809
9b6d8fcf 9810 if (!path->extra)
d62a17ae 9811 return;
718e3744 9812
14f51eba
LK
9813 if (json_paths) {
9814 json_path = json_object_new_object();
9815 json_overlay = json_object_new_object();
9816 json_nexthop = json_object_new_object();
9817 }
9818
d62a17ae 9819 /* short status lead text */
82c298be 9820 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9821
d62a17ae 9822 /* print prefix and mask */
9823 if (!display)
7d3cae70 9824 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9825 else
9826 vty_out(vty, "%*s", 17, " ");
9827
9828 /* Print attribute */
9b6d8fcf 9829 attr = path->attr;
05864da7 9830 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9831
05864da7
DS
9832 switch (af) {
9833 case AF_INET:
05864da7 9834 if (!json_path) {
db66cf7c 9835 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9836 } else {
db66cf7c
DA
9837 json_object_string_addf(json_nexthop, "ip", "%pI4",
9838 &attr->mp_nexthop_global_in);
14f51eba 9839
05864da7 9840 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9841
05864da7
DS
9842 json_object_object_add(json_path, "nexthop",
9843 json_nexthop);
9844 }
9845 break;
9846 case AF_INET6:
05864da7 9847 if (!json_path) {
db66cf7c
DA
9848 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9849 &attr->mp_nexthop_local);
05864da7 9850 } else {
db66cf7c
DA
9851 json_object_string_addf(json_nexthop, "ipv6Global",
9852 "%pI6",
9853 &attr->mp_nexthop_global);
14f51eba 9854
db66cf7c
DA
9855 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9856 "%pI6",
9857 &attr->mp_nexthop_local);
14f51eba 9858
05864da7 9859 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9860
05864da7
DS
9861 json_object_object_add(json_path, "nexthop",
9862 json_nexthop);
9863 }
9864 break;
9865 default:
9866 if (!json_path) {
9867 vty_out(vty, "?");
9868 } else {
77a2f8e5
DA
9869 json_object_string_add(json_nexthop, "error",
9870 "Unsupported address-family");
d62a17ae 9871 }
05864da7 9872 }
988258b4 9873
6c924775
DS
9874 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9875
05864da7 9876 if (!json_path)
db66cf7c 9877 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9878 else
db66cf7c 9879 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9880
b53e67a3 9881 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9882 char *mac = NULL;
9883 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9884 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9885 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9886
9887 if (routermac)
9888 mac = ecom_mac2str((char *)routermac->val);
9889 if (mac) {
9890 if (!json_path) {
c4efd0f4 9891 vty_out(vty, "/%s", mac);
05864da7
DS
9892 } else {
9893 json_object_string_add(json_overlay, "rmac",
9894 mac);
988258b4 9895 }
05864da7 9896 XFREE(MTYPE_TMP, mac);
988258b4 9897 }
05864da7 9898 }
718e3744 9899
05864da7
DS
9900 if (!json_path) {
9901 vty_out(vty, "\n");
9902 } else {
9903 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9904
05864da7 9905 json_object_array_add(json_paths, json_path);
14f51eba 9906 }
d62a17ae 9907}
718e3744 9908
d62a17ae 9909/* dampening route */
5f040085
DS
9910static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9911 struct bgp_path_info *path, int display,
9912 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9913 json_object *json_paths)
d62a17ae 9914{
e5be8c1d 9915 struct attr *attr = path->attr;
d62a17ae 9916 int len;
9917 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9918 json_object *json_path = NULL;
9919
9920 if (use_json)
9921 json_path = json_object_new_object();
d62a17ae 9922
9923 /* short status lead text */
e5be8c1d 9924 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9925
9926 /* print prefix and mask */
9927 if (!use_json) {
9928 if (!display)
7d3cae70 9929 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9930 else
9931 vty_out(vty, "%*s", 17, " ");
d62a17ae 9932
e5be8c1d
DA
9933 len = vty_out(vty, "%s", path->peer->host);
9934 len = 17 - len;
9935
9936 if (len < 1)
d62a17ae 9937 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9938 else
9939 vty_out(vty, "%*s", len, " ");
d62a17ae 9940
9b6d8fcf
DS
9941 vty_out(vty, "%s ",
9942 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9943 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9944 use_json, NULL));
d62a17ae 9945
e5be8c1d 9946 if (attr->aspath)
e678b143 9947 aspath_print_vty(vty, attr->aspath);
05864da7 9948
05864da7
DS
9949 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9950
d62a17ae 9951 vty_out(vty, "\n");
e5be8c1d
DA
9952 } else {
9953 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9954 safi, use_json, json_path);
9955
9956 if (attr->aspath)
9957 json_object_string_add(json_path, "asPath",
9958 attr->aspath->str);
9959
9960 json_object_string_add(json_path, "origin",
9961 bgp_origin_str[attr->origin]);
9962 json_object_string_add(json_path, "peerHost", path->peer->host);
9963
9964 json_object_array_add(json_paths, json_path);
9965 }
d62a17ae 9966}
718e3744 9967
d62a17ae 9968/* flap route */
5f040085
DS
9969static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9970 struct bgp_path_info *path, int display,
9971 afi_t afi, safi_t safi, bool use_json,
31258046 9972 json_object *json_paths)
784d3a42 9973{
31258046 9974 struct attr *attr = path->attr;
d62a17ae 9975 struct bgp_damp_info *bdi;
9976 char timebuf[BGP_UPTIME_LEN];
9977 int len;
31258046 9978 json_object *json_path = NULL;
784d3a42 9979
9b6d8fcf 9980 if (!path->extra)
d62a17ae 9981 return;
784d3a42 9982
31258046
DA
9983 if (use_json)
9984 json_path = json_object_new_object();
9985
9b6d8fcf 9986 bdi = path->extra->damp_info;
784d3a42 9987
d62a17ae 9988 /* short status lead text */
31258046 9989 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9990
d62a17ae 9991 if (!use_json) {
9992 if (!display)
7d3cae70 9993 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9994 else
9995 vty_out(vty, "%*s", 17, " ");
784d3a42 9996
31258046
DA
9997 len = vty_out(vty, "%s", path->peer->host);
9998 len = 16 - len;
9999 if (len < 1)
d62a17ae 10000 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10001 else
10002 vty_out(vty, "%*s", len, " ");
784d3a42 10003
31258046
DA
10004 len = vty_out(vty, "%d", bdi->flap);
10005 len = 5 - len;
10006 if (len < 1)
d62a17ae 10007 vty_out(vty, " ");
d62a17ae 10008 else
10009 vty_out(vty, "%*s", len, " ");
d62a17ae 10010
996c9314
LB
10011 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10012 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10013
31258046
DA
10014 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10015 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10016 vty_out(vty, "%s ",
9b6d8fcf 10017 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10018 BGP_UPTIME_LEN, afi,
31258046
DA
10019 safi, use_json, NULL));
10020 else
d62a17ae 10021 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10022
31258046 10023 if (attr->aspath)
e678b143 10024 aspath_print_vty(vty, attr->aspath);
05864da7 10025
05864da7
DS
10026 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10027
d62a17ae 10028 vty_out(vty, "\n");
31258046
DA
10029 } else {
10030 json_object_string_add(json_path, "peerHost", path->peer->host);
10031 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10032
10033 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10034 json_path);
10035
10036 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10037 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10038 bgp_damp_reuse_time_vty(vty, path, timebuf,
10039 BGP_UPTIME_LEN, afi, safi,
10040 use_json, json_path);
10041
10042 if (attr->aspath)
10043 json_object_string_add(json_path, "asPath",
10044 attr->aspath->str);
10045
10046 json_object_string_add(json_path, "origin",
10047 bgp_origin_str[attr->origin]);
10048
10049 json_object_array_add(json_paths, json_path);
10050 }
d62a17ae 10051}
10052
10053static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10054 int *first, const char *header,
10055 json_object *json_adv_to)
10056{
d62a17ae 10057 json_object *json_peer = NULL;
10058
10059 if (json_adv_to) {
10060 /* 'advertised-to' is a dictionary of peers we have advertised
10061 * this
10062 * prefix too. The key is the peer's IP or swpX, the value is
10063 * the
10064 * hostname if we know it and "" if not.
10065 */
10066 json_peer = json_object_new_object();
10067
10068 if (peer->hostname)
10069 json_object_string_add(json_peer, "hostname",
10070 peer->hostname);
10071
10072 if (peer->conf_if)
10073 json_object_object_add(json_adv_to, peer->conf_if,
10074 json_peer);
10075 else
47e12884
DA
10076 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10077 &peer->su);
d62a17ae 10078 } else {
10079 if (*first) {
10080 vty_out(vty, "%s", header);
10081 *first = 0;
10082 }
10083
10084 if (peer->hostname
892fedb6 10085 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10086 if (peer->conf_if)
10087 vty_out(vty, " %s(%s)", peer->hostname,
10088 peer->conf_if);
10089 else
47e12884
DA
10090 vty_out(vty, " %s(%pSU)", peer->hostname,
10091 &peer->su);
d62a17ae 10092 } else {
10093 if (peer->conf_if)
10094 vty_out(vty, " %s", peer->conf_if);
10095 else
47e12884 10096 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10097 }
10098 }
784d3a42
PG
10099}
10100
dcc68b5e
MS
10101static void route_vty_out_tx_ids(struct vty *vty,
10102 struct bgp_addpath_info_data *d)
10103{
10104 int i;
10105
10106 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10107 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10108 d->addpath_tx_id[i],
10109 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10110 }
10111}
10112
5e4d4c8a 10113static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10114 struct bgp_path_info *pi,
10115 struct attr *attr,
10116 json_object *json_path)
5e4d4c8a
AK
10117{
10118 char esi_buf[ESI_STR_LEN];
10119 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10120 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10121 ATTR_ES_PEER_ROUTER);
10122 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10123 ATTR_ES_PEER_ACTIVE);
10124 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10125 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10126 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10127 if (json_path) {
10128 json_object *json_es_info = NULL;
10129
10130 json_object_string_add(
10131 json_path, "esi",
10132 esi_buf);
10133 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10134 json_es_info = json_object_new_object();
10135 if (es_local)
10136 json_object_boolean_true_add(
10137 json_es_info, "localEs");
10138 if (peer_active)
10139 json_object_boolean_true_add(
10140 json_es_info, "peerActive");
10141 if (peer_proxy)
10142 json_object_boolean_true_add(
10143 json_es_info, "peerProxy");
10144 if (peer_router)
10145 json_object_boolean_true_add(
10146 json_es_info, "peerRouter");
10147 if (attr->mm_sync_seqnum)
10148 json_object_int_add(
10149 json_es_info, "peerSeq",
10150 attr->mm_sync_seqnum);
10151 json_object_object_add(
10152 json_path, "es_info",
10153 json_es_info);
10154 }
10155 } else {
10156 if (bgp_evpn_attr_is_sync(attr))
10157 vty_out(vty,
10158 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10159 esi_buf,
10160 es_local ? "local-es":"",
10161 peer_proxy ? "proxy " : "",
10162 peer_active ? "active ":"",
10163 peer_router ? "router ":"",
10164 attr->mm_sync_seqnum);
10165 else
10166 vty_out(vty, " ESI %s %s\n",
10167 esi_buf,
10168 es_local ? "local-es":"");
10169 }
10170}
10171
4933eaaf 10172void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10173 const struct prefix *p, struct bgp_path_info *path,
10174 afi_t afi, safi_t safi,
4027d19b
DS
10175 enum rpki_states rpki_curr_state,
10176 json_object *json_paths)
d62a17ae 10177{
10178 char buf[INET6_ADDRSTRLEN];
100290e4 10179 char tag_buf[30];
515c2602 10180 struct attr *attr = path->attr;
d62a17ae 10181 time_t tbuf;
10182 json_object *json_bestpath = NULL;
10183 json_object *json_cluster_list = NULL;
10184 json_object *json_cluster_list_list = NULL;
10185 json_object *json_ext_community = NULL;
10186 json_object *json_last_update = NULL;
7fd077aa 10187 json_object *json_pmsi = NULL;
d62a17ae 10188 json_object *json_nexthop_global = NULL;
10189 json_object *json_nexthop_ll = NULL;
10190 json_object *json_nexthops = NULL;
10191 json_object *json_path = NULL;
10192 json_object *json_peer = NULL;
10193 json_object *json_string = NULL;
10194 json_object *json_adv_to = NULL;
10195 int first = 0;
10196 struct listnode *node, *nnode;
10197 struct peer *peer;
be92fc9f 10198 bool addpath_capable;
d62a17ae 10199 int has_adj;
10200 unsigned int first_as;
1defdda8 10201 bool nexthop_self =
9b6d8fcf 10202 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10203 int i;
2ba93fd6
DA
10204 char *nexthop_hostname =
10205 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10206 uint32_t ttl = 0;
10207 uint32_t bos = 0;
10208 uint32_t exp = 0;
10209 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10210 tag_buf[0] = '\0';
f0cde006
LS
10211 struct bgp_path_info *bpi_ultimate =
10212 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10213
10214 if (json_paths) {
10215 json_path = json_object_new_object();
10216 json_peer = json_object_new_object();
10217 json_nexthop_global = json_object_new_object();
10218 }
10219
8304dabf
AD
10220 if (safi == SAFI_EVPN) {
10221 if (!json_paths)
34c7f35f 10222 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10223 }
10224
44c69747 10225 if (path->extra) {
9b6d8fcf
DS
10226 if (path->extra && path->extra->num_labels) {
10227 bgp_evpn_label2str(path->extra->label,
10228 path->extra->num_labels, tag_buf,
a4d82a8a 10229 sizeof(tag_buf));
d62a17ae 10230 }
d7325ee7 10231 if (safi == SAFI_EVPN) {
44c69747 10232 if (!json_paths) {
44c69747
LK
10233 if (tag_buf[0] != '\0')
10234 vty_out(vty, " VNI %s", tag_buf);
44c69747 10235 } else {
1ce23106 10236 if (tag_buf[0])
77a2f8e5
DA
10237 json_object_string_add(json_path, "vni",
10238 tag_buf);
44c69747 10239 }
d7325ee7 10240 }
d62a17ae 10241 }
d62a17ae 10242
8304dabf
AD
10243 if (safi == SAFI_EVPN
10244 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10245 char gwip_buf[INET6_ADDRSTRLEN];
10246
860e740b
IR
10247 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10248 sizeof(gwip_buf));
8304dabf
AD
10249
10250 if (json_paths)
10251 json_object_string_add(json_path, "gatewayIP",
10252 gwip_buf);
10253 else
10254 vty_out(vty, " Gateway IP %s", gwip_buf);
10255 }
10256
2bf9780b 10257 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10258 vty_out(vty, "\n");
10259
100290e4
SW
10260
10261 if (path->extra && path->extra->parent && !json_paths) {
10262 struct bgp_path_info *parent_ri;
10263 struct bgp_dest *dest, *pdest;
10264
10265 parent_ri = (struct bgp_path_info *)path->extra->parent;
10266 dest = parent_ri->net;
10267 if (dest && dest->pdest) {
10268 pdest = dest->pdest;
10269 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10270 vty_out(vty, " Imported from ");
10271 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10272 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10273 pdest));
10274 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10275 (struct prefix_evpn *)
10276 bgp_dest_get_prefix(dest),
10277 tag_buf);
6012963e 10278 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10279 vty_out(vty, ", L3NHG %s",
6012963e
SW
10280 CHECK_FLAG(
10281 attr->es_flags,
10282 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10283 ? "active"
10284 : "inactive");
10285 vty_out(vty, "\n");
10286
4a8cd6ad
PG
10287 } else {
10288 vty_out(vty, " Imported from ");
10289 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10290 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10291 pdest));
10292 vty_out(vty, ":%pFX\n",
100290e4
SW
10293 (struct prefix_evpn *)
10294 bgp_dest_get_prefix(dest));
4a8cd6ad 10295 }
100290e4
SW
10296 }
10297 }
10298
05864da7
DS
10299 /* Line1 display AS-path, Aggregator */
10300 if (attr->aspath) {
10301 if (json_paths) {
10302 if (!attr->aspath->json)
10303 aspath_str_update(attr->aspath, true);
10304 json_object_lock(attr->aspath->json);
10305 json_object_object_add(json_path, "aspath",
10306 attr->aspath->json);
10307 } else {
10308 if (attr->aspath->segments)
e678b143 10309 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10310 else
05864da7 10311 vty_out(vty, " Local");
d62a17ae 10312 }
05864da7 10313 }
d62a17ae 10314
05864da7
DS
10315 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10316 if (json_paths)
10317 json_object_boolean_true_add(json_path, "removed");
10318 else
10319 vty_out(vty, ", (removed)");
10320 }
d62a17ae 10321
05864da7
DS
10322 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10323 if (json_paths)
10324 json_object_boolean_true_add(json_path, "stale");
10325 else
10326 vty_out(vty, ", (stale)");
10327 }
d62a17ae 10328
05864da7
DS
10329 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10330 if (json_paths) {
10331 json_object_int_add(json_path, "aggregatorAs",
10332 attr->aggregator_as);
c949c771
DA
10333 json_object_string_addf(json_path, "aggregatorId",
10334 "%pI4", &attr->aggregator_addr);
05864da7 10335 } else {
88d495a9
DA
10336 vty_out(vty, ", (aggregated by %u %pI4)",
10337 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10338 }
05864da7 10339 }
d62a17ae 10340
05864da7
DS
10341 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10342 PEER_FLAG_REFLECTOR_CLIENT)) {
10343 if (json_paths)
10344 json_object_boolean_true_add(json_path,
10345 "rxedFromRrClient");
10346 else
10347 vty_out(vty, ", (Received from a RR-client)");
10348 }
d62a17ae 10349
05864da7
DS
10350 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10351 PEER_FLAG_RSERVER_CLIENT)) {
10352 if (json_paths)
10353 json_object_boolean_true_add(json_path,
10354 "rxedFromRsClient");
10355 else
10356 vty_out(vty, ", (Received from a RS-client)");
10357 }
d62a17ae 10358
05864da7
DS
10359 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10360 if (json_paths)
10361 json_object_boolean_true_add(json_path,
10362 "dampeningHistoryEntry");
10363 else
10364 vty_out(vty, ", (history entry)");
10365 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10366 if (json_paths)
10367 json_object_boolean_true_add(json_path,
10368 "dampeningSuppressed");
10369 else
10370 vty_out(vty, ", (suppressed due to dampening)");
10371 }
d62a17ae 10372
05864da7
DS
10373 if (!json_paths)
10374 vty_out(vty, "\n");
d62a17ae 10375
05864da7
DS
10376 /* Line2 display Next-hop, Neighbor, Router-id */
10377 /* Display the nexthop */
b54892e0 10378
34c7f35f
SW
10379 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10380 p->family == AF_EVPN) &&
7226bc40
TA
10381 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10382 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10383 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10384 || safi == SAFI_EVPN) {
515c2602 10385 if (json_paths) {
c949c771
DA
10386 json_object_string_addf(
10387 json_nexthop_global, "ip", "%pI4",
10388 &attr->mp_nexthop_global_in);
515c2602 10389
939a97f4 10390 if (path->peer->hostname)
515c2602
DA
10391 json_object_string_add(
10392 json_nexthop_global, "hostname",
939a97f4 10393 path->peer->hostname);
aef999a2
DA
10394 } else {
10395 if (nexthop_hostname)
10396 vty_out(vty, " %pI4(%s)",
10397 &attr->mp_nexthop_global_in,
10398 nexthop_hostname);
10399 else
10400 vty_out(vty, " %pI4",
10401 &attr->mp_nexthop_global_in);
10402 }
d62a17ae 10403 } else {
515c2602 10404 if (json_paths) {
c949c771
DA
10405 json_object_string_addf(json_nexthop_global,
10406 "ip", "%pI4",
10407 &attr->nexthop);
515c2602 10408
939a97f4 10409 if (path->peer->hostname)
515c2602
DA
10410 json_object_string_add(
10411 json_nexthop_global, "hostname",
939a97f4 10412 path->peer->hostname);
aef999a2
DA
10413 } else {
10414 if (nexthop_hostname)
10415 vty_out(vty, " %pI4(%s)",
10416 &attr->nexthop,
10417 nexthop_hostname);
10418 else
10419 vty_out(vty, " %pI4",
10420 &attr->nexthop);
10421 }
d62a17ae 10422 }
10423
05864da7
DS
10424 if (json_paths)
10425 json_object_string_add(json_nexthop_global, "afi",
10426 "ipv4");
10427 } else {
10428 if (json_paths) {
c949c771
DA
10429 json_object_string_addf(json_nexthop_global, "ip",
10430 "%pI6",
10431 &attr->mp_nexthop_global);
515c2602 10432
939a97f4 10433 if (path->peer->hostname)
515c2602
DA
10434 json_object_string_add(json_nexthop_global,
10435 "hostname",
939a97f4 10436 path->peer->hostname);
515c2602 10437
05864da7
DS
10438 json_object_string_add(json_nexthop_global, "afi",
10439 "ipv6");
10440 json_object_string_add(json_nexthop_global, "scope",
10441 "global");
10442 } else {
aef999a2
DA
10443 if (nexthop_hostname)
10444 vty_out(vty, " %pI6(%s)",
10445 &attr->mp_nexthop_global,
10446 nexthop_hostname);
10447 else
10448 vty_out(vty, " %pI6",
10449 &attr->mp_nexthop_global);
d62a17ae 10450 }
05864da7 10451 }
d62a17ae 10452
05864da7 10453 /* Display the IGP cost or 'inaccessible' */
f0cde006 10454 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10455 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10456
10457 if (json_paths) {
05864da7
DS
10458 json_object_boolean_false_add(json_nexthop_global,
10459 "accessible");
95ba22d5
DA
10460 json_object_boolean_add(json_nexthop_global,
10461 "importCheckEnabled", import);
10462 } else {
10463 vty_out(vty, " (inaccessible%s)",
10464 import ? ", import-check enabled" : "");
10465 }
05864da7 10466 } else {
f0cde006 10467 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10468 if (json_paths)
f0cde006
LS
10469 json_object_int_add(
10470 json_nexthop_global, "metric",
10471 bpi_ultimate->extra->igpmetric);
d62a17ae 10472 else
05864da7 10473 vty_out(vty, " (metric %u)",
f0cde006 10474 bpi_ultimate->extra->igpmetric);
d62a17ae 10475 }
10476
05864da7 10477 /* IGP cost is 0, display this only for json */
d62a17ae 10478 else {
d62a17ae 10479 if (json_paths)
05864da7
DS
10480 json_object_int_add(json_nexthop_global,
10481 "metric", 0);
d62a17ae 10482 }
d62a17ae 10483
05864da7
DS
10484 if (json_paths)
10485 json_object_boolean_true_add(json_nexthop_global,
10486 "accessible");
10487 }
d62a17ae 10488
05864da7
DS
10489 /* Display peer "from" output */
10490 /* This path was originated locally */
10491 if (path->peer == bgp->peer_self) {
d62a17ae 10492
34c7f35f 10493 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10494 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10495 if (json_paths)
05864da7
DS
10496 json_object_string_add(json_peer, "peerId",
10497 "0.0.0.0");
d62a17ae 10498 else
05864da7
DS
10499 vty_out(vty, " from 0.0.0.0 ");
10500 } else {
d62a17ae 10501 if (json_paths)
05864da7
DS
10502 json_object_string_add(json_peer, "peerId",
10503 "::");
d62a17ae 10504 else
05864da7 10505 vty_out(vty, " from :: ");
d62a17ae 10506 }
d62a17ae 10507
4e9a9863 10508 if (json_paths)
c949c771
DA
10509 json_object_string_addf(json_peer, "routerId", "%pI4",
10510 &bgp->router_id);
4e9a9863 10511 else
23d0a753 10512 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10513 }
d62a17ae 10514
05864da7
DS
10515 /* We RXed this path from one of our peers */
10516 else {
10517
10518 if (json_paths) {
47e12884
DA
10519 json_object_string_addf(json_peer, "peerId", "%pSU",
10520 &path->peer->su);
c949c771
DA
10521 json_object_string_addf(json_peer, "routerId", "%pI4",
10522 &path->peer->remote_id);
05864da7
DS
10523
10524 if (path->peer->hostname)
10525 json_object_string_add(json_peer, "hostname",
10526 path->peer->hostname);
10527
10528 if (path->peer->domainname)
10529 json_object_string_add(json_peer, "domainname",
10530 path->peer->domainname);
10531
10532 if (path->peer->conf_if)
10533 json_object_string_add(json_peer, "interface",
10534 path->peer->conf_if);
10535 } else {
10536 if (path->peer->conf_if) {
10537 if (path->peer->hostname
892fedb6
DA
10538 && CHECK_FLAG(path->peer->bgp->flags,
10539 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10540 vty_out(vty, " from %s(%s)",
10541 path->peer->hostname,
10542 path->peer->conf_if);
d62a17ae 10543 else
05864da7 10544 vty_out(vty, " from %s",
9b6d8fcf 10545 path->peer->conf_if);
d62a17ae 10546 } else {
05864da7 10547 if (path->peer->hostname
892fedb6
DA
10548 && CHECK_FLAG(path->peer->bgp->flags,
10549 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10550 vty_out(vty, " from %s(%s)",
10551 path->peer->hostname,
10552 path->peer->host);
d62a17ae 10553 else
47e12884
DA
10554 vty_out(vty, " from %pSU",
10555 &path->peer->su);
d62a17ae 10556 }
d62a17ae 10557
05864da7 10558 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10559 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10560 else
07380148 10561 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10562 }
05864da7 10563 }
9df8b37c 10564
05864da7
DS
10565 /*
10566 * Note when vrfid of nexthop is different from that of prefix
10567 */
10568 if (path->extra && path->extra->bgp_orig) {
10569 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10570
05864da7
DS
10571 if (json_paths) {
10572 const char *vn;
9df8b37c 10573
05864da7
DS
10574 if (path->extra->bgp_orig->inst_type
10575 == BGP_INSTANCE_TYPE_DEFAULT)
10576 vn = VRF_DEFAULT_NAME;
10577 else
10578 vn = path->extra->bgp_orig->name;
9df8b37c 10579
05864da7 10580 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10581
05864da7
DS
10582 if (nexthop_vrfid == VRF_UNKNOWN) {
10583 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10584 } else {
05864da7
DS
10585 json_object_int_add(json_path, "nhVrfId",
10586 (int)nexthop_vrfid);
9df8b37c 10587 }
05864da7
DS
10588 } else {
10589 if (nexthop_vrfid == VRF_UNKNOWN)
10590 vty_out(vty, " vrf ?");
137147c6
DS
10591 else {
10592 struct vrf *vrf;
10593
10594 vrf = vrf_lookup_by_id(nexthop_vrfid);
10595 vty_out(vty, " vrf %s(%u)",
10596 VRF_LOGNAME(vrf), nexthop_vrfid);
10597 }
9df8b37c 10598 }
05864da7 10599 }
9df8b37c 10600
05864da7
DS
10601 if (nexthop_self) {
10602 if (json_paths) {
10603 json_object_boolean_true_add(json_path,
10604 "announceNexthopSelf");
10605 } else {
10606 vty_out(vty, " announce-nh-self");
9df8b37c 10607 }
05864da7 10608 }
9df8b37c 10609
05864da7
DS
10610 if (!json_paths)
10611 vty_out(vty, "\n");
d62a17ae 10612
05864da7
DS
10613 /* display the link-local nexthop */
10614 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10615 if (json_paths) {
10616 json_nexthop_ll = json_object_new_object();
c949c771
DA
10617 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10618 &attr->mp_nexthop_local);
515c2602 10619
939a97f4 10620 if (path->peer->hostname)
515c2602
DA
10621 json_object_string_add(json_nexthop_ll,
10622 "hostname",
939a97f4 10623 path->peer->hostname);
515c2602 10624
05864da7
DS
10625 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10626 json_object_string_add(json_nexthop_ll, "scope",
10627 "link-local");
d62a17ae 10628
05864da7
DS
10629 json_object_boolean_true_add(json_nexthop_ll,
10630 "accessible");
d62a17ae 10631
2bb8b49c 10632 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10633 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10634 "used");
10635 else
10636 json_object_boolean_true_add(
10637 json_nexthop_global, "used");
10638 } else {
10639 vty_out(vty, " (%s) %s\n",
10640 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10641 buf, INET6_ADDRSTRLEN),
2bb8b49c 10642 attr->mp_nexthop_prefer_global
05864da7
DS
10643 ? "(prefer-global)"
10644 : "(used)");
d62a17ae 10645 }
05864da7
DS
10646 }
10647 /* If we do not have a link-local nexthop then we must flag the
10648 global as "used" */
10649 else {
10650 if (json_paths)
10651 json_object_boolean_true_add(json_nexthop_global,
10652 "used");
10653 }
d62a17ae 10654
b5e140c8 10655 if (safi == SAFI_EVPN &&
5e4d4c8a 10656 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10657 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10658 }
10659
05864da7
DS
10660 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10661 * Int/Ext/Local, Atomic, best */
10662 if (json_paths)
10663 json_object_string_add(json_path, "origin",
10664 bgp_origin_long_str[attr->origin]);
10665 else
10666 vty_out(vty, " Origin %s",
10667 bgp_origin_long_str[attr->origin]);
9df8b37c 10668
05864da7 10669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10670 if (json_paths)
05864da7 10671 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10672 else
05864da7
DS
10673 vty_out(vty, ", metric %u", attr->med);
10674 }
9df8b37c 10675
05864da7
DS
10676 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10677 if (json_paths)
0fbac0b4 10678 json_object_int_add(json_path, "locPrf",
05864da7
DS
10679 attr->local_pref);
10680 else
10681 vty_out(vty, ", localpref %u", attr->local_pref);
10682 }
9df8b37c 10683
97a52c82
DA
10684 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10685 if (json_paths)
10686 json_object_int_add(json_path, "aigpMetric",
10687 bgp_attr_get_aigp_metric(attr));
10688 else
10689 vty_out(vty, ", aigp-metric %" PRIu64,
10690 bgp_attr_get_aigp_metric(attr));
10691 }
10692
05864da7
DS
10693 if (attr->weight != 0) {
10694 if (json_paths)
10695 json_object_int_add(json_path, "weight", attr->weight);
10696 else
10697 vty_out(vty, ", weight %u", attr->weight);
10698 }
9df8b37c 10699
05864da7
DS
10700 if (attr->tag != 0) {
10701 if (json_paths)
10702 json_object_int_add(json_path, "tag", attr->tag);
10703 else
10704 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10705 }
9df8b37c 10706
05864da7
DS
10707 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10708 if (json_paths)
10709 json_object_boolean_false_add(json_path, "valid");
10710 else
10711 vty_out(vty, ", invalid");
10712 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10713 if (json_paths)
10714 json_object_boolean_true_add(json_path, "valid");
10715 else
10716 vty_out(vty, ", valid");
10717 }
9df8b37c 10718
7d3cae70
DA
10719 if (json_paths)
10720 json_object_int_add(json_path, "version", bn->version);
10721
05864da7
DS
10722 if (path->peer != bgp->peer_self) {
10723 if (path->peer->as == path->peer->local_as) {
10724 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10725 if (json_paths)
10726 json_object_string_add(
10727 json_peer, "type",
10728 "confed-internal");
d62a17ae 10729 else
05864da7 10730 vty_out(vty, ", confed-internal");
d62a17ae 10731 } else {
05864da7
DS
10732 if (json_paths)
10733 json_object_string_add(
10734 json_peer, "type", "internal");
10735 else
10736 vty_out(vty, ", internal");
9df8b37c 10737 }
05864da7
DS
10738 } else {
10739 if (bgp_confederation_peers_check(bgp,
10740 path->peer->as)) {
10741 if (json_paths)
10742 json_object_string_add(
10743 json_peer, "type",
10744 "confed-external");
d62a17ae 10745 else
05864da7 10746 vty_out(vty, ", confed-external");
d62a17ae 10747 } else {
05864da7
DS
10748 if (json_paths)
10749 json_object_string_add(
10750 json_peer, "type", "external");
10751 else
10752 vty_out(vty, ", external");
d62a17ae 10753 }
10754 }
05864da7
DS
10755 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10756 if (json_paths) {
10757 json_object_boolean_true_add(json_path, "aggregated");
10758 json_object_boolean_true_add(json_path, "local");
10759 } else {
10760 vty_out(vty, ", aggregated, local");
10761 }
10762 } else if (path->type != ZEBRA_ROUTE_BGP) {
10763 if (json_paths)
10764 json_object_boolean_true_add(json_path, "sourced");
10765 else
10766 vty_out(vty, ", sourced");
10767 } else {
10768 if (json_paths) {
10769 json_object_boolean_true_add(json_path, "sourced");
10770 json_object_boolean_true_add(json_path, "local");
10771 } else {
10772 vty_out(vty, ", sourced, local");
d62a17ae 10773 }
05864da7 10774 }
718e3744 10775
05864da7 10776 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10777 if (json_paths)
05864da7
DS
10778 json_object_boolean_true_add(json_path,
10779 "atomicAggregate");
d62a17ae 10780 else
05864da7
DS
10781 vty_out(vty, ", atomic-aggregate");
10782 }
d62a17ae 10783
d864dd9e
EB
10784 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10785 if (json_paths)
10786 json_object_int_add(json_path, "otc", attr->otc);
10787 else
10788 vty_out(vty, ", otc %u", attr->otc);
10789 }
10790
05864da7
DS
10791 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10792 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10793 && bgp_path_info_mpath_count(path))) {
10794 if (json_paths)
10795 json_object_boolean_true_add(json_path, "multipath");
10796 else
10797 vty_out(vty, ", multipath");
10798 }
50e05855 10799
05864da7
DS
10800 // Mark the bestpath(s)
10801 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10802 first_as = aspath_get_first_as(attr->aspath);
718e3744 10803
05864da7
DS
10804 if (json_paths) {
10805 if (!json_bestpath)
10806 json_bestpath = json_object_new_object();
10807 json_object_int_add(json_bestpath, "bestpathFromAs",
10808 first_as);
10809 } else {
10810 if (first_as)
10811 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10812 else
05864da7 10813 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10814 }
05864da7 10815 }
718e3744 10816
05864da7
DS
10817 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10818 if (json_paths) {
10819 if (!json_bestpath)
10820 json_bestpath = json_object_new_object();
10821 json_object_boolean_true_add(json_bestpath, "overall");
10822 json_object_string_add(
10823 json_bestpath, "selectionReason",
10824 bgp_path_selection_reason2str(bn->reason));
10825 } else {
10826 vty_out(vty, ", best");
10827 vty_out(vty, " (%s)",
10828 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10829 }
05864da7 10830 }
718e3744 10831
4027d19b 10832 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10833 if (json_paths)
10834 json_object_string_add(
10835 json_path, "rpkiValidationState",
4027d19b 10836 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10837 else
1d327209 10838 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10839 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10840 }
10841
05864da7
DS
10842 if (json_bestpath)
10843 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10844
05864da7
DS
10845 if (!json_paths)
10846 vty_out(vty, "\n");
10847
10848 /* Line 4 display Community */
29e72930 10849 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10850 if (json_paths) {
9a706b42
DA
10851 if (!bgp_attr_get_community(attr)->json)
10852 community_str(bgp_attr_get_community(attr),
c0945b78 10853 true, true);
9a706b42
DA
10854 json_object_lock(bgp_attr_get_community(attr)->json);
10855 json_object_object_add(
10856 json_path, "community",
10857 bgp_attr_get_community(attr)->json);
05864da7
DS
10858 } else {
10859 vty_out(vty, " Community: %s\n",
9a706b42 10860 bgp_attr_get_community(attr)->str);
d62a17ae 10861 }
05864da7 10862 }
718e3744 10863
05864da7
DS
10864 /* Line 5 display Extended-community */
10865 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10866 if (json_paths) {
10867 json_ext_community = json_object_new_object();
b53e67a3
DA
10868 json_object_string_add(
10869 json_ext_community, "string",
10870 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10871 json_object_object_add(json_path, "extendedCommunity",
10872 json_ext_community);
d62a17ae 10873 } else {
05864da7 10874 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10875 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10876 }
05864da7 10877 }
718e3744 10878
05864da7
DS
10879 /* Line 6 display Large community */
10880 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10881 if (json_paths) {
1bcf3a96
DA
10882 if (!bgp_attr_get_lcommunity(attr)->json)
10883 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10884 true, true);
1bcf3a96
DA
10885 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10886 json_object_object_add(
10887 json_path, "largeCommunity",
10888 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10889 } else {
10890 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10891 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10892 }
05864da7 10893 }
718e3744 10894
05864da7
DS
10895 /* Line 7 display Originator, Cluster-id */
10896 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10897 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10898 char buf[BUFSIZ] = {0};
10899
05864da7 10900 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10901 if (json_paths)
c949c771
DA
10902 json_object_string_addf(json_path,
10903 "originatorId", "%pI4",
10904 &attr->originator_id);
d62a17ae 10905 else
23d0a753
DA
10906 vty_out(vty, " Originator: %pI4",
10907 &attr->originator_id);
d62a17ae 10908 }
856ca177 10909
05864da7 10910 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10911 struct cluster_list *cluster =
10912 bgp_attr_get_cluster(attr);
05864da7 10913 int i;
d62a17ae 10914
10915 if (json_paths) {
05864da7
DS
10916 json_cluster_list = json_object_new_object();
10917 json_cluster_list_list =
10918 json_object_new_array();
10919
779fee93 10920 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10921 json_string = json_object_new_string(
779fee93
DS
10922 inet_ntop(AF_INET,
10923 &cluster->list[i],
10924 buf, sizeof(buf)));
05864da7
DS
10925 json_object_array_add(
10926 json_cluster_list_list,
10927 json_string);
10928 }
718e3744 10929
05864da7
DS
10930 /*
10931 * struct cluster_list does not have
10932 * "str" variable like aspath and community
10933 * do. Add this someday if someone asks
10934 * for it.
10935 * json_object_string_add(json_cluster_list,
779fee93 10936 * "string", cluster->str);
05864da7
DS
10937 */
10938 json_object_object_add(json_cluster_list,
10939 "list",
10940 json_cluster_list_list);
10941 json_object_object_add(json_path, "clusterList",
10942 json_cluster_list);
0dc8ee70 10943 } else {
05864da7
DS
10944 vty_out(vty, ", Cluster list: ");
10945
779fee93 10946 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10947 vty_out(vty, "%pI4 ",
779fee93 10948 &cluster->list[i]);
05864da7 10949 }
0dc8ee70 10950 }
d62a17ae 10951 }
718e3744 10952
d62a17ae 10953 if (!json_paths)
10954 vty_out(vty, "\n");
05864da7 10955 }
d62a17ae 10956
05864da7 10957 if (path->extra && path->extra->damp_info)
b4f7f45b 10958 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10959
05864da7
DS
10960 /* Remote Label */
10961 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10962 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10963 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10964 &bos);
d62a17ae 10965
05864da7
DS
10966 if (json_paths)
10967 json_object_int_add(json_path, "remoteLabel", label);
10968 else
10969 vty_out(vty, " Remote label: %d\n", label);
10970 }
d62a17ae 10971
e496b420
HS
10972 /* Remote SID */
10973 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10974 if (json_paths)
07380148
DA
10975 json_object_string_addf(json_path, "remoteSid", "%pI6",
10976 &path->extra->sid[0].sid);
e496b420 10977 else
07380148
DA
10978 vty_out(vty, " Remote SID: %pI6\n",
10979 &path->extra->sid[0].sid);
e496b420
HS
10980 }
10981
05864da7
DS
10982 /* Label Index */
10983 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10984 if (json_paths)
10985 json_object_int_add(json_path, "labelIndex",
10986 attr->label_index);
10987 else
10988 vty_out(vty, " Label Index: %d\n",
10989 attr->label_index);
10990 }
d62a17ae 10991
05864da7
DS
10992 /* Line 8 display Addpath IDs */
10993 if (path->addpath_rx_id
10994 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10995 if (json_paths) {
10996 json_object_int_add(json_path, "addpathRxId",
10997 path->addpath_rx_id);
d62a17ae 10998
05864da7
DS
10999 /* Keep backwards compatibility with the old API
11000 * by putting TX All's ID in the old field
11001 */
11002 json_object_int_add(
11003 json_path, "addpathTxId",
11004 path->tx_addpath
11005 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11006
05864da7
DS
11007 /* ... but create a specific field for each
11008 * strategy
11009 */
11010 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11011 json_object_int_add(
11012 json_path,
11013 bgp_addpath_names(i)->id_json_name,
11014 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11015 }
05864da7
DS
11016 } else {
11017 vty_out(vty, " AddPath ID: RX %u, ",
11018 path->addpath_rx_id);
d62a17ae 11019
05864da7 11020 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11021 }
05864da7 11022 }
520d5d76 11023
05864da7
DS
11024 /* If we used addpath to TX a non-bestpath we need to display
11025 * "Advertised to" on a path-by-path basis
11026 */
11027 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11028 first = 1;
dcc68b5e 11029
05864da7
DS
11030 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11031 addpath_capable =
11032 bgp_addpath_encode_tx(peer, afi, safi);
11033 has_adj = bgp_adj_out_lookup(
11034 peer, path->net,
11035 bgp_addpath_id_for_peer(peer, afi, safi,
11036 &path->tx_addpath));
11037
11038 if ((addpath_capable && has_adj)
11039 || (!addpath_capable && has_adj
11040 && CHECK_FLAG(path->flags,
11041 BGP_PATH_SELECTED))) {
11042 if (json_path && !json_adv_to)
11043 json_adv_to = json_object_new_object();
dcc68b5e 11044
05864da7
DS
11045 route_vty_out_advertised_to(
11046 vty, peer, &first,
11047 " Advertised to:", json_adv_to);
d62a17ae 11048 }
11049 }
718e3744 11050
05864da7
DS
11051 if (json_path) {
11052 if (json_adv_to) {
11053 json_object_object_add(
11054 json_path, "advertisedTo", json_adv_to);
d62a17ae 11055 }
05864da7
DS
11056 } else {
11057 if (!first) {
11058 vty_out(vty, "\n");
d62a17ae 11059 }
11060 }
05864da7 11061 }
b05a1c8b 11062
05864da7 11063 /* Line 9 display Uptime */
083ec940 11064 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11065 if (json_paths) {
11066 json_last_update = json_object_new_object();
11067 json_object_int_add(json_last_update, "epoch", tbuf);
11068 json_object_string_add(json_last_update, "string",
11069 ctime(&tbuf));
11070 json_object_object_add(json_path, "lastUpdate",
11071 json_last_update);
11072 } else
11073 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11074
05864da7
DS
11075 /* Line 10 display PMSI tunnel attribute, if present */
11076 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11077 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11078 bgp_attr_get_pmsi_tnl_type(attr),
11079 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11080
05864da7
DS
11081 if (json_paths) {
11082 json_pmsi = json_object_new_object();
11083 json_object_string_add(json_pmsi, "tunnelType", str);
11084 json_object_int_add(json_pmsi, "label",
11085 label2vni(&attr->label));
11086 json_object_object_add(json_path, "pmsi", json_pmsi);
11087 } else
11088 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11089 str, label2vni(&attr->label));
d62a17ae 11090 }
f1aa5d8a 11091
848e8cf6
DA
11092 if (path->peer->t_gr_restart &&
11093 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11094 unsigned long gr_remaining =
4f830a07 11095 event_timer_remain_second(path->peer->t_gr_restart);
848e8cf6
DA
11096
11097 if (json_paths) {
11098 json_object_int_add(json_path,
11099 "gracefulRestartSecondsRemaining",
11100 gr_remaining);
11101 } else
11102 vty_out(vty,
11103 " Time until Graceful Restart stale route deleted: %lu\n",
11104 gr_remaining);
11105 }
11106
9a706b42
DA
11107 if (path->peer->t_llgr_stale[afi][safi] &&
11108 bgp_attr_get_community(attr) &&
11109 community_include(bgp_attr_get_community(attr),
11110 COMMUNITY_LLGR_STALE)) {
4f830a07 11111 unsigned long llgr_remaining = event_timer_remain_second(
48ebba04 11112 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11113
48ebba04
DA
11114 if (json_paths) {
11115 json_object_int_add(json_path, "llgrSecondsRemaining",
11116 llgr_remaining);
11117 } else
11118 vty_out(vty,
11119 " Time until Long-lived stale route deleted: %lu\n",
11120 llgr_remaining);
11121 }
11122
92269aa2
DS
11123 /* Output some debug about internal state of the dest flags */
11124 if (json_paths) {
11125 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11126 json_object_boolean_true_add(json_path, "processScheduled");
11127 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11128 json_object_boolean_true_add(json_path, "userCleared");
11129 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11130 json_object_boolean_true_add(json_path, "labelChanged");
11131 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11132 json_object_boolean_true_add(json_path, "registeredForLabel");
11133 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11134 json_object_boolean_true_add(json_path, "selectDefered");
11135 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11136 json_object_boolean_true_add(json_path, "fibInstalled");
11137 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11138 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11139
d62a17ae 11140 if (json_nexthop_global || json_nexthop_ll) {
11141 json_nexthops = json_object_new_array();
f1aa5d8a 11142
d62a17ae 11143 if (json_nexthop_global)
11144 json_object_array_add(json_nexthops,
11145 json_nexthop_global);
f1aa5d8a 11146
d62a17ae 11147 if (json_nexthop_ll)
11148 json_object_array_add(json_nexthops,
11149 json_nexthop_ll);
f1aa5d8a 11150
d62a17ae 11151 json_object_object_add(json_path, "nexthops",
11152 json_nexthops);
11153 }
11154
11155 json_object_object_add(json_path, "peer", json_peer);
11156 json_object_array_add(json_paths, json_path);
05864da7 11157 }
b366b518
BB
11158}
11159
96ade3ed 11160#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11161#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11162#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11163
a4d82a8a 11164static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11165 afi_t afi, safi_t safi, enum bgp_show_type type,
11166 bool use_json);
7f323236
DW
11167static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11168 const char *comstr, int exact, afi_t afi,
96c81f66 11169 safi_t safi, uint16_t show_flags);
d62a17ae 11170
1ae44dfc 11171static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11172 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11173 void *output_arg, const char *rd, int is_last,
96f3485c 11174 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11175 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11176 enum rpki_states rpki_target_state)
d62a17ae 11177{
40381db7 11178 struct bgp_path_info *pi;
9bcb3eef 11179 struct bgp_dest *dest;
2aad8c42
MS
11180 bool header = true;
11181 bool json_detail_header = false;
d62a17ae 11182 int display;
1ae44dfc
LB
11183 unsigned long output_count = 0;
11184 unsigned long total_count = 0;
d62a17ae 11185 struct prefix *p;
d62a17ae 11186 json_object *json_paths = NULL;
11187 int first = 1;
96f3485c
MK
11188 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11189 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11190 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11191 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11192 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11193
1ae44dfc 11194 if (output_cum && *output_cum != 0)
2aad8c42 11195 header = false;
1ae44dfc 11196
9386b588 11197 if (use_json && !*json_header_depth) {
96f3485c
MK
11198 if (all)
11199 *json_header_depth = 1;
11200 else {
11201 vty_out(vty, "{\n");
11202 *json_header_depth = 2;
11203 }
d62a17ae 11204 vty_out(vty,
23d0a753
DA
11205 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11206 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11207 " \"localAS\": ",
a8bf7d9c 11208 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11209 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11210 ? VRF_DEFAULT_NAME
11211 : bgp->name,
11212 table->version, &bgp->router_id,
e84c7c12
PG
11213 bgp->default_local_pref);
11214 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11215 ((bgp->asnotation == ASNOTATION_DOT) &&
11216 (bgp->as < UINT16_MAX)))
11217 vty_out(vty, "%u", bgp->as);
11218 else {
11219 vty_out(vty, "\"");
11220 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11221 vty_out(vty, "\"");
11222 }
11223 vty_out(vty, ",\n \"routes\": { ");
9386b588 11224 if (rd) {
445c2480 11225 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11226 ++*json_header_depth;
11227 }
d62a17ae 11228 }
718e3744 11229
445c2480
DS
11230 if (use_json && rd) {
11231 vty_out(vty, " \"%s\" : { ", rd);
11232 }
11233
2aad8c42 11234 /* Check for 'json detail', where we need header output once per dest */
67799a48 11235 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11236 type != bgp_show_type_damp_neighbor &&
11237 type != bgp_show_type_flap_statistics &&
11238 type != bgp_show_type_flap_neighbor)
11239 json_detail_header = true;
11240
d62a17ae 11241 /* Start processing of routes. */
9bcb3eef
DS
11242 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11243 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11244 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11245 bool json_detail_header_used = false;
b54892e0 11246
9bcb3eef 11247 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11248 if (pi == NULL)
98ce9a06 11249 continue;
d62a17ae 11250
98ce9a06 11251 display = 0;
98ce9a06
DS
11252 if (use_json)
11253 json_paths = json_object_new_array();
11254 else
11255 json_paths = NULL;
d62a17ae 11256
6f94b685 11257 for (; pi; pi = pi->next) {
9a706b42
DA
11258 struct community *picomm = NULL;
11259
11260 picomm = bgp_attr_get_community(pi->attr);
11261
98ce9a06 11262 total_count++;
1e2ce4f1 11263
7d3cae70
DA
11264 if (type == bgp_show_type_prefix_version) {
11265 uint32_t version =
11266 strtoul(output_arg, NULL, 10);
11267 if (dest->version < version)
11268 continue;
11269 }
11270
a70a28a5
DA
11271 if (type == bgp_show_type_community_alias) {
11272 char *alias = output_arg;
11273 char **communities;
11274 int num;
11275 bool found = false;
11276
9a706b42
DA
11277 if (picomm) {
11278 frrstr_split(picomm->str, " ",
11279 &communities, &num);
a70a28a5
DA
11280 for (int i = 0; i < num; i++) {
11281 const char *com2alias =
11282 bgp_community2alias(
11283 communities[i]);
cd9cc0e6
IR
11284 if (!found
11285 && strcmp(alias, com2alias)
11286 == 0)
a70a28a5 11287 found = true;
cd9cc0e6
IR
11288 XFREE(MTYPE_TMP,
11289 communities[i]);
a70a28a5 11290 }
cd9cc0e6 11291 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11292 }
11293
1bcf3a96
DA
11294 if (!found &&
11295 bgp_attr_get_lcommunity(pi->attr)) {
11296 frrstr_split(bgp_attr_get_lcommunity(
11297 pi->attr)
11298 ->str,
a70a28a5
DA
11299 " ", &communities, &num);
11300 for (int i = 0; i < num; i++) {
11301 const char *com2alias =
11302 bgp_community2alias(
11303 communities[i]);
cd9cc0e6
IR
11304 if (!found
11305 && strcmp(alias, com2alias)
11306 == 0)
a70a28a5 11307 found = true;
cd9cc0e6
IR
11308 XFREE(MTYPE_TMP,
11309 communities[i]);
a70a28a5 11310 }
cd9cc0e6 11311 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11312 }
11313
11314 if (!found)
11315 continue;
11316 }
11317
1e2ce4f1
DS
11318 if (type == bgp_show_type_rpki) {
11319 if (dest_p->family == AF_INET
11320 || dest_p->family == AF_INET6)
4027d19b 11321 rpki_curr_state = hook_call(
1e2ce4f1
DS
11322 bgp_rpki_prefix_status,
11323 pi->peer, pi->attr, dest_p);
4027d19b
DS
11324 if (rpki_target_state != RPKI_NOT_BEING_USED
11325 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11326 continue;
11327 }
11328
98ce9a06
DS
11329 if (type == bgp_show_type_flap_statistics
11330 || type == bgp_show_type_flap_neighbor
11331 || type == bgp_show_type_dampend_paths
11332 || type == bgp_show_type_damp_neighbor) {
40381db7 11333 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11334 continue;
11335 }
11336 if (type == bgp_show_type_regexp) {
11337 regex_t *regex = output_arg;
d62a17ae 11338
40381db7 11339 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11340 == REG_NOMATCH)
11341 continue;
11342 }
11343 if (type == bgp_show_type_prefix_list) {
11344 struct prefix_list *plist = output_arg;
d62a17ae 11345
9bcb3eef 11346 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11347 != PREFIX_PERMIT)
11348 continue;
11349 }
ed126382
DA
11350 if (type == bgp_show_type_access_list) {
11351 struct access_list *alist = output_arg;
11352
11353 if (access_list_apply(alist, dest_p) !=
11354 FILTER_PERMIT)
11355 continue;
11356 }
98ce9a06
DS
11357 if (type == bgp_show_type_filter_list) {
11358 struct as_list *as_list = output_arg;
d62a17ae 11359
40381db7 11360 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11361 != AS_FILTER_PERMIT)
11362 continue;
11363 }
11364 if (type == bgp_show_type_route_map) {
11365 struct route_map *rmap = output_arg;
9b6d8fcf 11366 struct bgp_path_info path;
636632c3
DA
11367 struct bgp_path_info_extra extra;
11368 struct attr dummy_attr = {};
b68885f9 11369 route_map_result_t ret;
d62a17ae 11370
6f4f49b2 11371 dummy_attr = *pi->attr;
d62a17ae 11372
636632c3
DA
11373 prep_for_rmap_apply(&path, &extra, dest, pi,
11374 pi->peer, &dummy_attr);
d62a17ae 11375
1782514f 11376 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11377 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11378 if (ret == RMAP_DENYMATCH)
11379 continue;
11380 }
11381 if (type == bgp_show_type_neighbor
11382 || type == bgp_show_type_flap_neighbor
11383 || type == bgp_show_type_damp_neighbor) {
11384 union sockunion *su = output_arg;
11385
40381db7
DS
11386 if (pi->peer == NULL
11387 || pi->peer->su_remote == NULL
11388 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11389 continue;
11390 }
11391 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11392 uint32_t destination;
d62a17ae 11393
9bcb3eef 11394 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11395 if (IN_CLASSC(destination)
9bcb3eef 11396 && dest_p->prefixlen == 24)
98ce9a06
DS
11397 continue;
11398 if (IN_CLASSB(destination)
9bcb3eef 11399 && dest_p->prefixlen == 16)
98ce9a06
DS
11400 continue;
11401 if (IN_CLASSA(destination)
9bcb3eef 11402 && dest_p->prefixlen == 8)
98ce9a06
DS
11403 continue;
11404 }
11405 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11406 p = output_arg;
9bcb3eef 11407 if (!prefix_match(p, dest_p))
98ce9a06
DS
11408 continue;
11409 }
11410 if (type == bgp_show_type_community_all) {
9a706b42 11411 if (!picomm)
98ce9a06
DS
11412 continue;
11413 }
11414 if (type == bgp_show_type_community) {
11415 struct community *com = output_arg;
d62a17ae 11416
9a706b42 11417 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11418 continue;
11419 }
11420 if (type == bgp_show_type_community_exact) {
11421 struct community *com = output_arg;
d62a17ae 11422
9a706b42 11423 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11424 continue;
11425 }
11426 if (type == bgp_show_type_community_list) {
11427 struct community_list *list = output_arg;
d62a17ae 11428
9a706b42 11429 if (!community_list_match(picomm, list))
98ce9a06
DS
11430 continue;
11431 }
a4d82a8a 11432 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11433 struct community_list *list = output_arg;
d62a17ae 11434
9a706b42 11435 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11436 continue;
11437 }
11438 if (type == bgp_show_type_lcommunity) {
11439 struct lcommunity *lcom = output_arg;
d62a17ae 11440
1bcf3a96
DA
11441 if (!bgp_attr_get_lcommunity(pi->attr) ||
11442 !lcommunity_match(
11443 bgp_attr_get_lcommunity(pi->attr),
11444 lcom))
98ce9a06
DS
11445 continue;
11446 }
36a206db 11447
11448 if (type == bgp_show_type_lcommunity_exact) {
11449 struct lcommunity *lcom = output_arg;
11450
1bcf3a96
DA
11451 if (!bgp_attr_get_lcommunity(pi->attr) ||
11452 !lcommunity_cmp(
11453 bgp_attr_get_lcommunity(pi->attr),
11454 lcom))
36a206db 11455 continue;
11456 }
98ce9a06
DS
11457 if (type == bgp_show_type_lcommunity_list) {
11458 struct community_list *list = output_arg;
d62a17ae 11459
1bcf3a96
DA
11460 if (!lcommunity_list_match(
11461 bgp_attr_get_lcommunity(pi->attr),
11462 list))
98ce9a06
DS
11463 continue;
11464 }
36a206db 11465 if (type
11466 == bgp_show_type_lcommunity_list_exact) {
11467 struct community_list *list = output_arg;
11468
11469 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11470 bgp_attr_get_lcommunity(pi->attr),
11471 list))
36a206db 11472 continue;
11473 }
98ce9a06 11474 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11475 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11476 continue;
11477 }
11478 if (type == bgp_show_type_dampend_paths
11479 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11480 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11481 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11482 continue;
11483 }
83856649
KQ
11484 if (type == bgp_show_type_self_originated) {
11485 if (pi->peer != bgp->peer_self)
11486 continue;
11487 }
98ce9a06
DS
11488
11489 if (!use_json && header) {
23d0a753
DA
11490 vty_out(vty,
11491 "BGP table version is %" PRIu64
11492 ", local router ID is %pI4, vrf id ",
11493 table->version, &bgp->router_id);
9df8b37c
PZ
11494 if (bgp->vrf_id == VRF_UNKNOWN)
11495 vty_out(vty, "%s", VRFID_NONE_STR);
11496 else
11497 vty_out(vty, "%u", bgp->vrf_id);
11498 vty_out(vty, "\n");
01eced22
AD
11499 vty_out(vty, "Default local pref %u, ",
11500 bgp->default_local_pref);
e84c7c12
PG
11501 vty_out(vty, "local AS ");
11502 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11503 &bgp->as);
11504 vty_out(vty, "\n");
509d82bd 11505 if (!detail_routes) {
9a1aae2d
DA
11506 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11507 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11508 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11509 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11510 }
d62a17ae 11511 if (type == bgp_show_type_dampend_paths
11512 || type == bgp_show_type_damp_neighbor)
98ce9a06 11513 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11514 else if (type == bgp_show_type_flap_statistics
11515 || type == bgp_show_type_flap_neighbor)
98ce9a06 11516 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11517 else if (!detail_routes)
ae248832
MK
11518 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11519 : BGP_SHOW_HEADER));
2aad8c42
MS
11520 header = false;
11521
d62a17ae 11522 }
98ce9a06
DS
11523 if (rd != NULL && !display && !output_count) {
11524 if (!use_json)
11525 vty_out(vty,
11526 "Route Distinguisher: %s\n",
11527 rd);
d62a17ae 11528 }
98ce9a06
DS
11529 if (type == bgp_show_type_dampend_paths
11530 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11531 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11532 AFI_IP, safi, use_json,
11533 json_paths);
98ce9a06
DS
11534 else if (type == bgp_show_type_flap_statistics
11535 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11536 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11537 AFI_IP, safi, use_json,
11538 json_paths);
f280c93b 11539 else {
27bb782a
DA
11540 if (detail_routes || detail_json) {
11541 const struct prefix_rd *prd = NULL;
9a1aae2d 11542
27bb782a
DA
11543 if (dest->pdest)
11544 prd = bgp_rd_from_dest(
11545 dest->pdest, safi);
9a1aae2d
DA
11546
11547 if (!use_json)
11548 route_vty_out_detail_header(
11549 vty, bgp, dest,
11550 bgp_dest_get_prefix(
11551 dest),
11552 prd, table->afi, safi,
f9f2d188 11553 NULL, false);
9a1aae2d 11554
f280c93b 11555 route_vty_out_detail(
27bb782a 11556 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11557 family2afi(dest_p->family),
11558 safi, RPKI_NOT_BEING_USED,
11559 json_paths);
9a1aae2d 11560 } else {
f280c93b
DA
11561 route_vty_out(vty, dest_p, pi, display,
11562 safi, json_paths, wide);
9a1aae2d 11563 }
f280c93b 11564 }
98ce9a06 11565 display++;
d62a17ae 11566 }
11567
98ce9a06
DS
11568 if (display) {
11569 output_count++;
11570 if (!use_json)
11571 continue;
11572
625d2931 11573 /* encode prefix */
9bcb3eef 11574 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11575 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11576
1840384b 11577
b54892e0
DS
11578 bgp_fs_nlri_get_string(
11579 (unsigned char *)
9bcb3eef
DS
11580 dest_p->u.prefix_flowspec.ptr,
11581 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11582 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11583 family2afi(dest_p->u
11584 .prefix_flowspec.family));
625d2931 11585 if (first)
b54892e0 11586 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11587 dest_p->u.prefix_flowspec
b54892e0 11588 .prefixlen);
625d2931 11589 else
b54892e0 11590 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11591 dest_p->u.prefix_flowspec
b54892e0 11592 .prefixlen);
625d2931 11593 } else {
625d2931 11594 if (first)
1b78780b 11595 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11596 else
1b78780b 11597 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11598 }
f9f2d188
TA
11599
11600 if (json_detail_header && json_paths != NULL) {
11601 const struct prefix_rd *prd;
11602
11603 vty_out(vty, "{\n");
11604
11605 prd = bgp_rd_from_dest(dest, safi);
11606
11607 route_vty_out_detail_header(
11608 vty, bgp, dest,
11609 bgp_dest_get_prefix(dest), prd,
11610 table->afi, safi, json_paths, true);
11611
11612 vty_out(vty, "\"paths\": ");
11613 json_detail_header_used = true;
11614 }
11615
d7c6467b
DS
11616 /*
11617 * We are using no_pretty here because under
11618 * extremely high settings( say lots and lots of
11619 * routes with lots and lots of ways to reach
11620 * that route via different paths ) this can
11621 * save several minutes of output when FRR
11622 * is run on older cpu's or more underperforming
11623 * routers out there
11624 */
11625 vty_json_no_pretty(vty, json_paths);
f9f2d188
TA
11626
11627 if (json_detail_header_used)
11628 vty_out(vty, "} ");
11629
449feb8e 11630 json_paths = NULL;
98ce9a06 11631 first = 0;
1f83ed02
DS
11632 } else
11633 json_object_free(json_paths);
98ce9a06
DS
11634 }
11635
1ae44dfc
LB
11636 if (output_cum) {
11637 output_count += *output_cum;
11638 *output_cum = output_count;
11639 }
11640 if (total_cum) {
11641 total_count += *total_cum;
11642 *total_cum = total_count;
11643 }
d62a17ae 11644 if (use_json) {
9386b588 11645 if (rd) {
a4d82a8a 11646 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11647 }
11648 if (is_last) {
a4d82a8a
PZ
11649 unsigned long i;
11650 for (i = 0; i < *json_header_depth; ++i)
11651 vty_out(vty, " } ");
96f3485c
MK
11652 if (!all)
11653 vty_out(vty, "\n");
9386b588 11654 }
d62a17ae 11655 } else {
1ae44dfc
LB
11656 if (is_last) {
11657 /* No route is displayed */
11658 if (output_count == 0) {
11659 if (type == bgp_show_type_normal)
11660 vty_out(vty,
11661 "No BGP prefixes displayed, %ld exist\n",
11662 total_count);
11663 } else
d62a17ae 11664 vty_out(vty,
1ae44dfc
LB
11665 "\nDisplayed %ld routes and %ld total paths\n",
11666 output_count, total_count);
11667 }
d62a17ae 11668 }
718e3744 11669
d62a17ae 11670 return CMD_SUCCESS;
718e3744 11671}
11672
1ae44dfc
LB
11673int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11674 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11675 enum bgp_show_type type, void *output_arg,
11676 uint16_t show_flags)
1ae44dfc 11677{
9bcb3eef 11678 struct bgp_dest *dest, *next;
1ae44dfc
LB
11679 unsigned long output_cum = 0;
11680 unsigned long total_cum = 0;
9386b588 11681 unsigned long json_header_depth = 0;
67009e22 11682 struct bgp_table *itable;
0136788c 11683 bool show_msg;
27bb782a 11684 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11685
11686 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11687
9bcb3eef
DS
11688 for (dest = bgp_table_top(table); dest; dest = next) {
11689 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11690
9bcb3eef
DS
11691 next = bgp_route_next(dest);
11692 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11693 continue;
67009e22 11694
9bcb3eef 11695 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11696 if (itable != NULL) {
1ae44dfc 11697 struct prefix_rd prd;
06b9f471 11698 char rd[RD_ADDRSTRLEN];
1ae44dfc 11699
9bcb3eef 11700 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11701 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11702 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11703 rd, next == NULL, &output_cum,
11704 &total_cum, &json_header_depth,
1e2ce4f1 11705 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11706 if (next == NULL)
11707 show_msg = false;
1ae44dfc
LB
11708 }
11709 }
0136788c
LB
11710 if (show_msg) {
11711 if (output_cum == 0)
11712 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11713 total_cum);
11714 else
11715 vty_out(vty,
11716 "\nDisplayed %ld routes and %ld total paths\n",
11717 output_cum, total_cum);
0224b329
DA
11718 } else {
11719 if (use_json && output_cum == 0)
11720 vty_out(vty, "{}\n");
0136788c 11721 }
1ae44dfc
LB
11722 return CMD_SUCCESS;
11723}
2aad8c42 11724
d62a17ae 11725static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11726 enum bgp_show_type type, void *output_arg,
96c81f66 11727 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11728{
d62a17ae 11729 struct bgp_table *table;
9386b588 11730 unsigned long json_header_depth = 0;
96f3485c 11731 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11732
d62a17ae 11733 if (bgp == NULL) {
11734 bgp = bgp_get_default();
11735 }
fee0f4c6 11736
d62a17ae 11737 if (bgp == NULL) {
11738 if (!use_json)
11739 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11740 else
11741 vty_out(vty, "{}\n");
d62a17ae 11742 return CMD_WARNING;
11743 }
4dd6177e 11744
cd8c2a27
MS
11745 /* Labeled-unicast routes live in the unicast table. */
11746 if (safi == SAFI_LABELED_UNICAST)
11747 safi = SAFI_UNICAST;
11748
1ae44dfc 11749 table = bgp->rib[afi][safi];
d62a17ae 11750 /* use MPLS and ENCAP specific shows until they are merged */
11751 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11752 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11753 output_arg, show_flags);
d62a17ae 11754 }
dba3c1d3
PG
11755
11756 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11757 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11758 output_arg, use_json,
11759 1, NULL, NULL);
11760 }
fee0f4c6 11761
0adc5bbb
LS
11762 if (safi == SAFI_EVPN)
11763 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11764
96f3485c 11765 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11766 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11767 rpki_target_state);
fee0f4c6 11768}
11769
d62a17ae 11770static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11771 safi_t safi, uint16_t show_flags)
f186de26 11772{
d62a17ae 11773 struct listnode *node, *nnode;
11774 struct bgp *bgp;
11775 int is_first = 1;
9f049418 11776 bool route_output = false;
96f3485c 11777 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11778
d62a17ae 11779 if (use_json)
11780 vty_out(vty, "{\n");
9f689658 11781
d62a17ae 11782 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11783 route_output = true;
d62a17ae 11784 if (use_json) {
11785 if (!is_first)
11786 vty_out(vty, ",\n");
11787 else
11788 is_first = 0;
11789
11790 vty_out(vty, "\"%s\":",
11791 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11792 ? VRF_DEFAULT_NAME
d62a17ae 11793 : bgp->name);
11794 } else {
11795 vty_out(vty, "\nInstance %s:\n",
11796 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11797 ? VRF_DEFAULT_NAME
d62a17ae 11798 : bgp->name);
11799 }
11800 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11801 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11802 }
9f689658 11803
d62a17ae 11804 if (use_json)
11805 vty_out(vty, "}\n");
9f049418
DS
11806 else if (!route_output)
11807 vty_out(vty, "%% BGP instance not found\n");
f186de26 11808}
11809
718e3744 11810/* Header of detailed BGP route information */
d62a17ae 11811void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11812 struct bgp_dest *dest, const struct prefix *p,
11813 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11814 safi_t safi, json_object *json,
11815 bool incremental_print)
d62a17ae 11816{
40381db7 11817 struct bgp_path_info *pi;
d62a17ae 11818 struct peer *peer;
11819 struct listnode *node, *nnode;
06b9f471 11820 char buf1[RD_ADDRSTRLEN];
d62a17ae 11821 int count = 0;
11822 int best = 0;
11823 int suppress = 0;
c5f1e1b2
C
11824 int accept_own = 0;
11825 int route_filter_translated_v4 = 0;
11826 int route_filter_v4 = 0;
11827 int route_filter_translated_v6 = 0;
11828 int route_filter_v6 = 0;
11829 int llgr_stale = 0;
11830 int no_llgr = 0;
11831 int accept_own_nexthop = 0;
11832 int blackhole = 0;
d62a17ae 11833 int no_export = 0;
11834 int no_advertise = 0;
11835 int local_as = 0;
c5f1e1b2 11836 int no_peer = 0;
d62a17ae 11837 int first = 1;
11838 int has_valid_label = 0;
11839 mpls_label_t label = 0;
11840 json_object *json_adv_to = NULL;
67f67ba4
DA
11841 uint32_t ttl = 0;
11842 uint32_t bos = 0;
11843 uint32_t exp = 0;
9bedbb1e 11844
67f67ba4 11845 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11846
67f67ba4 11847 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11848
44c69747 11849 if (safi == SAFI_EVPN) {
44c69747 11850 if (!json) {
2dbe669b 11851 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11852 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11853 bgp->asnotation)
f137734b 11854 : "",
2dbe669b 11855 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11856 } else {
4a8cd6ad
PG
11857 json_object_string_add(
11858 json, "rd",
11859 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11860 bgp->asnotation)
11861 : "");
44c69747
LK
11862 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11863 }
11864 } else {
11865 if (!json) {
9119ef3a
DA
11866 vty_out(vty,
11867 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11868 "\n",
d62a17ae 11869 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11870 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11871 sizeof(buf1),
11872 bgp->asnotation)
8228a9a7 11873 : ""),
9119ef3a
DA
11874 safi == SAFI_MPLS_VPN ? ":" : "", p,
11875 dest->version);
cd1964ff 11876
9119ef3a 11877 } else {
f9f2d188
TA
11878 if (incremental_print) {
11879 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11880 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11881 dest->version);
11882 } else {
11883 json_object_string_addf(json, "prefix", "%pFX",
11884 p);
11885 json_object_int_add(json, "version",
11886 dest->version);
11887 }
9119ef3a 11888 }
44c69747
LK
11889 }
11890
11891 if (has_valid_label) {
f9f2d188
TA
11892 if (json) {
11893 if (incremental_print)
11894 vty_out(vty, "\"localLabel\": \"%u\",\n",
11895 label);
11896 else
11897 json_object_int_add(json, "localLabel", label);
11898 } else
d62a17ae 11899 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11900 }
11901
11902 if (!json)
d62a17ae 11903 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11904 vty_out(vty, "not allocated\n");
718e3744 11905
9bcb3eef 11906 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11907 struct community *picomm = NULL;
11908
11909 picomm = bgp_attr_get_community(pi->attr);
11910
d62a17ae 11911 count++;
40381db7 11912 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11913 best = count;
4056a5f6 11914 if (bgp_path_suppressed(pi))
d62a17ae 11915 suppress = 1;
cee9c031 11916
9a706b42 11917 if (!picomm)
cee9c031
QY
11918 continue;
11919
11920 no_advertise += community_include(
9a706b42
DA
11921 picomm, COMMUNITY_NO_ADVERTISE);
11922 no_export +=
11923 community_include(picomm, COMMUNITY_NO_EXPORT);
11924 local_as +=
11925 community_include(picomm, COMMUNITY_LOCAL_AS);
11926 accept_own +=
11927 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11928 route_filter_translated_v4 += community_include(
9a706b42 11929 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11930 route_filter_translated_v6 += community_include(
9a706b42 11931 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11932 route_filter_v4 += community_include(
9a706b42 11933 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11934 route_filter_v6 += community_include(
9a706b42
DA
11935 picomm, COMMUNITY_ROUTE_FILTER_v6);
11936 llgr_stale +=
11937 community_include(picomm, COMMUNITY_LLGR_STALE);
11938 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11939 accept_own_nexthop += community_include(
11940 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11941 blackhole +=
11942 community_include(picomm, COMMUNITY_BLACKHOLE);
11943 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11944 }
718e3744 11945 }
718e3744 11946
d62a17ae 11947 if (!json) {
11948 vty_out(vty, "Paths: (%d available", count);
11949 if (best) {
11950 vty_out(vty, ", best #%d", best);
b84060bb
PG
11951 if (safi == SAFI_UNICAST) {
11952 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11953 vty_out(vty, ", table %s",
11954 VRF_DEFAULT_NAME);
11955 else
11956 vty_out(vty, ", vrf %s",
11957 bgp->name);
11958 }
d62a17ae 11959 } else
11960 vty_out(vty, ", no best path");
11961
c5f1e1b2
C
11962 if (accept_own)
11963 vty_out(vty,
11964 ", accept own local route exported and imported in different VRF");
11965 else if (route_filter_translated_v4)
11966 vty_out(vty,
11967 ", mark translated RTs for VPNv4 route filtering");
11968 else if (route_filter_v4)
11969 vty_out(vty,
11970 ", attach RT as-is for VPNv4 route filtering");
11971 else if (route_filter_translated_v6)
11972 vty_out(vty,
11973 ", mark translated RTs for VPNv6 route filtering");
11974 else if (route_filter_v6)
11975 vty_out(vty,
11976 ", attach RT as-is for VPNv6 route filtering");
11977 else if (llgr_stale)
11978 vty_out(vty,
1479ed2f 11979 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11980 else if (no_llgr)
11981 vty_out(vty,
11982 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11983 else if (accept_own_nexthop)
11984 vty_out(vty,
11985 ", accept local nexthop");
11986 else if (blackhole)
11987 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11988 else if (no_export)
11989 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11990 else if (no_advertise)
11991 vty_out(vty, ", not advertised to any peer");
d62a17ae 11992 else if (local_as)
11993 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11994 else if (no_peer)
11995 vty_out(vty,
11996 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11997
11998 if (suppress)
11999 vty_out(vty,
12000 ", Advertisements suppressed by an aggregate.");
12001 vty_out(vty, ")\n");
12002 }
718e3744 12003
d62a17ae 12004 /* If we are not using addpath then we can display Advertised to and
12005 * that will
12006 * show what peers we advertised the bestpath to. If we are using
12007 * addpath
12008 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12009 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12010 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12011 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12012 if (json && !json_adv_to)
12013 json_adv_to = json_object_new_object();
12014
12015 route_vty_out_advertised_to(
12016 vty, peer, &first,
12017 " Advertised to non peer-group peers:\n ",
12018 json_adv_to);
12019 }
12020 }
12021
f9f2d188
TA
12022 if (json && json_adv_to) {
12023 if (incremental_print) {
12024 vty_out(vty, "\"advertisedTo\": ");
12025 vty_json(vty, json_adv_to);
12026 vty_out(vty, ",");
12027 } else
d62a17ae 12028 json_object_object_add(json, "advertisedTo",
12029 json_adv_to);
d62a17ae 12030 } else {
f9f2d188 12031 if (!json && first)
d62a17ae 12032 vty_out(vty, " Not advertised to any peer");
12033 vty_out(vty, "\n");
12034 }
12035 }
718e3744 12036}
12037
edfee30d 12038static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12039 struct bgp_dest *bgp_node, struct vty *vty,
12040 struct bgp *bgp, afi_t afi, safi_t safi,
12041 json_object *json, enum bgp_path_type pathtype,
4027d19b 12042 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12043{
12044 struct bgp_path_info *pi;
12045 int header = 1;
44c69747
LK
12046 json_object *json_header = NULL;
12047 json_object *json_paths = NULL;
4933eaaf 12048 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12049
9bcb3eef 12050 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12051 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12052
12053 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12054 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12055 pi->peer, pi->attr, p);
4933eaaf 12056
4027d19b
DS
12057 if (rpki_target_state != RPKI_NOT_BEING_USED
12058 && rpki_curr_state != rpki_target_state)
4933eaaf 12059 continue;
44c69747
LK
12060
12061 if (json && !json_paths) {
12062 /* Instantiate json_paths only if path is valid */
12063 json_paths = json_object_new_array();
c4f64ea9 12064 if (pfx_rd)
44c69747 12065 json_header = json_object_new_object();
c4f64ea9 12066 else
44c69747
LK
12067 json_header = json;
12068 }
12069
12070 if (header) {
12071 route_vty_out_detail_header(
34c7f35f
SW
12072 vty, bgp, bgp_node,
12073 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12074 safi, json_header, false);
44c69747
LK
12075 header = 0;
12076 }
12077 (*display)++;
12078
12079 if (pathtype == BGP_PATH_SHOW_ALL
12080 || (pathtype == BGP_PATH_SHOW_BESTPATH
12081 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12082 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12083 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12084 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12085 route_vty_out_detail(vty, bgp, bgp_node,
12086 bgp_dest_get_prefix(bgp_node), pi,
12087 AFI_IP, safi, rpki_curr_state,
12088 json_paths);
44c69747
LK
12089 }
12090
12091 if (json && json_paths) {
12092 json_object_object_add(json_header, "paths", json_paths);
12093
12094 if (pfx_rd)
4a8cd6ad
PG
12095 json_object_object_addf(
12096 json, json_header,
12097 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12098 }
12099}
12100
2aad8c42
MS
12101/*
12102 * Return rd based on safi
12103 */
46dbf9d0
DA
12104const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12105 safi_t safi)
2aad8c42
MS
12106{
12107 switch (safi) {
12108 case SAFI_MPLS_VPN:
12109 case SAFI_ENCAP:
12110 case SAFI_EVPN:
12111 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12112 case SAFI_UNSPEC:
12113 case SAFI_UNICAST:
12114 case SAFI_MULTICAST:
12115 case SAFI_LABELED_UNICAST:
12116 case SAFI_FLOWSPEC:
12117 case SAFI_MAX:
2aad8c42 12118 return NULL;
2aad8c42 12119 }
58cf0823
DS
12120
12121 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12122}
12123
718e3744 12124/* Display specified route of BGP table. */
d62a17ae 12125static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12126 struct bgp_table *rib, const char *ip_str,
12127 afi_t afi, safi_t safi,
4027d19b 12128 enum rpki_states rpki_target_state,
d62a17ae 12129 struct prefix_rd *prd, int prefix_check,
9f049418 12130 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12131{
12132 int ret;
d62a17ae 12133 int display = 0;
12134 struct prefix match;
9bcb3eef
DS
12135 struct bgp_dest *dest;
12136 struct bgp_dest *rm;
d62a17ae 12137 struct bgp_table *table;
12138 json_object *json = NULL;
12139 json_object *json_paths = NULL;
12140
12141 /* Check IP address argument. */
12142 ret = str2prefix(ip_str, &match);
12143 if (!ret) {
12144 vty_out(vty, "address is malformed\n");
12145 return CMD_WARNING;
12146 }
718e3744 12147
d62a17ae 12148 match.family = afi2family(afi);
b05a1c8b 12149
44c69747 12150 if (use_json)
d62a17ae 12151 json = json_object_new_object();
718e3744 12152
44c69747 12153 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12154 for (dest = bgp_table_top(rib); dest;
12155 dest = bgp_route_next(dest)) {
12156 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12157
9bcb3eef 12158 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12159 continue;
9bcb3eef 12160 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12161 if (!table)
ea47320b 12162 continue;
d62a17ae 12163
4953391b
DA
12164 rm = bgp_node_match(table, &match);
12165 if (rm == NULL)
ea47320b 12166 continue;
d62a17ae 12167
9bcb3eef 12168 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12169 if (prefix_check
b54892e0 12170 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12171 bgp_dest_unlock_node(rm);
ea47320b
DL
12172 continue;
12173 }
d62a17ae 12174
9bcb3eef 12175 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12176 bgp, afi, safi, json, pathtype,
4027d19b 12177 &display, rpki_target_state);
44c69747 12178
9bcb3eef 12179 bgp_dest_unlock_node(rm);
44c69747
LK
12180 }
12181 } else if (safi == SAFI_EVPN) {
9bcb3eef 12182 struct bgp_dest *longest_pfx;
cded3b72 12183 bool is_exact_pfxlen_match = false;
44c69747 12184
9bcb3eef
DS
12185 for (dest = bgp_table_top(rib); dest;
12186 dest = bgp_route_next(dest)) {
12187 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12188
9bcb3eef 12189 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12190 continue;
9bcb3eef 12191 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12192 if (!table)
12193 continue;
12194
12195 longest_pfx = NULL;
cded3b72 12196 is_exact_pfxlen_match = false;
44c69747
LK
12197 /*
12198 * Search through all the prefixes for a match. The
12199 * pfx's are enumerated in ascending order of pfxlens.
12200 * So, the last pfx match is the longest match. Set
12201 * is_exact_pfxlen_match when we get exact pfxlen match
12202 */
12203 for (rm = bgp_table_top(table); rm;
12204 rm = bgp_route_next(rm)) {
b54892e0 12205 const struct prefix *rm_p =
9bcb3eef 12206 bgp_dest_get_prefix(rm);
44c69747
LK
12207 /*
12208 * Get prefixlen of the ip-prefix within type5
12209 * evpn route
12210 */
b54892e0
DS
12211 if (evpn_type5_prefix_match(rm_p, &match)
12212 && rm->info) {
44c69747
LK
12213 longest_pfx = rm;
12214 int type5_pfxlen =
b54892e0
DS
12215 bgp_evpn_get_type5_prefixlen(
12216 rm_p);
44c69747 12217 if (type5_pfxlen == match.prefixlen) {
cded3b72 12218 is_exact_pfxlen_match = true;
9bcb3eef 12219 bgp_dest_unlock_node(rm);
44c69747
LK
12220 break;
12221 }
d62a17ae 12222 }
12223 }
ea47320b 12224
44c69747
LK
12225 if (!longest_pfx)
12226 continue;
12227
12228 if (prefix_check && !is_exact_pfxlen_match)
12229 continue;
12230
12231 rm = longest_pfx;
9bcb3eef 12232 bgp_dest_lock_node(rm);
44c69747 12233
9bcb3eef 12234 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12235 bgp, afi, safi, json, pathtype,
4027d19b 12236 &display, rpki_target_state);
44c69747 12237
9bcb3eef 12238 bgp_dest_unlock_node(rm);
d62a17ae 12239 }
98a9dbc7 12240 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12241 if (use_json)
12242 json_paths = json_object_new_array();
12243
63a0b7a9
PG
12244 display = bgp_flowspec_display_match_per_ip(afi, rib,
12245 &match, prefix_check,
12246 vty,
12247 use_json,
12248 json_paths);
d5f20468
SP
12249 if (use_json) {
12250 if (display)
12251 json_object_object_add(json, "paths",
12252 json_paths);
12253 else
12254 json_object_free(json_paths);
12255 }
d62a17ae 12256 } else {
4953391b
DA
12257 dest = bgp_node_match(rib, &match);
12258 if (dest != NULL) {
9bcb3eef 12259 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12260 if (!prefix_check
9bcb3eef
DS
12261 || dest_p->prefixlen == match.prefixlen) {
12262 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12263 safi, json, pathtype,
4027d19b 12264 &display, rpki_target_state);
d62a17ae 12265 }
12266
9bcb3eef 12267 bgp_dest_unlock_node(dest);
d62a17ae 12268 }
12269 }
e5eee9af 12270
d62a17ae 12271 if (use_json) {
75eeda93 12272 vty_json(vty, json);
d62a17ae 12273 } else {
12274 if (!display) {
12275 vty_out(vty, "%% Network not in table\n");
12276 return CMD_WARNING;
12277 }
12278 }
b05a1c8b 12279
d62a17ae 12280 return CMD_SUCCESS;
718e3744 12281}
12282
fee0f4c6 12283/* Display specified route of Main RIB */
d62a17ae 12284static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12285 afi_t afi, safi_t safi, struct prefix_rd *prd,
12286 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12287 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12288{
9b86009a 12289 if (!bgp) {
d62a17ae 12290 bgp = bgp_get_default();
9b86009a
RW
12291 if (!bgp) {
12292 if (!use_json)
12293 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12294 else
12295 vty_out(vty, "{}\n");
9b86009a
RW
12296 return CMD_WARNING;
12297 }
12298 }
d62a17ae 12299
12300 /* labeled-unicast routes live in the unicast table */
12301 if (safi == SAFI_LABELED_UNICAST)
12302 safi = SAFI_UNICAST;
12303
12304 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12305 afi, safi, rpki_target_state, prd,
8aa22bbb 12306 prefix_check, pathtype, use_json);
d62a17ae 12307}
12308
12309static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12310 struct cmd_token **argv, bool exact, afi_t afi,
12311 safi_t safi, bool uj)
d62a17ae 12312{
12313 struct lcommunity *lcom;
12314 struct buffer *b;
12315 int i;
12316 char *str;
12317 int first = 0;
96c81f66 12318 uint16_t show_flags = 0;
4f28b2b5 12319 int ret;
96f3485c
MK
12320
12321 if (uj)
12322 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12323
12324 b = buffer_new(1024);
12325 for (i = 0; i < argc; i++) {
12326 if (first)
12327 buffer_putc(b, ' ');
12328 else {
12329 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12330 first = 1;
12331 buffer_putstr(b, argv[i]->arg);
12332 }
12333 }
12334 }
12335 buffer_putc(b, '\0');
57d187bc 12336
d62a17ae 12337 str = buffer_getstr(b);
12338 buffer_free(b);
57d187bc 12339
d62a17ae 12340 lcom = lcommunity_str2com(str);
12341 XFREE(MTYPE_TMP, str);
12342 if (!lcom) {
12343 vty_out(vty, "%% Large-community malformed\n");
12344 return CMD_WARNING;
12345 }
57d187bc 12346
4f28b2b5 12347 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12348 (exact ? bgp_show_type_lcommunity_exact
12349 : bgp_show_type_lcommunity),
12350 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12351
12352 lcommunity_free(&lcom);
12353 return ret;
57d187bc
JS
12354}
12355
d62a17ae 12356static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12357 const char *lcom, bool exact, afi_t afi,
12358 safi_t safi, bool uj)
57d187bc 12359{
d62a17ae 12360 struct community_list *list;
96c81f66 12361 uint16_t show_flags = 0;
96f3485c
MK
12362
12363 if (uj)
12364 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12365
57d187bc 12366
e237b0d2 12367 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12368 LARGE_COMMUNITY_LIST_MASTER);
12369 if (list == NULL) {
12370 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12371 lcom);
12372 return CMD_WARNING;
12373 }
57d187bc 12374
36a206db 12375 return bgp_show(vty, bgp, afi, safi,
12376 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12377 : bgp_show_type_lcommunity_list),
1e2ce4f1 12378 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12379}
12380
52951b63
DS
12381DEFUN (show_ip_bgp_large_community_list,
12382 show_ip_bgp_large_community_list_cmd,
77a3a95e 12383 "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
12384 SHOW_STR
12385 IP_STR
12386 BGP_STR
12387 BGP_INSTANCE_HELP_STR
9bedbb1e 12388 BGP_AFI_HELP_STR
4dd6177e 12389 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12390 "Display routes matching the large-community-list\n"
12391 "large-community-list number\n"
12392 "large-community-list name\n"
36a206db 12393 "Exact match of the large-communities\n"
52951b63
DS
12394 JSON_STR)
12395{
d62a17ae 12396 afi_t afi = AFI_IP6;
12397 safi_t safi = SAFI_UNICAST;
12398 int idx = 0;
36a206db 12399 bool exact_match = 0;
4d678463 12400 struct bgp *bgp = NULL;
9f049418 12401 bool uj = use_json(argc, argv);
d62a17ae 12402
ef3364f0
DA
12403 if (uj)
12404 argc--;
4d678463 12405
ef3364f0
DA
12406 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12407 &bgp, uj);
12408 if (!idx)
12409 return CMD_WARNING;
d62a17ae 12410
12411 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12412
12413 const char *clist_number_or_name = argv[++idx]->arg;
12414
12415 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12416 exact_match = 1;
12417
12418 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12419 exact_match, afi, safi, uj);
52951b63
DS
12420}
12421DEFUN (show_ip_bgp_large_community,
12422 show_ip_bgp_large_community_cmd,
36a206db 12423 "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
12424 SHOW_STR
12425 IP_STR
12426 BGP_STR
12427 BGP_INSTANCE_HELP_STR
9bedbb1e 12428 BGP_AFI_HELP_STR
4dd6177e 12429 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12430 "Display routes matching the large-communities\n"
12431 "List of large-community numbers\n"
36a206db 12432 "Exact match of the large-communities\n"
52951b63
DS
12433 JSON_STR)
12434{
d62a17ae 12435 afi_t afi = AFI_IP6;
12436 safi_t safi = SAFI_UNICAST;
12437 int idx = 0;
36a206db 12438 bool exact_match = 0;
4d678463 12439 struct bgp *bgp = NULL;
9f049418 12440 bool uj = use_json(argc, argv);
96c81f66 12441 uint16_t show_flags = 0;
d62a17ae 12442
96f3485c
MK
12443 if (uj) {
12444 argc--;
12445 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12446 }
4d678463 12447
96f3485c
MK
12448 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12449 &bgp, uj);
12450 if (!idx)
12451 return CMD_WARNING;
d62a17ae 12452
36a206db 12453 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12454 if (argv_find(argv, argc, "exact-match", &idx)) {
12455 argc--;
36a206db 12456 exact_match = 1;
1857760c 12457 }
36a206db 12458 return bgp_show_lcommunity(vty, bgp, argc, argv,
12459 exact_match, afi, safi, uj);
12460 } else
d62a17ae 12461 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12462 bgp_show_type_lcommunity_all, NULL, show_flags,
12463 RPKI_NOT_BEING_USED);
52951b63
DS
12464}
12465
71f1613a
DA
12466static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12467 safi_t safi, struct json_object *json_array);
d62a17ae 12468static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12469 safi_t safi, struct json_object *json);
e01ca200 12470
7b2ff250 12471
9ab0cf58
PG
12472DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12473 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12474 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12475 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12476{
12477 bool uj = use_json(argc, argv);
12478 struct bgp *bgp = NULL;
ec76a1d1
DA
12479 safi_t safi = SAFI_UNICAST;
12480 afi_t afi = AFI_IP6;
4265b261 12481 int idx = 0;
6c9d22e2
PG
12482 struct json_object *json_all = NULL;
12483 struct json_object *json_afi_safi = NULL;
4265b261
PG
12484
12485 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12486 &bgp, false);
71f1613a 12487 if (!idx)
4265b261 12488 return CMD_WARNING;
6c9d22e2 12489
4265b261 12490 if (uj)
6c9d22e2 12491 json_all = json_object_new_object();
4265b261 12492
9ab0cf58
PG
12493 FOREACH_AFI_SAFI (afi, safi) {
12494 /*
12495 * So limit output to those afi/safi pairs that
12496 * actually have something interesting in them
12497 */
12498 if (strmatch(get_afi_safi_str(afi, safi, true),
12499 "Unknown")) {
12500 continue;
12501 }
12502 if (uj) {
12503 json_afi_safi = json_object_new_array();
12504 json_object_object_add(
12505 json_all,
12506 get_afi_safi_str(afi, safi, true),
12507 json_afi_safi);
12508 } else {
12509 json_afi_safi = NULL;
6c9d22e2 12510 }
9ab0cf58
PG
12511
12512 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12513 }
6c9d22e2 12514
3757f964
DA
12515 if (uj)
12516 vty_json(vty, json_all);
6c9d22e2 12517
4265b261
PG
12518 return CMD_SUCCESS;
12519}
12520
7b2ff250 12521/* BGP route print out function without JSON */
14718643
PG
12522DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12523 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12524 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12525 SHOW_STR
12526 IP_STR
12527 BGP_STR
12528 BGP_INSTANCE_HELP_STR
12529 L2VPN_HELP_STR
12530 EVPN_HELP_STR
12531 "BGP RIB advertisement statistics\n"
12532 JSON_STR)
12533{
ec76a1d1
DA
12534 afi_t afi = AFI_IP6;
12535 safi_t safi = SAFI_UNICAST;
14718643
PG
12536 struct bgp *bgp = NULL;
12537 int idx = 0, ret;
12538 bool uj = use_json(argc, argv);
12539 struct json_object *json_afi_safi = NULL, *json = NULL;
12540
12541 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12542 &bgp, false);
12543 if (!idx)
12544 return CMD_WARNING;
12545
12546 if (uj)
12547 json_afi_safi = json_object_new_array();
12548 else
12549 json_afi_safi = NULL;
12550
12551 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12552
12553 if (uj) {
12554 json = json_object_new_object();
12555 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12556 json_afi_safi);
3757f964 12557 vty_json(vty, json);
14718643
PG
12558 }
12559 return ret;
12560}
12561
893cccd0 12562/* BGP route print out function without JSON */
9ab0cf58
PG
12563DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12564 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12565 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12566 "]]\
893cccd0 12567 statistics [json]",
9ab0cf58
PG
12568 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12569 BGP_SAFI_WITH_LABEL_HELP_STR
12570 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12571{
ec76a1d1
DA
12572 afi_t afi = AFI_IP6;
12573 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12574 struct bgp *bgp = NULL;
12575 int idx = 0, ret;
12576 bool uj = use_json(argc, argv);
6c9d22e2 12577 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12578
12579 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12580 &bgp, false);
12581 if (!idx)
12582 return CMD_WARNING;
6c9d22e2 12583
893cccd0 12584 if (uj)
6c9d22e2
PG
12585 json_afi_safi = json_object_new_array();
12586 else
12587 json_afi_safi = NULL;
12588
12589 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12590
12591 if (uj) {
12592 json = json_object_new_object();
12593 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12594 json_afi_safi);
3757f964 12595 vty_json(vty, json);
893cccd0
PG
12596 }
12597 return ret;
893cccd0 12598}
7b2ff250 12599
fe0f234d 12600DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12602 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12603 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12604 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12605 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12606 "Display the entries for all address families\n"
9ab0cf58
PG
12607 "Display detailed information about dampening\n"
12608 "Display detail of configured dampening parameters\n"
fe0f234d 12609 JSON_STR)
718e3744 12610{
d62a17ae 12611 afi_t afi = AFI_IP6;
12612 safi_t safi = SAFI_UNICAST;
d62a17ae 12613 struct bgp *bgp = NULL;
12614 int idx = 0;
96c81f66 12615 uint16_t show_flags = 0;
fe0f234d
RW
12616 bool uj = use_json(argc, argv);
12617
12618 if (uj) {
12619 argc--;
12620 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12621 }
96f3485c
MK
12622
12623 /* [<ipv4|ipv6> [all]] */
12624 if (all) {
12625 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12626 if (argv_find(argv, argc, "ipv4", &idx))
12627 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12628
12629 if (argv_find(argv, argc, "ipv6", &idx))
12630 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12631 }
d62a17ae 12632
12633 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12634 &bgp, false);
d62a17ae 12635 if (!idx)
12636 return CMD_WARNING;
12637
fe0f234d 12638 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12639}
12640
fe0f234d
RW
12641/* BGP route print out function */
12642DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12643 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12644 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12645 "]]\
96f3485c 12646 [all$all]\
cf4898bc
QY
12647 [cidr-only\
12648 |dampening <flap-statistics|dampened-paths>\
12649 |community [AA:NN|local-AS|no-advertise|no-export\
12650 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12651 |accept-own|accept-own-nexthop|route-filter-v6\
12652 |route-filter-v4|route-filter-translated-v6\
12653 |route-filter-translated-v4] [exact-match]\
70799983 12654 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12655 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12656 |prefix-list WORD\
ed126382 12657 |access-list ACCESSLIST_NAME\
70dd370f 12658 |route-map RMAP_NAME\
1e2ce4f1 12659 |rpki <invalid|valid|notfound>\
7d3cae70 12660 |version (1-4294967295)\
b4ad2fae 12661 |alias ALIAS_NAME\
39c3c736
RW
12662 |A.B.C.D/M longer-prefixes\
12663 |X:X::X:X/M longer-prefixes\
83856649 12664 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12665 |detail-routes$detail_routes\
67799a48 12666 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12667 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12668 BGP_SAFI_WITH_LABEL_HELP_STR
12669 "Display the entries for all address families\n"
12670 "Display only routes with non-natural netmasks\n"
12671 "Display detailed information about dampening\n"
12672 "Display flap statistics of routes\n"
12673 "Display paths suppressed due to dampening\n"
12674 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12675 "Do not send outside local AS (well-known community)\n"
12676 "Do not advertise to any peer (well-known community)\n"
12677 "Do not export to next AS (well-known community)\n"
12678 "Graceful shutdown (well-known community)\n"
12679 "Do not export to any peer (well-known community)\n"
12680 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12681 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12682 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12683 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12684 "Should accept VPN route with local nexthop (well-known community)\n"
12685 "RT VPNv6 route filtering (well-known community)\n"
12686 "RT VPNv4 route filtering (well-known community)\n"
12687 "RT translated VPNv6 route filtering (well-known community)\n"
12688 "RT translated VPNv4 route filtering (well-known community)\n"
12689 "Exact match of the communities\n"
70799983
RW
12690 "Community-list number\n"
12691 "Community-list name\n"
12692 "Display routes matching the community-list\n"
12693 "Exact match of the communities\n"
a7129347
RW
12694 "Display routes conforming to the filter-list\n"
12695 "Regular expression access list name\n"
6deaf579
RW
12696 "Display routes conforming to the prefix-list\n"
12697 "Prefix-list name\n"
ed126382
DA
12698 "Display routes conforming to the access-list\n"
12699 "Access-list name\n"
bf1a944a
RW
12700 "Display routes matching the route-map\n"
12701 "A route-map to match on\n"
a70a28a5
DA
12702 "RPKI route types\n"
12703 "A valid path as determined by rpki\n"
12704 "A invalid path as determined by rpki\n"
12705 "A path that has no rpki data\n"
12706 "Display prefixes with matching version numbers\n"
12707 "Version number and above\n"
12708 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12709 "BGP community alias\n"
12710 "IPv4 prefix\n"
12711 "Display route and more specific routes\n"
12712 "IPv6 prefix\n"
12713 "Display route and more specific routes\n"
83856649 12714 BGP_SELF_ORIG_HELP_STR
509d82bd 12715 "Display detailed version of all routes\n"
39c3c736 12716 JSON_STR
a70a28a5
DA
12717 "Display detailed version of JSON output\n"
12718 "Increase table width for longer prefixes\n")
7b2ff250
DW
12719{
12720 afi_t afi = AFI_IP6;
12721 safi_t safi = SAFI_UNICAST;
12722 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12723 void *output_arg = NULL;
7b2ff250
DW
12724 struct bgp *bgp = NULL;
12725 int idx = 0;
d0086e8e 12726 int exact_match = 0;
96f3485c
MK
12727 char *community = NULL;
12728 bool first = true;
96c81f66 12729 uint16_t show_flags = 0;
4027d19b 12730 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12731 struct prefix p;
96f3485c
MK
12732
12733 if (uj) {
9f049418 12734 argc--;
96f3485c
MK
12735 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12736 }
12737
67799a48
DA
12738 if (detail_json)
12739 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12740
509d82bd
DA
12741 if (detail_routes)
12742 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12743
96f3485c
MK
12744 /* [<ipv4|ipv6> [all]] */
12745 if (all) {
12746 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12747
12748 if (argv_find(argv, argc, "ipv4", &idx))
12749 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12750
12751 if (argv_find(argv, argc, "ipv6", &idx))
12752 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12753 }
12754
12755 if (wide)
12756 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12757
12758 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12759 &bgp, uj);
7b2ff250
DW
12760 if (!idx)
12761 return CMD_WARNING;
12762
7b2ff250 12763 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12764 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12765
12766 if (argv_find(argv, argc, "dampening", &idx)) {
12767 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12768 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12769 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12770 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12771 }
12772
12773 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12774 char *maybecomm = NULL;
d0086e8e 12775
79bc257a
RW
12776 if (idx + 1 < argc) {
12777 if (argv[idx + 1]->type == VARIABLE_TKN)
12778 maybecomm = argv[idx + 1]->arg;
12779 else
12780 maybecomm = argv[idx + 1]->text;
12781 }
12782
cf4898bc
QY
12783 if (maybecomm && !strmatch(maybecomm, "json")
12784 && !strmatch(maybecomm, "exact-match"))
12785 community = maybecomm;
d0086e8e 12786
cf4898bc
QY
12787 if (argv_find(argv, argc, "exact-match", &idx))
12788 exact_match = 1;
d0086e8e 12789
96f3485c
MK
12790 if (!community)
12791 sh_type = bgp_show_type_community_all;
12792 }
12793
70799983
RW
12794 if (argv_find(argv, argc, "community-list", &idx)) {
12795 const char *clist_number_or_name = argv[++idx]->arg;
12796 struct community_list *list;
12797
12798 if (argv_find(argv, argc, "exact-match", &idx))
12799 exact_match = 1;
12800
12801 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12802 COMMUNITY_LIST_MASTER);
12803 if (list == NULL) {
606d49a4 12804 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12805 clist_number_or_name);
12806 return CMD_WARNING;
12807 }
12808
12809 if (exact_match)
12810 sh_type = bgp_show_type_community_list_exact;
12811 else
12812 sh_type = bgp_show_type_community_list;
12813 output_arg = list;
12814 }
12815
a7129347
RW
12816 if (argv_find(argv, argc, "filter-list", &idx)) {
12817 const char *filter = argv[++idx]->arg;
12818 struct as_list *as_list;
12819
12820 as_list = as_list_lookup(filter);
12821 if (as_list == NULL) {
606d49a4 12822 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12823 filter);
12824 return CMD_WARNING;
12825 }
12826
12827 sh_type = bgp_show_type_filter_list;
12828 output_arg = as_list;
12829 }
12830
6deaf579
RW
12831 if (argv_find(argv, argc, "prefix-list", &idx)) {
12832 const char *prefix_list_str = argv[++idx]->arg;
12833 struct prefix_list *plist;
12834
12835 plist = prefix_list_lookup(afi, prefix_list_str);
12836 if (plist == NULL) {
606d49a4 12837 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12838 prefix_list_str);
12839 return CMD_WARNING;
12840 }
12841
12842 sh_type = bgp_show_type_prefix_list;
12843 output_arg = plist;
12844 }
12845
ed126382
DA
12846 if (argv_find(argv, argc, "access-list", &idx)) {
12847 const char *access_list_str = argv[++idx]->arg;
12848 struct access_list *alist;
12849
12850 alist = access_list_lookup(afi, access_list_str);
12851 if (!alist) {
606d49a4 12852 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12853 access_list_str);
12854 return CMD_WARNING;
12855 }
12856
12857 sh_type = bgp_show_type_access_list;
12858 output_arg = alist;
12859 }
12860
bf1a944a
RW
12861 if (argv_find(argv, argc, "route-map", &idx)) {
12862 const char *rmap_str = argv[++idx]->arg;
12863 struct route_map *rmap;
12864
12865 rmap = route_map_lookup_by_name(rmap_str);
12866 if (!rmap) {
606d49a4 12867 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12868 return CMD_WARNING;
12869 }
12870
12871 sh_type = bgp_show_type_route_map;
12872 output_arg = rmap;
12873 }
12874
1e2ce4f1
DS
12875 if (argv_find(argv, argc, "rpki", &idx)) {
12876 sh_type = bgp_show_type_rpki;
12877 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12878 rpki_target_state = RPKI_VALID;
1e2ce4f1 12879 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12880 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12881 }
12882
7d3cae70
DA
12883 /* Display prefixes with matching version numbers */
12884 if (argv_find(argv, argc, "version", &idx)) {
12885 sh_type = bgp_show_type_prefix_version;
2391833e 12886 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12887 }
12888
a70a28a5
DA
12889 /* Display prefixes with matching BGP community alias */
12890 if (argv_find(argv, argc, "alias", &idx)) {
12891 sh_type = bgp_show_type_community_alias;
2391833e 12892 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12893 }
12894
39c3c736
RW
12895 /* prefix-longer */
12896 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12897 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12898 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12899
12900 if (!str2prefix(prefix_str, &p)) {
12901 vty_out(vty, "%% Malformed Prefix\n");
12902 return CMD_WARNING;
12903 }
12904
12905 sh_type = bgp_show_type_prefix_longer;
12906 output_arg = &p;
a70a28a5
DA
12907 }
12908
83856649
KQ
12909 /* self originated only */
12910 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12911 sh_type = bgp_show_type_self_originated;
12912
96f3485c
MK
12913 if (!all) {
12914 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12915 if (community)
12916 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12917 exact_match, afi, safi,
12918 show_flags);
2391833e 12919 else
a70a28a5 12920 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12921 output_arg, show_flags,
a70a28a5 12922 rpki_target_state);
96f3485c 12923 } else {
fa5ac378
DA
12924 struct listnode *node;
12925 struct bgp *abgp;
96f3485c
MK
12926 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12927 * AFI_IP6 */
12928
12929 if (uj)
12930 vty_out(vty, "{\n");
12931
12932 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12933 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12934 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12935 ? AFI_IP
12936 : AFI_IP6;
fa5ac378
DA
12937 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12938 FOREACH_SAFI (safi) {
12939 if (!bgp_afi_safi_peer_exists(abgp, afi,
12940 safi))
12941 continue;
96f3485c 12942
fa5ac378
DA
12943 if (uj) {
12944 if (first)
12945 first = false;
12946 else
12947 vty_out(vty, ",\n");
12948 vty_out(vty, "\"%s\":{\n",
12949 get_afi_safi_str(afi,
12950 safi,
12951 true));
12952 } else
12953 vty_out(vty,
12954 "\nFor address family: %s\n",
12955 get_afi_safi_str(
12956 afi, safi,
12957 false));
12958
12959 if (community)
12960 bgp_show_community(
12961 vty, abgp, community,
12962 exact_match, afi, safi,
12963 show_flags);
96f3485c 12964 else
fa5ac378
DA
12965 bgp_show(vty, abgp, afi, safi,
12966 sh_type, output_arg,
12967 show_flags,
12968 rpki_target_state);
12969 if (uj)
12970 vty_out(vty, "}\n");
12971 }
96f3485c
MK
12972 }
12973 } else {
12974 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12975 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12976 FOREACH_AFI_SAFI (afi, safi) {
12977 if (!bgp_afi_safi_peer_exists(abgp, afi,
12978 safi))
12979 continue;
96f3485c 12980
fa5ac378
DA
12981 if (uj) {
12982 if (first)
12983 first = false;
12984 else
12985 vty_out(vty, ",\n");
12986
12987 vty_out(vty, "\"%s\":{\n",
12988 get_afi_safi_str(afi,
12989 safi,
12990 true));
12991 } else
12992 vty_out(vty,
12993 "\nFor address family: %s\n",
12994 get_afi_safi_str(
12995 afi, safi,
12996 false));
12997
12998 if (community)
12999 bgp_show_community(
13000 vty, abgp, community,
13001 exact_match, afi, safi,
13002 show_flags);
96f3485c 13003 else
fa5ac378
DA
13004 bgp_show(vty, abgp, afi, safi,
13005 sh_type, output_arg,
13006 show_flags,
13007 rpki_target_state);
13008 if (uj)
13009 vty_out(vty, "}\n");
13010 }
96f3485c
MK
13011 }
13012 }
13013 if (uj)
13014 vty_out(vty, "}\n");
13015 }
13016 return CMD_SUCCESS;
a636c635 13017}
47fc97cc 13018
718e3744 13019DEFUN (show_ip_bgp_route,
13020 show_ip_bgp_route_cmd,
8aa22bbb 13021 "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 13022 SHOW_STR
13023 IP_STR
13024 BGP_STR
a636c635 13025 BGP_INSTANCE_HELP_STR
4f280b15 13026 BGP_AFI_HELP_STR
4dd6177e 13027 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13028 "Network in the BGP routing table to display\n"
0c7b1b01 13029 "IPv4 prefix\n"
8c3deaae 13030 "Network in the BGP routing table to display\n"
0c7b1b01 13031 "IPv6 prefix\n"
4092b06c 13032 "Display only the bestpath\n"
b05a1c8b 13033 "Display only multipaths\n"
8aa22bbb
DS
13034 "Display only paths that match the specified rpki state\n"
13035 "A valid path as determined by rpki\n"
13036 "A invalid path as determined by rpki\n"
13037 "A path that has no rpki data\n"
9973d184 13038 JSON_STR)
4092b06c 13039{
d62a17ae 13040 int prefix_check = 0;
ae19d7dd 13041
d62a17ae 13042 afi_t afi = AFI_IP6;
13043 safi_t safi = SAFI_UNICAST;
13044 char *prefix = NULL;
13045 struct bgp *bgp = NULL;
13046 enum bgp_path_type path_type;
9f049418 13047 bool uj = use_json(argc, argv);
b05a1c8b 13048
d62a17ae 13049 int idx = 0;
ae19d7dd 13050
d62a17ae 13051 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13052 &bgp, uj);
d62a17ae 13053 if (!idx)
13054 return CMD_WARNING;
c41247f5 13055
d62a17ae 13056 if (!bgp) {
13057 vty_out(vty,
13058 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13059 return CMD_WARNING;
13060 }
a636c635 13061
d62a17ae 13062 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13063 if (argv_find(argv, argc, "A.B.C.D", &idx)
13064 || argv_find(argv, argc, "X:X::X:X", &idx))
13065 prefix_check = 0;
13066 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13067 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13068 prefix_check = 1;
13069
13070 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13071 && afi != AFI_IP6) {
13072 vty_out(vty,
13073 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13074 return CMD_WARNING;
13075 }
13076 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13077 && afi != AFI_IP) {
13078 vty_out(vty,
13079 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13080 return CMD_WARNING;
13081 }
13082
13083 prefix = argv[idx]->arg;
13084
13085 /* [<bestpath|multipath>] */
13086 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13087 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13088 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13089 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13090 else
360660c6 13091 path_type = BGP_PATH_SHOW_ALL;
a636c635 13092
d62a17ae 13093 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13094 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13095}
13096
8c3deaae
QY
13097DEFUN (show_ip_bgp_regexp,
13098 show_ip_bgp_regexp_cmd,
3e5b31b3 13099 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13100 SHOW_STR
13101 IP_STR
13102 BGP_STR
b00b230a 13103 BGP_INSTANCE_HELP_STR
4f280b15 13104 BGP_AFI_HELP_STR
4dd6177e 13105 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13106 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13107 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13108 JSON_STR)
8c3deaae 13109{
d62a17ae 13110 afi_t afi = AFI_IP6;
13111 safi_t safi = SAFI_UNICAST;
13112 struct bgp *bgp = NULL;
3e5b31b3
DA
13113 bool uj = use_json(argc, argv);
13114 char *regstr = NULL;
8c3deaae 13115
d62a17ae 13116 int idx = 0;
13117 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13118 &bgp, false);
d62a17ae 13119 if (!idx)
13120 return CMD_WARNING;
8c3deaae 13121
d62a17ae 13122 // get index of regex
3e5b31b3
DA
13123 if (argv_find(argv, argc, "REGEX", &idx))
13124 regstr = argv[idx]->arg;
8c3deaae 13125
5f71d11c 13126 assert(regstr);
3e5b31b3
DA
13127 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13128 bgp_show_type_regexp, uj);
8c3deaae
QY
13129}
13130
ae248832 13131DEFPY (show_ip_bgp_instance_all,
a636c635 13132 show_ip_bgp_instance_all_cmd,
ae248832 13133 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13134 SHOW_STR
a636c635 13135 IP_STR
4092b06c 13136 BGP_STR
a636c635 13137 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13138 BGP_AFI_HELP_STR
4dd6177e 13139 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13140 JSON_STR
13141 "Increase table width for longer prefixes\n")
4092b06c 13142{
54d05dea 13143 afi_t afi = AFI_IP6;
d62a17ae 13144 safi_t safi = SAFI_UNICAST;
13145 struct bgp *bgp = NULL;
d62a17ae 13146 int idx = 0;
96c81f66 13147 uint16_t show_flags = 0;
ae19d7dd 13148
96f3485c 13149 if (uj) {
d62a17ae 13150 argc--;
96f3485c
MK
13151 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13152 }
13153
13154 if (wide)
13155 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13156
9f049418
DS
13157 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13158 &bgp, uj);
13159 if (!idx)
13160 return CMD_WARNING;
13161
96f3485c 13162 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13163 return CMD_SUCCESS;
e3e29b32
LB
13164}
13165
a4d82a8a 13166static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13167 afi_t afi, safi_t safi, enum bgp_show_type type,
13168 bool use_json)
718e3744 13169{
d62a17ae 13170 regex_t *regex;
13171 int rc;
96c81f66 13172 uint16_t show_flags = 0;
96f3485c
MK
13173
13174 if (use_json)
13175 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13176
c3900853 13177 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13178 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13179 regstr);
13180 return CMD_WARNING_CONFIG_FAILED;
13181 }
13182
d62a17ae 13183 regex = bgp_regcomp(regstr);
13184 if (!regex) {
13185 vty_out(vty, "Can't compile regexp %s\n", regstr);
13186 return CMD_WARNING;
13187 }
a636c635 13188
1e2ce4f1
DS
13189 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13190 RPKI_NOT_BEING_USED);
d62a17ae 13191 bgp_regex_free(regex);
13192 return rc;
e3e29b32
LB
13193}
13194
7f323236
DW
13195static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13196 const char *comstr, int exact, afi_t afi,
96c81f66 13197 safi_t safi, uint16_t show_flags)
d62a17ae 13198{
13199 struct community *com;
d62a17ae 13200 int ret = 0;
13201
7f323236 13202 com = community_str2com(comstr);
d62a17ae 13203 if (!com) {
7f323236 13204 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13205 return CMD_WARNING;
13206 }
13207
13208 ret = bgp_show(vty, bgp, afi, safi,
13209 (exact ? bgp_show_type_community_exact
13210 : bgp_show_type_community),
1e2ce4f1 13211 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13212 community_free(&com);
46c3ce83 13213
d62a17ae 13214 return ret;
718e3744 13215}
13216
d62a17ae 13217enum bgp_stats {
13218 BGP_STATS_MAXBITLEN = 0,
13219 BGP_STATS_RIB,
13220 BGP_STATS_PREFIXES,
13221 BGP_STATS_TOTPLEN,
13222 BGP_STATS_UNAGGREGATEABLE,
13223 BGP_STATS_MAX_AGGREGATEABLE,
13224 BGP_STATS_AGGREGATES,
13225 BGP_STATS_SPACE,
13226 BGP_STATS_ASPATH_COUNT,
13227 BGP_STATS_ASPATH_MAXHOPS,
13228 BGP_STATS_ASPATH_TOTHOPS,
13229 BGP_STATS_ASPATH_MAXSIZE,
13230 BGP_STATS_ASPATH_TOTSIZE,
13231 BGP_STATS_ASN_HIGHEST,
13232 BGP_STATS_MAX,
a636c635 13233};
2815e61f 13234
9ab0cf58 13235#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13236#define TABLE_STATS_IDX_JSON 1
13237
13238static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13239 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13240 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13241 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13242 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13243 "unaggregateablePrefixes"},
13244 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13245 "maximumAggregateablePrefixes"},
13246 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13247 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13248 [BGP_STATS_SPACE] = {"Address space advertised",
13249 "addressSpaceAdvertised"},
9ab0cf58
PG
13250 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13251 "advertisementsWithPaths"},
13252 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13253 "longestAsPath"},
13254 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13255 "largestAsPath"},
13256 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13257 "averageAsPathLengthHops"},
13258 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13259 "averageAsPathSizeBytes"},
13260 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13261 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13262};
2815e61f 13263
d62a17ae 13264struct bgp_table_stats {
13265 struct bgp_table *table;
13266 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13267
13268 unsigned long long
13269 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13270 1];
13271
8d0ab76d 13272 double total_space;
ff7924f6
PJ
13273};
13274
9bcb3eef 13275static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13276 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13277{
9bcb3eef 13278 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13279 struct bgp_path_info *pi;
b54892e0 13280 const struct prefix *rn_p;
d62a17ae 13281
9bcb3eef 13282 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13283 return;
d62a17ae 13284
9bcb3eef 13285 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13286 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13287 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13288
0747643e 13289 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13290 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13291 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13292 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13293
9bcb3eef 13294 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13295 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13296 /* announced address space */
13297 if (space)
b54892e0 13298 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13299 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13300 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13301
9c14ec72 13302
9bcb3eef 13303 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13304 ts->counts[BGP_STATS_RIB]++;
13305
05864da7
DS
13306 if (CHECK_FLAG(pi->attr->flag,
13307 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13308 ts->counts[BGP_STATS_AGGREGATES]++;
13309
13310 /* as-path stats */
05864da7 13311 if (pi->attr->aspath) {
9c14ec72
RW
13312 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13313 unsigned int size = aspath_size(pi->attr->aspath);
13314 as_t highest = aspath_highest(pi->attr->aspath);
13315
13316 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13317
13318 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13319 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13320
13321 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13322 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13323
13324 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13325 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13326 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13327 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13328 }
13329 }
13330}
13331
e6685141 13332static void bgp_table_stats_walker(struct event *t)
9c14ec72 13333{
9bcb3eef
DS
13334 struct bgp_dest *dest, *ndest;
13335 struct bgp_dest *top;
e16d030c 13336 struct bgp_table_stats *ts = EVENT_ARG(t);
9c14ec72
RW
13337 unsigned int space = 0;
13338
13339 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13340 return;
9c14ec72
RW
13341
13342 switch (ts->table->afi) {
13343 case AFI_IP:
13344 space = IPV4_MAX_BITLEN;
13345 break;
13346 case AFI_IP6:
13347 space = IPV6_MAX_BITLEN;
13348 break;
3ba7b4af
TA
13349 case AFI_L2VPN:
13350 space = EVPN_ROUTE_PREFIXLEN;
13351 break;
58cf0823
DS
13352 case AFI_UNSPEC:
13353 case AFI_MAX:
cc9f21da 13354 return;
9c14ec72
RW
13355 }
13356
13357 ts->counts[BGP_STATS_MAXBITLEN] = space;
13358
9bcb3eef 13359 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13360 if (ts->table->safi == SAFI_MPLS_VPN
13361 || ts->table->safi == SAFI_ENCAP
13362 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13363 struct bgp_table *table;
13364
9bcb3eef 13365 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13366 if (!table)
13367 continue;
13368
13369 top = bgp_table_top(table);
9bcb3eef
DS
13370 for (ndest = bgp_table_top(table); ndest;
13371 ndest = bgp_route_next(ndest))
13372 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13373 } else {
9bcb3eef 13374 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13375 }
13376 }
2815e61f 13377}
ff7924f6 13378
71f1613a
DA
13379static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13380 struct json_object *json_array)
13381{
13382 struct listnode *node, *nnode;
13383 struct bgp *bgp;
13384
13385 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13386 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13387}
13388
13389static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13390 safi_t safi, struct json_object *json_array)
2815e61f 13391{
d62a17ae 13392 struct bgp_table_stats ts;
13393 unsigned int i;
893cccd0
PG
13394 int ret = CMD_SUCCESS;
13395 char temp_buf[20];
6c9d22e2 13396 struct json_object *json = NULL;
0747643e
AQ
13397 uint32_t bitlen = 0;
13398 struct json_object *json_bitlen;
6c9d22e2
PG
13399
13400 if (json_array)
13401 json = json_object_new_object();
019386c2 13402
d62a17ae 13403 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13404 char warning_msg[50];
13405
13406 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13407 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13408 safi);
6c9d22e2
PG
13409
13410 if (!json)
893cccd0
PG
13411 vty_out(vty, "%s\n", warning_msg);
13412 else
9ab0cf58 13413 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13414
893cccd0
PG
13415 ret = CMD_WARNING;
13416 goto end_table_stats;
d62a17ae 13417 }
019386c2 13418
893cccd0 13419 if (!json)
5290ceab
DA
13420 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13421 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13422 else
13423 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13424
d62a17ae 13425 /* labeled-unicast routes live in the unicast table */
13426 if (safi == SAFI_LABELED_UNICAST)
13427 safi = SAFI_UNICAST;
019386c2 13428
d62a17ae 13429 memset(&ts, 0, sizeof(ts));
13430 ts.table = bgp->rib[afi][safi];
8c1186d3 13431 event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13432
d62a17ae 13433 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13434 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13435 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13436 continue;
13437
13438 switch (i) {
d62a17ae 13439 case BGP_STATS_ASPATH_TOTHOPS:
13440 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13441 if (!json) {
9ab0cf58
PG
13442 snprintf(
13443 temp_buf, sizeof(temp_buf), "%12.2f",
13444 ts.counts[i]
13445 ? (float)ts.counts[i]
13446 / (float)ts.counts
13447 [BGP_STATS_ASPATH_COUNT]
13448 : 0);
893cccd0 13449 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13450 table_stats_strs[i]
13451 [TABLE_STATS_IDX_VTY],
893cccd0 13452 temp_buf);
9ab0cf58
PG
13453 } else {
13454 json_object_double_add(
13455 json,
13456 table_stats_strs[i]
13457 [TABLE_STATS_IDX_JSON],
13458 ts.counts[i]
13459 ? (double)ts.counts[i]
13460 / (double)ts.counts
d62a17ae 13461 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13462 : 0);
13463 }
d62a17ae 13464 break;
13465 case BGP_STATS_TOTPLEN:
6c9d22e2 13466 if (!json) {
9ab0cf58
PG
13467 snprintf(
13468 temp_buf, sizeof(temp_buf), "%12.2f",
13469 ts.counts[i]
13470 ? (float)ts.counts[i]
13471 / (float)ts.counts
13472 [BGP_STATS_PREFIXES]
13473 : 0);
893cccd0 13474 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13475 table_stats_strs[i]
13476 [TABLE_STATS_IDX_VTY],
893cccd0 13477 temp_buf);
9ab0cf58
PG
13478 } else {
13479 json_object_double_add(
13480 json,
13481 table_stats_strs[i]
13482 [TABLE_STATS_IDX_JSON],
13483 ts.counts[i]
13484 ? (double)ts.counts[i]
13485 / (double)ts.counts
d62a17ae 13486 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13487 : 0);
13488 }
d62a17ae 13489 break;
13490 case BGP_STATS_SPACE:
6c9d22e2
PG
13491 if (!json) {
13492 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13493 ts.total_space);
893cccd0 13494 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13495 table_stats_strs[i]
13496 [TABLE_STATS_IDX_VTY],
893cccd0 13497 temp_buf);
9ab0cf58
PG
13498 } else {
13499 json_object_double_add(
13500 json,
13501 table_stats_strs[i]
13502 [TABLE_STATS_IDX_JSON],
13503 (double)ts.total_space);
13504 }
8d0ab76d 13505 if (afi == AFI_IP6) {
6c9d22e2
PG
13506 if (!json) {
13507 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13508 "%12g",
13509 ts.total_space
13510 * pow(2.0, -128 + 32));
6c9d22e2
PG
13511 vty_out(vty, "%30s: %s\n",
13512 "/32 equivalent %s\n",
13513 temp_buf);
9ab0cf58
PG
13514 } else {
13515 json_object_double_add(
13516 json, "/32equivalent",
13517 (double)(ts.total_space
13518 * pow(2.0,
13519 -128 + 32)));
13520 }
6c9d22e2
PG
13521 if (!json) {
13522 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13523 "%12g",
13524 ts.total_space
13525 * pow(2.0, -128 + 48));
6c9d22e2
PG
13526 vty_out(vty, "%30s: %s\n",
13527 "/48 equivalent %s\n",
13528 temp_buf);
9ab0cf58
PG
13529 } else {
13530 json_object_double_add(
13531 json, "/48equivalent",
13532 (double)(ts.total_space
13533 * pow(2.0,
13534 -128 + 48)));
13535 }
8d0ab76d 13536 } else {
6c9d22e2
PG
13537 if (!json) {
13538 snprintf(temp_buf, sizeof(temp_buf),
13539 "%12.2f",
9ab0cf58
PG
13540 ts.total_space * 100.
13541 * pow(2.0, -32));
6c9d22e2 13542 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13543 "% announced ", temp_buf);
13544 } else {
13545 json_object_double_add(
13546 json, "%announced",
13547 (double)(ts.total_space * 100.
13548 * pow(2.0, -32)));
13549 }
6c9d22e2
PG
13550 if (!json) {
13551 snprintf(temp_buf, sizeof(temp_buf),
13552 "%12.2f",
9ab0cf58
PG
13553 ts.total_space
13554 * pow(2.0, -32 + 8));
6c9d22e2
PG
13555 vty_out(vty, "%30s: %s\n",
13556 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13557 } else {
13558 json_object_double_add(
13559 json, "/8equivalent",
13560 (double)(ts.total_space
13561 * pow(2.0, -32 + 8)));
13562 }
6c9d22e2
PG
13563 if (!json) {
13564 snprintf(temp_buf, sizeof(temp_buf),
13565 "%12.2f",
9ab0cf58
PG
13566 ts.total_space
13567 * pow(2.0, -32 + 24));
6c9d22e2 13568 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13569 "/24 equivalent ", temp_buf);
13570 } else {
13571 json_object_double_add(
13572 json, "/24equivalent",
13573 (double)(ts.total_space
13574 * pow(2.0, -32 + 24)));
13575 }
8d0ab76d 13576 }
d62a17ae 13577 break;
13578 default:
6c9d22e2
PG
13579 if (!json) {
13580 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13581 ts.counts[i]);
893cccd0 13582 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13583 table_stats_strs[i]
13584 [TABLE_STATS_IDX_VTY],
13585 temp_buf);
13586 } else {
13587 json_object_int_add(
13588 json,
13589 table_stats_strs[i]
13590 [TABLE_STATS_IDX_JSON],
13591 ts.counts[i]);
13592 }
d62a17ae 13593 }
893cccd0
PG
13594 if (!json)
13595 vty_out(vty, "\n");
d62a17ae 13596 }
0747643e
AQ
13597
13598 switch (afi) {
13599 case AFI_IP:
13600 bitlen = IPV4_MAX_BITLEN;
13601 break;
13602 case AFI_IP6:
13603 bitlen = IPV6_MAX_BITLEN;
13604 break;
13605 case AFI_L2VPN:
13606 bitlen = EVPN_ROUTE_PREFIXLEN;
13607 break;
58cf0823
DS
13608 case AFI_UNSPEC:
13609 case AFI_MAX:
0747643e
AQ
13610 break;
13611 }
13612
13613 if (json) {
13614 json_bitlen = json_object_new_array();
13615
13616 for (i = 0; i <= bitlen; i++) {
13617 struct json_object *ind_bit = json_object_new_object();
13618
13619 if (!ts.prefix_len_count[i])
13620 continue;
13621
13622 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13623 json_object_int_add(ind_bit, temp_buf,
13624 ts.prefix_len_count[i]);
13625 json_object_array_add(json_bitlen, ind_bit);
13626 }
13627 json_object_object_add(json, "prefixLength", json_bitlen);
13628 }
13629
9ab0cf58 13630end_table_stats:
6c9d22e2
PG
13631 if (json)
13632 json_object_array_add(json_array, json);
893cccd0 13633 return ret;
d62a17ae 13634}
13635
71f1613a
DA
13636static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13637 safi_t safi, struct json_object *json_array)
13638{
13639 if (!bgp) {
13640 bgp_table_stats_all(vty, afi, safi, json_array);
13641 return CMD_SUCCESS;
13642 }
13643
13644 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13645}
13646
d62a17ae 13647enum bgp_pcounts {
13648 PCOUNT_ADJ_IN = 0,
13649 PCOUNT_DAMPED,
13650 PCOUNT_REMOVED,
13651 PCOUNT_HISTORY,
13652 PCOUNT_STALE,
13653 PCOUNT_VALID,
13654 PCOUNT_ALL,
13655 PCOUNT_COUNTED,
7e3d9632 13656 PCOUNT_BPATH_SELECTED,
d62a17ae 13657 PCOUNT_PFCNT, /* the figure we display to users */
13658 PCOUNT_MAX,
a636c635 13659};
718e3744 13660
2b64873d 13661static const char *const pcount_strs[] = {
9d303b37
DL
13662 [PCOUNT_ADJ_IN] = "Adj-in",
13663 [PCOUNT_DAMPED] = "Damped",
13664 [PCOUNT_REMOVED] = "Removed",
13665 [PCOUNT_HISTORY] = "History",
13666 [PCOUNT_STALE] = "Stale",
13667 [PCOUNT_VALID] = "Valid",
13668 [PCOUNT_ALL] = "All RIB",
13669 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13670 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13671 [PCOUNT_PFCNT] = "Useable",
13672 [PCOUNT_MAX] = NULL,
a636c635 13673};
718e3744 13674
d62a17ae 13675struct peer_pcounts {
13676 unsigned int count[PCOUNT_MAX];
13677 const struct peer *peer;
13678 const struct bgp_table *table;
54317cba 13679 safi_t safi;
a636c635 13680};
47fc97cc 13681
9bcb3eef 13682static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13683{
54317cba
JW
13684 const struct bgp_adj_in *ain;
13685 const struct bgp_path_info *pi;
d62a17ae 13686 const struct peer *peer = pc->peer;
13687
54317cba
JW
13688 for (ain = rn->adj_in; ain; ain = ain->next)
13689 if (ain->peer == peer)
13690 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13691
9bcb3eef 13692 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13693
54317cba
JW
13694 if (pi->peer != peer)
13695 continue;
d62a17ae 13696
54317cba 13697 pc->count[PCOUNT_ALL]++;
d62a17ae 13698
54317cba
JW
13699 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13700 pc->count[PCOUNT_DAMPED]++;
13701 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13702 pc->count[PCOUNT_HISTORY]++;
13703 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13704 pc->count[PCOUNT_REMOVED]++;
13705 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13706 pc->count[PCOUNT_STALE]++;
13707 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13708 pc->count[PCOUNT_VALID]++;
13709 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13710 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13711 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13712 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13713
13714 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13715 pc->count[PCOUNT_COUNTED]++;
13716 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13717 flog_err(
13718 EC_LIB_DEVELOPMENT,
13719 "Attempting to count but flags say it is unusable");
13720 } else {
40381db7 13721 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13722 flog_err(
13723 EC_LIB_DEVELOPMENT,
13724 "Not counted but flags say we should");
d62a17ae 13725 }
13726 }
54317cba
JW
13727}
13728
e6685141 13729static void bgp_peer_count_walker(struct event *t)
54317cba 13730{
9bcb3eef 13731 struct bgp_dest *rn, *rm;
54317cba 13732 const struct bgp_table *table;
e16d030c 13733 struct peer_pcounts *pc = EVENT_ARG(t);
54317cba
JW
13734
13735 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13736 || pc->safi == SAFI_EVPN) {
13737 /* Special handling for 2-level routing tables. */
13738 for (rn = bgp_table_top(pc->table); rn;
13739 rn = bgp_route_next(rn)) {
9bcb3eef 13740 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13741 if (table != NULL)
13742 for (rm = bgp_table_top(table); rm;
13743 rm = bgp_route_next(rm))
13744 bgp_peer_count_proc(rm, pc);
13745 }
13746 } else
13747 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13748 bgp_peer_count_proc(rn, pc);
718e3744 13749}
13750
d62a17ae 13751static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13752 safi_t safi, bool use_json)
856ca177 13753{
d62a17ae 13754 struct peer_pcounts pcounts = {.peer = peer};
13755 unsigned int i;
13756 json_object *json = NULL;
13757 json_object *json_loop = NULL;
856ca177 13758
d62a17ae 13759 if (use_json) {
13760 json = json_object_new_object();
13761 json_loop = json_object_new_object();
13762 }
718e3744 13763
d62a17ae 13764 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13765 || !peer->bgp->rib[afi][safi]) {
13766 if (use_json) {
13767 json_object_string_add(
13768 json, "warning",
13769 "No such neighbor or address family");
13770 vty_out(vty, "%s\n", json_object_to_json_string(json));
13771 json_object_free(json);
d5f20468 13772 json_object_free(json_loop);
d62a17ae 13773 } else
13774 vty_out(vty, "%% No such neighbor or address family\n");
13775
13776 return CMD_WARNING;
13777 }
2a71e9ce 13778
d62a17ae 13779 memset(&pcounts, 0, sizeof(pcounts));
13780 pcounts.peer = peer;
13781 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13782 pcounts.safi = safi;
d62a17ae 13783
13784 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13785 * stats for the thread-walk (i.e. ensure this can't be blamed on
13786 * on just vty_read()).
13787 */
8c1186d3 13788 event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
d62a17ae 13789
13790 if (use_json) {
13791 json_object_string_add(json, "prefixCountsFor", peer->host);
13792 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13793 get_afi_safi_str(afi, safi, true));
d62a17ae 13794 json_object_int_add(json, "pfxCounter",
13795 peer->pcount[afi][safi]);
13796
13797 for (i = 0; i < PCOUNT_MAX; i++)
13798 json_object_int_add(json_loop, pcount_strs[i],
13799 pcounts.count[i]);
13800
13801 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13802
13803 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13804 json_object_string_add(json, "pfxctDriftFor",
13805 peer->host);
13806 json_object_string_add(
13807 json, "recommended",
13808 "Please report this bug, with the above command output");
13809 }
75eeda93 13810 vty_json(vty, json);
d62a17ae 13811 } else {
13812
13813 if (peer->hostname
892fedb6 13814 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13815 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13816 peer->hostname, peer->host,
5cb5f4d0 13817 get_afi_safi_str(afi, safi, false));
d62a17ae 13818 } else {
13819 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13820 get_afi_safi_str(afi, safi, false));
d62a17ae 13821 }
13822
6cde4b45 13823 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13824 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13825
13826 for (i = 0; i < PCOUNT_MAX; i++)
13827 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13828 pcounts.count[i]);
13829
13830 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13831 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13832 vty_out(vty,
13833 "Please report this bug, with the above command output\n");
13834 }
13835 }
13836
13837 return CMD_SUCCESS;
718e3744 13838}
13839
a636c635
DW
13840DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13841 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13842 "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 13843 SHOW_STR
13844 IP_STR
13845 BGP_STR
8386ac43 13846 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13847 BGP_AFI_HELP_STR
13848 BGP_SAFI_HELP_STR
0b16f239
DS
13849 "Detailed information on TCP and BGP neighbor connections\n"
13850 "Neighbor to display information about\n"
13851 "Neighbor to display information about\n"
91d37724 13852 "Neighbor on BGP configured interface\n"
a636c635 13853 "Display detailed prefix count information\n"
9973d184 13854 JSON_STR)
0b16f239 13855{
d62a17ae 13856 afi_t afi = AFI_IP6;
13857 safi_t safi = SAFI_UNICAST;
13858 struct peer *peer;
13859 int idx = 0;
13860 struct bgp *bgp = NULL;
9f049418
DS
13861 bool uj = use_json(argc, argv);
13862
13863 if (uj)
13864 argc--;
856ca177 13865
d62a17ae 13866 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13867 &bgp, uj);
d62a17ae 13868 if (!idx)
13869 return CMD_WARNING;
0b16f239 13870
d62a17ae 13871 argv_find(argv, argc, "neighbors", &idx);
13872 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13873 if (!peer)
13874 return CMD_WARNING;
bb46e94f 13875
29c8d9da 13876 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13877}
0b16f239 13878
d6902373
PG
13879#ifdef KEEP_OLD_VPN_COMMANDS
13880DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13881 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13882 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13883 SHOW_STR
13884 IP_STR
13885 BGP_STR
d6902373 13886 BGP_VPNVX_HELP_STR
91d37724 13887 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13888 "Detailed information on TCP and BGP neighbor connections\n"
13889 "Neighbor to display information about\n"
13890 "Neighbor to display information about\n"
91d37724 13891 "Neighbor on BGP configured interface\n"
a636c635 13892 "Display detailed prefix count information\n"
9973d184 13893 JSON_STR)
a636c635 13894{
d62a17ae 13895 int idx_peer = 6;
13896 struct peer *peer;
9f049418 13897 bool uj = use_json(argc, argv);
a636c635 13898
d62a17ae 13899 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13900 if (!peer)
13901 return CMD_WARNING;
13902
13903 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13904}
13905
d6902373
PG
13906DEFUN (show_ip_bgp_vpn_all_route_prefix,
13907 show_ip_bgp_vpn_all_route_prefix_cmd,
13908 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13909 SHOW_STR
13910 IP_STR
13911 BGP_STR
d6902373 13912 BGP_VPNVX_HELP_STR
91d37724
QY
13913 "Display information about all VPNv4 NLRIs\n"
13914 "Network in the BGP routing table to display\n"
3a2d747c 13915 "Network in the BGP routing table to display\n"
9973d184 13916 JSON_STR)
91d37724 13917{
d62a17ae 13918 int idx = 0;
13919 char *network = NULL;
13920 struct bgp *bgp = bgp_get_default();
13921 if (!bgp) {
13922 vty_out(vty, "Can't find default instance\n");
13923 return CMD_WARNING;
13924 }
87e34b58 13925
d62a17ae 13926 if (argv_find(argv, argc, "A.B.C.D", &idx))
13927 network = argv[idx]->arg;
13928 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13929 network = argv[idx]->arg;
13930 else {
13931 vty_out(vty, "Unable to figure out Network\n");
13932 return CMD_WARNING;
13933 }
87e34b58 13934
d62a17ae 13935 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13936 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13937 use_json(argc, argv));
91d37724 13938}
d6902373 13939#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13940
44c69747
LK
13941DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13942 show_bgp_l2vpn_evpn_route_prefix_cmd,
13943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13944 SHOW_STR
4c63a661
PG
13945 BGP_STR
13946 L2VPN_HELP_STR
13947 EVPN_HELP_STR
44c69747
LK
13948 "Network in the BGP routing table to display\n"
13949 "Network in the BGP routing table to display\n"
4c63a661
PG
13950 "Network in the BGP routing table to display\n"
13951 "Network in the BGP routing table to display\n"
13952 JSON_STR)
13953{
d62a17ae 13954 int idx = 0;
13955 char *network = NULL;
44c69747 13956 int prefix_check = 0;
a636c635 13957
44c69747
LK
13958 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13959 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13960 network = argv[idx]->arg;
44c69747 13961 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13962 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13963 network = argv[idx]->arg;
44c69747
LK
13964 prefix_check = 1;
13965 } else {
d62a17ae 13966 vty_out(vty, "Unable to figure out Network\n");
13967 return CMD_WARNING;
13968 }
44c69747
LK
13969 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13970 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13971 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13972}
13973
114fc229 13974static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13975 struct bgp_table *table, int *header1,
13976 int *header2, json_object *json,
13977 json_object *json_scode,
e960b4ca
TA
13978 json_object *json_ocode, bool wide,
13979 bool detail)
2f9bc755
DS
13980{
13981 uint64_t version = table ? table->version : 0;
13982
13983 if (*header1) {
13984 if (json) {
13985 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13986 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13987 "%pI4", &peer->bgp->router_id);
2f9bc755 13988 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13989 peer->bgp->default_local_pref);
13990 json_object_int_add(json, "localAS",
13991 peer->change_local_as
13992 ? peer->change_local_as
13993 : peer->local_as);
2f9bc755
DS
13994 json_object_object_add(json, "bgpStatusCodes",
13995 json_scode);
13996 json_object_object_add(json, "bgpOriginCodes",
13997 json_ocode);
13998 } else {
13999 vty_out(vty,
23d0a753
DA
14000 "BGP table version is %" PRIu64
14001 ", local router ID is %pI4, vrf id ",
114fc229
DA
14002 version, &peer->bgp->router_id);
14003 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14004 vty_out(vty, "%s", VRFID_NONE_STR);
14005 else
114fc229 14006 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14007 vty_out(vty, "\n");
14008 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14009 peer->bgp->default_local_pref);
14010 vty_out(vty, "local AS %u\n",
14011 peer->change_local_as ? peer->change_local_as
14012 : peer->local_as);
e960b4ca
TA
14013 if (!detail) {
14014 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14015 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14016 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14017 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14018 }
2f9bc755
DS
14019 }
14020 *header1 = 0;
14021 }
14022 if (*header2) {
e960b4ca 14023 if (!json && !detail)
2f9bc755
DS
14024 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14025 : BGP_SHOW_HEADER));
14026 *header2 = 0;
14027 }
14028}
14029
d9478df0
TA
14030static void
14031show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14032 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14033 const char *rmap_name, json_object *json, json_object *json_ar,
14034 json_object *json_scode, json_object *json_ocode,
96c81f66 14035 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14036 const struct prefix *match, unsigned long *output_count,
14037 unsigned long *filtered_count)
d62a17ae 14038{
3880b4ec
TA
14039 struct bgp_adj_in *ain = NULL;
14040 struct bgp_adj_out *adj = NULL;
9bcb3eef 14041 struct bgp_dest *dest;
d62a17ae 14042 struct bgp *bgp;
d62a17ae 14043 struct attr attr;
14044 int ret;
14045 struct update_subgroup *subgrp;
3880b4ec 14046 struct peer_af *paf = NULL;
f99def61 14047 bool route_filtered;
e960b4ca 14048 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14049 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14050 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14051 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14052 || (safi == SAFI_EVPN))
14053 ? true
14054 : false;
e960b4ca
TA
14055 int display = 0;
14056 json_object *json_net = NULL;
a636c635 14057
d62a17ae 14058 bgp = peer->bgp;
a636c635 14059
3880b4ec
TA
14060 /* If the user supplied a prefix, look for a matching route instead
14061 * of walking the whole table.
14062 */
14063 if (match) {
14064 dest = bgp_node_match(table, match);
14065 if (!dest) {
14066 if (!use_json)
14067 vty_out(vty, "Network not in table\n");
14068 return;
14069 }
14070
14071 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14072
14073 if (rn_p->prefixlen != match->prefixlen) {
14074 if (!use_json)
14075 vty_out(vty, "Network not in table\n");
14076 bgp_dest_unlock_node(dest);
14077 return;
14078 }
14079
14080 if (type == bgp_show_adj_route_received ||
14081 type == bgp_show_adj_route_filtered) {
14082 for (ain = dest->adj_in; ain; ain = ain->next) {
14083 if (ain->peer == peer) {
14084 attr = *ain->attr;
14085 break;
14086 }
14087 }
14088 /* bail out if if adj_out is empty, or
14089 * if the prefix isn't in this peer's
14090 * adj_in
14091 */
14092 if (!ain || ain->peer != peer) {
14093 if (!use_json)
14094 vty_out(vty, "Network not in table\n");
14095 bgp_dest_unlock_node(dest);
14096 return;
14097 }
14098 } else if (type == bgp_show_adj_route_advertised) {
14099 bool peer_found = false;
14100
14101 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14102 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14103 if (paf->peer == peer && adj->attr) {
14104 attr = *adj->attr;
14105 peer_found = true;
14106 break;
14107 }
14108 }
14109 if (peer_found)
14110 break;
14111 }
14112 /* bail out if if adj_out is empty, or
14113 * if the prefix isn't in this peer's
14114 * adj_out
14115 */
14116 if (!paf || !peer_found) {
14117 if (!use_json)
14118 vty_out(vty, "Network not in table\n");
14119 bgp_dest_unlock_node(dest);
14120 return;
14121 }
14122 }
14123
14124 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14125 rmap_name);
14126
14127 if (ret != RMAP_DENY) {
14128 show_adj_route_header(vty, peer, table, header1,
14129 header2, json, json_scode,
14130 json_ocode, wide, detail);
14131
14132 if (use_json)
14133 json_net = json_object_new_object();
14134
14135 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14136 afi, safi, json_net,
14137 BGP_PATH_SHOW_ALL, &display,
14138 RPKI_NOT_BEING_USED);
14139 if (use_json)
14140 json_object_object_addf(json_ar, json_net,
14141 "%pFX", rn_p);
14142 (*output_count)++;
14143 } else
14144 (*filtered_count)++;
14145
14146 bgp_attr_flush(&attr);
14147 bgp_dest_unlock_node(dest);
14148 return;
14149 }
14150
14151
d62a17ae 14152 subgrp = peer_subgroup(peer, afi, safi);
14153
6392aaa6 14154 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14155 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14156 if (use_json) {
14157 json_object_int_add(json, "bgpTableVersion",
14158 table->version);
c949c771
DA
14159 json_object_string_addf(json, "bgpLocalRouterId",
14160 "%pI4", &bgp->router_id);
01eced22
AD
14161 json_object_int_add(json, "defaultLocPrf",
14162 bgp->default_local_pref);
114fc229
DA
14163 json_object_int_add(json, "localAS",
14164 peer->change_local_as
14165 ? peer->change_local_as
14166 : peer->local_as);
d62a17ae 14167 json_object_object_add(json, "bgpStatusCodes",
14168 json_scode);
14169 json_object_object_add(json, "bgpOriginCodes",
14170 json_ocode);
07d0c4ed
DA
14171 json_object_string_add(
14172 json, "bgpOriginatingDefaultNetwork",
14173 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14174 } else {
23d0a753
DA
14175 vty_out(vty,
14176 "BGP table version is %" PRIu64
14177 ", local router ID is %pI4, vrf id ",
14178 table->version, &bgp->router_id);
9df8b37c
PZ
14179 if (bgp->vrf_id == VRF_UNKNOWN)
14180 vty_out(vty, "%s", VRFID_NONE_STR);
14181 else
14182 vty_out(vty, "%u", bgp->vrf_id);
14183 vty_out(vty, "\n");
01eced22
AD
14184 vty_out(vty, "Default local pref %u, ",
14185 bgp->default_local_pref);
114fc229
DA
14186 vty_out(vty, "local AS %u\n",
14187 peer->change_local_as ? peer->change_local_as
14188 : peer->local_as);
e960b4ca
TA
14189 if (!detail) {
14190 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14191 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14192 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14193 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14194 }
d62a17ae 14195
07d0c4ed
DA
14196 vty_out(vty, "Originating default network %s\n\n",
14197 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14198 }
65565c9a 14199 (*output_count)++;
d9478df0 14200 *header1 = 0;
d62a17ae 14201 }
a636c635 14202
9bcb3eef 14203 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14204 if (type == bgp_show_adj_route_received
14205 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14206 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14207 if (ain->peer != peer)
ea47320b 14208 continue;
6392aaa6 14209
114fc229 14210 show_adj_route_header(vty, peer, table, header1,
d9478df0 14211 header2, json, json_scode,
e960b4ca 14212 json_ocode, wide, detail);
d9478df0
TA
14213
14214 if ((safi == SAFI_MPLS_VPN)
14215 || (safi == SAFI_ENCAP)
14216 || (safi == SAFI_EVPN)) {
14217 if (use_json)
14218 json_object_string_add(
14219 json_ar, "rd", rd_str);
14220 else if (show_rd && rd_str) {
14221 vty_out(vty,
14222 "Route Distinguisher: %s\n",
14223 rd_str);
14224 show_rd = false;
14225 }
14226 }
6392aaa6 14227
6f4f49b2 14228 attr = *ain->attr;
f99def61
AD
14229 route_filtered = false;
14230
14231 /* Filter prefix using distribute list,
14232 * filter list or prefix list
14233 */
b54892e0 14234 const struct prefix *rn_p =
9bcb3eef 14235 bgp_dest_get_prefix(dest);
b54892e0
DS
14236 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14237 safi))
14238 == FILTER_DENY)
f99def61
AD
14239 route_filtered = true;
14240
14241 /* Filter prefix using route-map */
b54892e0
DS
14242 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14243 safi, rmap_name, NULL,
14244 0, NULL);
6392aaa6 14245
13c8e163
AD
14246 if (type == bgp_show_adj_route_filtered &&
14247 !route_filtered && ret != RMAP_DENY) {
d498917e 14248 bgp_attr_flush(&attr);
6392aaa6 14249 continue;
d62a17ae 14250 }
6392aaa6 14251
d9478df0
TA
14252 if (type == bgp_show_adj_route_received
14253 && (route_filtered || ret == RMAP_DENY))
14254 (*filtered_count)++;
6392aaa6 14255
e960b4ca
TA
14256 if (detail) {
14257 if (use_json)
14258 json_net =
14259 json_object_new_object();
14260 bgp_show_path_info(
14261 NULL /* prefix_rd */, dest, vty,
14262 bgp, afi, safi, json_net,
14263 BGP_PATH_SHOW_ALL, &display,
14264 RPKI_NOT_BEING_USED);
14265 if (use_json)
14266 json_object_object_addf(
14267 json_ar, json_net,
14268 "%pFX", rn_p);
14269 } else
14270 route_vty_out_tmp(vty, dest, rn_p,
14271 &attr, safi, use_json,
14272 json_ar, wide);
d498917e 14273 bgp_attr_flush(&attr);
d9478df0 14274 (*output_count)++;
d62a17ae 14275 }
6392aaa6 14276 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14277 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14278 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14279 if (paf->peer != peer || !adj->attr)
924c3f6a 14280 continue;
d62a17ae 14281
e960b4ca
TA
14282 show_adj_route_header(
14283 vty, peer, table, header1,
14284 header2, json, json_scode,
14285 json_ocode, wide, detail);
d62a17ae 14286
b54892e0 14287 const struct prefix *rn_p =
9bcb3eef 14288 bgp_dest_get_prefix(dest);
b54892e0 14289
6f4f49b2 14290 attr = *adj->attr;
b755861b 14291 ret = bgp_output_modifier(
b54892e0 14292 peer, rn_p, &attr, afi, safi,
b755861b 14293 rmap_name);
f46d8e1e 14294
b755861b 14295 if (ret != RMAP_DENY) {
d9478df0
TA
14296 if ((safi == SAFI_MPLS_VPN)
14297 || (safi == SAFI_ENCAP)
14298 || (safi == SAFI_EVPN)) {
14299 if (use_json)
14300 json_object_string_add(
14301 json_ar,
14302 "rd",
14303 rd_str);
14304 else if (show_rd
14305 && rd_str) {
14306 vty_out(vty,
14307 "Route Distinguisher: %s\n",
14308 rd_str);
14309 show_rd = false;
14310 }
14311 }
e960b4ca
TA
14312 if (detail) {
14313 if (use_json)
14314 json_net =
14315 json_object_new_object();
14316 bgp_show_path_info(
14317 NULL /* prefix_rd
14318 */
14319 ,
14320 dest, vty, bgp,
14321 afi, safi,
14322 json_net,
14323 BGP_PATH_SHOW_ALL,
14324 &display,
14325 RPKI_NOT_BEING_USED);
14326 if (use_json)
14327 json_object_object_addf(
14328 json_ar,
14329 json_net,
14330 "%pFX",
14331 rn_p);
14332 } else
14333 route_vty_out_tmp(
14334 vty, dest, rn_p,
14335 &attr, safi,
14336 use_json,
14337 json_ar, wide);
d9478df0 14338 (*output_count)++;
b755861b 14339 } else {
d9478df0 14340 (*filtered_count)++;
a2addae8 14341 }
b755861b 14342
d498917e 14343 bgp_attr_flush(&attr);
924c3f6a 14344 }
f20ce998
DS
14345 } else if (type == bgp_show_adj_route_bestpath) {
14346 struct bgp_path_info *pi;
14347
114fc229
DA
14348 show_adj_route_header(vty, peer, table, header1,
14349 header2, json, json_scode,
e960b4ca 14350 json_ocode, wide, detail);
f20ce998 14351
aa9bf57e
TA
14352 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14353
f20ce998
DS
14354 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14355 pi = pi->next) {
14356 if (pi->peer != peer)
14357 continue;
14358
14359 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14360 continue;
14361
aa9bf57e
TA
14362 if (detail) {
14363 if (use_json)
14364 json_net =
14365 json_object_new_object();
14366 bgp_show_path_info(
14367 NULL /* prefix_rd */, dest, vty,
14368 bgp, afi, safi, json_net,
14369 BGP_PATH_SHOW_BESTPATH,
14370 &display, RPKI_NOT_BEING_USED);
14371 if (use_json)
14372 json_object_object_addf(
14373 json_ar, json_net,
14374 "%pFX", rn_p);
14375 } else
14376 route_vty_out_tmp(
14377 vty, dest, rn_p, pi->attr, safi,
14378 use_json, json_ar, wide);
d9478df0 14379 (*output_count)++;
f20ce998 14380 }
d62a17ae 14381 }
14382 }
a636c635 14383}
2a71e9ce 14384
d62a17ae 14385static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14386 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14387 const char *rmap_name, const struct prefix *match,
14388 uint16_t show_flags)
0b16f239 14389{
d9478df0
TA
14390 struct bgp *bgp;
14391 struct bgp_table *table;
d62a17ae 14392 json_object *json = NULL;
d9478df0
TA
14393 json_object *json_scode = NULL;
14394 json_object *json_ocode = NULL;
14395 json_object *json_ar = NULL;
96f3485c 14396 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14397
d9478df0
TA
14398 /* Init BGP headers here so they're only displayed once
14399 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14400 */
14401 int header1 = 1;
14402 int header2 = 1;
14403
14404 /*
14405 * Initialize variables for each RD
14406 * All prefixes under an RD is aggregated within "json_routes"
14407 */
14408 char rd_str[BUFSIZ] = {0};
14409 json_object *json_routes = NULL;
14410
14411
14412 /* For 2-tier tables, prefix counts need to be
14413 * maintained across multiple runs of show_adj_route()
14414 */
14415 unsigned long output_count_per_rd;
14416 unsigned long filtered_count_per_rd;
14417 unsigned long output_count = 0;
14418 unsigned long filtered_count = 0;
14419
14420 if (use_json) {
d62a17ae 14421 json = json_object_new_object();
d9478df0
TA
14422 json_ar = json_object_new_object();
14423 json_scode = json_object_new_object();
14424 json_ocode = json_object_new_object();
dd426a51
DA
14425#if CONFDATE > 20231208
14426CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14427#endif
d9478df0
TA
14428 json_object_string_add(json_scode, "suppressed", "s");
14429 json_object_string_add(json_scode, "damped", "d");
14430 json_object_string_add(json_scode, "history", "h");
14431 json_object_string_add(json_scode, "valid", "*");
14432 json_object_string_add(json_scode, "best", ">");
14433 json_object_string_add(json_scode, "multipath", "=");
14434 json_object_string_add(json_scode, "internal", "i");
14435 json_object_string_add(json_scode, "ribFailure", "r");
14436 json_object_string_add(json_scode, "stale", "S");
14437 json_object_string_add(json_scode, "removed", "R");
14438
dd426a51
DA
14439#if CONFDATE > 20231208
14440CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14441#endif
d9478df0
TA
14442 json_object_string_add(json_ocode, "igp", "i");
14443 json_object_string_add(json_ocode, "egp", "e");
14444 json_object_string_add(json_ocode, "incomplete", "?");
14445 }
0b16f239 14446
d62a17ae 14447 if (!peer || !peer->afc[afi][safi]) {
14448 if (use_json) {
14449 json_object_string_add(
14450 json, "warning",
14451 "No such neighbor or address family");
14452 vty_out(vty, "%s\n", json_object_to_json_string(json));
14453 json_object_free(json);
690c3134
MW
14454 json_object_free(json_ar);
14455 json_object_free(json_scode);
14456 json_object_free(json_ocode);
d62a17ae 14457 } else
14458 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14459
d62a17ae 14460 return CMD_WARNING;
14461 }
14462
6392aaa6
PM
14463 if ((type == bgp_show_adj_route_received
14464 || type == bgp_show_adj_route_filtered)
d62a17ae 14465 && !CHECK_FLAG(peer->af_flags[afi][safi],
14466 PEER_FLAG_SOFT_RECONFIG)) {
14467 if (use_json) {
14468 json_object_string_add(
14469 json, "warning",
14470 "Inbound soft reconfiguration not enabled");
14471 vty_out(vty, "%s\n", json_object_to_json_string(json));
14472 json_object_free(json);
690c3134
MW
14473 json_object_free(json_ar);
14474 json_object_free(json_scode);
14475 json_object_free(json_ocode);
d62a17ae 14476 } else
14477 vty_out(vty,
14478 "%% Inbound soft reconfiguration not enabled\n");
14479
14480 return CMD_WARNING;
14481 }
0b16f239 14482
d9478df0
TA
14483 bgp = peer->bgp;
14484
14485 /* labeled-unicast routes live in the unicast table */
14486 if (safi == SAFI_LABELED_UNICAST)
14487 table = bgp->rib[afi][SAFI_UNICAST];
14488 else
14489 table = bgp->rib[afi][safi];
14490
14491 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14492 || (safi == SAFI_EVPN)) {
14493
14494 struct bgp_dest *dest;
14495
14496 for (dest = bgp_table_top(table); dest;
14497 dest = bgp_route_next(dest)) {
14498 table = bgp_dest_get_bgp_table_info(dest);
14499 if (!table)
14500 continue;
14501
14502 output_count_per_rd = 0;
14503 filtered_count_per_rd = 0;
14504
14505 if (use_json)
14506 json_routes = json_object_new_object();
14507
14508 const struct prefix_rd *prd;
14509 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14510 dest);
14511
4a8cd6ad
PG
14512 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14513 bgp->asnotation);
d9478df0 14514
3880b4ec
TA
14515 show_adj_route(
14516 vty, peer, table, afi, safi, type, rmap_name,
14517 json, json_routes, json_scode, json_ocode,
14518 show_flags, &header1, &header2, rd_str, match,
14519 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14520
14521 /* Don't include an empty RD in the output! */
14522 if (json_routes && (output_count_per_rd > 0))
14523 json_object_object_add(json_ar, rd_str,
14524 json_routes);
14525
14526 output_count += output_count_per_rd;
14527 filtered_count += filtered_count_per_rd;
14528 }
14529 } else
14530 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14531 json, json_ar, json_scode, json_ocode,
3880b4ec 14532 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14533 &output_count, &filtered_count);
14534
14535 if (use_json) {
c1984955
TA
14536 if (type == bgp_show_adj_route_advertised)
14537 json_object_object_add(json, "advertisedRoutes",
14538 json_ar);
14539 else
14540 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14541 json_object_int_add(json, "totalPrefixCounter", output_count);
14542 json_object_int_add(json, "filteredPrefixCounter",
14543 filtered_count);
14544
690c3134
MW
14545 /*
14546 * These fields only give up ownership to `json` when `header1`
14547 * is used (set to zero). See code in `show_adj_route` and
14548 * `show_adj_route_header`.
14549 */
14550 if (header1 == 1) {
d9478df0
TA
14551 json_object_free(json_scode);
14552 json_object_free(json_ocode);
14553 }
14554
75eeda93 14555 vty_json(vty, json);
d9478df0 14556 } else if (output_count > 0) {
3880b4ec 14557 if (!match && filtered_count > 0)
d9478df0
TA
14558 vty_out(vty,
14559 "\nTotal number of prefixes %ld (%ld filtered)\n",
14560 output_count, filtered_count);
14561 else
14562 vty_out(vty, "\nTotal number of prefixes %ld\n",
14563 output_count);
14564 }
0b16f239 14565
d62a17ae 14566 return CMD_SUCCESS;
a636c635 14567}
50ef26d4 14568
f20ce998
DS
14569DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14570 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14571 "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
14572 SHOW_STR
14573 IP_STR
14574 BGP_STR
14575 BGP_INSTANCE_HELP_STR
14576 BGP_AFI_HELP_STR
14577 BGP_SAFI_WITH_LABEL_HELP_STR
14578 "Detailed information on TCP and BGP neighbor connections\n"
14579 "Neighbor to display information about\n"
14580 "Neighbor to display information about\n"
14581 "Neighbor on BGP configured interface\n"
14582 "Display the routes selected by best path\n"
aa9bf57e 14583 "Display detailed version of routes\n"
f20ce998
DS
14584 JSON_STR
14585 "Increase table width for longer prefixes\n")
14586{
14587 afi_t afi = AFI_IP6;
14588 safi_t safi = SAFI_UNICAST;
14589 char *rmap_name = NULL;
14590 char *peerstr = NULL;
14591 struct bgp *bgp = NULL;
14592 struct peer *peer;
14593 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14594 int idx = 0;
96c81f66 14595 uint16_t show_flags = 0;
96f3485c 14596
aa9bf57e
TA
14597 if (detail)
14598 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14599
96f3485c
MK
14600 if (uj)
14601 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14602
14603 if (wide)
14604 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14605
14606 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14607 &bgp, uj);
14608
14609 if (!idx)
14610 return CMD_WARNING;
14611
14612 argv_find(argv, argc, "neighbors", &idx);
14613 peerstr = argv[++idx]->arg;
14614
14615 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14616 if (!peer)
14617 return CMD_WARNING;
14618
3880b4ec 14619 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14620 show_flags);
f20ce998
DS
14621}
14622
e960b4ca
TA
14623DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14624 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14625 "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
14626 SHOW_STR
14627 IP_STR
14628 BGP_STR
14629 BGP_INSTANCE_HELP_STR
14630 BGP_AFI_HELP_STR
14631 BGP_SAFI_WITH_LABEL_HELP_STR
14632 "Display the entries for all address families\n"
14633 "Detailed information on TCP and BGP neighbor connections\n"
14634 "Neighbor to display information about\n"
14635 "Neighbor to display information about\n"
14636 "Neighbor on BGP configured interface\n"
14637 "Display the routes advertised to a BGP neighbor\n"
14638 "Display the received routes from neighbor\n"
14639 "Display the filtered routes received from neighbor\n"
14640 "Route-map to modify the attributes\n"
14641 "Name of the route map\n"
3880b4ec
TA
14642 "IPv4 prefix\n"
14643 "IPv6 prefix\n"
e960b4ca
TA
14644 "Display detailed version of routes\n"
14645 JSON_STR
14646 "Increase table width for longer prefixes\n")
718e3744 14647{
d62a17ae 14648 afi_t afi = AFI_IP6;
14649 safi_t safi = SAFI_UNICAST;
d62a17ae 14650 char *peerstr = NULL;
d62a17ae 14651 struct bgp *bgp = NULL;
14652 struct peer *peer;
6392aaa6 14653 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14654 int idx = 0;
96f3485c 14655 bool first = true;
96c81f66 14656 uint16_t show_flags = 0;
75ce3b14
DA
14657 struct listnode *node;
14658 struct bgp *abgp;
6392aaa6 14659
3880b4ec 14660 if (detail || prefix_str)
e960b4ca
TA
14661 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14662
96f3485c 14663 if (uj) {
d62a17ae 14664 argc--;
96f3485c
MK
14665 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14666 }
14667
14668 if (all) {
14669 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14670 if (argv_find(argv, argc, "ipv4", &idx))
14671 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14672
14673 if (argv_find(argv, argc, "ipv6", &idx))
14674 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14675 }
14676
14677 if (wide)
14678 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14679
9f049418
DS
14680 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14681 &bgp, uj);
14682 if (!idx)
14683 return CMD_WARNING;
14684
d62a17ae 14685 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14686 argv_find(argv, argc, "neighbors", &idx);
14687 peerstr = argv[++idx]->arg;
8c3deaae 14688
d62a17ae 14689 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14690 if (!peer)
14691 return CMD_WARNING;
856ca177 14692
d62a17ae 14693 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14694 type = bgp_show_adj_route_advertised;
14695 else if (argv_find(argv, argc, "received-routes", &idx))
14696 type = bgp_show_adj_route_received;
14697 else if (argv_find(argv, argc, "filtered-routes", &idx))
14698 type = bgp_show_adj_route_filtered;
14699
96f3485c 14700 if (!all)
70dd370f 14701 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14702 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14703 if (uj)
14704 vty_out(vty, "{\n");
14705
14706 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14707 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14708 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14709 : AFI_IP6;
75ce3b14
DA
14710 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14711 FOREACH_SAFI (safi) {
14712 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14713 continue;
96f3485c 14714
75ce3b14
DA
14715 if (uj) {
14716 if (first)
14717 first = false;
14718 else
14719 vty_out(vty, ",\n");
14720 vty_out(vty, "\"%s\":",
14721 get_afi_safi_str(afi, safi,
14722 true));
14723 } else
14724 vty_out(vty,
14725 "\nFor address family: %s\n",
14726 get_afi_safi_str(afi, safi,
14727 false));
96f3485c 14728
75ce3b14 14729 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14730 route_map, prefix, show_flags);
75ce3b14 14731 }
96f3485c
MK
14732 }
14733 } else {
75ce3b14
DA
14734 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14735 FOREACH_AFI_SAFI (afi, safi) {
14736 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14737 continue;
96f3485c 14738
75ce3b14
DA
14739 if (uj) {
14740 if (first)
14741 first = false;
14742 else
14743 vty_out(vty, ",\n");
14744 vty_out(vty, "\"%s\":",
14745 get_afi_safi_str(afi, safi,
14746 true));
14747 } else
14748 vty_out(vty,
14749 "\nFor address family: %s\n",
14750 get_afi_safi_str(afi, safi,
14751 false));
96f3485c 14752
75ce3b14 14753 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14754 route_map, prefix, show_flags);
75ce3b14 14755 }
96f3485c
MK
14756 }
14757 }
14758 if (uj)
14759 vty_out(vty, "}\n");
14760
14761 return CMD_SUCCESS;
95cbbd2a
ML
14762}
14763
718e3744 14764DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14765 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14766 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14767 SHOW_STR
14768 IP_STR
14769 BGP_STR
d3120452 14770 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14771 BGP_AF_STR
14772 BGP_AF_STR
14773 BGP_AF_MODIFIER_STR
718e3744 14774 "Detailed information on TCP and BGP neighbor connections\n"
14775 "Neighbor to display information about\n"
14776 "Neighbor to display information about\n"
91d37724 14777 "Neighbor on BGP configured interface\n"
718e3744 14778 "Display information received from a BGP neighbor\n"
856ca177 14779 "Display the prefixlist filter\n"
9973d184 14780 JSON_STR)
718e3744 14781{
d62a17ae 14782 afi_t afi = AFI_IP6;
14783 safi_t safi = SAFI_UNICAST;
14784 char *peerstr = NULL;
d62a17ae 14785 char name[BUFSIZ];
d62a17ae 14786 struct peer *peer;
d3120452 14787 int count;
d62a17ae 14788 int idx = 0;
d3120452
IR
14789 struct bgp *bgp = NULL;
14790 bool uj = use_json(argc, argv);
14791
14792 if (uj)
14793 argc--;
14794
14795 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14796 &bgp, uj);
14797 if (!idx)
14798 return CMD_WARNING;
d62a17ae 14799
d62a17ae 14800 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14801 argv_find(argv, argc, "neighbors", &idx);
14802 peerstr = argv[++idx]->arg;
14803
d3120452
IR
14804 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14805 if (!peer)
14806 return CMD_WARNING;
718e3744 14807
4ced1a2c 14808 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14809 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14810 if (count) {
14811 if (!uj)
14812 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14813 get_afi_safi_str(afi, safi, false));
d62a17ae 14814 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14815 } else {
14816 if (uj)
14817 vty_out(vty, "{}\n");
14818 else
14819 vty_out(vty, "No functional output\n");
14820 }
718e3744 14821
d62a17ae 14822 return CMD_SUCCESS;
14823}
14824
14825static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14826 afi_t afi, safi_t safi,
9f049418 14827 enum bgp_show_type type, bool use_json)
d62a17ae 14828{
96c81f66 14829 uint16_t show_flags = 0;
96f3485c
MK
14830
14831 if (use_json)
14832 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14833
d62a17ae 14834 if (!peer || !peer->afc[afi][safi]) {
14835 if (use_json) {
14836 json_object *json_no = NULL;
14837 json_no = json_object_new_object();
14838 json_object_string_add(
14839 json_no, "warning",
14840 "No such neighbor or address family");
14841 vty_out(vty, "%s\n",
14842 json_object_to_json_string(json_no));
14843 json_object_free(json_no);
14844 } else
14845 vty_out(vty, "%% No such neighbor or address family\n");
14846 return CMD_WARNING;
14847 }
47fc97cc 14848
7daf25a3
TA
14849 /* labeled-unicast routes live in the unicast table */
14850 if (safi == SAFI_LABELED_UNICAST)
14851 safi = SAFI_UNICAST;
14852
1e2ce4f1
DS
14853 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14854 RPKI_NOT_BEING_USED);
718e3744 14855}
14856
dba3c1d3
PG
14857DEFUN (show_ip_bgp_flowspec_routes_detailed,
14858 show_ip_bgp_flowspec_routes_detailed_cmd,
14859 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14860 SHOW_STR
14861 IP_STR
14862 BGP_STR
14863 BGP_INSTANCE_HELP_STR
14864 BGP_AFI_HELP_STR
14865 "SAFI Flowspec\n"
14866 "Detailed information on flowspec entries\n"
14867 JSON_STR)
14868{
458c1475 14869 afi_t afi = AFI_IP6;
dba3c1d3
PG
14870 safi_t safi = SAFI_UNICAST;
14871 struct bgp *bgp = NULL;
14872 int idx = 0;
9f049418 14873 bool uj = use_json(argc, argv);
81dcd881 14874 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14875
96f3485c 14876 if (uj) {
9f049418 14877 argc--;
96f3485c
MK
14878 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14879 }
dba3c1d3
PG
14880
14881 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14882 &bgp, uj);
dba3c1d3
PG
14883 if (!idx)
14884 return CMD_WARNING;
14885
96f3485c 14886 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14887 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14888}
14889
718e3744 14890DEFUN (show_ip_bgp_neighbor_routes,
14891 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14892 "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 14893 SHOW_STR
14894 IP_STR
14895 BGP_STR
8386ac43 14896 BGP_INSTANCE_HELP_STR
4f280b15 14897 BGP_AFI_HELP_STR
4dd6177e 14898 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14899 "Detailed information on TCP and BGP neighbor connections\n"
14900 "Neighbor to display information about\n"
14901 "Neighbor to display information about\n"
91d37724 14902 "Neighbor on BGP configured interface\n"
2525cf39 14903 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14904 "Display the dampened routes received from neighbor\n"
14905 "Display routes learned from neighbor\n"
9973d184 14906 JSON_STR)
718e3744 14907{
d62a17ae 14908 char *peerstr = NULL;
14909 struct bgp *bgp = NULL;
14910 afi_t afi = AFI_IP6;
14911 safi_t safi = SAFI_UNICAST;
14912 struct peer *peer;
14913 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14914 int idx = 0;
9f049418
DS
14915 bool uj = use_json(argc, argv);
14916
14917 if (uj)
14918 argc--;
bb46e94f 14919
d62a17ae 14920 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14921 &bgp, uj);
d62a17ae 14922 if (!idx)
14923 return CMD_WARNING;
c493f2d8 14924
d62a17ae 14925 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14926 argv_find(argv, argc, "neighbors", &idx);
14927 peerstr = argv[++idx]->arg;
8c3deaae 14928
d62a17ae 14929 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14930 if (!peer)
d62a17ae 14931 return CMD_WARNING;
bb46e94f 14932
d62a17ae 14933 if (argv_find(argv, argc, "flap-statistics", &idx))
14934 sh_type = bgp_show_type_flap_neighbor;
14935 else if (argv_find(argv, argc, "dampened-routes", &idx))
14936 sh_type = bgp_show_type_damp_neighbor;
14937 else if (argv_find(argv, argc, "routes", &idx))
14938 sh_type = bgp_show_type_neighbor;
2525cf39 14939
d62a17ae 14940 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14941}
6b0655a2 14942
734b349e 14943struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14944
d62a17ae 14945struct bgp_distance {
14946 /* Distance value for the IP source prefix. */
d7c0a89a 14947 uint8_t distance;
718e3744 14948
d62a17ae 14949 /* Name of the access-list to be matched. */
14950 char *access_list;
718e3744 14951};
14952
4f280b15
LB
14953DEFUN (show_bgp_afi_vpn_rd_route,
14954 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14955 "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
14956 SHOW_STR
14957 BGP_STR
14958 BGP_AFI_HELP_STR
00e6edb9 14959 BGP_AF_MODIFIER_STR
4f280b15
LB
14960 "Display information for a route distinguisher\n"
14961 "Route Distinguisher\n"
a111dd97 14962 "All Route Distinguishers\n"
7395a2c9
DS
14963 "Network in the BGP routing table to display\n"
14964 "Network in the BGP routing table to display\n"
14965 JSON_STR)
4f280b15 14966{
d62a17ae 14967 int ret;
14968 struct prefix_rd prd;
14969 afi_t afi = AFI_MAX;
14970 int idx = 0;
4f280b15 14971
ff6566f3
DS
14972 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14973 vty_out(vty, "%% Malformed Address Family\n");
14974 return CMD_WARNING;
14975 }
14976
a111dd97
TA
14977 if (!strcmp(argv[5]->arg, "all"))
14978 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14979 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14980 RPKI_NOT_BEING_USED,
14981 use_json(argc, argv));
14982
d62a17ae 14983 ret = str2prefix_rd(argv[5]->arg, &prd);
14984 if (!ret) {
14985 vty_out(vty, "%% Malformed Route Distinguisher\n");
14986 return CMD_WARNING;
14987 }
ff6566f3 14988
d62a17ae 14989 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14990 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14991 use_json(argc, argv));
4f280b15
LB
14992}
14993
d62a17ae 14994static struct bgp_distance *bgp_distance_new(void)
718e3744 14995{
d62a17ae 14996 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14997}
14998
d62a17ae 14999static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15000{
d62a17ae 15001 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15002}
15003
585f1adc
IR
15004static int bgp_distance_set(struct vty *vty, const char *distance_str,
15005 const char *ip_str, const char *access_list_str)
718e3744 15006{
d62a17ae 15007 int ret;
585f1adc
IR
15008 afi_t afi;
15009 safi_t safi;
d62a17ae 15010 struct prefix p;
585f1adc 15011 uint8_t distance;
9bcb3eef 15012 struct bgp_dest *dest;
d62a17ae 15013 struct bgp_distance *bdistance;
718e3744 15014
585f1adc
IR
15015 afi = bgp_node_afi(vty);
15016 safi = bgp_node_safi(vty);
15017
d62a17ae 15018 ret = str2prefix(ip_str, &p);
15019 if (ret == 0) {
585f1adc 15020 vty_out(vty, "Malformed prefix\n");
d62a17ae 15021 return CMD_WARNING_CONFIG_FAILED;
15022 }
718e3744 15023
585f1adc
IR
15024 distance = atoi(distance_str);
15025
d62a17ae 15026 /* Get BGP distance node. */
9bcb3eef
DS
15027 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15028 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15029 if (bdistance)
9bcb3eef 15030 bgp_dest_unlock_node(dest);
ca2e160d 15031 else {
d62a17ae 15032 bdistance = bgp_distance_new();
9bcb3eef 15033 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15034 }
718e3744 15035
d62a17ae 15036 /* Set distance value. */
15037 bdistance->distance = distance;
718e3744 15038
d62a17ae 15039 /* Reset access-list configuration. */
e1b36e13 15040 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15041 if (access_list_str)
15042 bdistance->access_list =
15043 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15044
d62a17ae 15045 return CMD_SUCCESS;
718e3744 15046}
15047
585f1adc
IR
15048static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15049 const char *ip_str, const char *access_list_str)
718e3744 15050{
d62a17ae 15051 int ret;
585f1adc
IR
15052 afi_t afi;
15053 safi_t safi;
d62a17ae 15054 struct prefix p;
585f1adc 15055 int distance;
9bcb3eef 15056 struct bgp_dest *dest;
d62a17ae 15057 struct bgp_distance *bdistance;
718e3744 15058
585f1adc
IR
15059 afi = bgp_node_afi(vty);
15060 safi = bgp_node_safi(vty);
15061
d62a17ae 15062 ret = str2prefix(ip_str, &p);
15063 if (ret == 0) {
585f1adc 15064 vty_out(vty, "Malformed prefix\n");
d62a17ae 15065 return CMD_WARNING_CONFIG_FAILED;
15066 }
718e3744 15067
9bcb3eef
DS
15068 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15069 if (!dest) {
585f1adc 15070 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15071 return CMD_WARNING_CONFIG_FAILED;
15072 }
718e3744 15073
9bcb3eef 15074 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15075 distance = atoi(distance_str);
1f9a9fff 15076
d62a17ae 15077 if (bdistance->distance != distance) {
585f1adc 15078 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15079 bgp_dest_unlock_node(dest);
d62a17ae 15080 return CMD_WARNING_CONFIG_FAILED;
15081 }
718e3744 15082
0a22ddfb 15083 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15084 bgp_distance_free(bdistance);
718e3744 15085
9bcb3eef
DS
15086 bgp_dest_set_bgp_path_info(dest, NULL);
15087 bgp_dest_unlock_node(dest);
15088 bgp_dest_unlock_node(dest);
718e3744 15089
d62a17ae 15090 return CMD_SUCCESS;
718e3744 15091}
15092
718e3744 15093/* Apply BGP information to distance method. */
b8685f9b 15094uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15095 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15096{
9bcb3eef 15097 struct bgp_dest *dest;
801bb996 15098 struct prefix q = {0};
d62a17ae 15099 struct peer *peer;
15100 struct bgp_distance *bdistance;
15101 struct access_list *alist;
15102 struct bgp_static *bgp_static;
a04f1c42 15103 struct bgp_path_info *bpi_ultimate;
d62a17ae 15104
15105 if (!bgp)
15106 return 0;
15107
40381db7 15108 peer = pinfo->peer;
d62a17ae 15109
7b7d48e5
DS
15110 if (pinfo->attr->distance)
15111 return pinfo->attr->distance;
15112
a04f1c42
PG
15113 /* get peer origin to calculate appropriate distance */
15114 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15115 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15116 peer = bpi_ultimate->peer;
15117 }
15118
801bb996
CS
15119 /* Check source address.
15120 * Note: for aggregate route, peer can have unspec af type.
15121 */
15122 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15123 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15124 return 0;
15125
9bcb3eef
DS
15126 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15127 if (dest) {
15128 bdistance = bgp_dest_get_bgp_distance_info(dest);
15129 bgp_dest_unlock_node(dest);
d62a17ae 15130
15131 if (bdistance->access_list) {
15132 alist = access_list_lookup(afi, bdistance->access_list);
15133 if (alist
15134 && access_list_apply(alist, p) == FILTER_PERMIT)
15135 return bdistance->distance;
15136 } else
15137 return bdistance->distance;
718e3744 15138 }
718e3744 15139
d62a17ae 15140 /* Backdoor check. */
9bcb3eef
DS
15141 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15142 if (dest) {
15143 bgp_static = bgp_dest_get_bgp_static_info(dest);
15144 bgp_dest_unlock_node(dest);
718e3744 15145
d62a17ae 15146 if (bgp_static->backdoor) {
15147 if (bgp->distance_local[afi][safi])
15148 return bgp->distance_local[afi][safi];
15149 else
15150 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15151 }
718e3744 15152 }
718e3744 15153
d62a17ae 15154 if (peer->sort == BGP_PEER_EBGP) {
15155 if (bgp->distance_ebgp[afi][safi])
15156 return bgp->distance_ebgp[afi][safi];
15157 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15158 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15159 if (bgp->distance_ibgp[afi][safi])
15160 return bgp->distance_ibgp[afi][safi];
15161 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15162 } else {
15163 if (bgp->distance_local[afi][safi])
15164 return bgp->distance_local[afi][safi];
15165 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15166 }
718e3744 15167}
15168
a612fb77
DA
15169/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15170 * we should tell ZEBRA update the routes for a specific
15171 * AFI/SAFI to reflect changes in RIB.
15172 */
585f1adc
IR
15173static void bgp_announce_routes_distance_update(struct bgp *bgp,
15174 afi_t update_afi,
15175 safi_t update_safi)
a612fb77
DA
15176{
15177 afi_t afi;
15178 safi_t safi;
15179
15180 FOREACH_AFI_SAFI (afi, safi) {
15181 if (!bgp_fibupd_safi(safi))
15182 continue;
15183
8b54bc30
DA
15184 if (afi != update_afi && safi != update_safi)
15185 continue;
15186
15187 if (BGP_DEBUG(zebra, ZEBRA))
15188 zlog_debug(
15189 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15190 __func__, afi, safi);
15191 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15192 }
15193}
15194
585f1adc
IR
15195DEFUN (bgp_distance,
15196 bgp_distance_cmd,
15197 "distance bgp (1-255) (1-255) (1-255)",
15198 "Define an administrative distance\n"
15199 "BGP distance\n"
15200 "Distance for routes external to the AS\n"
15201 "Distance for routes internal to the AS\n"
15202 "Distance for local routes\n")
718e3744 15203{
585f1adc 15204 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15205 int idx_number = 2;
15206 int idx_number_2 = 3;
15207 int idx_number_3 = 4;
585f1adc
IR
15208 int distance_ebgp = atoi(argv[idx_number]->arg);
15209 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15210 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15211 afi_t afi;
15212 safi_t safi;
718e3744 15213
d62a17ae 15214 afi = bgp_node_afi(vty);
15215 safi = bgp_node_safi(vty);
718e3744 15216
585f1adc
IR
15217 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15218 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15219 || bgp->distance_local[afi][safi] != distance_local) {
15220 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15221 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15222 bgp->distance_local[afi][safi] = distance_local;
15223 bgp_announce_routes_distance_update(bgp, afi, safi);
15224 }
15225 return CMD_SUCCESS;
15226}
37a87b8f 15227
585f1adc
IR
15228DEFUN (no_bgp_distance,
15229 no_bgp_distance_cmd,
15230 "no distance bgp [(1-255) (1-255) (1-255)]",
15231 NO_STR
15232 "Define an administrative distance\n"
15233 "BGP distance\n"
15234 "Distance for routes external to the AS\n"
15235 "Distance for routes internal to the AS\n"
15236 "Distance for local routes\n")
718e3744 15237{
585f1adc 15238 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15239 afi_t afi;
15240 safi_t safi;
37a87b8f
CS
15241
15242 afi = bgp_node_afi(vty);
15243 safi = bgp_node_safi(vty);
15244
585f1adc
IR
15245 if (bgp->distance_ebgp[afi][safi] != 0
15246 || bgp->distance_ibgp[afi][safi] != 0
15247 || bgp->distance_local[afi][safi] != 0) {
15248 bgp->distance_ebgp[afi][safi] = 0;
15249 bgp->distance_ibgp[afi][safi] = 0;
15250 bgp->distance_local[afi][safi] = 0;
15251 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15252 }
585f1adc
IR
15253 return CMD_SUCCESS;
15254}
37a87b8f 15255
37a87b8f 15256
585f1adc
IR
15257DEFUN (bgp_distance_source,
15258 bgp_distance_source_cmd,
15259 "distance (1-255) A.B.C.D/M",
15260 "Define an administrative distance\n"
15261 "Administrative distance\n"
15262 "IP source prefix\n")
15263{
15264 int idx_number = 1;
15265 int idx_ipv4_prefixlen = 2;
15266 bgp_distance_set(vty, argv[idx_number]->arg,
15267 argv[idx_ipv4_prefixlen]->arg, NULL);
15268 return CMD_SUCCESS;
734b349e
MZ
15269}
15270
585f1adc
IR
15271DEFUN (no_bgp_distance_source,
15272 no_bgp_distance_source_cmd,
15273 "no distance (1-255) A.B.C.D/M",
15274 NO_STR
15275 "Define an administrative distance\n"
15276 "Administrative distance\n"
15277 "IP source prefix\n")
37a87b8f 15278{
585f1adc
IR
15279 int idx_number = 2;
15280 int idx_ipv4_prefixlen = 3;
15281 bgp_distance_unset(vty, argv[idx_number]->arg,
15282 argv[idx_ipv4_prefixlen]->arg, NULL);
15283 return CMD_SUCCESS;
37a87b8f
CS
15284}
15285
585f1adc
IR
15286DEFUN (bgp_distance_source_access_list,
15287 bgp_distance_source_access_list_cmd,
15288 "distance (1-255) A.B.C.D/M WORD",
15289 "Define an administrative distance\n"
15290 "Administrative distance\n"
15291 "IP source prefix\n"
15292 "Access list name\n")
37a87b8f 15293{
585f1adc
IR
15294 int idx_number = 1;
15295 int idx_ipv4_prefixlen = 2;
15296 int idx_word = 3;
15297 bgp_distance_set(vty, argv[idx_number]->arg,
15298 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15299 return CMD_SUCCESS;
15300}
718e3744 15301
585f1adc
IR
15302DEFUN (no_bgp_distance_source_access_list,
15303 no_bgp_distance_source_access_list_cmd,
15304 "no distance (1-255) A.B.C.D/M WORD",
15305 NO_STR
15306 "Define an administrative distance\n"
15307 "Administrative distance\n"
15308 "IP source prefix\n"
15309 "Access list name\n")
15310{
15311 int idx_number = 2;
15312 int idx_ipv4_prefixlen = 3;
15313 int idx_word = 4;
15314 bgp_distance_unset(vty, argv[idx_number]->arg,
15315 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15316 return CMD_SUCCESS;
15317}
37a87b8f 15318
585f1adc
IR
15319DEFUN (ipv6_bgp_distance_source,
15320 ipv6_bgp_distance_source_cmd,
15321 "distance (1-255) X:X::X:X/M",
15322 "Define an administrative distance\n"
15323 "Administrative distance\n"
15324 "IP source prefix\n")
15325{
15326 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15327 return CMD_SUCCESS;
15328}
7ebe9748 15329
585f1adc
IR
15330DEFUN (no_ipv6_bgp_distance_source,
15331 no_ipv6_bgp_distance_source_cmd,
15332 "no distance (1-255) X:X::X:X/M",
15333 NO_STR
15334 "Define an administrative distance\n"
15335 "Administrative distance\n"
15336 "IP source prefix\n")
15337{
15338 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15339 return CMD_SUCCESS;
15340}
37a87b8f 15341
585f1adc
IR
15342DEFUN (ipv6_bgp_distance_source_access_list,
15343 ipv6_bgp_distance_source_access_list_cmd,
15344 "distance (1-255) X:X::X:X/M WORD",
15345 "Define an administrative distance\n"
15346 "Administrative distance\n"
15347 "IP source prefix\n"
15348 "Access list name\n")
15349{
15350 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15351 return CMD_SUCCESS;
718e3744 15352}
15353
585f1adc
IR
15354DEFUN (no_ipv6_bgp_distance_source_access_list,
15355 no_ipv6_bgp_distance_source_access_list_cmd,
15356 "no distance (1-255) X:X::X:X/M WORD",
15357 NO_STR
15358 "Define an administrative distance\n"
15359 "Administrative distance\n"
15360 "IP source prefix\n"
15361 "Access list name\n")
718e3744 15362{
585f1adc
IR
15363 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15364 return CMD_SUCCESS;
15365}
37a87b8f 15366
585f1adc
IR
15367DEFUN (bgp_damp_set,
15368 bgp_damp_set_cmd,
a30fec23 15369 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15370 "BGP Specific commands\n"
15371 "Enable route-flap dampening\n"
15372 "Half-life time for the penalty\n"
15373 "Value to start reusing a route\n"
15374 "Value to start suppressing a route\n"
15375 "Maximum duration to suppress a stable route\n")
15376{
15377 VTY_DECLVAR_CONTEXT(bgp, bgp);
15378 int idx_half_life = 2;
15379 int idx_reuse = 3;
15380 int idx_suppress = 4;
15381 int idx_max_suppress = 5;
37a87b8f
CS
15382 int half = DEFAULT_HALF_LIFE * 60;
15383 int reuse = DEFAULT_REUSE;
15384 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15385 int max = 4 * half;
15386
15387 if (argc == 6) {
15388 half = atoi(argv[idx_half_life]->arg) * 60;
15389 reuse = atoi(argv[idx_reuse]->arg);
15390 suppress = atoi(argv[idx_suppress]->arg);
15391 max = atoi(argv[idx_max_suppress]->arg) * 60;
15392 } else if (argc == 3) {
15393 half = atoi(argv[idx_half_life]->arg) * 60;
15394 max = 4 * half;
15395 }
15396
15397 /*
15398 * These can't be 0 but our SA doesn't understand the
15399 * way our cli is constructed
15400 */
15401 assert(reuse);
15402 assert(half);
15403 if (suppress < reuse) {
15404 vty_out(vty,
15405 "Suppress value cannot be less than reuse value \n");
15406 return 0;
15407 }
15408
15409 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15410 reuse, suppress, max);
15411}
15412
15413DEFUN (bgp_damp_unset,
15414 bgp_damp_unset_cmd,
a30fec23 15415 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15416 NO_STR
15417 "BGP Specific commands\n"
15418 "Enable route-flap dampening\n"
15419 "Half-life time for the penalty\n"
15420 "Value to start reusing a route\n"
15421 "Value to start suppressing a route\n"
15422 "Maximum duration to suppress a stable route\n")
15423{
15424 VTY_DECLVAR_CONTEXT(bgp, bgp);
15425 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15426}
15427
718e3744 15428/* Display specified route of BGP table. */
d62a17ae 15429static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15430 const char *ip_str, afi_t afi, safi_t safi,
15431 struct prefix_rd *prd, int prefix_check)
15432{
15433 int ret;
15434 struct prefix match;
9bcb3eef
DS
15435 struct bgp_dest *dest;
15436 struct bgp_dest *rm;
40381db7
DS
15437 struct bgp_path_info *pi;
15438 struct bgp_path_info *pi_temp;
d62a17ae 15439 struct bgp *bgp;
15440 struct bgp_table *table;
15441
15442 /* BGP structure lookup. */
15443 if (view_name) {
15444 bgp = bgp_lookup_by_name(view_name);
15445 if (bgp == NULL) {
15446 vty_out(vty, "%% Can't find BGP instance %s\n",
15447 view_name);
15448 return CMD_WARNING;
15449 }
15450 } else {
15451 bgp = bgp_get_default();
15452 if (bgp == NULL) {
15453 vty_out(vty, "%% No BGP process is configured\n");
15454 return CMD_WARNING;
15455 }
718e3744 15456 }
718e3744 15457
d62a17ae 15458 /* Check IP address argument. */
15459 ret = str2prefix(ip_str, &match);
15460 if (!ret) {
15461 vty_out(vty, "%% address is malformed\n");
15462 return CMD_WARNING;
15463 }
718e3744 15464
d62a17ae 15465 match.family = afi2family(afi);
15466
15467 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15468 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15469 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15470 dest = bgp_route_next(dest)) {
15471 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15472
9bcb3eef 15473 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15474 continue;
9bcb3eef 15475 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15476 if (!table)
ea47320b 15477 continue;
4953391b
DA
15478 rm = bgp_node_match(table, &match);
15479 if (rm == NULL)
ea47320b 15480 continue;
d62a17ae 15481
9bcb3eef 15482 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15483
ea47320b 15484 if (!prefix_check
b54892e0 15485 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15486 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15487 while (pi) {
15488 if (pi->extra && pi->extra->damp_info) {
15489 pi_temp = pi->next;
ea47320b 15490 bgp_damp_info_free(
19971c9a 15491 pi->extra->damp_info,
5c8846f6 15492 1, afi, safi);
40381db7 15493 pi = pi_temp;
ea47320b 15494 } else
40381db7 15495 pi = pi->next;
d62a17ae 15496 }
ea47320b
DL
15497 }
15498
9bcb3eef 15499 bgp_dest_unlock_node(rm);
d62a17ae 15500 }
15501 } else {
4953391b
DA
15502 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15503 if (dest != NULL) {
9bcb3eef 15504 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15505
d62a17ae 15506 if (!prefix_check
9bcb3eef
DS
15507 || dest_p->prefixlen == match.prefixlen) {
15508 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15509 while (pi) {
15510 if (pi->extra && pi->extra->damp_info) {
15511 pi_temp = pi->next;
d62a17ae 15512 bgp_damp_info_free(
19971c9a 15513 pi->extra->damp_info,
5c8846f6 15514 1, afi, safi);
40381db7 15515 pi = pi_temp;
d62a17ae 15516 } else
40381db7 15517 pi = pi->next;
d62a17ae 15518 }
15519 }
15520
9bcb3eef 15521 bgp_dest_unlock_node(dest);
d62a17ae 15522 }
15523 }
718e3744 15524
d62a17ae 15525 return CMD_SUCCESS;
718e3744 15526}
15527
15528DEFUN (clear_ip_bgp_dampening,
15529 clear_ip_bgp_dampening_cmd,
15530 "clear ip bgp dampening",
15531 CLEAR_STR
15532 IP_STR
15533 BGP_STR
15534 "Clear route flap dampening information\n")
15535{
b4f7f45b 15536 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15537 return CMD_SUCCESS;
718e3744 15538}
15539
15540DEFUN (clear_ip_bgp_dampening_prefix,
15541 clear_ip_bgp_dampening_prefix_cmd,
15542 "clear ip bgp dampening A.B.C.D/M",
15543 CLEAR_STR
15544 IP_STR
15545 BGP_STR
15546 "Clear route flap dampening information\n"
0c7b1b01 15547 "IPv4 prefix\n")
718e3744 15548{
d62a17ae 15549 int idx_ipv4_prefixlen = 4;
15550 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15551 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15552}
15553
15554DEFUN (clear_ip_bgp_dampening_address,
15555 clear_ip_bgp_dampening_address_cmd,
15556 "clear ip bgp dampening A.B.C.D",
15557 CLEAR_STR
15558 IP_STR
15559 BGP_STR
15560 "Clear route flap dampening information\n"
15561 "Network to clear damping information\n")
15562{
d62a17ae 15563 int idx_ipv4 = 4;
15564 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15565 SAFI_UNICAST, NULL, 0);
718e3744 15566}
15567
15568DEFUN (clear_ip_bgp_dampening_address_mask,
15569 clear_ip_bgp_dampening_address_mask_cmd,
15570 "clear ip bgp dampening A.B.C.D A.B.C.D",
15571 CLEAR_STR
15572 IP_STR
15573 BGP_STR
15574 "Clear route flap dampening information\n"
15575 "Network to clear damping information\n"
15576 "Network mask\n")
15577{
d62a17ae 15578 int idx_ipv4 = 4;
15579 int idx_ipv4_2 = 5;
15580 int ret;
15581 char prefix_str[BUFSIZ];
718e3744 15582
d62a17ae 15583 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15584 prefix_str, sizeof(prefix_str));
d62a17ae 15585 if (!ret) {
15586 vty_out(vty, "%% Inconsistent address and mask\n");
15587 return CMD_WARNING;
15588 }
718e3744 15589
d62a17ae 15590 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15591 NULL, 0);
718e3744 15592}
6b0655a2 15593
e3b78da8 15594static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15595{
15596 struct vty *vty = arg;
e3b78da8 15597 struct peer *peer = bucket->data;
825d9834 15598
47e12884 15599 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15600}
15601
2a0e69ae
DS
15602DEFUN (show_bgp_listeners,
15603 show_bgp_listeners_cmd,
15604 "show bgp listeners",
15605 SHOW_STR
15606 BGP_STR
15607 "Display Listen Sockets and who created them\n")
15608{
15609 bgp_dump_listener_info(vty);
15610
15611 return CMD_SUCCESS;
15612}
15613
825d9834
DS
15614DEFUN (show_bgp_peerhash,
15615 show_bgp_peerhash_cmd,
15616 "show bgp peerhash",
15617 SHOW_STR
15618 BGP_STR
15619 "Display information about the BGP peerhash\n")
15620{
15621 struct list *instances = bm->bgp;
15622 struct listnode *node;
15623 struct bgp *bgp;
15624
15625 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15626 vty_out(vty, "BGP: %s\n", bgp->name);
15627 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15628 vty);
15629 }
15630
15631 return CMD_SUCCESS;
15632}
15633
587ff0fd 15634/* also used for encap safi */
2b791107
DL
15635static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15636 afi_t afi, safi_t safi)
d62a17ae 15637{
9bcb3eef
DS
15638 struct bgp_dest *pdest;
15639 struct bgp_dest *dest;
d62a17ae 15640 struct bgp_table *table;
b54892e0 15641 const struct prefix *p;
d62a17ae 15642 struct bgp_static *bgp_static;
15643 mpls_label_t label;
d62a17ae 15644
15645 /* Network configuration. */
9bcb3eef
DS
15646 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15647 pdest = bgp_route_next(pdest)) {
15648 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15649 if (!table)
ea47320b 15650 continue;
d62a17ae 15651
9bcb3eef
DS
15652 for (dest = bgp_table_top(table); dest;
15653 dest = bgp_route_next(dest)) {
15654 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15655 if (bgp_static == NULL)
ea47320b 15656 continue;
d62a17ae 15657
9bcb3eef 15658 p = bgp_dest_get_prefix(dest);
d62a17ae 15659
ea47320b 15660 /* "network" configuration display. */
ea47320b
DL
15661 label = decode_label(&bgp_static->label);
15662
c1aa9e7f
PG
15663 vty_out(vty, " network %pFX rd %s", p,
15664 bgp_static->prd_pretty);
ea47320b
DL
15665 if (safi == SAFI_MPLS_VPN)
15666 vty_out(vty, " label %u", label);
15667
15668 if (bgp_static->rmap.name)
15669 vty_out(vty, " route-map %s",
15670 bgp_static->rmap.name);
e2a86ad9
DS
15671
15672 if (bgp_static->backdoor)
15673 vty_out(vty, " backdoor");
15674
ea47320b
DL
15675 vty_out(vty, "\n");
15676 }
15677 }
d62a17ae 15678}
15679
2b791107
DL
15680static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15681 afi_t afi, safi_t safi)
d62a17ae 15682{
9bcb3eef
DS
15683 struct bgp_dest *pdest;
15684 struct bgp_dest *dest;
d62a17ae 15685 struct bgp_table *table;
b54892e0 15686 const struct prefix *p;
d62a17ae 15687 struct bgp_static *bgp_static;
ff44f570 15688 char buf[PREFIX_STRLEN * 2];
d62a17ae 15689 char buf2[SU_ADDRSTRLEN];
5f933e1e 15690 char esi_buf[ESI_STR_LEN];
d62a17ae 15691
15692 /* Network configuration. */
9bcb3eef
DS
15693 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15694 pdest = bgp_route_next(pdest)) {
15695 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15696 if (!table)
ea47320b 15697 continue;
d62a17ae 15698
9bcb3eef
DS
15699 for (dest = bgp_table_top(table); dest;
15700 dest = bgp_route_next(dest)) {
15701 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15702 if (bgp_static == NULL)
ea47320b 15703 continue;
d62a17ae 15704
ea47320b 15705 char *macrouter = NULL;
d62a17ae 15706
ea47320b
DL
15707 if (bgp_static->router_mac)
15708 macrouter = prefix_mac2str(
15709 bgp_static->router_mac, NULL, 0);
15710 if (bgp_static->eth_s_id)
0a50c248
AK
15711 esi_to_str(bgp_static->eth_s_id,
15712 esi_buf, sizeof(esi_buf));
9bcb3eef 15713 p = bgp_dest_get_prefix(dest);
d62a17ae 15714
ea47320b 15715 /* "network" configuration display. */
197cb530
PG
15716 if (p->u.prefix_evpn.route_type == 5) {
15717 char local_buf[PREFIX_STRLEN];
07380148 15718
3714a385 15719 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15720 struct prefix_evpn *)p)
15721 ? AF_INET
15722 : AF_INET6;
3714a385 15723 inet_ntop(family,
07380148
DA
15724 &p->u.prefix_evpn.prefix_addr.ip.ip
15725 .addr,
15726 local_buf, sizeof(local_buf));
772270f3
QY
15727 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15728 p->u.prefix_evpn.prefix_addr
15729 .ip_prefix_length);
197cb530
PG
15730 } else {
15731 prefix2str(p, buf, sizeof(buf));
15732 }
ea47320b 15733
a4d82a8a
PZ
15734 if (bgp_static->gatewayIp.family == AF_INET
15735 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15736 inet_ntop(bgp_static->gatewayIp.family,
15737 &bgp_static->gatewayIp.u.prefix, buf2,
15738 sizeof(buf2));
ea47320b 15739 vty_out(vty,
c1aa9e7f
PG
15740 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15741 buf, bgp_static->prd_pretty,
15742 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15743 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15744 macrouter);
15745
0a22ddfb 15746 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15747 }
15748 }
3da6fcd5
PG
15749}
15750
718e3744 15751/* Configuration of static route announcement and aggregate
15752 information. */
2b791107
DL
15753void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15754 safi_t safi)
d62a17ae 15755{
9bcb3eef 15756 struct bgp_dest *dest;
b54892e0 15757 const struct prefix *p;
d62a17ae 15758 struct bgp_static *bgp_static;
15759 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15760
2b791107
DL
15761 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15762 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15763 return;
15764 }
d62a17ae 15765
2b791107
DL
15766 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15767 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15768 return;
15769 }
d62a17ae 15770
15771 /* Network configuration. */
9bcb3eef
DS
15772 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15773 dest = bgp_route_next(dest)) {
15774 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15775 if (bgp_static == NULL)
ea47320b 15776 continue;
d62a17ae 15777
9bcb3eef 15778 p = bgp_dest_get_prefix(dest);
d62a17ae 15779
8228a9a7 15780 vty_out(vty, " network %pFX", p);
d62a17ae 15781
ea47320b
DL
15782 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15783 vty_out(vty, " label-index %u",
15784 bgp_static->label_index);
d62a17ae 15785
ea47320b
DL
15786 if (bgp_static->rmap.name)
15787 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15788
15789 if (bgp_static->backdoor)
15790 vty_out(vty, " backdoor");
718e3744 15791
ea47320b
DL
15792 vty_out(vty, "\n");
15793 }
15794
d62a17ae 15795 /* Aggregate-address configuration. */
9bcb3eef
DS
15796 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15797 dest = bgp_route_next(dest)) {
15798 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15799 if (bgp_aggregate == NULL)
ea47320b 15800 continue;
d62a17ae 15801
9bcb3eef 15802 p = bgp_dest_get_prefix(dest);
d62a17ae 15803
8228a9a7 15804 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15805
ea47320b
DL
15806 if (bgp_aggregate->as_set)
15807 vty_out(vty, " as-set");
d62a17ae 15808
ea47320b
DL
15809 if (bgp_aggregate->summary_only)
15810 vty_out(vty, " summary-only");
718e3744 15811
20894f50
DA
15812 if (bgp_aggregate->rmap.name)
15813 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15814
229757f1
DA
15815 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15816 vty_out(vty, " origin %s",
15817 bgp_origin2str(bgp_aggregate->origin));
15818
6aabb15d
RZ
15819 if (bgp_aggregate->match_med)
15820 vty_out(vty, " matching-MED-only");
15821
365ab2e7
RZ
15822 if (bgp_aggregate->suppress_map_name)
15823 vty_out(vty, " suppress-map %s",
15824 bgp_aggregate->suppress_map_name);
15825
ea47320b
DL
15826 vty_out(vty, "\n");
15827 }
d62a17ae 15828}
734b349e 15829
2b791107 15830void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15831 safi_t safi)
d62a17ae 15832{
9bcb3eef 15833 struct bgp_dest *dest;
d62a17ae 15834 struct bgp_distance *bdistance;
15835
15836 /* Distance configuration. */
15837 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15838 && bgp->distance_local[afi][safi]
15839 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15840 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15841 || bgp->distance_local[afi][safi]
15842 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15843 vty_out(vty, " distance bgp %d %d %d\n",
15844 bgp->distance_ebgp[afi][safi],
15845 bgp->distance_ibgp[afi][safi],
15846 bgp->distance_local[afi][safi]);
15847 }
734b349e 15848
9bcb3eef
DS
15849 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15850 dest = bgp_route_next(dest)) {
15851 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15852 if (bdistance != NULL)
56ca3b5b 15853 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15854 bdistance->distance, dest,
d62a17ae 15855 bdistance->access_list ? bdistance->access_list
15856 : "");
ca2e160d 15857 }
718e3744 15858}
15859
15860/* Allocate routing table structure and install commands. */
d62a17ae 15861void bgp_route_init(void)
15862{
15863 afi_t afi;
15864 safi_t safi;
15865
15866 /* Init BGP distance table. */
05c7a1cc 15867 FOREACH_AFI_SAFI (afi, safi)
960035b2 15868 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15869
15870 /* IPv4 BGP commands. */
15871 install_element(BGP_NODE, &bgp_table_map_cmd);
15872 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15873 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15874
554b3b10 15875 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15876
15877 /* IPv4 unicast configuration. */
15878 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15879 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15880 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15881
554b3b10 15882 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15883
15884 /* IPv4 multicast configuration. */
15885 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15886 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15887 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15888 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15889
15890 /* IPv4 labeled-unicast configuration. */
fb985e0c 15891 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15892 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15893
d62a17ae 15894 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15895 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15896 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15897 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15898 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15899 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15900 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15901 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15902
15903 install_element(VIEW_NODE,
15904 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15905 install_element(VIEW_NODE,
15906 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15907 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15908 install_element(VIEW_NODE,
15909 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15910#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15911 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15912#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15913 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15914 install_element(VIEW_NODE,
44c69747 15915 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15916
d62a17ae 15917 /* BGP dampening clear commands */
15918 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15919 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15920
d62a17ae 15921 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15922 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15923
15924 /* prefix count */
15925 install_element(ENABLE_NODE,
15926 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15927#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15928 install_element(ENABLE_NODE,
15929 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15930#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15931
d62a17ae 15932 /* New config IPv6 BGP commands. */
15933 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15934 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15935 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15936
554b3b10 15937 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15938
15939 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15940
fb985e0c
DA
15941 /* IPv6 labeled unicast address family. */
15942 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15943 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15944
d62a17ae 15945 install_element(BGP_NODE, &bgp_distance_cmd);
15946 install_element(BGP_NODE, &no_bgp_distance_cmd);
15947 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15948 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15949 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15950 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15951 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15952 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15953 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15954 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15955 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15956 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15957 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15958 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15959 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15960 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15961 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15962 install_element(BGP_IPV4M_NODE,
15963 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15964 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15965 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15966 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15967 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15968 install_element(BGP_IPV6_NODE,
15969 &ipv6_bgp_distance_source_access_list_cmd);
15970 install_element(BGP_IPV6_NODE,
15971 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15972 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15973 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15974 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15975 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15976 install_element(BGP_IPV6M_NODE,
15977 &ipv6_bgp_distance_source_access_list_cmd);
15978 install_element(BGP_IPV6M_NODE,
15979 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15980
ef5f4b23 15981 /* BGP dampening */
585f1adc
IR
15982 install_element(BGP_NODE, &bgp_damp_set_cmd);
15983 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15984 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15985 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15986 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15987 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15988 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15989 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15990 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15991 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15992 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15993 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15994 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15995 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15996
15997 /* Large Communities */
15998 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15999 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
16000
16001 /* show bgp ipv4 flowspec detailed */
16002 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
16003
2a0e69ae 16004 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16005 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16006}
16007
16008void bgp_route_finish(void)
16009{
16010 afi_t afi;
16011 safi_t safi;
16012
05c7a1cc
QY
16013 FOREACH_AFI_SAFI (afi, safi) {
16014 bgp_table_unlock(bgp_distance_table[afi][safi]);
16015 bgp_distance_table[afi][safi] = NULL;
16016 }
228da428 16017}