]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #13349 from opensourcerouting/pim6-mld-coverity-20230421
[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 */
7ee70320
PG
3073static bool bgp_lu_need_null_label(struct bgp *bgp,
3074 const struct bgp_path_info *new_select,
3075 afi_t afi, mpls_label_t *label)
bb2ca692
MS
3076{
3077 /* Certain types get imp null; so do paths where the nexthop is
3078 * not labeled.
3079 */
3080 if (new_select->sub_type == BGP_ROUTE_STATIC
3081 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3082 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
f8141f4a 3083 goto need_null_label;
7ee70320
PG
3084 else if (new_select->extra &&
3085 bgp_is_valid_label(&new_select->extra->label[0]))
3086 return false;
f8141f4a 3087need_null_label:
7ee70320 3088 if (label == NULL)
bb2ca692 3089 return true;
7ee70320
PG
3090 if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
3091 /* Disable PHP : explicit-null */
3092 *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL
3093 : MPLS_LABEL_IPV6_EXPLICIT_NULL;
bb2ca692 3094 else
7ee70320
PG
3095 /* Enforced PHP popping: implicit-null */
3096 *label = MPLS_LABEL_IMPLICIT_NULL;
3097
3098 return true;
bb2ca692
MS
3099}
3100
3103e8d2
DS
3101/*
3102 * old_select = The old best path
3103 * new_select = the new best path
3104 *
3105 * if (!old_select && new_select)
3106 * We are sending new information on.
3107 *
3108 * if (old_select && new_select) {
3109 * if (new_select != old_select)
3110 * We have a new best path send a change
3111 * else
3112 * We've received a update with new attributes that needs
3113 * to be passed on.
3114 * }
3115 *
3116 * if (old_select && !new_select)
3117 * We have no eligible route that we can announce or the rn
3118 * is being removed.
3119 */
9bcb3eef 3120static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3121 afi_t afi, safi_t safi)
d62a17ae 3122{
4b7e6066
DS
3123 struct bgp_path_info *new_select;
3124 struct bgp_path_info *old_select;
3125 struct bgp_path_info_pair old_and_new;
ddb5b488 3126 int debug = 0;
7ee70320 3127 mpls_label_t mpls_label_null;
d62a17ae 3128
892fedb6 3129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3130 if (dest)
3131 debug = bgp_debug_bestpath(dest);
b54892e0 3132 if (debug)
f4c713ae 3133 zlog_debug(
7fd8ca9a
DS
3134 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3135 __func__, dest, bgp->name_pretty);
f4c713ae
LB
3136 return;
3137 }
d62a17ae 3138 /* Is it end of initial update? (after startup) */
9bcb3eef 3139 if (!dest) {
e36f61b5
DS
3140 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3141 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3142
3143 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3144 FOREACH_AFI_SAFI (afi, safi) {
3145 if (bgp_fibupd_safi(safi))
3146 bgp_zebra_announce_table(bgp, afi, safi);
3147 }
d62a17ae 3148 bgp->main_peers_update_hold = 0;
3149
3150 bgp_start_routeadv(bgp);
aac24838 3151 return;
d62a17ae 3152 }
cb1faec9 3153
9bcb3eef 3154 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3155
9bcb3eef 3156 debug = bgp_debug_bestpath(dest);
b54892e0 3157 if (debug)
7fd8ca9a 3158 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
4378495a
DS
3159 dest, bgp->name_pretty, afi2str(afi),
3160 safi2str(safi));
ddb5b488 3161
f009ff26 3162 /* The best path calculation for the route is deferred if
3163 * BGP_NODE_SELECT_DEFER is set
3164 */
9bcb3eef 3165 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3166 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
3167 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3168 dest, bgp->name_pretty);
f009ff26 3169 return;
3170 }
3171
d62a17ae 3172 /* Best path selection. */
9bcb3eef 3173 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3174 afi, safi);
3175 old_select = old_and_new.old;
3176 new_select = old_and_new.new;
3177
3178 /* Do we need to allocate or free labels?
3179 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3180 * necessary to do this upon changes to best path. Exceptions:
3181 * - label index has changed -> recalculate resulting label
7ee70320 3182 * - path_info sub_type changed -> switch to/from null label value
57592a53 3183 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3184 */
318cac96 3185 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3186 if (new_select) {
3187 if (!old_select
3188 || bgp_label_index_differs(new_select, old_select)
57592a53 3189 || new_select->sub_type != old_select->sub_type
9bcb3eef 3190 || !bgp_is_valid_label(&dest->local_label)) {
7ee70320
PG
3191 /* control label imposition for local routes,
3192 * aggregate and redistributed routes
57592a53 3193 */
7ee70320
PG
3194 mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
3195 if (bgp_lu_need_null_label(bgp, new_select, afi,
3196 &mpls_label_null)) {
d62a17ae 3197 if (CHECK_FLAG(
9bcb3eef 3198 dest->flags,
992dd67e
PR
3199 BGP_NODE_REGISTERED_FOR_LABEL)
3200 || CHECK_FLAG(
3201 dest->flags,
3202 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3203 bgp_unregister_for_label(dest);
67f67ba4 3204 dest->local_label = mpls_lse_encode(
7ee70320 3205 mpls_label_null, 0, 0, 1);
9bcb3eef 3206 bgp_set_valid_label(&dest->local_label);
d62a17ae 3207 } else
9bcb3eef
DS
3208 bgp_register_for_label(dest,
3209 new_select);
d62a17ae 3210 }
9bcb3eef 3211 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3212 BGP_NODE_REGISTERED_FOR_LABEL)
3213 || CHECK_FLAG(dest->flags,
3214 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3215 bgp_unregister_for_label(dest);
318cac96 3216 }
992dd67e
PR
3217 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3218 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3219 bgp_unregister_for_label(dest);
d62a17ae 3220 }
cd1964ff 3221
b54892e0 3222 if (debug)
ddb5b488 3223 zlog_debug(
4378495a
DS
3224 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3225 __func__, dest, bgp->name_pretty, afi2str(afi),
3226 safi2str(safi), old_select, new_select);
ddb5b488 3227
d62a17ae 3228 /* If best route remains the same and this is not due to user-initiated
3229 * clear, see exactly what needs to be done.
3230 */
d62a17ae 3231 if (old_select && old_select == new_select
9bcb3eef 3232 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3233 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3234 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3235 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3236#ifdef ENABLE_BGP_VNC
d62a17ae 3237 vnc_import_bgp_add_route(bgp, p, old_select);
3238 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3239#endif
bb744275 3240 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3241 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3242
3243 if (new_select->type == ZEBRA_ROUTE_BGP
3244 && (new_select->sub_type == BGP_ROUTE_NORMAL
3245 || new_select->sub_type
3246 == BGP_ROUTE_IMPORTED))
3247
9bcb3eef 3248 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3249 bgp, afi, safi);
3250 }
d62a17ae 3251 }
d62a17ae 3252
3253 /* If there is a change of interest to peers, reannounce the
3254 * route. */
1defdda8 3255 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3256 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3257 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3258 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3259
3260 /* unicast routes must also be annouced to
3261 * labeled-unicast update-groups */
3262 if (safi == SAFI_UNICAST)
3263 group_announce_route(bgp, afi,
9bcb3eef 3264 SAFI_LABELED_UNICAST, dest,
d62a17ae 3265 new_select);
3266
1defdda8 3267 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3268 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3269 }
fee0f4c6 3270
3b0c17e1 3271 /* advertise/withdraw type-5 routes */
3272 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3273 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3274 bgp_process_evpn_route_injection(
9bcb3eef 3275 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3276
b1875e65 3277 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3278 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3279 bgp_zebra_clear_route_change_flags(dest);
3280 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3281 return;
d62a17ae 3282 }
8ad7271d 3283
d62a17ae 3284 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3285 */
9bcb3eef 3286 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3287
3288 /* bestpath has changed; bump version */
3289 if (old_select || new_select) {
9bcb3eef 3290 bgp_bump_version(dest);
d62a17ae 3291
3292 if (!bgp->t_rmap_def_originate_eval) {
3293 bgp_lock(bgp);
907a2395 3294 event_add_timer(
d62a17ae 3295 bm->master,
3296 update_group_refresh_default_originate_route_map,
3297 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3298 &bgp->t_rmap_def_originate_eval);
3299 }
3300 }
3f9c7369 3301
d62a17ae 3302 if (old_select)
9bcb3eef 3303 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3304 if (new_select) {
ddb5b488
PZ
3305 if (debug)
3306 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3307 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3308 bgp_path_info_unset_flag(dest, new_select,
3309 BGP_PATH_ATTR_CHANGED);
1defdda8 3310 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3311 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3312 }
338b3424 3313
49e5a4a0 3314#ifdef ENABLE_BGP_VNC
d62a17ae 3315 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3316 if (old_select != new_select) {
3317 if (old_select) {
3318 vnc_import_bgp_exterior_del_route(bgp, p,
3319 old_select);
3320 vnc_import_bgp_del_route(bgp, p, old_select);
3321 }
3322 if (new_select) {
3323 vnc_import_bgp_exterior_add_route(bgp, p,
3324 new_select);
3325 vnc_import_bgp_add_route(bgp, p, new_select);
3326 }
3327 }
3328 }
65efcfce
LB
3329#endif
3330
9bcb3eef 3331 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3332
3333 /* unicast routes must also be annouced to labeled-unicast update-groups
3334 */
3335 if (safi == SAFI_UNICAST)
9bcb3eef 3336 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3337 new_select);
3338
3339 /* FIB update. */
3340 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3341 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3342
d62a17ae 3343 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3344 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3345 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3346 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3347
3348 /* if this is an evpn imported type-5 prefix,
3349 * we need to withdraw the route first to clear
3350 * the nh neigh and the RMAC entry.
3351 */
3352 if (old_select &&
3353 is_route_parent_evpn(old_select))
3354 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3355
9bcb3eef 3356 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3357 } else {
d62a17ae 3358 /* Withdraw the route from the kernel. */
3359 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3360 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3361 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3362 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3363
568e10ca 3364 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3365 }
718e3744 3366 }
3064bf43 3367
9bcb3eef 3368 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3369 old_select);
5424b7ba 3370
d62a17ae 3371 /* Clear any route change flags. */
9bcb3eef 3372 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3373
18ee8310 3374 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3375 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3376 bgp_path_info_reap(dest, old_select);
d62a17ae 3377
9bcb3eef 3378 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3379 return;
718e3744 3380}
3381
f009ff26 3382/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3383void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3384{
9bcb3eef 3385 struct bgp_dest *dest;
f009ff26 3386 int cnt = 0;
3387 struct afi_safi_info *thread_info;
f009ff26 3388
56c226e7 3389 if (bgp->gr_info[afi][safi].t_route_select) {
e6685141 3390 struct event *t = bgp->gr_info[afi][safi].t_route_select;
56c226e7 3391
e16d030c 3392 thread_info = EVENT_ARG(t);
56c226e7 3393 XFREE(MTYPE_TMP, thread_info);
e16d030c 3394 EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3395 }
f009ff26 3396
3397 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3398 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3399 get_afi_safi_str(afi, safi, false),
26742171 3400 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3401 }
3402
3403 /* Process the route list */
6338d242 3404 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3405 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3406 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3407 dest = bgp_route_next(dest)) {
3408 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3409 continue;
3410
3411 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3412 bgp->gr_info[afi][safi].gr_deferred--;
3413 bgp_process_main_one(bgp, dest, afi, safi);
3414 cnt++;
067ea165
CB
3415 }
3416 /* If iteration stopped before the entire table was traversed then the
3417 * node needs to be unlocked.
3418 */
3419 if (dest) {
3420 bgp_dest_unlock_node(dest);
3421 dest = NULL;
f009ff26 3422 }
3423
9e3b51a7 3424 /* Send EOR message when all routes are processed */
6338d242 3425 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3426 bgp_send_delayed_eor(bgp);
8c48b3b6 3427 /* Send route processing complete message to RIB */
115ccb9a 3428 bgp_zebra_update(bgp, afi, safi,
36235319 3429 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3430 return;
9e3b51a7 3431 }
f009ff26 3432
3433 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3434
3435 thread_info->afi = afi;
3436 thread_info->safi = safi;
3437 thread_info->bgp = bgp;
3438
3439 /* If there are more routes to be processed, start the
3440 * selection timer
3441 */
907a2395 3442 event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
f009ff26 3443 BGP_ROUTE_SELECT_DELAY,
3444 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3445}
3446
aac24838 3447static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3448{
aac24838
JB
3449 struct bgp_process_queue *pqnode = data;
3450 struct bgp *bgp = pqnode->bgp;
d62a17ae 3451 struct bgp_table *table;
9bcb3eef 3452 struct bgp_dest *dest;
aac24838
JB
3453
3454 /* eoiu marker */
3455 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3456 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3457 /* should always have dedicated wq call */
3458 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3459 return WQ_SUCCESS;
3460 }
3461
ac021f40 3462 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3463 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3464 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3465 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3466 table = bgp_dest_table(dest);
3467 /* note, new DESTs may be added as part of processing */
3468 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3469
9bcb3eef 3470 bgp_dest_unlock_node(dest);
d62a17ae 3471 bgp_table_unlock(table);
3472 }
aac24838
JB
3473
3474 return WQ_SUCCESS;
3475}
3476
3477static void bgp_processq_del(struct work_queue *wq, void *data)
3478{
3479 struct bgp_process_queue *pqnode = data;
3480
3481 bgp_unlock(pqnode->bgp);
3482
3483 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3484}
3485
b6c386bb 3486void bgp_process_queue_init(struct bgp *bgp)
200df115 3487{
b6c386bb
DS
3488 if (!bgp->process_queue) {
3489 char name[BUFSIZ];
3490
3491 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3492 bgp->process_queue = work_queue_new(bm->master, name);
3493 }
3494
3495 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3496 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3497 bgp->process_queue->spec.max_retries = 0;
3498 bgp->process_queue->spec.hold = 50;
d62a17ae 3499 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3500 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3501}
3502
cfe8d15a 3503static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3504{
3505 struct bgp_process_queue *pqnode;
3506
a4d82a8a
PZ
3507 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3508 sizeof(struct bgp_process_queue));
aac24838
JB
3509
3510 /* unlocked in bgp_processq_del */
3511 pqnode->bgp = bgp_lock(bgp);
3512 STAILQ_INIT(&pqnode->pqueue);
3513
aac24838
JB
3514 return pqnode;
3515}
3516
9bcb3eef 3517void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3518{
aac24838 3519#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3520 struct work_queue *wq = bgp->process_queue;
d62a17ae 3521 struct bgp_process_queue *pqnode;
cfe8d15a 3522 int pqnode_reuse = 0;
495f0b13 3523
d62a17ae 3524 /* already scheduled for processing? */
9bcb3eef 3525 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3526 return;
2e02b9b2 3527
f009ff26 3528 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3529 * the workqueue
3530 */
9bcb3eef 3531 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3532 if (BGP_DEBUG(update, UPDATE_OUT))
3533 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3534 dest);
f009ff26 3535 return;
3536 }
3537
46aeabed
LS
3538 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3539 if (BGP_DEBUG(update, UPDATE_OUT))
3540 zlog_debug(
3541 "Soft reconfigure table in progress for route %p",
3542 dest);
3543 return;
3544 }
3545
aac24838 3546 if (wq == NULL)
d62a17ae 3547 return;
3548
aac24838 3549 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3550 limit only if is from the same BGP view and it's not an EOIU marker
3551 */
aac24838
JB
3552 if (work_queue_item_count(wq)) {
3553 struct work_queue_item *item = work_queue_last_item(wq);
3554 pqnode = item->data;
228da428 3555
a4d82a8a
PZ
3556 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3557 || pqnode->bgp != bgp
3558 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3559 pqnode = bgp_processq_alloc(bgp);
3560 else
3561 pqnode_reuse = 1;
aac24838 3562 } else
cfe8d15a 3563 pqnode = bgp_processq_alloc(bgp);
aac24838 3564 /* all unlocked in bgp_process_wq */
9bcb3eef 3565 bgp_table_lock(bgp_dest_table(dest));
aac24838 3566
9bcb3eef
DS
3567 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3568 bgp_dest_lock_node(dest);
aac24838 3569
60466a63 3570 /* can't be enqueued twice */
9bcb3eef
DS
3571 assert(STAILQ_NEXT(dest, pq) == NULL);
3572 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3573 pqnode->queued++;
3574
cfe8d15a
LB
3575 if (!pqnode_reuse)
3576 work_queue_add(wq, pqnode);
3577
d62a17ae 3578 return;
fee0f4c6 3579}
0a486e5f 3580
d62a17ae 3581void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3582{
d62a17ae 3583 struct bgp_process_queue *pqnode;
cb1faec9 3584
b6c386bb 3585 if (bgp->process_queue == NULL)
d62a17ae 3586 return;
2e02b9b2 3587
cfe8d15a 3588 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3589
aac24838 3590 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3591 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3592}
3593
e6685141 3594static void bgp_maximum_prefix_restart_timer(struct event *thread)
0a486e5f 3595{
d62a17ae 3596 struct peer *peer;
0a486e5f 3597
e16d030c 3598 peer = EVENT_ARG(thread);
d62a17ae 3599 peer->t_pmax_restart = NULL;
0a486e5f 3600
d62a17ae 3601 if (bgp_debug_neighbor_events(peer))
3602 zlog_debug(
3603 "%s Maximum-prefix restart timer expired, restore peering",
3604 peer->host);
0a486e5f 3605
a9bafa95 3606 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3607 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3608}
3609
9cbd06e0
DA
3610static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3611 safi_t safi)
3612{
3613 uint32_t count = 0;
f41b0459 3614 bool filtered = false;
9cbd06e0
DA
3615 struct bgp_dest *dest;
3616 struct bgp_adj_in *ain;
40bb2ccf 3617 struct attr attr = {};
9cbd06e0
DA
3618 struct bgp_table *table = peer->bgp->rib[afi][safi];
3619
3620 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3621 for (ain = dest->adj_in; ain; ain = ain->next) {
3622 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3623
3624 attr = *ain->attr;
9cbd06e0
DA
3625
3626 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3627 == FILTER_DENY)
f41b0459
DA
3628 filtered = true;
3629
3630 if (bgp_input_modifier(
3631 peer, rn_p, &attr, afi, safi,
3632 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3633 NULL, 0, NULL)
3634 == RMAP_DENY)
3635 filtered = true;
3636
3637 if (filtered)
9cbd06e0 3638 count++;
f41b0459 3639
d498917e 3640 bgp_attr_flush(&attr);
9cbd06e0
DA
3641 }
3642 }
3643
3644 return count;
3645}
3646
3dc339cd
DA
3647bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3648 int always)
718e3744 3649{
d62a17ae 3650 iana_afi_t pkt_afi;
5c525538 3651 iana_safi_t pkt_safi;
9cbd06e0
DA
3652 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3653 PEER_FLAG_MAX_PREFIX_FORCE))
3654 ? bgp_filtered_routes_count(peer, afi, safi)
3655 + peer->pcount[afi][safi]
3656 : peer->pcount[afi][safi];
9cabb64b 3657
d62a17ae 3658 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3659 return false;
e0701b79 3660
9cbd06e0 3661 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3662 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3663 PEER_STATUS_PREFIX_LIMIT)
3664 && !always)
3dc339cd 3665 return false;
e0701b79 3666
d62a17ae 3667 zlog_info(
f70c91dc
DA
3668 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3669 get_afi_safi_str(afi, safi, false), peer, pcount,
3670 peer->pmax[afi][safi]);
d62a17ae 3671 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3672
3673 if (CHECK_FLAG(peer->af_flags[afi][safi],
3674 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3675 return false;
d62a17ae 3676
3677 /* Convert AFI, SAFI to values for packet. */
3678 pkt_afi = afi_int2iana(afi);
3679 pkt_safi = safi_int2iana(safi);
3680 {
d7c0a89a 3681 uint8_t ndata[7];
d62a17ae 3682
3683 ndata[0] = (pkt_afi >> 8);
3684 ndata[1] = pkt_afi;
3685 ndata[2] = pkt_safi;
3686 ndata[3] = (peer->pmax[afi][safi] >> 24);
3687 ndata[4] = (peer->pmax[afi][safi] >> 16);
3688 ndata[5] = (peer->pmax[afi][safi] >> 8);
3689 ndata[6] = (peer->pmax[afi][safi]);
3690
3691 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3692 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3693 BGP_NOTIFY_CEASE_MAX_PREFIX,
3694 ndata, 7);
3695 }
3696
3697 /* Dynamic peers will just close their connection. */
3698 if (peer_dynamic_neighbor(peer))
3dc339cd 3699 return true;
d62a17ae 3700
3701 /* restart timer start */
3702 if (peer->pmax_restart[afi][safi]) {
3703 peer->v_pmax_restart =
3704 peer->pmax_restart[afi][safi] * 60;
3705
3706 if (bgp_debug_neighbor_events(peer))
3707 zlog_debug(
f70c91dc
DA
3708 "%pBP Maximum-prefix restart timer started for %d secs",
3709 peer, peer->v_pmax_restart);
d62a17ae 3710
3711 BGP_TIMER_ON(peer->t_pmax_restart,
3712 bgp_maximum_prefix_restart_timer,
3713 peer->v_pmax_restart);
3714 }
3715
3dc339cd 3716 return true;
d62a17ae 3717 } else
3718 UNSET_FLAG(peer->af_sflags[afi][safi],
3719 PEER_STATUS_PREFIX_LIMIT);
3720
b1823b69
DS
3721 if (pcount
3722 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3723 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3724 PEER_STATUS_PREFIX_THRESHOLD)
3725 && !always)
3dc339cd 3726 return false;
d62a17ae 3727
3728 zlog_info(
f70c91dc
DA
3729 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3730 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3731 peer->pmax[afi][safi]);
d62a17ae 3732 SET_FLAG(peer->af_sflags[afi][safi],
3733 PEER_STATUS_PREFIX_THRESHOLD);
3734 } else
3735 UNSET_FLAG(peer->af_sflags[afi][safi],
3736 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3737 return false;
718e3744 3738}
3739
b40d939b 3740/* Unconditionally remove the route from the RIB, without taking
3741 * damping into consideration (eg, because the session went down)
3742 */
9bcb3eef 3743void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3744 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3745{
f009ff26 3746
3747 struct bgp *bgp = NULL;
3748 bool delete_route = false;
3749
9bcb3eef
DS
3750 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3751 safi);
d62a17ae 3752
f009ff26 3753 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3754 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3755
f009ff26 3756 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3757 * flag
3758 */
3759 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3760 delete_route = true;
9bcb3eef 3761 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3762 delete_route = true;
f009ff26 3763 if (delete_route) {
9bcb3eef
DS
3764 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3765 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3766 bgp = pi->peer->bgp;
26742171 3767 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3768 }
3769 }
3770 }
4a11bf2c 3771
9bcb3eef
DS
3772 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3773 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3774}
3775
9bcb3eef 3776static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3777 struct peer *peer, afi_t afi, safi_t safi,
3778 struct prefix_rd *prd)
3779{
9bcb3eef 3780 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3781
d62a17ae 3782 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3783 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3784 */
b4f7f45b
IR
3785 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3786 && peer->sort == BGP_PEER_EBGP)
3787 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3788 == BGP_DAMP_SUPPRESSED) {
3789 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3790 safi);
3791 return;
d62a17ae 3792 }
3793
49e5a4a0 3794#ifdef ENABLE_BGP_VNC
d62a17ae 3795 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3796 struct bgp_dest *pdest = NULL;
d62a17ae 3797 struct bgp_table *table = NULL;
3798
9bcb3eef
DS
3799 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3800 (struct prefix *)prd);
3801 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3802 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3803
3804 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3805 peer->bgp, prd, table, p, pi);
d62a17ae 3806 }
9bcb3eef 3807 bgp_dest_unlock_node(pdest);
d62a17ae 3808 }
3809 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3810 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3811
b54892e0
DS
3812 vnc_import_bgp_del_route(peer->bgp, p, pi);
3813 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3814 }
65efcfce 3815 }
d62a17ae 3816#endif
128ea8ab 3817
d62a17ae 3818 /* If this is an EVPN route, process for un-import. */
3819 if (safi == SAFI_EVPN)
b54892e0 3820 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3821
9bcb3eef 3822 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3823}
3824
4b7e6066
DS
3825struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3826 struct peer *peer, struct attr *attr,
9bcb3eef 3827 struct bgp_dest *dest)
fb018d25 3828{
4b7e6066 3829 struct bgp_path_info *new;
fb018d25 3830
d62a17ae 3831 /* Make new BGP info. */
4b7e6066 3832 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3833 new->type = type;
3834 new->instance = instance;
3835 new->sub_type = sub_type;
3836 new->peer = peer;
3837 new->attr = attr;
083ec940 3838 new->uptime = monotime(NULL);
9bcb3eef 3839 new->net = dest;
d62a17ae 3840 return new;
fb018d25
DS
3841}
3842
c265ee22 3843/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3844bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3845 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3846 struct bgp_dest *dest)
d62a17ae 3847{
2dbe3fa9 3848 bool ret = false;
b099a5c8
DA
3849 bool is_bgp_static_route =
3850 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3851 : false;
d62a17ae 3852
6cddc4c8
DA
3853 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3854 * as good.
3855 */
3856 if (bgp->allow_martian)
3857 return false;
3858
e8442016
DS
3859 /*
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3865 */
3866 if (is_bgp_static_route ||
3867 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3868 return false;
d62a17ae 3869
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3872 if (attr->nexthop.s_addr == INADDR_ANY ||
3873 !ipv4_unicast_valid(&attr->nexthop) ||
3874 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3875 return true;
d62a17ae 3876 }
c265ee22 3877
d62a17ae 3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
0355b41d
DA
3882 *
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
d62a17ae 3886 */
3887 if (attr->mp_nexthop_len) {
3888 switch (attr->mp_nexthop_len) {
3889 case BGP_ATTR_NHLEN_IPV4:
3890 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3891 ret = (attr->mp_nexthop_global_in.s_addr ==
3892 INADDR_ANY ||
3893 !ipv4_unicast_valid(
3894 &attr->mp_nexthop_global_in) ||
3895 bgp_nexthop_self(bgp, afi, type, stype, attr,
3896 dest));
d62a17ae 3897 break;
3898
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3901 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3902 &attr->mp_nexthop_global)
d62a17ae 3903 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3904 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3905 &attr->mp_nexthop_global)
3906 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3907 dest));
d62a17ae 3908 break;
0355b41d
DA
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3910 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr->mp_nexthop_global)
3913 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3914 dest));
0355b41d 3915 break;
d62a17ae 3916
3917 default:
3dc339cd 3918 ret = true;
d62a17ae 3919 break;
3920 }
3921 }
c265ee22 3922
d62a17ae 3923 return ret;
3924}
3925
aade37d7 3926static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3927{
3928 struct community *old;
3929 struct community *new;
3930 struct community *merge;
aade37d7 3931 struct community *no_export;
2721dd61 3932
9a706b42 3933 old = bgp_attr_get_community(attr);
aade37d7 3934 no_export = community_str2com("no-export");
2721dd61 3935
b4efa101
DA
3936 assert(no_export);
3937
2721dd61 3938 if (old) {
aade37d7 3939 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3940
3941 if (!old->refcnt)
3942 community_free(&old);
3943
3944 new = community_uniq_sort(merge);
3945 community_free(&merge);
3946 } else {
aade37d7 3947 new = community_dup(no_export);
2721dd61
DA
3948 }
3949
aade37d7 3950 community_free(&no_export);
2721dd61 3951
9a706b42 3952 bgp_attr_set_community(attr, new);
2721dd61
DA
3953}
3954
46dbf9d0
DA
3955static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3956 struct attr *attr, const struct prefix *prefix,
3957 int *sub_type)
3958{
3959 struct listnode *node, *nnode;
3960 struct bgp *bgp;
3961 bool accept_own_found = false;
3962
3963 if (safi != SAFI_MPLS_VPN)
3964 return false;
3965
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3968 return false;
3969
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3972 struct community *comm = bgp_attr_get_community(attr);
3973
3974 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3975 accept_own_found = true;
3976 }
3977
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3980 */
3981 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3982 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3983 continue;
3984
3985 if (accept_own_found &&
3986 ecommunity_include(
3987 bgp->vpn_policy[afi]
3988 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3989 bgp_attr_get_ecommunity(attr))) {
3990 if (bgp_debug_update(peer, prefix, NULL, 1))
3991 zlog_debug(
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3993 peer, prefix);
3994
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
3998 * community.
3999 */
4000 *sub_type = BGP_ROUTE_IMPORTED;
4001
4002 return true;
4003 }
4004 }
4005
4006 return false;
4007}
4008
367b458c
DS
4009void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4010 struct attr *attr, afi_t afi, safi_t safi, int type,
4011 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4012 uint32_t num_labels, int soft_reconfig,
4013 struct bgp_route_evpn *evpn)
d62a17ae 4014{
4015 int ret;
4016 int aspath_loop_count = 0;
9bcb3eef 4017 struct bgp_dest *dest;
d62a17ae 4018 struct bgp *bgp;
4019 struct attr new_attr;
4020 struct attr *attr_new;
40381db7 4021 struct bgp_path_info *pi;
819e6767 4022 struct bgp_path_info *new = NULL;
4b7e6066 4023 struct bgp_path_info_extra *extra;
d62a17ae 4024 const char *reason;
4025 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4026 int connected = 0;
4027 int do_loop_check = 1;
4028 int has_valid_label = 0;
7c312383 4029 afi_t nh_afi;
9146341f 4030 bool force_evpn_import = false;
907707db 4031 safi_t orig_safi = safi;
a486300b 4032 bool leak_success = true;
b2ac1d0d 4033 int allowas_in = 0;
949b0f24 4034
c7bb4f00 4035 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4036 char pfxprint[PREFIX2STR_BUFFER];
4037
4038 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4039 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4040 afi, safi, attr);
6401252f
QY
4041 }
4042
49e5a4a0 4043#ifdef ENABLE_BGP_VNC
d62a17ae 4044 int vnc_implicit_withdraw = 0;
65efcfce 4045#endif
d62a17ae 4046 int same_attr = 0;
f8745525 4047 const struct prefix *bgp_nht_param_prefix;
718e3744 4048
907707db
MS
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi == SAFI_LABELED_UNICAST)
4051 safi = SAFI_UNICAST;
4052
6006b807 4053 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4054 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4055 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4056
d62a17ae 4057 bgp = peer->bgp;
9bcb3eef 4058 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4061 has_valid_label = (num_labels > 0) ? 1 : 0;
4062 else
4063 has_valid_label = bgp_is_valid_label(label);
718e3744 4064
28f66de2
MS
4065 if (has_valid_label)
4066 assert(label != NULL);
4067
66ff6089 4068
d62a17ae 4069 /* When peer's soft reconfiguration enabled. Record input packet in
4070 Adj-RIBs-In. */
6e076ba5
PJD
4071 if (!soft_reconfig &&
4072 CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) &&
4073 peer != bgp->peer_self) {
4074 /*
4075 * If the trigger is not from soft_reconfig and if
4076 * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4077 * will not be interned. In which case, it is ok to update the
4078 * attr->evpn_overlay, so that, this can be stored in adj_in.
4079 */
4080 if ((afi == AFI_L2VPN) && evpn) {
4081 memcpy(&attr->evpn_overlay, evpn,
4082 sizeof(struct bgp_route_evpn));
4083 }
9bcb3eef 4084 bgp_adj_in_set(dest, peer, attr, addpath_id);
6e076ba5 4085 }
d62a17ae 4086
b2ac1d0d
MS
4087 /* Update permitted loop count */
4088 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4089 allowas_in = peer->allowas_in[afi][safi];
4090
d62a17ae 4091 /* Check previously received route. */
9bcb3eef 4092 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4093 if (pi->peer == peer && pi->type == type
4094 && pi->sub_type == sub_type
4095 && pi->addpath_rx_id == addpath_id)
d62a17ae 4096 break;
4097
4098 /* AS path local-as loop check. */
4099 if (peer->change_local_as) {
b2ac1d0d
MS
4100 if (allowas_in)
4101 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4102 else if (!CHECK_FLAG(peer->flags,
4103 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4104 aspath_loop_count = 1;
4105
4106 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4107 > aspath_loop_count) {
b4d46cc9 4108 peer->stat_pfx_aspath_loop++;
692174a1 4109 reason = "as-path contains our own AS;";
d62a17ae 4110 goto filtered;
4111 }
718e3744 4112 }
718e3744 4113
d62a17ae 4114 /* If the peer is configured for "allowas-in origin" and the last ASN in
4115 * the
4116 * as-path is our ASN then we do not need to call aspath_loop_check
4117 */
4118 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4119 if (aspath_get_last_as(attr->aspath) == bgp->as)
4120 do_loop_check = 0;
4121
f8745525
PG
4122 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4123 bgp_nht_param_prefix = NULL;
4124 else
4125 bgp_nht_param_prefix = p;
4126
d62a17ae 4127 /* AS path loop check. */
4128 if (do_loop_check) {
b0a8f709
FD
4129 if (aspath_loop_check(attr->aspath, bgp->as) >
4130 peer->allowas_in[afi][safi]) {
b4d46cc9 4131 peer->stat_pfx_aspath_loop++;
d62a17ae 4132 reason = "as-path contains our own AS;";
4133 goto filtered;
4134 }
4135 }
aac9ef6c 4136
b0a8f709
FD
4137 /* If we're a CONFED we need to loop check the CONFED ID too */
4138 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4139 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4140 peer->allowas_in[afi][safi]) {
4141 peer->stat_pfx_aspath_loop++;
4142 reason = "as-path contains our own confed AS;";
4143 goto filtered;
4144 }
4145
46dbf9d0
DA
4146 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4147 * enabled, then take care of that too.
4148 */
4149 bool accept_own = false;
4150
d62a17ae 4151 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4152 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4153 accept_own =
4154 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4155 if (!accept_own) {
4156 peer->stat_pfx_originator_loop++;
4157 reason = "originator is us;";
4158 goto filtered;
4159 }
d62a17ae 4160 }
718e3744 4161
d62a17ae 4162 /* Route reflector cluster ID check. */
4163 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4164 peer->stat_pfx_cluster_loop++;
d62a17ae 4165 reason = "reflected from the same cluster;";
4166 goto filtered;
4167 }
718e3744 4168
d62a17ae 4169 /* Apply incoming filter. */
907707db 4170 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4171 peer->stat_pfx_filter++;
d62a17ae 4172 reason = "filter;";
4173 goto filtered;
4174 }
718e3744 4175
a8b72dc6
DA
4176 /* RFC 8212 to prevent route leaks.
4177 * This specification intends to improve this situation by requiring the
4178 * explicit configuration of both BGP Import and Export Policies for any
4179 * External BGP (EBGP) session such as customers, peers, or
4180 * confederation boundaries for all enabled address families. Through
4181 * codification of the aforementioned requirement, operators will
4182 * benefit from consistent behavior across different BGP
4183 * implementations.
4184 */
1d3fdccf 4185 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4186 if (!bgp_inbound_policy_exists(peer,
4187 &peer->filter[afi][safi])) {
4188 reason = "inbound policy missing";
b17826b7
DS
4189 if (monotime_since(&bgp->ebgprequirespolicywarning,
4190 NULL) > FIFTEENMINUTE2USEC ||
4191 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4192 zlog_warn(
4193 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4194 monotime(&bgp->ebgprequirespolicywarning);
4195 }
a8b72dc6
DA
4196 goto filtered;
4197 }
4198
fb29348a
DA
4199 /* draft-ietf-idr-deprecate-as-set-confed-set
4200 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4201 * Eventually, This document (if approved) updates RFC 4271
4202 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4203 * and obsoletes RFC 6472.
4204 */
7f972cd8 4205 if (peer->bgp->reject_as_sets)
fb29348a
DA
4206 if (aspath_check_as_sets(attr->aspath)) {
4207 reason =
4208 "as-path contains AS_SET or AS_CONFED_SET type;";
4209 goto filtered;
4210 }
4211
6f4f49b2 4212 new_attr = *attr;
6e076ba5
PJD
4213 /*
4214 * If bgp_update is called with soft_reconfig set then
4215 * attr is interned. In this case, do not overwrite the
4216 * attr->evpn_overlay with evpn directly. Instead memcpy
4217 * evpn to new_atr.evpn_overlay before it is interned.
4218 */
4219 if (soft_reconfig && (afi == AFI_L2VPN) && evpn)
4220 memcpy(&new_attr.evpn_overlay, evpn,
4221 sizeof(struct bgp_route_evpn));
d62a17ae 4222
4223 /* Apply incoming route-map.
4224 * NB: new_attr may now contain newly allocated values from route-map
4225 * "set"
4226 * commands, so we need bgp_attr_flush in the error paths, until we
4227 * intern
4228 * the attr (which takes over the memory references) */
907707db 4229 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4230 num_labels, dest)
4231 == RMAP_DENY) {
b4d46cc9 4232 peer->stat_pfx_filter++;
d62a17ae 4233 reason = "route-map;";
4234 bgp_attr_flush(&new_attr);
4235 goto filtered;
4236 }
718e3744 4237
05864da7 4238 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4239 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4240 /* remove from RIB previous entry */
4241 bgp_zebra_withdraw(p, pi, bgp, safi);
4242 }
4243
7f323236
DW
4244 if (peer->sort == BGP_PEER_EBGP) {
4245
2721dd61
DA
4246 /* rfc7999:
4247 * A BGP speaker receiving an announcement tagged with the
4248 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4249 * NO_EXPORT community as defined in RFC1997, or a
4250 * similar community, to prevent propagation of the
4251 * prefix outside the local AS. The community to prevent
4252 * propagation SHOULD be chosen according to the operator's
4253 * routing policy.
4254 */
9a706b42
DA
4255 if (bgp_attr_get_community(&new_attr) &&
4256 community_include(bgp_attr_get_community(&new_attr),
4257 COMMUNITY_BLACKHOLE))
aade37d7 4258 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4259
a4d82a8a
PZ
4260 /* If we receive the graceful-shutdown community from an eBGP
4261 * peer we must lower local-preference */
9a706b42
DA
4262 if (bgp_attr_get_community(&new_attr) &&
4263 community_include(bgp_attr_get_community(&new_attr),
4264 COMMUNITY_GSHUT)) {
7f323236
DW
4265 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4266 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4267
4f770cf1
DA
4268 /* If graceful-shutdown is configured globally or
4269 * per neighbor, then add the GSHUT community to
4270 * all paths received from eBGP peers. */
4271 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4272 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4273 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4274 }
4275
d62a17ae 4276 /* next hop check. */
860ad3f9
DS
4277 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4278 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4279 &new_attr, dest)) {
b4d46cc9 4280 peer->stat_pfx_nh_invalid++;
d62a17ae 4281 reason = "martian or self next-hop;";
4282 bgp_attr_flush(&new_attr);
4283 goto filtered;
4284 }
718e3744 4285
5c14a191 4286 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4287 peer->stat_pfx_nh_invalid++;
4e802e66 4288 reason = "self mac;";
4dbf2038 4289 bgp_attr_flush(&new_attr);
4e802e66
DS
4290 goto filtered;
4291 }
4292
5a78f2bc
EB
4293 if (bgp_check_role_applicability(afi, safi) &&
4294 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4295 reason = "failing otc validation";
4296 bgp_attr_flush(&new_attr);
4297 goto filtered;
4298 }
a1b773e2 4299
01da2d26
DA
4300 /* If neighbor soo is configured, tag all incoming routes with
4301 * this SoO tag and then filter out advertisements in
4302 * subgroup_announce_check() if it matches the configured SoO
4303 * on the other peer.
4304 */
4305 if (peer->soo[afi][safi]) {
4306 struct ecommunity *old_ecomm =
4307 bgp_attr_get_ecommunity(&new_attr);
4308 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4309 struct ecommunity *new_ecomm;
4310
4311 if (old_ecomm) {
4312 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4313 ecomm_soo);
4314
4315 if (!old_ecomm->refcnt)
4316 ecommunity_free(&old_ecomm);
4317 } else {
4318 new_ecomm = ecommunity_dup(ecomm_soo);
4319 }
4320
4321 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4322 }
4323
4dbf2038 4324 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4325
d62a17ae 4326 /* If the update is implicit withdraw. */
40381db7 4327 if (pi) {
083ec940 4328 pi->uptime = monotime(NULL);
40381db7 4329 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4330
9bcb3eef 4331 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4332
d62a17ae 4333 /* Same attribute comes in. */
40381db7 4334 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4335 && same_attr
d62a17ae 4336 && (!has_valid_label
40381db7 4337 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4338 num_labels * sizeof(mpls_label_t))
66ff6089 4339 == 0)) {
b4f7f45b
IR
4340 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4341 BGP_CONFIG_DAMPENING)
d62a17ae 4342 && peer->sort == BGP_PEER_EBGP
40381db7 4343 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4344 if (bgp_debug_update(peer, p, NULL, 1)) {
4345 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4346 afi, safi, prd, p, label,
4347 num_labels, addpath_id ? 1 : 0,
66ff6089 4348 addpath_id, evpn, pfx_buf,
a4d82a8a 4349 sizeof(pfx_buf));
f70c91dc 4350 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4351 pfx_buf);
4352 }
4353
9bcb3eef 4354 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4355 != BGP_DAMP_SUPPRESSED) {
40381db7 4356 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4357 safi);
9bcb3eef 4358 bgp_process(bgp, dest, afi, safi);
d62a17ae 4359 }
4360 } else /* Duplicate - odd */
4361 {
4362 if (bgp_debug_update(peer, p, NULL, 1)) {
4363 if (!peer->rcvd_attr_printed) {
4364 zlog_debug(
f70c91dc
DA
4365 "%pBP rcvd UPDATE w/ attr: %s",
4366 peer,
d62a17ae 4367 peer->rcvd_attr_str);
4368 peer->rcvd_attr_printed = 1;
4369 }
4370
4371 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4372 afi, safi, prd, p, label,
4373 num_labels, addpath_id ? 1 : 0,
66ff6089 4374 addpath_id, evpn, pfx_buf,
a4d82a8a 4375 sizeof(pfx_buf));
d62a17ae 4376 zlog_debug(
f70c91dc
DA
4377 "%pBP rcvd %s...duplicate ignored",
4378 peer, pfx_buf);
d62a17ae 4379 }
4380
4381 /* graceful restart STALE flag unset. */
40381db7 4382 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4383 bgp_path_info_unset_flag(
9bcb3eef
DS
4384 dest, pi, BGP_PATH_STALE);
4385 bgp_dest_set_defer_flag(dest, false);
4386 bgp_process(bgp, dest, afi, safi);
d62a17ae 4387 }
4388 }
4389
9bcb3eef 4390 bgp_dest_unlock_node(dest);
d62a17ae 4391 bgp_attr_unintern(&attr_new);
4392
367b458c 4393 return;
d62a17ae 4394 }
718e3744 4395
d62a17ae 4396 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4397 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4398 if (bgp_debug_update(peer, p, NULL, 1)) {
4399 bgp_debug_rdpfxpath2str(
a4d82a8a 4400 afi, safi, prd, p, label, num_labels,
66ff6089 4401 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4402 pfx_buf, sizeof(pfx_buf));
d62a17ae 4403 zlog_debug(
f70c91dc
DA
4404 "%pBP rcvd %s, flapped quicker than processing",
4405 peer, pfx_buf);
d62a17ae 4406 }
4407
9bcb3eef 4408 bgp_path_info_restore(dest, pi);
9146341f 4409
4410 /*
4411 * If the BGP_PATH_REMOVED flag is set, then EVPN
4412 * routes would have been unimported already when a
4413 * prior BGP withdraw processing happened. Such routes
4414 * need to be imported again, so flag accordingly.
4415 */
4416 force_evpn_import = true;
704e189e 4417 } else {
4418 /* implicit withdraw, decrement aggregate and pcount
4419 * here. only if update is accepted, they'll increment
4420 * below.
4421 */
4422 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4423 }
718e3744 4424
d62a17ae 4425 /* Received Logging. */
4426 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4427 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4428 num_labels, addpath_id ? 1 : 0,
66ff6089 4429 addpath_id, evpn, pfx_buf,
a4d82a8a 4430 sizeof(pfx_buf));
f70c91dc 4431 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4432 }
718e3744 4433
d62a17ae 4434 /* graceful restart STALE flag unset. */
f009ff26 4435 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4436 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4437 bgp_dest_set_defer_flag(dest, false);
f009ff26 4438 }
d62a17ae 4439
4440 /* The attribute is changed. */
9bcb3eef 4441 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4442
d62a17ae 4443 /* Update bgp route dampening information. */
b4f7f45b 4444 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4445 && peer->sort == BGP_PEER_EBGP) {
4446 /* This is implicit withdraw so we should update
b4f7f45b
IR
4447 dampening
4448 information. */
40381db7 4449 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4450 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4451 }
49e5a4a0 4452#ifdef ENABLE_BGP_VNC
d62a17ae 4453 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4454 struct bgp_dest *pdest = NULL;
d62a17ae 4455 struct bgp_table *table = NULL;
4456
9bcb3eef
DS
4457 pdest = bgp_node_get(bgp->rib[afi][safi],
4458 (struct prefix *)prd);
4459 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4460 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4461
4462 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4463 bgp, prd, table, p, pi);
d62a17ae 4464 }
9bcb3eef 4465 bgp_dest_unlock_node(pdest);
d62a17ae 4466 }
4467 if ((afi == AFI_IP || afi == AFI_IP6)
4468 && (safi == SAFI_UNICAST)) {
40381db7 4469 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4470 /*
4471 * Implicit withdraw case.
4472 */
4473 ++vnc_implicit_withdraw;
40381db7
DS
4474 vnc_import_bgp_del_route(bgp, p, pi);
4475 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4476 }
4477 }
65efcfce 4478#endif
128ea8ab 4479
d62a17ae 4480 /* Special handling for EVPN update of an existing route. If the
4481 * extended community attribute has changed, we need to
4482 * un-import
4483 * the route using its existing extended community. It will be
4484 * subsequently processed for import with the new extended
4485 * community.
4486 */
6f8c9c11
PR
4487 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4488 && !same_attr) {
40381db7 4489 if ((pi->attr->flag
d62a17ae 4490 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4491 && (attr_new->flag
4492 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4493 int cmp;
4494
b53e67a3
DA
4495 cmp = ecommunity_cmp(
4496 bgp_attr_get_ecommunity(pi->attr),
4497 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4498 if (!cmp) {
4499 if (bgp_debug_update(peer, p, NULL, 1))
4500 zlog_debug(
4501 "Change in EXT-COMM, existing %s new %s",
4502 ecommunity_str(
b53e67a3
DA
4503 bgp_attr_get_ecommunity(
4504 pi->attr)),
d62a17ae 4505 ecommunity_str(
b53e67a3
DA
4506 bgp_attr_get_ecommunity(
4507 attr_new)));
6f8c9c11
PR
4508 if (safi == SAFI_EVPN)
4509 bgp_evpn_unimport_route(
4510 bgp, afi, safi, p, pi);
4511 else /* SAFI_MPLS_VPN */
1aa2c93e 4512 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4513 }
4514 }
4515 }
718e3744 4516
d62a17ae 4517 /* Update to new attribute. */
40381db7
DS
4518 bgp_attr_unintern(&pi->attr);
4519 pi->attr = attr_new;
d62a17ae 4520
4521 /* Update MPLS label */
4522 if (has_valid_label) {
40381db7 4523 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4524 if (extra->label != label) {
4525 memcpy(&extra->label, label,
dbd587da 4526 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4527 extra->num_labels = num_labels;
4528 }
b57ba6d2
MK
4529 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4530 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4531 }
718e3744 4532
e496b420
HS
4533 /* Update SRv6 SID */
4534 if (attr->srv6_l3vpn) {
4535 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4536 if (sid_diff(&extra->sid[0].sid,
4537 &attr->srv6_l3vpn->sid)) {
4538 sid_copy(&extra->sid[0].sid,
e496b420
HS
4539 &attr->srv6_l3vpn->sid);
4540 extra->num_sids = 1;
cc8f05df 4541
16f3db2d
RS
4542 extra->sid[0].loc_block_len = 0;
4543 extra->sid[0].loc_node_len = 0;
4544 extra->sid[0].func_len = 0;
4545 extra->sid[0].arg_len = 0;
ea7cd161
RS
4546 extra->sid[0].transposition_len = 0;
4547 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4548
4549 if (attr->srv6_l3vpn->loc_block_len != 0) {
4550 extra->sid[0].loc_block_len =
4551 attr->srv6_l3vpn->loc_block_len;
4552 extra->sid[0].loc_node_len =
4553 attr->srv6_l3vpn->loc_node_len;
4554 extra->sid[0].func_len =
4555 attr->srv6_l3vpn->func_len;
4556 extra->sid[0].arg_len =
4557 attr->srv6_l3vpn->arg_len;
ea7cd161 4558 extra->sid[0].transposition_len =
cc8f05df 4559 attr->srv6_l3vpn
ea7cd161
RS
4560 ->transposition_len;
4561 extra->sid[0].transposition_offset =
cc8f05df 4562 attr->srv6_l3vpn
ea7cd161
RS
4563 ->transposition_offset;
4564 }
e496b420
HS
4565 }
4566 } else if (attr->srv6_vpn) {
4567 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4568 if (sid_diff(&extra->sid[0].sid,
4569 &attr->srv6_vpn->sid)) {
4570 sid_copy(&extra->sid[0].sid,
4571 &attr->srv6_vpn->sid);
e496b420
HS
4572 extra->num_sids = 1;
4573 }
4574 }
4575
49e5a4a0 4576#ifdef ENABLE_BGP_VNC
d62a17ae 4577 if ((afi == AFI_IP || afi == AFI_IP6)
4578 && (safi == SAFI_UNICAST)) {
4579 if (vnc_implicit_withdraw) {
4580 /*
4581 * Add back the route with its new attributes
4582 * (e.g., nexthop).
4583 * The route is still selected, until the route
4584 * selection
4585 * queued by bgp_process actually runs. We have
4586 * to make this
4587 * update to the VNC side immediately to avoid
4588 * racing against
4589 * configuration changes (e.g., route-map
4590 * changes) which
4591 * trigger re-importation of the entire RIB.
4592 */
40381db7
DS
4593 vnc_import_bgp_add_route(bgp, p, pi);
4594 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4595 }
4596 }
65efcfce
LB
4597#endif
4598
d62a17ae 4599 /* Update bgp route dampening information. */
b4f7f45b 4600 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4601 && peer->sort == BGP_PEER_EBGP) {
4602 /* Now we do normal update dampening. */
9bcb3eef 4603 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4604 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4605 bgp_dest_unlock_node(dest);
367b458c 4606 return;
d62a17ae 4607 }
4608 }
128ea8ab 4609
d62a17ae 4610 /* Nexthop reachability check - for unicast and
4611 * labeled-unicast.. */
7c312383
AD
4612 if (((afi == AFI_IP || afi == AFI_IP6)
4613 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4614 || (safi == SAFI_EVPN &&
4615 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4616 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4617 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4618 && !CHECK_FLAG(peer->flags,
4619 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4620 && !CHECK_FLAG(bgp->flags,
4621 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4622 connected = 1;
4623 else
4624 connected = 0;
4625
960035b2
PZ
4626 struct bgp *bgp_nexthop = bgp;
4627
40381db7
DS
4628 if (pi->extra && pi->extra->bgp_orig)
4629 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4630
7c312383
AD
4631 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4632
4633 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4634 safi, pi, NULL, connected,
f8745525
PG
4635 bgp_nht_param_prefix) ||
4636 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4637 bgp_path_info_set_flag(dest, pi,
4638 BGP_PATH_VALID);
d62a17ae 4639 else {
4640 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4641 zlog_debug("%s(%pI4): NH unresolved",
4642 __func__,
4643 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4644 }
9bcb3eef 4645 bgp_path_info_unset_flag(dest, pi,
18ee8310 4646 BGP_PATH_VALID);
d62a17ae 4647 }
46dbf9d0
DA
4648 } else {
4649 if (accept_own)
4650 bgp_path_info_set_flag(dest, pi,
4651 BGP_PATH_ACCEPT_OWN);
4652
9bcb3eef 4653 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4654 }
d62a17ae 4655
49e5a4a0 4656#ifdef ENABLE_BGP_VNC
d62a17ae 4657 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4658 struct bgp_dest *pdest = NULL;
d62a17ae 4659 struct bgp_table *table = NULL;
4660
9bcb3eef
DS
4661 pdest = bgp_node_get(bgp->rib[afi][safi],
4662 (struct prefix *)prd);
4663 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4664 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4665
4666 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4667 bgp, prd, table, p, pi);
d62a17ae 4668 }
9bcb3eef 4669 bgp_dest_unlock_node(pdest);
d62a17ae 4670 }
4671#endif
718e3744 4672
d62a17ae 4673 /* If this is an EVPN route and some attribute has changed,
9146341f 4674 * or we are explicitly told to perform a route import, process
d62a17ae 4675 * route for import. If the extended community has changed, we
4676 * would
4677 * have done the un-import earlier and the import would result
4678 * in the
4679 * route getting injected into appropriate L2 VNIs. If it is
4680 * just
4681 * some other attribute change, the import will result in
4682 * updating
4683 * the attributes for the route in the VNI(s).
4684 */
9146341f 4685 if (safi == SAFI_EVPN &&
4686 (!same_attr || force_evpn_import) &&
7c312383 4687 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4688 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4689
4690 /* Process change. */
40381db7 4691 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4692
9bcb3eef
DS
4693 bgp_process(bgp, dest, afi, safi);
4694 bgp_dest_unlock_node(dest);
558d1fec 4695
ddb5b488
PZ
4696 if (SAFI_UNICAST == safi
4697 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4698 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4699
40381db7 4700 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4701 }
4702 if ((SAFI_MPLS_VPN == safi)
4703 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4704 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4705 }
4706
49e5a4a0 4707#ifdef ENABLE_BGP_VNC
d62a17ae 4708 if (SAFI_MPLS_VPN == safi) {
4709 mpls_label_t label_decoded = decode_label(label);
28070ee3 4710
d62a17ae 4711 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4712 type, sub_type, &label_decoded);
4713 }
4714 if (SAFI_ENCAP == safi) {
4715 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4716 type, sub_type, NULL);
4717 }
28070ee3 4718#endif
a486300b
PG
4719 if ((safi == SAFI_MPLS_VPN) &&
4720 !CHECK_FLAG(bgp->af_flags[afi][safi],
4721 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4722 !leak_success) {
4723 bgp_unlink_nexthop(pi);
4724 bgp_path_info_delete(dest, pi);
4725 }
367b458c 4726 return;
d62a17ae 4727 } // End of implicit withdraw
718e3744 4728
d62a17ae 4729 /* Received Logging. */
4730 if (bgp_debug_update(peer, p, NULL, 1)) {
4731 if (!peer->rcvd_attr_printed) {
f70c91dc 4732 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4733 peer->rcvd_attr_str);
4734 peer->rcvd_attr_printed = 1;
4735 }
718e3744 4736
a4d82a8a 4737 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4738 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4739 pfx_buf, sizeof(pfx_buf));
f70c91dc 4740 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4741 }
718e3744 4742
d62a17ae 4743 /* Make new BGP info. */
9bcb3eef 4744 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4745
d62a17ae 4746 /* Update MPLS label */
4747 if (has_valid_label) {
18ee8310 4748 extra = bgp_path_info_extra_get(new);
8ba71050 4749 if (extra->label != label) {
dbd587da
QY
4750 memcpy(&extra->label, label,
4751 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4752 extra->num_labels = num_labels;
4753 }
b57ba6d2
MK
4754 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4755 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4756 }
718e3744 4757
e496b420
HS
4758 /* Update SRv6 SID */
4759 if (safi == SAFI_MPLS_VPN) {
4760 extra = bgp_path_info_extra_get(new);
4761 if (attr->srv6_l3vpn) {
16f3db2d 4762 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4763 extra->num_sids = 1;
cc8f05df 4764
16f3db2d
RS
4765 extra->sid[0].loc_block_len =
4766 attr->srv6_l3vpn->loc_block_len;
4767 extra->sid[0].loc_node_len =
4768 attr->srv6_l3vpn->loc_node_len;
4769 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4770 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4771 extra->sid[0].transposition_len =
4772 attr->srv6_l3vpn->transposition_len;
4773 extra->sid[0].transposition_offset =
4774 attr->srv6_l3vpn->transposition_offset;
e496b420 4775 } else if (attr->srv6_vpn) {
16f3db2d 4776 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4777 extra->num_sids = 1;
4778 }
4779 }
4780
d62a17ae 4781 /* Nexthop reachability check. */
7c312383
AD
4782 if (((afi == AFI_IP || afi == AFI_IP6)
4783 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4784 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4785 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4786 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4787 && !CHECK_FLAG(peer->flags,
4788 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4789 && !CHECK_FLAG(bgp->flags,
4790 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4791 connected = 1;
4792 else
4793 connected = 0;
4794
7c312383
AD
4795 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4796
4053e952 4797 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4798 connected, bgp_nht_param_prefix) ||
4799 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4800 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4801 else {
07380148
DA
4802 if (BGP_DEBUG(nht, NHT))
4803 zlog_debug("%s(%pI4): NH unresolved", __func__,
4804 &attr_new->nexthop);
9bcb3eef 4805 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4806 }
46dbf9d0
DA
4807 } else {
4808 if (accept_own)
4809 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4810
9bcb3eef 4811 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4812 }
a82478b9 4813
b381ed97
DA
4814 /* If maximum prefix count is configured and current prefix
4815 * count exeed it.
4816 */
4817 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4818 reason = "maximum-prefix overflow";
4819 bgp_attr_flush(&new_attr);
b381ed97
DA
4820 goto filtered;
4821 }
4822
d62a17ae 4823 /* Addpath ID */
4824 new->addpath_rx_id = addpath_id;
4825
4826 /* Increment prefix */
4827 bgp_aggregate_increment(bgp, p, new, afi, safi);
4828
4829 /* Register new BGP information. */
9bcb3eef 4830 bgp_path_info_add(dest, new);
d62a17ae 4831
4832 /* route_node_get lock */
9bcb3eef 4833 bgp_dest_unlock_node(dest);
558d1fec 4834
49e5a4a0 4835#ifdef ENABLE_BGP_VNC
d62a17ae 4836 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4837 struct bgp_dest *pdest = NULL;
d62a17ae 4838 struct bgp_table *table = NULL;
4839
9bcb3eef
DS
4840 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4841 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4842 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4843
4844 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4845 bgp, prd, table, p, new);
4846 }
9bcb3eef 4847 bgp_dest_unlock_node(pdest);
d62a17ae 4848 }
65efcfce
LB
4849#endif
4850
d62a17ae 4851 /* If this is an EVPN route, process for import. */
7c312383 4852 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4853 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4854
9bcb3eef 4855 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4856
d62a17ae 4857 /* Process change. */
9bcb3eef 4858 bgp_process(bgp, dest, afi, safi);
718e3744 4859
ddb5b488
PZ
4860 if (SAFI_UNICAST == safi
4861 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4862 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4863 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4864 }
4865 if ((SAFI_MPLS_VPN == safi)
4866 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4867 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4868 }
49e5a4a0 4869#ifdef ENABLE_BGP_VNC
d62a17ae 4870 if (SAFI_MPLS_VPN == safi) {
4871 mpls_label_t label_decoded = decode_label(label);
28070ee3 4872
d62a17ae 4873 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4874 sub_type, &label_decoded);
4875 }
4876 if (SAFI_ENCAP == safi) {
4877 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4878 sub_type, NULL);
4879 }
28070ee3 4880#endif
a486300b
PG
4881 if ((safi == SAFI_MPLS_VPN) &&
4882 !CHECK_FLAG(bgp->af_flags[afi][safi],
4883 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4884 !leak_success) {
4885 bgp_unlink_nexthop(new);
4886 bgp_path_info_delete(dest, new);
4887 }
28070ee3 4888
367b458c 4889 return;
718e3744 4890
d62a17ae 4891/* This BGP update is filtered. Log the reason then update BGP
4892 entry. */
4893filtered:
819e6767
DA
4894 if (new) {
4895 bgp_unlink_nexthop(new);
4896 bgp_path_info_delete(dest, new);
4897 bgp_path_info_extra_free(&new->extra);
4898 XFREE(MTYPE_BGP_ROUTE, new);
4899 }
4900
9bcb3eef 4901 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4902
d62a17ae 4903 if (bgp_debug_update(peer, p, NULL, 1)) {
4904 if (!peer->rcvd_attr_printed) {
f70c91dc 4905 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4906 peer->rcvd_attr_str);
4907 peer->rcvd_attr_printed = 1;
4908 }
718e3744 4909
a4d82a8a 4910 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4911 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4912 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4913 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4914 peer, pfx_buf, reason);
d62a17ae 4915 }
128ea8ab 4916
40381db7 4917 if (pi) {
d62a17ae 4918 /* If this is an EVPN route, un-import it as it is now filtered.
4919 */
4920 if (safi == SAFI_EVPN)
40381db7 4921 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4922
ddb5b488
PZ
4923 if (SAFI_UNICAST == safi
4924 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4925 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4926
40381db7 4927 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4928 }
4929 if ((SAFI_MPLS_VPN == safi)
4930 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4931
1aa2c93e 4932 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4933 }
4934
9bcb3eef 4935 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4936 }
4937
9bcb3eef 4938 bgp_dest_unlock_node(dest);
558d1fec 4939
49e5a4a0 4940#ifdef ENABLE_BGP_VNC
d62a17ae 4941 /*
4942 * Filtered update is treated as an implicit withdrawal (see
4943 * bgp_rib_remove()
4944 * a few lines above)
4945 */
4946 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4947 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4948 0);
4949 }
97736e32
PZ
4950#endif
4951
367b458c 4952 return;
718e3744 4953}
4954
367b458c 4955void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4956 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4957 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4958 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4959{
d62a17ae 4960 struct bgp *bgp;
4961 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4962 struct bgp_dest *dest;
40381db7 4963 struct bgp_path_info *pi;
718e3744 4964
49e5a4a0 4965#ifdef ENABLE_BGP_VNC
d62a17ae 4966 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4967 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4968 0);
4969 }
28070ee3
PZ
4970#endif
4971
d62a17ae 4972 bgp = peer->bgp;
4973
4974 /* Lookup node. */
9bcb3eef 4975 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4976
4977 /* If peer is soft reconfiguration enabled. Record input packet for
4978 * further calculation.
4979 *
4980 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4981 * routes that are filtered. This tanks out Quagga RS pretty badly due
4982 * to
4983 * the iteration over all RS clients.
4984 * Since we need to remove the entry from adj_in anyway, do that first
4985 * and
4986 * if there was no entry, we don't need to do anything more.
4987 */
4988 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4989 && peer != bgp->peer_self)
9bcb3eef 4990 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4991 peer->stat_pfx_dup_withdraw++;
4992
d62a17ae 4993 if (bgp_debug_update(peer, p, NULL, 1)) {
4994 bgp_debug_rdpfxpath2str(
a4d82a8a 4995 afi, safi, prd, p, label, num_labels,
6c995628
AD
4996 addpath_id ? 1 : 0, addpath_id, NULL,
4997 pfx_buf, sizeof(pfx_buf));
d62a17ae 4998 zlog_debug(
4999 "%s withdrawing route %s not in adj-in",
5000 peer->host, pfx_buf);
5001 }
9bcb3eef 5002 bgp_dest_unlock_node(dest);
367b458c 5003 return;
d62a17ae 5004 }
cd808e74 5005
d62a17ae 5006 /* Lookup withdrawn route. */
9bcb3eef 5007 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5008 if (pi->peer == peer && pi->type == type
5009 && pi->sub_type == sub_type
5010 && pi->addpath_rx_id == addpath_id)
d62a17ae 5011 break;
5012
5013 /* Logging. */
5014 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5015 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5016 addpath_id ? 1 : 0, addpath_id, NULL,
5017 pfx_buf, sizeof(pfx_buf));
f70c91dc 5018 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 5019 pfx_buf);
5020 }
718e3744 5021
d62a17ae 5022 /* Withdraw specified route from routing table. */
40381db7 5023 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5024 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5025 if (SAFI_UNICAST == safi
5026 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5027 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5028 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5029 }
5030 if ((SAFI_MPLS_VPN == safi)
5031 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5032
1aa2c93e 5033 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
5034 }
5035 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5036 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5037 addpath_id ? 1 : 0, addpath_id, NULL,
5038 pfx_buf, sizeof(pfx_buf));
d62a17ae 5039 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5040 }
718e3744 5041
d62a17ae 5042 /* Unlock bgp_node_get() lock. */
9bcb3eef 5043 bgp_dest_unlock_node(dest);
d62a17ae 5044
367b458c 5045 return;
718e3744 5046}
6b0655a2 5047
d62a17ae 5048void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5049 int withdraw)
718e3744 5050{
d62a17ae 5051 struct update_subgroup *subgrp;
5052 subgrp = peer_subgroup(peer, afi, safi);
5053 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5054}
6182d65b 5055
718e3744 5056
3f9c7369
DS
5057/*
5058 * bgp_stop_announce_route_timer
5059 */
d62a17ae 5060void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5061{
d62a17ae 5062 if (!paf->t_announce_route)
5063 return;
5064
e16d030c 5065 EVENT_OFF(paf->t_announce_route);
718e3744 5066}
6b0655a2 5067
3f9c7369
DS
5068/*
5069 * bgp_announce_route_timer_expired
5070 *
5071 * Callback that is invoked when the route announcement timer for a
5072 * peer_af expires.
5073 */
e6685141 5074static void bgp_announce_route_timer_expired(struct event *t)
718e3744 5075{
d62a17ae 5076 struct peer_af *paf;
5077 struct peer *peer;
558d1fec 5078
e16d030c 5079 paf = EVENT_ARG(t);
d62a17ae 5080 peer = paf->peer;
718e3744 5081
feb17238 5082 if (!peer_established(peer))
cc9f21da 5083 return;
3f9c7369 5084
d62a17ae 5085 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5086 return;
3f9c7369 5087
d62a17ae 5088 peer_af_announce_route(paf, 1);
c5aec50b
MK
5089
5090 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5091 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5092}
5093
3f9c7369
DS
5094/*
5095 * bgp_announce_route
5096 *
5097 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5098 *
5099 * if force is true we will force an update even if the update
5100 * limiting code is attempted to kick in.
3f9c7369 5101 */
e1a32ec1 5102void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5103{
5104 struct peer_af *paf;
5105 struct update_subgroup *subgrp;
5106
5107 paf = peer_af_find(peer, afi, safi);
5108 if (!paf)
5109 return;
5110 subgrp = PAF_SUBGRP(paf);
5111
5112 /*
5113 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5114 * or a refresh has already been triggered.
5115 */
5116 if (!subgrp || paf->t_announce_route)
5117 return;
5118
e1a32ec1
DS
5119 if (force)
5120 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5121
d62a17ae 5122 /*
5123 * Start a timer to stagger/delay the announce. This serves
5124 * two purposes - announcement can potentially be combined for
5125 * multiple peers and the announcement doesn't happen in the
5126 * vty context.
5127 */
907a2395
DS
5128 event_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5129 (subgrp->peer_count == 1)
5130 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5131 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5132 &paf->t_announce_route);
3f9c7369
DS
5133}
5134
5135/*
5136 * Announce routes from all AF tables to a peer.
5137 *
5138 * This should ONLY be called when there is a need to refresh the
5139 * routes to the peer based on a policy change for this peer alone
5140 * or a route refresh request received from the peer.
5141 * The operation will result in splitting the peer from its existing
5142 * subgroups and putting it in new subgroups.
5143 */
d62a17ae 5144void bgp_announce_route_all(struct peer *peer)
718e3744 5145{
d62a17ae 5146 afi_t afi;
5147 safi_t safi;
5148
05c7a1cc 5149 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5150 bgp_announce_route(peer, afi, safi, false);
718e3744 5151}
6b0655a2 5152
46aeabed
LS
5153/* Flag or unflag bgp_dest to determine whether it should be treated by
5154 * bgp_soft_reconfig_table_task.
5155 * Flag if flag is true. Unflag if flag is false.
5156 */
5157static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5158{
5159 struct bgp_dest *dest;
5160 struct bgp_adj_in *ain;
5161
5162 if (!table)
5163 return;
5164
5165 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5166 for (ain = dest->adj_in; ain; ain = ain->next) {
5167 if (ain->peer != NULL)
5168 break;
5169 }
5170 if (flag && ain != NULL && ain->peer != NULL)
5171 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5172 else
5173 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5174 }
5175}
5176
367b458c
DS
5177static void bgp_soft_reconfig_table_update(struct peer *peer,
5178 struct bgp_dest *dest,
5179 struct bgp_adj_in *ain, afi_t afi,
5180 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5181{
5182 struct bgp_path_info *pi;
5183 uint32_t num_labels = 0;
5184 mpls_label_t *label_pnt = NULL;
5185 struct bgp_route_evpn evpn;
5186
5187 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5188 if (pi->peer == peer)
5189 break;
5190
5191 if (pi && pi->extra)
5192 num_labels = pi->extra->num_labels;
5193 if (num_labels)
5194 label_pnt = &pi->extra->label[0];
5195 if (pi)
5196 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5197 sizeof(evpn));
5198 else
5199 memset(&evpn, 0, sizeof(evpn));
5200
367b458c
DS
5201 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5202 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5203 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5204}
5205
d62a17ae 5206static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5207 struct bgp_table *table,
5208 struct prefix_rd *prd)
718e3744 5209{
9bcb3eef 5210 struct bgp_dest *dest;
d62a17ae 5211 struct bgp_adj_in *ain;
718e3744 5212
d62a17ae 5213 if (!table)
5214 table = peer->bgp->rib[afi][safi];
718e3744 5215
9bcb3eef
DS
5216 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5217 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5218 if (ain->peer != peer)
5219 continue;
8692c506 5220
367b458c
DS
5221 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5222 safi, prd);
d62a17ae 5223 }
718e3744 5224}
5225
46aeabed
LS
5226/* Do soft reconfig table per bgp table.
5227 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5228 * when BGP_NODE_SOFT_RECONFIG is set,
5229 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5230 * Schedule a new thread to continue the job.
5231 * Without splitting the full job into several part,
5232 * vtysh waits for the job to finish before responding to a BGP command
5233 */
e6685141 5234static void bgp_soft_reconfig_table_task(struct event *thread)
46aeabed
LS
5235{
5236 uint32_t iter, max_iter;
46aeabed
LS
5237 struct bgp_dest *dest;
5238 struct bgp_adj_in *ain;
5239 struct peer *peer;
5240 struct bgp_table *table;
5241 struct prefix_rd *prd;
5242 struct listnode *node, *nnode;
5243
e16d030c 5244 table = EVENT_ARG(thread);
46aeabed
LS
5245 prd = NULL;
5246
5247 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5248 if (table->soft_reconfig_init) {
5249 /* first call of the function with a new srta structure.
5250 * Don't do any treatment this time on nodes
5251 * in order vtysh to respond quickly
5252 */
5253 max_iter = 0;
5254 }
5255
5256 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5257 dest = bgp_route_next(dest)) {
5258 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5259 continue;
5260
5261 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5262
5263 for (ain = dest->adj_in; ain; ain = ain->next) {
5264 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5265 nnode, peer)) {
5266 if (ain->peer != peer)
5267 continue;
5268
367b458c 5269 bgp_soft_reconfig_table_update(
46aeabed
LS
5270 peer, dest, ain, table->afi,
5271 table->safi, prd);
5272 iter++;
46aeabed
LS
5273 }
5274 }
5275 }
5276
5277 /* we're either starting the initial iteration,
5278 * or we're going to continue an ongoing iteration
5279 */
5280 if (dest || table->soft_reconfig_init) {
5281 table->soft_reconfig_init = false;
907a2395
DS
5282 event_add_event(bm->master, bgp_soft_reconfig_table_task, table,
5283 0, &table->soft_reconfig_thread);
cc9f21da 5284 return;
46aeabed
LS
5285 }
5286 /* we're done, clean up the background iteration context info and
5287 schedule route annoucement
5288 */
5289 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5290 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5291 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5292 }
5293
5294 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5295}
5296
5297
5298/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5299 * and peer.
5300 * - bgp cannot be NULL
5301 * - if table and peer are NULL, cancel all threads within the bgp instance
5302 * - if table is NULL and peer is not,
5303 * remove peer in all threads within the bgp instance
5304 * - if peer is NULL, cancel all threads matching table within the bgp instance
5305 */
5306void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5307 const struct bgp_table *table,
5308 const struct peer *peer)
5309{
5310 struct peer *npeer;
5311 struct listnode *node, *nnode;
5312 int afi, safi;
5313 struct bgp_table *ntable;
5314
5315 if (!bgp)
5316 return;
5317
5318 FOREACH_AFI_SAFI (afi, safi) {
5319 ntable = bgp->rib[afi][safi];
5320 if (!ntable)
5321 continue;
5322 if (table && table != ntable)
5323 continue;
5324
5325 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5326 npeer)) {
5327 if (peer && peer != npeer)
5328 continue;
5329 listnode_delete(ntable->soft_reconfig_peers, npeer);
5330 }
5331
5332 if (!ntable->soft_reconfig_peers
5333 || !list_isempty(ntable->soft_reconfig_peers))
5334 continue;
5335
5336 list_delete(&ntable->soft_reconfig_peers);
5337 bgp_soft_reconfig_table_flag(ntable, false);
e16d030c 5338 EVENT_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5339 }
5340}
5341
89c73443
DS
5342/*
5343 * Returns false if the peer is not configured for soft reconfig in
5344 */
5345bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5346{
9bcb3eef 5347 struct bgp_dest *dest;
d62a17ae 5348 struct bgp_table *table;
46aeabed
LS
5349 struct listnode *node, *nnode;
5350 struct peer *npeer;
5351 struct peer_af *paf;
718e3744 5352
89c73443
DS
5353 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5354 return false;
718e3744 5355
d62a17ae 5356 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5357 && (safi != SAFI_EVPN)) {
5358 table = peer->bgp->rib[afi][safi];
5359 if (!table)
89c73443 5360 return true;
46aeabed
LS
5361
5362 table->soft_reconfig_init = true;
5363
5364 if (!table->soft_reconfig_peers)
5365 table->soft_reconfig_peers = list_new();
5366 npeer = NULL;
5367 /* add peer to the table soft_reconfig_peers if not already
5368 * there
5369 */
5370 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5371 npeer)) {
5372 if (peer == npeer)
5373 break;
5374 }
5375 if (peer != npeer)
5376 listnode_add(table->soft_reconfig_peers, peer);
5377
5378 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5379 * on table would start back at the beginning.
5380 */
5381 bgp_soft_reconfig_table_flag(table, true);
5382
5383 if (!table->soft_reconfig_thread)
907a2395
DS
5384 event_add_event(bm->master,
5385 bgp_soft_reconfig_table_task, table, 0,
5386 &table->soft_reconfig_thread);
46aeabed
LS
5387 /* Cancel bgp_announce_route_timer_expired threads.
5388 * bgp_announce_route_timer_expired threads have been scheduled
5389 * to announce routes as soon as the soft_reconfigure process
5390 * finishes.
5391 * In this case, soft_reconfigure is also scheduled by using
5392 * a thread but is planned after the
5393 * bgp_announce_route_timer_expired threads. It means that,
5394 * without cancelling the threads, the route announcement task
5395 * would run before the soft reconfiguration one. That would
5396 * useless and would block vtysh during several seconds. Route
5397 * announcements are rescheduled as soon as the soft_reconfigure
5398 * process finishes.
5399 */
5400 paf = peer_af_find(peer, afi, safi);
5401 if (paf)
5402 bgp_stop_announce_route_timer(paf);
5403 } else
9bcb3eef
DS
5404 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5405 dest = bgp_route_next(dest)) {
5406 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5407
b54892e0
DS
5408 if (table == NULL)
5409 continue;
8692c506 5410
9bcb3eef 5411 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5412 struct prefix_rd prd;
5413
5414 prd.family = AF_UNSPEC;
5415 prd.prefixlen = 64;
5416 memcpy(&prd.val, p->u.val, 8);
5417
5418 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5419 }
89c73443
DS
5420
5421 return true;
718e3744 5422}
6b0655a2 5423
228da428 5424
d62a17ae 5425struct bgp_clear_node_queue {
9bcb3eef 5426 struct bgp_dest *dest;
228da428
CC
5427};
5428
d62a17ae 5429static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5430{
d62a17ae 5431 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5432 struct bgp_dest *dest = cnq->dest;
d62a17ae 5433 struct peer *peer = wq->spec.data;
40381db7 5434 struct bgp_path_info *pi;
3103e8d2 5435 struct bgp *bgp;
9bcb3eef
DS
5436 afi_t afi = bgp_dest_table(dest)->afi;
5437 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5438
9bcb3eef 5439 assert(dest && peer);
3103e8d2 5440 bgp = peer->bgp;
d62a17ae 5441
5442 /* It is possible that we have multiple paths for a prefix from a peer
5443 * if that peer is using AddPath.
5444 */
9bcb3eef 5445 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5446 if (pi->peer != peer)
ea47320b
DL
5447 continue;
5448
5449 /* graceful restart STALE flag set. */
9af52ccf
DA
5450 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5451 && peer->nsf[afi][safi])
5452 || CHECK_FLAG(peer->af_sflags[afi][safi],
5453 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5454 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5455 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5456 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5457 else {
5458 /* If this is an EVPN route, process for
5459 * un-import. */
5460 if (safi == SAFI_EVPN)
9bcb3eef
DS
5461 bgp_evpn_unimport_route(
5462 bgp, afi, safi,
5463 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5464 /* Handle withdraw for VRF route-leaking and L3VPN */
5465 if (SAFI_UNICAST == safi
5466 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5467 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5468 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5469 bgp, pi);
960035b2 5470 }
3103e8d2 5471 if (SAFI_MPLS_VPN == safi &&
960035b2 5472 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5473 vpn_leak_to_vrf_withdraw(pi);
960035b2 5474 }
3103e8d2 5475
9bcb3eef 5476 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5477 }
ea47320b 5478 }
d62a17ae 5479 return WQ_SUCCESS;
200df115 5480}
5481
d62a17ae 5482static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5483{
d62a17ae 5484 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5485 struct bgp_dest *dest = cnq->dest;
5486 struct bgp_table *table = bgp_dest_table(dest);
228da428 5487
9bcb3eef 5488 bgp_dest_unlock_node(dest);
d62a17ae 5489 bgp_table_unlock(table);
5490 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5491}
5492
d62a17ae 5493static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5494{
d62a17ae 5495 struct peer *peer = wq->spec.data;
64e580a7 5496
d62a17ae 5497 /* Tickle FSM to start moving again */
5498 BGP_EVENT_ADD(peer, Clearing_Completed);
5499
5500 peer_unlock(peer); /* bgp_clear_route */
200df115 5501}
718e3744 5502
d62a17ae 5503static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5504{
d62a17ae 5505 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5506
5507 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5508#undef CLEAR_QUEUE_NAME_LEN
5509
0ce1ca80 5510 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5511 peer->clear_node_queue->spec.hold = 10;
5512 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5513 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5514 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5515 peer->clear_node_queue->spec.max_retries = 0;
5516
5517 /* we only 'lock' this peer reference when the queue is actually active
5518 */
5519 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5520}
5521
d62a17ae 5522static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5523 struct bgp_table *table)
65ca75e0 5524{
9bcb3eef 5525 struct bgp_dest *dest;
b6c386bb 5526 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5527
d62a17ae 5528 if (!table)
5529 table = peer->bgp->rib[afi][safi];
dc83d712 5530
d62a17ae 5531 /* If still no table => afi/safi isn't configured at all or smth. */
5532 if (!table)
5533 return;
dc83d712 5534
9bcb3eef 5535 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5536 struct bgp_path_info *pi, *next;
d62a17ae 5537 struct bgp_adj_in *ain;
5538 struct bgp_adj_in *ain_next;
5539
5540 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5541 * queued for every clearing peer, regardless of whether it is
5542 * relevant to the peer at hand.
5543 *
5544 * Overview: There are 3 different indices which need to be
5545 * scrubbed, potentially, when a peer is removed:
5546 *
5547 * 1 peer's routes visible via the RIB (ie accepted routes)
5548 * 2 peer's routes visible by the (optional) peer's adj-in index
5549 * 3 other routes visible by the peer's adj-out index
5550 *
5551 * 3 there is no hurry in scrubbing, once the struct peer is
5552 * removed from bgp->peer, we could just GC such deleted peer's
5553 * adj-outs at our leisure.
5554 *
5555 * 1 and 2 must be 'scrubbed' in some way, at least made
5556 * invisible via RIB index before peer session is allowed to be
5557 * brought back up. So one needs to know when such a 'search' is
5558 * complete.
5559 *
5560 * Ideally:
5561 *
5562 * - there'd be a single global queue or a single RIB walker
5563 * - rather than tracking which route_nodes still need to be
5564 * examined on a peer basis, we'd track which peers still
5565 * aren't cleared
5566 *
5567 * Given that our per-peer prefix-counts now should be reliable,
5568 * this may actually be achievable. It doesn't seem to be a huge
5569 * problem at this time,
5570 *
5571 * It is possible that we have multiple paths for a prefix from
5572 * a peer
5573 * if that peer is using AddPath.
5574 */
9bcb3eef 5575 ain = dest->adj_in;
d62a17ae 5576 while (ain) {
5577 ain_next = ain->next;
5578
6a840fd9 5579 if (ain->peer == peer)
9bcb3eef 5580 bgp_adj_in_remove(dest, ain);
d62a17ae 5581
5582 ain = ain_next;
5583 }
5584
9bcb3eef 5585 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5586 next = pi->next;
5587 if (pi->peer != peer)
d62a17ae 5588 continue;
5589
5590 if (force)
9bcb3eef 5591 bgp_path_info_reap(dest, pi);
d62a17ae 5592 else {
5593 struct bgp_clear_node_queue *cnq;
5594
5595 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5596 bgp_table_lock(bgp_dest_table(dest));
5597 bgp_dest_lock_node(dest);
d62a17ae 5598 cnq = XCALLOC(
5599 MTYPE_BGP_CLEAR_NODE_QUEUE,
5600 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5601 cnq->dest = dest;
d62a17ae 5602 work_queue_add(peer->clear_node_queue, cnq);
5603 break;
5604 }
5605 }
5606 }
5607 return;
5608}
5609
5610void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5611{
9bcb3eef 5612 struct bgp_dest *dest;
d62a17ae 5613 struct bgp_table *table;
5614
5615 if (peer->clear_node_queue == NULL)
5616 bgp_clear_node_queue_init(peer);
5617
5618 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5619 * Idle until it receives a Clearing_Completed event. This protects
5620 * against peers which flap faster than we can we clear, which could
5621 * lead to:
5622 *
5623 * a) race with routes from the new session being installed before
5624 * clear_route_node visits the node (to delete the route of that
5625 * peer)
5626 * b) resource exhaustion, clear_route_node likely leads to an entry
5627 * on the process_main queue. Fast-flapping could cause that queue
5628 * to grow and grow.
5629 */
5630
5631 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5632 * the unlock will happen upon work-queue completion; other wise, the
5633 * unlock happens at the end of this function.
5634 */
5635 if (!peer->clear_node_queue->thread)
5636 peer_lock(peer);
5637
5638 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5639 bgp_clear_route_table(peer, afi, safi, NULL);
5640 else
9bcb3eef
DS
5641 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5642 dest = bgp_route_next(dest)) {
5643 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5644 if (!table)
5645 continue;
5646
5647 bgp_clear_route_table(peer, afi, safi, table);
5648 }
d62a17ae 5649
5650 /* unlock if no nodes got added to the clear-node-queue. */
5651 if (!peer->clear_node_queue->thread)
5652 peer_unlock(peer);
718e3744 5653}
d62a17ae 5654
5655void bgp_clear_route_all(struct peer *peer)
718e3744 5656{
d62a17ae 5657 afi_t afi;
5658 safi_t safi;
718e3744 5659
05c7a1cc
QY
5660 FOREACH_AFI_SAFI (afi, safi)
5661 bgp_clear_route(peer, afi, safi);
65efcfce 5662
49e5a4a0 5663#ifdef ENABLE_BGP_VNC
d62a17ae 5664 rfapiProcessPeerDown(peer);
65efcfce 5665#endif
718e3744 5666}
5667
d62a17ae 5668void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5669{
d62a17ae 5670 struct bgp_table *table;
9bcb3eef 5671 struct bgp_dest *dest;
d62a17ae 5672 struct bgp_adj_in *ain;
5673 struct bgp_adj_in *ain_next;
718e3744 5674
d62a17ae 5675 table = peer->bgp->rib[afi][safi];
718e3744 5676
d62a17ae 5677 /* It is possible that we have multiple paths for a prefix from a peer
5678 * if that peer is using AddPath.
5679 */
9bcb3eef
DS
5680 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5681 ain = dest->adj_in;
43143c8f 5682
d62a17ae 5683 while (ain) {
5684 ain_next = ain->next;
43143c8f 5685
6a840fd9 5686 if (ain->peer == peer)
9bcb3eef 5687 bgp_adj_in_remove(dest, ain);
43143c8f 5688
d62a17ae 5689 ain = ain_next;
5690 }
5691 }
718e3744 5692}
93406d87 5693
1479ed2f
DA
5694/* If any of the routes from the peer have been marked with the NO_LLGR
5695 * community, either as sent by the peer, or as the result of a configured
5696 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5697 * operation of [RFC4271].
5698 */
d62a17ae 5699void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5700{
9bcb3eef 5701 struct bgp_dest *dest;
40381db7 5702 struct bgp_path_info *pi;
d62a17ae 5703 struct bgp_table *table;
5704
9af52ccf 5705 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5706 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5707 dest = bgp_route_next(dest)) {
5708 struct bgp_dest *rm;
d62a17ae 5709
5710 /* look for neighbor in tables */
9bcb3eef 5711 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5712 if (!table)
ea47320b
DL
5713 continue;
5714
5715 for (rm = bgp_table_top(table); rm;
5716 rm = bgp_route_next(rm))
9bcb3eef 5717 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5718 pi = pi->next) {
40381db7 5719 if (pi->peer != peer)
ea47320b 5720 continue;
1479ed2f
DA
5721 if (CHECK_FLAG(
5722 peer->af_sflags[afi][safi],
5723 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5724 bgp_attr_get_community(pi->attr) &&
1479ed2f 5725 !community_include(
9a706b42
DA
5726 bgp_attr_get_community(
5727 pi->attr),
1479ed2f 5728 COMMUNITY_NO_LLGR))
e3015d91 5729 continue;
40381db7 5730 if (!CHECK_FLAG(pi->flags,
1defdda8 5731 BGP_PATH_STALE))
e3015d91 5732 continue;
ea47320b 5733
641065d4
KM
5734 /*
5735 * If this is VRF leaked route
5736 * process for withdraw.
5737 */
5738 if (pi->sub_type ==
5739 BGP_ROUTE_IMPORTED &&
5740 peer->bgp->inst_type ==
5741 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5742 vpn_leak_to_vrf_withdraw(pi);
641065d4 5743
40381db7 5744 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5745 break;
5746 }
d62a17ae 5747 }
5748 } else {
9bcb3eef
DS
5749 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5750 dest = bgp_route_next(dest))
5751 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5752 pi = pi->next) {
40381db7 5753 if (pi->peer != peer)
ea47320b 5754 continue;
1479ed2f
DA
5755 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5756 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5757 bgp_attr_get_community(pi->attr) &&
5758 !community_include(
5759 bgp_attr_get_community(pi->attr),
5760 COMMUNITY_NO_LLGR))
e3015d91 5761 continue;
40381db7 5762 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5763 continue;
641065d4
KM
5764 if (safi == SAFI_UNICAST &&
5765 (peer->bgp->inst_type ==
5766 BGP_INSTANCE_TYPE_VRF ||
5767 peer->bgp->inst_type ==
5768 BGP_INSTANCE_TYPE_DEFAULT))
5769 vpn_leak_from_vrf_withdraw(
5770 bgp_get_default(), peer->bgp,
5771 pi);
5772
9bcb3eef 5773 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5774 break;
5775 }
d62a17ae 5776 }
93406d87 5777}
6b0655a2 5778
9af52ccf
DA
5779void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5780{
5781 struct bgp_dest *dest, *ndest;
5782 struct bgp_path_info *pi;
5783 struct bgp_table *table;
5784
5785 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5786 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5787 dest = bgp_route_next(dest)) {
5788 table = bgp_dest_get_bgp_table_info(dest);
5789 if (!table)
5790 continue;
5791
5792 for (ndest = bgp_table_top(table); ndest;
5793 ndest = bgp_route_next(ndest)) {
5794 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5795 pi = pi->next) {
5796 if (pi->peer != peer)
5797 continue;
5798
5799 if ((CHECK_FLAG(
5800 peer->af_sflags[afi][safi],
5801 PEER_STATUS_ENHANCED_REFRESH))
5802 && !CHECK_FLAG(pi->flags,
5803 BGP_PATH_STALE)
5804 && !CHECK_FLAG(
5805 pi->flags,
5806 BGP_PATH_UNUSEABLE)) {
5807 if (bgp_debug_neighbor_events(
5808 peer))
5809 zlog_debug(
58e111f6
DA
5810 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5811 peer,
9af52ccf
DA
5812 afi2str(afi),
5813 safi2str(safi),
5814 bgp_dest_get_prefix(
5815 ndest));
5816
5817 bgp_path_info_set_flag(
5818 ndest, pi,
5819 BGP_PATH_STALE);
5820 }
5821 }
5822 }
5823 }
5824 } else {
5825 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5826 dest = bgp_route_next(dest)) {
5827 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5828 pi = pi->next) {
5829 if (pi->peer != peer)
5830 continue;
5831
5832 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5833 PEER_STATUS_ENHANCED_REFRESH))
5834 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5835 && !CHECK_FLAG(pi->flags,
5836 BGP_PATH_UNUSEABLE)) {
5837 if (bgp_debug_neighbor_events(peer))
5838 zlog_debug(
58e111f6
DA
5839 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5840 peer, afi2str(afi),
9af52ccf
DA
5841 safi2str(safi),
5842 bgp_dest_get_prefix(
5843 dest));
5844
5845 bgp_path_info_set_flag(dest, pi,
5846 BGP_PATH_STALE);
5847 }
5848 }
5849 }
5850 }
5851}
5852
3dc339cd 5853bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5854{
e0df4c04 5855 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5856 return true;
e0df4c04 5857
9dac9fc8
DA
5858 if (peer->sort == BGP_PEER_EBGP
5859 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5860 || FILTER_LIST_OUT_NAME(filter)
5861 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5862 return true;
5863 return false;
9dac9fc8
DA
5864}
5865
3dc339cd 5866bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5867{
e0df4c04 5868 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5869 return true;
e0df4c04 5870
9dac9fc8
DA
5871 if (peer->sort == BGP_PEER_EBGP
5872 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5873 || FILTER_LIST_IN_NAME(filter)
5874 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5875 return true;
5876 return false;
9dac9fc8
DA
5877}
5878
568e10ca 5879static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5880 safi_t safi)
bb86c601 5881{
9bcb3eef 5882 struct bgp_dest *dest;
40381db7 5883 struct bgp_path_info *pi;
4b7e6066 5884 struct bgp_path_info *next;
bb86c601 5885
9bcb3eef
DS
5886 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5887 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5888 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5889
40381db7 5890 next = pi->next;
1b7bb747
CS
5891
5892 /* Unimport EVPN routes from VRFs */
5893 if (safi == SAFI_EVPN)
5894 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5895 SAFI_EVPN, p, pi);
1b7bb747 5896
40381db7
DS
5897 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5898 && pi->type == ZEBRA_ROUTE_BGP
5899 && (pi->sub_type == BGP_ROUTE_NORMAL
5900 || pi->sub_type == BGP_ROUTE_AGGREGATE
5901 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5902
d62a17ae 5903 if (bgp_fibupd_safi(safi))
b54892e0 5904 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5905 }
9514b37d 5906
9bcb3eef 5907 bgp_path_info_reap(dest, pi);
d62a17ae 5908 }
bb86c601
LB
5909}
5910
718e3744 5911/* Delete all kernel routes. */
d62a17ae 5912void bgp_cleanup_routes(struct bgp *bgp)
5913{
5914 afi_t afi;
9bcb3eef 5915 struct bgp_dest *dest;
67009e22 5916 struct bgp_table *table;
d62a17ae 5917
5918 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5919 if (afi == AFI_L2VPN)
5920 continue;
568e10ca 5921 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5922 SAFI_UNICAST);
d62a17ae 5923 /*
5924 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5925 */
5926 if (afi != AFI_L2VPN) {
5927 safi_t safi;
5928 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5929 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5930 dest = bgp_route_next(dest)) {
5931 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5932 if (table != NULL) {
5933 bgp_cleanup_table(bgp, table, safi);
5934 bgp_table_finish(&table);
9bcb3eef
DS
5935 bgp_dest_set_bgp_table_info(dest, NULL);
5936 bgp_dest_unlock_node(dest);
d62a17ae 5937 }
5938 }
5939 safi = SAFI_ENCAP;
9bcb3eef
DS
5940 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5941 dest = bgp_route_next(dest)) {
5942 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5943 if (table != NULL) {
5944 bgp_cleanup_table(bgp, table, safi);
5945 bgp_table_finish(&table);
9bcb3eef
DS
5946 bgp_dest_set_bgp_table_info(dest, NULL);
5947 bgp_dest_unlock_node(dest);
d62a17ae 5948 }
5949 }
5950 }
5951 }
9bcb3eef
DS
5952 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5953 dest = bgp_route_next(dest)) {
5954 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5955 if (table != NULL) {
5956 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5957 bgp_table_finish(&table);
9bcb3eef
DS
5958 bgp_dest_set_bgp_table_info(dest, NULL);
5959 bgp_dest_unlock_node(dest);
d62a17ae 5960 }
bb86c601 5961 }
718e3744 5962}
5963
d62a17ae 5964void bgp_reset(void)
718e3744 5965{
d62a17ae 5966 vty_reset();
5967 bgp_zclient_reset();
5968 access_list_reset();
5969 prefix_list_reset();
718e3744 5970}
6b0655a2 5971
be92fc9f 5972bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5973{
d62a17ae 5974 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5975 && CHECK_FLAG(peer->af_cap[afi][safi],
5976 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5977}
5978
718e3744 5979/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5980 value. */
d62a17ae 5981int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5982 struct bgp_nlri *packet)
5983{
d7c0a89a
QY
5984 uint8_t *pnt;
5985 uint8_t *lim;
d62a17ae 5986 struct prefix p;
5987 int psize;
d62a17ae 5988 afi_t afi;
5989 safi_t safi;
be92fc9f 5990 bool addpath_capable;
d7c0a89a 5991 uint32_t addpath_id;
d62a17ae 5992
d62a17ae 5993 pnt = packet->nlri;
5994 lim = pnt + packet->length;
5995 afi = packet->afi;
5996 safi = packet->safi;
5997 addpath_id = 0;
be92fc9f 5998 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5999
6000 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6001 syntactic validity. If the field is syntactically incorrect,
6002 then the Error Subcode is set to Invalid Network Field. */
6003 for (; pnt < lim; pnt += psize) {
6004 /* Clear prefix structure. */
6006b807 6005 memset(&p, 0, sizeof(p));
d62a17ae 6006
be92fc9f 6007 if (addpath_capable) {
d62a17ae 6008
6009 /* When packet overflow occurs return immediately. */
761ed665 6010 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6011 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6012
a3a850a1 6013 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6014 addpath_id = ntohl(addpath_id);
d62a17ae 6015 pnt += BGP_ADDPATH_ID_LEN;
6016 }
718e3744 6017
d62a17ae 6018 /* Fetch prefix length. */
6019 p.prefixlen = *pnt++;
6020 /* afi/safi validity already verified by caller,
6021 * bgp_update_receive */
6022 p.family = afi2family(afi);
6023
6024 /* Prefix length check. */
6025 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6026 flog_err(
e50f7cfd 6027 EC_BGP_UPDATE_RCV,
14454c9f 6028 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6029 peer->host, p.prefixlen, packet->afi);
513386b5 6030 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6031 }
6b0655a2 6032
d62a17ae 6033 /* Packet size overflow check. */
6034 psize = PSIZE(p.prefixlen);
6035
6036 /* When packet overflow occur return immediately. */
6037 if (pnt + psize > lim) {
af4c2728 6038 flog_err(
e50f7cfd 6039 EC_BGP_UPDATE_RCV,
d62a17ae 6040 "%s [Error] Update packet error (prefix length %d overflows packet)",
6041 peer->host, p.prefixlen);
513386b5 6042 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6043 }
6044
6045 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6046 * prefix for the v4 and v6 afi's and unicast/multicast */
6047 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6048 flog_err(
e50f7cfd 6049 EC_BGP_UPDATE_RCV,
d62a17ae 6050 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6051 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6052 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6053 }
6054
6055 /* Fetch prefix from NLRI packet. */
a85297a7 6056 memcpy(p.u.val, pnt, psize);
d62a17ae 6057
6058 /* Check address. */
6059 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6060 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6061 /* From RFC4271 Section 6.3:
6062 *
6063 * If a prefix in the NLRI field is semantically
6064 * incorrect
6065 * (e.g., an unexpected multicast IP address),
6066 * an error SHOULD
6067 * be logged locally, and the prefix SHOULD be
6068 * ignored.
a4d82a8a 6069 */
af4c2728 6070 flog_err(
e50f7cfd 6071 EC_BGP_UPDATE_RCV,
23d0a753
DA
6072 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6073 peer->host, &p.u.prefix4);
d62a17ae 6074 continue;
6075 }
6076 }
6077
6078 /* Check address. */
6079 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6080 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6081 flog_err(
e50f7cfd 6082 EC_BGP_UPDATE_RCV,
c0d72166
DS
6083 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6084 peer->host, &p.u.prefix6);
d62a17ae 6085
6086 continue;
6087 }
6088 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6089 flog_err(
e50f7cfd 6090 EC_BGP_UPDATE_RCV,
c0d72166
DS
6091 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6092 peer->host, &p.u.prefix6);
d62a17ae 6093
6094 continue;
6095 }
6096 }
6097
6098 /* Normal process. */
6099 if (attr)
367b458c
DS
6100 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6101 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6102 NULL, 0, 0, NULL);
d62a17ae 6103 else
bf0c6163 6104 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6105 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6106 NULL, 0, NULL);
d62a17ae 6107
513386b5
DA
6108 /* Do not send BGP notification twice when maximum-prefix count
6109 * overflow. */
6110 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6111 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6112 }
6113
6114 /* Packet length consistency check. */
6115 if (pnt != lim) {
af4c2728 6116 flog_err(
e50f7cfd 6117 EC_BGP_UPDATE_RCV,
d62a17ae 6118 "%s [Error] Update packet error (prefix length mismatch with total length)",
6119 peer->host);
513386b5 6120 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6121 }
6b0655a2 6122
513386b5 6123 return BGP_NLRI_PARSE_OK;
718e3744 6124}
6125
d62a17ae 6126static struct bgp_static *bgp_static_new(void)
718e3744 6127{
d62a17ae 6128 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6129}
6130
d62a17ae 6131static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6132{
0a22ddfb 6133 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6134 route_map_counter_decrement(bgp_static->rmap.map);
6135
c1aa9e7f
PG
6136 if (bgp_static->prd_pretty)
6137 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6138 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6139 XFREE(MTYPE_BGP_STATIC, bgp_static);
6140}
6141
5f040085 6142void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6143 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6144{
9bcb3eef 6145 struct bgp_dest *dest;
40381db7 6146 struct bgp_path_info *pi;
4b7e6066 6147 struct bgp_path_info *new;
40381db7 6148 struct bgp_path_info rmap_path;
d62a17ae 6149 struct attr attr;
6150 struct attr *attr_new;
b68885f9 6151 route_map_result_t ret;
49e5a4a0 6152#ifdef ENABLE_BGP_VNC
d62a17ae 6153 int vnc_implicit_withdraw = 0;
65efcfce 6154#endif
fee0f4c6 6155
d62a17ae 6156 assert(bgp_static);
dd8103a9 6157
9bcb3eef 6158 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6159
0f05ea43 6160 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6161
d62a17ae 6162 attr.nexthop = bgp_static->igpnexthop;
6163 attr.med = bgp_static->igpmetric;
6164 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6165
7226bc40
TA
6166 if (afi == AFI_IP)
6167 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6168
97a52c82
DA
6169 if (bgp_static->igpmetric)
6170 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6171
d62a17ae 6172 if (bgp_static->atomic)
6173 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6174
d62a17ae 6175 /* Store label index, if required. */
6176 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6177 attr.label_index = bgp_static->label_index;
6178 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6179 }
718e3744 6180
d62a17ae 6181 /* Apply route-map. */
6182 if (bgp_static->rmap.name) {
6183 struct attr attr_tmp = attr;
80ced710 6184
6006b807 6185 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6186 rmap_path.peer = bgp->peer_self;
6187 rmap_path.attr = &attr_tmp;
fee0f4c6 6188
d62a17ae 6189 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6190
1782514f 6191 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6192
d62a17ae 6193 bgp->peer_self->rmap_type = 0;
718e3744 6194
d62a17ae 6195 if (ret == RMAP_DENYMATCH) {
6196 /* Free uninterned attribute. */
6197 bgp_attr_flush(&attr_tmp);
718e3744 6198
d62a17ae 6199 /* Unintern original. */
6200 aspath_unintern(&attr.aspath);
6201 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6202 bgp_dest_unlock_node(dest);
d62a17ae 6203 return;
6204 }
7f323236 6205
637e5ba4 6206 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6207 bgp_attr_add_gshut_community(&attr_tmp);
6208
d62a17ae 6209 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6210 } else {
6211
637e5ba4 6212 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6213 bgp_attr_add_gshut_community(&attr);
6214
d62a17ae 6215 attr_new = bgp_attr_intern(&attr);
7f323236 6216 }
718e3744 6217
9bcb3eef 6218 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6219 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6220 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6221 break;
6222
40381db7
DS
6223 if (pi) {
6224 if (attrhash_cmp(pi->attr, attr_new)
6225 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6226 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6227 bgp_dest_unlock_node(dest);
d62a17ae 6228 bgp_attr_unintern(&attr_new);
6229 aspath_unintern(&attr.aspath);
6230 return;
6231 } else {
6232 /* The attribute is changed. */
9bcb3eef 6233 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6234
6235 /* Rewrite BGP route information. */
40381db7 6236 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6237 bgp_path_info_restore(dest, pi);
d62a17ae 6238 else
40381db7 6239 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6240#ifdef ENABLE_BGP_VNC
d62a17ae 6241 if ((afi == AFI_IP || afi == AFI_IP6)
6242 && (safi == SAFI_UNICAST)) {
40381db7 6243 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6244 /*
6245 * Implicit withdraw case.
40381db7 6246 * We have to do this before pi is
d62a17ae 6247 * changed
6248 */
6249 ++vnc_implicit_withdraw;
40381db7 6250 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6251 vnc_import_bgp_exterior_del_route(
40381db7 6252 bgp, p, pi);
d62a17ae 6253 }
6254 }
65efcfce 6255#endif
40381db7
DS
6256 bgp_attr_unintern(&pi->attr);
6257 pi->attr = attr_new;
083ec940 6258 pi->uptime = monotime(NULL);
49e5a4a0 6259#ifdef ENABLE_BGP_VNC
d62a17ae 6260 if ((afi == AFI_IP || afi == AFI_IP6)
6261 && (safi == SAFI_UNICAST)) {
6262 if (vnc_implicit_withdraw) {
40381db7 6263 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6264 vnc_import_bgp_exterior_add_route(
40381db7 6265 bgp, p, pi);
d62a17ae 6266 }
6267 }
65efcfce 6268#endif
718e3744 6269
d62a17ae 6270 /* Nexthop reachability check. */
892fedb6 6271 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6272 && (safi == SAFI_UNICAST
6273 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6274
6275 struct bgp *bgp_nexthop = bgp;
6276
40381db7
DS
6277 if (pi->extra && pi->extra->bgp_orig)
6278 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6279
6280 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6281 afi, safi, pi, NULL,
654a5978 6282 0, p))
9bcb3eef 6283 bgp_path_info_set_flag(dest, pi,
18ee8310 6284 BGP_PATH_VALID);
d62a17ae 6285 else {
6286 if (BGP_DEBUG(nht, NHT)) {
6287 char buf1[INET6_ADDRSTRLEN];
6288 inet_ntop(p->family,
6289 &p->u.prefix, buf1,
07380148 6290 sizeof(buf1));
d62a17ae 6291 zlog_debug(
6292 "%s(%s): Route not in table, not advertising",
15569c58 6293 __func__, buf1);
d62a17ae 6294 }
18ee8310 6295 bgp_path_info_unset_flag(
9bcb3eef 6296 dest, pi, BGP_PATH_VALID);
d62a17ae 6297 }
6298 } else {
6299 /* Delete the NHT structure if any, if we're
6300 * toggling between
6301 * enabling/disabling import check. We
6302 * deregister the route
6303 * from NHT to avoid overloading NHT and the
6304 * process interaction
6305 */
40381db7 6306 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6307 bgp_path_info_set_flag(dest, pi,
6308 BGP_PATH_VALID);
d62a17ae 6309 }
6310 /* Process change. */
40381db7 6311 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6312 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6313
6314 if (SAFI_UNICAST == safi
6315 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6316 || bgp->inst_type
6317 == BGP_INSTANCE_TYPE_DEFAULT)) {
6318 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6319 pi);
ddb5b488
PZ
6320 }
6321
9bcb3eef 6322 bgp_dest_unlock_node(dest);
d62a17ae 6323 aspath_unintern(&attr.aspath);
6324 return;
6325 }
718e3744 6326 }
718e3744 6327
d62a17ae 6328 /* Make new BGP info. */
6329 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6330 attr_new, dest);
d62a17ae 6331 /* Nexthop reachability check. */
892fedb6 6332 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6333 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6334 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6335 p))
9bcb3eef 6336 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6337 else {
6338 if (BGP_DEBUG(nht, NHT)) {
6339 char buf1[INET6_ADDRSTRLEN];
07380148 6340
d62a17ae 6341 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6342 sizeof(buf1));
d62a17ae 6343 zlog_debug(
6344 "%s(%s): Route not in table, not advertising",
15569c58 6345 __func__, buf1);
d62a17ae 6346 }
9bcb3eef 6347 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6348 }
6349 } else {
6350 /* Delete the NHT structure if any, if we're toggling between
6351 * enabling/disabling import check. We deregister the route
6352 * from NHT to avoid overloading NHT and the process interaction
6353 */
6354 bgp_unlink_nexthop(new);
6355
9bcb3eef 6356 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6357 }
078430f6 6358
d62a17ae 6359 /* Aggregate address increment. */
6360 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6361
d62a17ae 6362 /* Register new BGP information. */
9bcb3eef 6363 bgp_path_info_add(dest, new);
718e3744 6364
d62a17ae 6365 /* route_node_get lock */
9bcb3eef 6366 bgp_dest_unlock_node(dest);
d62a17ae 6367
6368 /* Process change. */
9bcb3eef 6369 bgp_process(bgp, dest, afi, safi);
d62a17ae 6370
ddb5b488
PZ
6371 if (SAFI_UNICAST == safi
6372 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6373 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6374 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6375 }
6376
d62a17ae 6377 /* Unintern original. */
6378 aspath_unintern(&attr.aspath);
718e3744 6379}
6380
5f040085 6381void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6382 safi_t safi)
718e3744 6383{
9bcb3eef 6384 struct bgp_dest *dest;
40381db7 6385 struct bgp_path_info *pi;
718e3744 6386
9bcb3eef 6387 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6388
d62a17ae 6389 /* Check selected route and self inserted route. */
9bcb3eef 6390 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6391 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6392 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6393 break;
6394
6395 /* Withdraw static BGP route from routing table. */
40381db7 6396 if (pi) {
ddb5b488
PZ
6397 if (SAFI_UNICAST == safi
6398 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6399 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6400 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6401 }
40381db7
DS
6402 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6403 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6404 bgp_path_info_delete(dest, pi);
6405 bgp_process(bgp, dest, afi, safi);
d62a17ae 6406 }
718e3744 6407
d62a17ae 6408 /* Unlock bgp_node_lookup. */
9bcb3eef 6409 bgp_dest_unlock_node(dest);
718e3744 6410}
6411
137446f9
LB
6412/*
6413 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6414 */
5f040085 6415static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6416 afi_t afi, safi_t safi,
6417 struct prefix_rd *prd)
718e3744 6418{
9bcb3eef 6419 struct bgp_dest *dest;
40381db7 6420 struct bgp_path_info *pi;
718e3744 6421
9bcb3eef 6422 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6423
d62a17ae 6424 /* Check selected route and self inserted route. */
9bcb3eef 6425 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6426 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6427 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6428 break;
718e3744 6429
d62a17ae 6430 /* Withdraw static BGP route from routing table. */
40381db7 6431 if (pi) {
49e5a4a0 6432#ifdef ENABLE_BGP_VNC
d62a17ae 6433 rfapiProcessWithdraw(
40381db7 6434 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6435 1); /* Kill, since it is an administrative change */
65efcfce 6436#endif
ddb5b488
PZ
6437 if (SAFI_MPLS_VPN == safi
6438 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6439 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6440 }
40381db7 6441 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6442 bgp_path_info_delete(dest, pi);
6443 bgp_process(bgp, dest, afi, safi);
d62a17ae 6444 }
718e3744 6445
d62a17ae 6446 /* Unlock bgp_node_lookup. */
9bcb3eef 6447 bgp_dest_unlock_node(dest);
718e3744 6448}
6449
5f040085 6450static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6451 struct bgp_static *bgp_static, afi_t afi,
6452 safi_t safi)
137446f9 6453{
9bcb3eef 6454 struct bgp_dest *dest;
4b7e6066 6455 struct bgp_path_info *new;
d62a17ae 6456 struct attr *attr_new;
6457 struct attr attr = {0};
40381db7 6458 struct bgp_path_info *pi;
49e5a4a0 6459#ifdef ENABLE_BGP_VNC
d62a17ae 6460 mpls_label_t label = 0;
65efcfce 6461#endif
d7c0a89a 6462 uint32_t num_labels = 0;
137446f9 6463
d62a17ae 6464 assert(bgp_static);
137446f9 6465
b57ba6d2
MK
6466 if (bgp_static->label != MPLS_INVALID_LABEL)
6467 num_labels = 1;
9bcb3eef
DS
6468 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6469 &bgp_static->prd);
137446f9 6470
0f05ea43 6471 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6472
d62a17ae 6473 attr.nexthop = bgp_static->igpnexthop;
6474 attr.med = bgp_static->igpmetric;
6475 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6476
d62a17ae 6477 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6478 || (safi == SAFI_ENCAP)) {
6479 if (afi == AFI_IP) {
6480 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6481 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6482 }
6483 }
6484 if (afi == AFI_L2VPN) {
b04c1e99
IR
6485 if (bgp_static->gatewayIp.family == AF_INET) {
6486 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6487 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6488 &bgp_static->gatewayIp.u.prefix4,
6489 IPV4_MAX_BYTELEN);
b04c1e99
IR
6490 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6491 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6492 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6493 &bgp_static->gatewayIp.u.prefix6,
6494 IPV6_MAX_BYTELEN);
b04c1e99 6495 }
0a50c248 6496 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6497 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6498 struct bgp_encap_type_vxlan bet;
6006b807 6499 memset(&bet, 0, sizeof(bet));
3714a385 6500 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6501 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6502 }
6503 if (bgp_static->router_mac) {
6504 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6505 }
6506 }
6507 /* Apply route-map. */
6508 if (bgp_static->rmap.name) {
6509 struct attr attr_tmp = attr;
40381db7 6510 struct bgp_path_info rmap_path;
b68885f9 6511 route_map_result_t ret;
137446f9 6512
40381db7
DS
6513 rmap_path.peer = bgp->peer_self;
6514 rmap_path.attr = &attr_tmp;
137446f9 6515
d62a17ae 6516 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6517
1782514f 6518 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6519
d62a17ae 6520 bgp->peer_self->rmap_type = 0;
137446f9 6521
d62a17ae 6522 if (ret == RMAP_DENYMATCH) {
6523 /* Free uninterned attribute. */
6524 bgp_attr_flush(&attr_tmp);
137446f9 6525
d62a17ae 6526 /* Unintern original. */
6527 aspath_unintern(&attr.aspath);
6528 bgp_static_withdraw_safi(bgp, p, afi, safi,
6529 &bgp_static->prd);
bbc52106 6530 bgp_dest_unlock_node(dest);
d62a17ae 6531 return;
6532 }
137446f9 6533
d62a17ae 6534 attr_new = bgp_attr_intern(&attr_tmp);
6535 } else {
6536 attr_new = bgp_attr_intern(&attr);
6537 }
137446f9 6538
9bcb3eef 6539 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6540 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6541 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6542 break;
6543
40381db7 6544 if (pi) {
40381db7 6545 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6546 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6547 bgp_dest_unlock_node(dest);
d62a17ae 6548 bgp_attr_unintern(&attr_new);
6549 aspath_unintern(&attr.aspath);
6550 return;
6551 } else {
6552 /* The attribute is changed. */
9bcb3eef 6553 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6554
6555 /* Rewrite BGP route information. */
40381db7 6556 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6557 bgp_path_info_restore(dest, pi);
d62a17ae 6558 else
40381db7
DS
6559 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6560 bgp_attr_unintern(&pi->attr);
6561 pi->attr = attr_new;
083ec940 6562 pi->uptime = monotime(NULL);
49e5a4a0 6563#ifdef ENABLE_BGP_VNC
40381db7
DS
6564 if (pi->extra)
6565 label = decode_label(&pi->extra->label[0]);
65efcfce 6566#endif
137446f9 6567
d62a17ae 6568 /* Process change. */
40381db7 6569 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6570 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6571
6572 if (SAFI_MPLS_VPN == safi
6573 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6574 vpn_leak_to_vrf_update(bgp, pi,
6575 &bgp_static->prd);
ddb5b488 6576 }
49e5a4a0 6577#ifdef ENABLE_BGP_VNC
40381db7
DS
6578 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6579 pi->attr, afi, safi, pi->type,
6580 pi->sub_type, &label);
65efcfce 6581#endif
9bcb3eef 6582 bgp_dest_unlock_node(dest);
d62a17ae 6583 aspath_unintern(&attr.aspath);
6584 return;
6585 }
6586 }
137446f9
LB
6587
6588
d62a17ae 6589 /* Make new BGP info. */
6590 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6591 attr_new, dest);
1defdda8 6592 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6593 bgp_path_info_extra_get(new);
b57ba6d2
MK
6594 if (num_labels) {
6595 new->extra->label[0] = bgp_static->label;
6596 new->extra->num_labels = num_labels;
6597 }
49e5a4a0 6598#ifdef ENABLE_BGP_VNC
d62a17ae 6599 label = decode_label(&bgp_static->label);
65efcfce 6600#endif
137446f9 6601
d62a17ae 6602 /* Aggregate address increment. */
6603 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6604
d62a17ae 6605 /* Register new BGP information. */
9bcb3eef 6606 bgp_path_info_add(dest, new);
d62a17ae 6607 /* route_node_get lock */
9bcb3eef 6608 bgp_dest_unlock_node(dest);
137446f9 6609
d62a17ae 6610 /* Process change. */
9bcb3eef 6611 bgp_process(bgp, dest, afi, safi);
137446f9 6612
ddb5b488
PZ
6613 if (SAFI_MPLS_VPN == safi
6614 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6615 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6616 }
49e5a4a0 6617#ifdef ENABLE_BGP_VNC
d62a17ae 6618 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6619 safi, new->type, new->sub_type, &label);
65efcfce
LB
6620#endif
6621
d62a17ae 6622 /* Unintern original. */
6623 aspath_unintern(&attr.aspath);
137446f9
LB
6624}
6625
718e3744 6626/* Configure static BGP network. When user don't run zebra, static
6627 route should be installed as valid. */
585f1adc
IR
6628static int bgp_static_set(struct vty *vty, const char *negate,
6629 const char *ip_str, afi_t afi, safi_t safi,
6630 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6631{
585f1adc
IR
6632 VTY_DECLVAR_CONTEXT(bgp, bgp);
6633 int ret;
d62a17ae 6634 struct prefix p;
6635 struct bgp_static *bgp_static;
9bcb3eef 6636 struct bgp_dest *dest;
d7c0a89a 6637 uint8_t need_update = 0;
d62a17ae 6638
585f1adc
IR
6639 /* Convert IP prefix string to struct prefix. */
6640 ret = str2prefix(ip_str, &p);
6641 if (!ret) {
6642 vty_out(vty, "%% Malformed prefix\n");
6643 return CMD_WARNING_CONFIG_FAILED;
6644 }
6645 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6646 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6647 return CMD_WARNING_CONFIG_FAILED;
6648 }
6649
d62a17ae 6650 apply_mask(&p);
718e3744 6651
e2a86ad9 6652 if (negate) {
718e3744 6653
e2a86ad9 6654 /* Set BGP static route configuration. */
9bcb3eef 6655 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6656
9bcb3eef 6657 if (!dest) {
585f1adc
IR
6658 vty_out(vty, "%% Can't find static route specified\n");
6659 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6660 }
6661
9bcb3eef 6662 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6663
e2a86ad9
DS
6664 if ((label_index != BGP_INVALID_LABEL_INDEX)
6665 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6666 vty_out(vty,
6667 "%% label-index doesn't match static route\n");
70d9b134 6668 bgp_dest_unlock_node(dest);
585f1adc 6669 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6670 }
d62a17ae 6671
e2a86ad9
DS
6672 if ((rmap && bgp_static->rmap.name)
6673 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6674 vty_out(vty,
6675 "%% route-map name doesn't match static route\n");
70d9b134 6676 bgp_dest_unlock_node(dest);
585f1adc 6677 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6678 }
718e3744 6679
e2a86ad9
DS
6680 /* Update BGP RIB. */
6681 if (!bgp_static->backdoor)
6682 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6683
e2a86ad9
DS
6684 /* Clear configuration. */
6685 bgp_static_free(bgp_static);
9bcb3eef
DS
6686 bgp_dest_set_bgp_static_info(dest, NULL);
6687 bgp_dest_unlock_node(dest);
6688 bgp_dest_unlock_node(dest);
e2a86ad9 6689 } else {
718e3744 6690
e2a86ad9 6691 /* Set BGP static route configuration. */
9bcb3eef
DS
6692 dest = bgp_node_get(bgp->route[afi][safi], &p);
6693 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6694 if (bgp_static) {
e2a86ad9 6695 /* Configuration change. */
e2a86ad9
DS
6696 /* Label index cannot be changed. */
6697 if (bgp_static->label_index != label_index) {
585f1adc 6698 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6699 bgp_dest_unlock_node(dest);
585f1adc 6700 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6701 }
d62a17ae 6702
e2a86ad9 6703 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6704 if (bgp_static->valid
6705 && bgp_static->backdoor != backdoor)
e2a86ad9 6706 need_update = 1;
718e3744 6707
e2a86ad9 6708 bgp_static->backdoor = backdoor;
718e3744 6709
e2a86ad9 6710 if (rmap) {
0a22ddfb
QY
6711 XFREE(MTYPE_ROUTE_MAP_NAME,
6712 bgp_static->rmap.name);
b4897fa5 6713 route_map_counter_decrement(
6714 bgp_static->rmap.map);
e2a86ad9
DS
6715 bgp_static->rmap.name =
6716 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6717 bgp_static->rmap.map =
6718 route_map_lookup_by_name(rmap);
b4897fa5 6719 route_map_counter_increment(
6720 bgp_static->rmap.map);
e2a86ad9 6721 } else {
0a22ddfb
QY
6722 XFREE(MTYPE_ROUTE_MAP_NAME,
6723 bgp_static->rmap.name);
b4897fa5 6724 route_map_counter_decrement(
6725 bgp_static->rmap.map);
e2a86ad9
DS
6726 bgp_static->rmap.map = NULL;
6727 bgp_static->valid = 0;
6728 }
9bcb3eef 6729 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6730 } else {
6731 /* New configuration. */
6732 bgp_static = bgp_static_new();
6733 bgp_static->backdoor = backdoor;
6734 bgp_static->valid = 0;
6735 bgp_static->igpmetric = 0;
975a328e 6736 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6737 bgp_static->label_index = label_index;
718e3744 6738
e2a86ad9 6739 if (rmap) {
0a22ddfb
QY
6740 XFREE(MTYPE_ROUTE_MAP_NAME,
6741 bgp_static->rmap.name);
b4897fa5 6742 route_map_counter_decrement(
6743 bgp_static->rmap.map);
e2a86ad9
DS
6744 bgp_static->rmap.name =
6745 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6746 bgp_static->rmap.map =
6747 route_map_lookup_by_name(rmap);
b4897fa5 6748 route_map_counter_increment(
6749 bgp_static->rmap.map);
e2a86ad9 6750 }
9bcb3eef 6751 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6752 }
d62a17ae 6753
e2a86ad9
DS
6754 bgp_static->valid = 1;
6755 if (need_update)
6756 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6757
e2a86ad9
DS
6758 if (!bgp_static->backdoor)
6759 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6760 }
d62a17ae 6761
585f1adc 6762 return CMD_SUCCESS;
d62a17ae 6763}
6764
6765void bgp_static_add(struct bgp *bgp)
6766{
6767 afi_t afi;
6768 safi_t safi;
9bcb3eef
DS
6769 struct bgp_dest *dest;
6770 struct bgp_dest *rm;
d62a17ae 6771 struct bgp_table *table;
6772 struct bgp_static *bgp_static;
6773
47fc6261 6774 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6775 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6776 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6777 dest = bgp_route_next(dest)) {
6778 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6779 continue;
ea47320b 6780
05c7a1cc
QY
6781 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6782 || (safi == SAFI_EVPN)) {
9bcb3eef 6783 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6784
6785 for (rm = bgp_table_top(table); rm;
6786 rm = bgp_route_next(rm)) {
a78beeb5 6787 bgp_static =
9bcb3eef 6788 bgp_dest_get_bgp_static_info(
5a8ba9fc 6789 rm);
9bcb3eef
DS
6790 bgp_static_update_safi(
6791 bgp, bgp_dest_get_prefix(rm),
6792 bgp_static, afi, safi);
d62a17ae 6793 }
05c7a1cc 6794 } else {
5a8ba9fc 6795 bgp_static_update(
9bcb3eef
DS
6796 bgp, bgp_dest_get_prefix(dest),
6797 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6798 safi);
ea47320b 6799 }
05c7a1cc 6800 }
47fc6261 6801 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6802}
6803
718e3744 6804/* Called from bgp_delete(). Delete all static routes from the BGP
6805 instance. */
d62a17ae 6806void bgp_static_delete(struct bgp *bgp)
6807{
6808 afi_t afi;
6809 safi_t safi;
9bcb3eef
DS
6810 struct bgp_dest *dest;
6811 struct bgp_dest *rm;
d62a17ae 6812 struct bgp_table *table;
6813 struct bgp_static *bgp_static;
6814
05c7a1cc 6815 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6816 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6817 dest = bgp_route_next(dest)) {
6818 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6819 continue;
ea47320b 6820
05c7a1cc
QY
6821 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6822 || (safi == SAFI_EVPN)) {
9bcb3eef 6823 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6824
6825 for (rm = bgp_table_top(table); rm;
6826 rm = bgp_route_next(rm)) {
a78beeb5 6827 bgp_static =
9bcb3eef 6828 bgp_dest_get_bgp_static_info(
5a8ba9fc 6829 rm);
c7d14ba6
PG
6830 if (!bgp_static)
6831 continue;
6832
05c7a1cc 6833 bgp_static_withdraw_safi(
9bcb3eef 6834 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6835 AFI_IP, safi,
6836 (struct prefix_rd *)
9bcb3eef
DS
6837 bgp_dest_get_prefix(
6838 dest));
ea47320b 6839 bgp_static_free(bgp_static);
811c6797 6840 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6841 NULL);
811c6797 6842 bgp_dest_unlock_node(rm);
d62a17ae 6843 }
05c7a1cc 6844 } else {
9bcb3eef 6845 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6846 bgp_static_withdraw(bgp,
9bcb3eef 6847 bgp_dest_get_prefix(dest),
b54892e0 6848 afi, safi);
05c7a1cc 6849 bgp_static_free(bgp_static);
9bcb3eef
DS
6850 bgp_dest_set_bgp_static_info(dest, NULL);
6851 bgp_dest_unlock_node(dest);
ea47320b 6852 }
05c7a1cc 6853 }
d62a17ae 6854}
6855
6856void bgp_static_redo_import_check(struct bgp *bgp)
6857{
6858 afi_t afi;
6859 safi_t safi;
9bcb3eef
DS
6860 struct bgp_dest *dest;
6861 struct bgp_dest *rm;
d62a17ae 6862 struct bgp_table *table;
6863 struct bgp_static *bgp_static;
6864
6865 /* Use this flag to force reprocessing of the route */
892fedb6 6866 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6867 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6868 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6869 dest = bgp_route_next(dest)) {
6870 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6871 continue;
ea47320b 6872
05c7a1cc
QY
6873 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6874 || (safi == SAFI_EVPN)) {
9bcb3eef 6875 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6876
6877 for (rm = bgp_table_top(table); rm;
6878 rm = bgp_route_next(rm)) {
a78beeb5 6879 bgp_static =
9bcb3eef 6880 bgp_dest_get_bgp_static_info(
5a8ba9fc 6881 rm);
9bcb3eef
DS
6882 bgp_static_update_safi(
6883 bgp, bgp_dest_get_prefix(rm),
6884 bgp_static, afi, safi);
d62a17ae 6885 }
05c7a1cc 6886 } else {
9bcb3eef
DS
6887 bgp_static = bgp_dest_get_bgp_static_info(dest);
6888 bgp_static_update(bgp,
6889 bgp_dest_get_prefix(dest),
6890 bgp_static, afi, safi);
ea47320b 6891 }
05c7a1cc
QY
6892 }
6893 }
892fedb6 6894 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6895}
6896
6897static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6898 safi_t safi)
6899{
6900 struct bgp_table *table;
9bcb3eef 6901 struct bgp_dest *dest;
40381db7 6902 struct bgp_path_info *pi;
d62a17ae 6903
dfb6fd1d
NT
6904 /* Do not install the aggregate route if BGP is in the
6905 * process of termination.
6906 */
892fedb6
DA
6907 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6908 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6909 return;
6910
d62a17ae 6911 table = bgp->rib[afi][safi];
9bcb3eef
DS
6912 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6913 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6914 if (pi->peer == bgp->peer_self
6915 && ((pi->type == ZEBRA_ROUTE_BGP
6916 && pi->sub_type == BGP_ROUTE_STATIC)
6917 || (pi->type != ZEBRA_ROUTE_BGP
6918 && pi->sub_type
d62a17ae 6919 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6920 bgp_aggregate_decrement(
6921 bgp, bgp_dest_get_prefix(dest), pi, afi,
6922 safi);
40381db7 6923 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6924 bgp_path_info_delete(dest, pi);
6925 bgp_process(bgp, dest, afi, safi);
d62a17ae 6926 }
6927 }
6928 }
ad4cbda1 6929}
6930
6931/*
6932 * Purge all networks and redistributed routes from routing table.
6933 * Invoked upon the instance going down.
6934 */
d62a17ae 6935void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6936{
d62a17ae 6937 afi_t afi;
6938 safi_t safi;
ad4cbda1 6939
05c7a1cc
QY
6940 FOREACH_AFI_SAFI (afi, safi)
6941 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6942}
6943
137446f9
LB
6944/*
6945 * gpz 110624
6946 * Currently this is used to set static routes for VPN and ENCAP.
6947 * I think it can probably be factored with bgp_static_set.
6948 */
d62a17ae 6949int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6950 const char *ip_str, const char *rd_str,
6951 const char *label_str, const char *rmap_str,
6952 int evpn_type, const char *esi, const char *gwip,
6953 const char *ethtag, const char *routermac)
6954{
6955 VTY_DECLVAR_CONTEXT(bgp, bgp);
6956 int ret;
6957 struct prefix p;
6958 struct prefix_rd prd;
9bcb3eef
DS
6959 struct bgp_dest *pdest;
6960 struct bgp_dest *dest;
d62a17ae 6961 struct bgp_table *table;
6962 struct bgp_static *bgp_static;
6963 mpls_label_t label = MPLS_INVALID_LABEL;
6964 struct prefix gw_ip;
6965
6966 /* validate ip prefix */
6967 ret = str2prefix(ip_str, &p);
6968 if (!ret) {
6969 vty_out(vty, "%% Malformed prefix\n");
6970 return CMD_WARNING_CONFIG_FAILED;
6971 }
6972 apply_mask(&p);
6973 if ((afi == AFI_L2VPN)
6974 && (bgp_build_evpn_prefix(evpn_type,
6975 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6976 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6977 return CMD_WARNING_CONFIG_FAILED;
6978 }
718e3744 6979
d62a17ae 6980 ret = str2prefix_rd(rd_str, &prd);
6981 if (!ret) {
6982 vty_out(vty, "%% Malformed rd\n");
6983 return CMD_WARNING_CONFIG_FAILED;
6984 }
718e3744 6985
d62a17ae 6986 if (label_str) {
6987 unsigned long label_val;
6988 label_val = strtoul(label_str, NULL, 10);
6989 encode_label(label_val, &label);
6990 }
9bedbb1e 6991
d62a17ae 6992 if (safi == SAFI_EVPN) {
6993 if (esi && str2esi(esi, NULL) == 0) {
6994 vty_out(vty, "%% Malformed ESI\n");
6995 return CMD_WARNING_CONFIG_FAILED;
6996 }
6997 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6998 vty_out(vty, "%% Malformed Router MAC\n");
6999 return CMD_WARNING_CONFIG_FAILED;
7000 }
7001 if (gwip) {
6006b807 7002 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7003 ret = str2prefix(gwip, &gw_ip);
7004 if (!ret) {
7005 vty_out(vty, "%% Malformed GatewayIp\n");
7006 return CMD_WARNING_CONFIG_FAILED;
7007 }
7008 if ((gw_ip.family == AF_INET
3714a385 7009 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7010 (struct prefix_evpn *)&p))
7011 || (gw_ip.family == AF_INET6
3714a385 7012 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7013 (struct prefix_evpn *)&p))) {
7014 vty_out(vty,
7015 "%% GatewayIp family differs with IP prefix\n");
7016 return CMD_WARNING_CONFIG_FAILED;
7017 }
7018 }
7019 }
9bcb3eef
DS
7020 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7021 if (!bgp_dest_has_bgp_path_info_data(pdest))
7022 bgp_dest_set_bgp_table_info(pdest,
67009e22 7023 bgp_table_init(bgp, afi, safi));
9bcb3eef 7024 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7025
9bcb3eef 7026 dest = bgp_node_get(table, &p);
d62a17ae 7027
9bcb3eef 7028 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7029 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7030 bgp_dest_unlock_node(dest);
d62a17ae 7031 } else {
7032 /* New configuration. */
7033 bgp_static = bgp_static_new();
7034 bgp_static->backdoor = 0;
7035 bgp_static->valid = 0;
7036 bgp_static->igpmetric = 0;
975a328e 7037 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7038 bgp_static->label = label;
7039 bgp_static->prd = prd;
7040
852f96eb
DS
7041 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
7042
d62a17ae 7043 if (rmap_str) {
0a22ddfb 7044 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7045 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7046 bgp_static->rmap.name =
7047 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7048 bgp_static->rmap.map =
7049 route_map_lookup_by_name(rmap_str);
b4897fa5 7050 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7051 }
718e3744 7052
d62a17ae 7053 if (safi == SAFI_EVPN) {
7054 if (esi) {
7055 bgp_static->eth_s_id =
7056 XCALLOC(MTYPE_ATTR,
0a50c248 7057 sizeof(esi_t));
d62a17ae 7058 str2esi(esi, bgp_static->eth_s_id);
7059 }
7060 if (routermac) {
7061 bgp_static->router_mac =
28328ea9 7062 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7063 (void)prefix_str2mac(routermac,
7064 bgp_static->router_mac);
d62a17ae 7065 }
7066 if (gwip)
7067 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7068 }
9bcb3eef 7069 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7070
d62a17ae 7071 bgp_static->valid = 1;
7072 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7073 }
718e3744 7074
d62a17ae 7075 return CMD_SUCCESS;
718e3744 7076}
7077
7078/* Configure static BGP network. */
d62a17ae 7079int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7080 const char *ip_str, const char *rd_str,
7081 const char *label_str, int evpn_type, const char *esi,
7082 const char *gwip, const char *ethtag)
7083{
7084 VTY_DECLVAR_CONTEXT(bgp, bgp);
7085 int ret;
7086 struct prefix p;
7087 struct prefix_rd prd;
9bcb3eef
DS
7088 struct bgp_dest *pdest;
7089 struct bgp_dest *dest;
d62a17ae 7090 struct bgp_table *table;
7091 struct bgp_static *bgp_static;
7092 mpls_label_t label = MPLS_INVALID_LABEL;
7093
7094 /* Convert IP prefix string to struct prefix. */
7095 ret = str2prefix(ip_str, &p);
7096 if (!ret) {
7097 vty_out(vty, "%% Malformed prefix\n");
7098 return CMD_WARNING_CONFIG_FAILED;
7099 }
7100 apply_mask(&p);
7101 if ((afi == AFI_L2VPN)
7102 && (bgp_build_evpn_prefix(evpn_type,
7103 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7104 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7105 return CMD_WARNING_CONFIG_FAILED;
7106 }
7107 ret = str2prefix_rd(rd_str, &prd);
7108 if (!ret) {
7109 vty_out(vty, "%% Malformed rd\n");
7110 return CMD_WARNING_CONFIG_FAILED;
7111 }
718e3744 7112
d62a17ae 7113 if (label_str) {
7114 unsigned long label_val;
7115 label_val = strtoul(label_str, NULL, 10);
7116 encode_label(label_val, &label);
7117 }
718e3744 7118
9bcb3eef
DS
7119 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7120 if (!bgp_dest_has_bgp_path_info_data(pdest))
7121 bgp_dest_set_bgp_table_info(pdest,
67009e22 7122 bgp_table_init(bgp, afi, safi));
d62a17ae 7123 else
9bcb3eef
DS
7124 bgp_dest_unlock_node(pdest);
7125 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7126
9bcb3eef 7127 dest = bgp_node_lookup(table, &p);
6b0655a2 7128
9bcb3eef 7129 if (dest) {
d62a17ae 7130 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7131
9bcb3eef 7132 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7133 bgp_static_free(bgp_static);
9bcb3eef
DS
7134 bgp_dest_set_bgp_static_info(dest, NULL);
7135 bgp_dest_unlock_node(dest);
7136 bgp_dest_unlock_node(dest);
d62a17ae 7137 } else
7138 vty_out(vty, "%% Can't find the route\n");
7139
7140 return CMD_SUCCESS;
7141}
7142
7143static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7144 const char *rmap_name)
7145{
7146 VTY_DECLVAR_CONTEXT(bgp, bgp);
7147 struct bgp_rmap *rmap;
7148
7149 rmap = &bgp->table_map[afi][safi];
7150 if (rmap_name) {
0a22ddfb 7151 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7152 route_map_counter_decrement(rmap->map);
d62a17ae 7153 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7154 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7155 route_map_counter_increment(rmap->map);
d62a17ae 7156 } else {
0a22ddfb 7157 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7158 route_map_counter_decrement(rmap->map);
d62a17ae 7159 rmap->map = NULL;
7160 }
73ac8160 7161
d62a17ae 7162 if (bgp_fibupd_safi(safi))
7163 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7164
d62a17ae 7165 return CMD_SUCCESS;
73ac8160
DS
7166}
7167
d62a17ae 7168static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7169 const char *rmap_name)
73ac8160 7170{
d62a17ae 7171 VTY_DECLVAR_CONTEXT(bgp, bgp);
7172 struct bgp_rmap *rmap;
73ac8160 7173
d62a17ae 7174 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7175 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7176 route_map_counter_decrement(rmap->map);
d62a17ae 7177 rmap->map = NULL;
73ac8160 7178
d62a17ae 7179 if (bgp_fibupd_safi(safi))
7180 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7181
d62a17ae 7182 return CMD_SUCCESS;
73ac8160
DS
7183}
7184
2b791107 7185void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7186 safi_t safi)
73ac8160 7187{
d62a17ae 7188 if (bgp->table_map[afi][safi].name) {
d62a17ae 7189 vty_out(vty, " table-map %s\n",
7190 bgp->table_map[afi][safi].name);
7191 }
73ac8160
DS
7192}
7193
73ac8160
DS
7194DEFUN (bgp_table_map,
7195 bgp_table_map_cmd,
7196 "table-map WORD",
7197 "BGP table to RIB route download filter\n"
7198 "Name of the route map\n")
7199{
d62a17ae 7200 int idx_word = 1;
7201 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7202 argv[idx_word]->arg);
73ac8160
DS
7203}
7204DEFUN (no_bgp_table_map,
7205 no_bgp_table_map_cmd,
7206 "no table-map WORD",
3a2d747c 7207 NO_STR
73ac8160
DS
7208 "BGP table to RIB route download filter\n"
7209 "Name of the route map\n")
7210{
d62a17ae 7211 int idx_word = 2;
7212 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7213 argv[idx_word]->arg);
73ac8160
DS
7214}
7215
585f1adc
IR
7216DEFPY(bgp_network,
7217 bgp_network_cmd,
7218 "[no] network \
7219 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7220 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7221 backdoor$backdoor}]",
7222 NO_STR
7223 "Specify a network to announce via BGP\n"
7224 "IPv4 prefix\n"
7225 "Network number\n"
7226 "Network mask\n"
7227 "Network mask\n"
7228 "Route-map to modify the attributes\n"
7229 "Name of the route map\n"
7230 "Label index to associate with the prefix\n"
7231 "Label index value\n"
7232 "Specify a BGP backdoor route\n")
7233{
7234 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7235
7236 if (address_str) {
7237 int ret;
718e3744 7238
e2a86ad9 7239 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7240 addr_prefix_str,
7241 sizeof(addr_prefix_str));
e2a86ad9
DS
7242 if (!ret) {
7243 vty_out(vty, "%% Inconsistent address and mask\n");
7244 return CMD_WARNING_CONFIG_FAILED;
7245 }
d62a17ae 7246 }
718e3744 7247
585f1adc
IR
7248 return bgp_static_set(
7249 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7250 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7251 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7252}
7253
585f1adc
IR
7254DEFPY(ipv6_bgp_network,
7255 ipv6_bgp_network_cmd,
7256 "[no] network X:X::X:X/M$prefix \
70dd370f 7257 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7258 NO_STR
7259 "Specify a network to announce via BGP\n"
7260 "IPv6 prefix\n"
7261 "Route-map to modify the attributes\n"
7262 "Name of the route map\n"
7263 "Label index to associate with the prefix\n"
7264 "Label index value\n")
37a87b8f 7265{
585f1adc
IR
7266 return bgp_static_set(
7267 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7268 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7269}
7270
d62a17ae 7271static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7272{
d62a17ae 7273 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7274}
7275
9bea1b4b 7276void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7277{
365ab2e7
RZ
7278 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7279 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7280 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7281 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7282 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7283}
718e3744 7284
365ab2e7
RZ
7285/**
7286 * Helper function to avoid repeated code: prepare variables for a
7287 * `route_map_apply` call.
7288 *
7289 * \returns `true` on route map match, otherwise `false`.
7290 */
7291static bool aggr_suppress_map_test(struct bgp *bgp,
7292 struct bgp_aggregate *aggregate,
7293 struct bgp_path_info *pi)
7294{
7295 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7296 route_map_result_t rmr = RMAP_DENYMATCH;
7297 struct bgp_path_info rmap_path = {};
7298 struct attr attr = {};
7299
7300 /* No route map entries created, just don't match. */
7301 if (aggregate->suppress_map == NULL)
7302 return false;
7303
7304 /* Call route map matching and return result. */
17571c4a 7305 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7306 rmap_path.peer = bgp->peer_self;
7307 rmap_path.attr = &attr;
7308
7309 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7310 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7311 bgp->peer_self->rmap_type = 0;
7312
7313 bgp_attr_flush(&attr);
afb254d7 7314 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7315
7316 return rmr == RMAP_PERMITMATCH;
7317}
7318
4056a5f6
RZ
7319/** Test whether the aggregation has suppressed this path or not. */
7320static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7321 struct bgp_path_info *pi)
7322{
7323 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7324 return false;
7325
7326 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7327}
7328
7329/**
7330 * Suppress this path and keep the reference.
7331 *
7332 * \returns `true` if needs processing otherwise `false`.
7333 */
7334static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7335 struct bgp_path_info *pi)
7336{
7337 struct bgp_path_info_extra *pie;
7338
7339 /* Path is already suppressed by this aggregation. */
7340 if (aggr_suppress_exists(aggregate, pi))
7341 return false;
7342
7343 pie = bgp_path_info_extra_get(pi);
7344
7345 /* This is the first suppression, allocate memory and list it. */
7346 if (pie->aggr_suppressors == NULL)
7347 pie->aggr_suppressors = list_new();
7348
7349 listnode_add(pie->aggr_suppressors, aggregate);
7350
7351 /* Only mark for processing if suppressed. */
7352 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7353 if (BGP_DEBUG(update, UPDATE_OUT))
7354 zlog_debug("aggregate-address suppressing: %pFX",
7355 bgp_dest_get_prefix(pi->net));
7356
4056a5f6
RZ
7357 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7358 return true;
7359 }
7360
7361 return false;
7362}
7363
7364/**
7365 * Unsuppress this path and remove the reference.
7366 *
7367 * \returns `true` if needs processing otherwise `false`.
7368 */
7369static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7370 struct bgp_path_info *pi)
7371{
7372 /* Path wasn't suppressed. */
7373 if (!aggr_suppress_exists(aggregate, pi))
7374 return false;
7375
7376 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7377
7378 /* Unsuppress and free extra memory if last item. */
7379 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7380 if (BGP_DEBUG(update, UPDATE_OUT))
7381 zlog_debug("aggregate-address unsuppressing: %pFX",
7382 bgp_dest_get_prefix(pi->net));
7383
4056a5f6
RZ
7384 list_delete(&pi->extra->aggr_suppressors);
7385 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7386 return true;
7387 }
7388
7389 return false;
7390}
7391
3dc339cd
DA
7392static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7393 struct aspath *aspath,
7394 struct community *comm,
7395 struct ecommunity *ecomm,
7396 struct lcommunity *lcomm)
eaaf8adb
DS
7397{
7398 static struct aspath *ae = NULL;
17571c4a
PG
7399 enum asnotation_mode asnotation;
7400
7401 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7402
7403 if (!ae)
17571c4a 7404 ae = aspath_empty(asnotation);
eaaf8adb 7405
40381db7 7406 if (!pi)
3dc339cd 7407 return false;
eaaf8adb 7408
40381db7 7409 if (origin != pi->attr->origin)
3dc339cd 7410 return false;
eaaf8adb 7411
40381db7 7412 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7413 return false;
29f7d023 7414
9a706b42 7415 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7416 return false;
eaaf8adb 7417
b53e67a3 7418 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7419 return false;
eaaf8adb 7420
1bcf3a96 7421 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7422 return false;
dd18c5a9 7423
40381db7 7424 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7425 return false;
7ce8a8e0 7426
3dc339cd 7427 return true;
eaaf8adb
DS
7428}
7429
5f040085
DS
7430static void bgp_aggregate_install(
7431 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7432 uint8_t origin, struct aspath *aspath, struct community *community,
7433 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7434 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7435{
9bcb3eef 7436 struct bgp_dest *dest;
c701010e 7437 struct bgp_table *table;
6f94b685 7438 struct bgp_path_info *pi, *orig, *new;
20894f50 7439 struct attr *attr;
c701010e
DS
7440
7441 table = bgp->rib[afi][safi];
7442
9bcb3eef 7443 dest = bgp_node_get(table, p);
eaaf8adb 7444
9bcb3eef 7445 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7446 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7447 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7448 break;
7449
6aabb15d
RZ
7450 /*
7451 * If we have paths with different MEDs, then don't install
7452 * (or uninstall) the aggregate route.
7453 */
7454 if (aggregate->match_med && aggregate->med_mismatched)
7455 goto uninstall_aggregate_route;
7456
c701010e 7457 if (aggregate->count > 0) {
eaaf8adb
DS
7458 /*
7459 * If the aggregate information has not changed
7460 * no need to re-install it again.
7461 */
6f94b685 7462 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7463 ecommunity, lcommunity)) {
9bcb3eef 7464 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7465
7466 if (aspath)
7467 aspath_free(aspath);
7468 if (community)
3c1f53de 7469 community_free(&community);
3da2cc32
DS
7470 if (ecommunity)
7471 ecommunity_free(&ecommunity);
dd18c5a9
DS
7472 if (lcommunity)
7473 lcommunity_free(&lcommunity);
eaaf8adb
DS
7474
7475 return;
7476 }
7477
7478 /*
7479 * Mark the old as unusable
7480 */
40381db7 7481 if (pi)
9bcb3eef 7482 bgp_path_info_delete(dest, pi);
eaaf8adb 7483
20894f50
DA
7484 attr = bgp_attr_aggregate_intern(
7485 bgp, origin, aspath, community, ecommunity, lcommunity,
7486 aggregate, atomic_aggregate, p);
7487
7488 if (!attr) {
e11791f4
DA
7489 aspath_free(aspath);
7490 community_free(&community);
7491 ecommunity_free(&ecommunity);
7492 lcommunity_free(&lcommunity);
8c0044f3 7493 bgp_dest_unlock_node(dest);
20894f50 7494 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7495 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7496 zlog_debug("%s: %pFX null attribute", __func__,
7497 p);
20894f50
DA
7498 return;
7499 }
7500
3da2cc32 7501 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7502 bgp->peer_self, attr, dest);
20894f50 7503
1defdda8 7504 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7505
9bcb3eef
DS
7506 bgp_path_info_add(dest, new);
7507 bgp_process(bgp, dest, afi, safi);
c701010e 7508 } else {
6aabb15d 7509 uninstall_aggregate_route:
6f94b685 7510 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7511 if (pi->peer == bgp->peer_self
7512 && pi->type == ZEBRA_ROUTE_BGP
7513 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7514 break;
7515
7516 /* Withdraw static BGP route from routing table. */
40381db7 7517 if (pi) {
9bcb3eef
DS
7518 bgp_path_info_delete(dest, pi);
7519 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7520 }
7521 }
7522
9bcb3eef 7523 bgp_dest_unlock_node(dest);
c701010e
DS
7524}
7525
6aabb15d
RZ
7526/**
7527 * Check if the current path has different MED than other known paths.
7528 *
7529 * \returns `true` if the MED matched the others else `false`.
7530 */
7531static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7532 struct bgp *bgp, struct bgp_path_info *pi)
7533{
7534 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7535
7536 /* This is the first route being analyzed. */
7537 if (!aggregate->med_initialized) {
7538 aggregate->med_initialized = true;
7539 aggregate->med_mismatched = false;
7540 aggregate->med_matched_value = cur_med;
7541 } else {
7542 /* Check if routes with different MED showed up. */
7543 if (cur_med != aggregate->med_matched_value)
7544 aggregate->med_mismatched = true;
7545 }
7546
7547 return !aggregate->med_mismatched;
7548}
7549
7550/**
7551 * Initializes and tests all routes in the aggregate address path for MED
7552 * values.
7553 *
7554 * \returns `true` if all MEDs are the same otherwise `false`.
7555 */
7556static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7557 struct bgp *bgp, const struct prefix *p,
7558 afi_t afi, safi_t safi)
7559{
7560 struct bgp_table *table = bgp->rib[afi][safi];
7561 const struct prefix *dest_p;
7562 struct bgp_dest *dest, *top;
7563 struct bgp_path_info *pi;
7564 bool med_matched = true;
7565
7566 aggregate->med_initialized = false;
7567
7568 top = bgp_node_get(table, p);
7569 for (dest = bgp_node_get(table, p); dest;
7570 dest = bgp_route_next_until(dest, top)) {
7571 dest_p = bgp_dest_get_prefix(dest);
7572 if (dest_p->prefixlen <= p->prefixlen)
7573 continue;
7574
7575 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7576 if (BGP_PATH_HOLDDOWN(pi))
7577 continue;
7578 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7579 continue;
7580 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7581 med_matched = false;
7582 break;
7583 }
7584 }
7585 if (!med_matched)
7586 break;
7587 }
7588 bgp_dest_unlock_node(top);
7589
7590 return med_matched;
7591}
7592
7593/**
7594 * Toggles the route suppression status for this aggregate address
7595 * configuration.
7596 */
4056a5f6
RZ
7597void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7598 struct bgp *bgp, const struct prefix *p,
7599 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7600{
7601 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7602 const struct prefix *dest_p;
7603 struct bgp_dest *dest, *top;
7604 struct bgp_path_info *pi;
7605 bool toggle_suppression;
7606
7607 /* We've found a different MED we must revert any suppressed routes. */
7608 top = bgp_node_get(table, p);
7609 for (dest = bgp_node_get(table, p); dest;
7610 dest = bgp_route_next_until(dest, top)) {
7611 dest_p = bgp_dest_get_prefix(dest);
7612 if (dest_p->prefixlen <= p->prefixlen)
7613 continue;
7614
7615 toggle_suppression = false;
7616 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7617 if (BGP_PATH_HOLDDOWN(pi))
7618 continue;
7619 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7620 continue;
7621
6aabb15d
RZ
7622 /* We are toggling suppression back. */
7623 if (suppress) {
6aabb15d 7624 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7625 if (aggr_suppress_path(aggregate, pi))
7626 toggle_suppression = true;
6aabb15d
RZ
7627 continue;
7628 }
7629
6aabb15d 7630 /* Install route if there is no more suppression. */
4056a5f6 7631 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7632 toggle_suppression = true;
6aabb15d
RZ
7633 }
7634
7635 if (toggle_suppression)
7636 bgp_process(bgp, dest, afi, safi);
7637 }
7638 bgp_dest_unlock_node(top);
7639}
7640
7641/**
7642 * Aggregate address MED matching incremental test: this function is called
7643 * when the initial aggregation occurred and we are only testing a single
7644 * new path.
7645 *
7646 * In addition to testing and setting the MED validity it also installs back
7647 * suppressed routes (if summary is configured).
7648 *
7649 * Must not be called in `bgp_aggregate_route`.
7650 */
7651static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7652 struct bgp *bgp, const struct prefix *p,
7653 afi_t afi, safi_t safi,
f66624f5 7654 struct bgp_path_info *pi)
6aabb15d
RZ
7655{
7656 /* MED matching disabled. */
7657 if (!aggregate->match_med)
7658 return;
7659
f66624f5
DA
7660 /* Aggregation with different MED, recheck if we have got equal MEDs
7661 * now.
6aabb15d 7662 */
f66624f5
DA
7663 if (aggregate->med_mismatched &&
7664 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7665 aggregate->summary_only)
7666 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7667 true);
7668 else
6aabb15d
RZ
7669 bgp_aggregate_med_match(aggregate, bgp, pi);
7670
7671 /* No mismatches, just quit. */
7672 if (!aggregate->med_mismatched)
7673 return;
7674
7675 /* Route summarization is disabled. */
7676 if (!aggregate->summary_only)
7677 return;
7678
7679 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7680}
7681
b5d58c32 7682/* Update an aggregate as routes are added/removed from the BGP table */
9bea1b4b 7683bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
5f040085 7684 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7685{
7686 struct bgp_table *table;
9bcb3eef
DS
7687 struct bgp_dest *top;
7688 struct bgp_dest *dest;
d7c0a89a 7689 uint8_t origin;
d62a17ae 7690 struct aspath *aspath = NULL;
d62a17ae 7691 struct community *community = NULL;
3da2cc32 7692 struct ecommunity *ecommunity = NULL;
dd18c5a9 7693 struct lcommunity *lcommunity = NULL;
40381db7 7694 struct bgp_path_info *pi;
d62a17ae 7695 unsigned long match = 0;
d7c0a89a 7696 uint8_t atomic_aggregate = 0;
d62a17ae 7697
9f822fa2
S
7698 /* If the bgp instance is being deleted or self peer is deleted
7699 * then do not create aggregate route
7700 */
69a9680a 7701 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
9bea1b4b
DA
7702 bgp->peer_self == NULL)
7703 return false;
9f822fa2 7704
6aabb15d
RZ
7705 /* Initialize and test routes for MED difference. */
7706 if (aggregate->match_med)
7707 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7708
4056a5f6
RZ
7709 /*
7710 * Reset aggregate count: we might've been called from route map
7711 * update so in that case we must retest all more specific routes.
7712 *
7713 * \see `bgp_route_map_process_update`.
7714 */
7715 aggregate->count = 0;
7716 aggregate->incomplete_origin_count = 0;
7717 aggregate->incomplete_origin_count = 0;
7718 aggregate->egp_origin_count = 0;
7719
d62a17ae 7720 /* ORIGIN attribute: If at least one route among routes that are
7721 aggregated has ORIGIN with the value INCOMPLETE, then the
7722 aggregated route must have the ORIGIN attribute with the value
7723 INCOMPLETE. Otherwise, if at least one route among routes that
7724 are aggregated has ORIGIN with the value EGP, then the aggregated
7725 route must have the origin attribute with the value EGP. In all
7726 other case the value of the ORIGIN attribute of the aggregated
7727 route is INTERNAL. */
7728 origin = BGP_ORIGIN_IGP;
718e3744 7729
d62a17ae 7730 table = bgp->rib[afi][safi];
718e3744 7731
d62a17ae 7732 top = bgp_node_get(table, p);
9bcb3eef
DS
7733 for (dest = bgp_node_get(table, p); dest;
7734 dest = bgp_route_next_until(dest, top)) {
7735 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7736
9bcb3eef 7737 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7738 continue;
d62a17ae 7739
a77e2f4b
S
7740 /* If suppress fib is enabled and route not installed
7741 * in FIB, skip the route
7742 */
7743 if (!bgp_check_advertise(bgp, dest))
7744 continue;
7745
c2ff8b3e 7746 match = 0;
d62a17ae 7747
9bcb3eef 7748 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7749 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7750 continue;
718e3744 7751
40381db7 7752 if (pi->attr->flag
c2ff8b3e
DS
7753 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7754 atomic_aggregate = 1;
d62a17ae 7755
40381db7 7756 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7757 continue;
d62a17ae 7758
f273fef1
DS
7759 /*
7760 * summary-only aggregate route suppress
7761 * aggregated route announcements.
6aabb15d
RZ
7762 *
7763 * MED matching:
7764 * Don't create summaries if MED didn't match
7765 * otherwise neither the specific routes and the
7766 * aggregation will be announced.
f273fef1 7767 */
6aabb15d
RZ
7768 if (aggregate->summary_only
7769 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7770 if (aggr_suppress_path(aggregate, pi))
7771 match++;
d62a17ae 7772 }
c2ff8b3e 7773
365ab2e7
RZ
7774 /*
7775 * Suppress more specific routes that match the route
7776 * map results.
7777 *
7778 * MED matching:
7779 * Don't suppress routes if MED matching is enabled and
7780 * it mismatched otherwise we might end up with no
7781 * routes for this path.
7782 */
7783 if (aggregate->suppress_map_name
7784 && AGGREGATE_MED_VALID(aggregate)
7785 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7786 if (aggr_suppress_path(aggregate, pi))
7787 match++;
d62a17ae 7788 }
c2ff8b3e
DS
7789
7790 aggregate->count++;
7791
f273fef1
DS
7792 /*
7793 * If at least one route among routes that are
7794 * aggregated has ORIGIN with the value INCOMPLETE,
7795 * then the aggregated route MUST have the ORIGIN
7796 * attribute with the value INCOMPLETE. Otherwise, if
7797 * at least one route among routes that are aggregated
7798 * has ORIGIN with the value EGP, then the aggregated
7799 * route MUST have the ORIGIN attribute with the value
7800 * EGP.
7801 */
fc968841
NT
7802 switch (pi->attr->origin) {
7803 case BGP_ORIGIN_INCOMPLETE:
7804 aggregate->incomplete_origin_count++;
7805 break;
7806 case BGP_ORIGIN_EGP:
7807 aggregate->egp_origin_count++;
7808 break;
7809 default:
7810 /*Do nothing.
7811 */
7812 break;
7813 }
c2ff8b3e
DS
7814
7815 if (!aggregate->as_set)
7816 continue;
7817
f273fef1
DS
7818 /*
7819 * as-set aggregate route generate origin, as path,
7820 * and community aggregation.
7821 */
fc968841
NT
7822 /* Compute aggregate route's as-path.
7823 */
ef51a7d8 7824 bgp_compute_aggregate_aspath_hash(aggregate,
7825 pi->attr->aspath);
c2ff8b3e 7826
fc968841
NT
7827 /* Compute aggregate route's community.
7828 */
9a706b42 7829 if (bgp_attr_get_community(pi->attr))
21fec674 7830 bgp_compute_aggregate_community_hash(
9a706b42
DA
7831 aggregate,
7832 bgp_attr_get_community(pi->attr));
dd18c5a9 7833
fc968841
NT
7834 /* Compute aggregate route's extended community.
7835 */
b53e67a3 7836 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7837 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7838 aggregate,
7839 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7840
7841 /* Compute aggregate route's large community.
7842 */
1bcf3a96 7843 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7844 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7845 aggregate,
7846 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7847 }
c2ff8b3e 7848 if (match)
9bcb3eef 7849 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7850 }
21fec674 7851 if (aggregate->as_set) {
ef51a7d8 7852 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7853 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7854 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7855 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7856 }
7857
f1eb1f05 7858
9bcb3eef 7859 bgp_dest_unlock_node(top);
718e3744 7860
718e3744 7861
fc968841
NT
7862 if (aggregate->incomplete_origin_count > 0)
7863 origin = BGP_ORIGIN_INCOMPLETE;
7864 else if (aggregate->egp_origin_count > 0)
7865 origin = BGP_ORIGIN_EGP;
d62a17ae 7866
229757f1
DA
7867 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7868 origin = aggregate->origin;
7869
fc968841
NT
7870 if (aggregate->as_set) {
7871 if (aggregate->aspath)
7872 /* Retrieve aggregate route's as-path.
7873 */
7874 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7875
fc968841
NT
7876 if (aggregate->community)
7877 /* Retrieve aggregate route's community.
7878 */
7879 community = community_dup(aggregate->community);
3da2cc32 7880
fc968841
NT
7881 if (aggregate->ecommunity)
7882 /* Retrieve aggregate route's ecommunity.
7883 */
7884 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7885
fc968841
NT
7886 if (aggregate->lcommunity)
7887 /* Retrieve aggregate route's lcommunity.
7888 */
7889 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7890 }
718e3744 7891
c701010e 7892 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7893 ecommunity, lcommunity, atomic_aggregate,
7894 aggregate);
9bea1b4b
DA
7895
7896 return true;
718e3744 7897}
7898
5f040085
DS
7899void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7900 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7901{
7902 struct bgp_table *table;
9bcb3eef
DS
7903 struct bgp_dest *top;
7904 struct bgp_dest *dest;
40381db7 7905 struct bgp_path_info *pi;
3b7db173
DS
7906 unsigned long match;
7907
7908 table = bgp->rib[afi][safi];
7909
7910 /* If routes exists below this node, generate aggregate routes. */
7911 top = bgp_node_get(table, p);
9bcb3eef
DS
7912 for (dest = bgp_node_get(table, p); dest;
7913 dest = bgp_route_next_until(dest, top)) {
7914 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7915
9bcb3eef 7916 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7917 continue;
7918 match = 0;
7919
9bcb3eef 7920 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7921 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7922 continue;
7923
40381db7 7924 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7925 continue;
7926
92b175bd
RZ
7927 /*
7928 * This route is suppressed: attempt to unsuppress it.
7929 *
7930 * `aggr_unsuppress_path` will fail if this particular
7931 * aggregate route was not the suppressor.
7932 */
7933 if (pi->extra && pi->extra->aggr_suppressors &&
7934 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7935 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7936 match++;
3b7db173 7937 }
365ab2e7 7938
3b7db173 7939 aggregate->count--;
fc968841
NT
7940
7941 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7942 aggregate->incomplete_origin_count--;
7943 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7944 aggregate->egp_origin_count--;
7945
7946 if (aggregate->as_set) {
7947 /* Remove as-path from aggregate.
7948 */
ef51a7d8 7949 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7950 aggregate,
7951 pi->attr->aspath);
7952
9a706b42 7953 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7954 /* Remove community from aggregate.
7955 */
21fec674 7956 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7957 aggregate,
7958 bgp_attr_get_community(
7959 pi->attr));
fc968841 7960
b53e67a3 7961 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7962 /* Remove ecommunity from aggregate.
7963 */
4edd83f9 7964 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7965 aggregate,
7966 bgp_attr_get_ecommunity(
7967 pi->attr));
fc968841 7968
1bcf3a96 7969 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7970 /* Remove lcommunity from aggregate.
7971 */
f1eb1f05 7972 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7973 aggregate,
7974 bgp_attr_get_lcommunity(
7975 pi->attr));
fc968841 7976 }
3b7db173
DS
7977 }
7978
7979 /* If this node was suppressed, process the change. */
7980 if (match)
9bcb3eef 7981 bgp_process(bgp, dest, afi, safi);
3b7db173 7982 }
f1eb1f05 7983 if (aggregate->as_set) {
ef51a7d8 7984 aspath_free(aggregate->aspath);
7985 aggregate->aspath = NULL;
21fec674 7986 if (aggregate->community)
7987 community_free(&aggregate->community);
4edd83f9 7988 if (aggregate->ecommunity)
7989 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7990 if (aggregate->lcommunity)
7991 lcommunity_free(&aggregate->lcommunity);
7992 }
7993
9bcb3eef 7994 bgp_dest_unlock_node(top);
3b7db173 7995}
718e3744 7996
5f040085
DS
7997static void bgp_add_route_to_aggregate(struct bgp *bgp,
7998 const struct prefix *aggr_p,
fc968841
NT
7999 struct bgp_path_info *pinew, afi_t afi,
8000 safi_t safi,
8001 struct bgp_aggregate *aggregate)
8002{
8003 uint8_t origin;
8004 struct aspath *aspath = NULL;
8005 uint8_t atomic_aggregate = 0;
8006 struct community *community = NULL;
8007 struct ecommunity *ecommunity = NULL;
8008 struct lcommunity *lcommunity = NULL;
8009
a4559740 8010 /* If the bgp instance is being deleted or self peer is deleted
8011 * then do not create aggregate route
8012 */
8013 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8014 || (bgp->peer_self == NULL))
8015 return;
8016
fc968841
NT
8017 /* ORIGIN attribute: If at least one route among routes that are
8018 * aggregated has ORIGIN with the value INCOMPLETE, then the
8019 * aggregated route must have the ORIGIN attribute with the value
8020 * INCOMPLETE. Otherwise, if at least one route among routes that
8021 * are aggregated has ORIGIN with the value EGP, then the aggregated
8022 * route must have the origin attribute with the value EGP. In all
8023 * other case the value of the ORIGIN attribute of the aggregated
8024 * route is INTERNAL.
8025 */
8026 origin = BGP_ORIGIN_IGP;
8027
8028 aggregate->count++;
8029
6aabb15d
RZ
8030 /*
8031 * This must be called before `summary` check to avoid
8032 * "suppressing" twice.
8033 */
8034 if (aggregate->match_med)
8035 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8036 pinew);
6aabb15d
RZ
8037
8038 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8039 aggr_suppress_path(aggregate, pinew);
fc968841 8040
365ab2e7
RZ
8041 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8042 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8043 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8044
8045 switch (pinew->attr->origin) {
8046 case BGP_ORIGIN_INCOMPLETE:
8047 aggregate->incomplete_origin_count++;
8048 break;
8049 case BGP_ORIGIN_EGP:
8050 aggregate->egp_origin_count++;
8051 break;
8052 default:
8053 /* Do nothing.
8054 */
8055 break;
8056 }
8057
8058 if (aggregate->incomplete_origin_count > 0)
8059 origin = BGP_ORIGIN_INCOMPLETE;
8060 else if (aggregate->egp_origin_count > 0)
8061 origin = BGP_ORIGIN_EGP;
8062
229757f1
DA
8063 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8064 origin = aggregate->origin;
8065
fc968841
NT
8066 if (aggregate->as_set) {
8067 /* Compute aggregate route's as-path.
8068 */
8069 bgp_compute_aggregate_aspath(aggregate,
8070 pinew->attr->aspath);
8071
8072 /* Compute aggregate route's community.
8073 */
9a706b42 8074 if (bgp_attr_get_community(pinew->attr))
fc968841 8075 bgp_compute_aggregate_community(
9a706b42 8076 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8077
8078 /* Compute aggregate route's extended community.
8079 */
b53e67a3 8080 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8081 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8082 aggregate,
8083 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8084
8085 /* Compute aggregate route's large community.
8086 */
1bcf3a96 8087 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8088 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8089 aggregate,
8090 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8091
8092 /* Retrieve aggregate route's as-path.
8093 */
8094 if (aggregate->aspath)
8095 aspath = aspath_dup(aggregate->aspath);
8096
8097 /* Retrieve aggregate route's community.
8098 */
8099 if (aggregate->community)
8100 community = community_dup(aggregate->community);
8101
8102 /* Retrieve aggregate route's ecommunity.
8103 */
8104 if (aggregate->ecommunity)
8105 ecommunity = ecommunity_dup(aggregate->ecommunity);
8106
8107 /* Retrieve aggregate route's lcommunity.
8108 */
8109 if (aggregate->lcommunity)
8110 lcommunity = lcommunity_dup(aggregate->lcommunity);
8111 }
8112
8113 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8114 aspath, community, ecommunity,
8115 lcommunity, atomic_aggregate, aggregate);
8116}
8117
8118static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8119 safi_t safi,
8120 struct bgp_path_info *pi,
8121 struct bgp_aggregate *aggregate,
5f040085 8122 const struct prefix *aggr_p)
fc968841
NT
8123{
8124 uint8_t origin;
8125 struct aspath *aspath = NULL;
8126 uint8_t atomic_aggregate = 0;
8127 struct community *community = NULL;
8128 struct ecommunity *ecommunity = NULL;
8129 struct lcommunity *lcommunity = NULL;
8130 unsigned long match = 0;
8131
a4559740 8132 /* If the bgp instance is being deleted or self peer is deleted
8133 * then do not create aggregate route
8134 */
8135 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8136 || (bgp->peer_self == NULL))
8137 return;
8138
fc968841
NT
8139 if (BGP_PATH_HOLDDOWN(pi))
8140 return;
8141
8142 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8143 return;
8144
4056a5f6
RZ
8145 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8146 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8147 match++;
fc968841 8148
365ab2e7 8149 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8150 && aggr_suppress_map_test(bgp, aggregate, pi))
8151 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8152 match++;
fc968841 8153
6aabb15d 8154 /*
365ab2e7 8155 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8156 * "unsuppressing" twice.
8157 */
8158 if (aggregate->match_med)
f66624f5 8159 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8160
fc968841
NT
8161 if (aggregate->count > 0)
8162 aggregate->count--;
8163
8164 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8165 aggregate->incomplete_origin_count--;
8166 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8167 aggregate->egp_origin_count--;
8168
8169 if (aggregate->as_set) {
8170 /* Remove as-path from aggregate.
8171 */
8172 bgp_remove_aspath_from_aggregate(aggregate,
8173 pi->attr->aspath);
8174
9a706b42 8175 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8176 /* Remove community from aggregate.
8177 */
8178 bgp_remove_community_from_aggregate(
9a706b42 8179 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8180
b53e67a3 8181 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8182 /* Remove ecommunity from aggregate.
8183 */
8184 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8185 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8186
1bcf3a96 8187 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8188 /* Remove lcommunity from aggregate.
8189 */
8190 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8191 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8192 }
8193
8194 /* If this node was suppressed, process the change. */
8195 if (match)
8196 bgp_process(bgp, pi->net, afi, safi);
8197
8198 origin = BGP_ORIGIN_IGP;
8199 if (aggregate->incomplete_origin_count > 0)
8200 origin = BGP_ORIGIN_INCOMPLETE;
8201 else if (aggregate->egp_origin_count > 0)
8202 origin = BGP_ORIGIN_EGP;
8203
229757f1
DA
8204 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8205 origin = aggregate->origin;
8206
fc968841
NT
8207 if (aggregate->as_set) {
8208 /* Retrieve aggregate route's as-path.
8209 */
8210 if (aggregate->aspath)
8211 aspath = aspath_dup(aggregate->aspath);
8212
8213 /* Retrieve aggregate route's community.
8214 */
8215 if (aggregate->community)
8216 community = community_dup(aggregate->community);
8217
8218 /* Retrieve aggregate route's ecommunity.
8219 */
8220 if (aggregate->ecommunity)
8221 ecommunity = ecommunity_dup(aggregate->ecommunity);
8222
8223 /* Retrieve aggregate route's lcommunity.
8224 */
8225 if (aggregate->lcommunity)
8226 lcommunity = lcommunity_dup(aggregate->lcommunity);
8227 }
8228
8229 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8230 aspath, community, ecommunity,
8231 lcommunity, atomic_aggregate, aggregate);
8232}
8233
5a1ae2c2 8234void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8235 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8236{
9bcb3eef
DS
8237 struct bgp_dest *child;
8238 struct bgp_dest *dest;
d62a17ae 8239 struct bgp_aggregate *aggregate;
8240 struct bgp_table *table;
718e3744 8241
d62a17ae 8242 table = bgp->aggregate[afi][safi];
f018db83 8243
d62a17ae 8244 /* No aggregates configured. */
8245 if (bgp_table_top_nolock(table) == NULL)
8246 return;
f018db83 8247
d62a17ae 8248 if (p->prefixlen == 0)
8249 return;
718e3744 8250
40381db7 8251 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8252 return;
718e3744 8253
a77e2f4b
S
8254 /* If suppress fib is enabled and route not installed
8255 * in FIB, do not update the aggregate route
8256 */
8257 if (!bgp_check_advertise(bgp, pi->net))
8258 return;
8259
d62a17ae 8260 child = bgp_node_get(table, p);
718e3744 8261
d62a17ae 8262 /* Aggregate address configuration check. */
9bcb3eef
DS
8263 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8264 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8265
9bcb3eef
DS
8266 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8267 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8268 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8269 aggregate);
d62a17ae 8270 }
b1e62edd 8271 }
9bcb3eef 8272 bgp_dest_unlock_node(child);
718e3744 8273}
8274
5a1ae2c2 8275void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8276 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8277{
9bcb3eef
DS
8278 struct bgp_dest *child;
8279 struct bgp_dest *dest;
d62a17ae 8280 struct bgp_aggregate *aggregate;
8281 struct bgp_table *table;
718e3744 8282
d62a17ae 8283 table = bgp->aggregate[afi][safi];
718e3744 8284
d62a17ae 8285 /* No aggregates configured. */
8286 if (bgp_table_top_nolock(table) == NULL)
8287 return;
718e3744 8288
d62a17ae 8289 if (p->prefixlen == 0)
8290 return;
718e3744 8291
d62a17ae 8292 child = bgp_node_get(table, p);
718e3744 8293
d62a17ae 8294 /* Aggregate address configuration check. */
9bcb3eef
DS
8295 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8296 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8297
9bcb3eef
DS
8298 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8299 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8300 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8301 aggregate, dest_p);
d62a17ae 8302 }
b1e62edd 8303 }
9bcb3eef 8304 bgp_dest_unlock_node(child);
d62a17ae 8305}
718e3744 8306
718e3744 8307/* Aggregate route attribute. */
8308#define AGGREGATE_SUMMARY_ONLY 1
8309#define AGGREGATE_AS_SET 1
fb29348a 8310#define AGGREGATE_AS_UNSET 0
718e3744 8311
229757f1
DA
8312static const char *bgp_origin2str(uint8_t origin)
8313{
8314 switch (origin) {
8315 case BGP_ORIGIN_IGP:
8316 return "igp";
8317 case BGP_ORIGIN_EGP:
8318 return "egp";
8319 case BGP_ORIGIN_INCOMPLETE:
8320 return "incomplete";
8321 }
8322 return "n/a";
8323}
8324
fdeb5a81 8325static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8326{
8327 switch (v_state) {
fdeb5a81
DS
8328 case RPKI_NOT_BEING_USED:
8329 return "not used";
8330 case RPKI_VALID:
b5b99af8 8331 return "valid";
fdeb5a81 8332 case RPKI_NOTFOUND:
b5b99af8 8333 return "not found";
fdeb5a81 8334 case RPKI_INVALID:
b5b99af8 8335 return "invalid";
b5b99af8 8336 }
fdeb5a81
DS
8337
8338 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8339 return "ERROR";
8340}
8341
585f1adc
IR
8342static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8343 afi_t afi, safi_t safi)
718e3744 8344{
585f1adc
IR
8345 VTY_DECLVAR_CONTEXT(bgp, bgp);
8346 int ret;
8347 struct prefix p;
9bcb3eef 8348 struct bgp_dest *dest;
d62a17ae 8349 struct bgp_aggregate *aggregate;
718e3744 8350
585f1adc
IR
8351 /* Convert string to prefix structure. */
8352 ret = str2prefix(prefix_str, &p);
8353 if (!ret) {
8354 vty_out(vty, "Malformed prefix\n");
8355 return CMD_WARNING_CONFIG_FAILED;
8356 }
8357 apply_mask(&p);
a4559740 8358
d62a17ae 8359 /* Old configuration check. */
585f1adc 8360 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8361 if (!dest) {
585f1adc
IR
8362 vty_out(vty,
8363 "%% There is no aggregate-address configuration.\n");
8364 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8365 }
f6269b4f 8366
9bcb3eef 8367 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8368 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8369 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8370 NULL, NULL, 0, aggregate);
d62a17ae 8371
8372 /* Unlock aggregate address configuration. */
9bcb3eef 8373 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841 8374
7a70d990 8375 bgp_free_aggregate_info(aggregate);
9bcb3eef
DS
8376 bgp_dest_unlock_node(dest);
8377 bgp_dest_unlock_node(dest);
d62a17ae 8378
585f1adc 8379 return CMD_SUCCESS;
d62a17ae 8380}
8381
585f1adc
IR
8382static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8383 safi_t safi, const char *rmap,
8384 uint8_t summary_only, uint8_t as_set,
8385 uint8_t origin, bool match_med,
8386 const char *suppress_map)
d62a17ae 8387{
585f1adc 8388 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8389 int ret;
585f1adc 8390 struct prefix p;
9bcb3eef 8391 struct bgp_dest *dest;
d62a17ae 8392 struct bgp_aggregate *aggregate;
fb29348a 8393 uint8_t as_set_new = as_set;
d62a17ae 8394
365ab2e7 8395 if (suppress_map && summary_only) {
585f1adc 8396 vty_out(vty,
365ab2e7 8397 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8398 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8399 }
8400
585f1adc
IR
8401 /* Convert string to prefix structure. */
8402 ret = str2prefix(prefix_str, &p);
8403 if (!ret) {
8404 vty_out(vty, "Malformed prefix\n");
8405 return CMD_WARNING_CONFIG_FAILED;
8406 }
8407 apply_mask(&p);
d62a17ae 8408
585f1adc
IR
8409 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8410 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8411 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8412 prefix_str);
8413 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8414 }
8415
d62a17ae 8416 /* Old configuration check. */
585f1adc 8417 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8418 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8419
20894f50 8420 if (aggregate) {
585f1adc 8421 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8422 /* try to remove the old entry */
585f1adc 8423 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8424 if (ret) {
585f1adc 8425 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8426 bgp_dest_unlock_node(dest);
585f1adc 8427 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8428 }
8429 }
718e3744 8430
d62a17ae 8431 /* Make aggregate address structure. */
8432 aggregate = bgp_aggregate_new();
8433 aggregate->summary_only = summary_only;
6aabb15d 8434 aggregate->match_med = match_med;
fb29348a
DA
8435
8436 /* Network operators MUST NOT locally generate any new
8437 * announcements containing AS_SET or AS_CONFED_SET. If they have
8438 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8439 * SHOULD withdraw those routes and re-announce routes for the
8440 * aggregate or component prefixes (i.e., the more-specific routes
8441 * subsumed by the previously aggregated route) without AS_SET
8442 * or AS_CONFED_SET in the updates.
8443 */
7f972cd8 8444 if (bgp->reject_as_sets) {
fb29348a
DA
8445 if (as_set == AGGREGATE_AS_SET) {
8446 as_set_new = AGGREGATE_AS_UNSET;
8447 zlog_warn(
63efca0e 8448 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8449 __func__);
585f1adc 8450 vty_out(vty,
fb29348a
DA
8451 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8452 }
8453 }
8454
8455 aggregate->as_set = as_set_new;
d62a17ae 8456 aggregate->safi = safi;
229757f1
DA
8457 /* Override ORIGIN attribute if defined.
8458 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8459 * to IGP which is not what rfc4271 says.
8460 * This enables the same behavior, optionally.
8461 */
8462 aggregate->origin = origin;
20894f50
DA
8463
8464 if (rmap) {
8465 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8466 route_map_counter_decrement(aggregate->rmap.map);
8467 aggregate->rmap.name =
8468 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8469 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8470 route_map_counter_increment(aggregate->rmap.map);
8471 }
365ab2e7
RZ
8472
8473 if (suppress_map) {
8474 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8475 route_map_counter_decrement(aggregate->suppress_map);
8476
8477 aggregate->suppress_map_name =
8478 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8479 aggregate->suppress_map =
8480 route_map_lookup_by_name(aggregate->suppress_map_name);
8481 route_map_counter_increment(aggregate->suppress_map);
8482 }
8483
9bcb3eef 8484 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8485
d62a17ae 8486 /* Aggregate address insert into BGP routing table. */
9bea1b4b
DA
8487 if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8488 bgp_aggregate_free(aggregate);
8489 bgp_dest_unlock_node(dest);
8490 }
718e3744 8491
585f1adc 8492 return CMD_SUCCESS;
718e3744 8493}
8494
585f1adc
IR
8495DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8496 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8497 "as-set$as_set_s"
8498 "|summary-only$summary_only"
cacba915 8499 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8500 "|origin <egp|igp|incomplete>$origin_s"
8501 "|matching-MED-only$match_med"
cacba915 8502 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8503 "}]",
8504 NO_STR
8505 "Configure BGP aggregate entries\n"
764402fe
DA
8506 "Aggregate prefix\n"
8507 "Aggregate address\n"
8508 "Aggregate mask\n"
585f1adc
IR
8509 "Generate AS set path information\n"
8510 "Filter more specific routes from updates\n"
8511 "Apply route map to aggregate network\n"
8512 "Route map name\n"
8513 "BGP origin code\n"
8514 "Remote EGP\n"
8515 "Local IGP\n"
8516 "Unknown heritage\n"
8517 "Only aggregate routes with matching MED\n"
8518 "Suppress the selected more specific routes\n"
8519 "Route map with the route selectors\n")
8520{
8521 const char *prefix_s = NULL;
554b3b10 8522 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8523 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8524 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8525 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8526
554b3b10 8527 if (addr_str) {
7533cad7
QY
8528 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8529 sizeof(prefix_buf))
554b3b10
RZ
8530 == 0) {
8531 vty_out(vty, "%% Inconsistent address and mask\n");
8532 return CMD_WARNING_CONFIG_FAILED;
8533 }
585f1adc
IR
8534 prefix_s = prefix_buf;
8535 } else
8536 prefix_s = prefix_str;
37a87b8f 8537
585f1adc
IR
8538 if (origin_s) {
8539 if (strcmp(origin_s, "egp") == 0)
8540 origin = BGP_ORIGIN_EGP;
8541 else if (strcmp(origin_s, "igp") == 0)
8542 origin = BGP_ORIGIN_IGP;
8543 else if (strcmp(origin_s, "incomplete") == 0)
8544 origin = BGP_ORIGIN_INCOMPLETE;
8545 }
90e21f35 8546
585f1adc
IR
8547 if (as_set_s)
8548 as_set = AGGREGATE_AS_SET;
554b3b10 8549
585f1adc 8550 /* Handle configuration removal, otherwise installation. */
554b3b10 8551 if (no)
585f1adc
IR
8552 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8553
8554 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8555 summary_only != NULL, as_set, origin,
8556 match_med != NULL, suppress_map);
8557}
8558
7a70d990
SB
8559void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
8560{
8561 if (aggregate->community)
8562 community_free(&aggregate->community);
8563
8564 hash_clean_and_free(&aggregate->community_hash,
8565 bgp_aggr_community_remove);
8566
8567 if (aggregate->ecommunity)
8568 ecommunity_free(&aggregate->ecommunity);
8569
8570 hash_clean_and_free(&aggregate->ecommunity_hash,
8571 bgp_aggr_ecommunity_remove);
8572
8573 if (aggregate->lcommunity)
8574 lcommunity_free(&aggregate->lcommunity);
8575
8576 hash_clean_and_free(&aggregate->lcommunity_hash,
8577 bgp_aggr_lcommunity_remove);
8578
8579 if (aggregate->aspath)
8580 aspath_free(aggregate->aspath);
8581
8582 hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
8583
8584 bgp_aggregate_free(aggregate);
8585}
8586
585f1adc
IR
8587DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8588 "[no] aggregate-address X:X::X:X/M$prefix [{"
8589 "as-set$as_set_s"
8590 "|summary-only$summary_only"
cacba915 8591 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8592 "|origin <egp|igp|incomplete>$origin_s"
8593 "|matching-MED-only$match_med"
cacba915 8594 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8595 "}]",
8596 NO_STR
8597 "Configure BGP aggregate entries\n"
8598 "Aggregate prefix\n"
8599 "Generate AS set path information\n"
8600 "Filter more specific routes from updates\n"
8601 "Apply route map to aggregate network\n"
8602 "Route map name\n"
8603 "BGP origin code\n"
8604 "Remote EGP\n"
8605 "Local IGP\n"
8606 "Unknown heritage\n"
8607 "Only aggregate routes with matching MED\n"
8608 "Suppress the selected more specific routes\n"
8609 "Route map with the route selectors\n")
8610{
8611 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8612 int as_set = AGGREGATE_AS_UNSET;
8613
8614 if (origin_s) {
8615 if (strcmp(origin_s, "egp") == 0)
8616 origin = BGP_ORIGIN_EGP;
8617 else if (strcmp(origin_s, "igp") == 0)
8618 origin = BGP_ORIGIN_IGP;
8619 else if (strcmp(origin_s, "incomplete") == 0)
8620 origin = BGP_ORIGIN_INCOMPLETE;
8621 }
8622
8623 if (as_set_s)
8624 as_set = AGGREGATE_AS_SET;
8625
8626 /* Handle configuration removal, otherwise installation. */
554b3b10 8627 if (no)
585f1adc
IR
8628 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8629 SAFI_UNICAST);
554b3b10 8630
585f1adc
IR
8631 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8632 rmap_name, summary_only != NULL, as_set,
8633 origin, match_med != NULL, suppress_map);
718e3744 8634}
8635
718e3744 8636/* Redistribute route treatment. */
d62a17ae 8637void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8638 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8639 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8640 enum blackhole_type bhtype, uint32_t metric,
8641 uint8_t type, unsigned short instance,
8642 route_tag_t tag)
d62a17ae 8643{
4b7e6066 8644 struct bgp_path_info *new;
40381db7
DS
8645 struct bgp_path_info *bpi;
8646 struct bgp_path_info rmap_path;
9bcb3eef 8647 struct bgp_dest *bn;
d62a17ae 8648 struct attr attr;
8649 struct attr *new_attr;
8650 afi_t afi;
b68885f9 8651 route_map_result_t ret;
d62a17ae 8652 struct bgp_redist *red;
8653
8654 /* Make default attribute. */
0f05ea43 8655 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8656 /*
8657 * This must not be NULL to satisfy Coverity SA
8658 */
8659 assert(attr.aspath);
9de1f7ff 8660
a4d82a8a 8661 switch (nhtype) {
9de1f7ff 8662 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8663 switch (p->family) {
8664 case AF_INET:
8665 attr.nexthop.s_addr = INADDR_ANY;
8666 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8667 break;
8668 case AF_INET6:
8669 memset(&attr.mp_nexthop_global, 0,
8670 sizeof(attr.mp_nexthop_global));
8671 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8672 break;
8673 }
9de1f7ff
DS
8674 break;
8675 case NEXTHOP_TYPE_IPV4:
8676 case NEXTHOP_TYPE_IPV4_IFINDEX:
8677 attr.nexthop = nexthop->ipv4;
7226bc40 8678 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8679 break;
8680 case NEXTHOP_TYPE_IPV6:
8681 case NEXTHOP_TYPE_IPV6_IFINDEX:
8682 attr.mp_nexthop_global = nexthop->ipv6;
8683 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8684 break;
8685 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8686 switch (p->family) {
8687 case AF_INET:
9de1f7ff 8688 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8689 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8690 break;
8691 case AF_INET6:
9de1f7ff
DS
8692 memset(&attr.mp_nexthop_global, 0,
8693 sizeof(attr.mp_nexthop_global));
74489921 8694 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8695 break;
74489921 8696 }
0789eb69 8697 attr.bh_type = bhtype;
9de1f7ff 8698 break;
d62a17ae 8699 }
0789eb69 8700 attr.nh_type = nhtype;
74489921 8701 attr.nh_ifindex = ifindex;
f04a80a5 8702
d62a17ae 8703 attr.med = metric;
957f74c3 8704 attr.distance = distance;
d62a17ae 8705 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8706 attr.tag = tag;
718e3744 8707
97a52c82
DA
8708 if (metric)
8709 bgp_attr_set_aigp_metric(&attr, metric);
8710
d62a17ae 8711 afi = family2afi(p->family);
6aeb9e78 8712
d62a17ae 8713 red = bgp_redist_lookup(bgp, afi, type, instance);
8714 if (red) {
8715 struct attr attr_new;
718e3744 8716
d62a17ae 8717 /* Copy attribute for modification. */
6f4f49b2 8718 attr_new = attr;
718e3744 8719
97a52c82 8720 if (red->redist_metric_flag) {
d62a17ae 8721 attr_new.med = red->redist_metric;
97a52c82
DA
8722 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8723 }
718e3744 8724
d62a17ae 8725 /* Apply route-map. */
8726 if (red->rmap.name) {
6006b807 8727 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8728 rmap_path.peer = bgp->peer_self;
8729 rmap_path.attr = &attr_new;
718e3744 8730
d62a17ae 8731 SET_FLAG(bgp->peer_self->rmap_type,
8732 PEER_RMAP_TYPE_REDISTRIBUTE);
8733
1782514f 8734 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8735
8736 bgp->peer_self->rmap_type = 0;
8737
8738 if (ret == RMAP_DENYMATCH) {
8739 /* Free uninterned attribute. */
8740 bgp_attr_flush(&attr_new);
8741
8742 /* Unintern original. */
8743 aspath_unintern(&attr.aspath);
8744 bgp_redistribute_delete(bgp, p, type, instance);
8745 return;
8746 }
8747 }
8748
637e5ba4 8749 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8750 bgp_attr_add_gshut_community(&attr_new);
8751
d62a17ae 8752 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8753 SAFI_UNICAST, p, NULL);
8754
8755 new_attr = bgp_attr_intern(&attr_new);
8756
9bcb3eef 8757 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8758 if (bpi->peer == bgp->peer_self
8759 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8760 break;
8761
40381db7 8762 if (bpi) {
d62a17ae 8763 /* Ensure the (source route) type is updated. */
40381db7
DS
8764 bpi->type = type;
8765 if (attrhash_cmp(bpi->attr, new_attr)
8766 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8767 bgp_attr_unintern(&new_attr);
8768 aspath_unintern(&attr.aspath);
9bcb3eef 8769 bgp_dest_unlock_node(bn);
d62a17ae 8770 return;
8771 } else {
8772 /* The attribute is changed. */
40381db7 8773 bgp_path_info_set_flag(bn, bpi,
18ee8310 8774 BGP_PATH_ATTR_CHANGED);
d62a17ae 8775
8776 /* Rewrite BGP route information. */
40381db7
DS
8777 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8778 bgp_path_info_restore(bn, bpi);
d62a17ae 8779 else
40381db7
DS
8780 bgp_aggregate_decrement(
8781 bgp, p, bpi, afi, SAFI_UNICAST);
8782 bgp_attr_unintern(&bpi->attr);
8783 bpi->attr = new_attr;
083ec940 8784 bpi->uptime = monotime(NULL);
d62a17ae 8785
8786 /* Process change. */
40381db7 8787 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8788 SAFI_UNICAST);
8789 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8790 bgp_dest_unlock_node(bn);
d62a17ae 8791 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8792
8793 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8794 || (bgp->inst_type
8795 == BGP_INSTANCE_TYPE_DEFAULT)) {
8796
8797 vpn_leak_from_vrf_update(
40381db7 8798 bgp_get_default(), bgp, bpi);
ddb5b488 8799 }
d62a17ae 8800 return;
8801 }
8802 }
8803
8804 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8805 bgp->peer_self, new_attr, bn);
1defdda8 8806 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8807
8808 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8809 bgp_path_info_add(bn, new);
9bcb3eef 8810 bgp_dest_unlock_node(bn);
be785e35 8811 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8812 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8813
8814 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8815 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8816
8817 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8818 }
d62a17ae 8819 }
8820
8821 /* Unintern original. */
8822 aspath_unintern(&attr.aspath);
718e3744 8823}
8824
d7c0a89a
QY
8825void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8826 unsigned short instance)
718e3744 8827{
d62a17ae 8828 afi_t afi;
9bcb3eef 8829 struct bgp_dest *dest;
40381db7 8830 struct bgp_path_info *pi;
d62a17ae 8831 struct bgp_redist *red;
718e3744 8832
d62a17ae 8833 afi = family2afi(p->family);
718e3744 8834
d62a17ae 8835 red = bgp_redist_lookup(bgp, afi, type, instance);
8836 if (red) {
9bcb3eef
DS
8837 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8838 SAFI_UNICAST, p, NULL);
d62a17ae 8839
9bcb3eef 8840 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8841 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8842 break;
8843
40381db7 8844 if (pi) {
ddb5b488
PZ
8845 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8846 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8847
8848 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8849 bgp, pi);
ddb5b488 8850 }
40381db7 8851 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8852 bgp_path_info_delete(dest, pi);
8853 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8854 }
9bcb3eef 8855 bgp_dest_unlock_node(dest);
d62a17ae 8856 }
8857}
8858
8859/* Withdraw specified route type's route. */
8860void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8861 unsigned short instance)
d62a17ae 8862{
9bcb3eef 8863 struct bgp_dest *dest;
40381db7 8864 struct bgp_path_info *pi;
d62a17ae 8865 struct bgp_table *table;
8866
8867 table = bgp->rib[afi][SAFI_UNICAST];
8868
9bcb3eef
DS
8869 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8870 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8871 if (pi->peer == bgp->peer_self && pi->type == type
8872 && pi->instance == instance)
d62a17ae 8873 break;
8874
40381db7 8875 if (pi) {
ddb5b488
PZ
8876 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8877 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8878
8879 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8880 bgp, pi);
ddb5b488 8881 }
9bcb3eef 8882 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8883 pi, afi, SAFI_UNICAST);
9bcb3eef 8884 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8885 if (!CHECK_FLAG(bgp->flags,
8886 BGP_FLAG_DELETE_IN_PROGRESS))
8887 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8888 else
8889 bgp_path_info_reap(dest, pi);
d62a17ae 8890 }
718e3744 8891 }
718e3744 8892}
6b0655a2 8893
718e3744 8894/* Static function to display route. */
7d3cae70
DA
8895static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8896 struct vty *vty, json_object *json, bool wide)
718e3744 8897{
be054588 8898 int len = 0;
07380148 8899 char buf[INET6_ADDRSTRLEN];
718e3744 8900
d62a17ae 8901 if (p->family == AF_INET) {
c6462ff4 8902 if (!json) {
8228a9a7 8903 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8904 } else {
8905 json_object_string_add(json, "prefix",
8906 inet_ntop(p->family,
8907 &p->u.prefix, buf,
07380148 8908 sizeof(buf)));
c6462ff4 8909 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8910 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8911 json_object_int_add(json, "version", dest->version);
c6462ff4 8912 }
d62a17ae 8913 } else if (p->family == AF_ETHERNET) {
8228a9a7 8914 len = vty_out(vty, "%pFX", p);
b03b8898 8915 } else if (p->family == AF_EVPN) {
57f7feb6 8916 if (!json)
2dbe669b 8917 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8918 else
60466a63 8919 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8920 } else if (p->family == AF_FLOWSPEC) {
8921 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8922 json ?
8923 NLRI_STRING_FORMAT_JSON_SIMPLE :
8924 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8925 } else {
c6462ff4 8926 if (!json)
8228a9a7 8927 len = vty_out(vty, "%pFX", p);
50e05855
AD
8928 else {
8929 json_object_string_add(json, "prefix",
07380148
DA
8930 inet_ntop(p->family,
8931 &p->u.prefix, buf,
8932 sizeof(buf)));
50e05855 8933 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8934 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8935 json_object_int_add(json, "version", dest->version);
37d4e0df 8936 }
9c92b5f7 8937 }
d62a17ae 8938
9c92b5f7 8939 if (!json) {
ae248832 8940 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8941 if (len < 1)
8942 vty_out(vty, "\n%*s", 20, " ");
8943 else
8944 vty_out(vty, "%*s", len, " ");
8945 }
718e3744 8946}
8947
d62a17ae 8948enum bgp_display_type {
8949 normal_list,
718e3744 8950};
8951
1d7260a1 8952const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8953{
8954 switch (reason) {
8955 case bgp_path_selection_none:
8956 return "Nothing to Select";
8957 case bgp_path_selection_first:
8958 return "First path received";
8959 case bgp_path_selection_evpn_sticky_mac:
8960 return "EVPN Sticky Mac";
8961 case bgp_path_selection_evpn_seq:
8962 return "EVPN sequence number";
8963 case bgp_path_selection_evpn_lower_ip:
8964 return "EVPN lower IP";
8965 case bgp_path_selection_evpn_local_path:
8966 return "EVPN local ES path";
8967 case bgp_path_selection_evpn_non_proxy:
8968 return "EVPN non proxy";
8969 case bgp_path_selection_weight:
8970 return "Weight";
8971 case bgp_path_selection_local_pref:
8972 return "Local Pref";
46dbf9d0
DA
8973 case bgp_path_selection_accept_own:
8974 return "Accept Own";
bbb46eb5
DA
8975 case bgp_path_selection_local_route:
8976 return "Local Route";
97a52c82
DA
8977 case bgp_path_selection_aigp:
8978 return "AIGP";
bbb46eb5
DA
8979 case bgp_path_selection_confed_as_path:
8980 return "Confederation based AS Path";
8981 case bgp_path_selection_as_path:
8982 return "AS Path";
8983 case bgp_path_selection_origin:
8984 return "Origin";
8985 case bgp_path_selection_med:
8986 return "MED";
8987 case bgp_path_selection_peer:
8988 return "Peer Type";
8989 case bgp_path_selection_confed:
8990 return "Confed Peer Type";
8991 case bgp_path_selection_igp_metric:
8992 return "IGP Metric";
8993 case bgp_path_selection_older:
8994 return "Older Path";
8995 case bgp_path_selection_router_id:
8996 return "Router ID";
8997 case bgp_path_selection_cluster_length:
bcab253c 8998 return "Cluster length";
bbb46eb5
DA
8999 case bgp_path_selection_stale:
9000 return "Path Staleness";
9001 case bgp_path_selection_local_configured:
9002 return "Locally configured route";
9003 case bgp_path_selection_neighbor_ip:
9004 return "Neighbor IP";
9005 case bgp_path_selection_default:
9006 return "Nothing left to compare";
9007 }
9008 return "Invalid (internal error)";
9009}
9010
18ee8310 9011/* Print the short form route status for a bgp_path_info */
4b7e6066 9012static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9013 struct bgp_path_info *path,
82c298be 9014 const struct prefix *p,
d62a17ae 9015 json_object *json_path)
718e3744 9016{
82c298be
DA
9017 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9018
d62a17ae 9019 if (json_path) {
b05a1c8b 9020
d62a17ae 9021 /* Route status display. */
9b6d8fcf 9022 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9023 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9024
9b6d8fcf 9025 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9026 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9027
4056a5f6 9028 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9029 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9030
9b6d8fcf
DS
9031 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9032 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9033 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9034
d62a17ae 9035 /* Selected */
9b6d8fcf 9036 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9037 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9038
9b6d8fcf 9039 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9040 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9041
bbb46eb5 9042 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9043 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9044 json_object_string_add(json_path, "selectionReason",
9045 bgp_path_selection_reason2str(
9046 path->net->reason));
9047 }
b05a1c8b 9048
9b6d8fcf 9049 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9050 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9051
d62a17ae 9052 /* Internal route. */
9b6d8fcf
DS
9053 if ((path->peer->as)
9054 && (path->peer->as == path->peer->local_as))
d62a17ae 9055 json_object_string_add(json_path, "pathFrom",
9056 "internal");
9057 else
9058 json_object_string_add(json_path, "pathFrom",
9059 "external");
b05a1c8b 9060
d62a17ae 9061 return;
9062 }
b05a1c8b 9063
82c298be
DA
9064 /* RPKI validation state */
9065 rpki_state =
9066 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9067
9068 if (rpki_state == RPKI_VALID)
9069 vty_out(vty, "V");
9070 else if (rpki_state == RPKI_INVALID)
9071 vty_out(vty, "I");
9072 else if (rpki_state == RPKI_NOTFOUND)
9073 vty_out(vty, "N");
eaeba5e8
WM
9074 else
9075 vty_out(vty, " ");
82c298be 9076
d62a17ae 9077 /* Route status display. */
9b6d8fcf 9078 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9079 vty_out(vty, "R");
9b6d8fcf 9080 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9081 vty_out(vty, "S");
4056a5f6 9082 else if (bgp_path_suppressed(path))
d62a17ae 9083 vty_out(vty, "s");
9b6d8fcf
DS
9084 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9085 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9086 vty_out(vty, "*");
9087 else
9088 vty_out(vty, " ");
9089
9090 /* Selected */
9b6d8fcf 9091 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9092 vty_out(vty, "h");
9b6d8fcf 9093 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9094 vty_out(vty, "d");
9b6d8fcf 9095 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9096 vty_out(vty, ">");
9b6d8fcf 9097 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9098 vty_out(vty, "=");
9099 else
9100 vty_out(vty, " ");
718e3744 9101
d62a17ae 9102 /* Internal route. */
9b6d8fcf
DS
9103 if (path->peer && (path->peer->as)
9104 && (path->peer->as == path->peer->local_as))
d62a17ae 9105 vty_out(vty, "i");
9106 else
9107 vty_out(vty, " ");
b40d939b 9108}
9109
2ba93fd6
DA
9110static char *bgp_nexthop_hostname(struct peer *peer,
9111 struct bgp_nexthop_cache *bnc)
25b5da8d 9112{
892fedb6 9113 if (peer->hostname
aef999a2 9114 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9115 return peer->hostname;
9116 return NULL;
9117}
9118
b40d939b 9119/* called from terminal list command */
bd494ec5 9120void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9121 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9122 json_object *json_paths, bool wide)
d62a17ae 9123{
aef999a2 9124 int len;
515c2602 9125 struct attr *attr = path->attr;
d62a17ae 9126 json_object *json_path = NULL;
9127 json_object *json_nexthops = NULL;
9128 json_object *json_nexthop_global = NULL;
9129 json_object *json_nexthop_ll = NULL;
6f214dd3 9130 json_object *json_ext_community = NULL;
9df8b37c 9131 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9132 bool nexthop_self =
9b6d8fcf 9133 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9134 bool nexthop_othervrf = false;
43089216 9135 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9136 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9137 char *nexthop_hostname =
9138 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9139 char esi_buf[ESI_STR_LEN];
d62a17ae 9140
9141 if (json_paths)
9142 json_path = json_object_new_object();
9143
9144 /* short status lead text */
82c298be 9145 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9146
9147 if (!json_paths) {
9148 /* print prefix and mask */
9149 if (!display)
7d3cae70 9150 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9151 else
ae248832 9152 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9153 } else {
7d3cae70 9154 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9155 }
47fc97cc 9156
9df8b37c
PZ
9157 /*
9158 * If vrf id of nexthop is different from that of prefix,
9159 * set up printable string to append
9160 */
9b6d8fcf 9161 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9162 const char *self = "";
9163
9164 if (nexthop_self)
9165 self = "<";
9166
9167 nexthop_othervrf = true;
9b6d8fcf 9168 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9169
9b6d8fcf 9170 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9171 snprintf(vrf_id_str, sizeof(vrf_id_str),
9172 "@%s%s", VRFID_NONE_STR, self);
9173 else
9174 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9175 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9176
9b6d8fcf
DS
9177 if (path->extra->bgp_orig->inst_type
9178 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9179
9b6d8fcf 9180 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9181 } else {
9182 const char *self = "";
9183
9184 if (nexthop_self)
9185 self = "<";
9186
9187 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9188 }
9189
445c2480
DS
9190 /*
9191 * For ENCAP and EVPN routes, nexthop address family is not
9192 * neccessarily the same as the prefix address family.
9193 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9194 * EVPN routes are also exchanged with a MP nexthop. Currently,
9195 * this
9196 * is only IPv4, the value will be present in either
9197 * attr->nexthop or
9198 * attr->mp_nexthop_global_in
9199 */
9200 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9201 char nexthop[128];
9202 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9203
9204 switch (af) {
9205 case AF_INET:
07380148
DA
9206 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9207 &attr->mp_nexthop_global_in);
445c2480
DS
9208 break;
9209 case AF_INET6:
07380148
DA
9210 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9211 &attr->mp_nexthop_global);
445c2480
DS
9212 break;
9213 default:
772270f3 9214 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9215 break;
d62a17ae 9216 }
d62a17ae 9217
445c2480
DS
9218 if (json_paths) {
9219 json_nexthop_global = json_object_new_object();
9220
515c2602
DA
9221 json_object_string_add(json_nexthop_global, "ip",
9222 nexthop);
9223
939a97f4 9224 if (path->peer->hostname)
515c2602
DA
9225 json_object_string_add(json_nexthop_global,
9226 "hostname",
939a97f4 9227 path->peer->hostname);
515c2602
DA
9228
9229 json_object_string_add(json_nexthop_global, "afi",
9230 (af == AF_INET) ? "ipv4"
9231 : "ipv6");
445c2480
DS
9232 json_object_boolean_true_add(json_nexthop_global,
9233 "used");
aef999a2
DA
9234 } else {
9235 if (nexthop_hostname)
9236 len = vty_out(vty, "%s(%s)%s", nexthop,
9237 nexthop_hostname, vrf_id_str);
9238 else
9239 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9240
ae248832 9241 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9242 if (len < 1)
9243 vty_out(vty, "\n%*s", 36, " ");
9244 else
9245 vty_out(vty, "%*s", len, " ");
9246 }
445c2480
DS
9247 } else if (safi == SAFI_EVPN) {
9248 if (json_paths) {
9249 json_nexthop_global = json_object_new_object();
9250
c949c771 9251 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9252 "%pI4",
9253 &attr->mp_nexthop_global_in);
515c2602 9254
939a97f4 9255 if (path->peer->hostname)
515c2602
DA
9256 json_object_string_add(json_nexthop_global,
9257 "hostname",
939a97f4 9258 path->peer->hostname);
515c2602 9259
a4d82a8a
PZ
9260 json_object_string_add(json_nexthop_global, "afi",
9261 "ipv4");
445c2480
DS
9262 json_object_boolean_true_add(json_nexthop_global,
9263 "used");
aef999a2
DA
9264 } else {
9265 if (nexthop_hostname)
7226bc40
TA
9266 len = vty_out(vty, "%pI4(%s)%s",
9267 &attr->mp_nexthop_global_in,
aef999a2
DA
9268 nexthop_hostname, vrf_id_str);
9269 else
7226bc40
TA
9270 len = vty_out(vty, "%pI4%s",
9271 &attr->mp_nexthop_global_in,
aef999a2
DA
9272 vrf_id_str);
9273
ae248832 9274 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9275 if (len < 1)
9276 vty_out(vty, "\n%*s", 36, " ");
9277 else
9278 vty_out(vty, "%*s", len, " ");
9279 }
d33fc23b 9280 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9281 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9282 if (json_paths) {
9283 json_nexthop_global = json_object_new_object();
515c2602 9284
026b914a
PG
9285 json_object_string_add(json_nexthop_global,
9286 "afi", "ipv4");
c949c771
DA
9287 json_object_string_addf(json_nexthop_global,
9288 "ip", "%pI4",
9289 &attr->nexthop);
515c2602 9290
939a97f4 9291 if (path->peer->hostname)
515c2602
DA
9292 json_object_string_add(
9293 json_nexthop_global, "hostname",
939a97f4 9294 path->peer->hostname);
515c2602 9295
50e05855
AD
9296 json_object_boolean_true_add(
9297 json_nexthop_global,
026b914a
PG
9298 "used");
9299 } else {
aef999a2
DA
9300 if (nexthop_hostname)
9301 len = vty_out(vty, "%pI4(%s)%s",
9302 &attr->nexthop,
9303 nexthop_hostname,
9304 vrf_id_str);
9305 else
9306 len = vty_out(vty, "%pI4%s",
9307 &attr->nexthop,
9308 vrf_id_str);
9309
ae248832 9310 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9311 if (len < 1)
9312 vty_out(vty, "\n%*s", 36, " ");
9313 else
9314 vty_out(vty, "%*s", len, " ");
026b914a
PG
9315 }
9316 }
7226bc40 9317 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9318 if (json_paths) {
9319 json_nexthop_global = json_object_new_object();
d62a17ae 9320
c949c771
DA
9321 json_object_string_addf(json_nexthop_global, "ip",
9322 "%pI4", &attr->nexthop);
515c2602 9323
939a97f4 9324 if (path->peer->hostname)
515c2602
DA
9325 json_object_string_add(json_nexthop_global,
9326 "hostname",
939a97f4 9327 path->peer->hostname);
445c2480 9328
a4d82a8a
PZ
9329 json_object_string_add(json_nexthop_global, "afi",
9330 "ipv4");
445c2480
DS
9331 json_object_boolean_true_add(json_nexthop_global,
9332 "used");
9333 } else {
aef999a2
DA
9334 if (nexthop_hostname)
9335 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9336 nexthop_hostname, vrf_id_str);
9337 else
9338 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9339 vrf_id_str);
9df8b37c 9340
ae248832 9341 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9342 if (len < 1)
9343 vty_out(vty, "\n%*s", 36, " ");
9344 else
9345 vty_out(vty, "%*s", len, " ");
d62a17ae 9346 }
445c2480 9347 }
b05a1c8b 9348
445c2480 9349 /* IPv6 Next Hop */
7226bc40 9350 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9351 if (json_paths) {
9352 json_nexthop_global = json_object_new_object();
c949c771
DA
9353 json_object_string_addf(json_nexthop_global, "ip",
9354 "%pI6",
9355 &attr->mp_nexthop_global);
515c2602 9356
939a97f4 9357 if (path->peer->hostname)
515c2602
DA
9358 json_object_string_add(json_nexthop_global,
9359 "hostname",
939a97f4 9360 path->peer->hostname);
515c2602 9361
a4d82a8a
PZ
9362 json_object_string_add(json_nexthop_global, "afi",
9363 "ipv6");
9364 json_object_string_add(json_nexthop_global, "scope",
9365 "global");
445c2480
DS
9366
9367 /* We display both LL & GL if both have been
9368 * received */
0606039c
DA
9369 if ((attr->mp_nexthop_len
9370 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9371 || (path->peer->conf_if)) {
a4d82a8a 9372 json_nexthop_ll = json_object_new_object();
c949c771
DA
9373 json_object_string_addf(
9374 json_nexthop_ll, "ip", "%pI6",
9375 &attr->mp_nexthop_local);
515c2602 9376
939a97f4 9377 if (path->peer->hostname)
515c2602
DA
9378 json_object_string_add(
9379 json_nexthop_ll, "hostname",
939a97f4 9380 path->peer->hostname);
515c2602 9381
a4d82a8a
PZ
9382 json_object_string_add(json_nexthop_ll, "afi",
9383 "ipv6");
9384 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9385 "link-local");
d62a17ae 9386
a4d82a8a 9387 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9388 &attr->mp_nexthop_local)
9389 != 0)
9390 && !attr->mp_nexthop_prefer_global)
d62a17ae 9391 json_object_boolean_true_add(
a4d82a8a 9392 json_nexthop_ll, "used");
445c2480
DS
9393 else
9394 json_object_boolean_true_add(
a4d82a8a 9395 json_nexthop_global, "used");
445c2480
DS
9396 } else
9397 json_object_boolean_true_add(
9398 json_nexthop_global, "used");
9399 } else {
9400 /* Display LL if LL/Global both in table unless
9401 * prefer-global is set */
2bb8b49c
DS
9402 if (((attr->mp_nexthop_len
9403 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9404 && !attr->mp_nexthop_prefer_global)
9405 || (path->peer->conf_if)) {
9b6d8fcf 9406 if (path->peer->conf_if) {
a4d82a8a 9407 len = vty_out(vty, "%s",
9b6d8fcf 9408 path->peer->conf_if);
ae248832
MK
9409 /* len of IPv6 addr + max len of def
9410 * ifname */
9411 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9412
9413 if (len < 1)
a4d82a8a 9414 vty_out(vty, "\n%*s", 36, " ");
445c2480 9415 else
a4d82a8a 9416 vty_out(vty, "%*s", len, " ");
d62a17ae 9417 } else {
aef999a2
DA
9418 if (nexthop_hostname)
9419 len = vty_out(
9420 vty, "%pI6(%s)%s",
9421 &attr->mp_nexthop_local,
9422 nexthop_hostname,
9423 vrf_id_str);
9424 else
9425 len = vty_out(
9426 vty, "%pI6%s",
9427 &attr->mp_nexthop_local,
9428 vrf_id_str);
9429
ae248832 9430 len = wide ? (41 - len) : (16 - len);
d62a17ae 9431
9432 if (len < 1)
a4d82a8a 9433 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9434 else
a4d82a8a 9435 vty_out(vty, "%*s", len, " ");
d62a17ae 9436 }
445c2480 9437 } else {
aef999a2
DA
9438 if (nexthop_hostname)
9439 len = vty_out(vty, "%pI6(%s)%s",
9440 &attr->mp_nexthop_global,
9441 nexthop_hostname,
9442 vrf_id_str);
9443 else
9444 len = vty_out(vty, "%pI6%s",
9445 &attr->mp_nexthop_global,
9446 vrf_id_str);
9447
ae248832 9448 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9449
9450 if (len < 1)
9451 vty_out(vty, "\n%*s", 36, " ");
9452 else
9453 vty_out(vty, "%*s", len, " ");
d62a17ae 9454 }
9455 }
445c2480 9456 }
718e3744 9457
445c2480
DS
9458 /* MED/Metric */
9459 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9460 if (json_paths)
50e05855 9461 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9462 else if (wide)
9463 vty_out(vty, "%7u", attr->med);
0fbac0b4 9464 else
445c2480 9465 vty_out(vty, "%10u", attr->med);
ae248832
MK
9466 else if (!json_paths) {
9467 if (wide)
9468 vty_out(vty, "%*s", 7, " ");
9469 else
9470 vty_out(vty, "%*s", 10, " ");
9471 }
d62a17ae 9472
445c2480
DS
9473 /* Local Pref */
9474 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9475 if (json_paths)
50e05855 9476 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9477 attr->local_pref);
9478 else
445c2480
DS
9479 vty_out(vty, "%7u", attr->local_pref);
9480 else if (!json_paths)
9481 vty_out(vty, " ");
d62a17ae 9482
445c2480
DS
9483 if (json_paths)
9484 json_object_int_add(json_path, "weight", attr->weight);
9485 else
9486 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9487
47e12884
DA
9488 if (json_paths)
9489 json_object_string_addf(json_path, "peerId", "%pSU",
9490 &path->peer->su);
b05a1c8b 9491
445c2480
DS
9492 /* Print aspath */
9493 if (attr->aspath) {
0fbac0b4 9494 if (json_paths)
50e05855 9495 json_object_string_add(json_path, "path",
0fbac0b4
DA
9496 attr->aspath->str);
9497 else
e678b143 9498 aspath_print_vty(vty, attr->aspath);
d62a17ae 9499 }
f1aa5d8a 9500
445c2480
DS
9501 /* Print origin */
9502 if (json_paths)
a4d82a8a
PZ
9503 json_object_string_add(json_path, "origin",
9504 bgp_origin_long_str[attr->origin]);
445c2480
DS
9505 else
9506 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9507
9df8b37c 9508 if (json_paths) {
d071f237 9509 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9510 json_object_string_add(json_path, "esi",
9511 esi_to_str(&attr->esi,
9512 esi_buf, sizeof(esi_buf)));
9513 }
6f214dd3
CS
9514 if (safi == SAFI_EVPN &&
9515 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9516 json_ext_community = json_object_new_object();
b53e67a3
DA
9517 json_object_string_add(
9518 json_ext_community, "string",
9519 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9520 json_object_object_add(json_path,
9521 "extendedCommunity",
9522 json_ext_community);
9523 }
9524
9df8b37c
PZ
9525 if (nexthop_self)
9526 json_object_boolean_true_add(json_path,
9527 "announceNexthopSelf");
9528 if (nexthop_othervrf) {
9529 json_object_string_add(json_path, "nhVrfName",
9530 nexthop_vrfname);
9531
9532 json_object_int_add(json_path, "nhVrfId",
9533 ((nexthop_vrfid == VRF_UNKNOWN)
9534 ? -1
9535 : (int)nexthop_vrfid));
9536 }
9537 }
9538
d62a17ae 9539 if (json_paths) {
9540 if (json_nexthop_global || json_nexthop_ll) {
9541 json_nexthops = json_object_new_array();
f1aa5d8a 9542
d62a17ae 9543 if (json_nexthop_global)
9544 json_object_array_add(json_nexthops,
9545 json_nexthop_global);
f1aa5d8a 9546
d62a17ae 9547 if (json_nexthop_ll)
9548 json_object_array_add(json_nexthops,
9549 json_nexthop_ll);
f1aa5d8a 9550
d62a17ae 9551 json_object_object_add(json_path, "nexthops",
9552 json_nexthops);
9553 }
9554
9555 json_object_array_add(json_paths, json_path);
9556 } else {
9557 vty_out(vty, "\n");
6f214dd3 9558
b5e140c8 9559 if (safi == SAFI_EVPN) {
d071f237 9560 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9561 /* XXX - add these params to the json out */
b5e140c8 9562 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9563 vty_out(vty, "ESI:%s",
9564 esi_to_str(&attr->esi, esi_buf,
9565 sizeof(esi_buf)));
60605cbc 9566
229587fb 9567 vty_out(vty, "\n");
b5e140c8
AK
9568 }
9569 if (attr->flag &
9570 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9571 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9572 vty_out(vty, "%s\n",
9573 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9574 }
6f214dd3
CS
9575 }
9576
49e5a4a0 9577#ifdef ENABLE_BGP_VNC
d62a17ae 9578 /* prints an additional line, indented, with VNC info, if
9579 * present */
9580 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9581 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9582#endif
d62a17ae 9583 }
9584}
718e3744 9585
9586/* called from terminal list command */
7d3cae70
DA
9587void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9588 const struct prefix *p, struct attr *attr, safi_t safi,
9589 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9590{
9591 json_object *json_status = NULL;
9592 json_object *json_net = NULL;
aef999a2 9593 int len;
d62a17ae 9594 char buff[BUFSIZ];
dc387b0f 9595
d62a17ae 9596 /* Route status display. */
9597 if (use_json) {
9598 json_status = json_object_new_object();
9599 json_net = json_object_new_object();
9600 } else {
146c574b 9601 vty_out(vty, " *");
d62a17ae 9602 vty_out(vty, ">");
9603 vty_out(vty, " ");
9604 }
718e3744 9605
d62a17ae 9606 /* print prefix and mask */
50e05855 9607 if (use_json) {
dc387b0f
LK
9608 if (safi == SAFI_EVPN)
9609 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9610 else if (p->family == AF_INET || p->family == AF_INET6) {
9611 json_object_string_add(
9612 json_net, "addrPrefix",
9613 inet_ntop(p->family, &p->u.prefix, buff,
9614 BUFSIZ));
9615 json_object_int_add(json_net, "prefixLen",
9616 p->prefixlen);
67d7e256 9617 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9618 }
50e05855 9619 } else
7d3cae70 9620 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9621
9622 /* Print attribute */
9623 if (attr) {
9624 if (use_json) {
7226bc40
TA
9625 if (p->family == AF_INET &&
9626 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9627 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9628 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9629 json_object_string_addf(
9630 json_net, "nextHop", "%pI4",
9631 &attr->mp_nexthop_global_in);
d62a17ae 9632 else
c949c771
DA
9633 json_object_string_addf(
9634 json_net, "nextHop", "%pI4",
9635 &attr->nexthop);
7226bc40
TA
9636 } else if (p->family == AF_INET6 ||
9637 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9638 json_object_string_addf(
9639 json_net, "nextHopGlobal", "%pI6",
9640 &attr->mp_nexthop_global);
7226bc40
TA
9641 } else if (p->family == AF_EVPN &&
9642 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9643 json_object_string_addf(
9644 json_net, "nextHop", "%pI4",
9645 &attr->mp_nexthop_global_in);
23d0a753 9646 }
d62a17ae 9647
9648 if (attr->flag
9649 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9650 json_object_int_add(json_net, "metric",
9651 attr->med);
9652
0fbac0b4 9653 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9654 json_object_int_add(json_net, "locPrf",
0fbac0b4 9655 attr->local_pref);
d62a17ae 9656
9657 json_object_int_add(json_net, "weight", attr->weight);
9658
9659 /* Print aspath */
0fbac0b4 9660 if (attr->aspath)
50e05855 9661 json_object_string_add(json_net, "path",
0fbac0b4 9662 attr->aspath->str);
d62a17ae 9663
9664 /* Print origin */
dd426a51
DA
9665#if CONFDATE > 20231208
9666CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9667#endif
d62a17ae 9668 json_object_string_add(json_net, "bgpOriginCode",
9669 bgp_origin_str[attr->origin]);
dd426a51
DA
9670 json_object_string_add(
9671 json_net, "origin",
9672 bgp_origin_long_str[attr->origin]);
d62a17ae 9673 } else {
7226bc40
TA
9674 if (p->family == AF_INET &&
9675 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9676 safi == SAFI_EVPN ||
9677 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9678 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9679 || safi == SAFI_EVPN)
23d0a753
DA
9680 vty_out(vty, "%-16pI4",
9681 &attr->mp_nexthop_global_in);
ae248832 9682 else if (wide)
23d0a753 9683 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9684 else
23d0a753 9685 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9686 } else if (p->family == AF_INET6 ||
9687 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9688 len = vty_out(vty, "%pI6",
9689 &attr->mp_nexthop_global);
ae248832 9690 len = wide ? (41 - len) : (16 - len);
d62a17ae 9691 if (len < 1)
9692 vty_out(vty, "\n%*s", 36, " ");
9693 else
9694 vty_out(vty, "%*s", len, " ");
9695 }
9696 if (attr->flag
9697 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9698 if (wide)
9699 vty_out(vty, "%7u", attr->med);
9700 else
9701 vty_out(vty, "%10u", attr->med);
9702 else if (wide)
9703 vty_out(vty, " ");
d62a17ae 9704 else
9705 vty_out(vty, " ");
718e3744 9706
d62a17ae 9707 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9708 vty_out(vty, "%7u", attr->local_pref);
9709 else
9710 vty_out(vty, " ");
9711
9712 vty_out(vty, "%7u ", attr->weight);
9713
9714 /* Print aspath */
9715 if (attr->aspath)
e678b143 9716 aspath_print_vty(vty, attr->aspath);
d62a17ae 9717
9718 /* Print origin */
9719 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9720 }
9721 }
9722 if (use_json) {
4d65410c
DA
9723 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9724
dd426a51
DA
9725#if CONFDATE > 20231208
9726CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9727#endif
d62a17ae 9728 json_object_boolean_true_add(json_status, "*");
9729 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9730 json_object_boolean_true_add(json_net, "valid");
9731 json_object_boolean_true_add(json_net, "best");
4d65410c 9732
dd426a51 9733 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9734 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9735 json_object_boolean_true_add(json_net, "multipath");
9736 }
d62a17ae 9737 json_object_object_add(json_net, "appliedStatusSymbols",
9738 json_status);
511211bf 9739 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9740 } else
9741 vty_out(vty, "\n");
9742}
9743
bd494ec5 9744void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9745 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9746 json_object *json)
9747{
9748 json_object *json_out = NULL;
9749 struct attr *attr;
9750 mpls_label_t label = MPLS_INVALID_LABEL;
9751
9b6d8fcf 9752 if (!path->extra)
d62a17ae 9753 return;
9754
9755 if (json)
9756 json_out = json_object_new_object();
9757
9758 /* short status lead text */
82c298be 9759 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9760
9761 /* print prefix and mask */
9762 if (json == NULL) {
9763 if (!display)
7d3cae70 9764 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9765 else
9766 vty_out(vty, "%*s", 17, " ");
9767 }
9768
9769 /* Print attribute */
9b6d8fcf 9770 attr = path->attr;
7226bc40
TA
9771 if (((p->family == AF_INET) &&
9772 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9773 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9774 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9775 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9776 || safi == SAFI_EVPN) {
9777 if (json)
c949c771
DA
9778 json_object_string_addf(
9779 json_out, "mpNexthopGlobalIn", "%pI4",
9780 &attr->mp_nexthop_global_in);
05864da7 9781 else
23d0a753
DA
9782 vty_out(vty, "%-16pI4",
9783 &attr->mp_nexthop_global_in);
05864da7
DS
9784 } else {
9785 if (json)
c949c771
DA
9786 json_object_string_addf(json_out, "nexthop",
9787 "%pI4", &attr->nexthop);
05864da7 9788 else
23d0a753 9789 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9790 }
7226bc40
TA
9791 } else if (((p->family == AF_INET6) &&
9792 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9793 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9794 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9795 char buf_a[512];
9796
9797 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9798 if (json)
c949c771
DA
9799 json_object_string_addf(
9800 json_out, "mpNexthopGlobalIn", "%pI6",
9801 &attr->mp_nexthop_global);
05864da7
DS
9802 else
9803 vty_out(vty, "%s",
9804 inet_ntop(AF_INET6,
9805 &attr->mp_nexthop_global,
9806 buf_a, sizeof(buf_a)));
9807 } else if (attr->mp_nexthop_len
9808 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9809 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9810 &attr->mp_nexthop_global,
9811 &attr->mp_nexthop_local);
9812 if (json)
9813 json_object_string_add(json_out,
9814 "mpNexthopGlobalLocal",
9815 buf_a);
9816 else
9817 vty_out(vty, "%s", buf_a);
d62a17ae 9818 }
9819 }
9820
9b6d8fcf 9821 label = decode_label(&path->extra->label[0]);
d62a17ae 9822
9823 if (bgp_is_valid_label(&label)) {
9824 if (json) {
9825 json_object_int_add(json_out, "notag", label);
9826 json_object_array_add(json, json_out);
9827 } else {
9828 vty_out(vty, "notag/%d", label);
9829 vty_out(vty, "\n");
9830 }
700ddfed
PG
9831 } else if (!json)
9832 vty_out(vty, "\n");
d62a17ae 9833}
718e3744 9834
bd494ec5 9835void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9836 struct bgp_path_info *path, int display,
d62a17ae 9837 json_object *json_paths)
718e3744 9838{
d62a17ae 9839 struct attr *attr;
d62a17ae 9840 json_object *json_path = NULL;
14f51eba
LK
9841 json_object *json_nexthop = NULL;
9842 json_object *json_overlay = NULL;
856ca177 9843
9b6d8fcf 9844 if (!path->extra)
d62a17ae 9845 return;
718e3744 9846
14f51eba
LK
9847 if (json_paths) {
9848 json_path = json_object_new_object();
9849 json_overlay = json_object_new_object();
9850 json_nexthop = json_object_new_object();
9851 }
9852
d62a17ae 9853 /* short status lead text */
82c298be 9854 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9855
d62a17ae 9856 /* print prefix and mask */
9857 if (!display)
7d3cae70 9858 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9859 else
9860 vty_out(vty, "%*s", 17, " ");
9861
9862 /* Print attribute */
9b6d8fcf 9863 attr = path->attr;
05864da7 9864 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9865
05864da7
DS
9866 switch (af) {
9867 case AF_INET:
05864da7 9868 if (!json_path) {
db66cf7c 9869 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9870 } else {
db66cf7c
DA
9871 json_object_string_addf(json_nexthop, "ip", "%pI4",
9872 &attr->mp_nexthop_global_in);
14f51eba 9873
05864da7 9874 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9875
05864da7
DS
9876 json_object_object_add(json_path, "nexthop",
9877 json_nexthop);
9878 }
9879 break;
9880 case AF_INET6:
05864da7 9881 if (!json_path) {
db66cf7c
DA
9882 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9883 &attr->mp_nexthop_local);
05864da7 9884 } else {
db66cf7c
DA
9885 json_object_string_addf(json_nexthop, "ipv6Global",
9886 "%pI6",
9887 &attr->mp_nexthop_global);
14f51eba 9888
db66cf7c
DA
9889 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9890 "%pI6",
9891 &attr->mp_nexthop_local);
14f51eba 9892
05864da7 9893 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9894
05864da7
DS
9895 json_object_object_add(json_path, "nexthop",
9896 json_nexthop);
9897 }
9898 break;
9899 default:
9900 if (!json_path) {
9901 vty_out(vty, "?");
9902 } else {
77a2f8e5
DA
9903 json_object_string_add(json_nexthop, "error",
9904 "Unsupported address-family");
d62a17ae 9905 }
05864da7 9906 }
988258b4 9907
6c924775
DS
9908 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9909
05864da7 9910 if (!json_path)
db66cf7c 9911 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9912 else
db66cf7c 9913 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9914
b53e67a3 9915 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9916 char *mac = NULL;
9917 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9918 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9919 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9920
9921 if (routermac)
9922 mac = ecom_mac2str((char *)routermac->val);
9923 if (mac) {
9924 if (!json_path) {
c4efd0f4 9925 vty_out(vty, "/%s", mac);
05864da7
DS
9926 } else {
9927 json_object_string_add(json_overlay, "rmac",
9928 mac);
988258b4 9929 }
05864da7 9930 XFREE(MTYPE_TMP, mac);
988258b4 9931 }
05864da7 9932 }
718e3744 9933
05864da7
DS
9934 if (!json_path) {
9935 vty_out(vty, "\n");
9936 } else {
9937 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9938
05864da7 9939 json_object_array_add(json_paths, json_path);
14f51eba 9940 }
d62a17ae 9941}
718e3744 9942
d62a17ae 9943/* dampening route */
5f040085
DS
9944static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9945 struct bgp_path_info *path, int display,
9946 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9947 json_object *json_paths)
d62a17ae 9948{
e5be8c1d 9949 struct attr *attr = path->attr;
d62a17ae 9950 int len;
9951 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9952 json_object *json_path = NULL;
9953
9954 if (use_json)
9955 json_path = json_object_new_object();
d62a17ae 9956
9957 /* short status lead text */
e5be8c1d 9958 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9959
9960 /* print prefix and mask */
9961 if (!use_json) {
9962 if (!display)
7d3cae70 9963 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9964 else
9965 vty_out(vty, "%*s", 17, " ");
d62a17ae 9966
e5be8c1d
DA
9967 len = vty_out(vty, "%s", path->peer->host);
9968 len = 17 - len;
9969
9970 if (len < 1)
d62a17ae 9971 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9972 else
9973 vty_out(vty, "%*s", len, " ");
d62a17ae 9974
9b6d8fcf
DS
9975 vty_out(vty, "%s ",
9976 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9977 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9978 use_json, NULL));
d62a17ae 9979
e5be8c1d 9980 if (attr->aspath)
e678b143 9981 aspath_print_vty(vty, attr->aspath);
05864da7 9982
05864da7
DS
9983 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9984
d62a17ae 9985 vty_out(vty, "\n");
e5be8c1d
DA
9986 } else {
9987 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9988 safi, use_json, json_path);
9989
9990 if (attr->aspath)
9991 json_object_string_add(json_path, "asPath",
9992 attr->aspath->str);
9993
9994 json_object_string_add(json_path, "origin",
9995 bgp_origin_str[attr->origin]);
9996 json_object_string_add(json_path, "peerHost", path->peer->host);
9997
9998 json_object_array_add(json_paths, json_path);
9999 }
d62a17ae 10000}
718e3744 10001
d62a17ae 10002/* flap route */
5f040085
DS
10003static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10004 struct bgp_path_info *path, int display,
10005 afi_t afi, safi_t safi, bool use_json,
31258046 10006 json_object *json_paths)
784d3a42 10007{
31258046 10008 struct attr *attr = path->attr;
d62a17ae 10009 struct bgp_damp_info *bdi;
10010 char timebuf[BGP_UPTIME_LEN];
10011 int len;
31258046 10012 json_object *json_path = NULL;
784d3a42 10013
9b6d8fcf 10014 if (!path->extra)
d62a17ae 10015 return;
784d3a42 10016
31258046
DA
10017 if (use_json)
10018 json_path = json_object_new_object();
10019
9b6d8fcf 10020 bdi = path->extra->damp_info;
784d3a42 10021
d62a17ae 10022 /* short status lead text */
31258046 10023 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10024
d62a17ae 10025 if (!use_json) {
10026 if (!display)
7d3cae70 10027 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10028 else
10029 vty_out(vty, "%*s", 17, " ");
784d3a42 10030
31258046
DA
10031 len = vty_out(vty, "%s", path->peer->host);
10032 len = 16 - len;
10033 if (len < 1)
d62a17ae 10034 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10035 else
10036 vty_out(vty, "%*s", len, " ");
784d3a42 10037
31258046
DA
10038 len = vty_out(vty, "%d", bdi->flap);
10039 len = 5 - len;
10040 if (len < 1)
d62a17ae 10041 vty_out(vty, " ");
d62a17ae 10042 else
10043 vty_out(vty, "%*s", len, " ");
d62a17ae 10044
996c9314
LB
10045 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10046 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10047
31258046
DA
10048 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10049 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10050 vty_out(vty, "%s ",
9b6d8fcf 10051 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10052 BGP_UPTIME_LEN, afi,
31258046
DA
10053 safi, use_json, NULL));
10054 else
d62a17ae 10055 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10056
31258046 10057 if (attr->aspath)
e678b143 10058 aspath_print_vty(vty, attr->aspath);
05864da7 10059
05864da7
DS
10060 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10061
d62a17ae 10062 vty_out(vty, "\n");
31258046
DA
10063 } else {
10064 json_object_string_add(json_path, "peerHost", path->peer->host);
10065 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10066
10067 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10068 json_path);
10069
10070 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10071 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10072 bgp_damp_reuse_time_vty(vty, path, timebuf,
10073 BGP_UPTIME_LEN, afi, safi,
10074 use_json, json_path);
10075
10076 if (attr->aspath)
10077 json_object_string_add(json_path, "asPath",
10078 attr->aspath->str);
10079
10080 json_object_string_add(json_path, "origin",
10081 bgp_origin_str[attr->origin]);
10082
10083 json_object_array_add(json_paths, json_path);
10084 }
d62a17ae 10085}
10086
10087static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10088 int *first, const char *header,
10089 json_object *json_adv_to)
10090{
d62a17ae 10091 json_object *json_peer = NULL;
10092
10093 if (json_adv_to) {
10094 /* 'advertised-to' is a dictionary of peers we have advertised
10095 * this
10096 * prefix too. The key is the peer's IP or swpX, the value is
10097 * the
10098 * hostname if we know it and "" if not.
10099 */
10100 json_peer = json_object_new_object();
10101
10102 if (peer->hostname)
10103 json_object_string_add(json_peer, "hostname",
10104 peer->hostname);
10105
10106 if (peer->conf_if)
10107 json_object_object_add(json_adv_to, peer->conf_if,
10108 json_peer);
10109 else
47e12884
DA
10110 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10111 &peer->su);
d62a17ae 10112 } else {
10113 if (*first) {
10114 vty_out(vty, "%s", header);
10115 *first = 0;
10116 }
10117
10118 if (peer->hostname
892fedb6 10119 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10120 if (peer->conf_if)
10121 vty_out(vty, " %s(%s)", peer->hostname,
10122 peer->conf_if);
10123 else
47e12884
DA
10124 vty_out(vty, " %s(%pSU)", peer->hostname,
10125 &peer->su);
d62a17ae 10126 } else {
10127 if (peer->conf_if)
10128 vty_out(vty, " %s", peer->conf_if);
10129 else
47e12884 10130 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10131 }
10132 }
784d3a42
PG
10133}
10134
dcc68b5e
MS
10135static void route_vty_out_tx_ids(struct vty *vty,
10136 struct bgp_addpath_info_data *d)
10137{
10138 int i;
10139
10140 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10141 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10142 d->addpath_tx_id[i],
10143 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10144 }
10145}
10146
5e4d4c8a 10147static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10148 struct bgp_path_info *pi,
10149 struct attr *attr,
10150 json_object *json_path)
5e4d4c8a
AK
10151{
10152 char esi_buf[ESI_STR_LEN];
10153 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10154 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10155 ATTR_ES_PEER_ROUTER);
10156 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10157 ATTR_ES_PEER_ACTIVE);
10158 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10159 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10160 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10161 if (json_path) {
10162 json_object *json_es_info = NULL;
10163
10164 json_object_string_add(
10165 json_path, "esi",
10166 esi_buf);
10167 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10168 json_es_info = json_object_new_object();
10169 if (es_local)
10170 json_object_boolean_true_add(
10171 json_es_info, "localEs");
10172 if (peer_active)
10173 json_object_boolean_true_add(
10174 json_es_info, "peerActive");
10175 if (peer_proxy)
10176 json_object_boolean_true_add(
10177 json_es_info, "peerProxy");
10178 if (peer_router)
10179 json_object_boolean_true_add(
10180 json_es_info, "peerRouter");
10181 if (attr->mm_sync_seqnum)
10182 json_object_int_add(
10183 json_es_info, "peerSeq",
10184 attr->mm_sync_seqnum);
10185 json_object_object_add(
10186 json_path, "es_info",
10187 json_es_info);
10188 }
10189 } else {
10190 if (bgp_evpn_attr_is_sync(attr))
10191 vty_out(vty,
10192 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10193 esi_buf,
10194 es_local ? "local-es":"",
10195 peer_proxy ? "proxy " : "",
10196 peer_active ? "active ":"",
10197 peer_router ? "router ":"",
10198 attr->mm_sync_seqnum);
10199 else
10200 vty_out(vty, " ESI %s %s\n",
10201 esi_buf,
10202 es_local ? "local-es":"");
10203 }
10204}
10205
4933eaaf 10206void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10207 const struct prefix *p, struct bgp_path_info *path,
10208 afi_t afi, safi_t safi,
4027d19b
DS
10209 enum rpki_states rpki_curr_state,
10210 json_object *json_paths)
d62a17ae 10211{
10212 char buf[INET6_ADDRSTRLEN];
100290e4 10213 char tag_buf[30];
515c2602 10214 struct attr *attr = path->attr;
d62a17ae 10215 time_t tbuf;
10216 json_object *json_bestpath = NULL;
10217 json_object *json_cluster_list = NULL;
10218 json_object *json_cluster_list_list = NULL;
10219 json_object *json_ext_community = NULL;
10220 json_object *json_last_update = NULL;
7fd077aa 10221 json_object *json_pmsi = NULL;
d62a17ae 10222 json_object *json_nexthop_global = NULL;
10223 json_object *json_nexthop_ll = NULL;
10224 json_object *json_nexthops = NULL;
10225 json_object *json_path = NULL;
10226 json_object *json_peer = NULL;
10227 json_object *json_string = NULL;
10228 json_object *json_adv_to = NULL;
10229 int first = 0;
10230 struct listnode *node, *nnode;
10231 struct peer *peer;
be92fc9f 10232 bool addpath_capable;
d62a17ae 10233 int has_adj;
10234 unsigned int first_as;
1defdda8 10235 bool nexthop_self =
9b6d8fcf 10236 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10237 int i;
2ba93fd6
DA
10238 char *nexthop_hostname =
10239 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10240 uint32_t ttl = 0;
10241 uint32_t bos = 0;
10242 uint32_t exp = 0;
10243 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10244 tag_buf[0] = '\0';
f0cde006
LS
10245 struct bgp_path_info *bpi_ultimate =
10246 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10247
10248 if (json_paths) {
10249 json_path = json_object_new_object();
10250 json_peer = json_object_new_object();
10251 json_nexthop_global = json_object_new_object();
10252 }
10253
8304dabf
AD
10254 if (safi == SAFI_EVPN) {
10255 if (!json_paths)
34c7f35f 10256 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10257 }
10258
44c69747 10259 if (path->extra) {
9b6d8fcf
DS
10260 if (path->extra && path->extra->num_labels) {
10261 bgp_evpn_label2str(path->extra->label,
10262 path->extra->num_labels, tag_buf,
a4d82a8a 10263 sizeof(tag_buf));
d62a17ae 10264 }
d7325ee7 10265 if (safi == SAFI_EVPN) {
44c69747 10266 if (!json_paths) {
44c69747
LK
10267 if (tag_buf[0] != '\0')
10268 vty_out(vty, " VNI %s", tag_buf);
44c69747 10269 } else {
1ce23106 10270 if (tag_buf[0])
77a2f8e5
DA
10271 json_object_string_add(json_path, "vni",
10272 tag_buf);
44c69747 10273 }
d7325ee7 10274 }
d62a17ae 10275 }
d62a17ae 10276
8304dabf
AD
10277 if (safi == SAFI_EVPN
10278 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10279 char gwip_buf[INET6_ADDRSTRLEN];
10280
860e740b
IR
10281 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10282 sizeof(gwip_buf));
8304dabf
AD
10283
10284 if (json_paths)
10285 json_object_string_add(json_path, "gatewayIP",
10286 gwip_buf);
10287 else
10288 vty_out(vty, " Gateway IP %s", gwip_buf);
10289 }
10290
2bf9780b 10291 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10292 vty_out(vty, "\n");
10293
100290e4
SW
10294
10295 if (path->extra && path->extra->parent && !json_paths) {
10296 struct bgp_path_info *parent_ri;
10297 struct bgp_dest *dest, *pdest;
10298
10299 parent_ri = (struct bgp_path_info *)path->extra->parent;
10300 dest = parent_ri->net;
10301 if (dest && dest->pdest) {
10302 pdest = dest->pdest;
10303 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10304 vty_out(vty, " Imported from ");
10305 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10306 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10307 pdest));
10308 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10309 (struct prefix_evpn *)
10310 bgp_dest_get_prefix(dest),
10311 tag_buf);
6012963e 10312 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10313 vty_out(vty, ", L3NHG %s",
6012963e
SW
10314 CHECK_FLAG(
10315 attr->es_flags,
10316 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10317 ? "active"
10318 : "inactive");
10319 vty_out(vty, "\n");
10320
4a8cd6ad
PG
10321 } else {
10322 vty_out(vty, " Imported from ");
10323 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10324 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10325 pdest));
10326 vty_out(vty, ":%pFX\n",
100290e4
SW
10327 (struct prefix_evpn *)
10328 bgp_dest_get_prefix(dest));
4a8cd6ad 10329 }
100290e4
SW
10330 }
10331 }
10332
05864da7
DS
10333 /* Line1 display AS-path, Aggregator */
10334 if (attr->aspath) {
10335 if (json_paths) {
10336 if (!attr->aspath->json)
10337 aspath_str_update(attr->aspath, true);
10338 json_object_lock(attr->aspath->json);
10339 json_object_object_add(json_path, "aspath",
10340 attr->aspath->json);
10341 } else {
10342 if (attr->aspath->segments)
e678b143 10343 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10344 else
05864da7 10345 vty_out(vty, " Local");
d62a17ae 10346 }
05864da7 10347 }
d62a17ae 10348
05864da7
DS
10349 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10350 if (json_paths)
10351 json_object_boolean_true_add(json_path, "removed");
10352 else
10353 vty_out(vty, ", (removed)");
10354 }
d62a17ae 10355
05864da7
DS
10356 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10357 if (json_paths)
10358 json_object_boolean_true_add(json_path, "stale");
10359 else
10360 vty_out(vty, ", (stale)");
10361 }
d62a17ae 10362
05864da7
DS
10363 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10364 if (json_paths) {
10365 json_object_int_add(json_path, "aggregatorAs",
10366 attr->aggregator_as);
c949c771
DA
10367 json_object_string_addf(json_path, "aggregatorId",
10368 "%pI4", &attr->aggregator_addr);
05864da7 10369 } else {
88d495a9
DA
10370 vty_out(vty, ", (aggregated by %u %pI4)",
10371 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10372 }
05864da7 10373 }
d62a17ae 10374
05864da7
DS
10375 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10376 PEER_FLAG_REFLECTOR_CLIENT)) {
10377 if (json_paths)
10378 json_object_boolean_true_add(json_path,
10379 "rxedFromRrClient");
10380 else
10381 vty_out(vty, ", (Received from a RR-client)");
10382 }
d62a17ae 10383
05864da7
DS
10384 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10385 PEER_FLAG_RSERVER_CLIENT)) {
10386 if (json_paths)
10387 json_object_boolean_true_add(json_path,
10388 "rxedFromRsClient");
10389 else
10390 vty_out(vty, ", (Received from a RS-client)");
10391 }
d62a17ae 10392
05864da7
DS
10393 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10394 if (json_paths)
10395 json_object_boolean_true_add(json_path,
10396 "dampeningHistoryEntry");
10397 else
10398 vty_out(vty, ", (history entry)");
10399 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10400 if (json_paths)
10401 json_object_boolean_true_add(json_path,
10402 "dampeningSuppressed");
10403 else
10404 vty_out(vty, ", (suppressed due to dampening)");
10405 }
d62a17ae 10406
05864da7
DS
10407 if (!json_paths)
10408 vty_out(vty, "\n");
d62a17ae 10409
05864da7
DS
10410 /* Line2 display Next-hop, Neighbor, Router-id */
10411 /* Display the nexthop */
b54892e0 10412
34c7f35f
SW
10413 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10414 p->family == AF_EVPN) &&
7226bc40
TA
10415 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10416 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10417 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10418 || safi == SAFI_EVPN) {
515c2602 10419 if (json_paths) {
c949c771
DA
10420 json_object_string_addf(
10421 json_nexthop_global, "ip", "%pI4",
10422 &attr->mp_nexthop_global_in);
515c2602 10423
939a97f4 10424 if (path->peer->hostname)
515c2602
DA
10425 json_object_string_add(
10426 json_nexthop_global, "hostname",
939a97f4 10427 path->peer->hostname);
aef999a2
DA
10428 } else {
10429 if (nexthop_hostname)
10430 vty_out(vty, " %pI4(%s)",
10431 &attr->mp_nexthop_global_in,
10432 nexthop_hostname);
10433 else
10434 vty_out(vty, " %pI4",
10435 &attr->mp_nexthop_global_in);
10436 }
d62a17ae 10437 } else {
515c2602 10438 if (json_paths) {
c949c771
DA
10439 json_object_string_addf(json_nexthop_global,
10440 "ip", "%pI4",
10441 &attr->nexthop);
515c2602 10442
939a97f4 10443 if (path->peer->hostname)
515c2602
DA
10444 json_object_string_add(
10445 json_nexthop_global, "hostname",
939a97f4 10446 path->peer->hostname);
aef999a2
DA
10447 } else {
10448 if (nexthop_hostname)
10449 vty_out(vty, " %pI4(%s)",
10450 &attr->nexthop,
10451 nexthop_hostname);
10452 else
10453 vty_out(vty, " %pI4",
10454 &attr->nexthop);
10455 }
d62a17ae 10456 }
10457
05864da7
DS
10458 if (json_paths)
10459 json_object_string_add(json_nexthop_global, "afi",
10460 "ipv4");
10461 } else {
10462 if (json_paths) {
c949c771
DA
10463 json_object_string_addf(json_nexthop_global, "ip",
10464 "%pI6",
10465 &attr->mp_nexthop_global);
515c2602 10466
939a97f4 10467 if (path->peer->hostname)
515c2602
DA
10468 json_object_string_add(json_nexthop_global,
10469 "hostname",
939a97f4 10470 path->peer->hostname);
515c2602 10471
05864da7
DS
10472 json_object_string_add(json_nexthop_global, "afi",
10473 "ipv6");
10474 json_object_string_add(json_nexthop_global, "scope",
10475 "global");
10476 } else {
aef999a2
DA
10477 if (nexthop_hostname)
10478 vty_out(vty, " %pI6(%s)",
10479 &attr->mp_nexthop_global,
10480 nexthop_hostname);
10481 else
10482 vty_out(vty, " %pI6",
10483 &attr->mp_nexthop_global);
d62a17ae 10484 }
05864da7 10485 }
d62a17ae 10486
05864da7 10487 /* Display the IGP cost or 'inaccessible' */
f0cde006 10488 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10489 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10490
10491 if (json_paths) {
05864da7
DS
10492 json_object_boolean_false_add(json_nexthop_global,
10493 "accessible");
95ba22d5
DA
10494 json_object_boolean_add(json_nexthop_global,
10495 "importCheckEnabled", import);
10496 } else {
10497 vty_out(vty, " (inaccessible%s)",
10498 import ? ", import-check enabled" : "");
10499 }
05864da7 10500 } else {
f0cde006 10501 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10502 if (json_paths)
f0cde006
LS
10503 json_object_int_add(
10504 json_nexthop_global, "metric",
10505 bpi_ultimate->extra->igpmetric);
d62a17ae 10506 else
05864da7 10507 vty_out(vty, " (metric %u)",
f0cde006 10508 bpi_ultimate->extra->igpmetric);
d62a17ae 10509 }
10510
05864da7 10511 /* IGP cost is 0, display this only for json */
d62a17ae 10512 else {
d62a17ae 10513 if (json_paths)
05864da7
DS
10514 json_object_int_add(json_nexthop_global,
10515 "metric", 0);
d62a17ae 10516 }
d62a17ae 10517
05864da7
DS
10518 if (json_paths)
10519 json_object_boolean_true_add(json_nexthop_global,
10520 "accessible");
10521 }
d62a17ae 10522
05864da7
DS
10523 /* Display peer "from" output */
10524 /* This path was originated locally */
10525 if (path->peer == bgp->peer_self) {
d62a17ae 10526
34c7f35f 10527 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10528 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10529 if (json_paths)
05864da7
DS
10530 json_object_string_add(json_peer, "peerId",
10531 "0.0.0.0");
d62a17ae 10532 else
05864da7
DS
10533 vty_out(vty, " from 0.0.0.0 ");
10534 } else {
d62a17ae 10535 if (json_paths)
05864da7
DS
10536 json_object_string_add(json_peer, "peerId",
10537 "::");
d62a17ae 10538 else
05864da7 10539 vty_out(vty, " from :: ");
d62a17ae 10540 }
d62a17ae 10541
4e9a9863 10542 if (json_paths)
c949c771
DA
10543 json_object_string_addf(json_peer, "routerId", "%pI4",
10544 &bgp->router_id);
4e9a9863 10545 else
23d0a753 10546 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10547 }
d62a17ae 10548
05864da7
DS
10549 /* We RXed this path from one of our peers */
10550 else {
10551
10552 if (json_paths) {
47e12884
DA
10553 json_object_string_addf(json_peer, "peerId", "%pSU",
10554 &path->peer->su);
c949c771
DA
10555 json_object_string_addf(json_peer, "routerId", "%pI4",
10556 &path->peer->remote_id);
05864da7
DS
10557
10558 if (path->peer->hostname)
10559 json_object_string_add(json_peer, "hostname",
10560 path->peer->hostname);
10561
10562 if (path->peer->domainname)
10563 json_object_string_add(json_peer, "domainname",
10564 path->peer->domainname);
10565
10566 if (path->peer->conf_if)
10567 json_object_string_add(json_peer, "interface",
10568 path->peer->conf_if);
10569 } else {
10570 if (path->peer->conf_if) {
10571 if (path->peer->hostname
892fedb6
DA
10572 && CHECK_FLAG(path->peer->bgp->flags,
10573 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10574 vty_out(vty, " from %s(%s)",
10575 path->peer->hostname,
10576 path->peer->conf_if);
d62a17ae 10577 else
05864da7 10578 vty_out(vty, " from %s",
9b6d8fcf 10579 path->peer->conf_if);
d62a17ae 10580 } else {
05864da7 10581 if (path->peer->hostname
892fedb6
DA
10582 && CHECK_FLAG(path->peer->bgp->flags,
10583 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10584 vty_out(vty, " from %s(%s)",
10585 path->peer->hostname,
10586 path->peer->host);
d62a17ae 10587 else
47e12884
DA
10588 vty_out(vty, " from %pSU",
10589 &path->peer->su);
d62a17ae 10590 }
d62a17ae 10591
05864da7 10592 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10593 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10594 else
07380148 10595 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10596 }
05864da7 10597 }
9df8b37c 10598
05864da7
DS
10599 /*
10600 * Note when vrfid of nexthop is different from that of prefix
10601 */
10602 if (path->extra && path->extra->bgp_orig) {
10603 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10604
05864da7
DS
10605 if (json_paths) {
10606 const char *vn;
9df8b37c 10607
05864da7
DS
10608 if (path->extra->bgp_orig->inst_type
10609 == BGP_INSTANCE_TYPE_DEFAULT)
10610 vn = VRF_DEFAULT_NAME;
10611 else
10612 vn = path->extra->bgp_orig->name;
9df8b37c 10613
05864da7 10614 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10615
05864da7
DS
10616 if (nexthop_vrfid == VRF_UNKNOWN) {
10617 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10618 } else {
05864da7
DS
10619 json_object_int_add(json_path, "nhVrfId",
10620 (int)nexthop_vrfid);
9df8b37c 10621 }
05864da7
DS
10622 } else {
10623 if (nexthop_vrfid == VRF_UNKNOWN)
10624 vty_out(vty, " vrf ?");
137147c6
DS
10625 else {
10626 struct vrf *vrf;
10627
10628 vrf = vrf_lookup_by_id(nexthop_vrfid);
10629 vty_out(vty, " vrf %s(%u)",
10630 VRF_LOGNAME(vrf), nexthop_vrfid);
10631 }
9df8b37c 10632 }
05864da7 10633 }
9df8b37c 10634
05864da7
DS
10635 if (nexthop_self) {
10636 if (json_paths) {
10637 json_object_boolean_true_add(json_path,
10638 "announceNexthopSelf");
10639 } else {
10640 vty_out(vty, " announce-nh-self");
9df8b37c 10641 }
05864da7 10642 }
9df8b37c 10643
05864da7
DS
10644 if (!json_paths)
10645 vty_out(vty, "\n");
d62a17ae 10646
05864da7
DS
10647 /* display the link-local nexthop */
10648 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10649 if (json_paths) {
10650 json_nexthop_ll = json_object_new_object();
c949c771
DA
10651 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10652 &attr->mp_nexthop_local);
515c2602 10653
939a97f4 10654 if (path->peer->hostname)
515c2602
DA
10655 json_object_string_add(json_nexthop_ll,
10656 "hostname",
939a97f4 10657 path->peer->hostname);
515c2602 10658
05864da7
DS
10659 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10660 json_object_string_add(json_nexthop_ll, "scope",
10661 "link-local");
d62a17ae 10662
05864da7
DS
10663 json_object_boolean_true_add(json_nexthop_ll,
10664 "accessible");
d62a17ae 10665
2bb8b49c 10666 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10667 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10668 "used");
10669 else
10670 json_object_boolean_true_add(
10671 json_nexthop_global, "used");
10672 } else {
10673 vty_out(vty, " (%s) %s\n",
10674 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10675 buf, INET6_ADDRSTRLEN),
2bb8b49c 10676 attr->mp_nexthop_prefer_global
05864da7
DS
10677 ? "(prefer-global)"
10678 : "(used)");
d62a17ae 10679 }
05864da7
DS
10680 }
10681 /* If we do not have a link-local nexthop then we must flag the
10682 global as "used" */
10683 else {
10684 if (json_paths)
10685 json_object_boolean_true_add(json_nexthop_global,
10686 "used");
10687 }
d62a17ae 10688
b5e140c8 10689 if (safi == SAFI_EVPN &&
5e4d4c8a 10690 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10691 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10692 }
10693
05864da7
DS
10694 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10695 * Int/Ext/Local, Atomic, best */
10696 if (json_paths)
10697 json_object_string_add(json_path, "origin",
10698 bgp_origin_long_str[attr->origin]);
10699 else
10700 vty_out(vty, " Origin %s",
10701 bgp_origin_long_str[attr->origin]);
9df8b37c 10702
05864da7 10703 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10704 if (json_paths)
05864da7 10705 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10706 else
05864da7
DS
10707 vty_out(vty, ", metric %u", attr->med);
10708 }
9df8b37c 10709
05864da7
DS
10710 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10711 if (json_paths)
0fbac0b4 10712 json_object_int_add(json_path, "locPrf",
05864da7
DS
10713 attr->local_pref);
10714 else
10715 vty_out(vty, ", localpref %u", attr->local_pref);
10716 }
9df8b37c 10717
97a52c82
DA
10718 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10719 if (json_paths)
10720 json_object_int_add(json_path, "aigpMetric",
10721 bgp_attr_get_aigp_metric(attr));
10722 else
10723 vty_out(vty, ", aigp-metric %" PRIu64,
10724 bgp_attr_get_aigp_metric(attr));
10725 }
10726
05864da7
DS
10727 if (attr->weight != 0) {
10728 if (json_paths)
10729 json_object_int_add(json_path, "weight", attr->weight);
10730 else
10731 vty_out(vty, ", weight %u", attr->weight);
10732 }
9df8b37c 10733
05864da7
DS
10734 if (attr->tag != 0) {
10735 if (json_paths)
10736 json_object_int_add(json_path, "tag", attr->tag);
10737 else
10738 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10739 }
9df8b37c 10740
05864da7
DS
10741 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10742 if (json_paths)
10743 json_object_boolean_false_add(json_path, "valid");
10744 else
10745 vty_out(vty, ", invalid");
10746 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10747 if (json_paths)
10748 json_object_boolean_true_add(json_path, "valid");
10749 else
10750 vty_out(vty, ", valid");
10751 }
9df8b37c 10752
7d3cae70
DA
10753 if (json_paths)
10754 json_object_int_add(json_path, "version", bn->version);
10755
05864da7
DS
10756 if (path->peer != bgp->peer_self) {
10757 if (path->peer->as == path->peer->local_as) {
10758 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10759 if (json_paths)
10760 json_object_string_add(
10761 json_peer, "type",
10762 "confed-internal");
d62a17ae 10763 else
05864da7 10764 vty_out(vty, ", confed-internal");
d62a17ae 10765 } else {
05864da7
DS
10766 if (json_paths)
10767 json_object_string_add(
10768 json_peer, "type", "internal");
10769 else
10770 vty_out(vty, ", internal");
9df8b37c 10771 }
05864da7
DS
10772 } else {
10773 if (bgp_confederation_peers_check(bgp,
10774 path->peer->as)) {
10775 if (json_paths)
10776 json_object_string_add(
10777 json_peer, "type",
10778 "confed-external");
d62a17ae 10779 else
05864da7 10780 vty_out(vty, ", confed-external");
d62a17ae 10781 } else {
05864da7
DS
10782 if (json_paths)
10783 json_object_string_add(
10784 json_peer, "type", "external");
10785 else
10786 vty_out(vty, ", external");
d62a17ae 10787 }
10788 }
05864da7
DS
10789 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10790 if (json_paths) {
10791 json_object_boolean_true_add(json_path, "aggregated");
10792 json_object_boolean_true_add(json_path, "local");
10793 } else {
10794 vty_out(vty, ", aggregated, local");
10795 }
10796 } else if (path->type != ZEBRA_ROUTE_BGP) {
10797 if (json_paths)
10798 json_object_boolean_true_add(json_path, "sourced");
10799 else
10800 vty_out(vty, ", sourced");
10801 } else {
10802 if (json_paths) {
10803 json_object_boolean_true_add(json_path, "sourced");
10804 json_object_boolean_true_add(json_path, "local");
10805 } else {
10806 vty_out(vty, ", sourced, local");
d62a17ae 10807 }
05864da7 10808 }
718e3744 10809
05864da7 10810 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10811 if (json_paths)
05864da7
DS
10812 json_object_boolean_true_add(json_path,
10813 "atomicAggregate");
d62a17ae 10814 else
05864da7
DS
10815 vty_out(vty, ", atomic-aggregate");
10816 }
d62a17ae 10817
d864dd9e
EB
10818 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10819 if (json_paths)
10820 json_object_int_add(json_path, "otc", attr->otc);
10821 else
10822 vty_out(vty, ", otc %u", attr->otc);
10823 }
10824
05864da7
DS
10825 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10826 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10827 && bgp_path_info_mpath_count(path))) {
10828 if (json_paths)
10829 json_object_boolean_true_add(json_path, "multipath");
10830 else
10831 vty_out(vty, ", multipath");
10832 }
50e05855 10833
05864da7
DS
10834 // Mark the bestpath(s)
10835 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10836 first_as = aspath_get_first_as(attr->aspath);
718e3744 10837
05864da7
DS
10838 if (json_paths) {
10839 if (!json_bestpath)
10840 json_bestpath = json_object_new_object();
10841 json_object_int_add(json_bestpath, "bestpathFromAs",
10842 first_as);
10843 } else {
10844 if (first_as)
10845 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10846 else
05864da7 10847 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10848 }
05864da7 10849 }
718e3744 10850
05864da7
DS
10851 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10852 if (json_paths) {
10853 if (!json_bestpath)
10854 json_bestpath = json_object_new_object();
10855 json_object_boolean_true_add(json_bestpath, "overall");
10856 json_object_string_add(
10857 json_bestpath, "selectionReason",
10858 bgp_path_selection_reason2str(bn->reason));
10859 } else {
10860 vty_out(vty, ", best");
10861 vty_out(vty, " (%s)",
10862 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10863 }
05864da7 10864 }
718e3744 10865
4027d19b 10866 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10867 if (json_paths)
10868 json_object_string_add(
10869 json_path, "rpkiValidationState",
4027d19b 10870 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10871 else
1d327209 10872 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10873 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10874 }
10875
05864da7
DS
10876 if (json_bestpath)
10877 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10878
05864da7
DS
10879 if (!json_paths)
10880 vty_out(vty, "\n");
10881
10882 /* Line 4 display Community */
29e72930 10883 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10884 if (json_paths) {
9a706b42
DA
10885 if (!bgp_attr_get_community(attr)->json)
10886 community_str(bgp_attr_get_community(attr),
c0945b78 10887 true, true);
9a706b42
DA
10888 json_object_lock(bgp_attr_get_community(attr)->json);
10889 json_object_object_add(
10890 json_path, "community",
10891 bgp_attr_get_community(attr)->json);
05864da7
DS
10892 } else {
10893 vty_out(vty, " Community: %s\n",
9a706b42 10894 bgp_attr_get_community(attr)->str);
d62a17ae 10895 }
05864da7 10896 }
718e3744 10897
05864da7
DS
10898 /* Line 5 display Extended-community */
10899 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10900 if (json_paths) {
10901 json_ext_community = json_object_new_object();
b53e67a3
DA
10902 json_object_string_add(
10903 json_ext_community, "string",
10904 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10905 json_object_object_add(json_path, "extendedCommunity",
10906 json_ext_community);
d62a17ae 10907 } else {
05864da7 10908 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10909 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10910 }
05864da7 10911 }
718e3744 10912
05864da7
DS
10913 /* Line 6 display Large community */
10914 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10915 if (json_paths) {
1bcf3a96
DA
10916 if (!bgp_attr_get_lcommunity(attr)->json)
10917 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10918 true, true);
1bcf3a96
DA
10919 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10920 json_object_object_add(
10921 json_path, "largeCommunity",
10922 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10923 } else {
10924 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10925 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10926 }
05864da7 10927 }
718e3744 10928
05864da7
DS
10929 /* Line 7 display Originator, Cluster-id */
10930 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10931 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10932 char buf[BUFSIZ] = {0};
10933
05864da7 10934 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10935 if (json_paths)
c949c771
DA
10936 json_object_string_addf(json_path,
10937 "originatorId", "%pI4",
10938 &attr->originator_id);
d62a17ae 10939 else
23d0a753
DA
10940 vty_out(vty, " Originator: %pI4",
10941 &attr->originator_id);
d62a17ae 10942 }
856ca177 10943
05864da7 10944 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10945 struct cluster_list *cluster =
10946 bgp_attr_get_cluster(attr);
05864da7 10947 int i;
d62a17ae 10948
10949 if (json_paths) {
05864da7
DS
10950 json_cluster_list = json_object_new_object();
10951 json_cluster_list_list =
10952 json_object_new_array();
10953
779fee93 10954 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10955 json_string = json_object_new_string(
779fee93
DS
10956 inet_ntop(AF_INET,
10957 &cluster->list[i],
10958 buf, sizeof(buf)));
05864da7
DS
10959 json_object_array_add(
10960 json_cluster_list_list,
10961 json_string);
10962 }
718e3744 10963
05864da7
DS
10964 /*
10965 * struct cluster_list does not have
10966 * "str" variable like aspath and community
10967 * do. Add this someday if someone asks
10968 * for it.
10969 * json_object_string_add(json_cluster_list,
779fee93 10970 * "string", cluster->str);
05864da7
DS
10971 */
10972 json_object_object_add(json_cluster_list,
10973 "list",
10974 json_cluster_list_list);
10975 json_object_object_add(json_path, "clusterList",
10976 json_cluster_list);
0dc8ee70 10977 } else {
05864da7
DS
10978 vty_out(vty, ", Cluster list: ");
10979
779fee93 10980 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10981 vty_out(vty, "%pI4 ",
779fee93 10982 &cluster->list[i]);
05864da7 10983 }
0dc8ee70 10984 }
d62a17ae 10985 }
718e3744 10986
d62a17ae 10987 if (!json_paths)
10988 vty_out(vty, "\n");
05864da7 10989 }
d62a17ae 10990
05864da7 10991 if (path->extra && path->extra->damp_info)
b4f7f45b 10992 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10993
05864da7
DS
10994 /* Remote Label */
10995 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10996 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10997 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10998 &bos);
d62a17ae 10999
05864da7
DS
11000 if (json_paths)
11001 json_object_int_add(json_path, "remoteLabel", label);
11002 else
11003 vty_out(vty, " Remote label: %d\n", label);
11004 }
d62a17ae 11005
e496b420
HS
11006 /* Remote SID */
11007 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 11008 if (json_paths)
07380148
DA
11009 json_object_string_addf(json_path, "remoteSid", "%pI6",
11010 &path->extra->sid[0].sid);
e496b420 11011 else
07380148
DA
11012 vty_out(vty, " Remote SID: %pI6\n",
11013 &path->extra->sid[0].sid);
e496b420
HS
11014 }
11015
05864da7
DS
11016 /* Label Index */
11017 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11018 if (json_paths)
11019 json_object_int_add(json_path, "labelIndex",
11020 attr->label_index);
11021 else
11022 vty_out(vty, " Label Index: %d\n",
11023 attr->label_index);
11024 }
d62a17ae 11025
05864da7
DS
11026 /* Line 8 display Addpath IDs */
11027 if (path->addpath_rx_id
11028 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11029 if (json_paths) {
11030 json_object_int_add(json_path, "addpathRxId",
11031 path->addpath_rx_id);
d62a17ae 11032
05864da7
DS
11033 /* Keep backwards compatibility with the old API
11034 * by putting TX All's ID in the old field
11035 */
11036 json_object_int_add(
11037 json_path, "addpathTxId",
11038 path->tx_addpath
11039 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11040
05864da7
DS
11041 /* ... but create a specific field for each
11042 * strategy
11043 */
11044 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11045 json_object_int_add(
11046 json_path,
11047 bgp_addpath_names(i)->id_json_name,
11048 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11049 }
05864da7
DS
11050 } else {
11051 vty_out(vty, " AddPath ID: RX %u, ",
11052 path->addpath_rx_id);
d62a17ae 11053
05864da7 11054 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11055 }
05864da7 11056 }
520d5d76 11057
05864da7
DS
11058 /* If we used addpath to TX a non-bestpath we need to display
11059 * "Advertised to" on a path-by-path basis
11060 */
11061 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11062 first = 1;
dcc68b5e 11063
05864da7
DS
11064 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11065 addpath_capable =
11066 bgp_addpath_encode_tx(peer, afi, safi);
11067 has_adj = bgp_adj_out_lookup(
11068 peer, path->net,
11069 bgp_addpath_id_for_peer(peer, afi, safi,
11070 &path->tx_addpath));
11071
11072 if ((addpath_capable && has_adj)
11073 || (!addpath_capable && has_adj
11074 && CHECK_FLAG(path->flags,
11075 BGP_PATH_SELECTED))) {
11076 if (json_path && !json_adv_to)
11077 json_adv_to = json_object_new_object();
dcc68b5e 11078
05864da7
DS
11079 route_vty_out_advertised_to(
11080 vty, peer, &first,
11081 " Advertised to:", json_adv_to);
d62a17ae 11082 }
11083 }
718e3744 11084
05864da7
DS
11085 if (json_path) {
11086 if (json_adv_to) {
11087 json_object_object_add(
11088 json_path, "advertisedTo", json_adv_to);
d62a17ae 11089 }
05864da7
DS
11090 } else {
11091 if (!first) {
11092 vty_out(vty, "\n");
d62a17ae 11093 }
11094 }
05864da7 11095 }
b05a1c8b 11096
05864da7 11097 /* Line 9 display Uptime */
083ec940 11098 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11099 if (json_paths) {
11100 json_last_update = json_object_new_object();
11101 json_object_int_add(json_last_update, "epoch", tbuf);
11102 json_object_string_add(json_last_update, "string",
11103 ctime(&tbuf));
11104 json_object_object_add(json_path, "lastUpdate",
11105 json_last_update);
11106 } else
11107 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11108
05864da7
DS
11109 /* Line 10 display PMSI tunnel attribute, if present */
11110 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11111 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11112 bgp_attr_get_pmsi_tnl_type(attr),
11113 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11114
05864da7
DS
11115 if (json_paths) {
11116 json_pmsi = json_object_new_object();
11117 json_object_string_add(json_pmsi, "tunnelType", str);
11118 json_object_int_add(json_pmsi, "label",
11119 label2vni(&attr->label));
11120 json_object_object_add(json_path, "pmsi", json_pmsi);
11121 } else
11122 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11123 str, label2vni(&attr->label));
d62a17ae 11124 }
f1aa5d8a 11125
848e8cf6
DA
11126 if (path->peer->t_gr_restart &&
11127 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11128 unsigned long gr_remaining =
4f830a07 11129 event_timer_remain_second(path->peer->t_gr_restart);
848e8cf6
DA
11130
11131 if (json_paths) {
11132 json_object_int_add(json_path,
11133 "gracefulRestartSecondsRemaining",
11134 gr_remaining);
11135 } else
11136 vty_out(vty,
11137 " Time until Graceful Restart stale route deleted: %lu\n",
11138 gr_remaining);
11139 }
11140
9a706b42
DA
11141 if (path->peer->t_llgr_stale[afi][safi] &&
11142 bgp_attr_get_community(attr) &&
11143 community_include(bgp_attr_get_community(attr),
11144 COMMUNITY_LLGR_STALE)) {
4f830a07 11145 unsigned long llgr_remaining = event_timer_remain_second(
48ebba04 11146 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11147
48ebba04
DA
11148 if (json_paths) {
11149 json_object_int_add(json_path, "llgrSecondsRemaining",
11150 llgr_remaining);
11151 } else
11152 vty_out(vty,
11153 " Time until Long-lived stale route deleted: %lu\n",
11154 llgr_remaining);
11155 }
11156
92269aa2
DS
11157 /* Output some debug about internal state of the dest flags */
11158 if (json_paths) {
11159 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11160 json_object_boolean_true_add(json_path, "processScheduled");
11161 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11162 json_object_boolean_true_add(json_path, "userCleared");
11163 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11164 json_object_boolean_true_add(json_path, "labelChanged");
11165 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11166 json_object_boolean_true_add(json_path, "registeredForLabel");
11167 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11168 json_object_boolean_true_add(json_path, "selectDefered");
11169 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11170 json_object_boolean_true_add(json_path, "fibInstalled");
11171 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11172 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11173
d62a17ae 11174 if (json_nexthop_global || json_nexthop_ll) {
11175 json_nexthops = json_object_new_array();
f1aa5d8a 11176
d62a17ae 11177 if (json_nexthop_global)
11178 json_object_array_add(json_nexthops,
11179 json_nexthop_global);
f1aa5d8a 11180
d62a17ae 11181 if (json_nexthop_ll)
11182 json_object_array_add(json_nexthops,
11183 json_nexthop_ll);
f1aa5d8a 11184
d62a17ae 11185 json_object_object_add(json_path, "nexthops",
11186 json_nexthops);
11187 }
11188
11189 json_object_object_add(json_path, "peer", json_peer);
11190 json_object_array_add(json_paths, json_path);
05864da7 11191 }
b366b518
BB
11192}
11193
96ade3ed 11194#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11195#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11196#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11197
a4d82a8a 11198static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11199 afi_t afi, safi_t safi, enum bgp_show_type type,
11200 bool use_json);
7f323236
DW
11201static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11202 const char *comstr, int exact, afi_t afi,
96c81f66 11203 safi_t safi, uint16_t show_flags);
d62a17ae 11204
1ae44dfc 11205static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11206 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11207 void *output_arg, const char *rd, int is_last,
96f3485c 11208 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11209 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11210 enum rpki_states rpki_target_state)
d62a17ae 11211{
40381db7 11212 struct bgp_path_info *pi;
9bcb3eef 11213 struct bgp_dest *dest;
2aad8c42
MS
11214 bool header = true;
11215 bool json_detail_header = false;
d62a17ae 11216 int display;
1ae44dfc
LB
11217 unsigned long output_count = 0;
11218 unsigned long total_count = 0;
d62a17ae 11219 struct prefix *p;
d62a17ae 11220 json_object *json_paths = NULL;
11221 int first = 1;
96f3485c
MK
11222 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11223 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11224 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11225 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11226 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11227
1ae44dfc 11228 if (output_cum && *output_cum != 0)
2aad8c42 11229 header = false;
1ae44dfc 11230
9386b588 11231 if (use_json && !*json_header_depth) {
96f3485c
MK
11232 if (all)
11233 *json_header_depth = 1;
11234 else {
11235 vty_out(vty, "{\n");
11236 *json_header_depth = 2;
11237 }
d62a17ae 11238 vty_out(vty,
23d0a753
DA
11239 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11240 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11241 " \"localAS\": ",
a8bf7d9c 11242 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11243 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11244 ? VRF_DEFAULT_NAME
11245 : bgp->name,
11246 table->version, &bgp->router_id,
e84c7c12
PG
11247 bgp->default_local_pref);
11248 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11249 ((bgp->asnotation == ASNOTATION_DOT) &&
11250 (bgp->as < UINT16_MAX)))
11251 vty_out(vty, "%u", bgp->as);
11252 else {
11253 vty_out(vty, "\"");
11254 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11255 vty_out(vty, "\"");
11256 }
11257 vty_out(vty, ",\n \"routes\": { ");
9386b588 11258 if (rd) {
445c2480 11259 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11260 ++*json_header_depth;
11261 }
d62a17ae 11262 }
718e3744 11263
445c2480
DS
11264 if (use_json && rd) {
11265 vty_out(vty, " \"%s\" : { ", rd);
11266 }
11267
2aad8c42 11268 /* Check for 'json detail', where we need header output once per dest */
67799a48 11269 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11270 type != bgp_show_type_damp_neighbor &&
11271 type != bgp_show_type_flap_statistics &&
11272 type != bgp_show_type_flap_neighbor)
11273 json_detail_header = true;
11274
d62a17ae 11275 /* Start processing of routes. */
9bcb3eef
DS
11276 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11277 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11278 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11279 bool json_detail_header_used = false;
b54892e0 11280
9bcb3eef 11281 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11282 if (pi == NULL)
98ce9a06 11283 continue;
d62a17ae 11284
98ce9a06 11285 display = 0;
98ce9a06
DS
11286 if (use_json)
11287 json_paths = json_object_new_array();
11288 else
11289 json_paths = NULL;
d62a17ae 11290
6f94b685 11291 for (; pi; pi = pi->next) {
9a706b42
DA
11292 struct community *picomm = NULL;
11293
11294 picomm = bgp_attr_get_community(pi->attr);
11295
98ce9a06 11296 total_count++;
1e2ce4f1 11297
7d3cae70
DA
11298 if (type == bgp_show_type_prefix_version) {
11299 uint32_t version =
11300 strtoul(output_arg, NULL, 10);
11301 if (dest->version < version)
11302 continue;
11303 }
11304
a70a28a5
DA
11305 if (type == bgp_show_type_community_alias) {
11306 char *alias = output_arg;
11307 char **communities;
11308 int num;
11309 bool found = false;
11310
9a706b42
DA
11311 if (picomm) {
11312 frrstr_split(picomm->str, " ",
11313 &communities, &num);
a70a28a5
DA
11314 for (int i = 0; i < num; i++) {
11315 const char *com2alias =
11316 bgp_community2alias(
11317 communities[i]);
cd9cc0e6
IR
11318 if (!found
11319 && strcmp(alias, com2alias)
11320 == 0)
a70a28a5 11321 found = true;
cd9cc0e6
IR
11322 XFREE(MTYPE_TMP,
11323 communities[i]);
a70a28a5 11324 }
cd9cc0e6 11325 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11326 }
11327
1bcf3a96
DA
11328 if (!found &&
11329 bgp_attr_get_lcommunity(pi->attr)) {
11330 frrstr_split(bgp_attr_get_lcommunity(
11331 pi->attr)
11332 ->str,
a70a28a5
DA
11333 " ", &communities, &num);
11334 for (int i = 0; i < num; i++) {
11335 const char *com2alias =
11336 bgp_community2alias(
11337 communities[i]);
cd9cc0e6
IR
11338 if (!found
11339 && strcmp(alias, com2alias)
11340 == 0)
a70a28a5 11341 found = true;
cd9cc0e6
IR
11342 XFREE(MTYPE_TMP,
11343 communities[i]);
a70a28a5 11344 }
cd9cc0e6 11345 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11346 }
11347
11348 if (!found)
11349 continue;
11350 }
11351
1e2ce4f1
DS
11352 if (type == bgp_show_type_rpki) {
11353 if (dest_p->family == AF_INET
11354 || dest_p->family == AF_INET6)
4027d19b 11355 rpki_curr_state = hook_call(
1e2ce4f1
DS
11356 bgp_rpki_prefix_status,
11357 pi->peer, pi->attr, dest_p);
4027d19b
DS
11358 if (rpki_target_state != RPKI_NOT_BEING_USED
11359 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11360 continue;
11361 }
11362
98ce9a06
DS
11363 if (type == bgp_show_type_flap_statistics
11364 || type == bgp_show_type_flap_neighbor
11365 || type == bgp_show_type_dampend_paths
11366 || type == bgp_show_type_damp_neighbor) {
40381db7 11367 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11368 continue;
11369 }
11370 if (type == bgp_show_type_regexp) {
11371 regex_t *regex = output_arg;
d62a17ae 11372
40381db7 11373 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11374 == REG_NOMATCH)
11375 continue;
11376 }
11377 if (type == bgp_show_type_prefix_list) {
11378 struct prefix_list *plist = output_arg;
d62a17ae 11379
9bcb3eef 11380 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11381 != PREFIX_PERMIT)
11382 continue;
11383 }
ed126382
DA
11384 if (type == bgp_show_type_access_list) {
11385 struct access_list *alist = output_arg;
11386
11387 if (access_list_apply(alist, dest_p) !=
11388 FILTER_PERMIT)
11389 continue;
11390 }
98ce9a06
DS
11391 if (type == bgp_show_type_filter_list) {
11392 struct as_list *as_list = output_arg;
d62a17ae 11393
40381db7 11394 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11395 != AS_FILTER_PERMIT)
11396 continue;
11397 }
11398 if (type == bgp_show_type_route_map) {
11399 struct route_map *rmap = output_arg;
9b6d8fcf 11400 struct bgp_path_info path;
636632c3
DA
11401 struct bgp_path_info_extra extra;
11402 struct attr dummy_attr = {};
b68885f9 11403 route_map_result_t ret;
d62a17ae 11404
6f4f49b2 11405 dummy_attr = *pi->attr;
d62a17ae 11406
636632c3
DA
11407 prep_for_rmap_apply(&path, &extra, dest, pi,
11408 pi->peer, &dummy_attr);
d62a17ae 11409
1782514f 11410 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11411 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11412 if (ret == RMAP_DENYMATCH)
11413 continue;
11414 }
11415 if (type == bgp_show_type_neighbor
11416 || type == bgp_show_type_flap_neighbor
11417 || type == bgp_show_type_damp_neighbor) {
11418 union sockunion *su = output_arg;
11419
40381db7
DS
11420 if (pi->peer == NULL
11421 || pi->peer->su_remote == NULL
11422 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11423 continue;
11424 }
11425 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11426 uint32_t destination;
d62a17ae 11427
9bcb3eef 11428 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11429 if (IN_CLASSC(destination)
9bcb3eef 11430 && dest_p->prefixlen == 24)
98ce9a06
DS
11431 continue;
11432 if (IN_CLASSB(destination)
9bcb3eef 11433 && dest_p->prefixlen == 16)
98ce9a06
DS
11434 continue;
11435 if (IN_CLASSA(destination)
9bcb3eef 11436 && dest_p->prefixlen == 8)
98ce9a06
DS
11437 continue;
11438 }
11439 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11440 p = output_arg;
9bcb3eef 11441 if (!prefix_match(p, dest_p))
98ce9a06
DS
11442 continue;
11443 }
11444 if (type == bgp_show_type_community_all) {
9a706b42 11445 if (!picomm)
98ce9a06
DS
11446 continue;
11447 }
11448 if (type == bgp_show_type_community) {
11449 struct community *com = output_arg;
d62a17ae 11450
9a706b42 11451 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11452 continue;
11453 }
11454 if (type == bgp_show_type_community_exact) {
11455 struct community *com = output_arg;
d62a17ae 11456
9a706b42 11457 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11458 continue;
11459 }
11460 if (type == bgp_show_type_community_list) {
11461 struct community_list *list = output_arg;
d62a17ae 11462
9a706b42 11463 if (!community_list_match(picomm, list))
98ce9a06
DS
11464 continue;
11465 }
a4d82a8a 11466 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11467 struct community_list *list = output_arg;
d62a17ae 11468
9a706b42 11469 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11470 continue;
11471 }
11472 if (type == bgp_show_type_lcommunity) {
11473 struct lcommunity *lcom = output_arg;
d62a17ae 11474
1bcf3a96
DA
11475 if (!bgp_attr_get_lcommunity(pi->attr) ||
11476 !lcommunity_match(
11477 bgp_attr_get_lcommunity(pi->attr),
11478 lcom))
98ce9a06
DS
11479 continue;
11480 }
36a206db 11481
11482 if (type == bgp_show_type_lcommunity_exact) {
11483 struct lcommunity *lcom = output_arg;
11484
1bcf3a96
DA
11485 if (!bgp_attr_get_lcommunity(pi->attr) ||
11486 !lcommunity_cmp(
11487 bgp_attr_get_lcommunity(pi->attr),
11488 lcom))
36a206db 11489 continue;
11490 }
98ce9a06
DS
11491 if (type == bgp_show_type_lcommunity_list) {
11492 struct community_list *list = output_arg;
d62a17ae 11493
1bcf3a96
DA
11494 if (!lcommunity_list_match(
11495 bgp_attr_get_lcommunity(pi->attr),
11496 list))
98ce9a06
DS
11497 continue;
11498 }
36a206db 11499 if (type
11500 == bgp_show_type_lcommunity_list_exact) {
11501 struct community_list *list = output_arg;
11502
11503 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11504 bgp_attr_get_lcommunity(pi->attr),
11505 list))
36a206db 11506 continue;
11507 }
98ce9a06 11508 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11509 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11510 continue;
11511 }
11512 if (type == bgp_show_type_dampend_paths
11513 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11514 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11515 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11516 continue;
11517 }
83856649
KQ
11518 if (type == bgp_show_type_self_originated) {
11519 if (pi->peer != bgp->peer_self)
11520 continue;
11521 }
98ce9a06
DS
11522
11523 if (!use_json && header) {
23d0a753
DA
11524 vty_out(vty,
11525 "BGP table version is %" PRIu64
11526 ", local router ID is %pI4, vrf id ",
11527 table->version, &bgp->router_id);
9df8b37c
PZ
11528 if (bgp->vrf_id == VRF_UNKNOWN)
11529 vty_out(vty, "%s", VRFID_NONE_STR);
11530 else
11531 vty_out(vty, "%u", bgp->vrf_id);
11532 vty_out(vty, "\n");
01eced22
AD
11533 vty_out(vty, "Default local pref %u, ",
11534 bgp->default_local_pref);
e84c7c12
PG
11535 vty_out(vty, "local AS ");
11536 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11537 &bgp->as);
11538 vty_out(vty, "\n");
509d82bd 11539 if (!detail_routes) {
9a1aae2d
DA
11540 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11541 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11542 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11543 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11544 }
d62a17ae 11545 if (type == bgp_show_type_dampend_paths
11546 || type == bgp_show_type_damp_neighbor)
98ce9a06 11547 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11548 else if (type == bgp_show_type_flap_statistics
11549 || type == bgp_show_type_flap_neighbor)
98ce9a06 11550 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11551 else if (!detail_routes)
ae248832
MK
11552 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11553 : BGP_SHOW_HEADER));
2aad8c42
MS
11554 header = false;
11555
d62a17ae 11556 }
98ce9a06
DS
11557 if (rd != NULL && !display && !output_count) {
11558 if (!use_json)
11559 vty_out(vty,
11560 "Route Distinguisher: %s\n",
11561 rd);
d62a17ae 11562 }
98ce9a06
DS
11563 if (type == bgp_show_type_dampend_paths
11564 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11565 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11566 AFI_IP, safi, use_json,
11567 json_paths);
98ce9a06
DS
11568 else if (type == bgp_show_type_flap_statistics
11569 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11570 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11571 AFI_IP, safi, use_json,
11572 json_paths);
f280c93b 11573 else {
27bb782a
DA
11574 if (detail_routes || detail_json) {
11575 const struct prefix_rd *prd = NULL;
9a1aae2d 11576
27bb782a
DA
11577 if (dest->pdest)
11578 prd = bgp_rd_from_dest(
11579 dest->pdest, safi);
9a1aae2d
DA
11580
11581 if (!use_json)
11582 route_vty_out_detail_header(
11583 vty, bgp, dest,
11584 bgp_dest_get_prefix(
11585 dest),
11586 prd, table->afi, safi,
f9f2d188 11587 NULL, false);
9a1aae2d 11588
f280c93b 11589 route_vty_out_detail(
27bb782a 11590 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11591 family2afi(dest_p->family),
11592 safi, RPKI_NOT_BEING_USED,
11593 json_paths);
9a1aae2d 11594 } else {
f280c93b
DA
11595 route_vty_out(vty, dest_p, pi, display,
11596 safi, json_paths, wide);
9a1aae2d 11597 }
f280c93b 11598 }
98ce9a06 11599 display++;
d62a17ae 11600 }
11601
98ce9a06
DS
11602 if (display) {
11603 output_count++;
11604 if (!use_json)
11605 continue;
11606
625d2931 11607 /* encode prefix */
9bcb3eef 11608 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11609 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11610
1840384b 11611
b54892e0
DS
11612 bgp_fs_nlri_get_string(
11613 (unsigned char *)
9bcb3eef
DS
11614 dest_p->u.prefix_flowspec.ptr,
11615 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11616 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11617 family2afi(dest_p->u
11618 .prefix_flowspec.family));
625d2931 11619 if (first)
b54892e0 11620 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11621 dest_p->u.prefix_flowspec
b54892e0 11622 .prefixlen);
625d2931 11623 else
b54892e0 11624 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11625 dest_p->u.prefix_flowspec
b54892e0 11626 .prefixlen);
625d2931 11627 } else {
625d2931 11628 if (first)
1b78780b 11629 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11630 else
1b78780b 11631 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11632 }
f9f2d188 11633
8ed85db6
TA
11634 /* This is used for 'json detail' vty keywords.
11635 *
11636 * In plain 'json' the per-prefix header is encoded
11637 * as a standalone dictionary in the first json_paths
11638 * array element:
11639 * "<prefix>": [{header}, {path-1}, {path-N}]
11640 * (which is confusing and borderline broken)
11641 *
11642 * For 'json detail' this changes the value
11643 * of each prefix-key to be a dictionary where each
11644 * header item has its own key, and json_paths is
11645 * tucked under the "paths" key:
11646 * "<prefix>": {
11647 * "<header-key-1>": <header-val-1>,
11648 * "<header-key-N>": <header-val-N>,
11649 * "paths": [{path-1}, {path-N}]
11650 * }
11651 */
f9f2d188
TA
11652 if (json_detail_header && json_paths != NULL) {
11653 const struct prefix_rd *prd;
11654
8ed85db6 11655 /* Start per-prefix dictionary */
f9f2d188
TA
11656 vty_out(vty, "{\n");
11657
11658 prd = bgp_rd_from_dest(dest, safi);
11659
11660 route_vty_out_detail_header(
11661 vty, bgp, dest,
11662 bgp_dest_get_prefix(dest), prd,
11663 table->afi, safi, json_paths, true);
11664
11665 vty_out(vty, "\"paths\": ");
11666 json_detail_header_used = true;
11667 }
11668
d7c6467b
DS
11669 /*
11670 * We are using no_pretty here because under
11671 * extremely high settings( say lots and lots of
11672 * routes with lots and lots of ways to reach
11673 * that route via different paths ) this can
11674 * save several minutes of output when FRR
11675 * is run on older cpu's or more underperforming
11676 * routers out there
11677 */
11678 vty_json_no_pretty(vty, json_paths);
f9f2d188 11679
8ed85db6 11680 /* End per-prefix dictionary */
f9f2d188
TA
11681 if (json_detail_header_used)
11682 vty_out(vty, "} ");
11683
449feb8e 11684 json_paths = NULL;
98ce9a06 11685 first = 0;
1f83ed02
DS
11686 } else
11687 json_object_free(json_paths);
98ce9a06
DS
11688 }
11689
1ae44dfc
LB
11690 if (output_cum) {
11691 output_count += *output_cum;
11692 *output_cum = output_count;
11693 }
11694 if (total_cum) {
11695 total_count += *total_cum;
11696 *total_cum = total_count;
11697 }
d62a17ae 11698 if (use_json) {
9386b588 11699 if (rd) {
a4d82a8a 11700 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11701 }
11702 if (is_last) {
a4d82a8a
PZ
11703 unsigned long i;
11704 for (i = 0; i < *json_header_depth; ++i)
11705 vty_out(vty, " } ");
96f3485c
MK
11706 if (!all)
11707 vty_out(vty, "\n");
9386b588 11708 }
d62a17ae 11709 } else {
1ae44dfc
LB
11710 if (is_last) {
11711 /* No route is displayed */
11712 if (output_count == 0) {
11713 if (type == bgp_show_type_normal)
11714 vty_out(vty,
11715 "No BGP prefixes displayed, %ld exist\n",
11716 total_count);
11717 } else
d62a17ae 11718 vty_out(vty,
1ae44dfc
LB
11719 "\nDisplayed %ld routes and %ld total paths\n",
11720 output_count, total_count);
11721 }
d62a17ae 11722 }
718e3744 11723
d62a17ae 11724 return CMD_SUCCESS;
718e3744 11725}
11726
1ae44dfc
LB
11727int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11728 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11729 enum bgp_show_type type, void *output_arg,
11730 uint16_t show_flags)
1ae44dfc 11731{
9bcb3eef 11732 struct bgp_dest *dest, *next;
1ae44dfc
LB
11733 unsigned long output_cum = 0;
11734 unsigned long total_cum = 0;
9386b588 11735 unsigned long json_header_depth = 0;
67009e22 11736 struct bgp_table *itable;
0136788c 11737 bool show_msg;
27bb782a 11738 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11739
11740 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11741
9bcb3eef
DS
11742 for (dest = bgp_table_top(table); dest; dest = next) {
11743 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11744
9bcb3eef
DS
11745 next = bgp_route_next(dest);
11746 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11747 continue;
67009e22 11748
9bcb3eef 11749 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11750 if (itable != NULL) {
1ae44dfc 11751 struct prefix_rd prd;
06b9f471 11752 char rd[RD_ADDRSTRLEN];
1ae44dfc 11753
9bcb3eef 11754 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11755 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11756 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11757 rd, next == NULL, &output_cum,
11758 &total_cum, &json_header_depth,
1e2ce4f1 11759 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11760 if (next == NULL)
11761 show_msg = false;
1ae44dfc
LB
11762 }
11763 }
0136788c
LB
11764 if (show_msg) {
11765 if (output_cum == 0)
11766 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11767 total_cum);
11768 else
11769 vty_out(vty,
11770 "\nDisplayed %ld routes and %ld total paths\n",
11771 output_cum, total_cum);
0224b329
DA
11772 } else {
11773 if (use_json && output_cum == 0)
11774 vty_out(vty, "{}\n");
0136788c 11775 }
1ae44dfc
LB
11776 return CMD_SUCCESS;
11777}
2aad8c42 11778
d62a17ae 11779static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11780 enum bgp_show_type type, void *output_arg,
96c81f66 11781 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11782{
d62a17ae 11783 struct bgp_table *table;
9386b588 11784 unsigned long json_header_depth = 0;
96f3485c 11785 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11786
d62a17ae 11787 if (bgp == NULL) {
11788 bgp = bgp_get_default();
11789 }
fee0f4c6 11790
d62a17ae 11791 if (bgp == NULL) {
11792 if (!use_json)
11793 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11794 else
11795 vty_out(vty, "{}\n");
d62a17ae 11796 return CMD_WARNING;
11797 }
4dd6177e 11798
cd8c2a27
MS
11799 /* Labeled-unicast routes live in the unicast table. */
11800 if (safi == SAFI_LABELED_UNICAST)
11801 safi = SAFI_UNICAST;
11802
1ae44dfc 11803 table = bgp->rib[afi][safi];
d62a17ae 11804 /* use MPLS and ENCAP specific shows until they are merged */
11805 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11806 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11807 output_arg, show_flags);
d62a17ae 11808 }
dba3c1d3
PG
11809
11810 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11811 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11812 output_arg, use_json,
11813 1, NULL, NULL);
11814 }
fee0f4c6 11815
0adc5bbb
LS
11816 if (safi == SAFI_EVPN)
11817 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11818
96f3485c 11819 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11820 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11821 rpki_target_state);
fee0f4c6 11822}
11823
d62a17ae 11824static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11825 safi_t safi, uint16_t show_flags)
f186de26 11826{
d62a17ae 11827 struct listnode *node, *nnode;
11828 struct bgp *bgp;
11829 int is_first = 1;
9f049418 11830 bool route_output = false;
96f3485c 11831 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11832
d62a17ae 11833 if (use_json)
11834 vty_out(vty, "{\n");
9f689658 11835
d62a17ae 11836 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11837 route_output = true;
d62a17ae 11838 if (use_json) {
11839 if (!is_first)
11840 vty_out(vty, ",\n");
11841 else
11842 is_first = 0;
11843
11844 vty_out(vty, "\"%s\":",
11845 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11846 ? VRF_DEFAULT_NAME
d62a17ae 11847 : bgp->name);
11848 } else {
11849 vty_out(vty, "\nInstance %s:\n",
11850 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11851 ? VRF_DEFAULT_NAME
d62a17ae 11852 : bgp->name);
11853 }
11854 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11855 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11856 }
9f689658 11857
d62a17ae 11858 if (use_json)
11859 vty_out(vty, "}\n");
9f049418
DS
11860 else if (!route_output)
11861 vty_out(vty, "%% BGP instance not found\n");
f186de26 11862}
11863
718e3744 11864/* Header of detailed BGP route information */
d62a17ae 11865void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11866 struct bgp_dest *dest, const struct prefix *p,
11867 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11868 safi_t safi, json_object *json,
11869 bool incremental_print)
d62a17ae 11870{
40381db7 11871 struct bgp_path_info *pi;
d62a17ae 11872 struct peer *peer;
11873 struct listnode *node, *nnode;
06b9f471 11874 char buf1[RD_ADDRSTRLEN];
d62a17ae 11875 int count = 0;
11876 int best = 0;
11877 int suppress = 0;
c5f1e1b2
C
11878 int accept_own = 0;
11879 int route_filter_translated_v4 = 0;
11880 int route_filter_v4 = 0;
11881 int route_filter_translated_v6 = 0;
11882 int route_filter_v6 = 0;
11883 int llgr_stale = 0;
11884 int no_llgr = 0;
11885 int accept_own_nexthop = 0;
11886 int blackhole = 0;
d62a17ae 11887 int no_export = 0;
11888 int no_advertise = 0;
11889 int local_as = 0;
c5f1e1b2 11890 int no_peer = 0;
d62a17ae 11891 int first = 1;
11892 int has_valid_label = 0;
11893 mpls_label_t label = 0;
11894 json_object *json_adv_to = NULL;
67f67ba4
DA
11895 uint32_t ttl = 0;
11896 uint32_t bos = 0;
11897 uint32_t exp = 0;
9bedbb1e 11898
67f67ba4 11899 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11900
67f67ba4 11901 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11902
44c69747 11903 if (safi == SAFI_EVPN) {
44c69747 11904 if (!json) {
2dbe669b 11905 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11906 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11907 bgp->asnotation)
f137734b 11908 : "",
2dbe669b 11909 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11910 } else {
4a8cd6ad
PG
11911 json_object_string_add(
11912 json, "rd",
11913 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11914 bgp->asnotation)
11915 : "");
44c69747
LK
11916 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11917 }
11918 } else {
11919 if (!json) {
9119ef3a
DA
11920 vty_out(vty,
11921 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11922 "\n",
ea5a8e4d
DA
11923 (((safi == SAFI_MPLS_VPN ||
11924 safi == SAFI_ENCAP) &&
11925 prd)
8228a9a7 11926 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11927 sizeof(buf1),
11928 bgp->asnotation)
8228a9a7 11929 : ""),
ea5a8e4d 11930 safi == SAFI_MPLS_VPN && prd ? ":" : "", p,
9119ef3a 11931 dest->version);
cd1964ff 11932
9119ef3a 11933 } else {
f9f2d188
TA
11934 if (incremental_print) {
11935 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11936 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11937 dest->version);
11938 } else {
11939 json_object_string_addf(json, "prefix", "%pFX",
11940 p);
11941 json_object_int_add(json, "version",
11942 dest->version);
11943 }
9119ef3a 11944 }
44c69747
LK
11945 }
11946
11947 if (has_valid_label) {
f9f2d188
TA
11948 if (json) {
11949 if (incremental_print)
11950 vty_out(vty, "\"localLabel\": \"%u\",\n",
11951 label);
11952 else
11953 json_object_int_add(json, "localLabel", label);
11954 } else
d62a17ae 11955 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11956 }
11957
11958 if (!json)
d62a17ae 11959 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11960 vty_out(vty, "not allocated\n");
718e3744 11961
9bcb3eef 11962 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11963 struct community *picomm = NULL;
11964
11965 picomm = bgp_attr_get_community(pi->attr);
11966
d62a17ae 11967 count++;
40381db7 11968 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11969 best = count;
4056a5f6 11970 if (bgp_path_suppressed(pi))
d62a17ae 11971 suppress = 1;
cee9c031 11972
9a706b42 11973 if (!picomm)
cee9c031
QY
11974 continue;
11975
11976 no_advertise += community_include(
9a706b42
DA
11977 picomm, COMMUNITY_NO_ADVERTISE);
11978 no_export +=
11979 community_include(picomm, COMMUNITY_NO_EXPORT);
11980 local_as +=
11981 community_include(picomm, COMMUNITY_LOCAL_AS);
11982 accept_own +=
11983 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11984 route_filter_translated_v4 += community_include(
9a706b42 11985 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11986 route_filter_translated_v6 += community_include(
9a706b42 11987 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11988 route_filter_v4 += community_include(
9a706b42 11989 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11990 route_filter_v6 += community_include(
9a706b42
DA
11991 picomm, COMMUNITY_ROUTE_FILTER_v6);
11992 llgr_stale +=
11993 community_include(picomm, COMMUNITY_LLGR_STALE);
11994 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11995 accept_own_nexthop += community_include(
11996 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11997 blackhole +=
11998 community_include(picomm, COMMUNITY_BLACKHOLE);
11999 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 12000 }
718e3744 12001 }
718e3744 12002
d62a17ae 12003 if (!json) {
12004 vty_out(vty, "Paths: (%d available", count);
12005 if (best) {
12006 vty_out(vty, ", best #%d", best);
b84060bb
PG
12007 if (safi == SAFI_UNICAST) {
12008 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
12009 vty_out(vty, ", table %s",
12010 VRF_DEFAULT_NAME);
12011 else
12012 vty_out(vty, ", vrf %s",
12013 bgp->name);
12014 }
d62a17ae 12015 } else
12016 vty_out(vty, ", no best path");
12017
c5f1e1b2
C
12018 if (accept_own)
12019 vty_out(vty,
12020 ", accept own local route exported and imported in different VRF");
12021 else if (route_filter_translated_v4)
12022 vty_out(vty,
12023 ", mark translated RTs for VPNv4 route filtering");
12024 else if (route_filter_v4)
12025 vty_out(vty,
12026 ", attach RT as-is for VPNv4 route filtering");
12027 else if (route_filter_translated_v6)
12028 vty_out(vty,
12029 ", mark translated RTs for VPNv6 route filtering");
12030 else if (route_filter_v6)
12031 vty_out(vty,
12032 ", attach RT as-is for VPNv6 route filtering");
12033 else if (llgr_stale)
12034 vty_out(vty,
1479ed2f 12035 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
12036 else if (no_llgr)
12037 vty_out(vty,
12038 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12039 else if (accept_own_nexthop)
12040 vty_out(vty,
12041 ", accept local nexthop");
12042 else if (blackhole)
12043 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 12044 else if (no_export)
12045 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
12046 else if (no_advertise)
12047 vty_out(vty, ", not advertised to any peer");
d62a17ae 12048 else if (local_as)
12049 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
12050 else if (no_peer)
12051 vty_out(vty,
12052 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 12053
12054 if (suppress)
12055 vty_out(vty,
12056 ", Advertisements suppressed by an aggregate.");
12057 vty_out(vty, ")\n");
12058 }
718e3744 12059
d62a17ae 12060 /* If we are not using addpath then we can display Advertised to and
12061 * that will
12062 * show what peers we advertised the bestpath to. If we are using
12063 * addpath
12064 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12065 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12066 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12067 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12068 if (json && !json_adv_to)
12069 json_adv_to = json_object_new_object();
12070
12071 route_vty_out_advertised_to(
12072 vty, peer, &first,
12073 " Advertised to non peer-group peers:\n ",
12074 json_adv_to);
12075 }
12076 }
12077
f9f2d188
TA
12078 if (json && json_adv_to) {
12079 if (incremental_print) {
12080 vty_out(vty, "\"advertisedTo\": ");
12081 vty_json(vty, json_adv_to);
12082 vty_out(vty, ",");
12083 } else
d62a17ae 12084 json_object_object_add(json, "advertisedTo",
12085 json_adv_to);
d62a17ae 12086 } else {
f9f2d188 12087 if (!json && first)
d62a17ae 12088 vty_out(vty, " Not advertised to any peer");
12089 vty_out(vty, "\n");
12090 }
12091 }
718e3744 12092}
12093
edfee30d 12094static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12095 struct bgp_dest *bgp_node, struct vty *vty,
12096 struct bgp *bgp, afi_t afi, safi_t safi,
12097 json_object *json, enum bgp_path_type pathtype,
4027d19b 12098 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12099{
12100 struct bgp_path_info *pi;
12101 int header = 1;
44c69747
LK
12102 json_object *json_header = NULL;
12103 json_object *json_paths = NULL;
4933eaaf 12104 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12105
9bcb3eef 12106 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12107 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12108
12109 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12110 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12111 pi->peer, pi->attr, p);
4933eaaf 12112
4027d19b
DS
12113 if (rpki_target_state != RPKI_NOT_BEING_USED
12114 && rpki_curr_state != rpki_target_state)
4933eaaf 12115 continue;
44c69747
LK
12116
12117 if (json && !json_paths) {
12118 /* Instantiate json_paths only if path is valid */
12119 json_paths = json_object_new_array();
c4f64ea9 12120 if (pfx_rd)
44c69747 12121 json_header = json_object_new_object();
c4f64ea9 12122 else
44c69747
LK
12123 json_header = json;
12124 }
12125
12126 if (header) {
12127 route_vty_out_detail_header(
34c7f35f
SW
12128 vty, bgp, bgp_node,
12129 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12130 safi, json_header, false);
44c69747
LK
12131 header = 0;
12132 }
12133 (*display)++;
12134
12135 if (pathtype == BGP_PATH_SHOW_ALL
12136 || (pathtype == BGP_PATH_SHOW_BESTPATH
12137 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12138 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12139 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12140 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12141 route_vty_out_detail(vty, bgp, bgp_node,
12142 bgp_dest_get_prefix(bgp_node), pi,
12143 AFI_IP, safi, rpki_curr_state,
12144 json_paths);
44c69747
LK
12145 }
12146
12147 if (json && json_paths) {
12148 json_object_object_add(json_header, "paths", json_paths);
12149
12150 if (pfx_rd)
4a8cd6ad
PG
12151 json_object_object_addf(
12152 json, json_header,
12153 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12154 }
12155}
12156
2aad8c42
MS
12157/*
12158 * Return rd based on safi
12159 */
46dbf9d0
DA
12160const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12161 safi_t safi)
2aad8c42
MS
12162{
12163 switch (safi) {
12164 case SAFI_MPLS_VPN:
12165 case SAFI_ENCAP:
12166 case SAFI_EVPN:
12167 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12168 case SAFI_UNSPEC:
12169 case SAFI_UNICAST:
12170 case SAFI_MULTICAST:
12171 case SAFI_LABELED_UNICAST:
12172 case SAFI_FLOWSPEC:
12173 case SAFI_MAX:
2aad8c42 12174 return NULL;
2aad8c42 12175 }
58cf0823
DS
12176
12177 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12178}
12179
718e3744 12180/* Display specified route of BGP table. */
d62a17ae 12181static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12182 struct bgp_table *rib, const char *ip_str,
12183 afi_t afi, safi_t safi,
4027d19b 12184 enum rpki_states rpki_target_state,
d62a17ae 12185 struct prefix_rd *prd, int prefix_check,
9f049418 12186 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12187{
12188 int ret;
d62a17ae 12189 int display = 0;
12190 struct prefix match;
9bcb3eef
DS
12191 struct bgp_dest *dest;
12192 struct bgp_dest *rm;
d62a17ae 12193 struct bgp_table *table;
12194 json_object *json = NULL;
12195 json_object *json_paths = NULL;
12196
12197 /* Check IP address argument. */
12198 ret = str2prefix(ip_str, &match);
12199 if (!ret) {
12200 vty_out(vty, "address is malformed\n");
12201 return CMD_WARNING;
12202 }
718e3744 12203
d62a17ae 12204 match.family = afi2family(afi);
b05a1c8b 12205
44c69747 12206 if (use_json)
d62a17ae 12207 json = json_object_new_object();
718e3744 12208
44c69747 12209 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12210 for (dest = bgp_table_top(rib); dest;
12211 dest = bgp_route_next(dest)) {
12212 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12213
9bcb3eef 12214 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12215 continue;
9bcb3eef 12216 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12217 if (!table)
ea47320b 12218 continue;
d62a17ae 12219
4953391b
DA
12220 rm = bgp_node_match(table, &match);
12221 if (rm == NULL)
ea47320b 12222 continue;
d62a17ae 12223
9bcb3eef 12224 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12225 if (prefix_check
b54892e0 12226 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12227 bgp_dest_unlock_node(rm);
ea47320b
DL
12228 continue;
12229 }
d62a17ae 12230
9bcb3eef 12231 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12232 bgp, afi, safi, json, pathtype,
4027d19b 12233 &display, rpki_target_state);
44c69747 12234
9bcb3eef 12235 bgp_dest_unlock_node(rm);
44c69747
LK
12236 }
12237 } else if (safi == SAFI_EVPN) {
9bcb3eef 12238 struct bgp_dest *longest_pfx;
cded3b72 12239 bool is_exact_pfxlen_match = false;
44c69747 12240
9bcb3eef
DS
12241 for (dest = bgp_table_top(rib); dest;
12242 dest = bgp_route_next(dest)) {
12243 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12244
9bcb3eef 12245 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12246 continue;
9bcb3eef 12247 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12248 if (!table)
12249 continue;
12250
12251 longest_pfx = NULL;
cded3b72 12252 is_exact_pfxlen_match = false;
44c69747
LK
12253 /*
12254 * Search through all the prefixes for a match. The
12255 * pfx's are enumerated in ascending order of pfxlens.
12256 * So, the last pfx match is the longest match. Set
12257 * is_exact_pfxlen_match when we get exact pfxlen match
12258 */
12259 for (rm = bgp_table_top(table); rm;
12260 rm = bgp_route_next(rm)) {
b54892e0 12261 const struct prefix *rm_p =
9bcb3eef 12262 bgp_dest_get_prefix(rm);
44c69747
LK
12263 /*
12264 * Get prefixlen of the ip-prefix within type5
12265 * evpn route
12266 */
b54892e0
DS
12267 if (evpn_type5_prefix_match(rm_p, &match)
12268 && rm->info) {
44c69747
LK
12269 longest_pfx = rm;
12270 int type5_pfxlen =
b54892e0
DS
12271 bgp_evpn_get_type5_prefixlen(
12272 rm_p);
44c69747 12273 if (type5_pfxlen == match.prefixlen) {
cded3b72 12274 is_exact_pfxlen_match = true;
9bcb3eef 12275 bgp_dest_unlock_node(rm);
44c69747
LK
12276 break;
12277 }
d62a17ae 12278 }
12279 }
ea47320b 12280
44c69747
LK
12281 if (!longest_pfx)
12282 continue;
12283
12284 if (prefix_check && !is_exact_pfxlen_match)
12285 continue;
12286
12287 rm = longest_pfx;
9bcb3eef 12288 bgp_dest_lock_node(rm);
44c69747 12289
9bcb3eef 12290 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12291 bgp, afi, safi, json, pathtype,
4027d19b 12292 &display, rpki_target_state);
44c69747 12293
9bcb3eef 12294 bgp_dest_unlock_node(rm);
d62a17ae 12295 }
98a9dbc7 12296 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12297 if (use_json)
12298 json_paths = json_object_new_array();
12299
63a0b7a9
PG
12300 display = bgp_flowspec_display_match_per_ip(afi, rib,
12301 &match, prefix_check,
12302 vty,
12303 use_json,
12304 json_paths);
d5f20468
SP
12305 if (use_json) {
12306 if (display)
12307 json_object_object_add(json, "paths",
12308 json_paths);
12309 else
12310 json_object_free(json_paths);
12311 }
d62a17ae 12312 } else {
4953391b
DA
12313 dest = bgp_node_match(rib, &match);
12314 if (dest != NULL) {
9bcb3eef 12315 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12316 if (!prefix_check
9bcb3eef
DS
12317 || dest_p->prefixlen == match.prefixlen) {
12318 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12319 safi, json, pathtype,
4027d19b 12320 &display, rpki_target_state);
d62a17ae 12321 }
12322
9bcb3eef 12323 bgp_dest_unlock_node(dest);
d62a17ae 12324 }
12325 }
e5eee9af 12326
d62a17ae 12327 if (use_json) {
75eeda93 12328 vty_json(vty, json);
d62a17ae 12329 } else {
12330 if (!display) {
12331 vty_out(vty, "%% Network not in table\n");
12332 return CMD_WARNING;
12333 }
12334 }
b05a1c8b 12335
d62a17ae 12336 return CMD_SUCCESS;
718e3744 12337}
12338
fee0f4c6 12339/* Display specified route of Main RIB */
d62a17ae 12340static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12341 afi_t afi, safi_t safi, struct prefix_rd *prd,
12342 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12343 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12344{
9b86009a 12345 if (!bgp) {
d62a17ae 12346 bgp = bgp_get_default();
9b86009a
RW
12347 if (!bgp) {
12348 if (!use_json)
12349 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12350 else
12351 vty_out(vty, "{}\n");
9b86009a
RW
12352 return CMD_WARNING;
12353 }
12354 }
d62a17ae 12355
12356 /* labeled-unicast routes live in the unicast table */
12357 if (safi == SAFI_LABELED_UNICAST)
12358 safi = SAFI_UNICAST;
12359
12360 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12361 afi, safi, rpki_target_state, prd,
8aa22bbb 12362 prefix_check, pathtype, use_json);
d62a17ae 12363}
12364
12365static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12366 struct cmd_token **argv, bool exact, afi_t afi,
12367 safi_t safi, bool uj)
d62a17ae 12368{
12369 struct lcommunity *lcom;
12370 struct buffer *b;
12371 int i;
12372 char *str;
12373 int first = 0;
96c81f66 12374 uint16_t show_flags = 0;
4f28b2b5 12375 int ret;
96f3485c
MK
12376
12377 if (uj)
12378 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12379
12380 b = buffer_new(1024);
12381 for (i = 0; i < argc; i++) {
12382 if (first)
12383 buffer_putc(b, ' ');
12384 else {
12385 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12386 first = 1;
12387 buffer_putstr(b, argv[i]->arg);
12388 }
12389 }
12390 }
12391 buffer_putc(b, '\0');
57d187bc 12392
d62a17ae 12393 str = buffer_getstr(b);
12394 buffer_free(b);
57d187bc 12395
d62a17ae 12396 lcom = lcommunity_str2com(str);
12397 XFREE(MTYPE_TMP, str);
12398 if (!lcom) {
12399 vty_out(vty, "%% Large-community malformed\n");
12400 return CMD_WARNING;
12401 }
57d187bc 12402
4f28b2b5 12403 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12404 (exact ? bgp_show_type_lcommunity_exact
12405 : bgp_show_type_lcommunity),
12406 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12407
12408 lcommunity_free(&lcom);
12409 return ret;
57d187bc
JS
12410}
12411
d62a17ae 12412static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12413 const char *lcom, bool exact, afi_t afi,
12414 safi_t safi, bool uj)
57d187bc 12415{
d62a17ae 12416 struct community_list *list;
96c81f66 12417 uint16_t show_flags = 0;
96f3485c
MK
12418
12419 if (uj)
12420 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12421
57d187bc 12422
e237b0d2 12423 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12424 LARGE_COMMUNITY_LIST_MASTER);
12425 if (list == NULL) {
12426 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12427 lcom);
12428 return CMD_WARNING;
12429 }
57d187bc 12430
36a206db 12431 return bgp_show(vty, bgp, afi, safi,
12432 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12433 : bgp_show_type_lcommunity_list),
1e2ce4f1 12434 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12435}
12436
52951b63
DS
12437DEFUN (show_ip_bgp_large_community_list,
12438 show_ip_bgp_large_community_list_cmd,
77a3a95e 12439 "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
12440 SHOW_STR
12441 IP_STR
12442 BGP_STR
12443 BGP_INSTANCE_HELP_STR
9bedbb1e 12444 BGP_AFI_HELP_STR
4dd6177e 12445 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12446 "Display routes matching the large-community-list\n"
12447 "large-community-list number\n"
12448 "large-community-list name\n"
36a206db 12449 "Exact match of the large-communities\n"
52951b63
DS
12450 JSON_STR)
12451{
d62a17ae 12452 afi_t afi = AFI_IP6;
12453 safi_t safi = SAFI_UNICAST;
12454 int idx = 0;
36a206db 12455 bool exact_match = 0;
4d678463 12456 struct bgp *bgp = NULL;
9f049418 12457 bool uj = use_json(argc, argv);
d62a17ae 12458
ef3364f0
DA
12459 if (uj)
12460 argc--;
4d678463 12461
ef3364f0
DA
12462 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12463 &bgp, uj);
12464 if (!idx)
12465 return CMD_WARNING;
d62a17ae 12466
12467 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12468
12469 const char *clist_number_or_name = argv[++idx]->arg;
12470
12471 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12472 exact_match = 1;
12473
12474 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12475 exact_match, afi, safi, uj);
52951b63
DS
12476}
12477DEFUN (show_ip_bgp_large_community,
12478 show_ip_bgp_large_community_cmd,
36a206db 12479 "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
12480 SHOW_STR
12481 IP_STR
12482 BGP_STR
12483 BGP_INSTANCE_HELP_STR
9bedbb1e 12484 BGP_AFI_HELP_STR
4dd6177e 12485 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12486 "Display routes matching the large-communities\n"
12487 "List of large-community numbers\n"
36a206db 12488 "Exact match of the large-communities\n"
52951b63
DS
12489 JSON_STR)
12490{
d62a17ae 12491 afi_t afi = AFI_IP6;
12492 safi_t safi = SAFI_UNICAST;
12493 int idx = 0;
36a206db 12494 bool exact_match = 0;
4d678463 12495 struct bgp *bgp = NULL;
9f049418 12496 bool uj = use_json(argc, argv);
96c81f66 12497 uint16_t show_flags = 0;
d62a17ae 12498
96f3485c
MK
12499 if (uj) {
12500 argc--;
12501 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12502 }
4d678463 12503
96f3485c
MK
12504 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12505 &bgp, uj);
12506 if (!idx)
12507 return CMD_WARNING;
d62a17ae 12508
36a206db 12509 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12510 if (argv_find(argv, argc, "exact-match", &idx)) {
12511 argc--;
36a206db 12512 exact_match = 1;
1857760c 12513 }
36a206db 12514 return bgp_show_lcommunity(vty, bgp, argc, argv,
12515 exact_match, afi, safi, uj);
12516 } else
d62a17ae 12517 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12518 bgp_show_type_lcommunity_all, NULL, show_flags,
12519 RPKI_NOT_BEING_USED);
52951b63
DS
12520}
12521
71f1613a
DA
12522static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12523 safi_t safi, struct json_object *json_array);
d62a17ae 12524static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12525 safi_t safi, struct json_object *json);
e01ca200 12526
7b2ff250 12527
9ab0cf58
PG
12528DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12529 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12530 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12531 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12532{
12533 bool uj = use_json(argc, argv);
12534 struct bgp *bgp = NULL;
ec76a1d1
DA
12535 safi_t safi = SAFI_UNICAST;
12536 afi_t afi = AFI_IP6;
4265b261 12537 int idx = 0;
6c9d22e2
PG
12538 struct json_object *json_all = NULL;
12539 struct json_object *json_afi_safi = NULL;
4265b261
PG
12540
12541 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12542 &bgp, false);
71f1613a 12543 if (!idx)
4265b261 12544 return CMD_WARNING;
6c9d22e2 12545
4265b261 12546 if (uj)
6c9d22e2 12547 json_all = json_object_new_object();
4265b261 12548
9ab0cf58
PG
12549 FOREACH_AFI_SAFI (afi, safi) {
12550 /*
12551 * So limit output to those afi/safi pairs that
12552 * actually have something interesting in them
12553 */
12554 if (strmatch(get_afi_safi_str(afi, safi, true),
12555 "Unknown")) {
12556 continue;
12557 }
12558 if (uj) {
12559 json_afi_safi = json_object_new_array();
12560 json_object_object_add(
12561 json_all,
12562 get_afi_safi_str(afi, safi, true),
12563 json_afi_safi);
12564 } else {
12565 json_afi_safi = NULL;
6c9d22e2 12566 }
9ab0cf58
PG
12567
12568 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12569 }
6c9d22e2 12570
3757f964
DA
12571 if (uj)
12572 vty_json(vty, json_all);
6c9d22e2 12573
4265b261
PG
12574 return CMD_SUCCESS;
12575}
12576
7b2ff250 12577/* BGP route print out function without JSON */
14718643
PG
12578DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12579 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12580 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12581 SHOW_STR
12582 IP_STR
12583 BGP_STR
12584 BGP_INSTANCE_HELP_STR
12585 L2VPN_HELP_STR
12586 EVPN_HELP_STR
12587 "BGP RIB advertisement statistics\n"
12588 JSON_STR)
12589{
ec76a1d1
DA
12590 afi_t afi = AFI_IP6;
12591 safi_t safi = SAFI_UNICAST;
14718643
PG
12592 struct bgp *bgp = NULL;
12593 int idx = 0, ret;
12594 bool uj = use_json(argc, argv);
12595 struct json_object *json_afi_safi = NULL, *json = NULL;
12596
12597 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12598 &bgp, false);
12599 if (!idx)
12600 return CMD_WARNING;
12601
12602 if (uj)
12603 json_afi_safi = json_object_new_array();
12604 else
12605 json_afi_safi = NULL;
12606
12607 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12608
12609 if (uj) {
12610 json = json_object_new_object();
12611 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12612 json_afi_safi);
3757f964 12613 vty_json(vty, json);
14718643
PG
12614 }
12615 return ret;
12616}
12617
893cccd0 12618/* BGP route print out function without JSON */
9ab0cf58
PG
12619DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12620 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12621 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12622 "]]\
893cccd0 12623 statistics [json]",
9ab0cf58
PG
12624 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12625 BGP_SAFI_WITH_LABEL_HELP_STR
12626 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12627{
ec76a1d1
DA
12628 afi_t afi = AFI_IP6;
12629 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12630 struct bgp *bgp = NULL;
12631 int idx = 0, ret;
12632 bool uj = use_json(argc, argv);
6c9d22e2 12633 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12634
12635 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12636 &bgp, false);
12637 if (!idx)
12638 return CMD_WARNING;
6c9d22e2 12639
893cccd0 12640 if (uj)
6c9d22e2
PG
12641 json_afi_safi = json_object_new_array();
12642 else
12643 json_afi_safi = NULL;
12644
12645 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12646
12647 if (uj) {
12648 json = json_object_new_object();
12649 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12650 json_afi_safi);
3757f964 12651 vty_json(vty, json);
893cccd0
PG
12652 }
12653 return ret;
893cccd0 12654}
7b2ff250 12655
fe0f234d 12656DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12657 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12658 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12659 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12660 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12661 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12662 "Display the entries for all address families\n"
9ab0cf58
PG
12663 "Display detailed information about dampening\n"
12664 "Display detail of configured dampening parameters\n"
fe0f234d 12665 JSON_STR)
718e3744 12666{
d62a17ae 12667 afi_t afi = AFI_IP6;
12668 safi_t safi = SAFI_UNICAST;
d62a17ae 12669 struct bgp *bgp = NULL;
12670 int idx = 0;
96c81f66 12671 uint16_t show_flags = 0;
fe0f234d
RW
12672 bool uj = use_json(argc, argv);
12673
12674 if (uj) {
12675 argc--;
12676 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12677 }
96f3485c
MK
12678
12679 /* [<ipv4|ipv6> [all]] */
12680 if (all) {
12681 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12682 if (argv_find(argv, argc, "ipv4", &idx))
12683 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12684
12685 if (argv_find(argv, argc, "ipv6", &idx))
12686 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12687 }
d62a17ae 12688
12689 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12690 &bgp, false);
d62a17ae 12691 if (!idx)
12692 return CMD_WARNING;
12693
fe0f234d 12694 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12695}
12696
fe0f234d
RW
12697/* BGP route print out function */
12698DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12699 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12700 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12701 "]]\
96f3485c 12702 [all$all]\
cf4898bc
QY
12703 [cidr-only\
12704 |dampening <flap-statistics|dampened-paths>\
12705 |community [AA:NN|local-AS|no-advertise|no-export\
12706 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12707 |accept-own|accept-own-nexthop|route-filter-v6\
12708 |route-filter-v4|route-filter-translated-v6\
12709 |route-filter-translated-v4] [exact-match]\
70799983 12710 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12711 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12712 |prefix-list WORD\
ed126382 12713 |access-list ACCESSLIST_NAME\
70dd370f 12714 |route-map RMAP_NAME\
1e2ce4f1 12715 |rpki <invalid|valid|notfound>\
7d3cae70 12716 |version (1-4294967295)\
b4ad2fae 12717 |alias ALIAS_NAME\
39c3c736
RW
12718 |A.B.C.D/M longer-prefixes\
12719 |X:X::X:X/M longer-prefixes\
83856649 12720 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12721 |detail-routes$detail_routes\
67799a48 12722 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12723 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12724 BGP_SAFI_WITH_LABEL_HELP_STR
12725 "Display the entries for all address families\n"
12726 "Display only routes with non-natural netmasks\n"
12727 "Display detailed information about dampening\n"
12728 "Display flap statistics of routes\n"
12729 "Display paths suppressed due to dampening\n"
12730 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12731 "Do not send outside local AS (well-known community)\n"
12732 "Do not advertise to any peer (well-known community)\n"
12733 "Do not export to next AS (well-known community)\n"
12734 "Graceful shutdown (well-known community)\n"
12735 "Do not export to any peer (well-known community)\n"
12736 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12737 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12738 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12739 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12740 "Should accept VPN route with local nexthop (well-known community)\n"
12741 "RT VPNv6 route filtering (well-known community)\n"
12742 "RT VPNv4 route filtering (well-known community)\n"
12743 "RT translated VPNv6 route filtering (well-known community)\n"
12744 "RT translated VPNv4 route filtering (well-known community)\n"
12745 "Exact match of the communities\n"
70799983
RW
12746 "Community-list number\n"
12747 "Community-list name\n"
12748 "Display routes matching the community-list\n"
12749 "Exact match of the communities\n"
a7129347
RW
12750 "Display routes conforming to the filter-list\n"
12751 "Regular expression access list name\n"
6deaf579
RW
12752 "Display routes conforming to the prefix-list\n"
12753 "Prefix-list name\n"
ed126382
DA
12754 "Display routes conforming to the access-list\n"
12755 "Access-list name\n"
bf1a944a
RW
12756 "Display routes matching the route-map\n"
12757 "A route-map to match on\n"
a70a28a5
DA
12758 "RPKI route types\n"
12759 "A valid path as determined by rpki\n"
12760 "A invalid path as determined by rpki\n"
12761 "A path that has no rpki data\n"
12762 "Display prefixes with matching version numbers\n"
12763 "Version number and above\n"
12764 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12765 "BGP community alias\n"
12766 "IPv4 prefix\n"
12767 "Display route and more specific routes\n"
12768 "IPv6 prefix\n"
12769 "Display route and more specific routes\n"
83856649 12770 BGP_SELF_ORIG_HELP_STR
509d82bd 12771 "Display detailed version of all routes\n"
39c3c736 12772 JSON_STR
a70a28a5
DA
12773 "Display detailed version of JSON output\n"
12774 "Increase table width for longer prefixes\n")
7b2ff250
DW
12775{
12776 afi_t afi = AFI_IP6;
12777 safi_t safi = SAFI_UNICAST;
12778 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12779 void *output_arg = NULL;
7b2ff250
DW
12780 struct bgp *bgp = NULL;
12781 int idx = 0;
d0086e8e 12782 int exact_match = 0;
96f3485c
MK
12783 char *community = NULL;
12784 bool first = true;
96c81f66 12785 uint16_t show_flags = 0;
4027d19b 12786 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12787 struct prefix p;
96f3485c
MK
12788
12789 if (uj) {
9f049418 12790 argc--;
96f3485c
MK
12791 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12792 }
12793
67799a48
DA
12794 if (detail_json)
12795 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12796
509d82bd
DA
12797 if (detail_routes)
12798 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12799
96f3485c
MK
12800 /* [<ipv4|ipv6> [all]] */
12801 if (all) {
12802 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12803
12804 if (argv_find(argv, argc, "ipv4", &idx))
12805 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12806
12807 if (argv_find(argv, argc, "ipv6", &idx))
12808 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12809 }
12810
12811 if (wide)
12812 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12813
12814 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12815 &bgp, uj);
7b2ff250
DW
12816 if (!idx)
12817 return CMD_WARNING;
12818
7b2ff250 12819 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12820 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12821
12822 if (argv_find(argv, argc, "dampening", &idx)) {
12823 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12824 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12825 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12826 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12827 }
12828
12829 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12830 char *maybecomm = NULL;
d0086e8e 12831
79bc257a
RW
12832 if (idx + 1 < argc) {
12833 if (argv[idx + 1]->type == VARIABLE_TKN)
12834 maybecomm = argv[idx + 1]->arg;
12835 else
12836 maybecomm = argv[idx + 1]->text;
12837 }
12838
cf4898bc
QY
12839 if (maybecomm && !strmatch(maybecomm, "json")
12840 && !strmatch(maybecomm, "exact-match"))
12841 community = maybecomm;
d0086e8e 12842
cf4898bc
QY
12843 if (argv_find(argv, argc, "exact-match", &idx))
12844 exact_match = 1;
d0086e8e 12845
96f3485c
MK
12846 if (!community)
12847 sh_type = bgp_show_type_community_all;
12848 }
12849
70799983
RW
12850 if (argv_find(argv, argc, "community-list", &idx)) {
12851 const char *clist_number_or_name = argv[++idx]->arg;
12852 struct community_list *list;
12853
12854 if (argv_find(argv, argc, "exact-match", &idx))
12855 exact_match = 1;
12856
12857 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12858 COMMUNITY_LIST_MASTER);
12859 if (list == NULL) {
606d49a4 12860 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12861 clist_number_or_name);
12862 return CMD_WARNING;
12863 }
12864
12865 if (exact_match)
12866 sh_type = bgp_show_type_community_list_exact;
12867 else
12868 sh_type = bgp_show_type_community_list;
12869 output_arg = list;
12870 }
12871
a7129347
RW
12872 if (argv_find(argv, argc, "filter-list", &idx)) {
12873 const char *filter = argv[++idx]->arg;
12874 struct as_list *as_list;
12875
12876 as_list = as_list_lookup(filter);
12877 if (as_list == NULL) {
606d49a4 12878 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12879 filter);
12880 return CMD_WARNING;
12881 }
12882
12883 sh_type = bgp_show_type_filter_list;
12884 output_arg = as_list;
12885 }
12886
6deaf579
RW
12887 if (argv_find(argv, argc, "prefix-list", &idx)) {
12888 const char *prefix_list_str = argv[++idx]->arg;
12889 struct prefix_list *plist;
12890
12891 plist = prefix_list_lookup(afi, prefix_list_str);
12892 if (plist == NULL) {
606d49a4 12893 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12894 prefix_list_str);
12895 return CMD_WARNING;
12896 }
12897
12898 sh_type = bgp_show_type_prefix_list;
12899 output_arg = plist;
12900 }
12901
ed126382
DA
12902 if (argv_find(argv, argc, "access-list", &idx)) {
12903 const char *access_list_str = argv[++idx]->arg;
12904 struct access_list *alist;
12905
12906 alist = access_list_lookup(afi, access_list_str);
12907 if (!alist) {
606d49a4 12908 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12909 access_list_str);
12910 return CMD_WARNING;
12911 }
12912
12913 sh_type = bgp_show_type_access_list;
12914 output_arg = alist;
12915 }
12916
bf1a944a
RW
12917 if (argv_find(argv, argc, "route-map", &idx)) {
12918 const char *rmap_str = argv[++idx]->arg;
12919 struct route_map *rmap;
12920
12921 rmap = route_map_lookup_by_name(rmap_str);
12922 if (!rmap) {
606d49a4 12923 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12924 return CMD_WARNING;
12925 }
12926
12927 sh_type = bgp_show_type_route_map;
12928 output_arg = rmap;
12929 }
12930
1e2ce4f1
DS
12931 if (argv_find(argv, argc, "rpki", &idx)) {
12932 sh_type = bgp_show_type_rpki;
12933 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12934 rpki_target_state = RPKI_VALID;
1e2ce4f1 12935 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12936 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12937 }
12938
7d3cae70
DA
12939 /* Display prefixes with matching version numbers */
12940 if (argv_find(argv, argc, "version", &idx)) {
12941 sh_type = bgp_show_type_prefix_version;
2391833e 12942 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12943 }
12944
a70a28a5
DA
12945 /* Display prefixes with matching BGP community alias */
12946 if (argv_find(argv, argc, "alias", &idx)) {
12947 sh_type = bgp_show_type_community_alias;
2391833e 12948 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12949 }
12950
39c3c736
RW
12951 /* prefix-longer */
12952 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12953 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12954 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12955
12956 if (!str2prefix(prefix_str, &p)) {
12957 vty_out(vty, "%% Malformed Prefix\n");
12958 return CMD_WARNING;
12959 }
12960
12961 sh_type = bgp_show_type_prefix_longer;
12962 output_arg = &p;
a70a28a5
DA
12963 }
12964
83856649
KQ
12965 /* self originated only */
12966 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12967 sh_type = bgp_show_type_self_originated;
12968
96f3485c
MK
12969 if (!all) {
12970 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12971 if (community)
12972 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12973 exact_match, afi, safi,
12974 show_flags);
2391833e 12975 else
a70a28a5 12976 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12977 output_arg, show_flags,
a70a28a5 12978 rpki_target_state);
96f3485c 12979 } else {
fa5ac378
DA
12980 struct listnode *node;
12981 struct bgp *abgp;
96f3485c
MK
12982 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12983 * AFI_IP6 */
12984
12985 if (uj)
12986 vty_out(vty, "{\n");
12987
12988 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12989 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12990 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12991 ? AFI_IP
12992 : AFI_IP6;
fa5ac378
DA
12993 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12994 FOREACH_SAFI (safi) {
12995 if (!bgp_afi_safi_peer_exists(abgp, afi,
12996 safi))
12997 continue;
96f3485c 12998
fa5ac378
DA
12999 if (uj) {
13000 if (first)
13001 first = false;
13002 else
13003 vty_out(vty, ",\n");
13004 vty_out(vty, "\"%s\":{\n",
13005 get_afi_safi_str(afi,
13006 safi,
13007 true));
13008 } else
13009 vty_out(vty,
13010 "\nFor address family: %s\n",
13011 get_afi_safi_str(
13012 afi, safi,
13013 false));
13014
13015 if (community)
13016 bgp_show_community(
13017 vty, abgp, community,
13018 exact_match, afi, safi,
13019 show_flags);
96f3485c 13020 else
fa5ac378
DA
13021 bgp_show(vty, abgp, afi, safi,
13022 sh_type, output_arg,
13023 show_flags,
13024 rpki_target_state);
13025 if (uj)
13026 vty_out(vty, "}\n");
13027 }
96f3485c
MK
13028 }
13029 } else {
13030 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
13031 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13032 FOREACH_AFI_SAFI (afi, safi) {
13033 if (!bgp_afi_safi_peer_exists(abgp, afi,
13034 safi))
13035 continue;
96f3485c 13036
fa5ac378
DA
13037 if (uj) {
13038 if (first)
13039 first = false;
13040 else
13041 vty_out(vty, ",\n");
13042
13043 vty_out(vty, "\"%s\":{\n",
13044 get_afi_safi_str(afi,
13045 safi,
13046 true));
13047 } else
13048 vty_out(vty,
13049 "\nFor address family: %s\n",
13050 get_afi_safi_str(
13051 afi, safi,
13052 false));
13053
13054 if (community)
13055 bgp_show_community(
13056 vty, abgp, community,
13057 exact_match, afi, safi,
13058 show_flags);
96f3485c 13059 else
fa5ac378
DA
13060 bgp_show(vty, abgp, afi, safi,
13061 sh_type, output_arg,
13062 show_flags,
13063 rpki_target_state);
13064 if (uj)
13065 vty_out(vty, "}\n");
13066 }
96f3485c
MK
13067 }
13068 }
13069 if (uj)
13070 vty_out(vty, "}\n");
13071 }
13072 return CMD_SUCCESS;
a636c635 13073}
47fc97cc 13074
718e3744 13075DEFUN (show_ip_bgp_route,
13076 show_ip_bgp_route_cmd,
8aa22bbb 13077 "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 13078 SHOW_STR
13079 IP_STR
13080 BGP_STR
a636c635 13081 BGP_INSTANCE_HELP_STR
4f280b15 13082 BGP_AFI_HELP_STR
4dd6177e 13083 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13084 "Network in the BGP routing table to display\n"
0c7b1b01 13085 "IPv4 prefix\n"
8c3deaae 13086 "Network in the BGP routing table to display\n"
0c7b1b01 13087 "IPv6 prefix\n"
4092b06c 13088 "Display only the bestpath\n"
b05a1c8b 13089 "Display only multipaths\n"
8aa22bbb
DS
13090 "Display only paths that match the specified rpki state\n"
13091 "A valid path as determined by rpki\n"
13092 "A invalid path as determined by rpki\n"
13093 "A path that has no rpki data\n"
9973d184 13094 JSON_STR)
4092b06c 13095{
d62a17ae 13096 int prefix_check = 0;
ae19d7dd 13097
d62a17ae 13098 afi_t afi = AFI_IP6;
13099 safi_t safi = SAFI_UNICAST;
13100 char *prefix = NULL;
13101 struct bgp *bgp = NULL;
13102 enum bgp_path_type path_type;
9f049418 13103 bool uj = use_json(argc, argv);
b05a1c8b 13104
d62a17ae 13105 int idx = 0;
ae19d7dd 13106
d62a17ae 13107 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13108 &bgp, uj);
d62a17ae 13109 if (!idx)
13110 return CMD_WARNING;
c41247f5 13111
d62a17ae 13112 if (!bgp) {
13113 vty_out(vty,
13114 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13115 return CMD_WARNING;
13116 }
a636c635 13117
d62a17ae 13118 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13119 if (argv_find(argv, argc, "A.B.C.D", &idx)
13120 || argv_find(argv, argc, "X:X::X:X", &idx))
13121 prefix_check = 0;
13122 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13123 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13124 prefix_check = 1;
13125
13126 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13127 && afi != AFI_IP6) {
13128 vty_out(vty,
13129 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13130 return CMD_WARNING;
13131 }
13132 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13133 && afi != AFI_IP) {
13134 vty_out(vty,
13135 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13136 return CMD_WARNING;
13137 }
13138
13139 prefix = argv[idx]->arg;
13140
13141 /* [<bestpath|multipath>] */
13142 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13143 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13144 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13145 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13146 else
360660c6 13147 path_type = BGP_PATH_SHOW_ALL;
a636c635 13148
d62a17ae 13149 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13150 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13151}
13152
8c3deaae
QY
13153DEFUN (show_ip_bgp_regexp,
13154 show_ip_bgp_regexp_cmd,
3e5b31b3 13155 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13156 SHOW_STR
13157 IP_STR
13158 BGP_STR
b00b230a 13159 BGP_INSTANCE_HELP_STR
4f280b15 13160 BGP_AFI_HELP_STR
4dd6177e 13161 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13162 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13163 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13164 JSON_STR)
8c3deaae 13165{
d62a17ae 13166 afi_t afi = AFI_IP6;
13167 safi_t safi = SAFI_UNICAST;
13168 struct bgp *bgp = NULL;
3e5b31b3
DA
13169 bool uj = use_json(argc, argv);
13170 char *regstr = NULL;
8c3deaae 13171
d62a17ae 13172 int idx = 0;
13173 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13174 &bgp, false);
d62a17ae 13175 if (!idx)
13176 return CMD_WARNING;
8c3deaae 13177
d62a17ae 13178 // get index of regex
3e5b31b3
DA
13179 if (argv_find(argv, argc, "REGEX", &idx))
13180 regstr = argv[idx]->arg;
8c3deaae 13181
5f71d11c 13182 assert(regstr);
3e5b31b3
DA
13183 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13184 bgp_show_type_regexp, uj);
8c3deaae
QY
13185}
13186
ae248832 13187DEFPY (show_ip_bgp_instance_all,
a636c635 13188 show_ip_bgp_instance_all_cmd,
ae248832 13189 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13190 SHOW_STR
a636c635 13191 IP_STR
4092b06c 13192 BGP_STR
a636c635 13193 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13194 BGP_AFI_HELP_STR
4dd6177e 13195 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13196 JSON_STR
13197 "Increase table width for longer prefixes\n")
4092b06c 13198{
54d05dea 13199 afi_t afi = AFI_IP6;
d62a17ae 13200 safi_t safi = SAFI_UNICAST;
13201 struct bgp *bgp = NULL;
d62a17ae 13202 int idx = 0;
96c81f66 13203 uint16_t show_flags = 0;
ae19d7dd 13204
96f3485c 13205 if (uj) {
d62a17ae 13206 argc--;
96f3485c
MK
13207 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13208 }
13209
13210 if (wide)
13211 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13212
9f049418
DS
13213 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13214 &bgp, uj);
13215 if (!idx)
13216 return CMD_WARNING;
13217
96f3485c 13218 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13219 return CMD_SUCCESS;
e3e29b32
LB
13220}
13221
a4d82a8a 13222static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13223 afi_t afi, safi_t safi, enum bgp_show_type type,
13224 bool use_json)
718e3744 13225{
d62a17ae 13226 regex_t *regex;
13227 int rc;
96c81f66 13228 uint16_t show_flags = 0;
96f3485c
MK
13229
13230 if (use_json)
13231 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13232
c3900853 13233 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13234 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13235 regstr);
13236 return CMD_WARNING_CONFIG_FAILED;
13237 }
13238
d62a17ae 13239 regex = bgp_regcomp(regstr);
13240 if (!regex) {
13241 vty_out(vty, "Can't compile regexp %s\n", regstr);
13242 return CMD_WARNING;
13243 }
a636c635 13244
1e2ce4f1
DS
13245 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13246 RPKI_NOT_BEING_USED);
d62a17ae 13247 bgp_regex_free(regex);
13248 return rc;
e3e29b32
LB
13249}
13250
7f323236
DW
13251static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13252 const char *comstr, int exact, afi_t afi,
96c81f66 13253 safi_t safi, uint16_t show_flags)
d62a17ae 13254{
13255 struct community *com;
d62a17ae 13256 int ret = 0;
13257
7f323236 13258 com = community_str2com(comstr);
d62a17ae 13259 if (!com) {
7f323236 13260 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13261 return CMD_WARNING;
13262 }
13263
13264 ret = bgp_show(vty, bgp, afi, safi,
13265 (exact ? bgp_show_type_community_exact
13266 : bgp_show_type_community),
1e2ce4f1 13267 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13268 community_free(&com);
46c3ce83 13269
d62a17ae 13270 return ret;
718e3744 13271}
13272
d62a17ae 13273enum bgp_stats {
13274 BGP_STATS_MAXBITLEN = 0,
13275 BGP_STATS_RIB,
13276 BGP_STATS_PREFIXES,
13277 BGP_STATS_TOTPLEN,
13278 BGP_STATS_UNAGGREGATEABLE,
13279 BGP_STATS_MAX_AGGREGATEABLE,
13280 BGP_STATS_AGGREGATES,
13281 BGP_STATS_SPACE,
13282 BGP_STATS_ASPATH_COUNT,
13283 BGP_STATS_ASPATH_MAXHOPS,
13284 BGP_STATS_ASPATH_TOTHOPS,
13285 BGP_STATS_ASPATH_MAXSIZE,
13286 BGP_STATS_ASPATH_TOTSIZE,
13287 BGP_STATS_ASN_HIGHEST,
13288 BGP_STATS_MAX,
a636c635 13289};
2815e61f 13290
9ab0cf58 13291#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13292#define TABLE_STATS_IDX_JSON 1
13293
13294static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13295 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13296 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13297 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13298 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13299 "unaggregateablePrefixes"},
13300 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13301 "maximumAggregateablePrefixes"},
13302 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13303 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13304 [BGP_STATS_SPACE] = {"Address space advertised",
13305 "addressSpaceAdvertised"},
9ab0cf58
PG
13306 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13307 "advertisementsWithPaths"},
13308 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13309 "longestAsPath"},
13310 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13311 "largestAsPath"},
13312 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13313 "averageAsPathLengthHops"},
13314 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13315 "averageAsPathSizeBytes"},
13316 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13317 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13318};
2815e61f 13319
d62a17ae 13320struct bgp_table_stats {
13321 struct bgp_table *table;
13322 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13323
13324 unsigned long long
13325 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13326 1];
13327
8d0ab76d 13328 double total_space;
ff7924f6
PJ
13329};
13330
9bcb3eef 13331static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13332 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13333{
9bcb3eef 13334 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13335 struct bgp_path_info *pi;
b54892e0 13336 const struct prefix *rn_p;
d62a17ae 13337
9bcb3eef 13338 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13339 return;
d62a17ae 13340
9bcb3eef 13341 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13342 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13343 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13344
0747643e 13345 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13346 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13347 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13348 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13349
9bcb3eef 13350 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13351 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13352 /* announced address space */
13353 if (space)
b54892e0 13354 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13355 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13356 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13357
9c14ec72 13358
9bcb3eef 13359 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13360 ts->counts[BGP_STATS_RIB]++;
13361
05864da7
DS
13362 if (CHECK_FLAG(pi->attr->flag,
13363 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13364 ts->counts[BGP_STATS_AGGREGATES]++;
13365
13366 /* as-path stats */
05864da7 13367 if (pi->attr->aspath) {
9c14ec72
RW
13368 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13369 unsigned int size = aspath_size(pi->attr->aspath);
13370 as_t highest = aspath_highest(pi->attr->aspath);
13371
13372 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13373
13374 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13375 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13376
13377 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13378 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13379
13380 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13381 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13382 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13383 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13384 }
13385 }
13386}
13387
e6685141 13388static void bgp_table_stats_walker(struct event *t)
9c14ec72 13389{
9bcb3eef
DS
13390 struct bgp_dest *dest, *ndest;
13391 struct bgp_dest *top;
e16d030c 13392 struct bgp_table_stats *ts = EVENT_ARG(t);
9c14ec72
RW
13393 unsigned int space = 0;
13394
13395 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13396 return;
9c14ec72
RW
13397
13398 switch (ts->table->afi) {
13399 case AFI_IP:
13400 space = IPV4_MAX_BITLEN;
13401 break;
13402 case AFI_IP6:
13403 space = IPV6_MAX_BITLEN;
13404 break;
3ba7b4af
TA
13405 case AFI_L2VPN:
13406 space = EVPN_ROUTE_PREFIXLEN;
13407 break;
58cf0823
DS
13408 case AFI_UNSPEC:
13409 case AFI_MAX:
cc9f21da 13410 return;
9c14ec72
RW
13411 }
13412
13413 ts->counts[BGP_STATS_MAXBITLEN] = space;
13414
9bcb3eef 13415 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13416 if (ts->table->safi == SAFI_MPLS_VPN
13417 || ts->table->safi == SAFI_ENCAP
13418 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13419 struct bgp_table *table;
13420
9bcb3eef 13421 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13422 if (!table)
13423 continue;
13424
13425 top = bgp_table_top(table);
9bcb3eef
DS
13426 for (ndest = bgp_table_top(table); ndest;
13427 ndest = bgp_route_next(ndest))
13428 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13429 } else {
9bcb3eef 13430 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13431 }
13432 }
2815e61f 13433}
ff7924f6 13434
71f1613a
DA
13435static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13436 struct json_object *json_array)
13437{
13438 struct listnode *node, *nnode;
13439 struct bgp *bgp;
13440
13441 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13442 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13443}
13444
13445static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13446 safi_t safi, struct json_object *json_array)
2815e61f 13447{
d62a17ae 13448 struct bgp_table_stats ts;
13449 unsigned int i;
893cccd0
PG
13450 int ret = CMD_SUCCESS;
13451 char temp_buf[20];
6c9d22e2 13452 struct json_object *json = NULL;
0747643e
AQ
13453 uint32_t bitlen = 0;
13454 struct json_object *json_bitlen;
6c9d22e2
PG
13455
13456 if (json_array)
13457 json = json_object_new_object();
019386c2 13458
d62a17ae 13459 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13460 char warning_msg[50];
13461
13462 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13463 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13464 safi);
6c9d22e2
PG
13465
13466 if (!json)
893cccd0
PG
13467 vty_out(vty, "%s\n", warning_msg);
13468 else
9ab0cf58 13469 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13470
893cccd0
PG
13471 ret = CMD_WARNING;
13472 goto end_table_stats;
d62a17ae 13473 }
019386c2 13474
893cccd0 13475 if (!json)
5290ceab
DA
13476 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13477 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13478 else
13479 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13480
d62a17ae 13481 /* labeled-unicast routes live in the unicast table */
13482 if (safi == SAFI_LABELED_UNICAST)
13483 safi = SAFI_UNICAST;
019386c2 13484
d62a17ae 13485 memset(&ts, 0, sizeof(ts));
13486 ts.table = bgp->rib[afi][safi];
8c1186d3 13487 event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13488
d62a17ae 13489 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13490 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13491 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13492 continue;
13493
13494 switch (i) {
d62a17ae 13495 case BGP_STATS_ASPATH_TOTHOPS:
13496 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13497 if (!json) {
9ab0cf58
PG
13498 snprintf(
13499 temp_buf, sizeof(temp_buf), "%12.2f",
13500 ts.counts[i]
13501 ? (float)ts.counts[i]
13502 / (float)ts.counts
13503 [BGP_STATS_ASPATH_COUNT]
13504 : 0);
893cccd0 13505 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13506 table_stats_strs[i]
13507 [TABLE_STATS_IDX_VTY],
893cccd0 13508 temp_buf);
9ab0cf58
PG
13509 } else {
13510 json_object_double_add(
13511 json,
13512 table_stats_strs[i]
13513 [TABLE_STATS_IDX_JSON],
13514 ts.counts[i]
13515 ? (double)ts.counts[i]
13516 / (double)ts.counts
d62a17ae 13517 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13518 : 0);
13519 }
d62a17ae 13520 break;
13521 case BGP_STATS_TOTPLEN:
6c9d22e2 13522 if (!json) {
9ab0cf58
PG
13523 snprintf(
13524 temp_buf, sizeof(temp_buf), "%12.2f",
13525 ts.counts[i]
13526 ? (float)ts.counts[i]
13527 / (float)ts.counts
13528 [BGP_STATS_PREFIXES]
13529 : 0);
893cccd0 13530 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13531 table_stats_strs[i]
13532 [TABLE_STATS_IDX_VTY],
893cccd0 13533 temp_buf);
9ab0cf58
PG
13534 } else {
13535 json_object_double_add(
13536 json,
13537 table_stats_strs[i]
13538 [TABLE_STATS_IDX_JSON],
13539 ts.counts[i]
13540 ? (double)ts.counts[i]
13541 / (double)ts.counts
d62a17ae 13542 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13543 : 0);
13544 }
d62a17ae 13545 break;
13546 case BGP_STATS_SPACE:
6c9d22e2
PG
13547 if (!json) {
13548 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13549 ts.total_space);
893cccd0 13550 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13551 table_stats_strs[i]
13552 [TABLE_STATS_IDX_VTY],
893cccd0 13553 temp_buf);
9ab0cf58
PG
13554 } else {
13555 json_object_double_add(
13556 json,
13557 table_stats_strs[i]
13558 [TABLE_STATS_IDX_JSON],
13559 (double)ts.total_space);
13560 }
8d0ab76d 13561 if (afi == AFI_IP6) {
6c9d22e2
PG
13562 if (!json) {
13563 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13564 "%12g",
13565 ts.total_space
13566 * pow(2.0, -128 + 32));
6c9d22e2
PG
13567 vty_out(vty, "%30s: %s\n",
13568 "/32 equivalent %s\n",
13569 temp_buf);
9ab0cf58
PG
13570 } else {
13571 json_object_double_add(
13572 json, "/32equivalent",
13573 (double)(ts.total_space
13574 * pow(2.0,
13575 -128 + 32)));
13576 }
6c9d22e2
PG
13577 if (!json) {
13578 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13579 "%12g",
13580 ts.total_space
13581 * pow(2.0, -128 + 48));
6c9d22e2
PG
13582 vty_out(vty, "%30s: %s\n",
13583 "/48 equivalent %s\n",
13584 temp_buf);
9ab0cf58
PG
13585 } else {
13586 json_object_double_add(
13587 json, "/48equivalent",
13588 (double)(ts.total_space
13589 * pow(2.0,
13590 -128 + 48)));
13591 }
8d0ab76d 13592 } else {
6c9d22e2
PG
13593 if (!json) {
13594 snprintf(temp_buf, sizeof(temp_buf),
13595 "%12.2f",
9ab0cf58
PG
13596 ts.total_space * 100.
13597 * pow(2.0, -32));
6c9d22e2 13598 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13599 "% announced ", temp_buf);
13600 } else {
13601 json_object_double_add(
13602 json, "%announced",
13603 (double)(ts.total_space * 100.
13604 * pow(2.0, -32)));
13605 }
6c9d22e2
PG
13606 if (!json) {
13607 snprintf(temp_buf, sizeof(temp_buf),
13608 "%12.2f",
9ab0cf58
PG
13609 ts.total_space
13610 * pow(2.0, -32 + 8));
6c9d22e2
PG
13611 vty_out(vty, "%30s: %s\n",
13612 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13613 } else {
13614 json_object_double_add(
13615 json, "/8equivalent",
13616 (double)(ts.total_space
13617 * pow(2.0, -32 + 8)));
13618 }
6c9d22e2
PG
13619 if (!json) {
13620 snprintf(temp_buf, sizeof(temp_buf),
13621 "%12.2f",
9ab0cf58
PG
13622 ts.total_space
13623 * pow(2.0, -32 + 24));
6c9d22e2 13624 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13625 "/24 equivalent ", temp_buf);
13626 } else {
13627 json_object_double_add(
13628 json, "/24equivalent",
13629 (double)(ts.total_space
13630 * pow(2.0, -32 + 24)));
13631 }
8d0ab76d 13632 }
d62a17ae 13633 break;
13634 default:
6c9d22e2
PG
13635 if (!json) {
13636 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13637 ts.counts[i]);
893cccd0 13638 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13639 table_stats_strs[i]
13640 [TABLE_STATS_IDX_VTY],
13641 temp_buf);
13642 } else {
13643 json_object_int_add(
13644 json,
13645 table_stats_strs[i]
13646 [TABLE_STATS_IDX_JSON],
13647 ts.counts[i]);
13648 }
d62a17ae 13649 }
893cccd0
PG
13650 if (!json)
13651 vty_out(vty, "\n");
d62a17ae 13652 }
0747643e
AQ
13653
13654 switch (afi) {
13655 case AFI_IP:
13656 bitlen = IPV4_MAX_BITLEN;
13657 break;
13658 case AFI_IP6:
13659 bitlen = IPV6_MAX_BITLEN;
13660 break;
13661 case AFI_L2VPN:
13662 bitlen = EVPN_ROUTE_PREFIXLEN;
13663 break;
58cf0823
DS
13664 case AFI_UNSPEC:
13665 case AFI_MAX:
0747643e
AQ
13666 break;
13667 }
13668
13669 if (json) {
13670 json_bitlen = json_object_new_array();
13671
13672 for (i = 0; i <= bitlen; i++) {
13673 struct json_object *ind_bit = json_object_new_object();
13674
13675 if (!ts.prefix_len_count[i])
13676 continue;
13677
13678 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13679 json_object_int_add(ind_bit, temp_buf,
13680 ts.prefix_len_count[i]);
13681 json_object_array_add(json_bitlen, ind_bit);
13682 }
13683 json_object_object_add(json, "prefixLength", json_bitlen);
13684 }
13685
9ab0cf58 13686end_table_stats:
6c9d22e2
PG
13687 if (json)
13688 json_object_array_add(json_array, json);
893cccd0 13689 return ret;
d62a17ae 13690}
13691
71f1613a
DA
13692static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13693 safi_t safi, struct json_object *json_array)
13694{
13695 if (!bgp) {
13696 bgp_table_stats_all(vty, afi, safi, json_array);
13697 return CMD_SUCCESS;
13698 }
13699
13700 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13701}
13702
d62a17ae 13703enum bgp_pcounts {
13704 PCOUNT_ADJ_IN = 0,
13705 PCOUNT_DAMPED,
13706 PCOUNT_REMOVED,
13707 PCOUNT_HISTORY,
13708 PCOUNT_STALE,
13709 PCOUNT_VALID,
13710 PCOUNT_ALL,
13711 PCOUNT_COUNTED,
7e3d9632 13712 PCOUNT_BPATH_SELECTED,
d62a17ae 13713 PCOUNT_PFCNT, /* the figure we display to users */
13714 PCOUNT_MAX,
a636c635 13715};
718e3744 13716
2b64873d 13717static const char *const pcount_strs[] = {
9d303b37
DL
13718 [PCOUNT_ADJ_IN] = "Adj-in",
13719 [PCOUNT_DAMPED] = "Damped",
13720 [PCOUNT_REMOVED] = "Removed",
13721 [PCOUNT_HISTORY] = "History",
13722 [PCOUNT_STALE] = "Stale",
13723 [PCOUNT_VALID] = "Valid",
13724 [PCOUNT_ALL] = "All RIB",
13725 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13726 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13727 [PCOUNT_PFCNT] = "Useable",
13728 [PCOUNT_MAX] = NULL,
a636c635 13729};
718e3744 13730
d62a17ae 13731struct peer_pcounts {
13732 unsigned int count[PCOUNT_MAX];
13733 const struct peer *peer;
13734 const struct bgp_table *table;
54317cba 13735 safi_t safi;
a636c635 13736};
47fc97cc 13737
9bcb3eef 13738static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13739{
54317cba
JW
13740 const struct bgp_adj_in *ain;
13741 const struct bgp_path_info *pi;
d62a17ae 13742 const struct peer *peer = pc->peer;
13743
54317cba
JW
13744 for (ain = rn->adj_in; ain; ain = ain->next)
13745 if (ain->peer == peer)
13746 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13747
9bcb3eef 13748 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13749
54317cba
JW
13750 if (pi->peer != peer)
13751 continue;
d62a17ae 13752
54317cba 13753 pc->count[PCOUNT_ALL]++;
d62a17ae 13754
54317cba
JW
13755 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13756 pc->count[PCOUNT_DAMPED]++;
13757 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13758 pc->count[PCOUNT_HISTORY]++;
13759 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13760 pc->count[PCOUNT_REMOVED]++;
13761 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13762 pc->count[PCOUNT_STALE]++;
13763 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13764 pc->count[PCOUNT_VALID]++;
13765 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13766 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13767 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13768 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13769
13770 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13771 pc->count[PCOUNT_COUNTED]++;
13772 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13773 flog_err(
13774 EC_LIB_DEVELOPMENT,
13775 "Attempting to count but flags say it is unusable");
13776 } else {
40381db7 13777 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13778 flog_err(
13779 EC_LIB_DEVELOPMENT,
13780 "Not counted but flags say we should");
d62a17ae 13781 }
13782 }
54317cba
JW
13783}
13784
e6685141 13785static void bgp_peer_count_walker(struct event *t)
54317cba 13786{
9bcb3eef 13787 struct bgp_dest *rn, *rm;
54317cba 13788 const struct bgp_table *table;
e16d030c 13789 struct peer_pcounts *pc = EVENT_ARG(t);
54317cba
JW
13790
13791 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13792 || pc->safi == SAFI_EVPN) {
13793 /* Special handling for 2-level routing tables. */
13794 for (rn = bgp_table_top(pc->table); rn;
13795 rn = bgp_route_next(rn)) {
9bcb3eef 13796 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13797 if (table != NULL)
13798 for (rm = bgp_table_top(table); rm;
13799 rm = bgp_route_next(rm))
13800 bgp_peer_count_proc(rm, pc);
13801 }
13802 } else
13803 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13804 bgp_peer_count_proc(rn, pc);
718e3744 13805}
13806
d62a17ae 13807static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13808 safi_t safi, bool use_json)
856ca177 13809{
d62a17ae 13810 struct peer_pcounts pcounts = {.peer = peer};
13811 unsigned int i;
13812 json_object *json = NULL;
13813 json_object *json_loop = NULL;
856ca177 13814
d62a17ae 13815 if (use_json) {
13816 json = json_object_new_object();
13817 json_loop = json_object_new_object();
13818 }
718e3744 13819
d62a17ae 13820 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13821 || !peer->bgp->rib[afi][safi]) {
13822 if (use_json) {
13823 json_object_string_add(
13824 json, "warning",
13825 "No such neighbor or address family");
13826 vty_out(vty, "%s\n", json_object_to_json_string(json));
13827 json_object_free(json);
d5f20468 13828 json_object_free(json_loop);
d62a17ae 13829 } else
13830 vty_out(vty, "%% No such neighbor or address family\n");
13831
13832 return CMD_WARNING;
13833 }
2a71e9ce 13834
d62a17ae 13835 memset(&pcounts, 0, sizeof(pcounts));
13836 pcounts.peer = peer;
13837 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13838 pcounts.safi = safi;
d62a17ae 13839
13840 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13841 * stats for the thread-walk (i.e. ensure this can't be blamed on
13842 * on just vty_read()).
13843 */
8c1186d3 13844 event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
d62a17ae 13845
13846 if (use_json) {
13847 json_object_string_add(json, "prefixCountsFor", peer->host);
13848 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13849 get_afi_safi_str(afi, safi, true));
d62a17ae 13850 json_object_int_add(json, "pfxCounter",
13851 peer->pcount[afi][safi]);
13852
13853 for (i = 0; i < PCOUNT_MAX; i++)
13854 json_object_int_add(json_loop, pcount_strs[i],
13855 pcounts.count[i]);
13856
13857 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13858
13859 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13860 json_object_string_add(json, "pfxctDriftFor",
13861 peer->host);
13862 json_object_string_add(
13863 json, "recommended",
13864 "Please report this bug, with the above command output");
13865 }
75eeda93 13866 vty_json(vty, json);
d62a17ae 13867 } else {
13868
13869 if (peer->hostname
892fedb6 13870 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13871 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13872 peer->hostname, peer->host,
5cb5f4d0 13873 get_afi_safi_str(afi, safi, false));
d62a17ae 13874 } else {
13875 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13876 get_afi_safi_str(afi, safi, false));
d62a17ae 13877 }
13878
6cde4b45 13879 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13880 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13881
13882 for (i = 0; i < PCOUNT_MAX; i++)
13883 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13884 pcounts.count[i]);
13885
13886 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13887 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13888 vty_out(vty,
13889 "Please report this bug, with the above command output\n");
13890 }
13891 }
13892
13893 return CMD_SUCCESS;
718e3744 13894}
13895
a636c635
DW
13896DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13897 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13898 "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 13899 SHOW_STR
13900 IP_STR
13901 BGP_STR
8386ac43 13902 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13903 BGP_AFI_HELP_STR
13904 BGP_SAFI_HELP_STR
0b16f239
DS
13905 "Detailed information on TCP and BGP neighbor connections\n"
13906 "Neighbor to display information about\n"
13907 "Neighbor to display information about\n"
91d37724 13908 "Neighbor on BGP configured interface\n"
a636c635 13909 "Display detailed prefix count information\n"
9973d184 13910 JSON_STR)
0b16f239 13911{
d62a17ae 13912 afi_t afi = AFI_IP6;
13913 safi_t safi = SAFI_UNICAST;
13914 struct peer *peer;
13915 int idx = 0;
13916 struct bgp *bgp = NULL;
9f049418
DS
13917 bool uj = use_json(argc, argv);
13918
13919 if (uj)
13920 argc--;
856ca177 13921
d62a17ae 13922 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13923 &bgp, uj);
d62a17ae 13924 if (!idx)
13925 return CMD_WARNING;
0b16f239 13926
d62a17ae 13927 argv_find(argv, argc, "neighbors", &idx);
13928 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13929 if (!peer)
13930 return CMD_WARNING;
bb46e94f 13931
29c8d9da 13932 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13933}
0b16f239 13934
d6902373
PG
13935#ifdef KEEP_OLD_VPN_COMMANDS
13936DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13937 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13938 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13939 SHOW_STR
13940 IP_STR
13941 BGP_STR
d6902373 13942 BGP_VPNVX_HELP_STR
91d37724 13943 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13944 "Detailed information on TCP and BGP neighbor connections\n"
13945 "Neighbor to display information about\n"
13946 "Neighbor to display information about\n"
91d37724 13947 "Neighbor on BGP configured interface\n"
a636c635 13948 "Display detailed prefix count information\n"
9973d184 13949 JSON_STR)
a636c635 13950{
d62a17ae 13951 int idx_peer = 6;
13952 struct peer *peer;
9f049418 13953 bool uj = use_json(argc, argv);
a636c635 13954
d62a17ae 13955 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13956 if (!peer)
13957 return CMD_WARNING;
13958
13959 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13960}
13961
d6902373
PG
13962DEFUN (show_ip_bgp_vpn_all_route_prefix,
13963 show_ip_bgp_vpn_all_route_prefix_cmd,
13964 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13965 SHOW_STR
13966 IP_STR
13967 BGP_STR
d6902373 13968 BGP_VPNVX_HELP_STR
91d37724
QY
13969 "Display information about all VPNv4 NLRIs\n"
13970 "Network in the BGP routing table to display\n"
3a2d747c 13971 "Network in the BGP routing table to display\n"
9973d184 13972 JSON_STR)
91d37724 13973{
d62a17ae 13974 int idx = 0;
13975 char *network = NULL;
13976 struct bgp *bgp = bgp_get_default();
13977 if (!bgp) {
13978 vty_out(vty, "Can't find default instance\n");
13979 return CMD_WARNING;
13980 }
87e34b58 13981
d62a17ae 13982 if (argv_find(argv, argc, "A.B.C.D", &idx))
13983 network = argv[idx]->arg;
13984 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13985 network = argv[idx]->arg;
13986 else {
13987 vty_out(vty, "Unable to figure out Network\n");
13988 return CMD_WARNING;
13989 }
87e34b58 13990
d62a17ae 13991 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13992 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13993 use_json(argc, argv));
91d37724 13994}
d6902373 13995#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13996
44c69747
LK
13997DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13998 show_bgp_l2vpn_evpn_route_prefix_cmd,
13999 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 14000 SHOW_STR
4c63a661
PG
14001 BGP_STR
14002 L2VPN_HELP_STR
14003 EVPN_HELP_STR
44c69747
LK
14004 "Network in the BGP routing table to display\n"
14005 "Network in the BGP routing table to display\n"
4c63a661
PG
14006 "Network in the BGP routing table to display\n"
14007 "Network in the BGP routing table to display\n"
14008 JSON_STR)
14009{
d62a17ae 14010 int idx = 0;
14011 char *network = NULL;
44c69747 14012 int prefix_check = 0;
a636c635 14013
44c69747
LK
14014 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
14015 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 14016 network = argv[idx]->arg;
44c69747 14017 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 14018 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 14019 network = argv[idx]->arg;
44c69747
LK
14020 prefix_check = 1;
14021 } else {
d62a17ae 14022 vty_out(vty, "Unable to figure out Network\n");
14023 return CMD_WARNING;
14024 }
44c69747
LK
14025 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
14026 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 14027 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 14028}
14029
114fc229 14030static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
14031 struct bgp_table *table, int *header1,
14032 int *header2, json_object *json,
14033 json_object *json_scode,
e960b4ca
TA
14034 json_object *json_ocode, bool wide,
14035 bool detail)
2f9bc755
DS
14036{
14037 uint64_t version = table ? table->version : 0;
14038
14039 if (*header1) {
14040 if (json) {
14041 json_object_int_add(json, "bgpTableVersion", version);
c949c771 14042 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 14043 "%pI4", &peer->bgp->router_id);
2f9bc755 14044 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
14045 peer->bgp->default_local_pref);
14046 json_object_int_add(json, "localAS",
14047 peer->change_local_as
14048 ? peer->change_local_as
14049 : peer->local_as);
2f9bc755
DS
14050 json_object_object_add(json, "bgpStatusCodes",
14051 json_scode);
14052 json_object_object_add(json, "bgpOriginCodes",
14053 json_ocode);
14054 } else {
14055 vty_out(vty,
23d0a753
DA
14056 "BGP table version is %" PRIu64
14057 ", local router ID is %pI4, vrf id ",
114fc229
DA
14058 version, &peer->bgp->router_id);
14059 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14060 vty_out(vty, "%s", VRFID_NONE_STR);
14061 else
114fc229 14062 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14063 vty_out(vty, "\n");
14064 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14065 peer->bgp->default_local_pref);
14066 vty_out(vty, "local AS %u\n",
14067 peer->change_local_as ? peer->change_local_as
14068 : peer->local_as);
e960b4ca
TA
14069 if (!detail) {
14070 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14071 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14072 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14073 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14074 }
2f9bc755
DS
14075 }
14076 *header1 = 0;
14077 }
14078 if (*header2) {
e960b4ca 14079 if (!json && !detail)
2f9bc755
DS
14080 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14081 : BGP_SHOW_HEADER));
14082 *header2 = 0;
14083 }
14084}
14085
d9478df0
TA
14086static void
14087show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14088 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14089 const char *rmap_name, json_object *json, json_object *json_ar,
14090 json_object *json_scode, json_object *json_ocode,
96c81f66 14091 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14092 const struct prefix *match, unsigned long *output_count,
14093 unsigned long *filtered_count)
d62a17ae 14094{
3880b4ec
TA
14095 struct bgp_adj_in *ain = NULL;
14096 struct bgp_adj_out *adj = NULL;
9bcb3eef 14097 struct bgp_dest *dest;
d62a17ae 14098 struct bgp *bgp;
d62a17ae 14099 struct attr attr;
14100 int ret;
14101 struct update_subgroup *subgrp;
3880b4ec 14102 struct peer_af *paf = NULL;
f99def61 14103 bool route_filtered;
e960b4ca 14104 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14105 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14106 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14107 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14108 || (safi == SAFI_EVPN))
14109 ? true
14110 : false;
e960b4ca
TA
14111 int display = 0;
14112 json_object *json_net = NULL;
a636c635 14113
d62a17ae 14114 bgp = peer->bgp;
a636c635 14115
3880b4ec
TA
14116 /* If the user supplied a prefix, look for a matching route instead
14117 * of walking the whole table.
14118 */
14119 if (match) {
14120 dest = bgp_node_match(table, match);
14121 if (!dest) {
14122 if (!use_json)
14123 vty_out(vty, "Network not in table\n");
14124 return;
14125 }
14126
14127 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14128
14129 if (rn_p->prefixlen != match->prefixlen) {
14130 if (!use_json)
14131 vty_out(vty, "Network not in table\n");
14132 bgp_dest_unlock_node(dest);
14133 return;
14134 }
14135
14136 if (type == bgp_show_adj_route_received ||
14137 type == bgp_show_adj_route_filtered) {
14138 for (ain = dest->adj_in; ain; ain = ain->next) {
14139 if (ain->peer == peer) {
14140 attr = *ain->attr;
14141 break;
14142 }
14143 }
14144 /* bail out if if adj_out is empty, or
14145 * if the prefix isn't in this peer's
14146 * adj_in
14147 */
14148 if (!ain || ain->peer != peer) {
14149 if (!use_json)
14150 vty_out(vty, "Network not in table\n");
14151 bgp_dest_unlock_node(dest);
14152 return;
14153 }
14154 } else if (type == bgp_show_adj_route_advertised) {
14155 bool peer_found = false;
14156
14157 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14158 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14159 if (paf->peer == peer && adj->attr) {
14160 attr = *adj->attr;
14161 peer_found = true;
14162 break;
14163 }
14164 }
14165 if (peer_found)
14166 break;
14167 }
14168 /* bail out if if adj_out is empty, or
14169 * if the prefix isn't in this peer's
14170 * adj_out
14171 */
14172 if (!paf || !peer_found) {
14173 if (!use_json)
14174 vty_out(vty, "Network not in table\n");
14175 bgp_dest_unlock_node(dest);
14176 return;
14177 }
14178 }
14179
14180 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14181 rmap_name);
14182
14183 if (ret != RMAP_DENY) {
14184 show_adj_route_header(vty, peer, table, header1,
14185 header2, json, json_scode,
14186 json_ocode, wide, detail);
14187
14188 if (use_json)
14189 json_net = json_object_new_object();
14190
14191 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14192 afi, safi, json_net,
14193 BGP_PATH_SHOW_ALL, &display,
14194 RPKI_NOT_BEING_USED);
14195 if (use_json)
14196 json_object_object_addf(json_ar, json_net,
14197 "%pFX", rn_p);
14198 (*output_count)++;
14199 } else
14200 (*filtered_count)++;
14201
14202 bgp_attr_flush(&attr);
14203 bgp_dest_unlock_node(dest);
14204 return;
14205 }
14206
14207
d62a17ae 14208 subgrp = peer_subgroup(peer, afi, safi);
14209
6392aaa6 14210 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14211 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14212 if (use_json) {
14213 json_object_int_add(json, "bgpTableVersion",
14214 table->version);
c949c771
DA
14215 json_object_string_addf(json, "bgpLocalRouterId",
14216 "%pI4", &bgp->router_id);
01eced22
AD
14217 json_object_int_add(json, "defaultLocPrf",
14218 bgp->default_local_pref);
114fc229
DA
14219 json_object_int_add(json, "localAS",
14220 peer->change_local_as
14221 ? peer->change_local_as
14222 : peer->local_as);
d62a17ae 14223 json_object_object_add(json, "bgpStatusCodes",
14224 json_scode);
14225 json_object_object_add(json, "bgpOriginCodes",
14226 json_ocode);
07d0c4ed
DA
14227 json_object_string_add(
14228 json, "bgpOriginatingDefaultNetwork",
14229 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14230 } else {
23d0a753
DA
14231 vty_out(vty,
14232 "BGP table version is %" PRIu64
14233 ", local router ID is %pI4, vrf id ",
14234 table->version, &bgp->router_id);
9df8b37c
PZ
14235 if (bgp->vrf_id == VRF_UNKNOWN)
14236 vty_out(vty, "%s", VRFID_NONE_STR);
14237 else
14238 vty_out(vty, "%u", bgp->vrf_id);
14239 vty_out(vty, "\n");
01eced22
AD
14240 vty_out(vty, "Default local pref %u, ",
14241 bgp->default_local_pref);
114fc229
DA
14242 vty_out(vty, "local AS %u\n",
14243 peer->change_local_as ? peer->change_local_as
14244 : peer->local_as);
e960b4ca
TA
14245 if (!detail) {
14246 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14247 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14248 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14249 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14250 }
d62a17ae 14251
07d0c4ed
DA
14252 vty_out(vty, "Originating default network %s\n\n",
14253 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14254 }
65565c9a 14255 (*output_count)++;
d9478df0 14256 *header1 = 0;
d62a17ae 14257 }
a636c635 14258
9bcb3eef 14259 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14260 if (type == bgp_show_adj_route_received
14261 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14262 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14263 if (ain->peer != peer)
ea47320b 14264 continue;
6392aaa6 14265
114fc229 14266 show_adj_route_header(vty, peer, table, header1,
d9478df0 14267 header2, json, json_scode,
e960b4ca 14268 json_ocode, wide, detail);
d9478df0
TA
14269
14270 if ((safi == SAFI_MPLS_VPN)
14271 || (safi == SAFI_ENCAP)
14272 || (safi == SAFI_EVPN)) {
14273 if (use_json)
14274 json_object_string_add(
14275 json_ar, "rd", rd_str);
14276 else if (show_rd && rd_str) {
14277 vty_out(vty,
14278 "Route Distinguisher: %s\n",
14279 rd_str);
14280 show_rd = false;
14281 }
14282 }
6392aaa6 14283
6f4f49b2 14284 attr = *ain->attr;
f99def61
AD
14285 route_filtered = false;
14286
14287 /* Filter prefix using distribute list,
14288 * filter list or prefix list
14289 */
b54892e0 14290 const struct prefix *rn_p =
9bcb3eef 14291 bgp_dest_get_prefix(dest);
b54892e0
DS
14292 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14293 safi))
14294 == FILTER_DENY)
f99def61
AD
14295 route_filtered = true;
14296
14297 /* Filter prefix using route-map */
b54892e0
DS
14298 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14299 safi, rmap_name, NULL,
14300 0, NULL);
6392aaa6 14301
13c8e163
AD
14302 if (type == bgp_show_adj_route_filtered &&
14303 !route_filtered && ret != RMAP_DENY) {
d498917e 14304 bgp_attr_flush(&attr);
6392aaa6 14305 continue;
d62a17ae 14306 }
6392aaa6 14307
d9478df0
TA
14308 if (type == bgp_show_adj_route_received
14309 && (route_filtered || ret == RMAP_DENY))
14310 (*filtered_count)++;
6392aaa6 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 */, dest, vty,
14318 bgp, afi, safi, json_net,
14319 BGP_PATH_SHOW_ALL, &display,
14320 RPKI_NOT_BEING_USED);
14321 if (use_json)
14322 json_object_object_addf(
14323 json_ar, json_net,
14324 "%pFX", rn_p);
14325 } else
14326 route_vty_out_tmp(vty, dest, rn_p,
14327 &attr, safi, use_json,
14328 json_ar, wide);
d498917e 14329 bgp_attr_flush(&attr);
d9478df0 14330 (*output_count)++;
d62a17ae 14331 }
6392aaa6 14332 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14333 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14334 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14335 if (paf->peer != peer || !adj->attr)
924c3f6a 14336 continue;
d62a17ae 14337
e960b4ca
TA
14338 show_adj_route_header(
14339 vty, peer, table, header1,
14340 header2, json, json_scode,
14341 json_ocode, wide, detail);
d62a17ae 14342
b54892e0 14343 const struct prefix *rn_p =
9bcb3eef 14344 bgp_dest_get_prefix(dest);
b54892e0 14345
6f4f49b2 14346 attr = *adj->attr;
b755861b 14347 ret = bgp_output_modifier(
b54892e0 14348 peer, rn_p, &attr, afi, safi,
b755861b 14349 rmap_name);
f46d8e1e 14350
b755861b 14351 if (ret != RMAP_DENY) {
d9478df0
TA
14352 if ((safi == SAFI_MPLS_VPN)
14353 || (safi == SAFI_ENCAP)
14354 || (safi == SAFI_EVPN)) {
14355 if (use_json)
14356 json_object_string_add(
14357 json_ar,
14358 "rd",
14359 rd_str);
14360 else if (show_rd
14361 && rd_str) {
14362 vty_out(vty,
14363 "Route Distinguisher: %s\n",
14364 rd_str);
14365 show_rd = false;
14366 }
14367 }
e960b4ca
TA
14368 if (detail) {
14369 if (use_json)
14370 json_net =
14371 json_object_new_object();
14372 bgp_show_path_info(
14373 NULL /* prefix_rd
14374 */
14375 ,
14376 dest, vty, bgp,
14377 afi, safi,
14378 json_net,
14379 BGP_PATH_SHOW_ALL,
14380 &display,
14381 RPKI_NOT_BEING_USED);
14382 if (use_json)
14383 json_object_object_addf(
14384 json_ar,
14385 json_net,
14386 "%pFX",
14387 rn_p);
14388 } else
14389 route_vty_out_tmp(
14390 vty, dest, rn_p,
14391 &attr, safi,
14392 use_json,
14393 json_ar, wide);
d9478df0 14394 (*output_count)++;
b755861b 14395 } else {
d9478df0 14396 (*filtered_count)++;
a2addae8 14397 }
b755861b 14398
d498917e 14399 bgp_attr_flush(&attr);
924c3f6a 14400 }
f20ce998
DS
14401 } else if (type == bgp_show_adj_route_bestpath) {
14402 struct bgp_path_info *pi;
14403
114fc229
DA
14404 show_adj_route_header(vty, peer, table, header1,
14405 header2, json, json_scode,
e960b4ca 14406 json_ocode, wide, detail);
f20ce998 14407
aa9bf57e
TA
14408 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14409
f20ce998
DS
14410 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14411 pi = pi->next) {
14412 if (pi->peer != peer)
14413 continue;
14414
14415 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14416 continue;
14417
aa9bf57e
TA
14418 if (detail) {
14419 if (use_json)
14420 json_net =
14421 json_object_new_object();
14422 bgp_show_path_info(
14423 NULL /* prefix_rd */, dest, vty,
14424 bgp, afi, safi, json_net,
14425 BGP_PATH_SHOW_BESTPATH,
14426 &display, RPKI_NOT_BEING_USED);
14427 if (use_json)
14428 json_object_object_addf(
14429 json_ar, json_net,
14430 "%pFX", rn_p);
14431 } else
14432 route_vty_out_tmp(
14433 vty, dest, rn_p, pi->attr, safi,
14434 use_json, json_ar, wide);
d9478df0 14435 (*output_count)++;
f20ce998 14436 }
d62a17ae 14437 }
14438 }
a636c635 14439}
2a71e9ce 14440
d62a17ae 14441static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14442 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14443 const char *rmap_name, const struct prefix *match,
14444 uint16_t show_flags)
0b16f239 14445{
d9478df0
TA
14446 struct bgp *bgp;
14447 struct bgp_table *table;
d62a17ae 14448 json_object *json = NULL;
d9478df0
TA
14449 json_object *json_scode = NULL;
14450 json_object *json_ocode = NULL;
14451 json_object *json_ar = NULL;
96f3485c 14452 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14453
d9478df0
TA
14454 /* Init BGP headers here so they're only displayed once
14455 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14456 */
14457 int header1 = 1;
14458 int header2 = 1;
14459
14460 /*
14461 * Initialize variables for each RD
14462 * All prefixes under an RD is aggregated within "json_routes"
14463 */
14464 char rd_str[BUFSIZ] = {0};
14465 json_object *json_routes = NULL;
14466
14467
14468 /* For 2-tier tables, prefix counts need to be
14469 * maintained across multiple runs of show_adj_route()
14470 */
14471 unsigned long output_count_per_rd;
14472 unsigned long filtered_count_per_rd;
14473 unsigned long output_count = 0;
14474 unsigned long filtered_count = 0;
14475
14476 if (use_json) {
d62a17ae 14477 json = json_object_new_object();
d9478df0
TA
14478 json_ar = json_object_new_object();
14479 json_scode = json_object_new_object();
14480 json_ocode = json_object_new_object();
dd426a51
DA
14481#if CONFDATE > 20231208
14482CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14483#endif
d9478df0
TA
14484 json_object_string_add(json_scode, "suppressed", "s");
14485 json_object_string_add(json_scode, "damped", "d");
14486 json_object_string_add(json_scode, "history", "h");
14487 json_object_string_add(json_scode, "valid", "*");
14488 json_object_string_add(json_scode, "best", ">");
14489 json_object_string_add(json_scode, "multipath", "=");
14490 json_object_string_add(json_scode, "internal", "i");
14491 json_object_string_add(json_scode, "ribFailure", "r");
14492 json_object_string_add(json_scode, "stale", "S");
14493 json_object_string_add(json_scode, "removed", "R");
14494
dd426a51
DA
14495#if CONFDATE > 20231208
14496CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14497#endif
d9478df0
TA
14498 json_object_string_add(json_ocode, "igp", "i");
14499 json_object_string_add(json_ocode, "egp", "e");
14500 json_object_string_add(json_ocode, "incomplete", "?");
14501 }
0b16f239 14502
d62a17ae 14503 if (!peer || !peer->afc[afi][safi]) {
14504 if (use_json) {
14505 json_object_string_add(
14506 json, "warning",
14507 "No such neighbor or address family");
14508 vty_out(vty, "%s\n", json_object_to_json_string(json));
14509 json_object_free(json);
690c3134
MW
14510 json_object_free(json_ar);
14511 json_object_free(json_scode);
14512 json_object_free(json_ocode);
d62a17ae 14513 } else
14514 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14515
d62a17ae 14516 return CMD_WARNING;
14517 }
14518
6392aaa6
PM
14519 if ((type == bgp_show_adj_route_received
14520 || type == bgp_show_adj_route_filtered)
d62a17ae 14521 && !CHECK_FLAG(peer->af_flags[afi][safi],
14522 PEER_FLAG_SOFT_RECONFIG)) {
14523 if (use_json) {
14524 json_object_string_add(
14525 json, "warning",
14526 "Inbound soft reconfiguration not enabled");
14527 vty_out(vty, "%s\n", json_object_to_json_string(json));
14528 json_object_free(json);
690c3134
MW
14529 json_object_free(json_ar);
14530 json_object_free(json_scode);
14531 json_object_free(json_ocode);
d62a17ae 14532 } else
14533 vty_out(vty,
14534 "%% Inbound soft reconfiguration not enabled\n");
14535
14536 return CMD_WARNING;
14537 }
0b16f239 14538
d9478df0
TA
14539 bgp = peer->bgp;
14540
14541 /* labeled-unicast routes live in the unicast table */
14542 if (safi == SAFI_LABELED_UNICAST)
14543 table = bgp->rib[afi][SAFI_UNICAST];
14544 else
14545 table = bgp->rib[afi][safi];
14546
14547 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14548 || (safi == SAFI_EVPN)) {
14549
14550 struct bgp_dest *dest;
14551
14552 for (dest = bgp_table_top(table); dest;
14553 dest = bgp_route_next(dest)) {
14554 table = bgp_dest_get_bgp_table_info(dest);
14555 if (!table)
14556 continue;
14557
14558 output_count_per_rd = 0;
14559 filtered_count_per_rd = 0;
14560
14561 if (use_json)
14562 json_routes = json_object_new_object();
14563
14564 const struct prefix_rd *prd;
14565 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14566 dest);
14567
4a8cd6ad
PG
14568 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14569 bgp->asnotation);
d9478df0 14570
3880b4ec
TA
14571 show_adj_route(
14572 vty, peer, table, afi, safi, type, rmap_name,
14573 json, json_routes, json_scode, json_ocode,
14574 show_flags, &header1, &header2, rd_str, match,
14575 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14576
14577 /* Don't include an empty RD in the output! */
14578 if (json_routes && (output_count_per_rd > 0))
14579 json_object_object_add(json_ar, rd_str,
14580 json_routes);
14581
14582 output_count += output_count_per_rd;
14583 filtered_count += filtered_count_per_rd;
14584 }
14585 } else
14586 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14587 json, json_ar, json_scode, json_ocode,
3880b4ec 14588 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14589 &output_count, &filtered_count);
14590
14591 if (use_json) {
c1984955
TA
14592 if (type == bgp_show_adj_route_advertised)
14593 json_object_object_add(json, "advertisedRoutes",
14594 json_ar);
14595 else
14596 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14597 json_object_int_add(json, "totalPrefixCounter", output_count);
14598 json_object_int_add(json, "filteredPrefixCounter",
14599 filtered_count);
14600
690c3134
MW
14601 /*
14602 * These fields only give up ownership to `json` when `header1`
14603 * is used (set to zero). See code in `show_adj_route` and
14604 * `show_adj_route_header`.
14605 */
14606 if (header1 == 1) {
d9478df0
TA
14607 json_object_free(json_scode);
14608 json_object_free(json_ocode);
14609 }
14610
75eeda93 14611 vty_json(vty, json);
d9478df0 14612 } else if (output_count > 0) {
3880b4ec 14613 if (!match && filtered_count > 0)
d9478df0
TA
14614 vty_out(vty,
14615 "\nTotal number of prefixes %ld (%ld filtered)\n",
14616 output_count, filtered_count);
14617 else
14618 vty_out(vty, "\nTotal number of prefixes %ld\n",
14619 output_count);
14620 }
0b16f239 14621
d62a17ae 14622 return CMD_SUCCESS;
a636c635 14623}
50ef26d4 14624
f20ce998
DS
14625DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14626 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14627 "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
14628 SHOW_STR
14629 IP_STR
14630 BGP_STR
14631 BGP_INSTANCE_HELP_STR
14632 BGP_AFI_HELP_STR
14633 BGP_SAFI_WITH_LABEL_HELP_STR
14634 "Detailed information on TCP and BGP neighbor connections\n"
14635 "Neighbor to display information about\n"
14636 "Neighbor to display information about\n"
14637 "Neighbor on BGP configured interface\n"
14638 "Display the routes selected by best path\n"
aa9bf57e 14639 "Display detailed version of routes\n"
f20ce998
DS
14640 JSON_STR
14641 "Increase table width for longer prefixes\n")
14642{
14643 afi_t afi = AFI_IP6;
14644 safi_t safi = SAFI_UNICAST;
14645 char *rmap_name = NULL;
14646 char *peerstr = NULL;
14647 struct bgp *bgp = NULL;
14648 struct peer *peer;
14649 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14650 int idx = 0;
96c81f66 14651 uint16_t show_flags = 0;
96f3485c 14652
aa9bf57e
TA
14653 if (detail)
14654 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14655
96f3485c
MK
14656 if (uj)
14657 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14658
14659 if (wide)
14660 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14661
14662 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14663 &bgp, uj);
14664
14665 if (!idx)
14666 return CMD_WARNING;
14667
14668 argv_find(argv, argc, "neighbors", &idx);
14669 peerstr = argv[++idx]->arg;
14670
14671 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14672 if (!peer)
14673 return CMD_WARNING;
14674
3880b4ec 14675 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14676 show_flags);
f20ce998
DS
14677}
14678
e960b4ca
TA
14679DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14680 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14681 "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
14682 SHOW_STR
14683 IP_STR
14684 BGP_STR
14685 BGP_INSTANCE_HELP_STR
14686 BGP_AFI_HELP_STR
14687 BGP_SAFI_WITH_LABEL_HELP_STR
14688 "Display the entries for all address families\n"
14689 "Detailed information on TCP and BGP neighbor connections\n"
14690 "Neighbor to display information about\n"
14691 "Neighbor to display information about\n"
14692 "Neighbor on BGP configured interface\n"
14693 "Display the routes advertised to a BGP neighbor\n"
14694 "Display the received routes from neighbor\n"
14695 "Display the filtered routes received from neighbor\n"
14696 "Route-map to modify the attributes\n"
14697 "Name of the route map\n"
3880b4ec
TA
14698 "IPv4 prefix\n"
14699 "IPv6 prefix\n"
e960b4ca
TA
14700 "Display detailed version of routes\n"
14701 JSON_STR
14702 "Increase table width for longer prefixes\n")
718e3744 14703{
d62a17ae 14704 afi_t afi = AFI_IP6;
14705 safi_t safi = SAFI_UNICAST;
d62a17ae 14706 char *peerstr = NULL;
d62a17ae 14707 struct bgp *bgp = NULL;
14708 struct peer *peer;
6392aaa6 14709 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14710 int idx = 0;
96f3485c 14711 bool first = true;
96c81f66 14712 uint16_t show_flags = 0;
75ce3b14
DA
14713 struct listnode *node;
14714 struct bgp *abgp;
6392aaa6 14715
3880b4ec 14716 if (detail || prefix_str)
e960b4ca
TA
14717 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14718
96f3485c 14719 if (uj) {
d62a17ae 14720 argc--;
96f3485c
MK
14721 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14722 }
14723
14724 if (all) {
14725 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14726 if (argv_find(argv, argc, "ipv4", &idx))
14727 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14728
14729 if (argv_find(argv, argc, "ipv6", &idx))
14730 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14731 }
14732
14733 if (wide)
14734 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14735
9f049418
DS
14736 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14737 &bgp, uj);
14738 if (!idx)
14739 return CMD_WARNING;
14740
d62a17ae 14741 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14742 argv_find(argv, argc, "neighbors", &idx);
14743 peerstr = argv[++idx]->arg;
8c3deaae 14744
d62a17ae 14745 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14746 if (!peer)
14747 return CMD_WARNING;
856ca177 14748
d62a17ae 14749 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14750 type = bgp_show_adj_route_advertised;
14751 else if (argv_find(argv, argc, "received-routes", &idx))
14752 type = bgp_show_adj_route_received;
14753 else if (argv_find(argv, argc, "filtered-routes", &idx))
14754 type = bgp_show_adj_route_filtered;
14755
96f3485c 14756 if (!all)
70dd370f 14757 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14758 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14759 if (uj)
14760 vty_out(vty, "{\n");
14761
14762 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14763 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14764 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14765 : AFI_IP6;
75ce3b14
DA
14766 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14767 FOREACH_SAFI (safi) {
14768 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14769 continue;
96f3485c 14770
75ce3b14
DA
14771 if (uj) {
14772 if (first)
14773 first = false;
14774 else
14775 vty_out(vty, ",\n");
14776 vty_out(vty, "\"%s\":",
14777 get_afi_safi_str(afi, safi,
14778 true));
14779 } else
14780 vty_out(vty,
14781 "\nFor address family: %s\n",
14782 get_afi_safi_str(afi, safi,
14783 false));
96f3485c 14784
75ce3b14 14785 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14786 route_map, prefix, show_flags);
75ce3b14 14787 }
96f3485c
MK
14788 }
14789 } else {
75ce3b14
DA
14790 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14791 FOREACH_AFI_SAFI (afi, safi) {
14792 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14793 continue;
96f3485c 14794
75ce3b14
DA
14795 if (uj) {
14796 if (first)
14797 first = false;
14798 else
14799 vty_out(vty, ",\n");
14800 vty_out(vty, "\"%s\":",
14801 get_afi_safi_str(afi, safi,
14802 true));
14803 } else
14804 vty_out(vty,
14805 "\nFor address family: %s\n",
14806 get_afi_safi_str(afi, safi,
14807 false));
96f3485c 14808
75ce3b14 14809 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14810 route_map, prefix, show_flags);
75ce3b14 14811 }
96f3485c
MK
14812 }
14813 }
14814 if (uj)
14815 vty_out(vty, "}\n");
14816
14817 return CMD_SUCCESS;
95cbbd2a
ML
14818}
14819
718e3744 14820DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14821 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14822 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14823 SHOW_STR
14824 IP_STR
14825 BGP_STR
d3120452 14826 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14827 BGP_AF_STR
14828 BGP_AF_STR
14829 BGP_AF_MODIFIER_STR
718e3744 14830 "Detailed information on TCP and BGP neighbor connections\n"
14831 "Neighbor to display information about\n"
14832 "Neighbor to display information about\n"
91d37724 14833 "Neighbor on BGP configured interface\n"
718e3744 14834 "Display information received from a BGP neighbor\n"
856ca177 14835 "Display the prefixlist filter\n"
9973d184 14836 JSON_STR)
718e3744 14837{
d62a17ae 14838 afi_t afi = AFI_IP6;
14839 safi_t safi = SAFI_UNICAST;
14840 char *peerstr = NULL;
d62a17ae 14841 char name[BUFSIZ];
d62a17ae 14842 struct peer *peer;
d3120452 14843 int count;
d62a17ae 14844 int idx = 0;
d3120452
IR
14845 struct bgp *bgp = NULL;
14846 bool uj = use_json(argc, argv);
14847
14848 if (uj)
14849 argc--;
14850
14851 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14852 &bgp, uj);
14853 if (!idx)
14854 return CMD_WARNING;
d62a17ae 14855
d62a17ae 14856 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14857 argv_find(argv, argc, "neighbors", &idx);
14858 peerstr = argv[++idx]->arg;
14859
d3120452
IR
14860 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14861 if (!peer)
14862 return CMD_WARNING;
718e3744 14863
4ced1a2c 14864 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14865 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14866 if (count) {
14867 if (!uj)
14868 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14869 get_afi_safi_str(afi, safi, false));
d62a17ae 14870 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14871 } else {
14872 if (uj)
14873 vty_out(vty, "{}\n");
14874 else
14875 vty_out(vty, "No functional output\n");
14876 }
718e3744 14877
d62a17ae 14878 return CMD_SUCCESS;
14879}
14880
14881static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14882 afi_t afi, safi_t safi,
9f049418 14883 enum bgp_show_type type, bool use_json)
d62a17ae 14884{
96c81f66 14885 uint16_t show_flags = 0;
96f3485c
MK
14886
14887 if (use_json)
14888 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14889
d62a17ae 14890 if (!peer || !peer->afc[afi][safi]) {
14891 if (use_json) {
14892 json_object *json_no = NULL;
14893 json_no = json_object_new_object();
14894 json_object_string_add(
14895 json_no, "warning",
14896 "No such neighbor or address family");
14897 vty_out(vty, "%s\n",
14898 json_object_to_json_string(json_no));
14899 json_object_free(json_no);
14900 } else
14901 vty_out(vty, "%% No such neighbor or address family\n");
14902 return CMD_WARNING;
14903 }
47fc97cc 14904
7daf25a3
TA
14905 /* labeled-unicast routes live in the unicast table */
14906 if (safi == SAFI_LABELED_UNICAST)
14907 safi = SAFI_UNICAST;
14908
1e2ce4f1
DS
14909 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14910 RPKI_NOT_BEING_USED);
718e3744 14911}
14912
dba3c1d3
PG
14913DEFUN (show_ip_bgp_flowspec_routes_detailed,
14914 show_ip_bgp_flowspec_routes_detailed_cmd,
14915 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14916 SHOW_STR
14917 IP_STR
14918 BGP_STR
14919 BGP_INSTANCE_HELP_STR
14920 BGP_AFI_HELP_STR
14921 "SAFI Flowspec\n"
14922 "Detailed information on flowspec entries\n"
14923 JSON_STR)
14924{
458c1475 14925 afi_t afi = AFI_IP6;
dba3c1d3
PG
14926 safi_t safi = SAFI_UNICAST;
14927 struct bgp *bgp = NULL;
14928 int idx = 0;
9f049418 14929 bool uj = use_json(argc, argv);
81dcd881 14930 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14931
96f3485c 14932 if (uj) {
9f049418 14933 argc--;
96f3485c
MK
14934 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14935 }
dba3c1d3
PG
14936
14937 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14938 &bgp, uj);
dba3c1d3
PG
14939 if (!idx)
14940 return CMD_WARNING;
14941
96f3485c 14942 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14943 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14944}
14945
718e3744 14946DEFUN (show_ip_bgp_neighbor_routes,
14947 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14948 "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 14949 SHOW_STR
14950 IP_STR
14951 BGP_STR
8386ac43 14952 BGP_INSTANCE_HELP_STR
4f280b15 14953 BGP_AFI_HELP_STR
4dd6177e 14954 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14955 "Detailed information on TCP and BGP neighbor connections\n"
14956 "Neighbor to display information about\n"
14957 "Neighbor to display information about\n"
91d37724 14958 "Neighbor on BGP configured interface\n"
2525cf39 14959 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14960 "Display the dampened routes received from neighbor\n"
14961 "Display routes learned from neighbor\n"
9973d184 14962 JSON_STR)
718e3744 14963{
d62a17ae 14964 char *peerstr = NULL;
14965 struct bgp *bgp = NULL;
14966 afi_t afi = AFI_IP6;
14967 safi_t safi = SAFI_UNICAST;
14968 struct peer *peer;
14969 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14970 int idx = 0;
9f049418
DS
14971 bool uj = use_json(argc, argv);
14972
14973 if (uj)
14974 argc--;
bb46e94f 14975
d62a17ae 14976 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14977 &bgp, uj);
d62a17ae 14978 if (!idx)
14979 return CMD_WARNING;
c493f2d8 14980
d62a17ae 14981 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14982 argv_find(argv, argc, "neighbors", &idx);
14983 peerstr = argv[++idx]->arg;
8c3deaae 14984
d62a17ae 14985 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14986 if (!peer)
d62a17ae 14987 return CMD_WARNING;
bb46e94f 14988
d62a17ae 14989 if (argv_find(argv, argc, "flap-statistics", &idx))
14990 sh_type = bgp_show_type_flap_neighbor;
14991 else if (argv_find(argv, argc, "dampened-routes", &idx))
14992 sh_type = bgp_show_type_damp_neighbor;
14993 else if (argv_find(argv, argc, "routes", &idx))
14994 sh_type = bgp_show_type_neighbor;
2525cf39 14995
d62a17ae 14996 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14997}
6b0655a2 14998
734b349e 14999struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 15000
d62a17ae 15001struct bgp_distance {
15002 /* Distance value for the IP source prefix. */
d7c0a89a 15003 uint8_t distance;
718e3744 15004
d62a17ae 15005 /* Name of the access-list to be matched. */
15006 char *access_list;
718e3744 15007};
15008
4f280b15
LB
15009DEFUN (show_bgp_afi_vpn_rd_route,
15010 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 15011 "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
15012 SHOW_STR
15013 BGP_STR
15014 BGP_AFI_HELP_STR
00e6edb9 15015 BGP_AF_MODIFIER_STR
4f280b15
LB
15016 "Display information for a route distinguisher\n"
15017 "Route Distinguisher\n"
a111dd97 15018 "All Route Distinguishers\n"
7395a2c9
DS
15019 "Network in the BGP routing table to display\n"
15020 "Network in the BGP routing table to display\n"
15021 JSON_STR)
4f280b15 15022{
d62a17ae 15023 int ret;
15024 struct prefix_rd prd;
15025 afi_t afi = AFI_MAX;
15026 int idx = 0;
4f280b15 15027
ff6566f3
DS
15028 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
15029 vty_out(vty, "%% Malformed Address Family\n");
15030 return CMD_WARNING;
15031 }
15032
a111dd97
TA
15033 if (!strcmp(argv[5]->arg, "all"))
15034 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
15035 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
15036 RPKI_NOT_BEING_USED,
15037 use_json(argc, argv));
15038
d62a17ae 15039 ret = str2prefix_rd(argv[5]->arg, &prd);
15040 if (!ret) {
15041 vty_out(vty, "%% Malformed Route Distinguisher\n");
15042 return CMD_WARNING;
15043 }
ff6566f3 15044
d62a17ae 15045 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
15046 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15047 use_json(argc, argv));
4f280b15
LB
15048}
15049
d62a17ae 15050static struct bgp_distance *bgp_distance_new(void)
718e3744 15051{
d62a17ae 15052 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 15053}
15054
d62a17ae 15055static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15056{
d62a17ae 15057 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15058}
15059
585f1adc
IR
15060static int bgp_distance_set(struct vty *vty, const char *distance_str,
15061 const char *ip_str, const char *access_list_str)
718e3744 15062{
d62a17ae 15063 int ret;
585f1adc
IR
15064 afi_t afi;
15065 safi_t safi;
d62a17ae 15066 struct prefix p;
585f1adc 15067 uint8_t distance;
9bcb3eef 15068 struct bgp_dest *dest;
d62a17ae 15069 struct bgp_distance *bdistance;
718e3744 15070
585f1adc
IR
15071 afi = bgp_node_afi(vty);
15072 safi = bgp_node_safi(vty);
15073
d62a17ae 15074 ret = str2prefix(ip_str, &p);
15075 if (ret == 0) {
585f1adc 15076 vty_out(vty, "Malformed prefix\n");
d62a17ae 15077 return CMD_WARNING_CONFIG_FAILED;
15078 }
718e3744 15079
585f1adc
IR
15080 distance = atoi(distance_str);
15081
d62a17ae 15082 /* Get BGP distance node. */
9bcb3eef
DS
15083 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15084 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15085 if (bdistance)
9bcb3eef 15086 bgp_dest_unlock_node(dest);
ca2e160d 15087 else {
d62a17ae 15088 bdistance = bgp_distance_new();
9bcb3eef 15089 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15090 }
718e3744 15091
d62a17ae 15092 /* Set distance value. */
15093 bdistance->distance = distance;
718e3744 15094
d62a17ae 15095 /* Reset access-list configuration. */
e1b36e13 15096 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15097 if (access_list_str)
15098 bdistance->access_list =
15099 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15100
d62a17ae 15101 return CMD_SUCCESS;
718e3744 15102}
15103
585f1adc
IR
15104static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15105 const char *ip_str, const char *access_list_str)
718e3744 15106{
d62a17ae 15107 int ret;
585f1adc
IR
15108 afi_t afi;
15109 safi_t safi;
d62a17ae 15110 struct prefix p;
585f1adc 15111 int distance;
9bcb3eef 15112 struct bgp_dest *dest;
d62a17ae 15113 struct bgp_distance *bdistance;
718e3744 15114
585f1adc
IR
15115 afi = bgp_node_afi(vty);
15116 safi = bgp_node_safi(vty);
15117
d62a17ae 15118 ret = str2prefix(ip_str, &p);
15119 if (ret == 0) {
585f1adc 15120 vty_out(vty, "Malformed prefix\n");
d62a17ae 15121 return CMD_WARNING_CONFIG_FAILED;
15122 }
718e3744 15123
9bcb3eef
DS
15124 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15125 if (!dest) {
585f1adc 15126 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15127 return CMD_WARNING_CONFIG_FAILED;
15128 }
718e3744 15129
9bcb3eef 15130 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15131 distance = atoi(distance_str);
1f9a9fff 15132
d62a17ae 15133 if (bdistance->distance != distance) {
585f1adc 15134 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15135 bgp_dest_unlock_node(dest);
d62a17ae 15136 return CMD_WARNING_CONFIG_FAILED;
15137 }
718e3744 15138
0a22ddfb 15139 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15140 bgp_distance_free(bdistance);
718e3744 15141
9bcb3eef
DS
15142 bgp_dest_set_bgp_path_info(dest, NULL);
15143 bgp_dest_unlock_node(dest);
15144 bgp_dest_unlock_node(dest);
718e3744 15145
d62a17ae 15146 return CMD_SUCCESS;
718e3744 15147}
15148
718e3744 15149/* Apply BGP information to distance method. */
b8685f9b 15150uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15151 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15152{
9bcb3eef 15153 struct bgp_dest *dest;
801bb996 15154 struct prefix q = {0};
d62a17ae 15155 struct peer *peer;
15156 struct bgp_distance *bdistance;
15157 struct access_list *alist;
15158 struct bgp_static *bgp_static;
a04f1c42 15159 struct bgp_path_info *bpi_ultimate;
d62a17ae 15160
15161 if (!bgp)
15162 return 0;
15163
40381db7 15164 peer = pinfo->peer;
d62a17ae 15165
7b7d48e5
DS
15166 if (pinfo->attr->distance)
15167 return pinfo->attr->distance;
15168
a04f1c42
PG
15169 /* get peer origin to calculate appropriate distance */
15170 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15171 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15172 peer = bpi_ultimate->peer;
15173 }
15174
801bb996
CS
15175 /* Check source address.
15176 * Note: for aggregate route, peer can have unspec af type.
15177 */
15178 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15179 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15180 return 0;
15181
9bcb3eef
DS
15182 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15183 if (dest) {
15184 bdistance = bgp_dest_get_bgp_distance_info(dest);
15185 bgp_dest_unlock_node(dest);
d62a17ae 15186
15187 if (bdistance->access_list) {
15188 alist = access_list_lookup(afi, bdistance->access_list);
15189 if (alist
15190 && access_list_apply(alist, p) == FILTER_PERMIT)
15191 return bdistance->distance;
15192 } else
15193 return bdistance->distance;
718e3744 15194 }
718e3744 15195
d62a17ae 15196 /* Backdoor check. */
9bcb3eef
DS
15197 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15198 if (dest) {
15199 bgp_static = bgp_dest_get_bgp_static_info(dest);
15200 bgp_dest_unlock_node(dest);
718e3744 15201
d62a17ae 15202 if (bgp_static->backdoor) {
15203 if (bgp->distance_local[afi][safi])
15204 return bgp->distance_local[afi][safi];
15205 else
15206 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15207 }
718e3744 15208 }
718e3744 15209
d62a17ae 15210 if (peer->sort == BGP_PEER_EBGP) {
15211 if (bgp->distance_ebgp[afi][safi])
15212 return bgp->distance_ebgp[afi][safi];
15213 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15214 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15215 if (bgp->distance_ibgp[afi][safi])
15216 return bgp->distance_ibgp[afi][safi];
15217 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15218 } else {
15219 if (bgp->distance_local[afi][safi])
15220 return bgp->distance_local[afi][safi];
15221 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15222 }
718e3744 15223}
15224
a612fb77
DA
15225/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15226 * we should tell ZEBRA update the routes for a specific
15227 * AFI/SAFI to reflect changes in RIB.
15228 */
585f1adc
IR
15229static void bgp_announce_routes_distance_update(struct bgp *bgp,
15230 afi_t update_afi,
15231 safi_t update_safi)
a612fb77
DA
15232{
15233 afi_t afi;
15234 safi_t safi;
15235
15236 FOREACH_AFI_SAFI (afi, safi) {
15237 if (!bgp_fibupd_safi(safi))
15238 continue;
15239
8b54bc30
DA
15240 if (afi != update_afi && safi != update_safi)
15241 continue;
15242
15243 if (BGP_DEBUG(zebra, ZEBRA))
15244 zlog_debug(
15245 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15246 __func__, afi, safi);
15247 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15248 }
15249}
15250
585f1adc
IR
15251DEFUN (bgp_distance,
15252 bgp_distance_cmd,
15253 "distance bgp (1-255) (1-255) (1-255)",
15254 "Define an administrative distance\n"
15255 "BGP distance\n"
15256 "Distance for routes external to the AS\n"
15257 "Distance for routes internal to the AS\n"
15258 "Distance for local routes\n")
718e3744 15259{
585f1adc 15260 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15261 int idx_number = 2;
15262 int idx_number_2 = 3;
15263 int idx_number_3 = 4;
585f1adc
IR
15264 int distance_ebgp = atoi(argv[idx_number]->arg);
15265 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15266 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15267 afi_t afi;
15268 safi_t safi;
718e3744 15269
d62a17ae 15270 afi = bgp_node_afi(vty);
15271 safi = bgp_node_safi(vty);
718e3744 15272
585f1adc
IR
15273 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15274 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15275 || bgp->distance_local[afi][safi] != distance_local) {
15276 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15277 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15278 bgp->distance_local[afi][safi] = distance_local;
15279 bgp_announce_routes_distance_update(bgp, afi, safi);
15280 }
15281 return CMD_SUCCESS;
15282}
37a87b8f 15283
585f1adc
IR
15284DEFUN (no_bgp_distance,
15285 no_bgp_distance_cmd,
15286 "no distance bgp [(1-255) (1-255) (1-255)]",
15287 NO_STR
15288 "Define an administrative distance\n"
15289 "BGP distance\n"
15290 "Distance for routes external to the AS\n"
15291 "Distance for routes internal to the AS\n"
15292 "Distance for local routes\n")
718e3744 15293{
585f1adc 15294 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15295 afi_t afi;
15296 safi_t safi;
37a87b8f
CS
15297
15298 afi = bgp_node_afi(vty);
15299 safi = bgp_node_safi(vty);
15300
585f1adc
IR
15301 if (bgp->distance_ebgp[afi][safi] != 0
15302 || bgp->distance_ibgp[afi][safi] != 0
15303 || bgp->distance_local[afi][safi] != 0) {
15304 bgp->distance_ebgp[afi][safi] = 0;
15305 bgp->distance_ibgp[afi][safi] = 0;
15306 bgp->distance_local[afi][safi] = 0;
15307 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15308 }
585f1adc
IR
15309 return CMD_SUCCESS;
15310}
37a87b8f 15311
37a87b8f 15312
585f1adc
IR
15313DEFUN (bgp_distance_source,
15314 bgp_distance_source_cmd,
15315 "distance (1-255) A.B.C.D/M",
15316 "Define an administrative distance\n"
15317 "Administrative distance\n"
15318 "IP source prefix\n")
15319{
15320 int idx_number = 1;
15321 int idx_ipv4_prefixlen = 2;
15322 bgp_distance_set(vty, argv[idx_number]->arg,
15323 argv[idx_ipv4_prefixlen]->arg, NULL);
15324 return CMD_SUCCESS;
734b349e
MZ
15325}
15326
585f1adc
IR
15327DEFUN (no_bgp_distance_source,
15328 no_bgp_distance_source_cmd,
15329 "no distance (1-255) A.B.C.D/M",
15330 NO_STR
15331 "Define an administrative distance\n"
15332 "Administrative distance\n"
15333 "IP source prefix\n")
37a87b8f 15334{
585f1adc
IR
15335 int idx_number = 2;
15336 int idx_ipv4_prefixlen = 3;
15337 bgp_distance_unset(vty, argv[idx_number]->arg,
15338 argv[idx_ipv4_prefixlen]->arg, NULL);
15339 return CMD_SUCCESS;
37a87b8f
CS
15340}
15341
585f1adc
IR
15342DEFUN (bgp_distance_source_access_list,
15343 bgp_distance_source_access_list_cmd,
15344 "distance (1-255) A.B.C.D/M WORD",
15345 "Define an administrative distance\n"
15346 "Administrative distance\n"
15347 "IP source prefix\n"
15348 "Access list name\n")
37a87b8f 15349{
585f1adc
IR
15350 int idx_number = 1;
15351 int idx_ipv4_prefixlen = 2;
15352 int idx_word = 3;
15353 bgp_distance_set(vty, argv[idx_number]->arg,
15354 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15355 return CMD_SUCCESS;
15356}
718e3744 15357
585f1adc
IR
15358DEFUN (no_bgp_distance_source_access_list,
15359 no_bgp_distance_source_access_list_cmd,
15360 "no distance (1-255) A.B.C.D/M WORD",
15361 NO_STR
15362 "Define an administrative distance\n"
15363 "Administrative distance\n"
15364 "IP source prefix\n"
15365 "Access list name\n")
15366{
15367 int idx_number = 2;
15368 int idx_ipv4_prefixlen = 3;
15369 int idx_word = 4;
15370 bgp_distance_unset(vty, argv[idx_number]->arg,
15371 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15372 return CMD_SUCCESS;
15373}
37a87b8f 15374
585f1adc
IR
15375DEFUN (ipv6_bgp_distance_source,
15376 ipv6_bgp_distance_source_cmd,
15377 "distance (1-255) X:X::X:X/M",
15378 "Define an administrative distance\n"
15379 "Administrative distance\n"
15380 "IP source prefix\n")
15381{
15382 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15383 return CMD_SUCCESS;
15384}
7ebe9748 15385
585f1adc
IR
15386DEFUN (no_ipv6_bgp_distance_source,
15387 no_ipv6_bgp_distance_source_cmd,
15388 "no distance (1-255) X:X::X:X/M",
15389 NO_STR
15390 "Define an administrative distance\n"
15391 "Administrative distance\n"
15392 "IP source prefix\n")
15393{
15394 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15395 return CMD_SUCCESS;
15396}
37a87b8f 15397
585f1adc
IR
15398DEFUN (ipv6_bgp_distance_source_access_list,
15399 ipv6_bgp_distance_source_access_list_cmd,
15400 "distance (1-255) X:X::X:X/M WORD",
15401 "Define an administrative distance\n"
15402 "Administrative distance\n"
15403 "IP source prefix\n"
15404 "Access list name\n")
15405{
15406 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15407 return CMD_SUCCESS;
718e3744 15408}
15409
585f1adc
IR
15410DEFUN (no_ipv6_bgp_distance_source_access_list,
15411 no_ipv6_bgp_distance_source_access_list_cmd,
15412 "no distance (1-255) X:X::X:X/M WORD",
15413 NO_STR
15414 "Define an administrative distance\n"
15415 "Administrative distance\n"
15416 "IP source prefix\n"
15417 "Access list name\n")
718e3744 15418{
585f1adc
IR
15419 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15420 return CMD_SUCCESS;
15421}
37a87b8f 15422
585f1adc
IR
15423DEFUN (bgp_damp_set,
15424 bgp_damp_set_cmd,
a30fec23 15425 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15426 "BGP Specific commands\n"
15427 "Enable route-flap dampening\n"
15428 "Half-life time for the penalty\n"
15429 "Value to start reusing a route\n"
15430 "Value to start suppressing a route\n"
15431 "Maximum duration to suppress a stable route\n")
15432{
15433 VTY_DECLVAR_CONTEXT(bgp, bgp);
15434 int idx_half_life = 2;
15435 int idx_reuse = 3;
15436 int idx_suppress = 4;
15437 int idx_max_suppress = 5;
37a87b8f
CS
15438 int half = DEFAULT_HALF_LIFE * 60;
15439 int reuse = DEFAULT_REUSE;
15440 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15441 int max = 4 * half;
15442
15443 if (argc == 6) {
15444 half = atoi(argv[idx_half_life]->arg) * 60;
15445 reuse = atoi(argv[idx_reuse]->arg);
15446 suppress = atoi(argv[idx_suppress]->arg);
15447 max = atoi(argv[idx_max_suppress]->arg) * 60;
15448 } else if (argc == 3) {
15449 half = atoi(argv[idx_half_life]->arg) * 60;
15450 max = 4 * half;
15451 }
15452
15453 /*
15454 * These can't be 0 but our SA doesn't understand the
15455 * way our cli is constructed
15456 */
15457 assert(reuse);
15458 assert(half);
15459 if (suppress < reuse) {
15460 vty_out(vty,
15461 "Suppress value cannot be less than reuse value \n");
15462 return 0;
15463 }
15464
15465 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15466 reuse, suppress, max);
15467}
15468
15469DEFUN (bgp_damp_unset,
15470 bgp_damp_unset_cmd,
a30fec23 15471 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15472 NO_STR
15473 "BGP Specific commands\n"
15474 "Enable route-flap dampening\n"
15475 "Half-life time for the penalty\n"
15476 "Value to start reusing a route\n"
15477 "Value to start suppressing a route\n"
15478 "Maximum duration to suppress a stable route\n")
15479{
15480 VTY_DECLVAR_CONTEXT(bgp, bgp);
15481 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15482}
15483
718e3744 15484/* Display specified route of BGP table. */
d62a17ae 15485static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15486 const char *ip_str, afi_t afi, safi_t safi,
15487 struct prefix_rd *prd, int prefix_check)
15488{
15489 int ret;
15490 struct prefix match;
9bcb3eef
DS
15491 struct bgp_dest *dest;
15492 struct bgp_dest *rm;
40381db7
DS
15493 struct bgp_path_info *pi;
15494 struct bgp_path_info *pi_temp;
d62a17ae 15495 struct bgp *bgp;
15496 struct bgp_table *table;
15497
15498 /* BGP structure lookup. */
15499 if (view_name) {
15500 bgp = bgp_lookup_by_name(view_name);
15501 if (bgp == NULL) {
15502 vty_out(vty, "%% Can't find BGP instance %s\n",
15503 view_name);
15504 return CMD_WARNING;
15505 }
15506 } else {
15507 bgp = bgp_get_default();
15508 if (bgp == NULL) {
15509 vty_out(vty, "%% No BGP process is configured\n");
15510 return CMD_WARNING;
15511 }
718e3744 15512 }
718e3744 15513
d62a17ae 15514 /* Check IP address argument. */
15515 ret = str2prefix(ip_str, &match);
15516 if (!ret) {
15517 vty_out(vty, "%% address is malformed\n");
15518 return CMD_WARNING;
15519 }
718e3744 15520
d62a17ae 15521 match.family = afi2family(afi);
15522
15523 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15524 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15525 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15526 dest = bgp_route_next(dest)) {
15527 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15528
9bcb3eef 15529 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15530 continue;
9bcb3eef 15531 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15532 if (!table)
ea47320b 15533 continue;
4953391b
DA
15534 rm = bgp_node_match(table, &match);
15535 if (rm == NULL)
ea47320b 15536 continue;
d62a17ae 15537
9bcb3eef 15538 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15539
ea47320b 15540 if (!prefix_check
b54892e0 15541 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15542 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15543 while (pi) {
15544 if (pi->extra && pi->extra->damp_info) {
15545 pi_temp = pi->next;
ea47320b 15546 bgp_damp_info_free(
19971c9a 15547 pi->extra->damp_info,
5c8846f6 15548 1, afi, safi);
40381db7 15549 pi = pi_temp;
ea47320b 15550 } else
40381db7 15551 pi = pi->next;
d62a17ae 15552 }
ea47320b
DL
15553 }
15554
9bcb3eef 15555 bgp_dest_unlock_node(rm);
d62a17ae 15556 }
15557 } else {
4953391b
DA
15558 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15559 if (dest != NULL) {
9bcb3eef 15560 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15561
d62a17ae 15562 if (!prefix_check
9bcb3eef
DS
15563 || dest_p->prefixlen == match.prefixlen) {
15564 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15565 while (pi) {
15566 if (pi->extra && pi->extra->damp_info) {
15567 pi_temp = pi->next;
d62a17ae 15568 bgp_damp_info_free(
19971c9a 15569 pi->extra->damp_info,
5c8846f6 15570 1, afi, safi);
40381db7 15571 pi = pi_temp;
d62a17ae 15572 } else
40381db7 15573 pi = pi->next;
d62a17ae 15574 }
15575 }
15576
9bcb3eef 15577 bgp_dest_unlock_node(dest);
d62a17ae 15578 }
15579 }
718e3744 15580
d62a17ae 15581 return CMD_SUCCESS;
718e3744 15582}
15583
15584DEFUN (clear_ip_bgp_dampening,
15585 clear_ip_bgp_dampening_cmd,
15586 "clear ip bgp dampening",
15587 CLEAR_STR
15588 IP_STR
15589 BGP_STR
15590 "Clear route flap dampening information\n")
15591{
b4f7f45b 15592 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15593 return CMD_SUCCESS;
718e3744 15594}
15595
15596DEFUN (clear_ip_bgp_dampening_prefix,
15597 clear_ip_bgp_dampening_prefix_cmd,
15598 "clear ip bgp dampening A.B.C.D/M",
15599 CLEAR_STR
15600 IP_STR
15601 BGP_STR
15602 "Clear route flap dampening information\n"
0c7b1b01 15603 "IPv4 prefix\n")
718e3744 15604{
d62a17ae 15605 int idx_ipv4_prefixlen = 4;
15606 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15607 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15608}
15609
15610DEFUN (clear_ip_bgp_dampening_address,
15611 clear_ip_bgp_dampening_address_cmd,
15612 "clear ip bgp dampening A.B.C.D",
15613 CLEAR_STR
15614 IP_STR
15615 BGP_STR
15616 "Clear route flap dampening information\n"
15617 "Network to clear damping information\n")
15618{
d62a17ae 15619 int idx_ipv4 = 4;
15620 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15621 SAFI_UNICAST, NULL, 0);
718e3744 15622}
15623
15624DEFUN (clear_ip_bgp_dampening_address_mask,
15625 clear_ip_bgp_dampening_address_mask_cmd,
15626 "clear ip bgp dampening A.B.C.D A.B.C.D",
15627 CLEAR_STR
15628 IP_STR
15629 BGP_STR
15630 "Clear route flap dampening information\n"
15631 "Network to clear damping information\n"
15632 "Network mask\n")
15633{
d62a17ae 15634 int idx_ipv4 = 4;
15635 int idx_ipv4_2 = 5;
15636 int ret;
15637 char prefix_str[BUFSIZ];
718e3744 15638
d62a17ae 15639 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15640 prefix_str, sizeof(prefix_str));
d62a17ae 15641 if (!ret) {
15642 vty_out(vty, "%% Inconsistent address and mask\n");
15643 return CMD_WARNING;
15644 }
718e3744 15645
d62a17ae 15646 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15647 NULL, 0);
718e3744 15648}
6b0655a2 15649
e3b78da8 15650static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15651{
15652 struct vty *vty = arg;
e3b78da8 15653 struct peer *peer = bucket->data;
825d9834 15654
47e12884 15655 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15656}
15657
2a0e69ae
DS
15658DEFUN (show_bgp_listeners,
15659 show_bgp_listeners_cmd,
15660 "show bgp listeners",
15661 SHOW_STR
15662 BGP_STR
15663 "Display Listen Sockets and who created them\n")
15664{
15665 bgp_dump_listener_info(vty);
15666
15667 return CMD_SUCCESS;
15668}
15669
825d9834
DS
15670DEFUN (show_bgp_peerhash,
15671 show_bgp_peerhash_cmd,
15672 "show bgp peerhash",
15673 SHOW_STR
15674 BGP_STR
15675 "Display information about the BGP peerhash\n")
15676{
15677 struct list *instances = bm->bgp;
15678 struct listnode *node;
15679 struct bgp *bgp;
15680
15681 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15682 vty_out(vty, "BGP: %s\n", bgp->name);
15683 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15684 vty);
15685 }
15686
15687 return CMD_SUCCESS;
15688}
15689
587ff0fd 15690/* also used for encap safi */
2b791107
DL
15691static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15692 afi_t afi, safi_t safi)
d62a17ae 15693{
9bcb3eef
DS
15694 struct bgp_dest *pdest;
15695 struct bgp_dest *dest;
d62a17ae 15696 struct bgp_table *table;
b54892e0 15697 const struct prefix *p;
d62a17ae 15698 struct bgp_static *bgp_static;
15699 mpls_label_t label;
d62a17ae 15700
15701 /* Network configuration. */
9bcb3eef
DS
15702 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15703 pdest = bgp_route_next(pdest)) {
15704 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15705 if (!table)
ea47320b 15706 continue;
d62a17ae 15707
9bcb3eef
DS
15708 for (dest = bgp_table_top(table); dest;
15709 dest = bgp_route_next(dest)) {
15710 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15711 if (bgp_static == NULL)
ea47320b 15712 continue;
d62a17ae 15713
9bcb3eef 15714 p = bgp_dest_get_prefix(dest);
d62a17ae 15715
ea47320b 15716 /* "network" configuration display. */
ea47320b
DL
15717 label = decode_label(&bgp_static->label);
15718
c1aa9e7f
PG
15719 vty_out(vty, " network %pFX rd %s", p,
15720 bgp_static->prd_pretty);
ea47320b
DL
15721 if (safi == SAFI_MPLS_VPN)
15722 vty_out(vty, " label %u", label);
15723
15724 if (bgp_static->rmap.name)
15725 vty_out(vty, " route-map %s",
15726 bgp_static->rmap.name);
e2a86ad9
DS
15727
15728 if (bgp_static->backdoor)
15729 vty_out(vty, " backdoor");
15730
ea47320b
DL
15731 vty_out(vty, "\n");
15732 }
15733 }
d62a17ae 15734}
15735
2b791107
DL
15736static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15737 afi_t afi, safi_t safi)
d62a17ae 15738{
9bcb3eef
DS
15739 struct bgp_dest *pdest;
15740 struct bgp_dest *dest;
d62a17ae 15741 struct bgp_table *table;
b54892e0 15742 const struct prefix *p;
d62a17ae 15743 struct bgp_static *bgp_static;
ff44f570 15744 char buf[PREFIX_STRLEN * 2];
d62a17ae 15745 char buf2[SU_ADDRSTRLEN];
5f933e1e 15746 char esi_buf[ESI_STR_LEN];
d62a17ae 15747
15748 /* Network configuration. */
9bcb3eef
DS
15749 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15750 pdest = bgp_route_next(pdest)) {
15751 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15752 if (!table)
ea47320b 15753 continue;
d62a17ae 15754
9bcb3eef
DS
15755 for (dest = bgp_table_top(table); dest;
15756 dest = bgp_route_next(dest)) {
15757 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15758 if (bgp_static == NULL)
ea47320b 15759 continue;
d62a17ae 15760
ea47320b 15761 char *macrouter = NULL;
d62a17ae 15762
ea47320b
DL
15763 if (bgp_static->router_mac)
15764 macrouter = prefix_mac2str(
15765 bgp_static->router_mac, NULL, 0);
15766 if (bgp_static->eth_s_id)
0a50c248
AK
15767 esi_to_str(bgp_static->eth_s_id,
15768 esi_buf, sizeof(esi_buf));
9bcb3eef 15769 p = bgp_dest_get_prefix(dest);
d62a17ae 15770
ea47320b 15771 /* "network" configuration display. */
197cb530
PG
15772 if (p->u.prefix_evpn.route_type == 5) {
15773 char local_buf[PREFIX_STRLEN];
07380148 15774
3714a385 15775 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15776 struct prefix_evpn *)p)
15777 ? AF_INET
15778 : AF_INET6;
3714a385 15779 inet_ntop(family,
07380148
DA
15780 &p->u.prefix_evpn.prefix_addr.ip.ip
15781 .addr,
15782 local_buf, sizeof(local_buf));
772270f3
QY
15783 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15784 p->u.prefix_evpn.prefix_addr
15785 .ip_prefix_length);
197cb530
PG
15786 } else {
15787 prefix2str(p, buf, sizeof(buf));
15788 }
ea47320b 15789
a4d82a8a
PZ
15790 if (bgp_static->gatewayIp.family == AF_INET
15791 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15792 inet_ntop(bgp_static->gatewayIp.family,
15793 &bgp_static->gatewayIp.u.prefix, buf2,
15794 sizeof(buf2));
ea47320b 15795 vty_out(vty,
c1aa9e7f
PG
15796 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15797 buf, bgp_static->prd_pretty,
15798 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15799 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15800 macrouter);
15801
0a22ddfb 15802 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15803 }
15804 }
3da6fcd5
PG
15805}
15806
718e3744 15807/* Configuration of static route announcement and aggregate
15808 information. */
2b791107
DL
15809void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15810 safi_t safi)
d62a17ae 15811{
9bcb3eef 15812 struct bgp_dest *dest;
b54892e0 15813 const struct prefix *p;
d62a17ae 15814 struct bgp_static *bgp_static;
15815 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15816
2b791107
DL
15817 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15818 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15819 return;
15820 }
d62a17ae 15821
2b791107
DL
15822 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15823 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15824 return;
15825 }
d62a17ae 15826
15827 /* Network configuration. */
9bcb3eef
DS
15828 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15829 dest = bgp_route_next(dest)) {
15830 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15831 if (bgp_static == NULL)
ea47320b 15832 continue;
d62a17ae 15833
9bcb3eef 15834 p = bgp_dest_get_prefix(dest);
d62a17ae 15835
8228a9a7 15836 vty_out(vty, " network %pFX", p);
d62a17ae 15837
ea47320b
DL
15838 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15839 vty_out(vty, " label-index %u",
15840 bgp_static->label_index);
d62a17ae 15841
ea47320b
DL
15842 if (bgp_static->rmap.name)
15843 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15844
15845 if (bgp_static->backdoor)
15846 vty_out(vty, " backdoor");
718e3744 15847
ea47320b
DL
15848 vty_out(vty, "\n");
15849 }
15850
d62a17ae 15851 /* Aggregate-address configuration. */
9bcb3eef
DS
15852 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15853 dest = bgp_route_next(dest)) {
15854 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15855 if (bgp_aggregate == NULL)
ea47320b 15856 continue;
d62a17ae 15857
9bcb3eef 15858 p = bgp_dest_get_prefix(dest);
d62a17ae 15859
8228a9a7 15860 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15861
ea47320b
DL
15862 if (bgp_aggregate->as_set)
15863 vty_out(vty, " as-set");
d62a17ae 15864
ea47320b
DL
15865 if (bgp_aggregate->summary_only)
15866 vty_out(vty, " summary-only");
718e3744 15867
20894f50
DA
15868 if (bgp_aggregate->rmap.name)
15869 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15870
229757f1
DA
15871 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15872 vty_out(vty, " origin %s",
15873 bgp_origin2str(bgp_aggregate->origin));
15874
6aabb15d
RZ
15875 if (bgp_aggregate->match_med)
15876 vty_out(vty, " matching-MED-only");
15877
365ab2e7
RZ
15878 if (bgp_aggregate->suppress_map_name)
15879 vty_out(vty, " suppress-map %s",
15880 bgp_aggregate->suppress_map_name);
15881
ea47320b
DL
15882 vty_out(vty, "\n");
15883 }
d62a17ae 15884}
734b349e 15885
2b791107 15886void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15887 safi_t safi)
d62a17ae 15888{
9bcb3eef 15889 struct bgp_dest *dest;
d62a17ae 15890 struct bgp_distance *bdistance;
15891
15892 /* Distance configuration. */
15893 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15894 && bgp->distance_local[afi][safi]
15895 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15896 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15897 || bgp->distance_local[afi][safi]
15898 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15899 vty_out(vty, " distance bgp %d %d %d\n",
15900 bgp->distance_ebgp[afi][safi],
15901 bgp->distance_ibgp[afi][safi],
15902 bgp->distance_local[afi][safi]);
15903 }
734b349e 15904
9bcb3eef
DS
15905 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15906 dest = bgp_route_next(dest)) {
15907 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15908 if (bdistance != NULL)
56ca3b5b 15909 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15910 bdistance->distance, dest,
d62a17ae 15911 bdistance->access_list ? bdistance->access_list
15912 : "");
ca2e160d 15913 }
718e3744 15914}
15915
15916/* Allocate routing table structure and install commands. */
d62a17ae 15917void bgp_route_init(void)
15918{
15919 afi_t afi;
15920 safi_t safi;
15921
15922 /* Init BGP distance table. */
05c7a1cc 15923 FOREACH_AFI_SAFI (afi, safi)
960035b2 15924 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15925
15926 /* IPv4 BGP commands. */
15927 install_element(BGP_NODE, &bgp_table_map_cmd);
15928 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15929 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15930
554b3b10 15931 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15932
15933 /* IPv4 unicast configuration. */
15934 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15935 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15936 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15937
554b3b10 15938 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15939
15940 /* IPv4 multicast configuration. */
15941 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15942 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15943 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15944 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15945
15946 /* IPv4 labeled-unicast configuration. */
fb985e0c 15947 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15948 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15949
d62a17ae 15950 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15951 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15952 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15953 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15954 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15955 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15956 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15957 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15958
15959 install_element(VIEW_NODE,
15960 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15961 install_element(VIEW_NODE,
15962 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15963 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15964 install_element(VIEW_NODE,
15965 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15966#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15967 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15968#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15969 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15970 install_element(VIEW_NODE,
44c69747 15971 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15972
d62a17ae 15973 /* BGP dampening clear commands */
15974 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15975 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15976
d62a17ae 15977 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15978 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15979
15980 /* prefix count */
15981 install_element(ENABLE_NODE,
15982 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15983#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15984 install_element(ENABLE_NODE,
15985 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15986#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15987
d62a17ae 15988 /* New config IPv6 BGP commands. */
15989 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15990 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15991 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15992
554b3b10 15993 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15994
15995 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15996
fb985e0c
DA
15997 /* IPv6 labeled unicast address family. */
15998 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15999 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 16000
d62a17ae 16001 install_element(BGP_NODE, &bgp_distance_cmd);
16002 install_element(BGP_NODE, &no_bgp_distance_cmd);
16003 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16004 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
16005 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
16006 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 16007 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
16008 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
16009 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16010 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
16011 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
16012 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 16013 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
16014 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
16015 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16016 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
16017 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
16018 install_element(BGP_IPV4M_NODE,
16019 &no_bgp_distance_source_access_list_cmd);
d62a17ae 16020 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
16021 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16022 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
16023 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
16024 install_element(BGP_IPV6_NODE,
16025 &ipv6_bgp_distance_source_access_list_cmd);
16026 install_element(BGP_IPV6_NODE,
16027 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16028 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
16029 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16030 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
16031 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
16032 install_element(BGP_IPV6M_NODE,
16033 &ipv6_bgp_distance_source_access_list_cmd);
16034 install_element(BGP_IPV6M_NODE,
16035 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16036
ef5f4b23 16037 /* BGP dampening */
585f1adc
IR
16038 install_element(BGP_NODE, &bgp_damp_set_cmd);
16039 install_element(BGP_NODE, &bgp_damp_unset_cmd);
16040 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
16041 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
16042 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16043 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16044 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16045 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16046 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16047 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16048 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16049 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16050 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16051 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 16052
16053 /* Large Communities */
16054 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16055 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
16056
16057 /* show bgp ipv4 flowspec detailed */
16058 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
16059
2a0e69ae 16060 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16061 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16062}
16063
16064void bgp_route_finish(void)
16065{
16066 afi_t afi;
16067 safi_t safi;
16068
05c7a1cc
QY
16069 FOREACH_AFI_SAFI (afi, safi) {
16070 bgp_table_unlock(bgp_distance_table[afi][safi]);
16071 bgp_distance_table[afi][safi] = NULL;
16072 }
228da428 16073}