]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
*: Convert `struct event_master` to `struct event_loop`
[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"
cb37cb33 23#include "event.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
DA
2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2389 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2390 bgp_attr_flush(rmap_path.attr);
3dc339cd 2391 return false;
d62a17ae 2392 }
3f9c7369 2393 }
3f9c7369 2394
9dac9fc8
DA
2395 /* RFC 8212 to prevent route leaks.
2396 * This specification intends to improve this situation by requiring the
2397 * explicit configuration of both BGP Import and Export Policies for any
2398 * External BGP (EBGP) session such as customers, peers, or
2399 * confederation boundaries for all enabled address families. Through
2400 * codification of the aforementioned requirement, operators will
2401 * benefit from consistent behavior across different BGP
2402 * implementations.
2403 */
1d3fdccf 2404 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2405 if (!bgp_outbound_policy_exists(peer, filter)) {
2406 if (monotime_since(&bgp->ebgprequirespolicywarning,
2407 NULL) > FIFTEENMINUTE2USEC ||
2408 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2409 zlog_warn(
2410 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2411 monotime(&bgp->ebgprequirespolicywarning);
2412 }
3dc339cd 2413 return false;
b17826b7 2414 }
9dac9fc8 2415
fb29348a
DA
2416 /* draft-ietf-idr-deprecate-as-set-confed-set
2417 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2418 * Eventually, This document (if approved) updates RFC 4271
2419 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2420 * and obsoletes RFC 6472.
2421 */
7f972cd8 2422 if (peer->bgp->reject_as_sets)
fb29348a 2423 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2424 return false;
fb29348a 2425
8c4d4624 2426 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2427 * SoO extended community and validate against the configured
2428 * one. If they match, do not announce, to prevent routing
2429 * loops.
2430 */
2431 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2432 peer->soo[afi][safi]) {
2433 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2434 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2435
2436 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2437 ECOMMUNITY_SITE_ORIGIN) ||
2438 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2439 ECOMMUNITY_SITE_ORIGIN) ||
2440 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2441 ECOMMUNITY_SITE_ORIGIN)) &&
2442 ecommunity_include(ecomm, ecomm_soo)) {
2443 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2444 zlog_debug(
2445 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2446 peer, p, ecommunity_str(ecomm_soo));
2447 return false;
2448 }
2449 }
2450
33d022bc
DA
2451 /* Codification of AS 0 Processing */
2452 if (aspath_check_as_zero(attr->aspath))
e2369003 2453 return false;
33d022bc 2454
637e5ba4 2455 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2456 if (peer->sort == BGP_PEER_IBGP
2457 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2458 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2459 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2460 } else {
2461 bgp_attr_add_gshut_community(attr);
2462 }
2463 }
2464
1479ed2f
DA
2465 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2466 * Capability" to a neighbor MUST perform the following upon receiving
2467 * a route from that neighbor with the "LLGR_STALE" community, or upon
2468 * attaching the "LLGR_STALE" community itself per Section 4.2:
2469 *
2470 * The route SHOULD NOT be advertised to any neighbor from which the
2471 * Long-lived Graceful Restart Capability has not been received.
2472 */
9a706b42
DA
2473 if (bgp_attr_get_community(attr) &&
2474 community_include(bgp_attr_get_community(attr),
2475 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2476 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2477 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2478 return false;
2479
d62a17ae 2480 /* After route-map has been applied, we check to see if the nexthop to
2481 * be carried in the attribute (that is used for the announcement) can
2482 * be cleared off or not. We do this in all cases where we would be
2483 * setting the nexthop to "ourselves". For IPv6, we only need to
2484 * consider
2485 * the global nexthop here; the link-local nexthop would have been
2486 * cleared
2487 * already, and if not, it is required by the update formation code.
2488 * Also see earlier comments in this function.
2489 */
2490 /*
2491 * If route-map has performed some operation on the nexthop or the peer
2492 * configuration says to pass it unchanged, we cannot reset the nexthop
2493 * here, so only attempt to do it if these aren't true. Note that the
2494 * route-map handler itself might have cleared the nexthop, if for
2495 * example,
2496 * it is configured as 'peer-address'.
2497 */
2498 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2499 piattr->rmap_change_flags)
d62a17ae 2500 && !transparent
2501 && !CHECK_FLAG(peer->af_flags[afi][safi],
2502 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2503 /* We can reset the nexthop, if setting (or forcing) it to
2504 * 'self' */
2505 if (CHECK_FLAG(peer->af_flags[afi][safi],
2506 PEER_FLAG_NEXTHOP_SELF)
2507 || CHECK_FLAG(peer->af_flags[afi][safi],
2508 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2509 if (!reflect
2510 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2511 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2512 subgroup_announce_reset_nhop(
2513 (peer_cap_enhe(peer, afi, safi)
2514 ? AF_INET6
2515 : p->family),
2516 attr);
7b651a32 2517 nh_reset = true;
2518 }
d62a17ae 2519 } else if (peer->sort == BGP_PEER_EBGP) {
2520 /* Can also reset the nexthop if announcing to EBGP, but
2521 * only if
2522 * no peer in the subgroup is on a shared subnet.
2523 * Note: 3rd party nexthop currently implemented for
2524 * IPv4 only.
2525 */
737af885
BS
2526 if ((p->family == AF_INET) &&
2527 (!bgp_subgrp_multiaccess_check_v4(
2528 piattr->nexthop,
7b651a32 2529 subgrp, from))) {
d62a17ae 2530 subgroup_announce_reset_nhop(
2531 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2532 ? AF_INET6
2533 : p->family),
737af885 2534 attr);
7b651a32 2535 nh_reset = true;
2536 }
737af885
BS
2537
2538 if ((p->family == AF_INET6) &&
2539 (!bgp_subgrp_multiaccess_check_v6(
2540 piattr->mp_nexthop_global,
7b651a32 2541 subgrp, from))) {
737af885
BS
2542 subgroup_announce_reset_nhop(
2543 (peer_cap_enhe(peer, afi, safi)
2544 ? AF_INET6
2545 : p->family),
2546 attr);
7b651a32 2547 nh_reset = true;
2548 }
737af885
BS
2549
2550
2551
40381db7 2552 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2553 /*
2554 * This flag is used for leaked vpn-vrf routes
2555 */
2556 int family = p->family;
2557
2558 if (peer_cap_enhe(peer, afi, safi))
2559 family = AF_INET6;
2560
2561 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2562 zlog_debug(
6cf8a4bf
DA
2563 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2564 __func__, p, family2str(family));
960035b2 2565 subgroup_announce_reset_nhop(family, attr);
7b651a32 2566 nh_reset = true;
d62a17ae 2567 }
63696f1d 2568 }
960035b2 2569
63696f1d 2570 /* If IPv6/MP and nexthop does not have any override and happens
2571 * to
2572 * be a link-local address, reset it so that we don't pass along
2573 * the
2574 * source's link-local IPv6 address to recipients who may not be
2575 * on
2576 * the same interface.
2577 */
2578 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2579 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2580 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2581 nh_reset = true;
2582 }
d62a17ae 2583 }
3f9c7369 2584
7b27cf7b
DA
2585 /* If this is an iBGP, send Origin Validation State (OVS)
2586 * extended community (rfc8097).
2587 */
2588 if (peer->sort == BGP_PEER_IBGP) {
2589 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2590
2591 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2592
2593 if (rpki_state != RPKI_NOT_BEING_USED)
2594 bgp_attr_set_ecommunity(
2595 attr, ecommunity_add_origin_validation_state(
2596 rpki_state,
2597 bgp_attr_get_ecommunity(attr)));
2598 }
2599
7b651a32 2600 /*
2601 * When the next hop is set to ourselves, if all multipaths have
2602 * link-bandwidth announce the cumulative bandwidth as that makes
2603 * the most sense. However, don't modify if the link-bandwidth has
2604 * been explicitly set by user policy.
2605 */
2606 if (nh_reset &&
f7e1c681 2607 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2608 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2609 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2610 bgp_attr_set_ecommunity(
2611 attr,
2612 ecommunity_replace_linkbw(
2613 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2614 CHECK_FLAG(
2615 peer->flags,
2616 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2617
3dc339cd 2618 return true;
3f9c7369
DS
2619}
2620
e6685141 2621static void bgp_route_select_timer_expire(struct event *thread)
f009ff26 2622{
2623 struct afi_safi_info *info;
2624 afi_t afi;
2625 safi_t safi;
2626 struct bgp *bgp;
2627
e16d030c 2628 info = EVENT_ARG(thread);
f009ff26 2629 afi = info->afi;
2630 safi = info->safi;
2631 bgp = info->bgp;
2632
f009ff26 2633 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2634 XFREE(MTYPE_TMP, info);
2635
2636 /* Best path selection */
cc9f21da 2637 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2638}
2639
9bcb3eef 2640void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2641 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2642 struct bgp_path_info_pair *result, afi_t afi,
2643 safi_t safi)
2644{
2645 struct bgp_path_info *new_select;
2646 struct bgp_path_info *old_select;
40381db7
DS
2647 struct bgp_path_info *pi;
2648 struct bgp_path_info *pi1;
2649 struct bgp_path_info *pi2;
2650 struct bgp_path_info *nextpi = NULL;
d62a17ae 2651 int paths_eq, do_mpath, debug;
2652 struct list mp_list;
2653 char pfx_buf[PREFIX2STR_BUFFER];
2654 char path_buf[PATH_ADDPATH_STR_BUFFER];
2655
2656 bgp_mp_list_init(&mp_list);
2657 do_mpath =
2658 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2659
9bcb3eef 2660 debug = bgp_debug_bestpath(dest);
d62a17ae 2661
2662 if (debug)
9bcb3eef 2663 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2664
9bcb3eef 2665 dest->reason = bgp_path_selection_none;
d62a17ae 2666 /* bgp deterministic-med */
2667 new_select = NULL;
892fedb6 2668 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2669
1defdda8 2670 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2671 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2672 pi1 = pi1->next)
9bcb3eef 2673 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2674 BGP_PATH_DMED_SELECTED);
d62a17ae 2675
9bcb3eef 2676 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2677 pi1 = pi1->next) {
40381db7 2678 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2679 continue;
40381db7 2680 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2681 continue;
de692a4e 2682 if (pi1->peer != bgp->peer_self &&
2683 !CHECK_FLAG(pi1->peer->sflags,
2684 PEER_STATUS_NSF_WAIT)) {
feb17238 2685 if (!peer_established(pi1->peer))
d62a17ae 2686 continue;
de692a4e 2687 }
d62a17ae 2688
40381db7
DS
2689 new_select = pi1;
2690 if (pi1->next) {
2691 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2692 if (CHECK_FLAG(pi2->flags,
1defdda8 2693 BGP_PATH_DMED_CHECK))
d62a17ae 2694 continue;
40381db7 2695 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2696 continue;
ea8b2282 2697 if (pi2->peer != bgp->peer_self
d62a17ae 2698 && !CHECK_FLAG(
ea8b2282
DS
2699 pi2->peer->sflags,
2700 PEER_STATUS_NSF_WAIT))
40381db7 2701 if (pi2->peer->status
d62a17ae 2702 != Established)
2703 continue;
2704
121e245d
DS
2705 if (!aspath_cmp_left(pi1->attr->aspath,
2706 pi2->attr->aspath)
2707 && !aspath_cmp_left_confed(
40381db7 2708 pi1->attr->aspath,
121e245d
DS
2709 pi2->attr->aspath))
2710 continue;
d62a17ae 2711
121e245d
DS
2712 if (bgp_path_info_cmp(
2713 bgp, pi2, new_select,
2714 &paths_eq, mpath_cfg, debug,
fdf81fa0 2715 pfx_buf, afi, safi,
9bcb3eef 2716 &dest->reason)) {
121e245d 2717 bgp_path_info_unset_flag(
9bcb3eef 2718 dest, new_select,
121e245d
DS
2719 BGP_PATH_DMED_SELECTED);
2720 new_select = pi2;
d62a17ae 2721 }
121e245d
DS
2722
2723 bgp_path_info_set_flag(
9bcb3eef 2724 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2725 }
2726 }
9bcb3eef 2727 bgp_path_info_set_flag(dest, new_select,
18ee8310 2728 BGP_PATH_DMED_CHECK);
9bcb3eef 2729 bgp_path_info_set_flag(dest, new_select,
18ee8310 2730 BGP_PATH_DMED_SELECTED);
d62a17ae 2731
2732 if (debug) {
18ee8310 2733 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2734 new_select, path_buf, sizeof(path_buf));
8228a9a7 2735 zlog_debug(
4378495a
DS
2736 "%pBD(%s): %s is the bestpath from AS %u",
2737 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2738 aspath_get_first_as(
2739 new_select->attr->aspath));
d62a17ae 2740 }
2741 }
2742 }
96450faf 2743
d62a17ae 2744 /* Check old selected route and new selected route. */
2745 old_select = NULL;
2746 new_select = NULL;
9bcb3eef 2747 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2748 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2749 enum bgp_path_selection_reason reason;
2750
40381db7
DS
2751 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2752 old_select = pi;
d62a17ae 2753
40381db7 2754 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2755 /* reap REMOVED routes, if needs be
2756 * selected route must stay for a while longer though
2757 */
40381db7
DS
2758 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2759 && (pi != old_select))
9bcb3eef 2760 bgp_path_info_reap(dest, pi);
d62a17ae 2761
ddb5b488 2762 if (debug)
7fd8ca9a
DS
2763 zlog_debug(
2764 "%s: %pBD(%s) pi from %s in holddown",
2765 __func__, dest, bgp->name_pretty,
2766 pi->peer->host);
ddb5b488 2767
d62a17ae 2768 continue;
2769 }
96450faf 2770
40381db7
DS
2771 if (pi->peer && pi->peer != bgp->peer_self
2772 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2773 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2774
2775 if (debug)
2776 zlog_debug(
7fd8ca9a
DS
2777 "%s: %pBD(%s) non self peer %s not estab state",
2778 __func__, dest,
2779 bgp->name_pretty,
2780 pi->peer->host);
ddb5b488 2781
d62a17ae 2782 continue;
ddb5b488 2783 }
9fbdd100 2784
892fedb6 2785 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2786 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2787 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2788 if (debug)
7fd8ca9a
DS
2789 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
2790 dest, bgp->name_pretty,
2791 pi->peer->host);
d62a17ae 2792 continue;
2793 }
9fbdd100 2794
9bcb3eef 2795 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2796
9bcb3eef 2797 reason = dest->reason;
40381db7 2798 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2799 debug, pfx_buf, afi, safi,
2800 &dest->reason)) {
19ea4cec
DS
2801 if (new_select == NULL &&
2802 reason != bgp_path_selection_none)
9bcb3eef 2803 dest->reason = reason;
40381db7 2804 new_select = pi;
d62a17ae 2805 }
2806 }
718e3744 2807
d62a17ae 2808 /* Now that we know which path is the bestpath see if any of the other
2809 * paths
2810 * qualify as multipaths
2811 */
2812 if (debug) {
2813 if (new_select)
7533cad7
QY
2814 bgp_path_info_path_with_addpath_rx_str(
2815 new_select, path_buf, sizeof(path_buf));
d62a17ae 2816 else
772270f3 2817 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2818 zlog_debug(
4378495a
DS
2819 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2820 dest, bgp->name_pretty, path_buf,
d62a17ae 2821 old_select ? old_select->peer->host : "NONE");
96450faf 2822 }
9fbdd100 2823
d62a17ae 2824 if (do_mpath && new_select) {
9bcb3eef 2825 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2826 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2827
2828 if (debug)
18ee8310 2829 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2830 pi, path_buf, sizeof(path_buf));
d62a17ae 2831
40381db7 2832 if (pi == new_select) {
d62a17ae 2833 if (debug)
2834 zlog_debug(
4378495a
DS
2835 "%pBD(%s): %s is the bestpath, add to the multipath list",
2836 dest, bgp->name_pretty,
2837 path_buf);
40381db7 2838 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2839 continue;
2840 }
2841
40381db7 2842 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2843 continue;
2844
40381db7
DS
2845 if (pi->peer && pi->peer != bgp->peer_self
2846 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2847 PEER_STATUS_NSF_WAIT))
feb17238 2848 if (!peer_established(pi->peer))
d62a17ae 2849 continue;
2850
40381db7 2851 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2852 if (debug)
2853 zlog_debug(
7fd8ca9a
DS
2854 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2855 dest, bgp->name_pretty,
2856 path_buf);
d62a17ae 2857 continue;
2858 }
2859
40381db7 2860 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2861 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2862 &dest->reason);
d62a17ae 2863
2864 if (paths_eq) {
2865 if (debug)
2866 zlog_debug(
7fd8ca9a
DS
2867 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2868 dest, bgp->name_pretty,
2869 path_buf);
40381db7 2870 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2871 }
2872 }
2873 }
fee0f4c6 2874
4378495a 2875 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2876 mpath_cfg);
2877 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2878 bgp_mp_list_clear(&mp_list);
96450faf 2879
9bcb3eef 2880 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2881
d62a17ae 2882 result->old = old_select;
2883 result->new = new_select;
96450faf 2884
d62a17ae 2885 return;
fee0f4c6 2886}
2887
3f9c7369
DS
2888/*
2889 * A new route/change in bestpath of an existing route. Evaluate the path
2890 * for advertisement to the subgroup.
2891 */
3dc339cd
DA
2892void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2893 struct bgp_path_info *selected,
9bcb3eef 2894 struct bgp_dest *dest,
3dc339cd 2895 uint32_t addpath_tx_id)
d62a17ae 2896{
b54892e0 2897 const struct prefix *p;
d62a17ae 2898 struct peer *onlypeer;
2899 struct attr attr;
2900 afi_t afi;
2901 safi_t safi;
a77e2f4b
S
2902 struct bgp *bgp;
2903 bool advertise;
adbac85e 2904
9bcb3eef 2905 p = bgp_dest_get_prefix(dest);
d62a17ae 2906 afi = SUBGRP_AFI(subgrp);
2907 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2908 bgp = SUBGRP_INST(subgrp);
d62a17ae 2909 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2910 : NULL);
2911
2dbe669b
DA
2912 if (BGP_DEBUG(update, UPDATE_OUT))
2913 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2914
d62a17ae 2915 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2916 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2917 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2918 return;
d62a17ae 2919
6006b807 2920 memset(&attr, 0, sizeof(attr));
d62a17ae 2921 /* It's initialized in bgp_announce_check() */
2922
a77e2f4b
S
2923 /* Announcement to the subgroup. If the route is filtered withdraw it.
2924 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2925 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2926 * route
d62a17ae 2927 */
a77e2f4b
S
2928 advertise = bgp_check_advertise(bgp, dest);
2929
d62a17ae 2930 if (selected) {
7f7940e6 2931 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2932 NULL)) {
a77e2f4b
S
2933 /* Route is selected, if the route is already installed
2934 * in FIB, then it is advertised
2935 */
be785e35 2936 if (advertise) {
84ef27fc
DA
2937 if (!bgp_check_withdrawal(bgp, dest)) {
2938 struct attr *adv_attr =
2939 bgp_attr_intern(&attr);
2940
2941 bgp_adj_out_set_subgroup(dest, subgrp,
2942 adv_attr,
2943 selected);
2944 } else
be785e35
DS
2945 bgp_adj_out_unset_subgroup(
2946 dest, subgrp, 1, addpath_tx_id);
2947 }
a77e2f4b 2948 } else
9bcb3eef 2949 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2950 addpath_tx_id);
d62a17ae 2951 }
2952
2953 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2954 else {
9bcb3eef 2955 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2956 }
200df115 2957}
fee0f4c6 2958
3064bf43 2959/*
e1072051 2960 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2961 * This is called at the end of route processing.
3064bf43 2962 */
9bcb3eef 2963void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2964{
40381db7 2965 struct bgp_path_info *pi;
3064bf43 2966
9bcb3eef 2967 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2968 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2969 continue;
40381db7
DS
2970 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2971 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2972 }
3064bf43 2973}
2974
2975/*
2976 * Has the route changed from the RIB's perspective? This is invoked only
2977 * if the route selection returns the same best route as earlier - to
2978 * determine if we need to update zebra or not.
2979 */
9bcb3eef 2980bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2981{
4b7e6066 2982 struct bgp_path_info *mpinfo;
d62a17ae 2983
2bb9eff4
DS
2984 /* If this is multipath, check all selected paths for any nexthop
2985 * change or attribute change. Some attribute changes (e.g., community)
2986 * aren't of relevance to the RIB, but we'll update zebra to ensure
2987 * we handle the case of BGP nexthop change. This is the behavior
2988 * when the best path has an attribute change anyway.
d62a17ae 2989 */
1defdda8 2990 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2991 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2992 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2993 return true;
d62a17ae 2994
2bb9eff4
DS
2995 /*
2996 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2997 */
18ee8310
DS
2998 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2999 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3000 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3001 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3002 return true;
d62a17ae 3003 }
3064bf43 3004
d62a17ae 3005 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3006 return false;
3064bf43 3007}
3008
d62a17ae 3009struct bgp_process_queue {
3010 struct bgp *bgp;
9bcb3eef 3011 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3012#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3013 unsigned int flags;
3014 unsigned int queued;
200df115 3015};
3016
3b0c17e1 3017static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3018 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3019 struct bgp_path_info *new_select,
3020 struct bgp_path_info *old_select)
3021{
9bcb3eef 3022 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3023
3024 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3025 return;
3026
3027 if (advertise_type5_routes(bgp, afi) && new_select
3028 && is_route_injectable_into_evpn(new_select)) {
3029
3030 /* apply the route-map */
3031 if (bgp->adv_cmd_rmap[afi][safi].map) {
3032 route_map_result_t ret;
3033 struct bgp_path_info rmap_path;
3034 struct bgp_path_info_extra rmap_path_extra;
3035 struct attr dummy_attr;
3036
3037 dummy_attr = *new_select->attr;
3038
3039 /* Fill temp path_info */
9bcb3eef 3040 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3041 new_select, new_select->peer,
3042 &dummy_attr);
3043
3044 RESET_FLAG(dummy_attr.rmap_change_flags);
3045
3046 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3047 p, &rmap_path);
3b0c17e1 3048
3049 if (ret == RMAP_DENYMATCH) {
3050 bgp_attr_flush(&dummy_attr);
3051 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3052 safi);
3053 } else
3054 bgp_evpn_advertise_type5_route(
3055 bgp, p, &dummy_attr, afi, safi);
3056 } else {
3057 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3058 afi, safi);
3059 }
3060 } else if (advertise_type5_routes(bgp, afi) && old_select
3061 && is_route_injectable_into_evpn(old_select))
3062 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3063}
3064
bb2ca692
MS
3065/*
3066 * Utility to determine whether a particular path_info should use
3067 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3068 * in a path where we basically _know_ this is a BGP-LU route.
3069 */
3070static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3071{
3072 /* Certain types get imp null; so do paths where the nexthop is
3073 * not labeled.
3074 */
3075 if (new_select->sub_type == BGP_ROUTE_STATIC
3076 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3077 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3078 return true;
3079 else if (new_select->extra == NULL ||
3080 !bgp_is_valid_label(&new_select->extra->label[0]))
3081 /* TODO -- should be configurable? */
3082 return true;
3083 else
3084 return false;
3085}
3086
3103e8d2
DS
3087/*
3088 * old_select = The old best path
3089 * new_select = the new best path
3090 *
3091 * if (!old_select && new_select)
3092 * We are sending new information on.
3093 *
3094 * if (old_select && new_select) {
3095 * if (new_select != old_select)
3096 * We have a new best path send a change
3097 * else
3098 * We've received a update with new attributes that needs
3099 * to be passed on.
3100 * }
3101 *
3102 * if (old_select && !new_select)
3103 * We have no eligible route that we can announce or the rn
3104 * is being removed.
3105 */
9bcb3eef 3106static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3107 afi_t afi, safi_t safi)
d62a17ae 3108{
4b7e6066
DS
3109 struct bgp_path_info *new_select;
3110 struct bgp_path_info *old_select;
3111 struct bgp_path_info_pair old_and_new;
ddb5b488 3112 int debug = 0;
d62a17ae 3113
892fedb6 3114 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3115 if (dest)
3116 debug = bgp_debug_bestpath(dest);
b54892e0 3117 if (debug)
f4c713ae 3118 zlog_debug(
7fd8ca9a
DS
3119 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3120 __func__, dest, bgp->name_pretty);
f4c713ae
LB
3121 return;
3122 }
d62a17ae 3123 /* Is it end of initial update? (after startup) */
9bcb3eef 3124 if (!dest) {
e36f61b5
DS
3125 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3126 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3127
3128 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3129 FOREACH_AFI_SAFI (afi, safi) {
3130 if (bgp_fibupd_safi(safi))
3131 bgp_zebra_announce_table(bgp, afi, safi);
3132 }
d62a17ae 3133 bgp->main_peers_update_hold = 0;
3134
3135 bgp_start_routeadv(bgp);
aac24838 3136 return;
d62a17ae 3137 }
cb1faec9 3138
9bcb3eef 3139 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3140
9bcb3eef 3141 debug = bgp_debug_bestpath(dest);
b54892e0 3142 if (debug)
7fd8ca9a 3143 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
4378495a
DS
3144 dest, bgp->name_pretty, afi2str(afi),
3145 safi2str(safi));
ddb5b488 3146
f009ff26 3147 /* The best path calculation for the route is deferred if
3148 * BGP_NODE_SELECT_DEFER is set
3149 */
9bcb3eef 3150 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3151 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
3152 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3153 dest, bgp->name_pretty);
f009ff26 3154 return;
3155 }
3156
d62a17ae 3157 /* Best path selection. */
9bcb3eef 3158 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3159 afi, safi);
3160 old_select = old_and_new.old;
3161 new_select = old_and_new.new;
3162
3163 /* Do we need to allocate or free labels?
3164 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3165 * necessary to do this upon changes to best path. Exceptions:
3166 * - label index has changed -> recalculate resulting label
3167 * - path_info sub_type changed -> switch to/from implicit-null
3168 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3169 */
318cac96 3170 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3171 if (new_select) {
3172 if (!old_select
3173 || bgp_label_index_differs(new_select, old_select)
57592a53 3174 || new_select->sub_type != old_select->sub_type
9bcb3eef 3175 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3176 /* Enforced penultimate hop popping:
3177 * implicit-null for local routes, aggregate
3178 * and redistributed routes
3179 */
bb2ca692 3180 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3181 if (CHECK_FLAG(
9bcb3eef 3182 dest->flags,
992dd67e
PR
3183 BGP_NODE_REGISTERED_FOR_LABEL)
3184 || CHECK_FLAG(
3185 dest->flags,
3186 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3187 bgp_unregister_for_label(dest);
67f67ba4
DA
3188 dest->local_label = mpls_lse_encode(
3189 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3190 1);
9bcb3eef 3191 bgp_set_valid_label(&dest->local_label);
d62a17ae 3192 } else
9bcb3eef
DS
3193 bgp_register_for_label(dest,
3194 new_select);
d62a17ae 3195 }
9bcb3eef 3196 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3197 BGP_NODE_REGISTERED_FOR_LABEL)
3198 || CHECK_FLAG(dest->flags,
3199 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3200 bgp_unregister_for_label(dest);
318cac96 3201 }
992dd67e
PR
3202 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3203 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3204 bgp_unregister_for_label(dest);
d62a17ae 3205 }
cd1964ff 3206
b54892e0 3207 if (debug)
ddb5b488 3208 zlog_debug(
4378495a
DS
3209 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3210 __func__, dest, bgp->name_pretty, afi2str(afi),
3211 safi2str(safi), old_select, new_select);
ddb5b488 3212
d62a17ae 3213 /* If best route remains the same and this is not due to user-initiated
3214 * clear, see exactly what needs to be done.
3215 */
d62a17ae 3216 if (old_select && old_select == new_select
9bcb3eef 3217 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3218 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3219 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3220 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3221#ifdef ENABLE_BGP_VNC
d62a17ae 3222 vnc_import_bgp_add_route(bgp, p, old_select);
3223 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3224#endif
bb744275 3225 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3226 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3227
be785e35
DS
3228 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3229 && new_select->sub_type == BGP_ROUTE_NORMAL)
3230 SET_FLAG(dest->flags,
3231 BGP_NODE_FIB_INSTALL_PENDING);
3232
ddb5b488
PZ
3233 if (new_select->type == ZEBRA_ROUTE_BGP
3234 && (new_select->sub_type == BGP_ROUTE_NORMAL
3235 || new_select->sub_type
3236 == BGP_ROUTE_IMPORTED))
3237
9bcb3eef 3238 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3239 bgp, afi, safi);
3240 }
d62a17ae 3241 }
d62a17ae 3242
3243 /* If there is a change of interest to peers, reannounce the
3244 * route. */
1defdda8 3245 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3246 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3247 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3248 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3249
3250 /* unicast routes must also be annouced to
3251 * labeled-unicast update-groups */
3252 if (safi == SAFI_UNICAST)
3253 group_announce_route(bgp, afi,
9bcb3eef 3254 SAFI_LABELED_UNICAST, dest,
d62a17ae 3255 new_select);
3256
1defdda8 3257 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3258 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3259 }
fee0f4c6 3260
3b0c17e1 3261 /* advertise/withdraw type-5 routes */
3262 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3263 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3264 bgp_process_evpn_route_injection(
9bcb3eef 3265 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3266
b1875e65 3267 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3268 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3269 bgp_zebra_clear_route_change_flags(dest);
3270 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3271 return;
d62a17ae 3272 }
8ad7271d 3273
d62a17ae 3274 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3275 */
9bcb3eef 3276 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3277
3278 /* bestpath has changed; bump version */
3279 if (old_select || new_select) {
9bcb3eef 3280 bgp_bump_version(dest);
d62a17ae 3281
3282 if (!bgp->t_rmap_def_originate_eval) {
3283 bgp_lock(bgp);
907a2395 3284 event_add_timer(
d62a17ae 3285 bm->master,
3286 update_group_refresh_default_originate_route_map,
3287 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3288 &bgp->t_rmap_def_originate_eval);
3289 }
3290 }
3f9c7369 3291
d62a17ae 3292 if (old_select)
9bcb3eef 3293 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3294 if (new_select) {
ddb5b488
PZ
3295 if (debug)
3296 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3297 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3298 bgp_path_info_unset_flag(dest, new_select,
3299 BGP_PATH_ATTR_CHANGED);
1defdda8 3300 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3301 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3302 }
338b3424 3303
49e5a4a0 3304#ifdef ENABLE_BGP_VNC
d62a17ae 3305 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3306 if (old_select != new_select) {
3307 if (old_select) {
3308 vnc_import_bgp_exterior_del_route(bgp, p,
3309 old_select);
3310 vnc_import_bgp_del_route(bgp, p, old_select);
3311 }
3312 if (new_select) {
3313 vnc_import_bgp_exterior_add_route(bgp, p,
3314 new_select);
3315 vnc_import_bgp_add_route(bgp, p, new_select);
3316 }
3317 }
3318 }
65efcfce
LB
3319#endif
3320
9bcb3eef 3321 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3322
3323 /* unicast routes must also be annouced to labeled-unicast update-groups
3324 */
3325 if (safi == SAFI_UNICAST)
9bcb3eef 3326 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3327 new_select);
3328
3329 /* FIB update. */
3330 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3331 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3332
d62a17ae 3333 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3334 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3335 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3336 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3337
be785e35
DS
3338 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3339 SET_FLAG(dest->flags,
3340 BGP_NODE_FIB_INSTALL_PENDING);
3341
2b659f33
MK
3342 /* if this is an evpn imported type-5 prefix,
3343 * we need to withdraw the route first to clear
3344 * the nh neigh and the RMAC entry.
3345 */
3346 if (old_select &&
3347 is_route_parent_evpn(old_select))
3348 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3349
9bcb3eef 3350 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3351 } else {
d62a17ae 3352 /* Withdraw the route from the kernel. */
3353 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3354 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3355 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3356 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3357
568e10ca 3358 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3359 }
718e3744 3360 }
3064bf43 3361
9bcb3eef 3362 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3363 old_select);
5424b7ba 3364
d62a17ae 3365 /* Clear any route change flags. */
9bcb3eef 3366 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3367
18ee8310 3368 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3369 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3370 bgp_path_info_reap(dest, old_select);
d62a17ae 3371
9bcb3eef 3372 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3373 return;
718e3744 3374}
3375
f009ff26 3376/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3377void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3378{
9bcb3eef 3379 struct bgp_dest *dest;
f009ff26 3380 int cnt = 0;
3381 struct afi_safi_info *thread_info;
f009ff26 3382
56c226e7 3383 if (bgp->gr_info[afi][safi].t_route_select) {
e6685141 3384 struct event *t = bgp->gr_info[afi][safi].t_route_select;
56c226e7 3385
e16d030c 3386 thread_info = EVENT_ARG(t);
56c226e7 3387 XFREE(MTYPE_TMP, thread_info);
e16d030c 3388 EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3389 }
f009ff26 3390
3391 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3392 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3393 get_afi_safi_str(afi, safi, false),
26742171 3394 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3395 }
3396
3397 /* Process the route list */
6338d242 3398 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3399 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3400 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3401 dest = bgp_route_next(dest)) {
3402 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3403 continue;
3404
3405 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3406 bgp->gr_info[afi][safi].gr_deferred--;
3407 bgp_process_main_one(bgp, dest, afi, safi);
3408 cnt++;
067ea165
CB
3409 }
3410 /* If iteration stopped before the entire table was traversed then the
3411 * node needs to be unlocked.
3412 */
3413 if (dest) {
3414 bgp_dest_unlock_node(dest);
3415 dest = NULL;
f009ff26 3416 }
3417
9e3b51a7 3418 /* Send EOR message when all routes are processed */
6338d242 3419 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3420 bgp_send_delayed_eor(bgp);
8c48b3b6 3421 /* Send route processing complete message to RIB */
115ccb9a 3422 bgp_zebra_update(bgp, afi, safi,
36235319 3423 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3424 return;
9e3b51a7 3425 }
f009ff26 3426
3427 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3428
3429 thread_info->afi = afi;
3430 thread_info->safi = safi;
3431 thread_info->bgp = bgp;
3432
3433 /* If there are more routes to be processed, start the
3434 * selection timer
3435 */
907a2395 3436 event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
f009ff26 3437 BGP_ROUTE_SELECT_DELAY,
3438 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3439}
3440
aac24838 3441static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3442{
aac24838
JB
3443 struct bgp_process_queue *pqnode = data;
3444 struct bgp *bgp = pqnode->bgp;
d62a17ae 3445 struct bgp_table *table;
9bcb3eef 3446 struct bgp_dest *dest;
aac24838
JB
3447
3448 /* eoiu marker */
3449 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3450 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3451 /* should always have dedicated wq call */
3452 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3453 return WQ_SUCCESS;
3454 }
3455
ac021f40 3456 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3457 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3458 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3459 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3460 table = bgp_dest_table(dest);
3461 /* note, new DESTs may be added as part of processing */
3462 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3463
9bcb3eef 3464 bgp_dest_unlock_node(dest);
d62a17ae 3465 bgp_table_unlock(table);
3466 }
aac24838
JB
3467
3468 return WQ_SUCCESS;
3469}
3470
3471static void bgp_processq_del(struct work_queue *wq, void *data)
3472{
3473 struct bgp_process_queue *pqnode = data;
3474
3475 bgp_unlock(pqnode->bgp);
3476
3477 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3478}
3479
b6c386bb 3480void bgp_process_queue_init(struct bgp *bgp)
200df115 3481{
b6c386bb
DS
3482 if (!bgp->process_queue) {
3483 char name[BUFSIZ];
3484
3485 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3486 bgp->process_queue = work_queue_new(bm->master, name);
3487 }
3488
3489 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3490 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3491 bgp->process_queue->spec.max_retries = 0;
3492 bgp->process_queue->spec.hold = 50;
d62a17ae 3493 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3494 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3495}
3496
cfe8d15a 3497static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3498{
3499 struct bgp_process_queue *pqnode;
3500
a4d82a8a
PZ
3501 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3502 sizeof(struct bgp_process_queue));
aac24838
JB
3503
3504 /* unlocked in bgp_processq_del */
3505 pqnode->bgp = bgp_lock(bgp);
3506 STAILQ_INIT(&pqnode->pqueue);
3507
aac24838
JB
3508 return pqnode;
3509}
3510
9bcb3eef 3511void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3512{
aac24838 3513#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3514 struct work_queue *wq = bgp->process_queue;
d62a17ae 3515 struct bgp_process_queue *pqnode;
cfe8d15a 3516 int pqnode_reuse = 0;
495f0b13 3517
d62a17ae 3518 /* already scheduled for processing? */
9bcb3eef 3519 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3520 return;
2e02b9b2 3521
f009ff26 3522 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3523 * the workqueue
3524 */
9bcb3eef 3525 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3526 if (BGP_DEBUG(update, UPDATE_OUT))
3527 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3528 dest);
f009ff26 3529 return;
3530 }
3531
46aeabed
LS
3532 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3533 if (BGP_DEBUG(update, UPDATE_OUT))
3534 zlog_debug(
3535 "Soft reconfigure table in progress for route %p",
3536 dest);
3537 return;
3538 }
3539
aac24838 3540 if (wq == NULL)
d62a17ae 3541 return;
3542
aac24838 3543 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3544 limit only if is from the same BGP view and it's not an EOIU marker
3545 */
aac24838
JB
3546 if (work_queue_item_count(wq)) {
3547 struct work_queue_item *item = work_queue_last_item(wq);
3548 pqnode = item->data;
228da428 3549
a4d82a8a
PZ
3550 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3551 || pqnode->bgp != bgp
3552 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3553 pqnode = bgp_processq_alloc(bgp);
3554 else
3555 pqnode_reuse = 1;
aac24838 3556 } else
cfe8d15a 3557 pqnode = bgp_processq_alloc(bgp);
aac24838 3558 /* all unlocked in bgp_process_wq */
9bcb3eef 3559 bgp_table_lock(bgp_dest_table(dest));
aac24838 3560
9bcb3eef
DS
3561 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3562 bgp_dest_lock_node(dest);
aac24838 3563
60466a63 3564 /* can't be enqueued twice */
9bcb3eef
DS
3565 assert(STAILQ_NEXT(dest, pq) == NULL);
3566 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3567 pqnode->queued++;
3568
cfe8d15a
LB
3569 if (!pqnode_reuse)
3570 work_queue_add(wq, pqnode);
3571
d62a17ae 3572 return;
fee0f4c6 3573}
0a486e5f 3574
d62a17ae 3575void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3576{
d62a17ae 3577 struct bgp_process_queue *pqnode;
cb1faec9 3578
b6c386bb 3579 if (bgp->process_queue == NULL)
d62a17ae 3580 return;
2e02b9b2 3581
cfe8d15a 3582 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3583
aac24838 3584 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3585 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3586}
3587
e6685141 3588static void bgp_maximum_prefix_restart_timer(struct event *thread)
0a486e5f 3589{
d62a17ae 3590 struct peer *peer;
0a486e5f 3591
e16d030c 3592 peer = EVENT_ARG(thread);
d62a17ae 3593 peer->t_pmax_restart = NULL;
0a486e5f 3594
d62a17ae 3595 if (bgp_debug_neighbor_events(peer))
3596 zlog_debug(
3597 "%s Maximum-prefix restart timer expired, restore peering",
3598 peer->host);
0a486e5f 3599
a9bafa95 3600 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3601 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3602}
3603
9cbd06e0
DA
3604static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3605 safi_t safi)
3606{
3607 uint32_t count = 0;
f41b0459 3608 bool filtered = false;
9cbd06e0
DA
3609 struct bgp_dest *dest;
3610 struct bgp_adj_in *ain;
40bb2ccf 3611 struct attr attr = {};
9cbd06e0
DA
3612 struct bgp_table *table = peer->bgp->rib[afi][safi];
3613
3614 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3615 for (ain = dest->adj_in; ain; ain = ain->next) {
3616 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3617
3618 attr = *ain->attr;
9cbd06e0
DA
3619
3620 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3621 == FILTER_DENY)
f41b0459
DA
3622 filtered = true;
3623
3624 if (bgp_input_modifier(
3625 peer, rn_p, &attr, afi, safi,
3626 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3627 NULL, 0, NULL)
3628 == RMAP_DENY)
3629 filtered = true;
3630
3631 if (filtered)
9cbd06e0 3632 count++;
f41b0459 3633
d498917e 3634 bgp_attr_flush(&attr);
9cbd06e0
DA
3635 }
3636 }
3637
3638 return count;
3639}
3640
3dc339cd
DA
3641bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3642 int always)
718e3744 3643{
d62a17ae 3644 iana_afi_t pkt_afi;
5c525538 3645 iana_safi_t pkt_safi;
9cbd06e0
DA
3646 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3647 PEER_FLAG_MAX_PREFIX_FORCE))
3648 ? bgp_filtered_routes_count(peer, afi, safi)
3649 + peer->pcount[afi][safi]
3650 : peer->pcount[afi][safi];
9cabb64b 3651
d62a17ae 3652 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3653 return false;
e0701b79 3654
9cbd06e0 3655 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3656 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3657 PEER_STATUS_PREFIX_LIMIT)
3658 && !always)
3dc339cd 3659 return false;
e0701b79 3660
d62a17ae 3661 zlog_info(
f70c91dc
DA
3662 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3663 get_afi_safi_str(afi, safi, false), peer, pcount,
3664 peer->pmax[afi][safi]);
d62a17ae 3665 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3666
3667 if (CHECK_FLAG(peer->af_flags[afi][safi],
3668 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3669 return false;
d62a17ae 3670
3671 /* Convert AFI, SAFI to values for packet. */
3672 pkt_afi = afi_int2iana(afi);
3673 pkt_safi = safi_int2iana(safi);
3674 {
d7c0a89a 3675 uint8_t ndata[7];
d62a17ae 3676
3677 ndata[0] = (pkt_afi >> 8);
3678 ndata[1] = pkt_afi;
3679 ndata[2] = pkt_safi;
3680 ndata[3] = (peer->pmax[afi][safi] >> 24);
3681 ndata[4] = (peer->pmax[afi][safi] >> 16);
3682 ndata[5] = (peer->pmax[afi][safi] >> 8);
3683 ndata[6] = (peer->pmax[afi][safi]);
3684
3685 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3686 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3687 BGP_NOTIFY_CEASE_MAX_PREFIX,
3688 ndata, 7);
3689 }
3690
3691 /* Dynamic peers will just close their connection. */
3692 if (peer_dynamic_neighbor(peer))
3dc339cd 3693 return true;
d62a17ae 3694
3695 /* restart timer start */
3696 if (peer->pmax_restart[afi][safi]) {
3697 peer->v_pmax_restart =
3698 peer->pmax_restart[afi][safi] * 60;
3699
3700 if (bgp_debug_neighbor_events(peer))
3701 zlog_debug(
f70c91dc
DA
3702 "%pBP Maximum-prefix restart timer started for %d secs",
3703 peer, peer->v_pmax_restart);
d62a17ae 3704
3705 BGP_TIMER_ON(peer->t_pmax_restart,
3706 bgp_maximum_prefix_restart_timer,
3707 peer->v_pmax_restart);
3708 }
3709
3dc339cd 3710 return true;
d62a17ae 3711 } else
3712 UNSET_FLAG(peer->af_sflags[afi][safi],
3713 PEER_STATUS_PREFIX_LIMIT);
3714
b1823b69
DS
3715 if (pcount
3716 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3717 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3718 PEER_STATUS_PREFIX_THRESHOLD)
3719 && !always)
3dc339cd 3720 return false;
d62a17ae 3721
3722 zlog_info(
f70c91dc
DA
3723 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3724 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3725 peer->pmax[afi][safi]);
d62a17ae 3726 SET_FLAG(peer->af_sflags[afi][safi],
3727 PEER_STATUS_PREFIX_THRESHOLD);
3728 } else
3729 UNSET_FLAG(peer->af_sflags[afi][safi],
3730 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3731 return false;
718e3744 3732}
3733
b40d939b 3734/* Unconditionally remove the route from the RIB, without taking
3735 * damping into consideration (eg, because the session went down)
3736 */
9bcb3eef 3737void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3738 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3739{
f009ff26 3740
3741 struct bgp *bgp = NULL;
3742 bool delete_route = false;
3743
9bcb3eef
DS
3744 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3745 safi);
d62a17ae 3746
f009ff26 3747 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3748 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3749
f009ff26 3750 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3751 * flag
3752 */
3753 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3754 delete_route = true;
9bcb3eef 3755 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3756 delete_route = true;
f009ff26 3757 if (delete_route) {
9bcb3eef
DS
3758 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3759 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3760 bgp = pi->peer->bgp;
26742171 3761 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3762 }
3763 }
3764 }
4a11bf2c 3765
9bcb3eef
DS
3766 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3767 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3768}
3769
9bcb3eef 3770static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3771 struct peer *peer, afi_t afi, safi_t safi,
3772 struct prefix_rd *prd)
3773{
9bcb3eef 3774 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3775
d62a17ae 3776 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3777 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3778 */
b4f7f45b
IR
3779 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3780 && peer->sort == BGP_PEER_EBGP)
3781 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3782 == BGP_DAMP_SUPPRESSED) {
3783 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3784 safi);
3785 return;
d62a17ae 3786 }
3787
49e5a4a0 3788#ifdef ENABLE_BGP_VNC
d62a17ae 3789 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3790 struct bgp_dest *pdest = NULL;
d62a17ae 3791 struct bgp_table *table = NULL;
3792
9bcb3eef
DS
3793 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3794 (struct prefix *)prd);
3795 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3796 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3797
3798 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3799 peer->bgp, prd, table, p, pi);
d62a17ae 3800 }
9bcb3eef 3801 bgp_dest_unlock_node(pdest);
d62a17ae 3802 }
3803 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3804 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3805
b54892e0
DS
3806 vnc_import_bgp_del_route(peer->bgp, p, pi);
3807 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3808 }
65efcfce 3809 }
d62a17ae 3810#endif
128ea8ab 3811
d62a17ae 3812 /* If this is an EVPN route, process for un-import. */
3813 if (safi == SAFI_EVPN)
b54892e0 3814 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3815
9bcb3eef 3816 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3817}
3818
4b7e6066
DS
3819struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3820 struct peer *peer, struct attr *attr,
9bcb3eef 3821 struct bgp_dest *dest)
fb018d25 3822{
4b7e6066 3823 struct bgp_path_info *new;
fb018d25 3824
d62a17ae 3825 /* Make new BGP info. */
4b7e6066 3826 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3827 new->type = type;
3828 new->instance = instance;
3829 new->sub_type = sub_type;
3830 new->peer = peer;
3831 new->attr = attr;
083ec940 3832 new->uptime = monotime(NULL);
9bcb3eef 3833 new->net = dest;
d62a17ae 3834 return new;
fb018d25
DS
3835}
3836
c265ee22 3837/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3838bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3839 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3840 struct bgp_dest *dest)
d62a17ae 3841{
2dbe3fa9 3842 bool ret = false;
b099a5c8
DA
3843 bool is_bgp_static_route =
3844 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3845 : false;
d62a17ae 3846
e8442016
DS
3847 /*
3848 * Only validated for unicast and multicast currently.
3849 * Also valid for EVPN where the nexthop is an IP address.
3850 * If we are a bgp static route being checked then there is
3851 * no need to check to see if the nexthop is martian as
3852 * that it should be ok.
3853 */
3854 if (is_bgp_static_route ||
3855 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3856 return false;
d62a17ae 3857
3858 /* If NEXT_HOP is present, validate it. */
3859 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3860 if (attr->nexthop.s_addr == INADDR_ANY ||
3861 !ipv4_unicast_valid(&attr->nexthop) ||
3862 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3863 return true;
d62a17ae 3864 }
c265ee22 3865
d62a17ae 3866 /* If MP_NEXTHOP is present, validate it. */
3867 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3868 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3869 * it is not an IPv6 link-local address.
0355b41d
DA
3870 *
3871 * If we receive an UPDATE with nexthop length set to 32 bytes
3872 * we shouldn't discard an UPDATE if it's set to (::).
3873 * The link-local (2st) is validated along the code path later.
d62a17ae 3874 */
3875 if (attr->mp_nexthop_len) {
3876 switch (attr->mp_nexthop_len) {
3877 case BGP_ATTR_NHLEN_IPV4:
3878 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3879 ret = (attr->mp_nexthop_global_in.s_addr ==
3880 INADDR_ANY ||
3881 !ipv4_unicast_valid(
3882 &attr->mp_nexthop_global_in) ||
3883 bgp_nexthop_self(bgp, afi, type, stype, attr,
3884 dest));
d62a17ae 3885 break;
3886
3887 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3888 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3889 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3890 &attr->mp_nexthop_global)
d62a17ae 3891 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3892 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3893 &attr->mp_nexthop_global)
3894 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3895 dest));
d62a17ae 3896 break;
0355b41d
DA
3897 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3898 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3899 || IN6_IS_ADDR_MULTICAST(
3900 &attr->mp_nexthop_global)
3901 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3902 dest));
0355b41d 3903 break;
d62a17ae 3904
3905 default:
3dc339cd 3906 ret = true;
d62a17ae 3907 break;
3908 }
3909 }
c265ee22 3910
d62a17ae 3911 return ret;
3912}
3913
aade37d7 3914static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3915{
3916 struct community *old;
3917 struct community *new;
3918 struct community *merge;
aade37d7 3919 struct community *no_export;
2721dd61 3920
9a706b42 3921 old = bgp_attr_get_community(attr);
aade37d7 3922 no_export = community_str2com("no-export");
2721dd61 3923
b4efa101
DA
3924 assert(no_export);
3925
2721dd61 3926 if (old) {
aade37d7 3927 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3928
3929 if (!old->refcnt)
3930 community_free(&old);
3931
3932 new = community_uniq_sort(merge);
3933 community_free(&merge);
3934 } else {
aade37d7 3935 new = community_dup(no_export);
2721dd61
DA
3936 }
3937
aade37d7 3938 community_free(&no_export);
2721dd61 3939
9a706b42 3940 bgp_attr_set_community(attr, new);
2721dd61
DA
3941}
3942
46dbf9d0
DA
3943static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3944 struct attr *attr, const struct prefix *prefix,
3945 int *sub_type)
3946{
3947 struct listnode *node, *nnode;
3948 struct bgp *bgp;
3949 bool accept_own_found = false;
3950
3951 if (safi != SAFI_MPLS_VPN)
3952 return false;
3953
3954 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3955 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3956 return false;
3957
3958 /* The route in question carries the ACCEPT_OWN community */
3959 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3960 struct community *comm = bgp_attr_get_community(attr);
3961
3962 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3963 accept_own_found = true;
3964 }
3965
3966 /* The route in question is targeted to one or more destination VRFs
3967 * on the router (as determined by inspecting the Route Target(s)).
3968 */
3969 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3970 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3971 continue;
3972
3973 if (accept_own_found &&
3974 ecommunity_include(
3975 bgp->vpn_policy[afi]
3976 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3977 bgp_attr_get_ecommunity(attr))) {
3978 if (bgp_debug_update(peer, prefix, NULL, 1))
3979 zlog_debug(
3980 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3981 peer, prefix);
3982
3983 /* Treat this route as imported, because it's leaked
3984 * already from another VRF, and we got an updated
3985 * version from route-reflector with ACCEPT_OWN
3986 * community.
3987 */
3988 *sub_type = BGP_ROUTE_IMPORTED;
3989
3990 return true;
3991 }
3992 }
3993
3994 return false;
3995}
3996
367b458c
DS
3997void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3998 struct attr *attr, afi_t afi, safi_t safi, int type,
3999 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4000 uint32_t num_labels, int soft_reconfig,
4001 struct bgp_route_evpn *evpn)
d62a17ae 4002{
4003 int ret;
4004 int aspath_loop_count = 0;
9bcb3eef 4005 struct bgp_dest *dest;
d62a17ae 4006 struct bgp *bgp;
4007 struct attr new_attr;
4008 struct attr *attr_new;
40381db7 4009 struct bgp_path_info *pi;
819e6767 4010 struct bgp_path_info *new = NULL;
4b7e6066 4011 struct bgp_path_info_extra *extra;
d62a17ae 4012 const char *reason;
4013 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4014 int connected = 0;
4015 int do_loop_check = 1;
4016 int has_valid_label = 0;
7c312383 4017 afi_t nh_afi;
9146341f 4018 bool force_evpn_import = false;
907707db 4019 safi_t orig_safi = safi;
a486300b 4020 bool leak_success = true;
b2ac1d0d 4021 int allowas_in = 0;
949b0f24 4022
c7bb4f00 4023 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4024 char pfxprint[PREFIX2STR_BUFFER];
4025
4026 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4027 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4028 afi, safi, attr);
6401252f
QY
4029 }
4030
49e5a4a0 4031#ifdef ENABLE_BGP_VNC
d62a17ae 4032 int vnc_implicit_withdraw = 0;
65efcfce 4033#endif
d62a17ae 4034 int same_attr = 0;
f8745525 4035 const struct prefix *bgp_nht_param_prefix;
718e3744 4036
907707db
MS
4037 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4038 if (orig_safi == SAFI_LABELED_UNICAST)
4039 safi = SAFI_UNICAST;
4040
6006b807 4041 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4042 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4043 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4044
d62a17ae 4045 bgp = peer->bgp;
9bcb3eef 4046 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4047 /* TODO: Check to see if we can get rid of "is_valid_label" */
4048 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4049 has_valid_label = (num_labels > 0) ? 1 : 0;
4050 else
4051 has_valid_label = bgp_is_valid_label(label);
718e3744 4052
28f66de2
MS
4053 if (has_valid_label)
4054 assert(label != NULL);
4055
66ff6089
AD
4056 /* Update overlay index of the attribute */
4057 if (afi == AFI_L2VPN && evpn)
4058 memcpy(&attr->evpn_overlay, evpn,
4059 sizeof(struct bgp_route_evpn));
4060
d62a17ae 4061 /* When peer's soft reconfiguration enabled. Record input packet in
4062 Adj-RIBs-In. */
4063 if (!soft_reconfig
4064 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4065 && peer != bgp->peer_self)
9bcb3eef 4066 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4067
b2ac1d0d
MS
4068 /* Update permitted loop count */
4069 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4070 allowas_in = peer->allowas_in[afi][safi];
4071
d62a17ae 4072 /* Check previously received route. */
9bcb3eef 4073 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4074 if (pi->peer == peer && pi->type == type
4075 && pi->sub_type == sub_type
4076 && pi->addpath_rx_id == addpath_id)
d62a17ae 4077 break;
4078
4079 /* AS path local-as loop check. */
4080 if (peer->change_local_as) {
b2ac1d0d
MS
4081 if (allowas_in)
4082 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4083 else if (!CHECK_FLAG(peer->flags,
4084 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4085 aspath_loop_count = 1;
4086
4087 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4088 > aspath_loop_count) {
b4d46cc9 4089 peer->stat_pfx_aspath_loop++;
692174a1 4090 reason = "as-path contains our own AS;";
d62a17ae 4091 goto filtered;
4092 }
718e3744 4093 }
718e3744 4094
d62a17ae 4095 /* If the peer is configured for "allowas-in origin" and the last ASN in
4096 * the
4097 * as-path is our ASN then we do not need to call aspath_loop_check
4098 */
4099 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4100 if (aspath_get_last_as(attr->aspath) == bgp->as)
4101 do_loop_check = 0;
4102
f8745525
PG
4103 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4104 bgp_nht_param_prefix = NULL;
4105 else
4106 bgp_nht_param_prefix = p;
4107
d62a17ae 4108 /* AS path loop check. */
4109 if (do_loop_check) {
b0a8f709
FD
4110 if (aspath_loop_check(attr->aspath, bgp->as) >
4111 peer->allowas_in[afi][safi]) {
b4d46cc9 4112 peer->stat_pfx_aspath_loop++;
d62a17ae 4113 reason = "as-path contains our own AS;";
4114 goto filtered;
4115 }
4116 }
aac9ef6c 4117
b0a8f709
FD
4118 /* If we're a CONFED we need to loop check the CONFED ID too */
4119 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4120 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4121 peer->allowas_in[afi][safi]) {
4122 peer->stat_pfx_aspath_loop++;
4123 reason = "as-path contains our own confed AS;";
4124 goto filtered;
4125 }
4126
46dbf9d0
DA
4127 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4128 * enabled, then take care of that too.
4129 */
4130 bool accept_own = false;
4131
d62a17ae 4132 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4133 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4134 accept_own =
4135 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4136 if (!accept_own) {
4137 peer->stat_pfx_originator_loop++;
4138 reason = "originator is us;";
4139 goto filtered;
4140 }
d62a17ae 4141 }
718e3744 4142
d62a17ae 4143 /* Route reflector cluster ID check. */
4144 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4145 peer->stat_pfx_cluster_loop++;
d62a17ae 4146 reason = "reflected from the same cluster;";
4147 goto filtered;
4148 }
718e3744 4149
d62a17ae 4150 /* Apply incoming filter. */
907707db 4151 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4152 peer->stat_pfx_filter++;
d62a17ae 4153 reason = "filter;";
4154 goto filtered;
4155 }
718e3744 4156
a8b72dc6
DA
4157 /* RFC 8212 to prevent route leaks.
4158 * This specification intends to improve this situation by requiring the
4159 * explicit configuration of both BGP Import and Export Policies for any
4160 * External BGP (EBGP) session such as customers, peers, or
4161 * confederation boundaries for all enabled address families. Through
4162 * codification of the aforementioned requirement, operators will
4163 * benefit from consistent behavior across different BGP
4164 * implementations.
4165 */
1d3fdccf 4166 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4167 if (!bgp_inbound_policy_exists(peer,
4168 &peer->filter[afi][safi])) {
4169 reason = "inbound policy missing";
b17826b7
DS
4170 if (monotime_since(&bgp->ebgprequirespolicywarning,
4171 NULL) > FIFTEENMINUTE2USEC ||
4172 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4173 zlog_warn(
4174 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4175 monotime(&bgp->ebgprequirespolicywarning);
4176 }
a8b72dc6
DA
4177 goto filtered;
4178 }
4179
fb29348a
DA
4180 /* draft-ietf-idr-deprecate-as-set-confed-set
4181 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4182 * Eventually, This document (if approved) updates RFC 4271
4183 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4184 * and obsoletes RFC 6472.
4185 */
7f972cd8 4186 if (peer->bgp->reject_as_sets)
fb29348a
DA
4187 if (aspath_check_as_sets(attr->aspath)) {
4188 reason =
4189 "as-path contains AS_SET or AS_CONFED_SET type;";
4190 goto filtered;
4191 }
4192
6f4f49b2 4193 new_attr = *attr;
d62a17ae 4194
4195 /* Apply incoming route-map.
4196 * NB: new_attr may now contain newly allocated values from route-map
4197 * "set"
4198 * commands, so we need bgp_attr_flush in the error paths, until we
4199 * intern
4200 * the attr (which takes over the memory references) */
907707db 4201 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4202 num_labels, dest)
4203 == RMAP_DENY) {
b4d46cc9 4204 peer->stat_pfx_filter++;
d62a17ae 4205 reason = "route-map;";
4206 bgp_attr_flush(&new_attr);
4207 goto filtered;
4208 }
718e3744 4209
05864da7 4210 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4211 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4212 /* remove from RIB previous entry */
4213 bgp_zebra_withdraw(p, pi, bgp, safi);
4214 }
4215
7f323236
DW
4216 if (peer->sort == BGP_PEER_EBGP) {
4217
2721dd61
DA
4218 /* rfc7999:
4219 * A BGP speaker receiving an announcement tagged with the
4220 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4221 * NO_EXPORT community as defined in RFC1997, or a
4222 * similar community, to prevent propagation of the
4223 * prefix outside the local AS. The community to prevent
4224 * propagation SHOULD be chosen according to the operator's
4225 * routing policy.
4226 */
9a706b42
DA
4227 if (bgp_attr_get_community(&new_attr) &&
4228 community_include(bgp_attr_get_community(&new_attr),
4229 COMMUNITY_BLACKHOLE))
aade37d7 4230 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4231
a4d82a8a
PZ
4232 /* If we receive the graceful-shutdown community from an eBGP
4233 * peer we must lower local-preference */
9a706b42
DA
4234 if (bgp_attr_get_community(&new_attr) &&
4235 community_include(bgp_attr_get_community(&new_attr),
4236 COMMUNITY_GSHUT)) {
7f323236
DW
4237 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4238 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4239
4f770cf1
DA
4240 /* If graceful-shutdown is configured globally or
4241 * per neighbor, then add the GSHUT community to
4242 * all paths received from eBGP peers. */
4243 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4244 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4245 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4246 }
4247
d62a17ae 4248 /* next hop check. */
860ad3f9
DS
4249 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4250 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4251 &new_attr, dest)) {
b4d46cc9 4252 peer->stat_pfx_nh_invalid++;
d62a17ae 4253 reason = "martian or self next-hop;";
4254 bgp_attr_flush(&new_attr);
4255 goto filtered;
4256 }
718e3744 4257
5c14a191 4258 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4259 peer->stat_pfx_nh_invalid++;
4e802e66 4260 reason = "self mac;";
4dbf2038 4261 bgp_attr_flush(&new_attr);
4e802e66
DS
4262 goto filtered;
4263 }
4264
5a78f2bc
EB
4265 if (bgp_check_role_applicability(afi, safi) &&
4266 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4267 reason = "failing otc validation";
4268 bgp_attr_flush(&new_attr);
4269 goto filtered;
4270 }
a1b773e2
DS
4271 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4272 * condition :
4273 * Suppress fib is enabled
4274 * BGP_OPT_NO_FIB is not enabled
4275 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4276 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4277 */
4278 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4279 && (sub_type == BGP_ROUTE_NORMAL)
4280 && (!bgp_option_check(BGP_OPT_NO_FIB))
4281 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4282 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4283
01da2d26
DA
4284 /* If neighbor soo is configured, tag all incoming routes with
4285 * this SoO tag and then filter out advertisements in
4286 * subgroup_announce_check() if it matches the configured SoO
4287 * on the other peer.
4288 */
4289 if (peer->soo[afi][safi]) {
4290 struct ecommunity *old_ecomm =
4291 bgp_attr_get_ecommunity(&new_attr);
4292 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4293 struct ecommunity *new_ecomm;
4294
4295 if (old_ecomm) {
4296 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4297 ecomm_soo);
4298
4299 if (!old_ecomm->refcnt)
4300 ecommunity_free(&old_ecomm);
4301 } else {
4302 new_ecomm = ecommunity_dup(ecomm_soo);
4303 }
4304
4305 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4306 }
4307
4dbf2038 4308 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4309
d62a17ae 4310 /* If the update is implicit withdraw. */
40381db7 4311 if (pi) {
083ec940 4312 pi->uptime = monotime(NULL);
40381db7 4313 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4314
9bcb3eef 4315 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4316
d62a17ae 4317 /* Same attribute comes in. */
40381db7 4318 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4319 && same_attr
d62a17ae 4320 && (!has_valid_label
40381db7 4321 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4322 num_labels * sizeof(mpls_label_t))
66ff6089 4323 == 0)) {
b4f7f45b
IR
4324 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4325 BGP_CONFIG_DAMPENING)
d62a17ae 4326 && peer->sort == BGP_PEER_EBGP
40381db7 4327 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4328 if (bgp_debug_update(peer, p, NULL, 1)) {
4329 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4330 afi, safi, prd, p, label,
4331 num_labels, addpath_id ? 1 : 0,
66ff6089 4332 addpath_id, evpn, pfx_buf,
a4d82a8a 4333 sizeof(pfx_buf));
f70c91dc 4334 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4335 pfx_buf);
4336 }
4337
9bcb3eef 4338 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4339 != BGP_DAMP_SUPPRESSED) {
40381db7 4340 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4341 safi);
9bcb3eef 4342 bgp_process(bgp, dest, afi, safi);
d62a17ae 4343 }
4344 } else /* Duplicate - odd */
4345 {
4346 if (bgp_debug_update(peer, p, NULL, 1)) {
4347 if (!peer->rcvd_attr_printed) {
4348 zlog_debug(
f70c91dc
DA
4349 "%pBP rcvd UPDATE w/ attr: %s",
4350 peer,
d62a17ae 4351 peer->rcvd_attr_str);
4352 peer->rcvd_attr_printed = 1;
4353 }
4354
4355 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4356 afi, safi, prd, p, label,
4357 num_labels, addpath_id ? 1 : 0,
66ff6089 4358 addpath_id, evpn, pfx_buf,
a4d82a8a 4359 sizeof(pfx_buf));
d62a17ae 4360 zlog_debug(
f70c91dc
DA
4361 "%pBP rcvd %s...duplicate ignored",
4362 peer, pfx_buf);
d62a17ae 4363 }
4364
4365 /* graceful restart STALE flag unset. */
40381db7 4366 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4367 bgp_path_info_unset_flag(
9bcb3eef
DS
4368 dest, pi, BGP_PATH_STALE);
4369 bgp_dest_set_defer_flag(dest, false);
4370 bgp_process(bgp, dest, afi, safi);
d62a17ae 4371 }
4372 }
4373
9bcb3eef 4374 bgp_dest_unlock_node(dest);
d62a17ae 4375 bgp_attr_unintern(&attr_new);
4376
367b458c 4377 return;
d62a17ae 4378 }
718e3744 4379
d62a17ae 4380 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4381 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4382 if (bgp_debug_update(peer, p, NULL, 1)) {
4383 bgp_debug_rdpfxpath2str(
a4d82a8a 4384 afi, safi, prd, p, label, num_labels,
66ff6089 4385 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4386 pfx_buf, sizeof(pfx_buf));
d62a17ae 4387 zlog_debug(
f70c91dc
DA
4388 "%pBP rcvd %s, flapped quicker than processing",
4389 peer, pfx_buf);
d62a17ae 4390 }
4391
9bcb3eef 4392 bgp_path_info_restore(dest, pi);
9146341f 4393
4394 /*
4395 * If the BGP_PATH_REMOVED flag is set, then EVPN
4396 * routes would have been unimported already when a
4397 * prior BGP withdraw processing happened. Such routes
4398 * need to be imported again, so flag accordingly.
4399 */
4400 force_evpn_import = true;
704e189e 4401 } else {
4402 /* implicit withdraw, decrement aggregate and pcount
4403 * here. only if update is accepted, they'll increment
4404 * below.
4405 */
4406 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4407 }
718e3744 4408
d62a17ae 4409 /* Received Logging. */
4410 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4411 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4412 num_labels, addpath_id ? 1 : 0,
66ff6089 4413 addpath_id, evpn, pfx_buf,
a4d82a8a 4414 sizeof(pfx_buf));
f70c91dc 4415 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4416 }
718e3744 4417
d62a17ae 4418 /* graceful restart STALE flag unset. */
f009ff26 4419 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4420 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4421 bgp_dest_set_defer_flag(dest, false);
f009ff26 4422 }
d62a17ae 4423
4424 /* The attribute is changed. */
9bcb3eef 4425 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4426
d62a17ae 4427 /* Update bgp route dampening information. */
b4f7f45b 4428 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4429 && peer->sort == BGP_PEER_EBGP) {
4430 /* This is implicit withdraw so we should update
b4f7f45b
IR
4431 dampening
4432 information. */
40381db7 4433 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4434 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4435 }
49e5a4a0 4436#ifdef ENABLE_BGP_VNC
d62a17ae 4437 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4438 struct bgp_dest *pdest = NULL;
d62a17ae 4439 struct bgp_table *table = NULL;
4440
9bcb3eef
DS
4441 pdest = bgp_node_get(bgp->rib[afi][safi],
4442 (struct prefix *)prd);
4443 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4444 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4445
4446 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4447 bgp, prd, table, p, pi);
d62a17ae 4448 }
9bcb3eef 4449 bgp_dest_unlock_node(pdest);
d62a17ae 4450 }
4451 if ((afi == AFI_IP || afi == AFI_IP6)
4452 && (safi == SAFI_UNICAST)) {
40381db7 4453 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4454 /*
4455 * Implicit withdraw case.
4456 */
4457 ++vnc_implicit_withdraw;
40381db7
DS
4458 vnc_import_bgp_del_route(bgp, p, pi);
4459 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4460 }
4461 }
65efcfce 4462#endif
128ea8ab 4463
d62a17ae 4464 /* Special handling for EVPN update of an existing route. If the
4465 * extended community attribute has changed, we need to
4466 * un-import
4467 * the route using its existing extended community. It will be
4468 * subsequently processed for import with the new extended
4469 * community.
4470 */
6f8c9c11
PR
4471 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4472 && !same_attr) {
40381db7 4473 if ((pi->attr->flag
d62a17ae 4474 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4475 && (attr_new->flag
4476 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4477 int cmp;
4478
b53e67a3
DA
4479 cmp = ecommunity_cmp(
4480 bgp_attr_get_ecommunity(pi->attr),
4481 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4482 if (!cmp) {
4483 if (bgp_debug_update(peer, p, NULL, 1))
4484 zlog_debug(
4485 "Change in EXT-COMM, existing %s new %s",
4486 ecommunity_str(
b53e67a3
DA
4487 bgp_attr_get_ecommunity(
4488 pi->attr)),
d62a17ae 4489 ecommunity_str(
b53e67a3
DA
4490 bgp_attr_get_ecommunity(
4491 attr_new)));
6f8c9c11
PR
4492 if (safi == SAFI_EVPN)
4493 bgp_evpn_unimport_route(
4494 bgp, afi, safi, p, pi);
4495 else /* SAFI_MPLS_VPN */
1aa2c93e 4496 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4497 }
4498 }
4499 }
718e3744 4500
d62a17ae 4501 /* Update to new attribute. */
40381db7
DS
4502 bgp_attr_unintern(&pi->attr);
4503 pi->attr = attr_new;
d62a17ae 4504
4505 /* Update MPLS label */
4506 if (has_valid_label) {
40381db7 4507 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4508 if (extra->label != label) {
4509 memcpy(&extra->label, label,
dbd587da 4510 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4511 extra->num_labels = num_labels;
4512 }
b57ba6d2
MK
4513 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4514 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4515 }
718e3744 4516
e496b420
HS
4517 /* Update SRv6 SID */
4518 if (attr->srv6_l3vpn) {
4519 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4520 if (sid_diff(&extra->sid[0].sid,
4521 &attr->srv6_l3vpn->sid)) {
4522 sid_copy(&extra->sid[0].sid,
e496b420
HS
4523 &attr->srv6_l3vpn->sid);
4524 extra->num_sids = 1;
cc8f05df 4525
16f3db2d
RS
4526 extra->sid[0].loc_block_len = 0;
4527 extra->sid[0].loc_node_len = 0;
4528 extra->sid[0].func_len = 0;
4529 extra->sid[0].arg_len = 0;
ea7cd161
RS
4530 extra->sid[0].transposition_len = 0;
4531 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4532
4533 if (attr->srv6_l3vpn->loc_block_len != 0) {
4534 extra->sid[0].loc_block_len =
4535 attr->srv6_l3vpn->loc_block_len;
4536 extra->sid[0].loc_node_len =
4537 attr->srv6_l3vpn->loc_node_len;
4538 extra->sid[0].func_len =
4539 attr->srv6_l3vpn->func_len;
4540 extra->sid[0].arg_len =
4541 attr->srv6_l3vpn->arg_len;
ea7cd161 4542 extra->sid[0].transposition_len =
cc8f05df 4543 attr->srv6_l3vpn
ea7cd161
RS
4544 ->transposition_len;
4545 extra->sid[0].transposition_offset =
cc8f05df 4546 attr->srv6_l3vpn
ea7cd161
RS
4547 ->transposition_offset;
4548 }
e496b420
HS
4549 }
4550 } else if (attr->srv6_vpn) {
4551 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4552 if (sid_diff(&extra->sid[0].sid,
4553 &attr->srv6_vpn->sid)) {
4554 sid_copy(&extra->sid[0].sid,
4555 &attr->srv6_vpn->sid);
e496b420
HS
4556 extra->num_sids = 1;
4557 }
4558 }
4559
49e5a4a0 4560#ifdef ENABLE_BGP_VNC
d62a17ae 4561 if ((afi == AFI_IP || afi == AFI_IP6)
4562 && (safi == SAFI_UNICAST)) {
4563 if (vnc_implicit_withdraw) {
4564 /*
4565 * Add back the route with its new attributes
4566 * (e.g., nexthop).
4567 * The route is still selected, until the route
4568 * selection
4569 * queued by bgp_process actually runs. We have
4570 * to make this
4571 * update to the VNC side immediately to avoid
4572 * racing against
4573 * configuration changes (e.g., route-map
4574 * changes) which
4575 * trigger re-importation of the entire RIB.
4576 */
40381db7
DS
4577 vnc_import_bgp_add_route(bgp, p, pi);
4578 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4579 }
4580 }
65efcfce
LB
4581#endif
4582
d62a17ae 4583 /* Update bgp route dampening information. */
b4f7f45b 4584 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4585 && peer->sort == BGP_PEER_EBGP) {
4586 /* Now we do normal update dampening. */
9bcb3eef 4587 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4588 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4589 bgp_dest_unlock_node(dest);
367b458c 4590 return;
d62a17ae 4591 }
4592 }
128ea8ab 4593
d62a17ae 4594 /* Nexthop reachability check - for unicast and
4595 * labeled-unicast.. */
7c312383
AD
4596 if (((afi == AFI_IP || afi == AFI_IP6)
4597 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4598 || (safi == SAFI_EVPN &&
4599 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4600 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4601 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4602 && !CHECK_FLAG(peer->flags,
4603 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4604 && !CHECK_FLAG(bgp->flags,
4605 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4606 connected = 1;
4607 else
4608 connected = 0;
4609
960035b2
PZ
4610 struct bgp *bgp_nexthop = bgp;
4611
40381db7
DS
4612 if (pi->extra && pi->extra->bgp_orig)
4613 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4614
7c312383
AD
4615 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4616
4617 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4618 safi, pi, NULL, connected,
f8745525
PG
4619 bgp_nht_param_prefix) ||
4620 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4621 bgp_path_info_set_flag(dest, pi,
4622 BGP_PATH_VALID);
d62a17ae 4623 else {
4624 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4625 zlog_debug("%s(%pI4): NH unresolved",
4626 __func__,
4627 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4628 }
9bcb3eef 4629 bgp_path_info_unset_flag(dest, pi,
18ee8310 4630 BGP_PATH_VALID);
d62a17ae 4631 }
46dbf9d0
DA
4632 } else {
4633 if (accept_own)
4634 bgp_path_info_set_flag(dest, pi,
4635 BGP_PATH_ACCEPT_OWN);
4636
9bcb3eef 4637 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4638 }
d62a17ae 4639
49e5a4a0 4640#ifdef ENABLE_BGP_VNC
d62a17ae 4641 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4642 struct bgp_dest *pdest = NULL;
d62a17ae 4643 struct bgp_table *table = NULL;
4644
9bcb3eef
DS
4645 pdest = bgp_node_get(bgp->rib[afi][safi],
4646 (struct prefix *)prd);
4647 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4648 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4649
4650 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4651 bgp, prd, table, p, pi);
d62a17ae 4652 }
9bcb3eef 4653 bgp_dest_unlock_node(pdest);
d62a17ae 4654 }
4655#endif
718e3744 4656
d62a17ae 4657 /* If this is an EVPN route and some attribute has changed,
9146341f 4658 * or we are explicitly told to perform a route import, process
d62a17ae 4659 * route for import. If the extended community has changed, we
4660 * would
4661 * have done the un-import earlier and the import would result
4662 * in the
4663 * route getting injected into appropriate L2 VNIs. If it is
4664 * just
4665 * some other attribute change, the import will result in
4666 * updating
4667 * the attributes for the route in the VNI(s).
4668 */
9146341f 4669 if (safi == SAFI_EVPN &&
4670 (!same_attr || force_evpn_import) &&
7c312383 4671 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4672 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4673
4674 /* Process change. */
40381db7 4675 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4676
9bcb3eef
DS
4677 bgp_process(bgp, dest, afi, safi);
4678 bgp_dest_unlock_node(dest);
558d1fec 4679
ddb5b488
PZ
4680 if (SAFI_UNICAST == safi
4681 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4682 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4683
40381db7 4684 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4685 }
4686 if ((SAFI_MPLS_VPN == safi)
4687 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4688 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4689 }
4690
49e5a4a0 4691#ifdef ENABLE_BGP_VNC
d62a17ae 4692 if (SAFI_MPLS_VPN == safi) {
4693 mpls_label_t label_decoded = decode_label(label);
28070ee3 4694
d62a17ae 4695 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4696 type, sub_type, &label_decoded);
4697 }
4698 if (SAFI_ENCAP == safi) {
4699 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4700 type, sub_type, NULL);
4701 }
28070ee3 4702#endif
a486300b
PG
4703 if ((safi == SAFI_MPLS_VPN) &&
4704 !CHECK_FLAG(bgp->af_flags[afi][safi],
4705 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4706 !leak_success) {
4707 bgp_unlink_nexthop(pi);
4708 bgp_path_info_delete(dest, pi);
4709 }
367b458c 4710 return;
d62a17ae 4711 } // End of implicit withdraw
718e3744 4712
d62a17ae 4713 /* Received Logging. */
4714 if (bgp_debug_update(peer, p, NULL, 1)) {
4715 if (!peer->rcvd_attr_printed) {
f70c91dc 4716 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4717 peer->rcvd_attr_str);
4718 peer->rcvd_attr_printed = 1;
4719 }
718e3744 4720
a4d82a8a 4721 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4722 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4723 pfx_buf, sizeof(pfx_buf));
f70c91dc 4724 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4725 }
718e3744 4726
d62a17ae 4727 /* Make new BGP info. */
9bcb3eef 4728 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4729
d62a17ae 4730 /* Update MPLS label */
4731 if (has_valid_label) {
18ee8310 4732 extra = bgp_path_info_extra_get(new);
8ba71050 4733 if (extra->label != label) {
dbd587da
QY
4734 memcpy(&extra->label, label,
4735 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4736 extra->num_labels = num_labels;
4737 }
b57ba6d2
MK
4738 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4739 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4740 }
718e3744 4741
e496b420
HS
4742 /* Update SRv6 SID */
4743 if (safi == SAFI_MPLS_VPN) {
4744 extra = bgp_path_info_extra_get(new);
4745 if (attr->srv6_l3vpn) {
16f3db2d 4746 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4747 extra->num_sids = 1;
cc8f05df 4748
16f3db2d
RS
4749 extra->sid[0].loc_block_len =
4750 attr->srv6_l3vpn->loc_block_len;
4751 extra->sid[0].loc_node_len =
4752 attr->srv6_l3vpn->loc_node_len;
4753 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4754 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4755 extra->sid[0].transposition_len =
4756 attr->srv6_l3vpn->transposition_len;
4757 extra->sid[0].transposition_offset =
4758 attr->srv6_l3vpn->transposition_offset;
e496b420 4759 } else if (attr->srv6_vpn) {
16f3db2d 4760 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4761 extra->num_sids = 1;
4762 }
4763 }
4764
d62a17ae 4765 /* Nexthop reachability check. */
7c312383
AD
4766 if (((afi == AFI_IP || afi == AFI_IP6)
4767 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4768 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4769 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4770 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4771 && !CHECK_FLAG(peer->flags,
4772 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4773 && !CHECK_FLAG(bgp->flags,
4774 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4775 connected = 1;
4776 else
4777 connected = 0;
4778
7c312383
AD
4779 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4780
4053e952 4781 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4782 connected, bgp_nht_param_prefix) ||
4783 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4784 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4785 else {
07380148
DA
4786 if (BGP_DEBUG(nht, NHT))
4787 zlog_debug("%s(%pI4): NH unresolved", __func__,
4788 &attr_new->nexthop);
9bcb3eef 4789 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4790 }
46dbf9d0
DA
4791 } else {
4792 if (accept_own)
4793 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4794
9bcb3eef 4795 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4796 }
a82478b9 4797
b381ed97
DA
4798 /* If maximum prefix count is configured and current prefix
4799 * count exeed it.
4800 */
4801 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4802 reason = "maximum-prefix overflow";
4803 bgp_attr_flush(&new_attr);
b381ed97
DA
4804 goto filtered;
4805 }
4806
d62a17ae 4807 /* Addpath ID */
4808 new->addpath_rx_id = addpath_id;
4809
4810 /* Increment prefix */
4811 bgp_aggregate_increment(bgp, p, new, afi, safi);
4812
4813 /* Register new BGP information. */
9bcb3eef 4814 bgp_path_info_add(dest, new);
d62a17ae 4815
4816 /* route_node_get lock */
9bcb3eef 4817 bgp_dest_unlock_node(dest);
558d1fec 4818
49e5a4a0 4819#ifdef ENABLE_BGP_VNC
d62a17ae 4820 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4821 struct bgp_dest *pdest = NULL;
d62a17ae 4822 struct bgp_table *table = NULL;
4823
9bcb3eef
DS
4824 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4825 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4826 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4827
4828 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4829 bgp, prd, table, p, new);
4830 }
9bcb3eef 4831 bgp_dest_unlock_node(pdest);
d62a17ae 4832 }
65efcfce
LB
4833#endif
4834
d62a17ae 4835 /* If this is an EVPN route, process for import. */
7c312383 4836 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4837 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4838
9bcb3eef 4839 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4840
d62a17ae 4841 /* Process change. */
9bcb3eef 4842 bgp_process(bgp, dest, afi, safi);
718e3744 4843
ddb5b488
PZ
4844 if (SAFI_UNICAST == safi
4845 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4846 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4847 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4848 }
4849 if ((SAFI_MPLS_VPN == safi)
4850 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4851 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4852 }
49e5a4a0 4853#ifdef ENABLE_BGP_VNC
d62a17ae 4854 if (SAFI_MPLS_VPN == safi) {
4855 mpls_label_t label_decoded = decode_label(label);
28070ee3 4856
d62a17ae 4857 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4858 sub_type, &label_decoded);
4859 }
4860 if (SAFI_ENCAP == safi) {
4861 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4862 sub_type, NULL);
4863 }
28070ee3 4864#endif
a486300b
PG
4865 if ((safi == SAFI_MPLS_VPN) &&
4866 !CHECK_FLAG(bgp->af_flags[afi][safi],
4867 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4868 !leak_success) {
4869 bgp_unlink_nexthop(new);
4870 bgp_path_info_delete(dest, new);
4871 }
28070ee3 4872
367b458c 4873 return;
718e3744 4874
d62a17ae 4875/* This BGP update is filtered. Log the reason then update BGP
4876 entry. */
4877filtered:
819e6767
DA
4878 if (new) {
4879 bgp_unlink_nexthop(new);
4880 bgp_path_info_delete(dest, new);
4881 bgp_path_info_extra_free(&new->extra);
4882 XFREE(MTYPE_BGP_ROUTE, new);
4883 }
4884
9bcb3eef 4885 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4886
d62a17ae 4887 if (bgp_debug_update(peer, p, NULL, 1)) {
4888 if (!peer->rcvd_attr_printed) {
f70c91dc 4889 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4890 peer->rcvd_attr_str);
4891 peer->rcvd_attr_printed = 1;
4892 }
718e3744 4893
a4d82a8a 4894 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4895 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4896 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4897 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4898 peer, pfx_buf, reason);
d62a17ae 4899 }
128ea8ab 4900
40381db7 4901 if (pi) {
d62a17ae 4902 /* If this is an EVPN route, un-import it as it is now filtered.
4903 */
4904 if (safi == SAFI_EVPN)
40381db7 4905 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4906
ddb5b488
PZ
4907 if (SAFI_UNICAST == safi
4908 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4909 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4910
40381db7 4911 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4912 }
4913 if ((SAFI_MPLS_VPN == safi)
4914 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4915
1aa2c93e 4916 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4917 }
4918
9bcb3eef 4919 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4920 }
4921
9bcb3eef 4922 bgp_dest_unlock_node(dest);
558d1fec 4923
49e5a4a0 4924#ifdef ENABLE_BGP_VNC
d62a17ae 4925 /*
4926 * Filtered update is treated as an implicit withdrawal (see
4927 * bgp_rib_remove()
4928 * a few lines above)
4929 */
4930 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4931 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4932 0);
4933 }
97736e32
PZ
4934#endif
4935
367b458c 4936 return;
718e3744 4937}
4938
367b458c 4939void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4940 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4941 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4942 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4943{
d62a17ae 4944 struct bgp *bgp;
4945 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4946 struct bgp_dest *dest;
40381db7 4947 struct bgp_path_info *pi;
718e3744 4948
49e5a4a0 4949#ifdef ENABLE_BGP_VNC
d62a17ae 4950 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4951 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4952 0);
4953 }
28070ee3
PZ
4954#endif
4955
d62a17ae 4956 bgp = peer->bgp;
4957
4958 /* Lookup node. */
9bcb3eef 4959 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4960
4961 /* If peer is soft reconfiguration enabled. Record input packet for
4962 * further calculation.
4963 *
4964 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4965 * routes that are filtered. This tanks out Quagga RS pretty badly due
4966 * to
4967 * the iteration over all RS clients.
4968 * Since we need to remove the entry from adj_in anyway, do that first
4969 * and
4970 * if there was no entry, we don't need to do anything more.
4971 */
4972 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4973 && peer != bgp->peer_self)
9bcb3eef 4974 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4975 peer->stat_pfx_dup_withdraw++;
4976
d62a17ae 4977 if (bgp_debug_update(peer, p, NULL, 1)) {
4978 bgp_debug_rdpfxpath2str(
a4d82a8a 4979 afi, safi, prd, p, label, num_labels,
6c995628
AD
4980 addpath_id ? 1 : 0, addpath_id, NULL,
4981 pfx_buf, sizeof(pfx_buf));
d62a17ae 4982 zlog_debug(
4983 "%s withdrawing route %s not in adj-in",
4984 peer->host, pfx_buf);
4985 }
9bcb3eef 4986 bgp_dest_unlock_node(dest);
367b458c 4987 return;
d62a17ae 4988 }
cd808e74 4989
d62a17ae 4990 /* Lookup withdrawn route. */
9bcb3eef 4991 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4992 if (pi->peer == peer && pi->type == type
4993 && pi->sub_type == sub_type
4994 && pi->addpath_rx_id == addpath_id)
d62a17ae 4995 break;
4996
4997 /* Logging. */
4998 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4999 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5000 addpath_id ? 1 : 0, addpath_id, NULL,
5001 pfx_buf, sizeof(pfx_buf));
f70c91dc 5002 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 5003 pfx_buf);
5004 }
718e3744 5005
d62a17ae 5006 /* Withdraw specified route from routing table. */
40381db7 5007 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5008 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5009 if (SAFI_UNICAST == safi
5010 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5011 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5012 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5013 }
5014 if ((SAFI_MPLS_VPN == safi)
5015 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5016
1aa2c93e 5017 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
5018 }
5019 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5020 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5021 addpath_id ? 1 : 0, addpath_id, NULL,
5022 pfx_buf, sizeof(pfx_buf));
d62a17ae 5023 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5024 }
718e3744 5025
d62a17ae 5026 /* Unlock bgp_node_get() lock. */
9bcb3eef 5027 bgp_dest_unlock_node(dest);
d62a17ae 5028
367b458c 5029 return;
718e3744 5030}
6b0655a2 5031
d62a17ae 5032void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5033 int withdraw)
718e3744 5034{
d62a17ae 5035 struct update_subgroup *subgrp;
5036 subgrp = peer_subgroup(peer, afi, safi);
5037 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5038}
6182d65b 5039
718e3744 5040
3f9c7369
DS
5041/*
5042 * bgp_stop_announce_route_timer
5043 */
d62a17ae 5044void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5045{
d62a17ae 5046 if (!paf->t_announce_route)
5047 return;
5048
e16d030c 5049 EVENT_OFF(paf->t_announce_route);
718e3744 5050}
6b0655a2 5051
3f9c7369
DS
5052/*
5053 * bgp_announce_route_timer_expired
5054 *
5055 * Callback that is invoked when the route announcement timer for a
5056 * peer_af expires.
5057 */
e6685141 5058static void bgp_announce_route_timer_expired(struct event *t)
718e3744 5059{
d62a17ae 5060 struct peer_af *paf;
5061 struct peer *peer;
558d1fec 5062
e16d030c 5063 paf = EVENT_ARG(t);
d62a17ae 5064 peer = paf->peer;
718e3744 5065
feb17238 5066 if (!peer_established(peer))
cc9f21da 5067 return;
3f9c7369 5068
d62a17ae 5069 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5070 return;
3f9c7369 5071
d62a17ae 5072 peer_af_announce_route(paf, 1);
c5aec50b
MK
5073
5074 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5075 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5076}
5077
3f9c7369
DS
5078/*
5079 * bgp_announce_route
5080 *
5081 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5082 *
5083 * if force is true we will force an update even if the update
5084 * limiting code is attempted to kick in.
3f9c7369 5085 */
e1a32ec1 5086void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5087{
5088 struct peer_af *paf;
5089 struct update_subgroup *subgrp;
5090
5091 paf = peer_af_find(peer, afi, safi);
5092 if (!paf)
5093 return;
5094 subgrp = PAF_SUBGRP(paf);
5095
5096 /*
5097 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5098 * or a refresh has already been triggered.
5099 */
5100 if (!subgrp || paf->t_announce_route)
5101 return;
5102
e1a32ec1
DS
5103 if (force)
5104 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5105
d62a17ae 5106 /*
5107 * Start a timer to stagger/delay the announce. This serves
5108 * two purposes - announcement can potentially be combined for
5109 * multiple peers and the announcement doesn't happen in the
5110 * vty context.
5111 */
907a2395
DS
5112 event_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5113 (subgrp->peer_count == 1)
5114 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5115 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5116 &paf->t_announce_route);
3f9c7369
DS
5117}
5118
5119/*
5120 * Announce routes from all AF tables to a peer.
5121 *
5122 * This should ONLY be called when there is a need to refresh the
5123 * routes to the peer based on a policy change for this peer alone
5124 * or a route refresh request received from the peer.
5125 * The operation will result in splitting the peer from its existing
5126 * subgroups and putting it in new subgroups.
5127 */
d62a17ae 5128void bgp_announce_route_all(struct peer *peer)
718e3744 5129{
d62a17ae 5130 afi_t afi;
5131 safi_t safi;
5132
05c7a1cc 5133 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5134 bgp_announce_route(peer, afi, safi, false);
718e3744 5135}
6b0655a2 5136
46aeabed
LS
5137/* Flag or unflag bgp_dest to determine whether it should be treated by
5138 * bgp_soft_reconfig_table_task.
5139 * Flag if flag is true. Unflag if flag is false.
5140 */
5141static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5142{
5143 struct bgp_dest *dest;
5144 struct bgp_adj_in *ain;
5145
5146 if (!table)
5147 return;
5148
5149 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5150 for (ain = dest->adj_in; ain; ain = ain->next) {
5151 if (ain->peer != NULL)
5152 break;
5153 }
5154 if (flag && ain != NULL && ain->peer != NULL)
5155 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5156 else
5157 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5158 }
5159}
5160
367b458c
DS
5161static void bgp_soft_reconfig_table_update(struct peer *peer,
5162 struct bgp_dest *dest,
5163 struct bgp_adj_in *ain, afi_t afi,
5164 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5165{
5166 struct bgp_path_info *pi;
5167 uint32_t num_labels = 0;
5168 mpls_label_t *label_pnt = NULL;
5169 struct bgp_route_evpn evpn;
5170
5171 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5172 if (pi->peer == peer)
5173 break;
5174
5175 if (pi && pi->extra)
5176 num_labels = pi->extra->num_labels;
5177 if (num_labels)
5178 label_pnt = &pi->extra->label[0];
5179 if (pi)
5180 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5181 sizeof(evpn));
5182 else
5183 memset(&evpn, 0, sizeof(evpn));
5184
367b458c
DS
5185 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5186 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5187 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5188}
5189
d62a17ae 5190static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5191 struct bgp_table *table,
5192 struct prefix_rd *prd)
718e3744 5193{
9bcb3eef 5194 struct bgp_dest *dest;
d62a17ae 5195 struct bgp_adj_in *ain;
718e3744 5196
d62a17ae 5197 if (!table)
5198 table = peer->bgp->rib[afi][safi];
718e3744 5199
9bcb3eef
DS
5200 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5201 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5202 if (ain->peer != peer)
5203 continue;
8692c506 5204
367b458c
DS
5205 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5206 safi, prd);
d62a17ae 5207 }
718e3744 5208}
5209
46aeabed
LS
5210/* Do soft reconfig table per bgp table.
5211 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5212 * when BGP_NODE_SOFT_RECONFIG is set,
5213 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5214 * Schedule a new thread to continue the job.
5215 * Without splitting the full job into several part,
5216 * vtysh waits for the job to finish before responding to a BGP command
5217 */
e6685141 5218static void bgp_soft_reconfig_table_task(struct event *thread)
46aeabed
LS
5219{
5220 uint32_t iter, max_iter;
46aeabed
LS
5221 struct bgp_dest *dest;
5222 struct bgp_adj_in *ain;
5223 struct peer *peer;
5224 struct bgp_table *table;
5225 struct prefix_rd *prd;
5226 struct listnode *node, *nnode;
5227
e16d030c 5228 table = EVENT_ARG(thread);
46aeabed
LS
5229 prd = NULL;
5230
5231 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5232 if (table->soft_reconfig_init) {
5233 /* first call of the function with a new srta structure.
5234 * Don't do any treatment this time on nodes
5235 * in order vtysh to respond quickly
5236 */
5237 max_iter = 0;
5238 }
5239
5240 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5241 dest = bgp_route_next(dest)) {
5242 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5243 continue;
5244
5245 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5246
5247 for (ain = dest->adj_in; ain; ain = ain->next) {
5248 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5249 nnode, peer)) {
5250 if (ain->peer != peer)
5251 continue;
5252
367b458c 5253 bgp_soft_reconfig_table_update(
46aeabed
LS
5254 peer, dest, ain, table->afi,
5255 table->safi, prd);
5256 iter++;
46aeabed
LS
5257 }
5258 }
5259 }
5260
5261 /* we're either starting the initial iteration,
5262 * or we're going to continue an ongoing iteration
5263 */
5264 if (dest || table->soft_reconfig_init) {
5265 table->soft_reconfig_init = false;
907a2395
DS
5266 event_add_event(bm->master, bgp_soft_reconfig_table_task, table,
5267 0, &table->soft_reconfig_thread);
cc9f21da 5268 return;
46aeabed
LS
5269 }
5270 /* we're done, clean up the background iteration context info and
5271 schedule route annoucement
5272 */
5273 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5274 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5275 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5276 }
5277
5278 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5279}
5280
5281
5282/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5283 * and peer.
5284 * - bgp cannot be NULL
5285 * - if table and peer are NULL, cancel all threads within the bgp instance
5286 * - if table is NULL and peer is not,
5287 * remove peer in all threads within the bgp instance
5288 * - if peer is NULL, cancel all threads matching table within the bgp instance
5289 */
5290void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5291 const struct bgp_table *table,
5292 const struct peer *peer)
5293{
5294 struct peer *npeer;
5295 struct listnode *node, *nnode;
5296 int afi, safi;
5297 struct bgp_table *ntable;
5298
5299 if (!bgp)
5300 return;
5301
5302 FOREACH_AFI_SAFI (afi, safi) {
5303 ntable = bgp->rib[afi][safi];
5304 if (!ntable)
5305 continue;
5306 if (table && table != ntable)
5307 continue;
5308
5309 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5310 npeer)) {
5311 if (peer && peer != npeer)
5312 continue;
5313 listnode_delete(ntable->soft_reconfig_peers, npeer);
5314 }
5315
5316 if (!ntable->soft_reconfig_peers
5317 || !list_isempty(ntable->soft_reconfig_peers))
5318 continue;
5319
5320 list_delete(&ntable->soft_reconfig_peers);
5321 bgp_soft_reconfig_table_flag(ntable, false);
e16d030c 5322 EVENT_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5323 }
5324}
5325
89c73443
DS
5326/*
5327 * Returns false if the peer is not configured for soft reconfig in
5328 */
5329bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5330{
9bcb3eef 5331 struct bgp_dest *dest;
d62a17ae 5332 struct bgp_table *table;
46aeabed
LS
5333 struct listnode *node, *nnode;
5334 struct peer *npeer;
5335 struct peer_af *paf;
718e3744 5336
89c73443
DS
5337 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5338 return false;
718e3744 5339
d62a17ae 5340 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5341 && (safi != SAFI_EVPN)) {
5342 table = peer->bgp->rib[afi][safi];
5343 if (!table)
89c73443 5344 return true;
46aeabed
LS
5345
5346 table->soft_reconfig_init = true;
5347
5348 if (!table->soft_reconfig_peers)
5349 table->soft_reconfig_peers = list_new();
5350 npeer = NULL;
5351 /* add peer to the table soft_reconfig_peers if not already
5352 * there
5353 */
5354 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5355 npeer)) {
5356 if (peer == npeer)
5357 break;
5358 }
5359 if (peer != npeer)
5360 listnode_add(table->soft_reconfig_peers, peer);
5361
5362 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5363 * on table would start back at the beginning.
5364 */
5365 bgp_soft_reconfig_table_flag(table, true);
5366
5367 if (!table->soft_reconfig_thread)
907a2395
DS
5368 event_add_event(bm->master,
5369 bgp_soft_reconfig_table_task, table, 0,
5370 &table->soft_reconfig_thread);
46aeabed
LS
5371 /* Cancel bgp_announce_route_timer_expired threads.
5372 * bgp_announce_route_timer_expired threads have been scheduled
5373 * to announce routes as soon as the soft_reconfigure process
5374 * finishes.
5375 * In this case, soft_reconfigure is also scheduled by using
5376 * a thread but is planned after the
5377 * bgp_announce_route_timer_expired threads. It means that,
5378 * without cancelling the threads, the route announcement task
5379 * would run before the soft reconfiguration one. That would
5380 * useless and would block vtysh during several seconds. Route
5381 * announcements are rescheduled as soon as the soft_reconfigure
5382 * process finishes.
5383 */
5384 paf = peer_af_find(peer, afi, safi);
5385 if (paf)
5386 bgp_stop_announce_route_timer(paf);
5387 } else
9bcb3eef
DS
5388 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5389 dest = bgp_route_next(dest)) {
5390 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5391
b54892e0
DS
5392 if (table == NULL)
5393 continue;
8692c506 5394
9bcb3eef 5395 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5396 struct prefix_rd prd;
5397
5398 prd.family = AF_UNSPEC;
5399 prd.prefixlen = 64;
5400 memcpy(&prd.val, p->u.val, 8);
5401
5402 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5403 }
89c73443
DS
5404
5405 return true;
718e3744 5406}
6b0655a2 5407
228da428 5408
d62a17ae 5409struct bgp_clear_node_queue {
9bcb3eef 5410 struct bgp_dest *dest;
228da428
CC
5411};
5412
d62a17ae 5413static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5414{
d62a17ae 5415 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5416 struct bgp_dest *dest = cnq->dest;
d62a17ae 5417 struct peer *peer = wq->spec.data;
40381db7 5418 struct bgp_path_info *pi;
3103e8d2 5419 struct bgp *bgp;
9bcb3eef
DS
5420 afi_t afi = bgp_dest_table(dest)->afi;
5421 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5422
9bcb3eef 5423 assert(dest && peer);
3103e8d2 5424 bgp = peer->bgp;
d62a17ae 5425
5426 /* It is possible that we have multiple paths for a prefix from a peer
5427 * if that peer is using AddPath.
5428 */
9bcb3eef 5429 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5430 if (pi->peer != peer)
ea47320b
DL
5431 continue;
5432
5433 /* graceful restart STALE flag set. */
9af52ccf
DA
5434 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5435 && peer->nsf[afi][safi])
5436 || CHECK_FLAG(peer->af_sflags[afi][safi],
5437 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5438 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5439 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5440 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5441 else {
5442 /* If this is an EVPN route, process for
5443 * un-import. */
5444 if (safi == SAFI_EVPN)
9bcb3eef
DS
5445 bgp_evpn_unimport_route(
5446 bgp, afi, safi,
5447 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5448 /* Handle withdraw for VRF route-leaking and L3VPN */
5449 if (SAFI_UNICAST == safi
5450 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5451 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5452 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5453 bgp, pi);
960035b2 5454 }
3103e8d2 5455 if (SAFI_MPLS_VPN == safi &&
960035b2 5456 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5457 vpn_leak_to_vrf_withdraw(pi);
960035b2 5458 }
3103e8d2 5459
9bcb3eef 5460 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5461 }
ea47320b 5462 }
d62a17ae 5463 return WQ_SUCCESS;
200df115 5464}
5465
d62a17ae 5466static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5467{
d62a17ae 5468 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5469 struct bgp_dest *dest = cnq->dest;
5470 struct bgp_table *table = bgp_dest_table(dest);
228da428 5471
9bcb3eef 5472 bgp_dest_unlock_node(dest);
d62a17ae 5473 bgp_table_unlock(table);
5474 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5475}
5476
d62a17ae 5477static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5478{
d62a17ae 5479 struct peer *peer = wq->spec.data;
64e580a7 5480
d62a17ae 5481 /* Tickle FSM to start moving again */
5482 BGP_EVENT_ADD(peer, Clearing_Completed);
5483
5484 peer_unlock(peer); /* bgp_clear_route */
200df115 5485}
718e3744 5486
d62a17ae 5487static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5488{
d62a17ae 5489 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5490
5491 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5492#undef CLEAR_QUEUE_NAME_LEN
5493
0ce1ca80 5494 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5495 peer->clear_node_queue->spec.hold = 10;
5496 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5497 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5498 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5499 peer->clear_node_queue->spec.max_retries = 0;
5500
5501 /* we only 'lock' this peer reference when the queue is actually active
5502 */
5503 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5504}
5505
d62a17ae 5506static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5507 struct bgp_table *table)
65ca75e0 5508{
9bcb3eef 5509 struct bgp_dest *dest;
b6c386bb 5510 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5511
d62a17ae 5512 if (!table)
5513 table = peer->bgp->rib[afi][safi];
dc83d712 5514
d62a17ae 5515 /* If still no table => afi/safi isn't configured at all or smth. */
5516 if (!table)
5517 return;
dc83d712 5518
9bcb3eef 5519 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5520 struct bgp_path_info *pi, *next;
d62a17ae 5521 struct bgp_adj_in *ain;
5522 struct bgp_adj_in *ain_next;
5523
5524 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5525 * queued for every clearing peer, regardless of whether it is
5526 * relevant to the peer at hand.
5527 *
5528 * Overview: There are 3 different indices which need to be
5529 * scrubbed, potentially, when a peer is removed:
5530 *
5531 * 1 peer's routes visible via the RIB (ie accepted routes)
5532 * 2 peer's routes visible by the (optional) peer's adj-in index
5533 * 3 other routes visible by the peer's adj-out index
5534 *
5535 * 3 there is no hurry in scrubbing, once the struct peer is
5536 * removed from bgp->peer, we could just GC such deleted peer's
5537 * adj-outs at our leisure.
5538 *
5539 * 1 and 2 must be 'scrubbed' in some way, at least made
5540 * invisible via RIB index before peer session is allowed to be
5541 * brought back up. So one needs to know when such a 'search' is
5542 * complete.
5543 *
5544 * Ideally:
5545 *
5546 * - there'd be a single global queue or a single RIB walker
5547 * - rather than tracking which route_nodes still need to be
5548 * examined on a peer basis, we'd track which peers still
5549 * aren't cleared
5550 *
5551 * Given that our per-peer prefix-counts now should be reliable,
5552 * this may actually be achievable. It doesn't seem to be a huge
5553 * problem at this time,
5554 *
5555 * It is possible that we have multiple paths for a prefix from
5556 * a peer
5557 * if that peer is using AddPath.
5558 */
9bcb3eef 5559 ain = dest->adj_in;
d62a17ae 5560 while (ain) {
5561 ain_next = ain->next;
5562
6a840fd9 5563 if (ain->peer == peer)
9bcb3eef 5564 bgp_adj_in_remove(dest, ain);
d62a17ae 5565
5566 ain = ain_next;
5567 }
5568
9bcb3eef 5569 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5570 next = pi->next;
5571 if (pi->peer != peer)
d62a17ae 5572 continue;
5573
5574 if (force)
9bcb3eef 5575 bgp_path_info_reap(dest, pi);
d62a17ae 5576 else {
5577 struct bgp_clear_node_queue *cnq;
5578
5579 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5580 bgp_table_lock(bgp_dest_table(dest));
5581 bgp_dest_lock_node(dest);
d62a17ae 5582 cnq = XCALLOC(
5583 MTYPE_BGP_CLEAR_NODE_QUEUE,
5584 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5585 cnq->dest = dest;
d62a17ae 5586 work_queue_add(peer->clear_node_queue, cnq);
5587 break;
5588 }
5589 }
5590 }
5591 return;
5592}
5593
5594void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5595{
9bcb3eef 5596 struct bgp_dest *dest;
d62a17ae 5597 struct bgp_table *table;
5598
5599 if (peer->clear_node_queue == NULL)
5600 bgp_clear_node_queue_init(peer);
5601
5602 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5603 * Idle until it receives a Clearing_Completed event. This protects
5604 * against peers which flap faster than we can we clear, which could
5605 * lead to:
5606 *
5607 * a) race with routes from the new session being installed before
5608 * clear_route_node visits the node (to delete the route of that
5609 * peer)
5610 * b) resource exhaustion, clear_route_node likely leads to an entry
5611 * on the process_main queue. Fast-flapping could cause that queue
5612 * to grow and grow.
5613 */
5614
5615 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5616 * the unlock will happen upon work-queue completion; other wise, the
5617 * unlock happens at the end of this function.
5618 */
5619 if (!peer->clear_node_queue->thread)
5620 peer_lock(peer);
5621
5622 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5623 bgp_clear_route_table(peer, afi, safi, NULL);
5624 else
9bcb3eef
DS
5625 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5626 dest = bgp_route_next(dest)) {
5627 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5628 if (!table)
5629 continue;
5630
5631 bgp_clear_route_table(peer, afi, safi, table);
5632 }
d62a17ae 5633
5634 /* unlock if no nodes got added to the clear-node-queue. */
5635 if (!peer->clear_node_queue->thread)
5636 peer_unlock(peer);
718e3744 5637}
d62a17ae 5638
5639void bgp_clear_route_all(struct peer *peer)
718e3744 5640{
d62a17ae 5641 afi_t afi;
5642 safi_t safi;
718e3744 5643
05c7a1cc
QY
5644 FOREACH_AFI_SAFI (afi, safi)
5645 bgp_clear_route(peer, afi, safi);
65efcfce 5646
49e5a4a0 5647#ifdef ENABLE_BGP_VNC
d62a17ae 5648 rfapiProcessPeerDown(peer);
65efcfce 5649#endif
718e3744 5650}
5651
d62a17ae 5652void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5653{
d62a17ae 5654 struct bgp_table *table;
9bcb3eef 5655 struct bgp_dest *dest;
d62a17ae 5656 struct bgp_adj_in *ain;
5657 struct bgp_adj_in *ain_next;
718e3744 5658
d62a17ae 5659 table = peer->bgp->rib[afi][safi];
718e3744 5660
d62a17ae 5661 /* It is possible that we have multiple paths for a prefix from a peer
5662 * if that peer is using AddPath.
5663 */
9bcb3eef
DS
5664 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5665 ain = dest->adj_in;
43143c8f 5666
d62a17ae 5667 while (ain) {
5668 ain_next = ain->next;
43143c8f 5669
6a840fd9 5670 if (ain->peer == peer)
9bcb3eef 5671 bgp_adj_in_remove(dest, ain);
43143c8f 5672
d62a17ae 5673 ain = ain_next;
5674 }
5675 }
718e3744 5676}
93406d87 5677
1479ed2f
DA
5678/* If any of the routes from the peer have been marked with the NO_LLGR
5679 * community, either as sent by the peer, or as the result of a configured
5680 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5681 * operation of [RFC4271].
5682 */
d62a17ae 5683void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5684{
9bcb3eef 5685 struct bgp_dest *dest;
40381db7 5686 struct bgp_path_info *pi;
d62a17ae 5687 struct bgp_table *table;
5688
9af52ccf 5689 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5690 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5691 dest = bgp_route_next(dest)) {
5692 struct bgp_dest *rm;
d62a17ae 5693
5694 /* look for neighbor in tables */
9bcb3eef 5695 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5696 if (!table)
ea47320b
DL
5697 continue;
5698
5699 for (rm = bgp_table_top(table); rm;
5700 rm = bgp_route_next(rm))
9bcb3eef 5701 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5702 pi = pi->next) {
40381db7 5703 if (pi->peer != peer)
ea47320b 5704 continue;
1479ed2f
DA
5705 if (CHECK_FLAG(
5706 peer->af_sflags[afi][safi],
5707 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5708 bgp_attr_get_community(pi->attr) &&
1479ed2f 5709 !community_include(
9a706b42
DA
5710 bgp_attr_get_community(
5711 pi->attr),
1479ed2f 5712 COMMUNITY_NO_LLGR))
e3015d91 5713 continue;
40381db7 5714 if (!CHECK_FLAG(pi->flags,
1defdda8 5715 BGP_PATH_STALE))
e3015d91 5716 continue;
ea47320b 5717
641065d4
KM
5718 /*
5719 * If this is VRF leaked route
5720 * process for withdraw.
5721 */
5722 if (pi->sub_type ==
5723 BGP_ROUTE_IMPORTED &&
5724 peer->bgp->inst_type ==
5725 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5726 vpn_leak_to_vrf_withdraw(pi);
641065d4 5727
40381db7 5728 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5729 break;
5730 }
d62a17ae 5731 }
5732 } else {
9bcb3eef
DS
5733 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5734 dest = bgp_route_next(dest))
5735 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5736 pi = pi->next) {
40381db7 5737 if (pi->peer != peer)
ea47320b 5738 continue;
1479ed2f
DA
5739 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5740 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5741 bgp_attr_get_community(pi->attr) &&
5742 !community_include(
5743 bgp_attr_get_community(pi->attr),
5744 COMMUNITY_NO_LLGR))
e3015d91 5745 continue;
40381db7 5746 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5747 continue;
641065d4
KM
5748 if (safi == SAFI_UNICAST &&
5749 (peer->bgp->inst_type ==
5750 BGP_INSTANCE_TYPE_VRF ||
5751 peer->bgp->inst_type ==
5752 BGP_INSTANCE_TYPE_DEFAULT))
5753 vpn_leak_from_vrf_withdraw(
5754 bgp_get_default(), peer->bgp,
5755 pi);
5756
9bcb3eef 5757 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5758 break;
5759 }
d62a17ae 5760 }
93406d87 5761}
6b0655a2 5762
9af52ccf
DA
5763void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5764{
5765 struct bgp_dest *dest, *ndest;
5766 struct bgp_path_info *pi;
5767 struct bgp_table *table;
5768
5769 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5770 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5771 dest = bgp_route_next(dest)) {
5772 table = bgp_dest_get_bgp_table_info(dest);
5773 if (!table)
5774 continue;
5775
5776 for (ndest = bgp_table_top(table); ndest;
5777 ndest = bgp_route_next(ndest)) {
5778 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5779 pi = pi->next) {
5780 if (pi->peer != peer)
5781 continue;
5782
5783 if ((CHECK_FLAG(
5784 peer->af_sflags[afi][safi],
5785 PEER_STATUS_ENHANCED_REFRESH))
5786 && !CHECK_FLAG(pi->flags,
5787 BGP_PATH_STALE)
5788 && !CHECK_FLAG(
5789 pi->flags,
5790 BGP_PATH_UNUSEABLE)) {
5791 if (bgp_debug_neighbor_events(
5792 peer))
5793 zlog_debug(
58e111f6
DA
5794 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5795 peer,
9af52ccf
DA
5796 afi2str(afi),
5797 safi2str(safi),
5798 bgp_dest_get_prefix(
5799 ndest));
5800
5801 bgp_path_info_set_flag(
5802 ndest, pi,
5803 BGP_PATH_STALE);
5804 }
5805 }
5806 }
5807 }
5808 } else {
5809 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5810 dest = bgp_route_next(dest)) {
5811 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5812 pi = pi->next) {
5813 if (pi->peer != peer)
5814 continue;
5815
5816 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5817 PEER_STATUS_ENHANCED_REFRESH))
5818 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5819 && !CHECK_FLAG(pi->flags,
5820 BGP_PATH_UNUSEABLE)) {
5821 if (bgp_debug_neighbor_events(peer))
5822 zlog_debug(
58e111f6
DA
5823 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5824 peer, afi2str(afi),
9af52ccf
DA
5825 safi2str(safi),
5826 bgp_dest_get_prefix(
5827 dest));
5828
5829 bgp_path_info_set_flag(dest, pi,
5830 BGP_PATH_STALE);
5831 }
5832 }
5833 }
5834 }
5835}
5836
3dc339cd 5837bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5838{
e0df4c04 5839 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5840 return true;
e0df4c04 5841
9dac9fc8
DA
5842 if (peer->sort == BGP_PEER_EBGP
5843 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5844 || FILTER_LIST_OUT_NAME(filter)
5845 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5846 return true;
5847 return false;
9dac9fc8
DA
5848}
5849
3dc339cd 5850bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5851{
e0df4c04 5852 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5853 return true;
e0df4c04 5854
9dac9fc8
DA
5855 if (peer->sort == BGP_PEER_EBGP
5856 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5857 || FILTER_LIST_IN_NAME(filter)
5858 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5859 return true;
5860 return false;
9dac9fc8
DA
5861}
5862
568e10ca 5863static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5864 safi_t safi)
bb86c601 5865{
9bcb3eef 5866 struct bgp_dest *dest;
40381db7 5867 struct bgp_path_info *pi;
4b7e6066 5868 struct bgp_path_info *next;
bb86c601 5869
9bcb3eef
DS
5870 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5871 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5872 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5873
40381db7 5874 next = pi->next;
1b7bb747
CS
5875
5876 /* Unimport EVPN routes from VRFs */
5877 if (safi == SAFI_EVPN)
5878 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5879 SAFI_EVPN, p, pi);
1b7bb747 5880
40381db7
DS
5881 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5882 && pi->type == ZEBRA_ROUTE_BGP
5883 && (pi->sub_type == BGP_ROUTE_NORMAL
5884 || pi->sub_type == BGP_ROUTE_AGGREGATE
5885 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5886
d62a17ae 5887 if (bgp_fibupd_safi(safi))
b54892e0 5888 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5889 }
9514b37d 5890
9bcb3eef 5891 bgp_path_info_reap(dest, pi);
d62a17ae 5892 }
bb86c601
LB
5893}
5894
718e3744 5895/* Delete all kernel routes. */
d62a17ae 5896void bgp_cleanup_routes(struct bgp *bgp)
5897{
5898 afi_t afi;
9bcb3eef 5899 struct bgp_dest *dest;
67009e22 5900 struct bgp_table *table;
d62a17ae 5901
5902 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5903 if (afi == AFI_L2VPN)
5904 continue;
568e10ca 5905 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5906 SAFI_UNICAST);
d62a17ae 5907 /*
5908 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5909 */
5910 if (afi != AFI_L2VPN) {
5911 safi_t safi;
5912 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5913 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5914 dest = bgp_route_next(dest)) {
5915 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5916 if (table != NULL) {
5917 bgp_cleanup_table(bgp, table, safi);
5918 bgp_table_finish(&table);
9bcb3eef
DS
5919 bgp_dest_set_bgp_table_info(dest, NULL);
5920 bgp_dest_unlock_node(dest);
d62a17ae 5921 }
5922 }
5923 safi = SAFI_ENCAP;
9bcb3eef
DS
5924 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5925 dest = bgp_route_next(dest)) {
5926 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5927 if (table != NULL) {
5928 bgp_cleanup_table(bgp, table, safi);
5929 bgp_table_finish(&table);
9bcb3eef
DS
5930 bgp_dest_set_bgp_table_info(dest, NULL);
5931 bgp_dest_unlock_node(dest);
d62a17ae 5932 }
5933 }
5934 }
5935 }
9bcb3eef
DS
5936 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5937 dest = bgp_route_next(dest)) {
5938 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5939 if (table != NULL) {
5940 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5941 bgp_table_finish(&table);
9bcb3eef
DS
5942 bgp_dest_set_bgp_table_info(dest, NULL);
5943 bgp_dest_unlock_node(dest);
d62a17ae 5944 }
bb86c601 5945 }
718e3744 5946}
5947
d62a17ae 5948void bgp_reset(void)
718e3744 5949{
d62a17ae 5950 vty_reset();
5951 bgp_zclient_reset();
5952 access_list_reset();
5953 prefix_list_reset();
718e3744 5954}
6b0655a2 5955
be92fc9f 5956bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5957{
d62a17ae 5958 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5959 && CHECK_FLAG(peer->af_cap[afi][safi],
5960 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5961}
5962
718e3744 5963/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5964 value. */
d62a17ae 5965int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5966 struct bgp_nlri *packet)
5967{
d7c0a89a
QY
5968 uint8_t *pnt;
5969 uint8_t *lim;
d62a17ae 5970 struct prefix p;
5971 int psize;
d62a17ae 5972 afi_t afi;
5973 safi_t safi;
be92fc9f 5974 bool addpath_capable;
d7c0a89a 5975 uint32_t addpath_id;
d62a17ae 5976
d62a17ae 5977 pnt = packet->nlri;
5978 lim = pnt + packet->length;
5979 afi = packet->afi;
5980 safi = packet->safi;
5981 addpath_id = 0;
be92fc9f 5982 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5983
5984 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5985 syntactic validity. If the field is syntactically incorrect,
5986 then the Error Subcode is set to Invalid Network Field. */
5987 for (; pnt < lim; pnt += psize) {
5988 /* Clear prefix structure. */
6006b807 5989 memset(&p, 0, sizeof(p));
d62a17ae 5990
be92fc9f 5991 if (addpath_capable) {
d62a17ae 5992
5993 /* When packet overflow occurs return immediately. */
761ed665 5994 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5995 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5996
a3a850a1 5997 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5998 addpath_id = ntohl(addpath_id);
d62a17ae 5999 pnt += BGP_ADDPATH_ID_LEN;
6000 }
718e3744 6001
d62a17ae 6002 /* Fetch prefix length. */
6003 p.prefixlen = *pnt++;
6004 /* afi/safi validity already verified by caller,
6005 * bgp_update_receive */
6006 p.family = afi2family(afi);
6007
6008 /* Prefix length check. */
6009 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6010 flog_err(
e50f7cfd 6011 EC_BGP_UPDATE_RCV,
14454c9f 6012 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6013 peer->host, p.prefixlen, packet->afi);
513386b5 6014 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6015 }
6b0655a2 6016
d62a17ae 6017 /* Packet size overflow check. */
6018 psize = PSIZE(p.prefixlen);
6019
6020 /* When packet overflow occur return immediately. */
6021 if (pnt + psize > lim) {
af4c2728 6022 flog_err(
e50f7cfd 6023 EC_BGP_UPDATE_RCV,
d62a17ae 6024 "%s [Error] Update packet error (prefix length %d overflows packet)",
6025 peer->host, p.prefixlen);
513386b5 6026 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6027 }
6028
6029 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6030 * prefix for the v4 and v6 afi's and unicast/multicast */
6031 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6032 flog_err(
e50f7cfd 6033 EC_BGP_UPDATE_RCV,
d62a17ae 6034 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6035 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6036 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6037 }
6038
6039 /* Fetch prefix from NLRI packet. */
a85297a7 6040 memcpy(p.u.val, pnt, psize);
d62a17ae 6041
6042 /* Check address. */
6043 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6044 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6045 /* From RFC4271 Section 6.3:
6046 *
6047 * If a prefix in the NLRI field is semantically
6048 * incorrect
6049 * (e.g., an unexpected multicast IP address),
6050 * an error SHOULD
6051 * be logged locally, and the prefix SHOULD be
6052 * ignored.
a4d82a8a 6053 */
af4c2728 6054 flog_err(
e50f7cfd 6055 EC_BGP_UPDATE_RCV,
23d0a753
DA
6056 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6057 peer->host, &p.u.prefix4);
d62a17ae 6058 continue;
6059 }
6060 }
6061
6062 /* Check address. */
6063 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6064 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6065 flog_err(
e50f7cfd 6066 EC_BGP_UPDATE_RCV,
c0d72166
DS
6067 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6068 peer->host, &p.u.prefix6);
d62a17ae 6069
6070 continue;
6071 }
6072 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6073 flog_err(
e50f7cfd 6074 EC_BGP_UPDATE_RCV,
c0d72166
DS
6075 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6076 peer->host, &p.u.prefix6);
d62a17ae 6077
6078 continue;
6079 }
6080 }
6081
6082 /* Normal process. */
6083 if (attr)
367b458c
DS
6084 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6085 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6086 NULL, 0, 0, NULL);
d62a17ae 6087 else
bf0c6163 6088 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6089 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6090 NULL, 0, NULL);
d62a17ae 6091
513386b5
DA
6092 /* Do not send BGP notification twice when maximum-prefix count
6093 * overflow. */
6094 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6095 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6096 }
6097
6098 /* Packet length consistency check. */
6099 if (pnt != lim) {
af4c2728 6100 flog_err(
e50f7cfd 6101 EC_BGP_UPDATE_RCV,
d62a17ae 6102 "%s [Error] Update packet error (prefix length mismatch with total length)",
6103 peer->host);
513386b5 6104 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6105 }
6b0655a2 6106
513386b5 6107 return BGP_NLRI_PARSE_OK;
718e3744 6108}
6109
d62a17ae 6110static struct bgp_static *bgp_static_new(void)
718e3744 6111{
d62a17ae 6112 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6113}
6114
d62a17ae 6115static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6116{
0a22ddfb 6117 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6118 route_map_counter_decrement(bgp_static->rmap.map);
6119
c1aa9e7f
PG
6120 if (bgp_static->prd_pretty)
6121 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6122 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6123 XFREE(MTYPE_BGP_STATIC, bgp_static);
6124}
6125
5f040085 6126void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6127 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6128{
9bcb3eef 6129 struct bgp_dest *dest;
40381db7 6130 struct bgp_path_info *pi;
4b7e6066 6131 struct bgp_path_info *new;
40381db7 6132 struct bgp_path_info rmap_path;
d62a17ae 6133 struct attr attr;
6134 struct attr *attr_new;
b68885f9 6135 route_map_result_t ret;
49e5a4a0 6136#ifdef ENABLE_BGP_VNC
d62a17ae 6137 int vnc_implicit_withdraw = 0;
65efcfce 6138#endif
fee0f4c6 6139
d62a17ae 6140 assert(bgp_static);
dd8103a9 6141
9bcb3eef 6142 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6143
0f05ea43 6144 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6145
d62a17ae 6146 attr.nexthop = bgp_static->igpnexthop;
6147 attr.med = bgp_static->igpmetric;
6148 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6149
7226bc40
TA
6150 if (afi == AFI_IP)
6151 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6152
97a52c82
DA
6153 if (bgp_static->igpmetric)
6154 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6155
d62a17ae 6156 if (bgp_static->atomic)
6157 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6158
d62a17ae 6159 /* Store label index, if required. */
6160 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6161 attr.label_index = bgp_static->label_index;
6162 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6163 }
718e3744 6164
d62a17ae 6165 /* Apply route-map. */
6166 if (bgp_static->rmap.name) {
6167 struct attr attr_tmp = attr;
80ced710 6168
6006b807 6169 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6170 rmap_path.peer = bgp->peer_self;
6171 rmap_path.attr = &attr_tmp;
fee0f4c6 6172
d62a17ae 6173 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6174
1782514f 6175 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6176
d62a17ae 6177 bgp->peer_self->rmap_type = 0;
718e3744 6178
d62a17ae 6179 if (ret == RMAP_DENYMATCH) {
6180 /* Free uninterned attribute. */
6181 bgp_attr_flush(&attr_tmp);
718e3744 6182
d62a17ae 6183 /* Unintern original. */
6184 aspath_unintern(&attr.aspath);
6185 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6186 bgp_dest_unlock_node(dest);
d62a17ae 6187 return;
6188 }
7f323236 6189
637e5ba4 6190 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6191 bgp_attr_add_gshut_community(&attr_tmp);
6192
d62a17ae 6193 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6194 } else {
6195
637e5ba4 6196 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6197 bgp_attr_add_gshut_community(&attr);
6198
d62a17ae 6199 attr_new = bgp_attr_intern(&attr);
7f323236 6200 }
718e3744 6201
9bcb3eef 6202 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6203 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6204 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6205 break;
6206
40381db7
DS
6207 if (pi) {
6208 if (attrhash_cmp(pi->attr, attr_new)
6209 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6210 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6211 bgp_dest_unlock_node(dest);
d62a17ae 6212 bgp_attr_unintern(&attr_new);
6213 aspath_unintern(&attr.aspath);
6214 return;
6215 } else {
6216 /* The attribute is changed. */
9bcb3eef 6217 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6218
6219 /* Rewrite BGP route information. */
40381db7 6220 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6221 bgp_path_info_restore(dest, pi);
d62a17ae 6222 else
40381db7 6223 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6224#ifdef ENABLE_BGP_VNC
d62a17ae 6225 if ((afi == AFI_IP || afi == AFI_IP6)
6226 && (safi == SAFI_UNICAST)) {
40381db7 6227 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6228 /*
6229 * Implicit withdraw case.
40381db7 6230 * We have to do this before pi is
d62a17ae 6231 * changed
6232 */
6233 ++vnc_implicit_withdraw;
40381db7 6234 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6235 vnc_import_bgp_exterior_del_route(
40381db7 6236 bgp, p, pi);
d62a17ae 6237 }
6238 }
65efcfce 6239#endif
40381db7
DS
6240 bgp_attr_unintern(&pi->attr);
6241 pi->attr = attr_new;
083ec940 6242 pi->uptime = monotime(NULL);
49e5a4a0 6243#ifdef ENABLE_BGP_VNC
d62a17ae 6244 if ((afi == AFI_IP || afi == AFI_IP6)
6245 && (safi == SAFI_UNICAST)) {
6246 if (vnc_implicit_withdraw) {
40381db7 6247 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6248 vnc_import_bgp_exterior_add_route(
40381db7 6249 bgp, p, pi);
d62a17ae 6250 }
6251 }
65efcfce 6252#endif
718e3744 6253
d62a17ae 6254 /* Nexthop reachability check. */
892fedb6 6255 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6256 && (safi == SAFI_UNICAST
6257 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6258
6259 struct bgp *bgp_nexthop = bgp;
6260
40381db7
DS
6261 if (pi->extra && pi->extra->bgp_orig)
6262 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6263
6264 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6265 afi, safi, pi, NULL,
654a5978 6266 0, p))
9bcb3eef 6267 bgp_path_info_set_flag(dest, pi,
18ee8310 6268 BGP_PATH_VALID);
d62a17ae 6269 else {
6270 if (BGP_DEBUG(nht, NHT)) {
6271 char buf1[INET6_ADDRSTRLEN];
6272 inet_ntop(p->family,
6273 &p->u.prefix, buf1,
07380148 6274 sizeof(buf1));
d62a17ae 6275 zlog_debug(
6276 "%s(%s): Route not in table, not advertising",
15569c58 6277 __func__, buf1);
d62a17ae 6278 }
18ee8310 6279 bgp_path_info_unset_flag(
9bcb3eef 6280 dest, pi, BGP_PATH_VALID);
d62a17ae 6281 }
6282 } else {
6283 /* Delete the NHT structure if any, if we're
6284 * toggling between
6285 * enabling/disabling import check. We
6286 * deregister the route
6287 * from NHT to avoid overloading NHT and the
6288 * process interaction
6289 */
40381db7 6290 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6291 bgp_path_info_set_flag(dest, pi,
6292 BGP_PATH_VALID);
d62a17ae 6293 }
6294 /* Process change. */
40381db7 6295 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6296 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6297
6298 if (SAFI_UNICAST == safi
6299 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6300 || bgp->inst_type
6301 == BGP_INSTANCE_TYPE_DEFAULT)) {
6302 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6303 pi);
ddb5b488
PZ
6304 }
6305
9bcb3eef 6306 bgp_dest_unlock_node(dest);
d62a17ae 6307 aspath_unintern(&attr.aspath);
6308 return;
6309 }
718e3744 6310 }
718e3744 6311
d62a17ae 6312 /* Make new BGP info. */
6313 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6314 attr_new, dest);
d62a17ae 6315 /* Nexthop reachability check. */
892fedb6 6316 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6317 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6318 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6319 p))
9bcb3eef 6320 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6321 else {
6322 if (BGP_DEBUG(nht, NHT)) {
6323 char buf1[INET6_ADDRSTRLEN];
07380148 6324
d62a17ae 6325 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6326 sizeof(buf1));
d62a17ae 6327 zlog_debug(
6328 "%s(%s): Route not in table, not advertising",
15569c58 6329 __func__, buf1);
d62a17ae 6330 }
9bcb3eef 6331 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6332 }
6333 } else {
6334 /* Delete the NHT structure if any, if we're toggling between
6335 * enabling/disabling import check. We deregister the route
6336 * from NHT to avoid overloading NHT and the process interaction
6337 */
6338 bgp_unlink_nexthop(new);
6339
9bcb3eef 6340 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6341 }
078430f6 6342
d62a17ae 6343 /* Aggregate address increment. */
6344 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6345
d62a17ae 6346 /* Register new BGP information. */
9bcb3eef 6347 bgp_path_info_add(dest, new);
718e3744 6348
d62a17ae 6349 /* route_node_get lock */
9bcb3eef 6350 bgp_dest_unlock_node(dest);
d62a17ae 6351
6352 /* Process change. */
9bcb3eef 6353 bgp_process(bgp, dest, afi, safi);
d62a17ae 6354
ddb5b488
PZ
6355 if (SAFI_UNICAST == safi
6356 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6357 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6358 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6359 }
6360
d62a17ae 6361 /* Unintern original. */
6362 aspath_unintern(&attr.aspath);
718e3744 6363}
6364
5f040085 6365void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6366 safi_t safi)
718e3744 6367{
9bcb3eef 6368 struct bgp_dest *dest;
40381db7 6369 struct bgp_path_info *pi;
718e3744 6370
9bcb3eef 6371 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6372
d62a17ae 6373 /* Check selected route and self inserted route. */
9bcb3eef 6374 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6375 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6376 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6377 break;
6378
6379 /* Withdraw static BGP route from routing table. */
40381db7 6380 if (pi) {
ddb5b488
PZ
6381 if (SAFI_UNICAST == safi
6382 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6383 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6384 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6385 }
40381db7
DS
6386 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6387 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6388 bgp_path_info_delete(dest, pi);
6389 bgp_process(bgp, dest, afi, safi);
d62a17ae 6390 }
718e3744 6391
d62a17ae 6392 /* Unlock bgp_node_lookup. */
9bcb3eef 6393 bgp_dest_unlock_node(dest);
718e3744 6394}
6395
137446f9
LB
6396/*
6397 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6398 */
5f040085 6399static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6400 afi_t afi, safi_t safi,
6401 struct prefix_rd *prd)
718e3744 6402{
9bcb3eef 6403 struct bgp_dest *dest;
40381db7 6404 struct bgp_path_info *pi;
718e3744 6405
9bcb3eef 6406 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6407
d62a17ae 6408 /* Check selected route and self inserted route. */
9bcb3eef 6409 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6410 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6411 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6412 break;
718e3744 6413
d62a17ae 6414 /* Withdraw static BGP route from routing table. */
40381db7 6415 if (pi) {
49e5a4a0 6416#ifdef ENABLE_BGP_VNC
d62a17ae 6417 rfapiProcessWithdraw(
40381db7 6418 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6419 1); /* Kill, since it is an administrative change */
65efcfce 6420#endif
ddb5b488
PZ
6421 if (SAFI_MPLS_VPN == safi
6422 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6423 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6424 }
40381db7 6425 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6426 bgp_path_info_delete(dest, pi);
6427 bgp_process(bgp, dest, afi, safi);
d62a17ae 6428 }
718e3744 6429
d62a17ae 6430 /* Unlock bgp_node_lookup. */
9bcb3eef 6431 bgp_dest_unlock_node(dest);
718e3744 6432}
6433
5f040085 6434static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6435 struct bgp_static *bgp_static, afi_t afi,
6436 safi_t safi)
137446f9 6437{
9bcb3eef 6438 struct bgp_dest *dest;
4b7e6066 6439 struct bgp_path_info *new;
d62a17ae 6440 struct attr *attr_new;
6441 struct attr attr = {0};
40381db7 6442 struct bgp_path_info *pi;
49e5a4a0 6443#ifdef ENABLE_BGP_VNC
d62a17ae 6444 mpls_label_t label = 0;
65efcfce 6445#endif
d7c0a89a 6446 uint32_t num_labels = 0;
137446f9 6447
d62a17ae 6448 assert(bgp_static);
137446f9 6449
b57ba6d2
MK
6450 if (bgp_static->label != MPLS_INVALID_LABEL)
6451 num_labels = 1;
9bcb3eef
DS
6452 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6453 &bgp_static->prd);
137446f9 6454
0f05ea43 6455 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6456
d62a17ae 6457 attr.nexthop = bgp_static->igpnexthop;
6458 attr.med = bgp_static->igpmetric;
6459 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6460
d62a17ae 6461 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6462 || (safi == SAFI_ENCAP)) {
6463 if (afi == AFI_IP) {
6464 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6465 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6466 }
6467 }
6468 if (afi == AFI_L2VPN) {
b04c1e99
IR
6469 if (bgp_static->gatewayIp.family == AF_INET) {
6470 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6471 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6472 &bgp_static->gatewayIp.u.prefix4,
6473 IPV4_MAX_BYTELEN);
b04c1e99
IR
6474 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6475 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6476 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6477 &bgp_static->gatewayIp.u.prefix6,
6478 IPV6_MAX_BYTELEN);
b04c1e99 6479 }
0a50c248 6480 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6481 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6482 struct bgp_encap_type_vxlan bet;
6006b807 6483 memset(&bet, 0, sizeof(bet));
3714a385 6484 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6485 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6486 }
6487 if (bgp_static->router_mac) {
6488 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6489 }
6490 }
6491 /* Apply route-map. */
6492 if (bgp_static->rmap.name) {
6493 struct attr attr_tmp = attr;
40381db7 6494 struct bgp_path_info rmap_path;
b68885f9 6495 route_map_result_t ret;
137446f9 6496
40381db7
DS
6497 rmap_path.peer = bgp->peer_self;
6498 rmap_path.attr = &attr_tmp;
137446f9 6499
d62a17ae 6500 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6501
1782514f 6502 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6503
d62a17ae 6504 bgp->peer_self->rmap_type = 0;
137446f9 6505
d62a17ae 6506 if (ret == RMAP_DENYMATCH) {
6507 /* Free uninterned attribute. */
6508 bgp_attr_flush(&attr_tmp);
137446f9 6509
d62a17ae 6510 /* Unintern original. */
6511 aspath_unintern(&attr.aspath);
6512 bgp_static_withdraw_safi(bgp, p, afi, safi,
6513 &bgp_static->prd);
bbc52106 6514 bgp_dest_unlock_node(dest);
d62a17ae 6515 return;
6516 }
137446f9 6517
d62a17ae 6518 attr_new = bgp_attr_intern(&attr_tmp);
6519 } else {
6520 attr_new = bgp_attr_intern(&attr);
6521 }
137446f9 6522
9bcb3eef 6523 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6524 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6525 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6526 break;
6527
40381db7 6528 if (pi) {
40381db7 6529 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6530 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6531 bgp_dest_unlock_node(dest);
d62a17ae 6532 bgp_attr_unintern(&attr_new);
6533 aspath_unintern(&attr.aspath);
6534 return;
6535 } else {
6536 /* The attribute is changed. */
9bcb3eef 6537 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6538
6539 /* Rewrite BGP route information. */
40381db7 6540 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6541 bgp_path_info_restore(dest, pi);
d62a17ae 6542 else
40381db7
DS
6543 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6544 bgp_attr_unintern(&pi->attr);
6545 pi->attr = attr_new;
083ec940 6546 pi->uptime = monotime(NULL);
49e5a4a0 6547#ifdef ENABLE_BGP_VNC
40381db7
DS
6548 if (pi->extra)
6549 label = decode_label(&pi->extra->label[0]);
65efcfce 6550#endif
137446f9 6551
d62a17ae 6552 /* Process change. */
40381db7 6553 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6554 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6555
6556 if (SAFI_MPLS_VPN == safi
6557 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6558 vpn_leak_to_vrf_update(bgp, pi,
6559 &bgp_static->prd);
ddb5b488 6560 }
49e5a4a0 6561#ifdef ENABLE_BGP_VNC
40381db7
DS
6562 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6563 pi->attr, afi, safi, pi->type,
6564 pi->sub_type, &label);
65efcfce 6565#endif
9bcb3eef 6566 bgp_dest_unlock_node(dest);
d62a17ae 6567 aspath_unintern(&attr.aspath);
6568 return;
6569 }
6570 }
137446f9
LB
6571
6572
d62a17ae 6573 /* Make new BGP info. */
6574 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6575 attr_new, dest);
1defdda8 6576 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6577 bgp_path_info_extra_get(new);
b57ba6d2
MK
6578 if (num_labels) {
6579 new->extra->label[0] = bgp_static->label;
6580 new->extra->num_labels = num_labels;
6581 }
49e5a4a0 6582#ifdef ENABLE_BGP_VNC
d62a17ae 6583 label = decode_label(&bgp_static->label);
65efcfce 6584#endif
137446f9 6585
d62a17ae 6586 /* Aggregate address increment. */
6587 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6588
d62a17ae 6589 /* Register new BGP information. */
9bcb3eef 6590 bgp_path_info_add(dest, new);
d62a17ae 6591 /* route_node_get lock */
9bcb3eef 6592 bgp_dest_unlock_node(dest);
137446f9 6593
d62a17ae 6594 /* Process change. */
9bcb3eef 6595 bgp_process(bgp, dest, afi, safi);
137446f9 6596
ddb5b488
PZ
6597 if (SAFI_MPLS_VPN == safi
6598 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6599 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6600 }
49e5a4a0 6601#ifdef ENABLE_BGP_VNC
d62a17ae 6602 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6603 safi, new->type, new->sub_type, &label);
65efcfce
LB
6604#endif
6605
d62a17ae 6606 /* Unintern original. */
6607 aspath_unintern(&attr.aspath);
137446f9
LB
6608}
6609
718e3744 6610/* Configure static BGP network. When user don't run zebra, static
6611 route should be installed as valid. */
585f1adc
IR
6612static int bgp_static_set(struct vty *vty, const char *negate,
6613 const char *ip_str, afi_t afi, safi_t safi,
6614 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6615{
585f1adc
IR
6616 VTY_DECLVAR_CONTEXT(bgp, bgp);
6617 int ret;
d62a17ae 6618 struct prefix p;
6619 struct bgp_static *bgp_static;
9bcb3eef 6620 struct bgp_dest *dest;
d7c0a89a 6621 uint8_t need_update = 0;
d62a17ae 6622
585f1adc
IR
6623 /* Convert IP prefix string to struct prefix. */
6624 ret = str2prefix(ip_str, &p);
6625 if (!ret) {
6626 vty_out(vty, "%% Malformed prefix\n");
6627 return CMD_WARNING_CONFIG_FAILED;
6628 }
6629 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6630 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6631 return CMD_WARNING_CONFIG_FAILED;
6632 }
6633
d62a17ae 6634 apply_mask(&p);
718e3744 6635
e2a86ad9 6636 if (negate) {
718e3744 6637
e2a86ad9 6638 /* Set BGP static route configuration. */
9bcb3eef 6639 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6640
9bcb3eef 6641 if (!dest) {
585f1adc
IR
6642 vty_out(vty, "%% Can't find static route specified\n");
6643 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6644 }
6645
9bcb3eef 6646 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6647
e2a86ad9
DS
6648 if ((label_index != BGP_INVALID_LABEL_INDEX)
6649 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6650 vty_out(vty,
6651 "%% label-index doesn't match static route\n");
70d9b134 6652 bgp_dest_unlock_node(dest);
585f1adc 6653 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6654 }
d62a17ae 6655
e2a86ad9
DS
6656 if ((rmap && bgp_static->rmap.name)
6657 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6658 vty_out(vty,
6659 "%% route-map name doesn't match static route\n");
70d9b134 6660 bgp_dest_unlock_node(dest);
585f1adc 6661 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6662 }
718e3744 6663
e2a86ad9
DS
6664 /* Update BGP RIB. */
6665 if (!bgp_static->backdoor)
6666 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6667
e2a86ad9
DS
6668 /* Clear configuration. */
6669 bgp_static_free(bgp_static);
9bcb3eef
DS
6670 bgp_dest_set_bgp_static_info(dest, NULL);
6671 bgp_dest_unlock_node(dest);
6672 bgp_dest_unlock_node(dest);
e2a86ad9 6673 } else {
718e3744 6674
e2a86ad9 6675 /* Set BGP static route configuration. */
9bcb3eef
DS
6676 dest = bgp_node_get(bgp->route[afi][safi], &p);
6677 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6678 if (bgp_static) {
e2a86ad9 6679 /* Configuration change. */
e2a86ad9
DS
6680 /* Label index cannot be changed. */
6681 if (bgp_static->label_index != label_index) {
585f1adc 6682 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6683 bgp_dest_unlock_node(dest);
585f1adc 6684 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6685 }
d62a17ae 6686
e2a86ad9 6687 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6688 if (bgp_static->valid
6689 && bgp_static->backdoor != backdoor)
e2a86ad9 6690 need_update = 1;
718e3744 6691
e2a86ad9 6692 bgp_static->backdoor = backdoor;
718e3744 6693
e2a86ad9 6694 if (rmap) {
0a22ddfb
QY
6695 XFREE(MTYPE_ROUTE_MAP_NAME,
6696 bgp_static->rmap.name);
b4897fa5 6697 route_map_counter_decrement(
6698 bgp_static->rmap.map);
e2a86ad9
DS
6699 bgp_static->rmap.name =
6700 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6701 bgp_static->rmap.map =
6702 route_map_lookup_by_name(rmap);
b4897fa5 6703 route_map_counter_increment(
6704 bgp_static->rmap.map);
e2a86ad9 6705 } else {
0a22ddfb
QY
6706 XFREE(MTYPE_ROUTE_MAP_NAME,
6707 bgp_static->rmap.name);
b4897fa5 6708 route_map_counter_decrement(
6709 bgp_static->rmap.map);
e2a86ad9
DS
6710 bgp_static->rmap.map = NULL;
6711 bgp_static->valid = 0;
6712 }
9bcb3eef 6713 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6714 } else {
6715 /* New configuration. */
6716 bgp_static = bgp_static_new();
6717 bgp_static->backdoor = backdoor;
6718 bgp_static->valid = 0;
6719 bgp_static->igpmetric = 0;
975a328e 6720 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6721 bgp_static->label_index = label_index;
718e3744 6722
e2a86ad9 6723 if (rmap) {
0a22ddfb
QY
6724 XFREE(MTYPE_ROUTE_MAP_NAME,
6725 bgp_static->rmap.name);
b4897fa5 6726 route_map_counter_decrement(
6727 bgp_static->rmap.map);
e2a86ad9
DS
6728 bgp_static->rmap.name =
6729 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6730 bgp_static->rmap.map =
6731 route_map_lookup_by_name(rmap);
b4897fa5 6732 route_map_counter_increment(
6733 bgp_static->rmap.map);
e2a86ad9 6734 }
9bcb3eef 6735 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6736 }
d62a17ae 6737
e2a86ad9
DS
6738 bgp_static->valid = 1;
6739 if (need_update)
6740 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6741
e2a86ad9
DS
6742 if (!bgp_static->backdoor)
6743 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6744 }
d62a17ae 6745
585f1adc 6746 return CMD_SUCCESS;
d62a17ae 6747}
6748
6749void bgp_static_add(struct bgp *bgp)
6750{
6751 afi_t afi;
6752 safi_t safi;
9bcb3eef
DS
6753 struct bgp_dest *dest;
6754 struct bgp_dest *rm;
d62a17ae 6755 struct bgp_table *table;
6756 struct bgp_static *bgp_static;
6757
47fc6261 6758 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6759 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6760 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6761 dest = bgp_route_next(dest)) {
6762 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6763 continue;
ea47320b 6764
05c7a1cc
QY
6765 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6766 || (safi == SAFI_EVPN)) {
9bcb3eef 6767 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6768
6769 for (rm = bgp_table_top(table); rm;
6770 rm = bgp_route_next(rm)) {
a78beeb5 6771 bgp_static =
9bcb3eef 6772 bgp_dest_get_bgp_static_info(
5a8ba9fc 6773 rm);
9bcb3eef
DS
6774 bgp_static_update_safi(
6775 bgp, bgp_dest_get_prefix(rm),
6776 bgp_static, afi, safi);
d62a17ae 6777 }
05c7a1cc 6778 } else {
5a8ba9fc 6779 bgp_static_update(
9bcb3eef
DS
6780 bgp, bgp_dest_get_prefix(dest),
6781 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6782 safi);
ea47320b 6783 }
05c7a1cc 6784 }
47fc6261 6785 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6786}
6787
718e3744 6788/* Called from bgp_delete(). Delete all static routes from the BGP
6789 instance. */
d62a17ae 6790void bgp_static_delete(struct bgp *bgp)
6791{
6792 afi_t afi;
6793 safi_t safi;
9bcb3eef
DS
6794 struct bgp_dest *dest;
6795 struct bgp_dest *rm;
d62a17ae 6796 struct bgp_table *table;
6797 struct bgp_static *bgp_static;
6798
05c7a1cc 6799 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6800 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6801 dest = bgp_route_next(dest)) {
6802 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6803 continue;
ea47320b 6804
05c7a1cc
QY
6805 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6806 || (safi == SAFI_EVPN)) {
9bcb3eef 6807 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6808
6809 for (rm = bgp_table_top(table); rm;
6810 rm = bgp_route_next(rm)) {
a78beeb5 6811 bgp_static =
9bcb3eef 6812 bgp_dest_get_bgp_static_info(
5a8ba9fc 6813 rm);
c7d14ba6
PG
6814 if (!bgp_static)
6815 continue;
6816
05c7a1cc 6817 bgp_static_withdraw_safi(
9bcb3eef 6818 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6819 AFI_IP, safi,
6820 (struct prefix_rd *)
9bcb3eef
DS
6821 bgp_dest_get_prefix(
6822 dest));
ea47320b 6823 bgp_static_free(bgp_static);
811c6797 6824 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6825 NULL);
811c6797 6826 bgp_dest_unlock_node(rm);
d62a17ae 6827 }
05c7a1cc 6828 } else {
9bcb3eef 6829 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6830 bgp_static_withdraw(bgp,
9bcb3eef 6831 bgp_dest_get_prefix(dest),
b54892e0 6832 afi, safi);
05c7a1cc 6833 bgp_static_free(bgp_static);
9bcb3eef
DS
6834 bgp_dest_set_bgp_static_info(dest, NULL);
6835 bgp_dest_unlock_node(dest);
ea47320b 6836 }
05c7a1cc 6837 }
d62a17ae 6838}
6839
6840void bgp_static_redo_import_check(struct bgp *bgp)
6841{
6842 afi_t afi;
6843 safi_t safi;
9bcb3eef
DS
6844 struct bgp_dest *dest;
6845 struct bgp_dest *rm;
d62a17ae 6846 struct bgp_table *table;
6847 struct bgp_static *bgp_static;
6848
6849 /* Use this flag to force reprocessing of the route */
892fedb6 6850 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6851 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6852 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6853 dest = bgp_route_next(dest)) {
6854 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6855 continue;
ea47320b 6856
05c7a1cc
QY
6857 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6858 || (safi == SAFI_EVPN)) {
9bcb3eef 6859 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6860
6861 for (rm = bgp_table_top(table); rm;
6862 rm = bgp_route_next(rm)) {
a78beeb5 6863 bgp_static =
9bcb3eef 6864 bgp_dest_get_bgp_static_info(
5a8ba9fc 6865 rm);
9bcb3eef
DS
6866 bgp_static_update_safi(
6867 bgp, bgp_dest_get_prefix(rm),
6868 bgp_static, afi, safi);
d62a17ae 6869 }
05c7a1cc 6870 } else {
9bcb3eef
DS
6871 bgp_static = bgp_dest_get_bgp_static_info(dest);
6872 bgp_static_update(bgp,
6873 bgp_dest_get_prefix(dest),
6874 bgp_static, afi, safi);
ea47320b 6875 }
05c7a1cc
QY
6876 }
6877 }
892fedb6 6878 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6879}
6880
6881static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6882 safi_t safi)
6883{
6884 struct bgp_table *table;
9bcb3eef 6885 struct bgp_dest *dest;
40381db7 6886 struct bgp_path_info *pi;
d62a17ae 6887
dfb6fd1d
NT
6888 /* Do not install the aggregate route if BGP is in the
6889 * process of termination.
6890 */
892fedb6
DA
6891 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6892 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6893 return;
6894
d62a17ae 6895 table = bgp->rib[afi][safi];
9bcb3eef
DS
6896 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6897 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6898 if (pi->peer == bgp->peer_self
6899 && ((pi->type == ZEBRA_ROUTE_BGP
6900 && pi->sub_type == BGP_ROUTE_STATIC)
6901 || (pi->type != ZEBRA_ROUTE_BGP
6902 && pi->sub_type
d62a17ae 6903 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6904 bgp_aggregate_decrement(
6905 bgp, bgp_dest_get_prefix(dest), pi, afi,
6906 safi);
40381db7 6907 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6908 bgp_path_info_delete(dest, pi);
6909 bgp_process(bgp, dest, afi, safi);
d62a17ae 6910 }
6911 }
6912 }
ad4cbda1 6913}
6914
6915/*
6916 * Purge all networks and redistributed routes from routing table.
6917 * Invoked upon the instance going down.
6918 */
d62a17ae 6919void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6920{
d62a17ae 6921 afi_t afi;
6922 safi_t safi;
ad4cbda1 6923
05c7a1cc
QY
6924 FOREACH_AFI_SAFI (afi, safi)
6925 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6926}
6927
137446f9
LB
6928/*
6929 * gpz 110624
6930 * Currently this is used to set static routes for VPN and ENCAP.
6931 * I think it can probably be factored with bgp_static_set.
6932 */
d62a17ae 6933int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6934 const char *ip_str, const char *rd_str,
6935 const char *label_str, const char *rmap_str,
6936 int evpn_type, const char *esi, const char *gwip,
6937 const char *ethtag, const char *routermac)
6938{
6939 VTY_DECLVAR_CONTEXT(bgp, bgp);
6940 int ret;
6941 struct prefix p;
6942 struct prefix_rd prd;
9bcb3eef
DS
6943 struct bgp_dest *pdest;
6944 struct bgp_dest *dest;
d62a17ae 6945 struct bgp_table *table;
6946 struct bgp_static *bgp_static;
6947 mpls_label_t label = MPLS_INVALID_LABEL;
6948 struct prefix gw_ip;
6949
6950 /* validate ip prefix */
6951 ret = str2prefix(ip_str, &p);
6952 if (!ret) {
6953 vty_out(vty, "%% Malformed prefix\n");
6954 return CMD_WARNING_CONFIG_FAILED;
6955 }
6956 apply_mask(&p);
6957 if ((afi == AFI_L2VPN)
6958 && (bgp_build_evpn_prefix(evpn_type,
6959 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6960 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6961 return CMD_WARNING_CONFIG_FAILED;
6962 }
718e3744 6963
d62a17ae 6964 ret = str2prefix_rd(rd_str, &prd);
6965 if (!ret) {
6966 vty_out(vty, "%% Malformed rd\n");
6967 return CMD_WARNING_CONFIG_FAILED;
6968 }
718e3744 6969
d62a17ae 6970 if (label_str) {
6971 unsigned long label_val;
6972 label_val = strtoul(label_str, NULL, 10);
6973 encode_label(label_val, &label);
6974 }
9bedbb1e 6975
d62a17ae 6976 if (safi == SAFI_EVPN) {
6977 if (esi && str2esi(esi, NULL) == 0) {
6978 vty_out(vty, "%% Malformed ESI\n");
6979 return CMD_WARNING_CONFIG_FAILED;
6980 }
6981 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6982 vty_out(vty, "%% Malformed Router MAC\n");
6983 return CMD_WARNING_CONFIG_FAILED;
6984 }
6985 if (gwip) {
6006b807 6986 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6987 ret = str2prefix(gwip, &gw_ip);
6988 if (!ret) {
6989 vty_out(vty, "%% Malformed GatewayIp\n");
6990 return CMD_WARNING_CONFIG_FAILED;
6991 }
6992 if ((gw_ip.family == AF_INET
3714a385 6993 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6994 (struct prefix_evpn *)&p))
6995 || (gw_ip.family == AF_INET6
3714a385 6996 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6997 (struct prefix_evpn *)&p))) {
6998 vty_out(vty,
6999 "%% GatewayIp family differs with IP prefix\n");
7000 return CMD_WARNING_CONFIG_FAILED;
7001 }
7002 }
7003 }
9bcb3eef
DS
7004 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7005 if (!bgp_dest_has_bgp_path_info_data(pdest))
7006 bgp_dest_set_bgp_table_info(pdest,
67009e22 7007 bgp_table_init(bgp, afi, safi));
9bcb3eef 7008 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7009
9bcb3eef 7010 dest = bgp_node_get(table, &p);
d62a17ae 7011
9bcb3eef 7012 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7013 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7014 bgp_dest_unlock_node(dest);
d62a17ae 7015 } else {
7016 /* New configuration. */
7017 bgp_static = bgp_static_new();
7018 bgp_static->backdoor = 0;
7019 bgp_static->valid = 0;
7020 bgp_static->igpmetric = 0;
975a328e 7021 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7022 bgp_static->label = label;
7023 bgp_static->prd = prd;
7024
c1aa9e7f
PG
7025 if (rd_str)
7026 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
d62a17ae 7027 if (rmap_str) {
0a22ddfb 7028 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7029 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7030 bgp_static->rmap.name =
7031 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7032 bgp_static->rmap.map =
7033 route_map_lookup_by_name(rmap_str);
b4897fa5 7034 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7035 }
718e3744 7036
d62a17ae 7037 if (safi == SAFI_EVPN) {
7038 if (esi) {
7039 bgp_static->eth_s_id =
7040 XCALLOC(MTYPE_ATTR,
0a50c248 7041 sizeof(esi_t));
d62a17ae 7042 str2esi(esi, bgp_static->eth_s_id);
7043 }
7044 if (routermac) {
7045 bgp_static->router_mac =
28328ea9 7046 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7047 (void)prefix_str2mac(routermac,
7048 bgp_static->router_mac);
d62a17ae 7049 }
7050 if (gwip)
7051 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7052 }
9bcb3eef 7053 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7054
d62a17ae 7055 bgp_static->valid = 1;
7056 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7057 }
718e3744 7058
d62a17ae 7059 return CMD_SUCCESS;
718e3744 7060}
7061
7062/* Configure static BGP network. */
d62a17ae 7063int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7064 const char *ip_str, const char *rd_str,
7065 const char *label_str, int evpn_type, const char *esi,
7066 const char *gwip, const char *ethtag)
7067{
7068 VTY_DECLVAR_CONTEXT(bgp, bgp);
7069 int ret;
7070 struct prefix p;
7071 struct prefix_rd prd;
9bcb3eef
DS
7072 struct bgp_dest *pdest;
7073 struct bgp_dest *dest;
d62a17ae 7074 struct bgp_table *table;
7075 struct bgp_static *bgp_static;
7076 mpls_label_t label = MPLS_INVALID_LABEL;
7077
7078 /* Convert IP prefix string to struct prefix. */
7079 ret = str2prefix(ip_str, &p);
7080 if (!ret) {
7081 vty_out(vty, "%% Malformed prefix\n");
7082 return CMD_WARNING_CONFIG_FAILED;
7083 }
7084 apply_mask(&p);
7085 if ((afi == AFI_L2VPN)
7086 && (bgp_build_evpn_prefix(evpn_type,
7087 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7088 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7089 return CMD_WARNING_CONFIG_FAILED;
7090 }
7091 ret = str2prefix_rd(rd_str, &prd);
7092 if (!ret) {
7093 vty_out(vty, "%% Malformed rd\n");
7094 return CMD_WARNING_CONFIG_FAILED;
7095 }
718e3744 7096
d62a17ae 7097 if (label_str) {
7098 unsigned long label_val;
7099 label_val = strtoul(label_str, NULL, 10);
7100 encode_label(label_val, &label);
7101 }
718e3744 7102
9bcb3eef
DS
7103 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7104 if (!bgp_dest_has_bgp_path_info_data(pdest))
7105 bgp_dest_set_bgp_table_info(pdest,
67009e22 7106 bgp_table_init(bgp, afi, safi));
d62a17ae 7107 else
9bcb3eef
DS
7108 bgp_dest_unlock_node(pdest);
7109 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7110
9bcb3eef 7111 dest = bgp_node_lookup(table, &p);
6b0655a2 7112
9bcb3eef 7113 if (dest) {
d62a17ae 7114 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7115
9bcb3eef 7116 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7117 bgp_static_free(bgp_static);
9bcb3eef
DS
7118 bgp_dest_set_bgp_static_info(dest, NULL);
7119 bgp_dest_unlock_node(dest);
7120 bgp_dest_unlock_node(dest);
d62a17ae 7121 } else
7122 vty_out(vty, "%% Can't find the route\n");
7123
7124 return CMD_SUCCESS;
7125}
7126
7127static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7128 const char *rmap_name)
7129{
7130 VTY_DECLVAR_CONTEXT(bgp, bgp);
7131 struct bgp_rmap *rmap;
7132
7133 rmap = &bgp->table_map[afi][safi];
7134 if (rmap_name) {
0a22ddfb 7135 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7136 route_map_counter_decrement(rmap->map);
d62a17ae 7137 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7138 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7139 route_map_counter_increment(rmap->map);
d62a17ae 7140 } else {
0a22ddfb 7141 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7142 route_map_counter_decrement(rmap->map);
d62a17ae 7143 rmap->map = NULL;
7144 }
73ac8160 7145
d62a17ae 7146 if (bgp_fibupd_safi(safi))
7147 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7148
d62a17ae 7149 return CMD_SUCCESS;
73ac8160
DS
7150}
7151
d62a17ae 7152static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7153 const char *rmap_name)
73ac8160 7154{
d62a17ae 7155 VTY_DECLVAR_CONTEXT(bgp, bgp);
7156 struct bgp_rmap *rmap;
73ac8160 7157
d62a17ae 7158 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7159 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7160 route_map_counter_decrement(rmap->map);
d62a17ae 7161 rmap->map = NULL;
73ac8160 7162
d62a17ae 7163 if (bgp_fibupd_safi(safi))
7164 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7165
d62a17ae 7166 return CMD_SUCCESS;
73ac8160
DS
7167}
7168
2b791107 7169void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7170 safi_t safi)
73ac8160 7171{
d62a17ae 7172 if (bgp->table_map[afi][safi].name) {
d62a17ae 7173 vty_out(vty, " table-map %s\n",
7174 bgp->table_map[afi][safi].name);
7175 }
73ac8160
DS
7176}
7177
73ac8160
DS
7178DEFUN (bgp_table_map,
7179 bgp_table_map_cmd,
7180 "table-map WORD",
7181 "BGP table to RIB route download filter\n"
7182 "Name of the route map\n")
7183{
d62a17ae 7184 int idx_word = 1;
7185 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7186 argv[idx_word]->arg);
73ac8160
DS
7187}
7188DEFUN (no_bgp_table_map,
7189 no_bgp_table_map_cmd,
7190 "no table-map WORD",
3a2d747c 7191 NO_STR
73ac8160
DS
7192 "BGP table to RIB route download filter\n"
7193 "Name of the route map\n")
7194{
d62a17ae 7195 int idx_word = 2;
7196 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7197 argv[idx_word]->arg);
73ac8160
DS
7198}
7199
585f1adc
IR
7200DEFPY(bgp_network,
7201 bgp_network_cmd,
7202 "[no] network \
7203 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7204 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7205 backdoor$backdoor}]",
7206 NO_STR
7207 "Specify a network to announce via BGP\n"
7208 "IPv4 prefix\n"
7209 "Network number\n"
7210 "Network mask\n"
7211 "Network mask\n"
7212 "Route-map to modify the attributes\n"
7213 "Name of the route map\n"
7214 "Label index to associate with the prefix\n"
7215 "Label index value\n"
7216 "Specify a BGP backdoor route\n")
7217{
7218 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7219
7220 if (address_str) {
7221 int ret;
718e3744 7222
e2a86ad9 7223 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7224 addr_prefix_str,
7225 sizeof(addr_prefix_str));
e2a86ad9
DS
7226 if (!ret) {
7227 vty_out(vty, "%% Inconsistent address and mask\n");
7228 return CMD_WARNING_CONFIG_FAILED;
7229 }
d62a17ae 7230 }
718e3744 7231
585f1adc
IR
7232 return bgp_static_set(
7233 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7234 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7235 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7236}
7237
585f1adc
IR
7238DEFPY(ipv6_bgp_network,
7239 ipv6_bgp_network_cmd,
7240 "[no] network X:X::X:X/M$prefix \
70dd370f 7241 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7242 NO_STR
7243 "Specify a network to announce via BGP\n"
7244 "IPv6 prefix\n"
7245 "Route-map to modify the attributes\n"
7246 "Name of the route map\n"
7247 "Label index to associate with the prefix\n"
7248 "Label index value\n")
37a87b8f 7249{
585f1adc
IR
7250 return bgp_static_set(
7251 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7252 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7253}
7254
d62a17ae 7255static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7256{
d62a17ae 7257 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7258}
7259
9bea1b4b 7260void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7261{
365ab2e7
RZ
7262 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7263 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7264 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7265 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7266 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7267}
718e3744 7268
365ab2e7
RZ
7269/**
7270 * Helper function to avoid repeated code: prepare variables for a
7271 * `route_map_apply` call.
7272 *
7273 * \returns `true` on route map match, otherwise `false`.
7274 */
7275static bool aggr_suppress_map_test(struct bgp *bgp,
7276 struct bgp_aggregate *aggregate,
7277 struct bgp_path_info *pi)
7278{
7279 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7280 route_map_result_t rmr = RMAP_DENYMATCH;
7281 struct bgp_path_info rmap_path = {};
7282 struct attr attr = {};
7283
7284 /* No route map entries created, just don't match. */
7285 if (aggregate->suppress_map == NULL)
7286 return false;
7287
7288 /* Call route map matching and return result. */
17571c4a 7289 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7290 rmap_path.peer = bgp->peer_self;
7291 rmap_path.attr = &attr;
7292
7293 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7294 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7295 bgp->peer_self->rmap_type = 0;
7296
7297 bgp_attr_flush(&attr);
afb254d7 7298 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7299
7300 return rmr == RMAP_PERMITMATCH;
7301}
7302
4056a5f6
RZ
7303/** Test whether the aggregation has suppressed this path or not. */
7304static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7305 struct bgp_path_info *pi)
7306{
7307 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7308 return false;
7309
7310 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7311}
7312
7313/**
7314 * Suppress this path and keep the reference.
7315 *
7316 * \returns `true` if needs processing otherwise `false`.
7317 */
7318static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7319 struct bgp_path_info *pi)
7320{
7321 struct bgp_path_info_extra *pie;
7322
7323 /* Path is already suppressed by this aggregation. */
7324 if (aggr_suppress_exists(aggregate, pi))
7325 return false;
7326
7327 pie = bgp_path_info_extra_get(pi);
7328
7329 /* This is the first suppression, allocate memory and list it. */
7330 if (pie->aggr_suppressors == NULL)
7331 pie->aggr_suppressors = list_new();
7332
7333 listnode_add(pie->aggr_suppressors, aggregate);
7334
7335 /* Only mark for processing if suppressed. */
7336 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7337 if (BGP_DEBUG(update, UPDATE_OUT))
7338 zlog_debug("aggregate-address suppressing: %pFX",
7339 bgp_dest_get_prefix(pi->net));
7340
4056a5f6
RZ
7341 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7342 return true;
7343 }
7344
7345 return false;
7346}
7347
7348/**
7349 * Unsuppress this path and remove the reference.
7350 *
7351 * \returns `true` if needs processing otherwise `false`.
7352 */
7353static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7354 struct bgp_path_info *pi)
7355{
7356 /* Path wasn't suppressed. */
7357 if (!aggr_suppress_exists(aggregate, pi))
7358 return false;
7359
7360 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7361
7362 /* Unsuppress and free extra memory if last item. */
7363 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7364 if (BGP_DEBUG(update, UPDATE_OUT))
7365 zlog_debug("aggregate-address unsuppressing: %pFX",
7366 bgp_dest_get_prefix(pi->net));
7367
4056a5f6
RZ
7368 list_delete(&pi->extra->aggr_suppressors);
7369 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7370 return true;
7371 }
7372
7373 return false;
7374}
7375
3dc339cd
DA
7376static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7377 struct aspath *aspath,
7378 struct community *comm,
7379 struct ecommunity *ecomm,
7380 struct lcommunity *lcomm)
eaaf8adb
DS
7381{
7382 static struct aspath *ae = NULL;
17571c4a
PG
7383 enum asnotation_mode asnotation;
7384
7385 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7386
7387 if (!ae)
17571c4a 7388 ae = aspath_empty(asnotation);
eaaf8adb 7389
40381db7 7390 if (!pi)
3dc339cd 7391 return false;
eaaf8adb 7392
40381db7 7393 if (origin != pi->attr->origin)
3dc339cd 7394 return false;
eaaf8adb 7395
40381db7 7396 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7397 return false;
29f7d023 7398
9a706b42 7399 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7400 return false;
eaaf8adb 7401
b53e67a3 7402 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7403 return false;
eaaf8adb 7404
1bcf3a96 7405 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7406 return false;
dd18c5a9 7407
40381db7 7408 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7409 return false;
7ce8a8e0 7410
3dc339cd 7411 return true;
eaaf8adb
DS
7412}
7413
5f040085
DS
7414static void bgp_aggregate_install(
7415 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7416 uint8_t origin, struct aspath *aspath, struct community *community,
7417 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7418 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7419{
9bcb3eef 7420 struct bgp_dest *dest;
c701010e 7421 struct bgp_table *table;
6f94b685 7422 struct bgp_path_info *pi, *orig, *new;
20894f50 7423 struct attr *attr;
c701010e
DS
7424
7425 table = bgp->rib[afi][safi];
7426
9bcb3eef 7427 dest = bgp_node_get(table, p);
eaaf8adb 7428
9bcb3eef 7429 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7430 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7431 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7432 break;
7433
6aabb15d
RZ
7434 /*
7435 * If we have paths with different MEDs, then don't install
7436 * (or uninstall) the aggregate route.
7437 */
7438 if (aggregate->match_med && aggregate->med_mismatched)
7439 goto uninstall_aggregate_route;
7440
c701010e 7441 if (aggregate->count > 0) {
eaaf8adb
DS
7442 /*
7443 * If the aggregate information has not changed
7444 * no need to re-install it again.
7445 */
6f94b685 7446 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7447 ecommunity, lcommunity)) {
9bcb3eef 7448 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7449
7450 if (aspath)
7451 aspath_free(aspath);
7452 if (community)
3c1f53de 7453 community_free(&community);
3da2cc32
DS
7454 if (ecommunity)
7455 ecommunity_free(&ecommunity);
dd18c5a9
DS
7456 if (lcommunity)
7457 lcommunity_free(&lcommunity);
eaaf8adb
DS
7458
7459 return;
7460 }
7461
7462 /*
7463 * Mark the old as unusable
7464 */
40381db7 7465 if (pi)
9bcb3eef 7466 bgp_path_info_delete(dest, pi);
eaaf8adb 7467
20894f50
DA
7468 attr = bgp_attr_aggregate_intern(
7469 bgp, origin, aspath, community, ecommunity, lcommunity,
7470 aggregate, atomic_aggregate, p);
7471
7472 if (!attr) {
e11791f4
DA
7473 aspath_free(aspath);
7474 community_free(&community);
7475 ecommunity_free(&ecommunity);
7476 lcommunity_free(&lcommunity);
8c0044f3 7477 bgp_dest_unlock_node(dest);
20894f50 7478 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7479 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7480 zlog_debug("%s: %pFX null attribute", __func__,
7481 p);
20894f50
DA
7482 return;
7483 }
7484
3da2cc32 7485 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7486 bgp->peer_self, attr, dest);
20894f50 7487
1defdda8 7488 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7489
9bcb3eef
DS
7490 bgp_path_info_add(dest, new);
7491 bgp_process(bgp, dest, afi, safi);
c701010e 7492 } else {
6aabb15d 7493 uninstall_aggregate_route:
6f94b685 7494 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7495 if (pi->peer == bgp->peer_self
7496 && pi->type == ZEBRA_ROUTE_BGP
7497 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7498 break;
7499
7500 /* Withdraw static BGP route from routing table. */
40381db7 7501 if (pi) {
9bcb3eef
DS
7502 bgp_path_info_delete(dest, pi);
7503 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7504 }
7505 }
7506
9bcb3eef 7507 bgp_dest_unlock_node(dest);
c701010e
DS
7508}
7509
6aabb15d
RZ
7510/**
7511 * Check if the current path has different MED than other known paths.
7512 *
7513 * \returns `true` if the MED matched the others else `false`.
7514 */
7515static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7516 struct bgp *bgp, struct bgp_path_info *pi)
7517{
7518 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7519
7520 /* This is the first route being analyzed. */
7521 if (!aggregate->med_initialized) {
7522 aggregate->med_initialized = true;
7523 aggregate->med_mismatched = false;
7524 aggregate->med_matched_value = cur_med;
7525 } else {
7526 /* Check if routes with different MED showed up. */
7527 if (cur_med != aggregate->med_matched_value)
7528 aggregate->med_mismatched = true;
7529 }
7530
7531 return !aggregate->med_mismatched;
7532}
7533
7534/**
7535 * Initializes and tests all routes in the aggregate address path for MED
7536 * values.
7537 *
7538 * \returns `true` if all MEDs are the same otherwise `false`.
7539 */
7540static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7541 struct bgp *bgp, const struct prefix *p,
7542 afi_t afi, safi_t safi)
7543{
7544 struct bgp_table *table = bgp->rib[afi][safi];
7545 const struct prefix *dest_p;
7546 struct bgp_dest *dest, *top;
7547 struct bgp_path_info *pi;
7548 bool med_matched = true;
7549
7550 aggregate->med_initialized = false;
7551
7552 top = bgp_node_get(table, p);
7553 for (dest = bgp_node_get(table, p); dest;
7554 dest = bgp_route_next_until(dest, top)) {
7555 dest_p = bgp_dest_get_prefix(dest);
7556 if (dest_p->prefixlen <= p->prefixlen)
7557 continue;
7558
7559 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7560 if (BGP_PATH_HOLDDOWN(pi))
7561 continue;
7562 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7563 continue;
7564 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7565 med_matched = false;
7566 break;
7567 }
7568 }
7569 if (!med_matched)
7570 break;
7571 }
7572 bgp_dest_unlock_node(top);
7573
7574 return med_matched;
7575}
7576
7577/**
7578 * Toggles the route suppression status for this aggregate address
7579 * configuration.
7580 */
4056a5f6
RZ
7581void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7582 struct bgp *bgp, const struct prefix *p,
7583 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7584{
7585 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7586 const struct prefix *dest_p;
7587 struct bgp_dest *dest, *top;
7588 struct bgp_path_info *pi;
7589 bool toggle_suppression;
7590
7591 /* We've found a different MED we must revert any suppressed routes. */
7592 top = bgp_node_get(table, p);
7593 for (dest = bgp_node_get(table, p); dest;
7594 dest = bgp_route_next_until(dest, top)) {
7595 dest_p = bgp_dest_get_prefix(dest);
7596 if (dest_p->prefixlen <= p->prefixlen)
7597 continue;
7598
7599 toggle_suppression = false;
7600 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7601 if (BGP_PATH_HOLDDOWN(pi))
7602 continue;
7603 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7604 continue;
7605
6aabb15d
RZ
7606 /* We are toggling suppression back. */
7607 if (suppress) {
6aabb15d 7608 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7609 if (aggr_suppress_path(aggregate, pi))
7610 toggle_suppression = true;
6aabb15d
RZ
7611 continue;
7612 }
7613
6aabb15d 7614 /* Install route if there is no more suppression. */
4056a5f6 7615 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7616 toggle_suppression = true;
6aabb15d
RZ
7617 }
7618
7619 if (toggle_suppression)
7620 bgp_process(bgp, dest, afi, safi);
7621 }
7622 bgp_dest_unlock_node(top);
7623}
7624
7625/**
7626 * Aggregate address MED matching incremental test: this function is called
7627 * when the initial aggregation occurred and we are only testing a single
7628 * new path.
7629 *
7630 * In addition to testing and setting the MED validity it also installs back
7631 * suppressed routes (if summary is configured).
7632 *
7633 * Must not be called in `bgp_aggregate_route`.
7634 */
7635static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7636 struct bgp *bgp, const struct prefix *p,
7637 afi_t afi, safi_t safi,
f66624f5 7638 struct bgp_path_info *pi)
6aabb15d
RZ
7639{
7640 /* MED matching disabled. */
7641 if (!aggregate->match_med)
7642 return;
7643
f66624f5
DA
7644 /* Aggregation with different MED, recheck if we have got equal MEDs
7645 * now.
6aabb15d 7646 */
f66624f5
DA
7647 if (aggregate->med_mismatched &&
7648 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7649 aggregate->summary_only)
7650 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7651 true);
7652 else
6aabb15d
RZ
7653 bgp_aggregate_med_match(aggregate, bgp, pi);
7654
7655 /* No mismatches, just quit. */
7656 if (!aggregate->med_mismatched)
7657 return;
7658
7659 /* Route summarization is disabled. */
7660 if (!aggregate->summary_only)
7661 return;
7662
7663 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7664}
7665
b5d58c32 7666/* Update an aggregate as routes are added/removed from the BGP table */
9bea1b4b 7667bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
5f040085 7668 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7669{
7670 struct bgp_table *table;
9bcb3eef
DS
7671 struct bgp_dest *top;
7672 struct bgp_dest *dest;
d7c0a89a 7673 uint8_t origin;
d62a17ae 7674 struct aspath *aspath = NULL;
d62a17ae 7675 struct community *community = NULL;
3da2cc32 7676 struct ecommunity *ecommunity = NULL;
dd18c5a9 7677 struct lcommunity *lcommunity = NULL;
40381db7 7678 struct bgp_path_info *pi;
d62a17ae 7679 unsigned long match = 0;
d7c0a89a 7680 uint8_t atomic_aggregate = 0;
d62a17ae 7681
9f822fa2
S
7682 /* If the bgp instance is being deleted or self peer is deleted
7683 * then do not create aggregate route
7684 */
69a9680a 7685 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
9bea1b4b
DA
7686 bgp->peer_self == NULL)
7687 return false;
9f822fa2 7688
6aabb15d
RZ
7689 /* Initialize and test routes for MED difference. */
7690 if (aggregate->match_med)
7691 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7692
4056a5f6
RZ
7693 /*
7694 * Reset aggregate count: we might've been called from route map
7695 * update so in that case we must retest all more specific routes.
7696 *
7697 * \see `bgp_route_map_process_update`.
7698 */
7699 aggregate->count = 0;
7700 aggregate->incomplete_origin_count = 0;
7701 aggregate->incomplete_origin_count = 0;
7702 aggregate->egp_origin_count = 0;
7703
d62a17ae 7704 /* ORIGIN attribute: If at least one route among routes that are
7705 aggregated has ORIGIN with the value INCOMPLETE, then the
7706 aggregated route must have the ORIGIN attribute with the value
7707 INCOMPLETE. Otherwise, if at least one route among routes that
7708 are aggregated has ORIGIN with the value EGP, then the aggregated
7709 route must have the origin attribute with the value EGP. In all
7710 other case the value of the ORIGIN attribute of the aggregated
7711 route is INTERNAL. */
7712 origin = BGP_ORIGIN_IGP;
718e3744 7713
d62a17ae 7714 table = bgp->rib[afi][safi];
718e3744 7715
d62a17ae 7716 top = bgp_node_get(table, p);
9bcb3eef
DS
7717 for (dest = bgp_node_get(table, p); dest;
7718 dest = bgp_route_next_until(dest, top)) {
7719 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7720
9bcb3eef 7721 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7722 continue;
d62a17ae 7723
a77e2f4b
S
7724 /* If suppress fib is enabled and route not installed
7725 * in FIB, skip the route
7726 */
7727 if (!bgp_check_advertise(bgp, dest))
7728 continue;
7729
c2ff8b3e 7730 match = 0;
d62a17ae 7731
9bcb3eef 7732 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7733 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7734 continue;
718e3744 7735
40381db7 7736 if (pi->attr->flag
c2ff8b3e
DS
7737 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7738 atomic_aggregate = 1;
d62a17ae 7739
40381db7 7740 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7741 continue;
d62a17ae 7742
f273fef1
DS
7743 /*
7744 * summary-only aggregate route suppress
7745 * aggregated route announcements.
6aabb15d
RZ
7746 *
7747 * MED matching:
7748 * Don't create summaries if MED didn't match
7749 * otherwise neither the specific routes and the
7750 * aggregation will be announced.
f273fef1 7751 */
6aabb15d
RZ
7752 if (aggregate->summary_only
7753 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7754 if (aggr_suppress_path(aggregate, pi))
7755 match++;
d62a17ae 7756 }
c2ff8b3e 7757
365ab2e7
RZ
7758 /*
7759 * Suppress more specific routes that match the route
7760 * map results.
7761 *
7762 * MED matching:
7763 * Don't suppress routes if MED matching is enabled and
7764 * it mismatched otherwise we might end up with no
7765 * routes for this path.
7766 */
7767 if (aggregate->suppress_map_name
7768 && AGGREGATE_MED_VALID(aggregate)
7769 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7770 if (aggr_suppress_path(aggregate, pi))
7771 match++;
d62a17ae 7772 }
c2ff8b3e
DS
7773
7774 aggregate->count++;
7775
f273fef1
DS
7776 /*
7777 * If at least one route among routes that are
7778 * aggregated has ORIGIN with the value INCOMPLETE,
7779 * then the aggregated route MUST have the ORIGIN
7780 * attribute with the value INCOMPLETE. Otherwise, if
7781 * at least one route among routes that are aggregated
7782 * has ORIGIN with the value EGP, then the aggregated
7783 * route MUST have the ORIGIN attribute with the value
7784 * EGP.
7785 */
fc968841
NT
7786 switch (pi->attr->origin) {
7787 case BGP_ORIGIN_INCOMPLETE:
7788 aggregate->incomplete_origin_count++;
7789 break;
7790 case BGP_ORIGIN_EGP:
7791 aggregate->egp_origin_count++;
7792 break;
7793 default:
7794 /*Do nothing.
7795 */
7796 break;
7797 }
c2ff8b3e
DS
7798
7799 if (!aggregate->as_set)
7800 continue;
7801
f273fef1
DS
7802 /*
7803 * as-set aggregate route generate origin, as path,
7804 * and community aggregation.
7805 */
fc968841
NT
7806 /* Compute aggregate route's as-path.
7807 */
ef51a7d8 7808 bgp_compute_aggregate_aspath_hash(aggregate,
7809 pi->attr->aspath);
c2ff8b3e 7810
fc968841
NT
7811 /* Compute aggregate route's community.
7812 */
9a706b42 7813 if (bgp_attr_get_community(pi->attr))
21fec674 7814 bgp_compute_aggregate_community_hash(
9a706b42
DA
7815 aggregate,
7816 bgp_attr_get_community(pi->attr));
dd18c5a9 7817
fc968841
NT
7818 /* Compute aggregate route's extended community.
7819 */
b53e67a3 7820 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7821 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7822 aggregate,
7823 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7824
7825 /* Compute aggregate route's large community.
7826 */
1bcf3a96 7827 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7828 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7829 aggregate,
7830 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7831 }
c2ff8b3e 7832 if (match)
9bcb3eef 7833 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7834 }
21fec674 7835 if (aggregate->as_set) {
ef51a7d8 7836 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7837 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7838 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7839 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7840 }
7841
f1eb1f05 7842
9bcb3eef 7843 bgp_dest_unlock_node(top);
718e3744 7844
718e3744 7845
fc968841
NT
7846 if (aggregate->incomplete_origin_count > 0)
7847 origin = BGP_ORIGIN_INCOMPLETE;
7848 else if (aggregate->egp_origin_count > 0)
7849 origin = BGP_ORIGIN_EGP;
d62a17ae 7850
229757f1
DA
7851 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7852 origin = aggregate->origin;
7853
fc968841
NT
7854 if (aggregate->as_set) {
7855 if (aggregate->aspath)
7856 /* Retrieve aggregate route's as-path.
7857 */
7858 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7859
fc968841
NT
7860 if (aggregate->community)
7861 /* Retrieve aggregate route's community.
7862 */
7863 community = community_dup(aggregate->community);
3da2cc32 7864
fc968841
NT
7865 if (aggregate->ecommunity)
7866 /* Retrieve aggregate route's ecommunity.
7867 */
7868 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7869
fc968841
NT
7870 if (aggregate->lcommunity)
7871 /* Retrieve aggregate route's lcommunity.
7872 */
7873 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7874 }
718e3744 7875
c701010e 7876 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7877 ecommunity, lcommunity, atomic_aggregate,
7878 aggregate);
9bea1b4b
DA
7879
7880 return true;
718e3744 7881}
7882
5f040085
DS
7883void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7884 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7885{
7886 struct bgp_table *table;
9bcb3eef
DS
7887 struct bgp_dest *top;
7888 struct bgp_dest *dest;
40381db7 7889 struct bgp_path_info *pi;
3b7db173
DS
7890 unsigned long match;
7891
7892 table = bgp->rib[afi][safi];
7893
7894 /* If routes exists below this node, generate aggregate routes. */
7895 top = bgp_node_get(table, p);
9bcb3eef
DS
7896 for (dest = bgp_node_get(table, p); dest;
7897 dest = bgp_route_next_until(dest, top)) {
7898 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7899
9bcb3eef 7900 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7901 continue;
7902 match = 0;
7903
9bcb3eef 7904 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7905 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7906 continue;
7907
40381db7 7908 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7909 continue;
7910
92b175bd
RZ
7911 /*
7912 * This route is suppressed: attempt to unsuppress it.
7913 *
7914 * `aggr_unsuppress_path` will fail if this particular
7915 * aggregate route was not the suppressor.
7916 */
7917 if (pi->extra && pi->extra->aggr_suppressors &&
7918 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7919 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7920 match++;
3b7db173 7921 }
365ab2e7 7922
3b7db173 7923 aggregate->count--;
fc968841
NT
7924
7925 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7926 aggregate->incomplete_origin_count--;
7927 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7928 aggregate->egp_origin_count--;
7929
7930 if (aggregate->as_set) {
7931 /* Remove as-path from aggregate.
7932 */
ef51a7d8 7933 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7934 aggregate,
7935 pi->attr->aspath);
7936
9a706b42 7937 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7938 /* Remove community from aggregate.
7939 */
21fec674 7940 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7941 aggregate,
7942 bgp_attr_get_community(
7943 pi->attr));
fc968841 7944
b53e67a3 7945 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7946 /* Remove ecommunity from aggregate.
7947 */
4edd83f9 7948 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7949 aggregate,
7950 bgp_attr_get_ecommunity(
7951 pi->attr));
fc968841 7952
1bcf3a96 7953 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7954 /* Remove lcommunity from aggregate.
7955 */
f1eb1f05 7956 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7957 aggregate,
7958 bgp_attr_get_lcommunity(
7959 pi->attr));
fc968841 7960 }
3b7db173
DS
7961 }
7962
7963 /* If this node was suppressed, process the change. */
7964 if (match)
9bcb3eef 7965 bgp_process(bgp, dest, afi, safi);
3b7db173 7966 }
f1eb1f05 7967 if (aggregate->as_set) {
ef51a7d8 7968 aspath_free(aggregate->aspath);
7969 aggregate->aspath = NULL;
21fec674 7970 if (aggregate->community)
7971 community_free(&aggregate->community);
4edd83f9 7972 if (aggregate->ecommunity)
7973 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7974 if (aggregate->lcommunity)
7975 lcommunity_free(&aggregate->lcommunity);
7976 }
7977
9bcb3eef 7978 bgp_dest_unlock_node(top);
3b7db173 7979}
718e3744 7980
5f040085
DS
7981static void bgp_add_route_to_aggregate(struct bgp *bgp,
7982 const struct prefix *aggr_p,
fc968841
NT
7983 struct bgp_path_info *pinew, afi_t afi,
7984 safi_t safi,
7985 struct bgp_aggregate *aggregate)
7986{
7987 uint8_t origin;
7988 struct aspath *aspath = NULL;
7989 uint8_t atomic_aggregate = 0;
7990 struct community *community = NULL;
7991 struct ecommunity *ecommunity = NULL;
7992 struct lcommunity *lcommunity = NULL;
7993
a4559740 7994 /* If the bgp instance is being deleted or self peer is deleted
7995 * then do not create aggregate route
7996 */
7997 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7998 || (bgp->peer_self == NULL))
7999 return;
8000
fc968841
NT
8001 /* ORIGIN attribute: If at least one route among routes that are
8002 * aggregated has ORIGIN with the value INCOMPLETE, then the
8003 * aggregated route must have the ORIGIN attribute with the value
8004 * INCOMPLETE. Otherwise, if at least one route among routes that
8005 * are aggregated has ORIGIN with the value EGP, then the aggregated
8006 * route must have the origin attribute with the value EGP. In all
8007 * other case the value of the ORIGIN attribute of the aggregated
8008 * route is INTERNAL.
8009 */
8010 origin = BGP_ORIGIN_IGP;
8011
8012 aggregate->count++;
8013
6aabb15d
RZ
8014 /*
8015 * This must be called before `summary` check to avoid
8016 * "suppressing" twice.
8017 */
8018 if (aggregate->match_med)
8019 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8020 pinew);
6aabb15d
RZ
8021
8022 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8023 aggr_suppress_path(aggregate, pinew);
fc968841 8024
365ab2e7
RZ
8025 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8026 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8027 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8028
8029 switch (pinew->attr->origin) {
8030 case BGP_ORIGIN_INCOMPLETE:
8031 aggregate->incomplete_origin_count++;
8032 break;
8033 case BGP_ORIGIN_EGP:
8034 aggregate->egp_origin_count++;
8035 break;
8036 default:
8037 /* Do nothing.
8038 */
8039 break;
8040 }
8041
8042 if (aggregate->incomplete_origin_count > 0)
8043 origin = BGP_ORIGIN_INCOMPLETE;
8044 else if (aggregate->egp_origin_count > 0)
8045 origin = BGP_ORIGIN_EGP;
8046
229757f1
DA
8047 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8048 origin = aggregate->origin;
8049
fc968841
NT
8050 if (aggregate->as_set) {
8051 /* Compute aggregate route's as-path.
8052 */
8053 bgp_compute_aggregate_aspath(aggregate,
8054 pinew->attr->aspath);
8055
8056 /* Compute aggregate route's community.
8057 */
9a706b42 8058 if (bgp_attr_get_community(pinew->attr))
fc968841 8059 bgp_compute_aggregate_community(
9a706b42 8060 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8061
8062 /* Compute aggregate route's extended community.
8063 */
b53e67a3 8064 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8065 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8066 aggregate,
8067 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8068
8069 /* Compute aggregate route's large community.
8070 */
1bcf3a96 8071 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8072 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8073 aggregate,
8074 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8075
8076 /* Retrieve aggregate route's as-path.
8077 */
8078 if (aggregate->aspath)
8079 aspath = aspath_dup(aggregate->aspath);
8080
8081 /* Retrieve aggregate route's community.
8082 */
8083 if (aggregate->community)
8084 community = community_dup(aggregate->community);
8085
8086 /* Retrieve aggregate route's ecommunity.
8087 */
8088 if (aggregate->ecommunity)
8089 ecommunity = ecommunity_dup(aggregate->ecommunity);
8090
8091 /* Retrieve aggregate route's lcommunity.
8092 */
8093 if (aggregate->lcommunity)
8094 lcommunity = lcommunity_dup(aggregate->lcommunity);
8095 }
8096
8097 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8098 aspath, community, ecommunity,
8099 lcommunity, atomic_aggregate, aggregate);
8100}
8101
8102static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8103 safi_t safi,
8104 struct bgp_path_info *pi,
8105 struct bgp_aggregate *aggregate,
5f040085 8106 const struct prefix *aggr_p)
fc968841
NT
8107{
8108 uint8_t origin;
8109 struct aspath *aspath = NULL;
8110 uint8_t atomic_aggregate = 0;
8111 struct community *community = NULL;
8112 struct ecommunity *ecommunity = NULL;
8113 struct lcommunity *lcommunity = NULL;
8114 unsigned long match = 0;
8115
a4559740 8116 /* If the bgp instance is being deleted or self peer is deleted
8117 * then do not create aggregate route
8118 */
8119 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8120 || (bgp->peer_self == NULL))
8121 return;
8122
fc968841
NT
8123 if (BGP_PATH_HOLDDOWN(pi))
8124 return;
8125
8126 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8127 return;
8128
4056a5f6
RZ
8129 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8130 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8131 match++;
fc968841 8132
365ab2e7 8133 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8134 && aggr_suppress_map_test(bgp, aggregate, pi))
8135 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8136 match++;
fc968841 8137
6aabb15d 8138 /*
365ab2e7 8139 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8140 * "unsuppressing" twice.
8141 */
8142 if (aggregate->match_med)
f66624f5 8143 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8144
fc968841
NT
8145 if (aggregate->count > 0)
8146 aggregate->count--;
8147
8148 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8149 aggregate->incomplete_origin_count--;
8150 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8151 aggregate->egp_origin_count--;
8152
8153 if (aggregate->as_set) {
8154 /* Remove as-path from aggregate.
8155 */
8156 bgp_remove_aspath_from_aggregate(aggregate,
8157 pi->attr->aspath);
8158
9a706b42 8159 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8160 /* Remove community from aggregate.
8161 */
8162 bgp_remove_community_from_aggregate(
9a706b42 8163 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8164
b53e67a3 8165 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8166 /* Remove ecommunity from aggregate.
8167 */
8168 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8169 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8170
1bcf3a96 8171 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8172 /* Remove lcommunity from aggregate.
8173 */
8174 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8175 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8176 }
8177
8178 /* If this node was suppressed, process the change. */
8179 if (match)
8180 bgp_process(bgp, pi->net, afi, safi);
8181
8182 origin = BGP_ORIGIN_IGP;
8183 if (aggregate->incomplete_origin_count > 0)
8184 origin = BGP_ORIGIN_INCOMPLETE;
8185 else if (aggregate->egp_origin_count > 0)
8186 origin = BGP_ORIGIN_EGP;
8187
229757f1
DA
8188 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8189 origin = aggregate->origin;
8190
fc968841
NT
8191 if (aggregate->as_set) {
8192 /* Retrieve aggregate route's as-path.
8193 */
8194 if (aggregate->aspath)
8195 aspath = aspath_dup(aggregate->aspath);
8196
8197 /* Retrieve aggregate route's community.
8198 */
8199 if (aggregate->community)
8200 community = community_dup(aggregate->community);
8201
8202 /* Retrieve aggregate route's ecommunity.
8203 */
8204 if (aggregate->ecommunity)
8205 ecommunity = ecommunity_dup(aggregate->ecommunity);
8206
8207 /* Retrieve aggregate route's lcommunity.
8208 */
8209 if (aggregate->lcommunity)
8210 lcommunity = lcommunity_dup(aggregate->lcommunity);
8211 }
8212
8213 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8214 aspath, community, ecommunity,
8215 lcommunity, atomic_aggregate, aggregate);
8216}
8217
5a1ae2c2 8218void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8219 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8220{
9bcb3eef
DS
8221 struct bgp_dest *child;
8222 struct bgp_dest *dest;
d62a17ae 8223 struct bgp_aggregate *aggregate;
8224 struct bgp_table *table;
718e3744 8225
d62a17ae 8226 table = bgp->aggregate[afi][safi];
f018db83 8227
d62a17ae 8228 /* No aggregates configured. */
8229 if (bgp_table_top_nolock(table) == NULL)
8230 return;
f018db83 8231
d62a17ae 8232 if (p->prefixlen == 0)
8233 return;
718e3744 8234
40381db7 8235 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8236 return;
718e3744 8237
a77e2f4b
S
8238 /* If suppress fib is enabled and route not installed
8239 * in FIB, do not update the aggregate route
8240 */
8241 if (!bgp_check_advertise(bgp, pi->net))
8242 return;
8243
d62a17ae 8244 child = bgp_node_get(table, p);
718e3744 8245
d62a17ae 8246 /* Aggregate address configuration check. */
9bcb3eef
DS
8247 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8248 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8249
9bcb3eef
DS
8250 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8251 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8252 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8253 aggregate);
d62a17ae 8254 }
b1e62edd 8255 }
9bcb3eef 8256 bgp_dest_unlock_node(child);
718e3744 8257}
8258
5a1ae2c2 8259void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8260 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8261{
9bcb3eef
DS
8262 struct bgp_dest *child;
8263 struct bgp_dest *dest;
d62a17ae 8264 struct bgp_aggregate *aggregate;
8265 struct bgp_table *table;
718e3744 8266
d62a17ae 8267 table = bgp->aggregate[afi][safi];
718e3744 8268
d62a17ae 8269 /* No aggregates configured. */
8270 if (bgp_table_top_nolock(table) == NULL)
8271 return;
718e3744 8272
d62a17ae 8273 if (p->prefixlen == 0)
8274 return;
718e3744 8275
d62a17ae 8276 child = bgp_node_get(table, p);
718e3744 8277
d62a17ae 8278 /* Aggregate address configuration check. */
9bcb3eef
DS
8279 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8280 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8281
9bcb3eef
DS
8282 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8283 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8284 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8285 aggregate, dest_p);
d62a17ae 8286 }
b1e62edd 8287 }
9bcb3eef 8288 bgp_dest_unlock_node(child);
d62a17ae 8289}
718e3744 8290
718e3744 8291/* Aggregate route attribute. */
8292#define AGGREGATE_SUMMARY_ONLY 1
8293#define AGGREGATE_AS_SET 1
fb29348a 8294#define AGGREGATE_AS_UNSET 0
718e3744 8295
229757f1
DA
8296static const char *bgp_origin2str(uint8_t origin)
8297{
8298 switch (origin) {
8299 case BGP_ORIGIN_IGP:
8300 return "igp";
8301 case BGP_ORIGIN_EGP:
8302 return "egp";
8303 case BGP_ORIGIN_INCOMPLETE:
8304 return "incomplete";
8305 }
8306 return "n/a";
8307}
8308
fdeb5a81 8309static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8310{
8311 switch (v_state) {
fdeb5a81
DS
8312 case RPKI_NOT_BEING_USED:
8313 return "not used";
8314 case RPKI_VALID:
b5b99af8 8315 return "valid";
fdeb5a81 8316 case RPKI_NOTFOUND:
b5b99af8 8317 return "not found";
fdeb5a81 8318 case RPKI_INVALID:
b5b99af8 8319 return "invalid";
b5b99af8 8320 }
fdeb5a81
DS
8321
8322 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8323 return "ERROR";
8324}
8325
585f1adc
IR
8326static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8327 afi_t afi, safi_t safi)
718e3744 8328{
585f1adc
IR
8329 VTY_DECLVAR_CONTEXT(bgp, bgp);
8330 int ret;
8331 struct prefix p;
9bcb3eef 8332 struct bgp_dest *dest;
d62a17ae 8333 struct bgp_aggregate *aggregate;
718e3744 8334
585f1adc
IR
8335 /* Convert string to prefix structure. */
8336 ret = str2prefix(prefix_str, &p);
8337 if (!ret) {
8338 vty_out(vty, "Malformed prefix\n");
8339 return CMD_WARNING_CONFIG_FAILED;
8340 }
8341 apply_mask(&p);
a4559740 8342
d62a17ae 8343 /* Old configuration check. */
585f1adc 8344 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8345 if (!dest) {
585f1adc
IR
8346 vty_out(vty,
8347 "%% There is no aggregate-address configuration.\n");
8348 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8349 }
f6269b4f 8350
9bcb3eef 8351 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8352 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8353 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8354 NULL, NULL, 0, aggregate);
d62a17ae 8355
8356 /* Unlock aggregate address configuration. */
9bcb3eef 8357 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8358
8359 if (aggregate->community)
8360 community_free(&aggregate->community);
8361
d8bc11a5
DS
8362 hash_clean_and_free(&aggregate->community_hash,
8363 bgp_aggr_community_remove);
fc968841
NT
8364
8365 if (aggregate->ecommunity)
8366 ecommunity_free(&aggregate->ecommunity);
8367
d8bc11a5
DS
8368 hash_clean_and_free(&aggregate->ecommunity_hash,
8369 bgp_aggr_ecommunity_remove);
fc968841
NT
8370
8371 if (aggregate->lcommunity)
8372 lcommunity_free(&aggregate->lcommunity);
8373
d8bc11a5
DS
8374 hash_clean_and_free(&aggregate->lcommunity_hash,
8375 bgp_aggr_lcommunity_remove);
fc968841
NT
8376
8377 if (aggregate->aspath)
8378 aspath_free(aggregate->aspath);
8379
d8bc11a5 8380 hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
fc968841 8381
d62a17ae 8382 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8383 bgp_dest_unlock_node(dest);
8384 bgp_dest_unlock_node(dest);
d62a17ae 8385
585f1adc 8386 return CMD_SUCCESS;
d62a17ae 8387}
8388
585f1adc
IR
8389static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8390 safi_t safi, const char *rmap,
8391 uint8_t summary_only, uint8_t as_set,
8392 uint8_t origin, bool match_med,
8393 const char *suppress_map)
d62a17ae 8394{
585f1adc 8395 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8396 int ret;
585f1adc 8397 struct prefix p;
9bcb3eef 8398 struct bgp_dest *dest;
d62a17ae 8399 struct bgp_aggregate *aggregate;
fb29348a 8400 uint8_t as_set_new = as_set;
d62a17ae 8401
365ab2e7 8402 if (suppress_map && summary_only) {
585f1adc 8403 vty_out(vty,
365ab2e7 8404 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8405 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8406 }
8407
585f1adc
IR
8408 /* Convert string to prefix structure. */
8409 ret = str2prefix(prefix_str, &p);
8410 if (!ret) {
8411 vty_out(vty, "Malformed prefix\n");
8412 return CMD_WARNING_CONFIG_FAILED;
8413 }
8414 apply_mask(&p);
d62a17ae 8415
585f1adc
IR
8416 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8417 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8418 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8419 prefix_str);
8420 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8421 }
8422
d62a17ae 8423 /* Old configuration check. */
585f1adc 8424 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8425 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8426
20894f50 8427 if (aggregate) {
585f1adc 8428 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8429 /* try to remove the old entry */
585f1adc 8430 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8431 if (ret) {
585f1adc 8432 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8433 bgp_dest_unlock_node(dest);
585f1adc 8434 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8435 }
8436 }
718e3744 8437
d62a17ae 8438 /* Make aggregate address structure. */
8439 aggregate = bgp_aggregate_new();
8440 aggregate->summary_only = summary_only;
6aabb15d 8441 aggregate->match_med = match_med;
fb29348a
DA
8442
8443 /* Network operators MUST NOT locally generate any new
8444 * announcements containing AS_SET or AS_CONFED_SET. If they have
8445 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8446 * SHOULD withdraw those routes and re-announce routes for the
8447 * aggregate or component prefixes (i.e., the more-specific routes
8448 * subsumed by the previously aggregated route) without AS_SET
8449 * or AS_CONFED_SET in the updates.
8450 */
7f972cd8 8451 if (bgp->reject_as_sets) {
fb29348a
DA
8452 if (as_set == AGGREGATE_AS_SET) {
8453 as_set_new = AGGREGATE_AS_UNSET;
8454 zlog_warn(
63efca0e 8455 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8456 __func__);
585f1adc 8457 vty_out(vty,
fb29348a
DA
8458 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8459 }
8460 }
8461
8462 aggregate->as_set = as_set_new;
d62a17ae 8463 aggregate->safi = safi;
229757f1
DA
8464 /* Override ORIGIN attribute if defined.
8465 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8466 * to IGP which is not what rfc4271 says.
8467 * This enables the same behavior, optionally.
8468 */
8469 aggregate->origin = origin;
20894f50
DA
8470
8471 if (rmap) {
8472 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8473 route_map_counter_decrement(aggregate->rmap.map);
8474 aggregate->rmap.name =
8475 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8476 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8477 route_map_counter_increment(aggregate->rmap.map);
8478 }
365ab2e7
RZ
8479
8480 if (suppress_map) {
8481 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8482 route_map_counter_decrement(aggregate->suppress_map);
8483
8484 aggregate->suppress_map_name =
8485 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8486 aggregate->suppress_map =
8487 route_map_lookup_by_name(aggregate->suppress_map_name);
8488 route_map_counter_increment(aggregate->suppress_map);
8489 }
8490
9bcb3eef 8491 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8492
d62a17ae 8493 /* Aggregate address insert into BGP routing table. */
9bea1b4b
DA
8494 if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8495 bgp_aggregate_free(aggregate);
8496 bgp_dest_unlock_node(dest);
8497 }
718e3744 8498
585f1adc 8499 return CMD_SUCCESS;
718e3744 8500}
8501
585f1adc
IR
8502DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8503 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8504 "as-set$as_set_s"
8505 "|summary-only$summary_only"
cacba915 8506 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8507 "|origin <egp|igp|incomplete>$origin_s"
8508 "|matching-MED-only$match_med"
cacba915 8509 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8510 "}]",
8511 NO_STR
8512 "Configure BGP aggregate entries\n"
764402fe
DA
8513 "Aggregate prefix\n"
8514 "Aggregate address\n"
8515 "Aggregate mask\n"
585f1adc
IR
8516 "Generate AS set path information\n"
8517 "Filter more specific routes from updates\n"
8518 "Apply route map to aggregate network\n"
8519 "Route map name\n"
8520 "BGP origin code\n"
8521 "Remote EGP\n"
8522 "Local IGP\n"
8523 "Unknown heritage\n"
8524 "Only aggregate routes with matching MED\n"
8525 "Suppress the selected more specific routes\n"
8526 "Route map with the route selectors\n")
8527{
8528 const char *prefix_s = NULL;
554b3b10 8529 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8530 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8531 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8532 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8533
554b3b10 8534 if (addr_str) {
7533cad7
QY
8535 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8536 sizeof(prefix_buf))
554b3b10
RZ
8537 == 0) {
8538 vty_out(vty, "%% Inconsistent address and mask\n");
8539 return CMD_WARNING_CONFIG_FAILED;
8540 }
585f1adc
IR
8541 prefix_s = prefix_buf;
8542 } else
8543 prefix_s = prefix_str;
37a87b8f 8544
585f1adc
IR
8545 if (origin_s) {
8546 if (strcmp(origin_s, "egp") == 0)
8547 origin = BGP_ORIGIN_EGP;
8548 else if (strcmp(origin_s, "igp") == 0)
8549 origin = BGP_ORIGIN_IGP;
8550 else if (strcmp(origin_s, "incomplete") == 0)
8551 origin = BGP_ORIGIN_INCOMPLETE;
8552 }
90e21f35 8553
585f1adc
IR
8554 if (as_set_s)
8555 as_set = AGGREGATE_AS_SET;
554b3b10 8556
585f1adc 8557 /* Handle configuration removal, otherwise installation. */
554b3b10 8558 if (no)
585f1adc
IR
8559 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8560
8561 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8562 summary_only != NULL, as_set, origin,
8563 match_med != NULL, suppress_map);
8564}
8565
8566DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8567 "[no] aggregate-address X:X::X:X/M$prefix [{"
8568 "as-set$as_set_s"
8569 "|summary-only$summary_only"
cacba915 8570 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8571 "|origin <egp|igp|incomplete>$origin_s"
8572 "|matching-MED-only$match_med"
cacba915 8573 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8574 "}]",
8575 NO_STR
8576 "Configure BGP aggregate entries\n"
8577 "Aggregate prefix\n"
8578 "Generate AS set path information\n"
8579 "Filter more specific routes from updates\n"
8580 "Apply route map to aggregate network\n"
8581 "Route map name\n"
8582 "BGP origin code\n"
8583 "Remote EGP\n"
8584 "Local IGP\n"
8585 "Unknown heritage\n"
8586 "Only aggregate routes with matching MED\n"
8587 "Suppress the selected more specific routes\n"
8588 "Route map with the route selectors\n")
8589{
8590 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8591 int as_set = AGGREGATE_AS_UNSET;
8592
8593 if (origin_s) {
8594 if (strcmp(origin_s, "egp") == 0)
8595 origin = BGP_ORIGIN_EGP;
8596 else if (strcmp(origin_s, "igp") == 0)
8597 origin = BGP_ORIGIN_IGP;
8598 else if (strcmp(origin_s, "incomplete") == 0)
8599 origin = BGP_ORIGIN_INCOMPLETE;
8600 }
8601
8602 if (as_set_s)
8603 as_set = AGGREGATE_AS_SET;
8604
8605 /* Handle configuration removal, otherwise installation. */
554b3b10 8606 if (no)
585f1adc
IR
8607 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8608 SAFI_UNICAST);
554b3b10 8609
585f1adc
IR
8610 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8611 rmap_name, summary_only != NULL, as_set,
8612 origin, match_med != NULL, suppress_map);
718e3744 8613}
8614
718e3744 8615/* Redistribute route treatment. */
d62a17ae 8616void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8617 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8618 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8619 enum blackhole_type bhtype, uint32_t metric,
8620 uint8_t type, unsigned short instance,
8621 route_tag_t tag)
d62a17ae 8622{
4b7e6066 8623 struct bgp_path_info *new;
40381db7
DS
8624 struct bgp_path_info *bpi;
8625 struct bgp_path_info rmap_path;
9bcb3eef 8626 struct bgp_dest *bn;
d62a17ae 8627 struct attr attr;
8628 struct attr *new_attr;
8629 afi_t afi;
b68885f9 8630 route_map_result_t ret;
d62a17ae 8631 struct bgp_redist *red;
8632
8633 /* Make default attribute. */
0f05ea43 8634 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8635 /*
8636 * This must not be NULL to satisfy Coverity SA
8637 */
8638 assert(attr.aspath);
9de1f7ff 8639
a4d82a8a 8640 switch (nhtype) {
9de1f7ff 8641 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8642 switch (p->family) {
8643 case AF_INET:
8644 attr.nexthop.s_addr = INADDR_ANY;
8645 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8646 break;
8647 case AF_INET6:
8648 memset(&attr.mp_nexthop_global, 0,
8649 sizeof(attr.mp_nexthop_global));
8650 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8651 break;
8652 }
9de1f7ff
DS
8653 break;
8654 case NEXTHOP_TYPE_IPV4:
8655 case NEXTHOP_TYPE_IPV4_IFINDEX:
8656 attr.nexthop = nexthop->ipv4;
7226bc40 8657 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8658 break;
8659 case NEXTHOP_TYPE_IPV6:
8660 case NEXTHOP_TYPE_IPV6_IFINDEX:
8661 attr.mp_nexthop_global = nexthop->ipv6;
8662 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8663 break;
8664 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8665 switch (p->family) {
8666 case AF_INET:
9de1f7ff 8667 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8668 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8669 break;
8670 case AF_INET6:
9de1f7ff
DS
8671 memset(&attr.mp_nexthop_global, 0,
8672 sizeof(attr.mp_nexthop_global));
74489921 8673 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8674 break;
74489921 8675 }
0789eb69 8676 attr.bh_type = bhtype;
9de1f7ff 8677 break;
d62a17ae 8678 }
0789eb69 8679 attr.nh_type = nhtype;
74489921 8680 attr.nh_ifindex = ifindex;
f04a80a5 8681
d62a17ae 8682 attr.med = metric;
957f74c3 8683 attr.distance = distance;
d62a17ae 8684 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8685 attr.tag = tag;
718e3744 8686
97a52c82
DA
8687 if (metric)
8688 bgp_attr_set_aigp_metric(&attr, metric);
8689
d62a17ae 8690 afi = family2afi(p->family);
6aeb9e78 8691
d62a17ae 8692 red = bgp_redist_lookup(bgp, afi, type, instance);
8693 if (red) {
8694 struct attr attr_new;
718e3744 8695
d62a17ae 8696 /* Copy attribute for modification. */
6f4f49b2 8697 attr_new = attr;
718e3744 8698
97a52c82 8699 if (red->redist_metric_flag) {
d62a17ae 8700 attr_new.med = red->redist_metric;
97a52c82
DA
8701 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8702 }
718e3744 8703
d62a17ae 8704 /* Apply route-map. */
8705 if (red->rmap.name) {
6006b807 8706 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8707 rmap_path.peer = bgp->peer_self;
8708 rmap_path.attr = &attr_new;
718e3744 8709
d62a17ae 8710 SET_FLAG(bgp->peer_self->rmap_type,
8711 PEER_RMAP_TYPE_REDISTRIBUTE);
8712
1782514f 8713 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8714
8715 bgp->peer_self->rmap_type = 0;
8716
8717 if (ret == RMAP_DENYMATCH) {
8718 /* Free uninterned attribute. */
8719 bgp_attr_flush(&attr_new);
8720
8721 /* Unintern original. */
8722 aspath_unintern(&attr.aspath);
8723 bgp_redistribute_delete(bgp, p, type, instance);
8724 return;
8725 }
8726 }
8727
637e5ba4 8728 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8729 bgp_attr_add_gshut_community(&attr_new);
8730
d62a17ae 8731 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8732 SAFI_UNICAST, p, NULL);
8733
8734 new_attr = bgp_attr_intern(&attr_new);
8735
9bcb3eef 8736 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8737 if (bpi->peer == bgp->peer_self
8738 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8739 break;
8740
40381db7 8741 if (bpi) {
d62a17ae 8742 /* Ensure the (source route) type is updated. */
40381db7
DS
8743 bpi->type = type;
8744 if (attrhash_cmp(bpi->attr, new_attr)
8745 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8746 bgp_attr_unintern(&new_attr);
8747 aspath_unintern(&attr.aspath);
9bcb3eef 8748 bgp_dest_unlock_node(bn);
d62a17ae 8749 return;
8750 } else {
8751 /* The attribute is changed. */
40381db7 8752 bgp_path_info_set_flag(bn, bpi,
18ee8310 8753 BGP_PATH_ATTR_CHANGED);
d62a17ae 8754
8755 /* Rewrite BGP route information. */
40381db7
DS
8756 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8757 bgp_path_info_restore(bn, bpi);
d62a17ae 8758 else
40381db7
DS
8759 bgp_aggregate_decrement(
8760 bgp, p, bpi, afi, SAFI_UNICAST);
8761 bgp_attr_unintern(&bpi->attr);
8762 bpi->attr = new_attr;
083ec940 8763 bpi->uptime = monotime(NULL);
d62a17ae 8764
8765 /* Process change. */
40381db7 8766 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8767 SAFI_UNICAST);
8768 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8769 bgp_dest_unlock_node(bn);
d62a17ae 8770 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8771
8772 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8773 || (bgp->inst_type
8774 == BGP_INSTANCE_TYPE_DEFAULT)) {
8775
8776 vpn_leak_from_vrf_update(
40381db7 8777 bgp_get_default(), bgp, bpi);
ddb5b488 8778 }
d62a17ae 8779 return;
8780 }
8781 }
8782
8783 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8784 bgp->peer_self, new_attr, bn);
1defdda8 8785 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8786
8787 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8788 bgp_path_info_add(bn, new);
9bcb3eef 8789 bgp_dest_unlock_node(bn);
be785e35 8790 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8791 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8792
8793 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8794 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8795
8796 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8797 }
d62a17ae 8798 }
8799
8800 /* Unintern original. */
8801 aspath_unintern(&attr.aspath);
718e3744 8802}
8803
d7c0a89a
QY
8804void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8805 unsigned short instance)
718e3744 8806{
d62a17ae 8807 afi_t afi;
9bcb3eef 8808 struct bgp_dest *dest;
40381db7 8809 struct bgp_path_info *pi;
d62a17ae 8810 struct bgp_redist *red;
718e3744 8811
d62a17ae 8812 afi = family2afi(p->family);
718e3744 8813
d62a17ae 8814 red = bgp_redist_lookup(bgp, afi, type, instance);
8815 if (red) {
9bcb3eef
DS
8816 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8817 SAFI_UNICAST, p, NULL);
d62a17ae 8818
9bcb3eef 8819 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8820 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8821 break;
8822
40381db7 8823 if (pi) {
ddb5b488
PZ
8824 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8825 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8826
8827 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8828 bgp, pi);
ddb5b488 8829 }
40381db7 8830 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8831 bgp_path_info_delete(dest, pi);
8832 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8833 }
9bcb3eef 8834 bgp_dest_unlock_node(dest);
d62a17ae 8835 }
8836}
8837
8838/* Withdraw specified route type's route. */
8839void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8840 unsigned short instance)
d62a17ae 8841{
9bcb3eef 8842 struct bgp_dest *dest;
40381db7 8843 struct bgp_path_info *pi;
d62a17ae 8844 struct bgp_table *table;
8845
8846 table = bgp->rib[afi][SAFI_UNICAST];
8847
9bcb3eef
DS
8848 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8849 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8850 if (pi->peer == bgp->peer_self && pi->type == type
8851 && pi->instance == instance)
d62a17ae 8852 break;
8853
40381db7 8854 if (pi) {
ddb5b488
PZ
8855 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8856 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8857
8858 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8859 bgp, pi);
ddb5b488 8860 }
9bcb3eef 8861 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8862 pi, afi, SAFI_UNICAST);
9bcb3eef 8863 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8864 if (!CHECK_FLAG(bgp->flags,
8865 BGP_FLAG_DELETE_IN_PROGRESS))
8866 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8867 else
8868 bgp_path_info_reap(dest, pi);
d62a17ae 8869 }
718e3744 8870 }
718e3744 8871}
6b0655a2 8872
718e3744 8873/* Static function to display route. */
7d3cae70
DA
8874static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8875 struct vty *vty, json_object *json, bool wide)
718e3744 8876{
be054588 8877 int len = 0;
07380148 8878 char buf[INET6_ADDRSTRLEN];
718e3744 8879
d62a17ae 8880 if (p->family == AF_INET) {
c6462ff4 8881 if (!json) {
8228a9a7 8882 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8883 } else {
8884 json_object_string_add(json, "prefix",
8885 inet_ntop(p->family,
8886 &p->u.prefix, buf,
07380148 8887 sizeof(buf)));
c6462ff4 8888 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8889 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8890 json_object_int_add(json, "version", dest->version);
c6462ff4 8891 }
d62a17ae 8892 } else if (p->family == AF_ETHERNET) {
8228a9a7 8893 len = vty_out(vty, "%pFX", p);
b03b8898 8894 } else if (p->family == AF_EVPN) {
57f7feb6 8895 if (!json)
2dbe669b 8896 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8897 else
60466a63 8898 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8899 } else if (p->family == AF_FLOWSPEC) {
8900 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8901 json ?
8902 NLRI_STRING_FORMAT_JSON_SIMPLE :
8903 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8904 } else {
c6462ff4 8905 if (!json)
8228a9a7 8906 len = vty_out(vty, "%pFX", p);
50e05855
AD
8907 else {
8908 json_object_string_add(json, "prefix",
07380148
DA
8909 inet_ntop(p->family,
8910 &p->u.prefix, buf,
8911 sizeof(buf)));
50e05855 8912 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8913 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8914 json_object_int_add(json, "version", dest->version);
37d4e0df 8915 }
9c92b5f7 8916 }
d62a17ae 8917
9c92b5f7 8918 if (!json) {
ae248832 8919 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8920 if (len < 1)
8921 vty_out(vty, "\n%*s", 20, " ");
8922 else
8923 vty_out(vty, "%*s", len, " ");
8924 }
718e3744 8925}
8926
d62a17ae 8927enum bgp_display_type {
8928 normal_list,
718e3744 8929};
8930
1d7260a1 8931const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8932{
8933 switch (reason) {
8934 case bgp_path_selection_none:
8935 return "Nothing to Select";
8936 case bgp_path_selection_first:
8937 return "First path received";
8938 case bgp_path_selection_evpn_sticky_mac:
8939 return "EVPN Sticky Mac";
8940 case bgp_path_selection_evpn_seq:
8941 return "EVPN sequence number";
8942 case bgp_path_selection_evpn_lower_ip:
8943 return "EVPN lower IP";
8944 case bgp_path_selection_evpn_local_path:
8945 return "EVPN local ES path";
8946 case bgp_path_selection_evpn_non_proxy:
8947 return "EVPN non proxy";
8948 case bgp_path_selection_weight:
8949 return "Weight";
8950 case bgp_path_selection_local_pref:
8951 return "Local Pref";
46dbf9d0
DA
8952 case bgp_path_selection_accept_own:
8953 return "Accept Own";
bbb46eb5
DA
8954 case bgp_path_selection_local_route:
8955 return "Local Route";
97a52c82
DA
8956 case bgp_path_selection_aigp:
8957 return "AIGP";
bbb46eb5
DA
8958 case bgp_path_selection_confed_as_path:
8959 return "Confederation based AS Path";
8960 case bgp_path_selection_as_path:
8961 return "AS Path";
8962 case bgp_path_selection_origin:
8963 return "Origin";
8964 case bgp_path_selection_med:
8965 return "MED";
8966 case bgp_path_selection_peer:
8967 return "Peer Type";
8968 case bgp_path_selection_confed:
8969 return "Confed Peer Type";
8970 case bgp_path_selection_igp_metric:
8971 return "IGP Metric";
8972 case bgp_path_selection_older:
8973 return "Older Path";
8974 case bgp_path_selection_router_id:
8975 return "Router ID";
8976 case bgp_path_selection_cluster_length:
bcab253c 8977 return "Cluster length";
bbb46eb5
DA
8978 case bgp_path_selection_stale:
8979 return "Path Staleness";
8980 case bgp_path_selection_local_configured:
8981 return "Locally configured route";
8982 case bgp_path_selection_neighbor_ip:
8983 return "Neighbor IP";
8984 case bgp_path_selection_default:
8985 return "Nothing left to compare";
8986 }
8987 return "Invalid (internal error)";
8988}
8989
18ee8310 8990/* Print the short form route status for a bgp_path_info */
4b7e6066 8991static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8992 struct bgp_path_info *path,
82c298be 8993 const struct prefix *p,
d62a17ae 8994 json_object *json_path)
718e3744 8995{
82c298be
DA
8996 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8997
d62a17ae 8998 if (json_path) {
b05a1c8b 8999
d62a17ae 9000 /* Route status display. */
9b6d8fcf 9001 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9002 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9003
9b6d8fcf 9004 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9005 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9006
4056a5f6 9007 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9008 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9009
9b6d8fcf
DS
9010 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9011 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9012 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9013
d62a17ae 9014 /* Selected */
9b6d8fcf 9015 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9016 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9017
9b6d8fcf 9018 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9019 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9020
bbb46eb5 9021 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9022 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9023 json_object_string_add(json_path, "selectionReason",
9024 bgp_path_selection_reason2str(
9025 path->net->reason));
9026 }
b05a1c8b 9027
9b6d8fcf 9028 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9029 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9030
d62a17ae 9031 /* Internal route. */
9b6d8fcf
DS
9032 if ((path->peer->as)
9033 && (path->peer->as == path->peer->local_as))
d62a17ae 9034 json_object_string_add(json_path, "pathFrom",
9035 "internal");
9036 else
9037 json_object_string_add(json_path, "pathFrom",
9038 "external");
b05a1c8b 9039
d62a17ae 9040 return;
9041 }
b05a1c8b 9042
82c298be
DA
9043 /* RPKI validation state */
9044 rpki_state =
9045 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9046
9047 if (rpki_state == RPKI_VALID)
9048 vty_out(vty, "V");
9049 else if (rpki_state == RPKI_INVALID)
9050 vty_out(vty, "I");
9051 else if (rpki_state == RPKI_NOTFOUND)
9052 vty_out(vty, "N");
eaeba5e8
WM
9053 else
9054 vty_out(vty, " ");
82c298be 9055
d62a17ae 9056 /* Route status display. */
9b6d8fcf 9057 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9058 vty_out(vty, "R");
9b6d8fcf 9059 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9060 vty_out(vty, "S");
4056a5f6 9061 else if (bgp_path_suppressed(path))
d62a17ae 9062 vty_out(vty, "s");
9b6d8fcf
DS
9063 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9064 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9065 vty_out(vty, "*");
9066 else
9067 vty_out(vty, " ");
9068
9069 /* Selected */
9b6d8fcf 9070 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9071 vty_out(vty, "h");
9b6d8fcf 9072 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9073 vty_out(vty, "d");
9b6d8fcf 9074 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9075 vty_out(vty, ">");
9b6d8fcf 9076 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9077 vty_out(vty, "=");
9078 else
9079 vty_out(vty, " ");
718e3744 9080
d62a17ae 9081 /* Internal route. */
9b6d8fcf
DS
9082 if (path->peer && (path->peer->as)
9083 && (path->peer->as == path->peer->local_as))
d62a17ae 9084 vty_out(vty, "i");
9085 else
9086 vty_out(vty, " ");
b40d939b 9087}
9088
2ba93fd6
DA
9089static char *bgp_nexthop_hostname(struct peer *peer,
9090 struct bgp_nexthop_cache *bnc)
25b5da8d 9091{
892fedb6 9092 if (peer->hostname
aef999a2 9093 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9094 return peer->hostname;
9095 return NULL;
9096}
9097
b40d939b 9098/* called from terminal list command */
bd494ec5 9099void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9100 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9101 json_object *json_paths, bool wide)
d62a17ae 9102{
aef999a2 9103 int len;
515c2602 9104 struct attr *attr = path->attr;
d62a17ae 9105 json_object *json_path = NULL;
9106 json_object *json_nexthops = NULL;
9107 json_object *json_nexthop_global = NULL;
9108 json_object *json_nexthop_ll = NULL;
6f214dd3 9109 json_object *json_ext_community = NULL;
9df8b37c 9110 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9111 bool nexthop_self =
9b6d8fcf 9112 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9113 bool nexthop_othervrf = false;
43089216 9114 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9115 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9116 char *nexthop_hostname =
9117 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9118 char esi_buf[ESI_STR_LEN];
d62a17ae 9119
9120 if (json_paths)
9121 json_path = json_object_new_object();
9122
9123 /* short status lead text */
82c298be 9124 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9125
9126 if (!json_paths) {
9127 /* print prefix and mask */
9128 if (!display)
7d3cae70 9129 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9130 else
ae248832 9131 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9132 } else {
7d3cae70 9133 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9134 }
47fc97cc 9135
9df8b37c
PZ
9136 /*
9137 * If vrf id of nexthop is different from that of prefix,
9138 * set up printable string to append
9139 */
9b6d8fcf 9140 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9141 const char *self = "";
9142
9143 if (nexthop_self)
9144 self = "<";
9145
9146 nexthop_othervrf = true;
9b6d8fcf 9147 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9148
9b6d8fcf 9149 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9150 snprintf(vrf_id_str, sizeof(vrf_id_str),
9151 "@%s%s", VRFID_NONE_STR, self);
9152 else
9153 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9154 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9155
9b6d8fcf
DS
9156 if (path->extra->bgp_orig->inst_type
9157 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9158
9b6d8fcf 9159 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9160 } else {
9161 const char *self = "";
9162
9163 if (nexthop_self)
9164 self = "<";
9165
9166 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9167 }
9168
445c2480
DS
9169 /*
9170 * For ENCAP and EVPN routes, nexthop address family is not
9171 * neccessarily the same as the prefix address family.
9172 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9173 * EVPN routes are also exchanged with a MP nexthop. Currently,
9174 * this
9175 * is only IPv4, the value will be present in either
9176 * attr->nexthop or
9177 * attr->mp_nexthop_global_in
9178 */
9179 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9180 char nexthop[128];
9181 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9182
9183 switch (af) {
9184 case AF_INET:
07380148
DA
9185 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9186 &attr->mp_nexthop_global_in);
445c2480
DS
9187 break;
9188 case AF_INET6:
07380148
DA
9189 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9190 &attr->mp_nexthop_global);
445c2480
DS
9191 break;
9192 default:
772270f3 9193 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9194 break;
d62a17ae 9195 }
d62a17ae 9196
445c2480
DS
9197 if (json_paths) {
9198 json_nexthop_global = json_object_new_object();
9199
515c2602
DA
9200 json_object_string_add(json_nexthop_global, "ip",
9201 nexthop);
9202
939a97f4 9203 if (path->peer->hostname)
515c2602
DA
9204 json_object_string_add(json_nexthop_global,
9205 "hostname",
939a97f4 9206 path->peer->hostname);
515c2602
DA
9207
9208 json_object_string_add(json_nexthop_global, "afi",
9209 (af == AF_INET) ? "ipv4"
9210 : "ipv6");
445c2480
DS
9211 json_object_boolean_true_add(json_nexthop_global,
9212 "used");
aef999a2
DA
9213 } else {
9214 if (nexthop_hostname)
9215 len = vty_out(vty, "%s(%s)%s", nexthop,
9216 nexthop_hostname, vrf_id_str);
9217 else
9218 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9219
ae248832 9220 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9221 if (len < 1)
9222 vty_out(vty, "\n%*s", 36, " ");
9223 else
9224 vty_out(vty, "%*s", len, " ");
9225 }
445c2480
DS
9226 } else if (safi == SAFI_EVPN) {
9227 if (json_paths) {
9228 json_nexthop_global = json_object_new_object();
9229
c949c771 9230 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9231 "%pI4",
9232 &attr->mp_nexthop_global_in);
515c2602 9233
939a97f4 9234 if (path->peer->hostname)
515c2602
DA
9235 json_object_string_add(json_nexthop_global,
9236 "hostname",
939a97f4 9237 path->peer->hostname);
515c2602 9238
a4d82a8a
PZ
9239 json_object_string_add(json_nexthop_global, "afi",
9240 "ipv4");
445c2480
DS
9241 json_object_boolean_true_add(json_nexthop_global,
9242 "used");
aef999a2
DA
9243 } else {
9244 if (nexthop_hostname)
7226bc40
TA
9245 len = vty_out(vty, "%pI4(%s)%s",
9246 &attr->mp_nexthop_global_in,
aef999a2
DA
9247 nexthop_hostname, vrf_id_str);
9248 else
7226bc40
TA
9249 len = vty_out(vty, "%pI4%s",
9250 &attr->mp_nexthop_global_in,
aef999a2
DA
9251 vrf_id_str);
9252
ae248832 9253 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9254 if (len < 1)
9255 vty_out(vty, "\n%*s", 36, " ");
9256 else
9257 vty_out(vty, "%*s", len, " ");
9258 }
d33fc23b 9259 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9260 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9261 if (json_paths) {
9262 json_nexthop_global = json_object_new_object();
515c2602 9263
026b914a
PG
9264 json_object_string_add(json_nexthop_global,
9265 "afi", "ipv4");
c949c771
DA
9266 json_object_string_addf(json_nexthop_global,
9267 "ip", "%pI4",
9268 &attr->nexthop);
515c2602 9269
939a97f4 9270 if (path->peer->hostname)
515c2602
DA
9271 json_object_string_add(
9272 json_nexthop_global, "hostname",
939a97f4 9273 path->peer->hostname);
515c2602 9274
50e05855
AD
9275 json_object_boolean_true_add(
9276 json_nexthop_global,
026b914a
PG
9277 "used");
9278 } else {
aef999a2
DA
9279 if (nexthop_hostname)
9280 len = vty_out(vty, "%pI4(%s)%s",
9281 &attr->nexthop,
9282 nexthop_hostname,
9283 vrf_id_str);
9284 else
9285 len = vty_out(vty, "%pI4%s",
9286 &attr->nexthop,
9287 vrf_id_str);
9288
ae248832 9289 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9290 if (len < 1)
9291 vty_out(vty, "\n%*s", 36, " ");
9292 else
9293 vty_out(vty, "%*s", len, " ");
026b914a
PG
9294 }
9295 }
7226bc40 9296 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9297 if (json_paths) {
9298 json_nexthop_global = json_object_new_object();
d62a17ae 9299
c949c771
DA
9300 json_object_string_addf(json_nexthop_global, "ip",
9301 "%pI4", &attr->nexthop);
515c2602 9302
939a97f4 9303 if (path->peer->hostname)
515c2602
DA
9304 json_object_string_add(json_nexthop_global,
9305 "hostname",
939a97f4 9306 path->peer->hostname);
445c2480 9307
a4d82a8a
PZ
9308 json_object_string_add(json_nexthop_global, "afi",
9309 "ipv4");
445c2480
DS
9310 json_object_boolean_true_add(json_nexthop_global,
9311 "used");
9312 } else {
aef999a2
DA
9313 if (nexthop_hostname)
9314 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9315 nexthop_hostname, vrf_id_str);
9316 else
9317 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9318 vrf_id_str);
9df8b37c 9319
ae248832 9320 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9321 if (len < 1)
9322 vty_out(vty, "\n%*s", 36, " ");
9323 else
9324 vty_out(vty, "%*s", len, " ");
d62a17ae 9325 }
445c2480 9326 }
b05a1c8b 9327
445c2480 9328 /* IPv6 Next Hop */
7226bc40 9329 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9330 if (json_paths) {
9331 json_nexthop_global = json_object_new_object();
c949c771
DA
9332 json_object_string_addf(json_nexthop_global, "ip",
9333 "%pI6",
9334 &attr->mp_nexthop_global);
515c2602 9335
939a97f4 9336 if (path->peer->hostname)
515c2602
DA
9337 json_object_string_add(json_nexthop_global,
9338 "hostname",
939a97f4 9339 path->peer->hostname);
515c2602 9340
a4d82a8a
PZ
9341 json_object_string_add(json_nexthop_global, "afi",
9342 "ipv6");
9343 json_object_string_add(json_nexthop_global, "scope",
9344 "global");
445c2480
DS
9345
9346 /* We display both LL & GL if both have been
9347 * received */
0606039c
DA
9348 if ((attr->mp_nexthop_len
9349 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9350 || (path->peer->conf_if)) {
a4d82a8a 9351 json_nexthop_ll = json_object_new_object();
c949c771
DA
9352 json_object_string_addf(
9353 json_nexthop_ll, "ip", "%pI6",
9354 &attr->mp_nexthop_local);
515c2602 9355
939a97f4 9356 if (path->peer->hostname)
515c2602
DA
9357 json_object_string_add(
9358 json_nexthop_ll, "hostname",
939a97f4 9359 path->peer->hostname);
515c2602 9360
a4d82a8a
PZ
9361 json_object_string_add(json_nexthop_ll, "afi",
9362 "ipv6");
9363 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9364 "link-local");
d62a17ae 9365
a4d82a8a 9366 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9367 &attr->mp_nexthop_local)
9368 != 0)
9369 && !attr->mp_nexthop_prefer_global)
d62a17ae 9370 json_object_boolean_true_add(
a4d82a8a 9371 json_nexthop_ll, "used");
445c2480
DS
9372 else
9373 json_object_boolean_true_add(
a4d82a8a 9374 json_nexthop_global, "used");
445c2480
DS
9375 } else
9376 json_object_boolean_true_add(
9377 json_nexthop_global, "used");
9378 } else {
9379 /* Display LL if LL/Global both in table unless
9380 * prefer-global is set */
2bb8b49c
DS
9381 if (((attr->mp_nexthop_len
9382 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9383 && !attr->mp_nexthop_prefer_global)
9384 || (path->peer->conf_if)) {
9b6d8fcf 9385 if (path->peer->conf_if) {
a4d82a8a 9386 len = vty_out(vty, "%s",
9b6d8fcf 9387 path->peer->conf_if);
ae248832
MK
9388 /* len of IPv6 addr + max len of def
9389 * ifname */
9390 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9391
9392 if (len < 1)
a4d82a8a 9393 vty_out(vty, "\n%*s", 36, " ");
445c2480 9394 else
a4d82a8a 9395 vty_out(vty, "%*s", len, " ");
d62a17ae 9396 } else {
aef999a2
DA
9397 if (nexthop_hostname)
9398 len = vty_out(
9399 vty, "%pI6(%s)%s",
9400 &attr->mp_nexthop_local,
9401 nexthop_hostname,
9402 vrf_id_str);
9403 else
9404 len = vty_out(
9405 vty, "%pI6%s",
9406 &attr->mp_nexthop_local,
9407 vrf_id_str);
9408
ae248832 9409 len = wide ? (41 - len) : (16 - len);
d62a17ae 9410
9411 if (len < 1)
a4d82a8a 9412 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9413 else
a4d82a8a 9414 vty_out(vty, "%*s", len, " ");
d62a17ae 9415 }
445c2480 9416 } else {
aef999a2
DA
9417 if (nexthop_hostname)
9418 len = vty_out(vty, "%pI6(%s)%s",
9419 &attr->mp_nexthop_global,
9420 nexthop_hostname,
9421 vrf_id_str);
9422 else
9423 len = vty_out(vty, "%pI6%s",
9424 &attr->mp_nexthop_global,
9425 vrf_id_str);
9426
ae248832 9427 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9428
9429 if (len < 1)
9430 vty_out(vty, "\n%*s", 36, " ");
9431 else
9432 vty_out(vty, "%*s", len, " ");
d62a17ae 9433 }
9434 }
445c2480 9435 }
718e3744 9436
445c2480
DS
9437 /* MED/Metric */
9438 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9439 if (json_paths)
50e05855 9440 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9441 else if (wide)
9442 vty_out(vty, "%7u", attr->med);
0fbac0b4 9443 else
445c2480 9444 vty_out(vty, "%10u", attr->med);
ae248832
MK
9445 else if (!json_paths) {
9446 if (wide)
9447 vty_out(vty, "%*s", 7, " ");
9448 else
9449 vty_out(vty, "%*s", 10, " ");
9450 }
d62a17ae 9451
445c2480
DS
9452 /* Local Pref */
9453 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9454 if (json_paths)
50e05855 9455 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9456 attr->local_pref);
9457 else
445c2480
DS
9458 vty_out(vty, "%7u", attr->local_pref);
9459 else if (!json_paths)
9460 vty_out(vty, " ");
d62a17ae 9461
445c2480
DS
9462 if (json_paths)
9463 json_object_int_add(json_path, "weight", attr->weight);
9464 else
9465 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9466
47e12884
DA
9467 if (json_paths)
9468 json_object_string_addf(json_path, "peerId", "%pSU",
9469 &path->peer->su);
b05a1c8b 9470
445c2480
DS
9471 /* Print aspath */
9472 if (attr->aspath) {
0fbac0b4 9473 if (json_paths)
50e05855 9474 json_object_string_add(json_path, "path",
0fbac0b4
DA
9475 attr->aspath->str);
9476 else
e678b143 9477 aspath_print_vty(vty, attr->aspath);
d62a17ae 9478 }
f1aa5d8a 9479
445c2480
DS
9480 /* Print origin */
9481 if (json_paths)
a4d82a8a
PZ
9482 json_object_string_add(json_path, "origin",
9483 bgp_origin_long_str[attr->origin]);
445c2480
DS
9484 else
9485 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9486
9df8b37c 9487 if (json_paths) {
d071f237 9488 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9489 json_object_string_add(json_path, "esi",
9490 esi_to_str(&attr->esi,
9491 esi_buf, sizeof(esi_buf)));
9492 }
6f214dd3
CS
9493 if (safi == SAFI_EVPN &&
9494 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9495 json_ext_community = json_object_new_object();
b53e67a3
DA
9496 json_object_string_add(
9497 json_ext_community, "string",
9498 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9499 json_object_object_add(json_path,
9500 "extendedCommunity",
9501 json_ext_community);
9502 }
9503
9df8b37c
PZ
9504 if (nexthop_self)
9505 json_object_boolean_true_add(json_path,
9506 "announceNexthopSelf");
9507 if (nexthop_othervrf) {
9508 json_object_string_add(json_path, "nhVrfName",
9509 nexthop_vrfname);
9510
9511 json_object_int_add(json_path, "nhVrfId",
9512 ((nexthop_vrfid == VRF_UNKNOWN)
9513 ? -1
9514 : (int)nexthop_vrfid));
9515 }
9516 }
9517
d62a17ae 9518 if (json_paths) {
9519 if (json_nexthop_global || json_nexthop_ll) {
9520 json_nexthops = json_object_new_array();
f1aa5d8a 9521
d62a17ae 9522 if (json_nexthop_global)
9523 json_object_array_add(json_nexthops,
9524 json_nexthop_global);
f1aa5d8a 9525
d62a17ae 9526 if (json_nexthop_ll)
9527 json_object_array_add(json_nexthops,
9528 json_nexthop_ll);
f1aa5d8a 9529
d62a17ae 9530 json_object_object_add(json_path, "nexthops",
9531 json_nexthops);
9532 }
9533
9534 json_object_array_add(json_paths, json_path);
9535 } else {
9536 vty_out(vty, "\n");
6f214dd3 9537
b5e140c8 9538 if (safi == SAFI_EVPN) {
d071f237 9539 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9540 /* XXX - add these params to the json out */
b5e140c8 9541 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9542 vty_out(vty, "ESI:%s",
9543 esi_to_str(&attr->esi, esi_buf,
9544 sizeof(esi_buf)));
60605cbc 9545
229587fb 9546 vty_out(vty, "\n");
b5e140c8
AK
9547 }
9548 if (attr->flag &
9549 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9550 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9551 vty_out(vty, "%s\n",
9552 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9553 }
6f214dd3
CS
9554 }
9555
49e5a4a0 9556#ifdef ENABLE_BGP_VNC
d62a17ae 9557 /* prints an additional line, indented, with VNC info, if
9558 * present */
9559 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9560 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9561#endif
d62a17ae 9562 }
9563}
718e3744 9564
9565/* called from terminal list command */
7d3cae70
DA
9566void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9567 const struct prefix *p, struct attr *attr, safi_t safi,
9568 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9569{
9570 json_object *json_status = NULL;
9571 json_object *json_net = NULL;
aef999a2 9572 int len;
d62a17ae 9573 char buff[BUFSIZ];
dc387b0f 9574
d62a17ae 9575 /* Route status display. */
9576 if (use_json) {
9577 json_status = json_object_new_object();
9578 json_net = json_object_new_object();
9579 } else {
146c574b 9580 vty_out(vty, " *");
d62a17ae 9581 vty_out(vty, ">");
9582 vty_out(vty, " ");
9583 }
718e3744 9584
d62a17ae 9585 /* print prefix and mask */
50e05855 9586 if (use_json) {
dc387b0f
LK
9587 if (safi == SAFI_EVPN)
9588 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9589 else if (p->family == AF_INET || p->family == AF_INET6) {
9590 json_object_string_add(
9591 json_net, "addrPrefix",
9592 inet_ntop(p->family, &p->u.prefix, buff,
9593 BUFSIZ));
9594 json_object_int_add(json_net, "prefixLen",
9595 p->prefixlen);
67d7e256 9596 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9597 }
50e05855 9598 } else
7d3cae70 9599 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9600
9601 /* Print attribute */
9602 if (attr) {
9603 if (use_json) {
7226bc40
TA
9604 if (p->family == AF_INET &&
9605 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9606 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9607 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9608 json_object_string_addf(
9609 json_net, "nextHop", "%pI4",
9610 &attr->mp_nexthop_global_in);
d62a17ae 9611 else
c949c771
DA
9612 json_object_string_addf(
9613 json_net, "nextHop", "%pI4",
9614 &attr->nexthop);
7226bc40
TA
9615 } else if (p->family == AF_INET6 ||
9616 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9617 json_object_string_addf(
9618 json_net, "nextHopGlobal", "%pI6",
9619 &attr->mp_nexthop_global);
7226bc40
TA
9620 } else if (p->family == AF_EVPN &&
9621 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9622 json_object_string_addf(
9623 json_net, "nextHop", "%pI4",
9624 &attr->mp_nexthop_global_in);
23d0a753 9625 }
d62a17ae 9626
9627 if (attr->flag
9628 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9629 json_object_int_add(json_net, "metric",
9630 attr->med);
9631
0fbac0b4 9632 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9633 json_object_int_add(json_net, "locPrf",
0fbac0b4 9634 attr->local_pref);
d62a17ae 9635
9636 json_object_int_add(json_net, "weight", attr->weight);
9637
9638 /* Print aspath */
0fbac0b4 9639 if (attr->aspath)
50e05855 9640 json_object_string_add(json_net, "path",
0fbac0b4 9641 attr->aspath->str);
d62a17ae 9642
9643 /* Print origin */
dd426a51
DA
9644#if CONFDATE > 20231208
9645CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9646#endif
d62a17ae 9647 json_object_string_add(json_net, "bgpOriginCode",
9648 bgp_origin_str[attr->origin]);
dd426a51
DA
9649 json_object_string_add(
9650 json_net, "origin",
9651 bgp_origin_long_str[attr->origin]);
d62a17ae 9652 } else {
7226bc40
TA
9653 if (p->family == AF_INET &&
9654 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9655 safi == SAFI_EVPN ||
9656 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9657 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9658 || safi == SAFI_EVPN)
23d0a753
DA
9659 vty_out(vty, "%-16pI4",
9660 &attr->mp_nexthop_global_in);
ae248832 9661 else if (wide)
23d0a753 9662 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9663 else
23d0a753 9664 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9665 } else if (p->family == AF_INET6 ||
9666 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9667 len = vty_out(vty, "%pI6",
9668 &attr->mp_nexthop_global);
ae248832 9669 len = wide ? (41 - len) : (16 - len);
d62a17ae 9670 if (len < 1)
9671 vty_out(vty, "\n%*s", 36, " ");
9672 else
9673 vty_out(vty, "%*s", len, " ");
9674 }
9675 if (attr->flag
9676 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9677 if (wide)
9678 vty_out(vty, "%7u", attr->med);
9679 else
9680 vty_out(vty, "%10u", attr->med);
9681 else if (wide)
9682 vty_out(vty, " ");
d62a17ae 9683 else
9684 vty_out(vty, " ");
718e3744 9685
d62a17ae 9686 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9687 vty_out(vty, "%7u", attr->local_pref);
9688 else
9689 vty_out(vty, " ");
9690
9691 vty_out(vty, "%7u ", attr->weight);
9692
9693 /* Print aspath */
9694 if (attr->aspath)
e678b143 9695 aspath_print_vty(vty, attr->aspath);
d62a17ae 9696
9697 /* Print origin */
9698 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9699 }
9700 }
9701 if (use_json) {
4d65410c
DA
9702 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9703
dd426a51
DA
9704#if CONFDATE > 20231208
9705CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9706#endif
d62a17ae 9707 json_object_boolean_true_add(json_status, "*");
9708 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9709 json_object_boolean_true_add(json_net, "valid");
9710 json_object_boolean_true_add(json_net, "best");
4d65410c 9711
dd426a51 9712 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9713 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9714 json_object_boolean_true_add(json_net, "multipath");
9715 }
d62a17ae 9716 json_object_object_add(json_net, "appliedStatusSymbols",
9717 json_status);
511211bf 9718 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9719 } else
9720 vty_out(vty, "\n");
9721}
9722
bd494ec5 9723void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9724 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9725 json_object *json)
9726{
9727 json_object *json_out = NULL;
9728 struct attr *attr;
9729 mpls_label_t label = MPLS_INVALID_LABEL;
9730
9b6d8fcf 9731 if (!path->extra)
d62a17ae 9732 return;
9733
9734 if (json)
9735 json_out = json_object_new_object();
9736
9737 /* short status lead text */
82c298be 9738 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9739
9740 /* print prefix and mask */
9741 if (json == NULL) {
9742 if (!display)
7d3cae70 9743 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9744 else
9745 vty_out(vty, "%*s", 17, " ");
9746 }
9747
9748 /* Print attribute */
9b6d8fcf 9749 attr = path->attr;
7226bc40
TA
9750 if (((p->family == AF_INET) &&
9751 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9752 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9753 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9754 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9755 || safi == SAFI_EVPN) {
9756 if (json)
c949c771
DA
9757 json_object_string_addf(
9758 json_out, "mpNexthopGlobalIn", "%pI4",
9759 &attr->mp_nexthop_global_in);
05864da7 9760 else
23d0a753
DA
9761 vty_out(vty, "%-16pI4",
9762 &attr->mp_nexthop_global_in);
05864da7
DS
9763 } else {
9764 if (json)
c949c771
DA
9765 json_object_string_addf(json_out, "nexthop",
9766 "%pI4", &attr->nexthop);
05864da7 9767 else
23d0a753 9768 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9769 }
7226bc40
TA
9770 } else if (((p->family == AF_INET6) &&
9771 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9772 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9773 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9774 char buf_a[512];
9775
9776 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9777 if (json)
c949c771
DA
9778 json_object_string_addf(
9779 json_out, "mpNexthopGlobalIn", "%pI6",
9780 &attr->mp_nexthop_global);
05864da7
DS
9781 else
9782 vty_out(vty, "%s",
9783 inet_ntop(AF_INET6,
9784 &attr->mp_nexthop_global,
9785 buf_a, sizeof(buf_a)));
9786 } else if (attr->mp_nexthop_len
9787 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9788 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9789 &attr->mp_nexthop_global,
9790 &attr->mp_nexthop_local);
9791 if (json)
9792 json_object_string_add(json_out,
9793 "mpNexthopGlobalLocal",
9794 buf_a);
9795 else
9796 vty_out(vty, "%s", buf_a);
d62a17ae 9797 }
9798 }
9799
9b6d8fcf 9800 label = decode_label(&path->extra->label[0]);
d62a17ae 9801
9802 if (bgp_is_valid_label(&label)) {
9803 if (json) {
9804 json_object_int_add(json_out, "notag", label);
9805 json_object_array_add(json, json_out);
9806 } else {
9807 vty_out(vty, "notag/%d", label);
9808 vty_out(vty, "\n");
9809 }
700ddfed
PG
9810 } else if (!json)
9811 vty_out(vty, "\n");
d62a17ae 9812}
718e3744 9813
bd494ec5 9814void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9815 struct bgp_path_info *path, int display,
d62a17ae 9816 json_object *json_paths)
718e3744 9817{
d62a17ae 9818 struct attr *attr;
d62a17ae 9819 json_object *json_path = NULL;
14f51eba
LK
9820 json_object *json_nexthop = NULL;
9821 json_object *json_overlay = NULL;
856ca177 9822
9b6d8fcf 9823 if (!path->extra)
d62a17ae 9824 return;
718e3744 9825
14f51eba
LK
9826 if (json_paths) {
9827 json_path = json_object_new_object();
9828 json_overlay = json_object_new_object();
9829 json_nexthop = json_object_new_object();
9830 }
9831
d62a17ae 9832 /* short status lead text */
82c298be 9833 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9834
d62a17ae 9835 /* print prefix and mask */
9836 if (!display)
7d3cae70 9837 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9838 else
9839 vty_out(vty, "%*s", 17, " ");
9840
9841 /* Print attribute */
9b6d8fcf 9842 attr = path->attr;
05864da7 9843 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9844
05864da7
DS
9845 switch (af) {
9846 case AF_INET:
05864da7 9847 if (!json_path) {
db66cf7c 9848 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9849 } else {
db66cf7c
DA
9850 json_object_string_addf(json_nexthop, "ip", "%pI4",
9851 &attr->mp_nexthop_global_in);
14f51eba 9852
05864da7 9853 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9854
05864da7
DS
9855 json_object_object_add(json_path, "nexthop",
9856 json_nexthop);
9857 }
9858 break;
9859 case AF_INET6:
05864da7 9860 if (!json_path) {
db66cf7c
DA
9861 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9862 &attr->mp_nexthop_local);
05864da7 9863 } else {
db66cf7c
DA
9864 json_object_string_addf(json_nexthop, "ipv6Global",
9865 "%pI6",
9866 &attr->mp_nexthop_global);
14f51eba 9867
db66cf7c
DA
9868 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9869 "%pI6",
9870 &attr->mp_nexthop_local);
14f51eba 9871
05864da7 9872 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9873
05864da7
DS
9874 json_object_object_add(json_path, "nexthop",
9875 json_nexthop);
9876 }
9877 break;
9878 default:
9879 if (!json_path) {
9880 vty_out(vty, "?");
9881 } else {
77a2f8e5
DA
9882 json_object_string_add(json_nexthop, "error",
9883 "Unsupported address-family");
d62a17ae 9884 }
05864da7 9885 }
988258b4 9886
6c924775
DS
9887 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9888
05864da7 9889 if (!json_path)
db66cf7c 9890 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9891 else
db66cf7c 9892 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9893
b53e67a3 9894 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9895 char *mac = NULL;
9896 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9897 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9898 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9899
9900 if (routermac)
9901 mac = ecom_mac2str((char *)routermac->val);
9902 if (mac) {
9903 if (!json_path) {
c4efd0f4 9904 vty_out(vty, "/%s", mac);
05864da7
DS
9905 } else {
9906 json_object_string_add(json_overlay, "rmac",
9907 mac);
988258b4 9908 }
05864da7 9909 XFREE(MTYPE_TMP, mac);
988258b4 9910 }
05864da7 9911 }
718e3744 9912
05864da7
DS
9913 if (!json_path) {
9914 vty_out(vty, "\n");
9915 } else {
9916 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9917
05864da7 9918 json_object_array_add(json_paths, json_path);
14f51eba 9919 }
d62a17ae 9920}
718e3744 9921
d62a17ae 9922/* dampening route */
5f040085
DS
9923static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9924 struct bgp_path_info *path, int display,
9925 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9926 json_object *json_paths)
d62a17ae 9927{
e5be8c1d 9928 struct attr *attr = path->attr;
d62a17ae 9929 int len;
9930 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9931 json_object *json_path = NULL;
9932
9933 if (use_json)
9934 json_path = json_object_new_object();
d62a17ae 9935
9936 /* short status lead text */
e5be8c1d 9937 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9938
9939 /* print prefix and mask */
9940 if (!use_json) {
9941 if (!display)
7d3cae70 9942 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9943 else
9944 vty_out(vty, "%*s", 17, " ");
d62a17ae 9945
e5be8c1d
DA
9946 len = vty_out(vty, "%s", path->peer->host);
9947 len = 17 - len;
9948
9949 if (len < 1)
d62a17ae 9950 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9951 else
9952 vty_out(vty, "%*s", len, " ");
d62a17ae 9953
9b6d8fcf
DS
9954 vty_out(vty, "%s ",
9955 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9956 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9957 use_json, NULL));
d62a17ae 9958
e5be8c1d 9959 if (attr->aspath)
e678b143 9960 aspath_print_vty(vty, attr->aspath);
05864da7 9961
05864da7
DS
9962 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9963
d62a17ae 9964 vty_out(vty, "\n");
e5be8c1d
DA
9965 } else {
9966 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9967 safi, use_json, json_path);
9968
9969 if (attr->aspath)
9970 json_object_string_add(json_path, "asPath",
9971 attr->aspath->str);
9972
9973 json_object_string_add(json_path, "origin",
9974 bgp_origin_str[attr->origin]);
9975 json_object_string_add(json_path, "peerHost", path->peer->host);
9976
9977 json_object_array_add(json_paths, json_path);
9978 }
d62a17ae 9979}
718e3744 9980
d62a17ae 9981/* flap route */
5f040085
DS
9982static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9983 struct bgp_path_info *path, int display,
9984 afi_t afi, safi_t safi, bool use_json,
31258046 9985 json_object *json_paths)
784d3a42 9986{
31258046 9987 struct attr *attr = path->attr;
d62a17ae 9988 struct bgp_damp_info *bdi;
9989 char timebuf[BGP_UPTIME_LEN];
9990 int len;
31258046 9991 json_object *json_path = NULL;
784d3a42 9992
9b6d8fcf 9993 if (!path->extra)
d62a17ae 9994 return;
784d3a42 9995
31258046
DA
9996 if (use_json)
9997 json_path = json_object_new_object();
9998
9b6d8fcf 9999 bdi = path->extra->damp_info;
784d3a42 10000
d62a17ae 10001 /* short status lead text */
31258046 10002 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10003
d62a17ae 10004 if (!use_json) {
10005 if (!display)
7d3cae70 10006 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10007 else
10008 vty_out(vty, "%*s", 17, " ");
784d3a42 10009
31258046
DA
10010 len = vty_out(vty, "%s", path->peer->host);
10011 len = 16 - len;
10012 if (len < 1)
d62a17ae 10013 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10014 else
10015 vty_out(vty, "%*s", len, " ");
784d3a42 10016
31258046
DA
10017 len = vty_out(vty, "%d", bdi->flap);
10018 len = 5 - len;
10019 if (len < 1)
d62a17ae 10020 vty_out(vty, " ");
d62a17ae 10021 else
10022 vty_out(vty, "%*s", len, " ");
d62a17ae 10023
996c9314
LB
10024 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10025 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10026
31258046
DA
10027 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10028 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10029 vty_out(vty, "%s ",
9b6d8fcf 10030 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10031 BGP_UPTIME_LEN, afi,
31258046
DA
10032 safi, use_json, NULL));
10033 else
d62a17ae 10034 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10035
31258046 10036 if (attr->aspath)
e678b143 10037 aspath_print_vty(vty, attr->aspath);
05864da7 10038
05864da7
DS
10039 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10040
d62a17ae 10041 vty_out(vty, "\n");
31258046
DA
10042 } else {
10043 json_object_string_add(json_path, "peerHost", path->peer->host);
10044 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10045
10046 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10047 json_path);
10048
10049 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10050 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10051 bgp_damp_reuse_time_vty(vty, path, timebuf,
10052 BGP_UPTIME_LEN, afi, safi,
10053 use_json, json_path);
10054
10055 if (attr->aspath)
10056 json_object_string_add(json_path, "asPath",
10057 attr->aspath->str);
10058
10059 json_object_string_add(json_path, "origin",
10060 bgp_origin_str[attr->origin]);
10061
10062 json_object_array_add(json_paths, json_path);
10063 }
d62a17ae 10064}
10065
10066static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10067 int *first, const char *header,
10068 json_object *json_adv_to)
10069{
d62a17ae 10070 json_object *json_peer = NULL;
10071
10072 if (json_adv_to) {
10073 /* 'advertised-to' is a dictionary of peers we have advertised
10074 * this
10075 * prefix too. The key is the peer's IP or swpX, the value is
10076 * the
10077 * hostname if we know it and "" if not.
10078 */
10079 json_peer = json_object_new_object();
10080
10081 if (peer->hostname)
10082 json_object_string_add(json_peer, "hostname",
10083 peer->hostname);
10084
10085 if (peer->conf_if)
10086 json_object_object_add(json_adv_to, peer->conf_if,
10087 json_peer);
10088 else
47e12884
DA
10089 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10090 &peer->su);
d62a17ae 10091 } else {
10092 if (*first) {
10093 vty_out(vty, "%s", header);
10094 *first = 0;
10095 }
10096
10097 if (peer->hostname
892fedb6 10098 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10099 if (peer->conf_if)
10100 vty_out(vty, " %s(%s)", peer->hostname,
10101 peer->conf_if);
10102 else
47e12884
DA
10103 vty_out(vty, " %s(%pSU)", peer->hostname,
10104 &peer->su);
d62a17ae 10105 } else {
10106 if (peer->conf_if)
10107 vty_out(vty, " %s", peer->conf_if);
10108 else
47e12884 10109 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10110 }
10111 }
784d3a42
PG
10112}
10113
dcc68b5e
MS
10114static void route_vty_out_tx_ids(struct vty *vty,
10115 struct bgp_addpath_info_data *d)
10116{
10117 int i;
10118
10119 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10120 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10121 d->addpath_tx_id[i],
10122 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10123 }
10124}
10125
5e4d4c8a 10126static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10127 struct bgp_path_info *pi,
10128 struct attr *attr,
10129 json_object *json_path)
5e4d4c8a
AK
10130{
10131 char esi_buf[ESI_STR_LEN];
10132 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10133 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10134 ATTR_ES_PEER_ROUTER);
10135 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10136 ATTR_ES_PEER_ACTIVE);
10137 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10138 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10139 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10140 if (json_path) {
10141 json_object *json_es_info = NULL;
10142
10143 json_object_string_add(
10144 json_path, "esi",
10145 esi_buf);
10146 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10147 json_es_info = json_object_new_object();
10148 if (es_local)
10149 json_object_boolean_true_add(
10150 json_es_info, "localEs");
10151 if (peer_active)
10152 json_object_boolean_true_add(
10153 json_es_info, "peerActive");
10154 if (peer_proxy)
10155 json_object_boolean_true_add(
10156 json_es_info, "peerProxy");
10157 if (peer_router)
10158 json_object_boolean_true_add(
10159 json_es_info, "peerRouter");
10160 if (attr->mm_sync_seqnum)
10161 json_object_int_add(
10162 json_es_info, "peerSeq",
10163 attr->mm_sync_seqnum);
10164 json_object_object_add(
10165 json_path, "es_info",
10166 json_es_info);
10167 }
10168 } else {
10169 if (bgp_evpn_attr_is_sync(attr))
10170 vty_out(vty,
10171 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10172 esi_buf,
10173 es_local ? "local-es":"",
10174 peer_proxy ? "proxy " : "",
10175 peer_active ? "active ":"",
10176 peer_router ? "router ":"",
10177 attr->mm_sync_seqnum);
10178 else
10179 vty_out(vty, " ESI %s %s\n",
10180 esi_buf,
10181 es_local ? "local-es":"");
10182 }
10183}
10184
4933eaaf 10185void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10186 const struct prefix *p, struct bgp_path_info *path,
10187 afi_t afi, safi_t safi,
4027d19b
DS
10188 enum rpki_states rpki_curr_state,
10189 json_object *json_paths)
d62a17ae 10190{
10191 char buf[INET6_ADDRSTRLEN];
100290e4 10192 char tag_buf[30];
515c2602 10193 struct attr *attr = path->attr;
d62a17ae 10194 time_t tbuf;
10195 json_object *json_bestpath = NULL;
10196 json_object *json_cluster_list = NULL;
10197 json_object *json_cluster_list_list = NULL;
10198 json_object *json_ext_community = NULL;
10199 json_object *json_last_update = NULL;
7fd077aa 10200 json_object *json_pmsi = NULL;
d62a17ae 10201 json_object *json_nexthop_global = NULL;
10202 json_object *json_nexthop_ll = NULL;
10203 json_object *json_nexthops = NULL;
10204 json_object *json_path = NULL;
10205 json_object *json_peer = NULL;
10206 json_object *json_string = NULL;
10207 json_object *json_adv_to = NULL;
10208 int first = 0;
10209 struct listnode *node, *nnode;
10210 struct peer *peer;
be92fc9f 10211 bool addpath_capable;
d62a17ae 10212 int has_adj;
10213 unsigned int first_as;
1defdda8 10214 bool nexthop_self =
9b6d8fcf 10215 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10216 int i;
2ba93fd6
DA
10217 char *nexthop_hostname =
10218 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10219 uint32_t ttl = 0;
10220 uint32_t bos = 0;
10221 uint32_t exp = 0;
10222 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10223 tag_buf[0] = '\0';
f0cde006
LS
10224 struct bgp_path_info *bpi_ultimate =
10225 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10226
10227 if (json_paths) {
10228 json_path = json_object_new_object();
10229 json_peer = json_object_new_object();
10230 json_nexthop_global = json_object_new_object();
10231 }
10232
8304dabf
AD
10233 if (safi == SAFI_EVPN) {
10234 if (!json_paths)
34c7f35f 10235 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10236 }
10237
44c69747 10238 if (path->extra) {
9b6d8fcf
DS
10239 if (path->extra && path->extra->num_labels) {
10240 bgp_evpn_label2str(path->extra->label,
10241 path->extra->num_labels, tag_buf,
a4d82a8a 10242 sizeof(tag_buf));
d62a17ae 10243 }
d7325ee7 10244 if (safi == SAFI_EVPN) {
44c69747 10245 if (!json_paths) {
44c69747
LK
10246 if (tag_buf[0] != '\0')
10247 vty_out(vty, " VNI %s", tag_buf);
44c69747 10248 } else {
1ce23106 10249 if (tag_buf[0])
77a2f8e5
DA
10250 json_object_string_add(json_path, "vni",
10251 tag_buf);
44c69747 10252 }
d7325ee7 10253 }
d62a17ae 10254 }
d62a17ae 10255
8304dabf
AD
10256 if (safi == SAFI_EVPN
10257 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10258 char gwip_buf[INET6_ADDRSTRLEN];
10259
860e740b
IR
10260 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10261 sizeof(gwip_buf));
8304dabf
AD
10262
10263 if (json_paths)
10264 json_object_string_add(json_path, "gatewayIP",
10265 gwip_buf);
10266 else
10267 vty_out(vty, " Gateway IP %s", gwip_buf);
10268 }
10269
2bf9780b 10270 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10271 vty_out(vty, "\n");
10272
100290e4
SW
10273
10274 if (path->extra && path->extra->parent && !json_paths) {
10275 struct bgp_path_info *parent_ri;
10276 struct bgp_dest *dest, *pdest;
10277
10278 parent_ri = (struct bgp_path_info *)path->extra->parent;
10279 dest = parent_ri->net;
10280 if (dest && dest->pdest) {
10281 pdest = dest->pdest;
10282 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10283 vty_out(vty, " Imported from ");
10284 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10285 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10286 pdest));
10287 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10288 (struct prefix_evpn *)
10289 bgp_dest_get_prefix(dest),
10290 tag_buf);
6012963e 10291 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10292 vty_out(vty, ", L3NHG %s",
6012963e
SW
10293 CHECK_FLAG(
10294 attr->es_flags,
10295 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10296 ? "active"
10297 : "inactive");
10298 vty_out(vty, "\n");
10299
4a8cd6ad
PG
10300 } else {
10301 vty_out(vty, " Imported from ");
10302 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10303 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10304 pdest));
10305 vty_out(vty, ":%pFX\n",
100290e4
SW
10306 (struct prefix_evpn *)
10307 bgp_dest_get_prefix(dest));
4a8cd6ad 10308 }
100290e4
SW
10309 }
10310 }
10311
05864da7
DS
10312 /* Line1 display AS-path, Aggregator */
10313 if (attr->aspath) {
10314 if (json_paths) {
10315 if (!attr->aspath->json)
10316 aspath_str_update(attr->aspath, true);
10317 json_object_lock(attr->aspath->json);
10318 json_object_object_add(json_path, "aspath",
10319 attr->aspath->json);
10320 } else {
10321 if (attr->aspath->segments)
e678b143 10322 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10323 else
05864da7 10324 vty_out(vty, " Local");
d62a17ae 10325 }
05864da7 10326 }
d62a17ae 10327
05864da7
DS
10328 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10329 if (json_paths)
10330 json_object_boolean_true_add(json_path, "removed");
10331 else
10332 vty_out(vty, ", (removed)");
10333 }
d62a17ae 10334
05864da7
DS
10335 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10336 if (json_paths)
10337 json_object_boolean_true_add(json_path, "stale");
10338 else
10339 vty_out(vty, ", (stale)");
10340 }
d62a17ae 10341
05864da7
DS
10342 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10343 if (json_paths) {
10344 json_object_int_add(json_path, "aggregatorAs",
10345 attr->aggregator_as);
c949c771
DA
10346 json_object_string_addf(json_path, "aggregatorId",
10347 "%pI4", &attr->aggregator_addr);
05864da7 10348 } else {
88d495a9
DA
10349 vty_out(vty, ", (aggregated by %u %pI4)",
10350 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10351 }
05864da7 10352 }
d62a17ae 10353
05864da7
DS
10354 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10355 PEER_FLAG_REFLECTOR_CLIENT)) {
10356 if (json_paths)
10357 json_object_boolean_true_add(json_path,
10358 "rxedFromRrClient");
10359 else
10360 vty_out(vty, ", (Received from a RR-client)");
10361 }
d62a17ae 10362
05864da7
DS
10363 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10364 PEER_FLAG_RSERVER_CLIENT)) {
10365 if (json_paths)
10366 json_object_boolean_true_add(json_path,
10367 "rxedFromRsClient");
10368 else
10369 vty_out(vty, ", (Received from a RS-client)");
10370 }
d62a17ae 10371
05864da7
DS
10372 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10373 if (json_paths)
10374 json_object_boolean_true_add(json_path,
10375 "dampeningHistoryEntry");
10376 else
10377 vty_out(vty, ", (history entry)");
10378 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10379 if (json_paths)
10380 json_object_boolean_true_add(json_path,
10381 "dampeningSuppressed");
10382 else
10383 vty_out(vty, ", (suppressed due to dampening)");
10384 }
d62a17ae 10385
05864da7
DS
10386 if (!json_paths)
10387 vty_out(vty, "\n");
d62a17ae 10388
05864da7
DS
10389 /* Line2 display Next-hop, Neighbor, Router-id */
10390 /* Display the nexthop */
b54892e0 10391
34c7f35f
SW
10392 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10393 p->family == AF_EVPN) &&
7226bc40
TA
10394 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10395 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10396 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10397 || safi == SAFI_EVPN) {
515c2602 10398 if (json_paths) {
c949c771
DA
10399 json_object_string_addf(
10400 json_nexthop_global, "ip", "%pI4",
10401 &attr->mp_nexthop_global_in);
515c2602 10402
939a97f4 10403 if (path->peer->hostname)
515c2602
DA
10404 json_object_string_add(
10405 json_nexthop_global, "hostname",
939a97f4 10406 path->peer->hostname);
aef999a2
DA
10407 } else {
10408 if (nexthop_hostname)
10409 vty_out(vty, " %pI4(%s)",
10410 &attr->mp_nexthop_global_in,
10411 nexthop_hostname);
10412 else
10413 vty_out(vty, " %pI4",
10414 &attr->mp_nexthop_global_in);
10415 }
d62a17ae 10416 } else {
515c2602 10417 if (json_paths) {
c949c771
DA
10418 json_object_string_addf(json_nexthop_global,
10419 "ip", "%pI4",
10420 &attr->nexthop);
515c2602 10421
939a97f4 10422 if (path->peer->hostname)
515c2602
DA
10423 json_object_string_add(
10424 json_nexthop_global, "hostname",
939a97f4 10425 path->peer->hostname);
aef999a2
DA
10426 } else {
10427 if (nexthop_hostname)
10428 vty_out(vty, " %pI4(%s)",
10429 &attr->nexthop,
10430 nexthop_hostname);
10431 else
10432 vty_out(vty, " %pI4",
10433 &attr->nexthop);
10434 }
d62a17ae 10435 }
10436
05864da7
DS
10437 if (json_paths)
10438 json_object_string_add(json_nexthop_global, "afi",
10439 "ipv4");
10440 } else {
10441 if (json_paths) {
c949c771
DA
10442 json_object_string_addf(json_nexthop_global, "ip",
10443 "%pI6",
10444 &attr->mp_nexthop_global);
515c2602 10445
939a97f4 10446 if (path->peer->hostname)
515c2602
DA
10447 json_object_string_add(json_nexthop_global,
10448 "hostname",
939a97f4 10449 path->peer->hostname);
515c2602 10450
05864da7
DS
10451 json_object_string_add(json_nexthop_global, "afi",
10452 "ipv6");
10453 json_object_string_add(json_nexthop_global, "scope",
10454 "global");
10455 } else {
aef999a2
DA
10456 if (nexthop_hostname)
10457 vty_out(vty, " %pI6(%s)",
10458 &attr->mp_nexthop_global,
10459 nexthop_hostname);
10460 else
10461 vty_out(vty, " %pI6",
10462 &attr->mp_nexthop_global);
d62a17ae 10463 }
05864da7 10464 }
d62a17ae 10465
05864da7 10466 /* Display the IGP cost or 'inaccessible' */
f0cde006 10467 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10468 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10469
10470 if (json_paths) {
05864da7
DS
10471 json_object_boolean_false_add(json_nexthop_global,
10472 "accessible");
95ba22d5
DA
10473 json_object_boolean_add(json_nexthop_global,
10474 "importCheckEnabled", import);
10475 } else {
10476 vty_out(vty, " (inaccessible%s)",
10477 import ? ", import-check enabled" : "");
10478 }
05864da7 10479 } else {
f0cde006 10480 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10481 if (json_paths)
f0cde006
LS
10482 json_object_int_add(
10483 json_nexthop_global, "metric",
10484 bpi_ultimate->extra->igpmetric);
d62a17ae 10485 else
05864da7 10486 vty_out(vty, " (metric %u)",
f0cde006 10487 bpi_ultimate->extra->igpmetric);
d62a17ae 10488 }
10489
05864da7 10490 /* IGP cost is 0, display this only for json */
d62a17ae 10491 else {
d62a17ae 10492 if (json_paths)
05864da7
DS
10493 json_object_int_add(json_nexthop_global,
10494 "metric", 0);
d62a17ae 10495 }
d62a17ae 10496
05864da7
DS
10497 if (json_paths)
10498 json_object_boolean_true_add(json_nexthop_global,
10499 "accessible");
10500 }
d62a17ae 10501
05864da7
DS
10502 /* Display peer "from" output */
10503 /* This path was originated locally */
10504 if (path->peer == bgp->peer_self) {
d62a17ae 10505
34c7f35f 10506 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10507 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10508 if (json_paths)
05864da7
DS
10509 json_object_string_add(json_peer, "peerId",
10510 "0.0.0.0");
d62a17ae 10511 else
05864da7
DS
10512 vty_out(vty, " from 0.0.0.0 ");
10513 } else {
d62a17ae 10514 if (json_paths)
05864da7
DS
10515 json_object_string_add(json_peer, "peerId",
10516 "::");
d62a17ae 10517 else
05864da7 10518 vty_out(vty, " from :: ");
d62a17ae 10519 }
d62a17ae 10520
4e9a9863 10521 if (json_paths)
c949c771
DA
10522 json_object_string_addf(json_peer, "routerId", "%pI4",
10523 &bgp->router_id);
4e9a9863 10524 else
23d0a753 10525 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10526 }
d62a17ae 10527
05864da7
DS
10528 /* We RXed this path from one of our peers */
10529 else {
10530
10531 if (json_paths) {
47e12884
DA
10532 json_object_string_addf(json_peer, "peerId", "%pSU",
10533 &path->peer->su);
c949c771
DA
10534 json_object_string_addf(json_peer, "routerId", "%pI4",
10535 &path->peer->remote_id);
05864da7
DS
10536
10537 if (path->peer->hostname)
10538 json_object_string_add(json_peer, "hostname",
10539 path->peer->hostname);
10540
10541 if (path->peer->domainname)
10542 json_object_string_add(json_peer, "domainname",
10543 path->peer->domainname);
10544
10545 if (path->peer->conf_if)
10546 json_object_string_add(json_peer, "interface",
10547 path->peer->conf_if);
10548 } else {
10549 if (path->peer->conf_if) {
10550 if (path->peer->hostname
892fedb6
DA
10551 && CHECK_FLAG(path->peer->bgp->flags,
10552 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10553 vty_out(vty, " from %s(%s)",
10554 path->peer->hostname,
10555 path->peer->conf_if);
d62a17ae 10556 else
05864da7 10557 vty_out(vty, " from %s",
9b6d8fcf 10558 path->peer->conf_if);
d62a17ae 10559 } else {
05864da7 10560 if (path->peer->hostname
892fedb6
DA
10561 && CHECK_FLAG(path->peer->bgp->flags,
10562 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10563 vty_out(vty, " from %s(%s)",
10564 path->peer->hostname,
10565 path->peer->host);
d62a17ae 10566 else
47e12884
DA
10567 vty_out(vty, " from %pSU",
10568 &path->peer->su);
d62a17ae 10569 }
d62a17ae 10570
05864da7 10571 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10572 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10573 else
07380148 10574 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10575 }
05864da7 10576 }
9df8b37c 10577
05864da7
DS
10578 /*
10579 * Note when vrfid of nexthop is different from that of prefix
10580 */
10581 if (path->extra && path->extra->bgp_orig) {
10582 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10583
05864da7
DS
10584 if (json_paths) {
10585 const char *vn;
9df8b37c 10586
05864da7
DS
10587 if (path->extra->bgp_orig->inst_type
10588 == BGP_INSTANCE_TYPE_DEFAULT)
10589 vn = VRF_DEFAULT_NAME;
10590 else
10591 vn = path->extra->bgp_orig->name;
9df8b37c 10592
05864da7 10593 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10594
05864da7
DS
10595 if (nexthop_vrfid == VRF_UNKNOWN) {
10596 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10597 } else {
05864da7
DS
10598 json_object_int_add(json_path, "nhVrfId",
10599 (int)nexthop_vrfid);
9df8b37c 10600 }
05864da7
DS
10601 } else {
10602 if (nexthop_vrfid == VRF_UNKNOWN)
10603 vty_out(vty, " vrf ?");
137147c6
DS
10604 else {
10605 struct vrf *vrf;
10606
10607 vrf = vrf_lookup_by_id(nexthop_vrfid);
10608 vty_out(vty, " vrf %s(%u)",
10609 VRF_LOGNAME(vrf), nexthop_vrfid);
10610 }
9df8b37c 10611 }
05864da7 10612 }
9df8b37c 10613
05864da7
DS
10614 if (nexthop_self) {
10615 if (json_paths) {
10616 json_object_boolean_true_add(json_path,
10617 "announceNexthopSelf");
10618 } else {
10619 vty_out(vty, " announce-nh-self");
9df8b37c 10620 }
05864da7 10621 }
9df8b37c 10622
05864da7
DS
10623 if (!json_paths)
10624 vty_out(vty, "\n");
d62a17ae 10625
05864da7
DS
10626 /* display the link-local nexthop */
10627 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10628 if (json_paths) {
10629 json_nexthop_ll = json_object_new_object();
c949c771
DA
10630 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10631 &attr->mp_nexthop_local);
515c2602 10632
939a97f4 10633 if (path->peer->hostname)
515c2602
DA
10634 json_object_string_add(json_nexthop_ll,
10635 "hostname",
939a97f4 10636 path->peer->hostname);
515c2602 10637
05864da7
DS
10638 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10639 json_object_string_add(json_nexthop_ll, "scope",
10640 "link-local");
d62a17ae 10641
05864da7
DS
10642 json_object_boolean_true_add(json_nexthop_ll,
10643 "accessible");
d62a17ae 10644
2bb8b49c 10645 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10646 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10647 "used");
10648 else
10649 json_object_boolean_true_add(
10650 json_nexthop_global, "used");
10651 } else {
10652 vty_out(vty, " (%s) %s\n",
10653 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10654 buf, INET6_ADDRSTRLEN),
2bb8b49c 10655 attr->mp_nexthop_prefer_global
05864da7
DS
10656 ? "(prefer-global)"
10657 : "(used)");
d62a17ae 10658 }
05864da7
DS
10659 }
10660 /* If we do not have a link-local nexthop then we must flag the
10661 global as "used" */
10662 else {
10663 if (json_paths)
10664 json_object_boolean_true_add(json_nexthop_global,
10665 "used");
10666 }
d62a17ae 10667
b5e140c8 10668 if (safi == SAFI_EVPN &&
5e4d4c8a 10669 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10670 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10671 }
10672
05864da7
DS
10673 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10674 * Int/Ext/Local, Atomic, best */
10675 if (json_paths)
10676 json_object_string_add(json_path, "origin",
10677 bgp_origin_long_str[attr->origin]);
10678 else
10679 vty_out(vty, " Origin %s",
10680 bgp_origin_long_str[attr->origin]);
9df8b37c 10681
05864da7 10682 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10683 if (json_paths)
05864da7 10684 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10685 else
05864da7
DS
10686 vty_out(vty, ", metric %u", attr->med);
10687 }
9df8b37c 10688
05864da7
DS
10689 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10690 if (json_paths)
0fbac0b4 10691 json_object_int_add(json_path, "locPrf",
05864da7
DS
10692 attr->local_pref);
10693 else
10694 vty_out(vty, ", localpref %u", attr->local_pref);
10695 }
9df8b37c 10696
97a52c82
DA
10697 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10698 if (json_paths)
10699 json_object_int_add(json_path, "aigpMetric",
10700 bgp_attr_get_aigp_metric(attr));
10701 else
10702 vty_out(vty, ", aigp-metric %" PRIu64,
10703 bgp_attr_get_aigp_metric(attr));
10704 }
10705
05864da7
DS
10706 if (attr->weight != 0) {
10707 if (json_paths)
10708 json_object_int_add(json_path, "weight", attr->weight);
10709 else
10710 vty_out(vty, ", weight %u", attr->weight);
10711 }
9df8b37c 10712
05864da7
DS
10713 if (attr->tag != 0) {
10714 if (json_paths)
10715 json_object_int_add(json_path, "tag", attr->tag);
10716 else
10717 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10718 }
9df8b37c 10719
05864da7
DS
10720 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10721 if (json_paths)
10722 json_object_boolean_false_add(json_path, "valid");
10723 else
10724 vty_out(vty, ", invalid");
10725 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10726 if (json_paths)
10727 json_object_boolean_true_add(json_path, "valid");
10728 else
10729 vty_out(vty, ", valid");
10730 }
9df8b37c 10731
7d3cae70
DA
10732 if (json_paths)
10733 json_object_int_add(json_path, "version", bn->version);
10734
05864da7
DS
10735 if (path->peer != bgp->peer_self) {
10736 if (path->peer->as == path->peer->local_as) {
10737 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10738 if (json_paths)
10739 json_object_string_add(
10740 json_peer, "type",
10741 "confed-internal");
d62a17ae 10742 else
05864da7 10743 vty_out(vty, ", confed-internal");
d62a17ae 10744 } else {
05864da7
DS
10745 if (json_paths)
10746 json_object_string_add(
10747 json_peer, "type", "internal");
10748 else
10749 vty_out(vty, ", internal");
9df8b37c 10750 }
05864da7
DS
10751 } else {
10752 if (bgp_confederation_peers_check(bgp,
10753 path->peer->as)) {
10754 if (json_paths)
10755 json_object_string_add(
10756 json_peer, "type",
10757 "confed-external");
d62a17ae 10758 else
05864da7 10759 vty_out(vty, ", confed-external");
d62a17ae 10760 } else {
05864da7
DS
10761 if (json_paths)
10762 json_object_string_add(
10763 json_peer, "type", "external");
10764 else
10765 vty_out(vty, ", external");
d62a17ae 10766 }
10767 }
05864da7
DS
10768 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10769 if (json_paths) {
10770 json_object_boolean_true_add(json_path, "aggregated");
10771 json_object_boolean_true_add(json_path, "local");
10772 } else {
10773 vty_out(vty, ", aggregated, local");
10774 }
10775 } else if (path->type != ZEBRA_ROUTE_BGP) {
10776 if (json_paths)
10777 json_object_boolean_true_add(json_path, "sourced");
10778 else
10779 vty_out(vty, ", sourced");
10780 } else {
10781 if (json_paths) {
10782 json_object_boolean_true_add(json_path, "sourced");
10783 json_object_boolean_true_add(json_path, "local");
10784 } else {
10785 vty_out(vty, ", sourced, local");
d62a17ae 10786 }
05864da7 10787 }
718e3744 10788
05864da7 10789 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10790 if (json_paths)
05864da7
DS
10791 json_object_boolean_true_add(json_path,
10792 "atomicAggregate");
d62a17ae 10793 else
05864da7
DS
10794 vty_out(vty, ", atomic-aggregate");
10795 }
d62a17ae 10796
d864dd9e
EB
10797 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10798 if (json_paths)
10799 json_object_int_add(json_path, "otc", attr->otc);
10800 else
10801 vty_out(vty, ", otc %u", attr->otc);
10802 }
10803
05864da7
DS
10804 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10805 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10806 && bgp_path_info_mpath_count(path))) {
10807 if (json_paths)
10808 json_object_boolean_true_add(json_path, "multipath");
10809 else
10810 vty_out(vty, ", multipath");
10811 }
50e05855 10812
05864da7
DS
10813 // Mark the bestpath(s)
10814 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10815 first_as = aspath_get_first_as(attr->aspath);
718e3744 10816
05864da7
DS
10817 if (json_paths) {
10818 if (!json_bestpath)
10819 json_bestpath = json_object_new_object();
10820 json_object_int_add(json_bestpath, "bestpathFromAs",
10821 first_as);
10822 } else {
10823 if (first_as)
10824 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10825 else
05864da7 10826 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10827 }
05864da7 10828 }
718e3744 10829
05864da7
DS
10830 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10831 if (json_paths) {
10832 if (!json_bestpath)
10833 json_bestpath = json_object_new_object();
10834 json_object_boolean_true_add(json_bestpath, "overall");
10835 json_object_string_add(
10836 json_bestpath, "selectionReason",
10837 bgp_path_selection_reason2str(bn->reason));
10838 } else {
10839 vty_out(vty, ", best");
10840 vty_out(vty, " (%s)",
10841 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10842 }
05864da7 10843 }
718e3744 10844
4027d19b 10845 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10846 if (json_paths)
10847 json_object_string_add(
10848 json_path, "rpkiValidationState",
4027d19b 10849 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10850 else
1d327209 10851 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10852 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10853 }
10854
05864da7
DS
10855 if (json_bestpath)
10856 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10857
05864da7
DS
10858 if (!json_paths)
10859 vty_out(vty, "\n");
10860
10861 /* Line 4 display Community */
29e72930 10862 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10863 if (json_paths) {
9a706b42
DA
10864 if (!bgp_attr_get_community(attr)->json)
10865 community_str(bgp_attr_get_community(attr),
c0945b78 10866 true, true);
9a706b42
DA
10867 json_object_lock(bgp_attr_get_community(attr)->json);
10868 json_object_object_add(
10869 json_path, "community",
10870 bgp_attr_get_community(attr)->json);
05864da7
DS
10871 } else {
10872 vty_out(vty, " Community: %s\n",
9a706b42 10873 bgp_attr_get_community(attr)->str);
d62a17ae 10874 }
05864da7 10875 }
718e3744 10876
05864da7
DS
10877 /* Line 5 display Extended-community */
10878 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10879 if (json_paths) {
10880 json_ext_community = json_object_new_object();
b53e67a3
DA
10881 json_object_string_add(
10882 json_ext_community, "string",
10883 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10884 json_object_object_add(json_path, "extendedCommunity",
10885 json_ext_community);
d62a17ae 10886 } else {
05864da7 10887 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10888 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10889 }
05864da7 10890 }
718e3744 10891
05864da7
DS
10892 /* Line 6 display Large community */
10893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10894 if (json_paths) {
1bcf3a96
DA
10895 if (!bgp_attr_get_lcommunity(attr)->json)
10896 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10897 true, true);
1bcf3a96
DA
10898 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10899 json_object_object_add(
10900 json_path, "largeCommunity",
10901 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10902 } else {
10903 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10904 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10905 }
05864da7 10906 }
718e3744 10907
05864da7
DS
10908 /* Line 7 display Originator, Cluster-id */
10909 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10910 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10911 char buf[BUFSIZ] = {0};
10912
05864da7 10913 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10914 if (json_paths)
c949c771
DA
10915 json_object_string_addf(json_path,
10916 "originatorId", "%pI4",
10917 &attr->originator_id);
d62a17ae 10918 else
23d0a753
DA
10919 vty_out(vty, " Originator: %pI4",
10920 &attr->originator_id);
d62a17ae 10921 }
856ca177 10922
05864da7 10923 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10924 struct cluster_list *cluster =
10925 bgp_attr_get_cluster(attr);
05864da7 10926 int i;
d62a17ae 10927
10928 if (json_paths) {
05864da7
DS
10929 json_cluster_list = json_object_new_object();
10930 json_cluster_list_list =
10931 json_object_new_array();
10932
779fee93 10933 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10934 json_string = json_object_new_string(
779fee93
DS
10935 inet_ntop(AF_INET,
10936 &cluster->list[i],
10937 buf, sizeof(buf)));
05864da7
DS
10938 json_object_array_add(
10939 json_cluster_list_list,
10940 json_string);
10941 }
718e3744 10942
05864da7
DS
10943 /*
10944 * struct cluster_list does not have
10945 * "str" variable like aspath and community
10946 * do. Add this someday if someone asks
10947 * for it.
10948 * json_object_string_add(json_cluster_list,
779fee93 10949 * "string", cluster->str);
05864da7
DS
10950 */
10951 json_object_object_add(json_cluster_list,
10952 "list",
10953 json_cluster_list_list);
10954 json_object_object_add(json_path, "clusterList",
10955 json_cluster_list);
0dc8ee70 10956 } else {
05864da7
DS
10957 vty_out(vty, ", Cluster list: ");
10958
779fee93 10959 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10960 vty_out(vty, "%pI4 ",
779fee93 10961 &cluster->list[i]);
05864da7 10962 }
0dc8ee70 10963 }
d62a17ae 10964 }
718e3744 10965
d62a17ae 10966 if (!json_paths)
10967 vty_out(vty, "\n");
05864da7 10968 }
d62a17ae 10969
05864da7 10970 if (path->extra && path->extra->damp_info)
b4f7f45b 10971 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10972
05864da7
DS
10973 /* Remote Label */
10974 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10975 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10976 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10977 &bos);
d62a17ae 10978
05864da7
DS
10979 if (json_paths)
10980 json_object_int_add(json_path, "remoteLabel", label);
10981 else
10982 vty_out(vty, " Remote label: %d\n", label);
10983 }
d62a17ae 10984
e496b420
HS
10985 /* Remote SID */
10986 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10987 if (json_paths)
07380148
DA
10988 json_object_string_addf(json_path, "remoteSid", "%pI6",
10989 &path->extra->sid[0].sid);
e496b420 10990 else
07380148
DA
10991 vty_out(vty, " Remote SID: %pI6\n",
10992 &path->extra->sid[0].sid);
e496b420
HS
10993 }
10994
05864da7
DS
10995 /* Label Index */
10996 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10997 if (json_paths)
10998 json_object_int_add(json_path, "labelIndex",
10999 attr->label_index);
11000 else
11001 vty_out(vty, " Label Index: %d\n",
11002 attr->label_index);
11003 }
d62a17ae 11004
05864da7
DS
11005 /* Line 8 display Addpath IDs */
11006 if (path->addpath_rx_id
11007 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11008 if (json_paths) {
11009 json_object_int_add(json_path, "addpathRxId",
11010 path->addpath_rx_id);
d62a17ae 11011
05864da7
DS
11012 /* Keep backwards compatibility with the old API
11013 * by putting TX All's ID in the old field
11014 */
11015 json_object_int_add(
11016 json_path, "addpathTxId",
11017 path->tx_addpath
11018 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11019
05864da7
DS
11020 /* ... but create a specific field for each
11021 * strategy
11022 */
11023 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11024 json_object_int_add(
11025 json_path,
11026 bgp_addpath_names(i)->id_json_name,
11027 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11028 }
05864da7
DS
11029 } else {
11030 vty_out(vty, " AddPath ID: RX %u, ",
11031 path->addpath_rx_id);
d62a17ae 11032
05864da7 11033 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11034 }
05864da7 11035 }
520d5d76 11036
05864da7
DS
11037 /* If we used addpath to TX a non-bestpath we need to display
11038 * "Advertised to" on a path-by-path basis
11039 */
11040 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11041 first = 1;
dcc68b5e 11042
05864da7
DS
11043 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11044 addpath_capable =
11045 bgp_addpath_encode_tx(peer, afi, safi);
11046 has_adj = bgp_adj_out_lookup(
11047 peer, path->net,
11048 bgp_addpath_id_for_peer(peer, afi, safi,
11049 &path->tx_addpath));
11050
11051 if ((addpath_capable && has_adj)
11052 || (!addpath_capable && has_adj
11053 && CHECK_FLAG(path->flags,
11054 BGP_PATH_SELECTED))) {
11055 if (json_path && !json_adv_to)
11056 json_adv_to = json_object_new_object();
dcc68b5e 11057
05864da7
DS
11058 route_vty_out_advertised_to(
11059 vty, peer, &first,
11060 " Advertised to:", json_adv_to);
d62a17ae 11061 }
11062 }
718e3744 11063
05864da7
DS
11064 if (json_path) {
11065 if (json_adv_to) {
11066 json_object_object_add(
11067 json_path, "advertisedTo", json_adv_to);
d62a17ae 11068 }
05864da7
DS
11069 } else {
11070 if (!first) {
11071 vty_out(vty, "\n");
d62a17ae 11072 }
11073 }
05864da7 11074 }
b05a1c8b 11075
05864da7 11076 /* Line 9 display Uptime */
083ec940 11077 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11078 if (json_paths) {
11079 json_last_update = json_object_new_object();
11080 json_object_int_add(json_last_update, "epoch", tbuf);
11081 json_object_string_add(json_last_update, "string",
11082 ctime(&tbuf));
11083 json_object_object_add(json_path, "lastUpdate",
11084 json_last_update);
11085 } else
11086 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11087
05864da7
DS
11088 /* Line 10 display PMSI tunnel attribute, if present */
11089 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11090 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11091 bgp_attr_get_pmsi_tnl_type(attr),
11092 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11093
05864da7
DS
11094 if (json_paths) {
11095 json_pmsi = json_object_new_object();
11096 json_object_string_add(json_pmsi, "tunnelType", str);
11097 json_object_int_add(json_pmsi, "label",
11098 label2vni(&attr->label));
11099 json_object_object_add(json_path, "pmsi", json_pmsi);
11100 } else
11101 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11102 str, label2vni(&attr->label));
d62a17ae 11103 }
f1aa5d8a 11104
848e8cf6
DA
11105 if (path->peer->t_gr_restart &&
11106 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11107 unsigned long gr_remaining =
4f830a07 11108 event_timer_remain_second(path->peer->t_gr_restart);
848e8cf6
DA
11109
11110 if (json_paths) {
11111 json_object_int_add(json_path,
11112 "gracefulRestartSecondsRemaining",
11113 gr_remaining);
11114 } else
11115 vty_out(vty,
11116 " Time until Graceful Restart stale route deleted: %lu\n",
11117 gr_remaining);
11118 }
11119
9a706b42
DA
11120 if (path->peer->t_llgr_stale[afi][safi] &&
11121 bgp_attr_get_community(attr) &&
11122 community_include(bgp_attr_get_community(attr),
11123 COMMUNITY_LLGR_STALE)) {
4f830a07 11124 unsigned long llgr_remaining = event_timer_remain_second(
48ebba04 11125 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11126
48ebba04
DA
11127 if (json_paths) {
11128 json_object_int_add(json_path, "llgrSecondsRemaining",
11129 llgr_remaining);
11130 } else
11131 vty_out(vty,
11132 " Time until Long-lived stale route deleted: %lu\n",
11133 llgr_remaining);
11134 }
11135
92269aa2
DS
11136 /* Output some debug about internal state of the dest flags */
11137 if (json_paths) {
11138 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11139 json_object_boolean_true_add(json_path, "processScheduled");
11140 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11141 json_object_boolean_true_add(json_path, "userCleared");
11142 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11143 json_object_boolean_true_add(json_path, "labelChanged");
11144 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11145 json_object_boolean_true_add(json_path, "registeredForLabel");
11146 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11147 json_object_boolean_true_add(json_path, "selectDefered");
11148 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11149 json_object_boolean_true_add(json_path, "fibInstalled");
11150 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11151 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11152
d62a17ae 11153 if (json_nexthop_global || json_nexthop_ll) {
11154 json_nexthops = json_object_new_array();
f1aa5d8a 11155
d62a17ae 11156 if (json_nexthop_global)
11157 json_object_array_add(json_nexthops,
11158 json_nexthop_global);
f1aa5d8a 11159
d62a17ae 11160 if (json_nexthop_ll)
11161 json_object_array_add(json_nexthops,
11162 json_nexthop_ll);
f1aa5d8a 11163
d62a17ae 11164 json_object_object_add(json_path, "nexthops",
11165 json_nexthops);
11166 }
11167
11168 json_object_object_add(json_path, "peer", json_peer);
11169 json_object_array_add(json_paths, json_path);
05864da7 11170 }
b366b518
BB
11171}
11172
96ade3ed 11173#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11174#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11175#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11176
a4d82a8a 11177static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11178 afi_t afi, safi_t safi, enum bgp_show_type type,
11179 bool use_json);
7f323236
DW
11180static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11181 const char *comstr, int exact, afi_t afi,
96c81f66 11182 safi_t safi, uint16_t show_flags);
d62a17ae 11183
1ae44dfc 11184static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11185 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11186 void *output_arg, const char *rd, int is_last,
96f3485c 11187 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11188 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11189 enum rpki_states rpki_target_state)
d62a17ae 11190{
40381db7 11191 struct bgp_path_info *pi;
9bcb3eef 11192 struct bgp_dest *dest;
2aad8c42
MS
11193 bool header = true;
11194 bool json_detail_header = false;
d62a17ae 11195 int display;
1ae44dfc
LB
11196 unsigned long output_count = 0;
11197 unsigned long total_count = 0;
d62a17ae 11198 struct prefix *p;
d62a17ae 11199 json_object *json_paths = NULL;
11200 int first = 1;
96f3485c
MK
11201 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11202 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11203 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11204 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11205 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11206
1ae44dfc 11207 if (output_cum && *output_cum != 0)
2aad8c42 11208 header = false;
1ae44dfc 11209
9386b588 11210 if (use_json && !*json_header_depth) {
96f3485c
MK
11211 if (all)
11212 *json_header_depth = 1;
11213 else {
11214 vty_out(vty, "{\n");
11215 *json_header_depth = 2;
11216 }
d62a17ae 11217 vty_out(vty,
23d0a753
DA
11218 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11219 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11220 " \"localAS\": ",
a8bf7d9c 11221 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11222 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11223 ? VRF_DEFAULT_NAME
11224 : bgp->name,
11225 table->version, &bgp->router_id,
e84c7c12
PG
11226 bgp->default_local_pref);
11227 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11228 ((bgp->asnotation == ASNOTATION_DOT) &&
11229 (bgp->as < UINT16_MAX)))
11230 vty_out(vty, "%u", bgp->as);
11231 else {
11232 vty_out(vty, "\"");
11233 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11234 vty_out(vty, "\"");
11235 }
11236 vty_out(vty, ",\n \"routes\": { ");
9386b588 11237 if (rd) {
445c2480 11238 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11239 ++*json_header_depth;
11240 }
d62a17ae 11241 }
718e3744 11242
445c2480
DS
11243 if (use_json && rd) {
11244 vty_out(vty, " \"%s\" : { ", rd);
11245 }
11246
2aad8c42 11247 /* Check for 'json detail', where we need header output once per dest */
67799a48 11248 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11249 type != bgp_show_type_damp_neighbor &&
11250 type != bgp_show_type_flap_statistics &&
11251 type != bgp_show_type_flap_neighbor)
11252 json_detail_header = true;
11253
d62a17ae 11254 /* Start processing of routes. */
9bcb3eef
DS
11255 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11256 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11257 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11258 bool json_detail_header_used = false;
b54892e0 11259
9bcb3eef 11260 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11261 if (pi == NULL)
98ce9a06 11262 continue;
d62a17ae 11263
98ce9a06 11264 display = 0;
98ce9a06
DS
11265 if (use_json)
11266 json_paths = json_object_new_array();
11267 else
11268 json_paths = NULL;
d62a17ae 11269
6f94b685 11270 for (; pi; pi = pi->next) {
9a706b42
DA
11271 struct community *picomm = NULL;
11272
11273 picomm = bgp_attr_get_community(pi->attr);
11274
98ce9a06 11275 total_count++;
1e2ce4f1 11276
7d3cae70
DA
11277 if (type == bgp_show_type_prefix_version) {
11278 uint32_t version =
11279 strtoul(output_arg, NULL, 10);
11280 if (dest->version < version)
11281 continue;
11282 }
11283
a70a28a5
DA
11284 if (type == bgp_show_type_community_alias) {
11285 char *alias = output_arg;
11286 char **communities;
11287 int num;
11288 bool found = false;
11289
9a706b42
DA
11290 if (picomm) {
11291 frrstr_split(picomm->str, " ",
11292 &communities, &num);
a70a28a5
DA
11293 for (int i = 0; i < num; i++) {
11294 const char *com2alias =
11295 bgp_community2alias(
11296 communities[i]);
cd9cc0e6
IR
11297 if (!found
11298 && strcmp(alias, com2alias)
11299 == 0)
a70a28a5 11300 found = true;
cd9cc0e6
IR
11301 XFREE(MTYPE_TMP,
11302 communities[i]);
a70a28a5 11303 }
cd9cc0e6 11304 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11305 }
11306
1bcf3a96
DA
11307 if (!found &&
11308 bgp_attr_get_lcommunity(pi->attr)) {
11309 frrstr_split(bgp_attr_get_lcommunity(
11310 pi->attr)
11311 ->str,
a70a28a5
DA
11312 " ", &communities, &num);
11313 for (int i = 0; i < num; i++) {
11314 const char *com2alias =
11315 bgp_community2alias(
11316 communities[i]);
cd9cc0e6
IR
11317 if (!found
11318 && strcmp(alias, com2alias)
11319 == 0)
a70a28a5 11320 found = true;
cd9cc0e6
IR
11321 XFREE(MTYPE_TMP,
11322 communities[i]);
a70a28a5 11323 }
cd9cc0e6 11324 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11325 }
11326
11327 if (!found)
11328 continue;
11329 }
11330
1e2ce4f1
DS
11331 if (type == bgp_show_type_rpki) {
11332 if (dest_p->family == AF_INET
11333 || dest_p->family == AF_INET6)
4027d19b 11334 rpki_curr_state = hook_call(
1e2ce4f1
DS
11335 bgp_rpki_prefix_status,
11336 pi->peer, pi->attr, dest_p);
4027d19b
DS
11337 if (rpki_target_state != RPKI_NOT_BEING_USED
11338 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11339 continue;
11340 }
11341
98ce9a06
DS
11342 if (type == bgp_show_type_flap_statistics
11343 || type == bgp_show_type_flap_neighbor
11344 || type == bgp_show_type_dampend_paths
11345 || type == bgp_show_type_damp_neighbor) {
40381db7 11346 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11347 continue;
11348 }
11349 if (type == bgp_show_type_regexp) {
11350 regex_t *regex = output_arg;
d62a17ae 11351
40381db7 11352 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11353 == REG_NOMATCH)
11354 continue;
11355 }
11356 if (type == bgp_show_type_prefix_list) {
11357 struct prefix_list *plist = output_arg;
d62a17ae 11358
9bcb3eef 11359 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11360 != PREFIX_PERMIT)
11361 continue;
11362 }
ed126382
DA
11363 if (type == bgp_show_type_access_list) {
11364 struct access_list *alist = output_arg;
11365
11366 if (access_list_apply(alist, dest_p) !=
11367 FILTER_PERMIT)
11368 continue;
11369 }
98ce9a06
DS
11370 if (type == bgp_show_type_filter_list) {
11371 struct as_list *as_list = output_arg;
d62a17ae 11372
40381db7 11373 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11374 != AS_FILTER_PERMIT)
11375 continue;
11376 }
11377 if (type == bgp_show_type_route_map) {
11378 struct route_map *rmap = output_arg;
9b6d8fcf 11379 struct bgp_path_info path;
636632c3
DA
11380 struct bgp_path_info_extra extra;
11381 struct attr dummy_attr = {};
b68885f9 11382 route_map_result_t ret;
d62a17ae 11383
6f4f49b2 11384 dummy_attr = *pi->attr;
d62a17ae 11385
636632c3
DA
11386 prep_for_rmap_apply(&path, &extra, dest, pi,
11387 pi->peer, &dummy_attr);
d62a17ae 11388
1782514f 11389 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11390 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11391 if (ret == RMAP_DENYMATCH)
11392 continue;
11393 }
11394 if (type == bgp_show_type_neighbor
11395 || type == bgp_show_type_flap_neighbor
11396 || type == bgp_show_type_damp_neighbor) {
11397 union sockunion *su = output_arg;
11398
40381db7
DS
11399 if (pi->peer == NULL
11400 || pi->peer->su_remote == NULL
11401 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11402 continue;
11403 }
11404 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11405 uint32_t destination;
d62a17ae 11406
9bcb3eef 11407 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11408 if (IN_CLASSC(destination)
9bcb3eef 11409 && dest_p->prefixlen == 24)
98ce9a06
DS
11410 continue;
11411 if (IN_CLASSB(destination)
9bcb3eef 11412 && dest_p->prefixlen == 16)
98ce9a06
DS
11413 continue;
11414 if (IN_CLASSA(destination)
9bcb3eef 11415 && dest_p->prefixlen == 8)
98ce9a06
DS
11416 continue;
11417 }
11418 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11419 p = output_arg;
9bcb3eef 11420 if (!prefix_match(p, dest_p))
98ce9a06
DS
11421 continue;
11422 }
11423 if (type == bgp_show_type_community_all) {
9a706b42 11424 if (!picomm)
98ce9a06
DS
11425 continue;
11426 }
11427 if (type == bgp_show_type_community) {
11428 struct community *com = output_arg;
d62a17ae 11429
9a706b42 11430 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11431 continue;
11432 }
11433 if (type == bgp_show_type_community_exact) {
11434 struct community *com = output_arg;
d62a17ae 11435
9a706b42 11436 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11437 continue;
11438 }
11439 if (type == bgp_show_type_community_list) {
11440 struct community_list *list = output_arg;
d62a17ae 11441
9a706b42 11442 if (!community_list_match(picomm, list))
98ce9a06
DS
11443 continue;
11444 }
a4d82a8a 11445 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11446 struct community_list *list = output_arg;
d62a17ae 11447
9a706b42 11448 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11449 continue;
11450 }
11451 if (type == bgp_show_type_lcommunity) {
11452 struct lcommunity *lcom = output_arg;
d62a17ae 11453
1bcf3a96
DA
11454 if (!bgp_attr_get_lcommunity(pi->attr) ||
11455 !lcommunity_match(
11456 bgp_attr_get_lcommunity(pi->attr),
11457 lcom))
98ce9a06
DS
11458 continue;
11459 }
36a206db 11460
11461 if (type == bgp_show_type_lcommunity_exact) {
11462 struct lcommunity *lcom = output_arg;
11463
1bcf3a96
DA
11464 if (!bgp_attr_get_lcommunity(pi->attr) ||
11465 !lcommunity_cmp(
11466 bgp_attr_get_lcommunity(pi->attr),
11467 lcom))
36a206db 11468 continue;
11469 }
98ce9a06
DS
11470 if (type == bgp_show_type_lcommunity_list) {
11471 struct community_list *list = output_arg;
d62a17ae 11472
1bcf3a96
DA
11473 if (!lcommunity_list_match(
11474 bgp_attr_get_lcommunity(pi->attr),
11475 list))
98ce9a06
DS
11476 continue;
11477 }
36a206db 11478 if (type
11479 == bgp_show_type_lcommunity_list_exact) {
11480 struct community_list *list = output_arg;
11481
11482 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11483 bgp_attr_get_lcommunity(pi->attr),
11484 list))
36a206db 11485 continue;
11486 }
98ce9a06 11487 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11488 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11489 continue;
11490 }
11491 if (type == bgp_show_type_dampend_paths
11492 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11493 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11494 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11495 continue;
11496 }
83856649
KQ
11497 if (type == bgp_show_type_self_originated) {
11498 if (pi->peer != bgp->peer_self)
11499 continue;
11500 }
98ce9a06
DS
11501
11502 if (!use_json && header) {
23d0a753
DA
11503 vty_out(vty,
11504 "BGP table version is %" PRIu64
11505 ", local router ID is %pI4, vrf id ",
11506 table->version, &bgp->router_id);
9df8b37c
PZ
11507 if (bgp->vrf_id == VRF_UNKNOWN)
11508 vty_out(vty, "%s", VRFID_NONE_STR);
11509 else
11510 vty_out(vty, "%u", bgp->vrf_id);
11511 vty_out(vty, "\n");
01eced22
AD
11512 vty_out(vty, "Default local pref %u, ",
11513 bgp->default_local_pref);
e84c7c12
PG
11514 vty_out(vty, "local AS ");
11515 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11516 &bgp->as);
11517 vty_out(vty, "\n");
509d82bd 11518 if (!detail_routes) {
9a1aae2d
DA
11519 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11520 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11521 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11522 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11523 }
d62a17ae 11524 if (type == bgp_show_type_dampend_paths
11525 || type == bgp_show_type_damp_neighbor)
98ce9a06 11526 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11527 else if (type == bgp_show_type_flap_statistics
11528 || type == bgp_show_type_flap_neighbor)
98ce9a06 11529 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11530 else if (!detail_routes)
ae248832
MK
11531 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11532 : BGP_SHOW_HEADER));
2aad8c42
MS
11533 header = false;
11534
d62a17ae 11535 }
98ce9a06
DS
11536 if (rd != NULL && !display && !output_count) {
11537 if (!use_json)
11538 vty_out(vty,
11539 "Route Distinguisher: %s\n",
11540 rd);
d62a17ae 11541 }
98ce9a06
DS
11542 if (type == bgp_show_type_dampend_paths
11543 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11544 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11545 AFI_IP, safi, use_json,
11546 json_paths);
98ce9a06
DS
11547 else if (type == bgp_show_type_flap_statistics
11548 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11549 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11550 AFI_IP, safi, use_json,
11551 json_paths);
f280c93b 11552 else {
27bb782a
DA
11553 if (detail_routes || detail_json) {
11554 const struct prefix_rd *prd = NULL;
9a1aae2d 11555
27bb782a
DA
11556 if (dest->pdest)
11557 prd = bgp_rd_from_dest(
11558 dest->pdest, safi);
9a1aae2d
DA
11559
11560 if (!use_json)
11561 route_vty_out_detail_header(
11562 vty, bgp, dest,
11563 bgp_dest_get_prefix(
11564 dest),
11565 prd, table->afi, safi,
f9f2d188 11566 NULL, false);
9a1aae2d 11567
f280c93b 11568 route_vty_out_detail(
27bb782a 11569 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11570 family2afi(dest_p->family),
11571 safi, RPKI_NOT_BEING_USED,
11572 json_paths);
9a1aae2d 11573 } else {
f280c93b
DA
11574 route_vty_out(vty, dest_p, pi, display,
11575 safi, json_paths, wide);
9a1aae2d 11576 }
f280c93b 11577 }
98ce9a06 11578 display++;
d62a17ae 11579 }
11580
98ce9a06
DS
11581 if (display) {
11582 output_count++;
11583 if (!use_json)
11584 continue;
11585
625d2931 11586 /* encode prefix */
9bcb3eef 11587 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11588 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11589
1840384b 11590
b54892e0
DS
11591 bgp_fs_nlri_get_string(
11592 (unsigned char *)
9bcb3eef
DS
11593 dest_p->u.prefix_flowspec.ptr,
11594 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11595 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11596 family2afi(dest_p->u
11597 .prefix_flowspec.family));
625d2931 11598 if (first)
b54892e0 11599 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11600 dest_p->u.prefix_flowspec
b54892e0 11601 .prefixlen);
625d2931 11602 else
b54892e0 11603 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11604 dest_p->u.prefix_flowspec
b54892e0 11605 .prefixlen);
625d2931 11606 } else {
625d2931 11607 if (first)
1b78780b 11608 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11609 else
1b78780b 11610 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11611 }
f9f2d188
TA
11612
11613 if (json_detail_header && json_paths != NULL) {
11614 const struct prefix_rd *prd;
11615
11616 vty_out(vty, "{\n");
11617
11618 prd = bgp_rd_from_dest(dest, safi);
11619
11620 route_vty_out_detail_header(
11621 vty, bgp, dest,
11622 bgp_dest_get_prefix(dest), prd,
11623 table->afi, safi, json_paths, true);
11624
11625 vty_out(vty, "\"paths\": ");
11626 json_detail_header_used = true;
11627 }
11628
d7c6467b
DS
11629 /*
11630 * We are using no_pretty here because under
11631 * extremely high settings( say lots and lots of
11632 * routes with lots and lots of ways to reach
11633 * that route via different paths ) this can
11634 * save several minutes of output when FRR
11635 * is run on older cpu's or more underperforming
11636 * routers out there
11637 */
11638 vty_json_no_pretty(vty, json_paths);
f9f2d188
TA
11639
11640 if (json_detail_header_used)
11641 vty_out(vty, "} ");
11642
449feb8e 11643 json_paths = NULL;
98ce9a06 11644 first = 0;
1f83ed02
DS
11645 } else
11646 json_object_free(json_paths);
98ce9a06
DS
11647 }
11648
1ae44dfc
LB
11649 if (output_cum) {
11650 output_count += *output_cum;
11651 *output_cum = output_count;
11652 }
11653 if (total_cum) {
11654 total_count += *total_cum;
11655 *total_cum = total_count;
11656 }
d62a17ae 11657 if (use_json) {
9386b588 11658 if (rd) {
a4d82a8a 11659 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11660 }
11661 if (is_last) {
a4d82a8a
PZ
11662 unsigned long i;
11663 for (i = 0; i < *json_header_depth; ++i)
11664 vty_out(vty, " } ");
96f3485c
MK
11665 if (!all)
11666 vty_out(vty, "\n");
9386b588 11667 }
d62a17ae 11668 } else {
1ae44dfc
LB
11669 if (is_last) {
11670 /* No route is displayed */
11671 if (output_count == 0) {
11672 if (type == bgp_show_type_normal)
11673 vty_out(vty,
11674 "No BGP prefixes displayed, %ld exist\n",
11675 total_count);
11676 } else
d62a17ae 11677 vty_out(vty,
1ae44dfc
LB
11678 "\nDisplayed %ld routes and %ld total paths\n",
11679 output_count, total_count);
11680 }
d62a17ae 11681 }
718e3744 11682
d62a17ae 11683 return CMD_SUCCESS;
718e3744 11684}
11685
1ae44dfc
LB
11686int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11687 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11688 enum bgp_show_type type, void *output_arg,
11689 uint16_t show_flags)
1ae44dfc 11690{
9bcb3eef 11691 struct bgp_dest *dest, *next;
1ae44dfc
LB
11692 unsigned long output_cum = 0;
11693 unsigned long total_cum = 0;
9386b588 11694 unsigned long json_header_depth = 0;
67009e22 11695 struct bgp_table *itable;
0136788c 11696 bool show_msg;
27bb782a 11697 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11698
11699 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11700
9bcb3eef
DS
11701 for (dest = bgp_table_top(table); dest; dest = next) {
11702 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11703
9bcb3eef
DS
11704 next = bgp_route_next(dest);
11705 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11706 continue;
67009e22 11707
9bcb3eef 11708 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11709 if (itable != NULL) {
1ae44dfc 11710 struct prefix_rd prd;
06b9f471 11711 char rd[RD_ADDRSTRLEN];
1ae44dfc 11712
9bcb3eef 11713 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11714 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11715 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11716 rd, next == NULL, &output_cum,
11717 &total_cum, &json_header_depth,
1e2ce4f1 11718 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11719 if (next == NULL)
11720 show_msg = false;
1ae44dfc
LB
11721 }
11722 }
0136788c
LB
11723 if (show_msg) {
11724 if (output_cum == 0)
11725 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11726 total_cum);
11727 else
11728 vty_out(vty,
11729 "\nDisplayed %ld routes and %ld total paths\n",
11730 output_cum, total_cum);
0224b329
DA
11731 } else {
11732 if (use_json && output_cum == 0)
11733 vty_out(vty, "{}\n");
0136788c 11734 }
1ae44dfc
LB
11735 return CMD_SUCCESS;
11736}
2aad8c42 11737
d62a17ae 11738static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11739 enum bgp_show_type type, void *output_arg,
96c81f66 11740 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11741{
d62a17ae 11742 struct bgp_table *table;
9386b588 11743 unsigned long json_header_depth = 0;
96f3485c 11744 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11745
d62a17ae 11746 if (bgp == NULL) {
11747 bgp = bgp_get_default();
11748 }
fee0f4c6 11749
d62a17ae 11750 if (bgp == NULL) {
11751 if (!use_json)
11752 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11753 else
11754 vty_out(vty, "{}\n");
d62a17ae 11755 return CMD_WARNING;
11756 }
4dd6177e 11757
cd8c2a27
MS
11758 /* Labeled-unicast routes live in the unicast table. */
11759 if (safi == SAFI_LABELED_UNICAST)
11760 safi = SAFI_UNICAST;
11761
1ae44dfc 11762 table = bgp->rib[afi][safi];
d62a17ae 11763 /* use MPLS and ENCAP specific shows until they are merged */
11764 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11765 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11766 output_arg, show_flags);
d62a17ae 11767 }
dba3c1d3
PG
11768
11769 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11770 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11771 output_arg, use_json,
11772 1, NULL, NULL);
11773 }
fee0f4c6 11774
0adc5bbb
LS
11775 if (safi == SAFI_EVPN)
11776 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11777
96f3485c 11778 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11779 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11780 rpki_target_state);
fee0f4c6 11781}
11782
d62a17ae 11783static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11784 safi_t safi, uint16_t show_flags)
f186de26 11785{
d62a17ae 11786 struct listnode *node, *nnode;
11787 struct bgp *bgp;
11788 int is_first = 1;
9f049418 11789 bool route_output = false;
96f3485c 11790 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11791
d62a17ae 11792 if (use_json)
11793 vty_out(vty, "{\n");
9f689658 11794
d62a17ae 11795 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11796 route_output = true;
d62a17ae 11797 if (use_json) {
11798 if (!is_first)
11799 vty_out(vty, ",\n");
11800 else
11801 is_first = 0;
11802
11803 vty_out(vty, "\"%s\":",
11804 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11805 ? VRF_DEFAULT_NAME
d62a17ae 11806 : bgp->name);
11807 } else {
11808 vty_out(vty, "\nInstance %s:\n",
11809 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11810 ? VRF_DEFAULT_NAME
d62a17ae 11811 : bgp->name);
11812 }
11813 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11814 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11815 }
9f689658 11816
d62a17ae 11817 if (use_json)
11818 vty_out(vty, "}\n");
9f049418
DS
11819 else if (!route_output)
11820 vty_out(vty, "%% BGP instance not found\n");
f186de26 11821}
11822
718e3744 11823/* Header of detailed BGP route information */
d62a17ae 11824void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11825 struct bgp_dest *dest, const struct prefix *p,
11826 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11827 safi_t safi, json_object *json,
11828 bool incremental_print)
d62a17ae 11829{
40381db7 11830 struct bgp_path_info *pi;
d62a17ae 11831 struct peer *peer;
11832 struct listnode *node, *nnode;
06b9f471 11833 char buf1[RD_ADDRSTRLEN];
d62a17ae 11834 int count = 0;
11835 int best = 0;
11836 int suppress = 0;
c5f1e1b2
C
11837 int accept_own = 0;
11838 int route_filter_translated_v4 = 0;
11839 int route_filter_v4 = 0;
11840 int route_filter_translated_v6 = 0;
11841 int route_filter_v6 = 0;
11842 int llgr_stale = 0;
11843 int no_llgr = 0;
11844 int accept_own_nexthop = 0;
11845 int blackhole = 0;
d62a17ae 11846 int no_export = 0;
11847 int no_advertise = 0;
11848 int local_as = 0;
c5f1e1b2 11849 int no_peer = 0;
d62a17ae 11850 int first = 1;
11851 int has_valid_label = 0;
11852 mpls_label_t label = 0;
11853 json_object *json_adv_to = NULL;
67f67ba4
DA
11854 uint32_t ttl = 0;
11855 uint32_t bos = 0;
11856 uint32_t exp = 0;
9bedbb1e 11857
67f67ba4 11858 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11859
67f67ba4 11860 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11861
44c69747 11862 if (safi == SAFI_EVPN) {
44c69747 11863 if (!json) {
2dbe669b 11864 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11865 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11866 bgp->asnotation)
f137734b 11867 : "",
2dbe669b 11868 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11869 } else {
4a8cd6ad
PG
11870 json_object_string_add(
11871 json, "rd",
11872 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11873 bgp->asnotation)
11874 : "");
44c69747
LK
11875 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11876 }
11877 } else {
11878 if (!json) {
9119ef3a
DA
11879 vty_out(vty,
11880 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11881 "\n",
d62a17ae 11882 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11883 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11884 sizeof(buf1),
11885 bgp->asnotation)
8228a9a7 11886 : ""),
9119ef3a
DA
11887 safi == SAFI_MPLS_VPN ? ":" : "", p,
11888 dest->version);
cd1964ff 11889
9119ef3a 11890 } else {
f9f2d188
TA
11891 if (incremental_print) {
11892 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11893 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11894 dest->version);
11895 } else {
11896 json_object_string_addf(json, "prefix", "%pFX",
11897 p);
11898 json_object_int_add(json, "version",
11899 dest->version);
11900 }
9119ef3a 11901 }
44c69747
LK
11902 }
11903
11904 if (has_valid_label) {
f9f2d188
TA
11905 if (json) {
11906 if (incremental_print)
11907 vty_out(vty, "\"localLabel\": \"%u\",\n",
11908 label);
11909 else
11910 json_object_int_add(json, "localLabel", label);
11911 } else
d62a17ae 11912 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11913 }
11914
11915 if (!json)
d62a17ae 11916 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11917 vty_out(vty, "not allocated\n");
718e3744 11918
9bcb3eef 11919 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11920 struct community *picomm = NULL;
11921
11922 picomm = bgp_attr_get_community(pi->attr);
11923
d62a17ae 11924 count++;
40381db7 11925 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11926 best = count;
4056a5f6 11927 if (bgp_path_suppressed(pi))
d62a17ae 11928 suppress = 1;
cee9c031 11929
9a706b42 11930 if (!picomm)
cee9c031
QY
11931 continue;
11932
11933 no_advertise += community_include(
9a706b42
DA
11934 picomm, COMMUNITY_NO_ADVERTISE);
11935 no_export +=
11936 community_include(picomm, COMMUNITY_NO_EXPORT);
11937 local_as +=
11938 community_include(picomm, COMMUNITY_LOCAL_AS);
11939 accept_own +=
11940 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11941 route_filter_translated_v4 += community_include(
9a706b42 11942 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11943 route_filter_translated_v6 += community_include(
9a706b42 11944 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11945 route_filter_v4 += community_include(
9a706b42 11946 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11947 route_filter_v6 += community_include(
9a706b42
DA
11948 picomm, COMMUNITY_ROUTE_FILTER_v6);
11949 llgr_stale +=
11950 community_include(picomm, COMMUNITY_LLGR_STALE);
11951 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11952 accept_own_nexthop += community_include(
11953 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11954 blackhole +=
11955 community_include(picomm, COMMUNITY_BLACKHOLE);
11956 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11957 }
718e3744 11958 }
718e3744 11959
d62a17ae 11960 if (!json) {
11961 vty_out(vty, "Paths: (%d available", count);
11962 if (best) {
11963 vty_out(vty, ", best #%d", best);
b84060bb
PG
11964 if (safi == SAFI_UNICAST) {
11965 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11966 vty_out(vty, ", table %s",
11967 VRF_DEFAULT_NAME);
11968 else
11969 vty_out(vty, ", vrf %s",
11970 bgp->name);
11971 }
d62a17ae 11972 } else
11973 vty_out(vty, ", no best path");
11974
c5f1e1b2
C
11975 if (accept_own)
11976 vty_out(vty,
11977 ", accept own local route exported and imported in different VRF");
11978 else if (route_filter_translated_v4)
11979 vty_out(vty,
11980 ", mark translated RTs for VPNv4 route filtering");
11981 else if (route_filter_v4)
11982 vty_out(vty,
11983 ", attach RT as-is for VPNv4 route filtering");
11984 else if (route_filter_translated_v6)
11985 vty_out(vty,
11986 ", mark translated RTs for VPNv6 route filtering");
11987 else if (route_filter_v6)
11988 vty_out(vty,
11989 ", attach RT as-is for VPNv6 route filtering");
11990 else if (llgr_stale)
11991 vty_out(vty,
1479ed2f 11992 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11993 else if (no_llgr)
11994 vty_out(vty,
11995 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11996 else if (accept_own_nexthop)
11997 vty_out(vty,
11998 ", accept local nexthop");
11999 else if (blackhole)
12000 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 12001 else if (no_export)
12002 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
12003 else if (no_advertise)
12004 vty_out(vty, ", not advertised to any peer");
d62a17ae 12005 else if (local_as)
12006 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
12007 else if (no_peer)
12008 vty_out(vty,
12009 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 12010
12011 if (suppress)
12012 vty_out(vty,
12013 ", Advertisements suppressed by an aggregate.");
12014 vty_out(vty, ")\n");
12015 }
718e3744 12016
d62a17ae 12017 /* If we are not using addpath then we can display Advertised to and
12018 * that will
12019 * show what peers we advertised the bestpath to. If we are using
12020 * addpath
12021 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12022 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12023 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12024 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12025 if (json && !json_adv_to)
12026 json_adv_to = json_object_new_object();
12027
12028 route_vty_out_advertised_to(
12029 vty, peer, &first,
12030 " Advertised to non peer-group peers:\n ",
12031 json_adv_to);
12032 }
12033 }
12034
f9f2d188
TA
12035 if (json && json_adv_to) {
12036 if (incremental_print) {
12037 vty_out(vty, "\"advertisedTo\": ");
12038 vty_json(vty, json_adv_to);
12039 vty_out(vty, ",");
12040 } else
d62a17ae 12041 json_object_object_add(json, "advertisedTo",
12042 json_adv_to);
d62a17ae 12043 } else {
f9f2d188 12044 if (!json && first)
d62a17ae 12045 vty_out(vty, " Not advertised to any peer");
12046 vty_out(vty, "\n");
12047 }
12048 }
718e3744 12049}
12050
edfee30d 12051static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12052 struct bgp_dest *bgp_node, struct vty *vty,
12053 struct bgp *bgp, afi_t afi, safi_t safi,
12054 json_object *json, enum bgp_path_type pathtype,
4027d19b 12055 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12056{
12057 struct bgp_path_info *pi;
12058 int header = 1;
44c69747
LK
12059 json_object *json_header = NULL;
12060 json_object *json_paths = NULL;
4933eaaf 12061 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12062
9bcb3eef 12063 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12064 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12065
12066 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12067 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12068 pi->peer, pi->attr, p);
4933eaaf 12069
4027d19b
DS
12070 if (rpki_target_state != RPKI_NOT_BEING_USED
12071 && rpki_curr_state != rpki_target_state)
4933eaaf 12072 continue;
44c69747
LK
12073
12074 if (json && !json_paths) {
12075 /* Instantiate json_paths only if path is valid */
12076 json_paths = json_object_new_array();
c4f64ea9 12077 if (pfx_rd)
44c69747 12078 json_header = json_object_new_object();
c4f64ea9 12079 else
44c69747
LK
12080 json_header = json;
12081 }
12082
12083 if (header) {
12084 route_vty_out_detail_header(
34c7f35f
SW
12085 vty, bgp, bgp_node,
12086 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12087 safi, json_header, false);
44c69747
LK
12088 header = 0;
12089 }
12090 (*display)++;
12091
12092 if (pathtype == BGP_PATH_SHOW_ALL
12093 || (pathtype == BGP_PATH_SHOW_BESTPATH
12094 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12095 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12096 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12097 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12098 route_vty_out_detail(vty, bgp, bgp_node,
12099 bgp_dest_get_prefix(bgp_node), pi,
12100 AFI_IP, safi, rpki_curr_state,
12101 json_paths);
44c69747
LK
12102 }
12103
12104 if (json && json_paths) {
12105 json_object_object_add(json_header, "paths", json_paths);
12106
12107 if (pfx_rd)
4a8cd6ad
PG
12108 json_object_object_addf(
12109 json, json_header,
12110 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12111 }
12112}
12113
2aad8c42
MS
12114/*
12115 * Return rd based on safi
12116 */
46dbf9d0
DA
12117const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12118 safi_t safi)
2aad8c42
MS
12119{
12120 switch (safi) {
12121 case SAFI_MPLS_VPN:
12122 case SAFI_ENCAP:
12123 case SAFI_EVPN:
12124 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12125 case SAFI_UNSPEC:
12126 case SAFI_UNICAST:
12127 case SAFI_MULTICAST:
12128 case SAFI_LABELED_UNICAST:
12129 case SAFI_FLOWSPEC:
12130 case SAFI_MAX:
2aad8c42 12131 return NULL;
2aad8c42 12132 }
58cf0823
DS
12133
12134 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12135}
12136
718e3744 12137/* Display specified route of BGP table. */
d62a17ae 12138static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12139 struct bgp_table *rib, const char *ip_str,
12140 afi_t afi, safi_t safi,
4027d19b 12141 enum rpki_states rpki_target_state,
d62a17ae 12142 struct prefix_rd *prd, int prefix_check,
9f049418 12143 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12144{
12145 int ret;
d62a17ae 12146 int display = 0;
12147 struct prefix match;
9bcb3eef
DS
12148 struct bgp_dest *dest;
12149 struct bgp_dest *rm;
d62a17ae 12150 struct bgp_table *table;
12151 json_object *json = NULL;
12152 json_object *json_paths = NULL;
12153
12154 /* Check IP address argument. */
12155 ret = str2prefix(ip_str, &match);
12156 if (!ret) {
12157 vty_out(vty, "address is malformed\n");
12158 return CMD_WARNING;
12159 }
718e3744 12160
d62a17ae 12161 match.family = afi2family(afi);
b05a1c8b 12162
44c69747 12163 if (use_json)
d62a17ae 12164 json = json_object_new_object();
718e3744 12165
44c69747 12166 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12167 for (dest = bgp_table_top(rib); dest;
12168 dest = bgp_route_next(dest)) {
12169 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12170
9bcb3eef 12171 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12172 continue;
9bcb3eef 12173 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12174 if (!table)
ea47320b 12175 continue;
d62a17ae 12176
4953391b
DA
12177 rm = bgp_node_match(table, &match);
12178 if (rm == NULL)
ea47320b 12179 continue;
d62a17ae 12180
9bcb3eef 12181 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12182 if (prefix_check
b54892e0 12183 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12184 bgp_dest_unlock_node(rm);
ea47320b
DL
12185 continue;
12186 }
d62a17ae 12187
9bcb3eef 12188 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12189 bgp, afi, safi, json, pathtype,
4027d19b 12190 &display, rpki_target_state);
44c69747 12191
9bcb3eef 12192 bgp_dest_unlock_node(rm);
44c69747
LK
12193 }
12194 } else if (safi == SAFI_EVPN) {
9bcb3eef 12195 struct bgp_dest *longest_pfx;
cded3b72 12196 bool is_exact_pfxlen_match = false;
44c69747 12197
9bcb3eef
DS
12198 for (dest = bgp_table_top(rib); dest;
12199 dest = bgp_route_next(dest)) {
12200 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12201
9bcb3eef 12202 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12203 continue;
9bcb3eef 12204 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12205 if (!table)
12206 continue;
12207
12208 longest_pfx = NULL;
cded3b72 12209 is_exact_pfxlen_match = false;
44c69747
LK
12210 /*
12211 * Search through all the prefixes for a match. The
12212 * pfx's are enumerated in ascending order of pfxlens.
12213 * So, the last pfx match is the longest match. Set
12214 * is_exact_pfxlen_match when we get exact pfxlen match
12215 */
12216 for (rm = bgp_table_top(table); rm;
12217 rm = bgp_route_next(rm)) {
b54892e0 12218 const struct prefix *rm_p =
9bcb3eef 12219 bgp_dest_get_prefix(rm);
44c69747
LK
12220 /*
12221 * Get prefixlen of the ip-prefix within type5
12222 * evpn route
12223 */
b54892e0
DS
12224 if (evpn_type5_prefix_match(rm_p, &match)
12225 && rm->info) {
44c69747
LK
12226 longest_pfx = rm;
12227 int type5_pfxlen =
b54892e0
DS
12228 bgp_evpn_get_type5_prefixlen(
12229 rm_p);
44c69747 12230 if (type5_pfxlen == match.prefixlen) {
cded3b72 12231 is_exact_pfxlen_match = true;
9bcb3eef 12232 bgp_dest_unlock_node(rm);
44c69747
LK
12233 break;
12234 }
d62a17ae 12235 }
12236 }
ea47320b 12237
44c69747
LK
12238 if (!longest_pfx)
12239 continue;
12240
12241 if (prefix_check && !is_exact_pfxlen_match)
12242 continue;
12243
12244 rm = longest_pfx;
9bcb3eef 12245 bgp_dest_lock_node(rm);
44c69747 12246
9bcb3eef 12247 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12248 bgp, afi, safi, json, pathtype,
4027d19b 12249 &display, rpki_target_state);
44c69747 12250
9bcb3eef 12251 bgp_dest_unlock_node(rm);
d62a17ae 12252 }
98a9dbc7 12253 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12254 if (use_json)
12255 json_paths = json_object_new_array();
12256
63a0b7a9
PG
12257 display = bgp_flowspec_display_match_per_ip(afi, rib,
12258 &match, prefix_check,
12259 vty,
12260 use_json,
12261 json_paths);
d5f20468
SP
12262 if (use_json) {
12263 if (display)
12264 json_object_object_add(json, "paths",
12265 json_paths);
12266 else
12267 json_object_free(json_paths);
12268 }
d62a17ae 12269 } else {
4953391b
DA
12270 dest = bgp_node_match(rib, &match);
12271 if (dest != NULL) {
9bcb3eef 12272 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12273 if (!prefix_check
9bcb3eef
DS
12274 || dest_p->prefixlen == match.prefixlen) {
12275 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12276 safi, json, pathtype,
4027d19b 12277 &display, rpki_target_state);
d62a17ae 12278 }
12279
9bcb3eef 12280 bgp_dest_unlock_node(dest);
d62a17ae 12281 }
12282 }
e5eee9af 12283
d62a17ae 12284 if (use_json) {
75eeda93 12285 vty_json(vty, json);
d62a17ae 12286 } else {
12287 if (!display) {
12288 vty_out(vty, "%% Network not in table\n");
12289 return CMD_WARNING;
12290 }
12291 }
b05a1c8b 12292
d62a17ae 12293 return CMD_SUCCESS;
718e3744 12294}
12295
fee0f4c6 12296/* Display specified route of Main RIB */
d62a17ae 12297static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12298 afi_t afi, safi_t safi, struct prefix_rd *prd,
12299 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12300 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12301{
9b86009a 12302 if (!bgp) {
d62a17ae 12303 bgp = bgp_get_default();
9b86009a
RW
12304 if (!bgp) {
12305 if (!use_json)
12306 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12307 else
12308 vty_out(vty, "{}\n");
9b86009a
RW
12309 return CMD_WARNING;
12310 }
12311 }
d62a17ae 12312
12313 /* labeled-unicast routes live in the unicast table */
12314 if (safi == SAFI_LABELED_UNICAST)
12315 safi = SAFI_UNICAST;
12316
12317 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12318 afi, safi, rpki_target_state, prd,
8aa22bbb 12319 prefix_check, pathtype, use_json);
d62a17ae 12320}
12321
12322static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12323 struct cmd_token **argv, bool exact, afi_t afi,
12324 safi_t safi, bool uj)
d62a17ae 12325{
12326 struct lcommunity *lcom;
12327 struct buffer *b;
12328 int i;
12329 char *str;
12330 int first = 0;
96c81f66 12331 uint16_t show_flags = 0;
4f28b2b5 12332 int ret;
96f3485c
MK
12333
12334 if (uj)
12335 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12336
12337 b = buffer_new(1024);
12338 for (i = 0; i < argc; i++) {
12339 if (first)
12340 buffer_putc(b, ' ');
12341 else {
12342 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12343 first = 1;
12344 buffer_putstr(b, argv[i]->arg);
12345 }
12346 }
12347 }
12348 buffer_putc(b, '\0');
57d187bc 12349
d62a17ae 12350 str = buffer_getstr(b);
12351 buffer_free(b);
57d187bc 12352
d62a17ae 12353 lcom = lcommunity_str2com(str);
12354 XFREE(MTYPE_TMP, str);
12355 if (!lcom) {
12356 vty_out(vty, "%% Large-community malformed\n");
12357 return CMD_WARNING;
12358 }
57d187bc 12359
4f28b2b5 12360 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12361 (exact ? bgp_show_type_lcommunity_exact
12362 : bgp_show_type_lcommunity),
12363 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12364
12365 lcommunity_free(&lcom);
12366 return ret;
57d187bc
JS
12367}
12368
d62a17ae 12369static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12370 const char *lcom, bool exact, afi_t afi,
12371 safi_t safi, bool uj)
57d187bc 12372{
d62a17ae 12373 struct community_list *list;
96c81f66 12374 uint16_t show_flags = 0;
96f3485c
MK
12375
12376 if (uj)
12377 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12378
57d187bc 12379
e237b0d2 12380 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12381 LARGE_COMMUNITY_LIST_MASTER);
12382 if (list == NULL) {
12383 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12384 lcom);
12385 return CMD_WARNING;
12386 }
57d187bc 12387
36a206db 12388 return bgp_show(vty, bgp, afi, safi,
12389 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12390 : bgp_show_type_lcommunity_list),
1e2ce4f1 12391 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12392}
12393
52951b63
DS
12394DEFUN (show_ip_bgp_large_community_list,
12395 show_ip_bgp_large_community_list_cmd,
77a3a95e 12396 "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
12397 SHOW_STR
12398 IP_STR
12399 BGP_STR
12400 BGP_INSTANCE_HELP_STR
9bedbb1e 12401 BGP_AFI_HELP_STR
4dd6177e 12402 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12403 "Display routes matching the large-community-list\n"
12404 "large-community-list number\n"
12405 "large-community-list name\n"
36a206db 12406 "Exact match of the large-communities\n"
52951b63
DS
12407 JSON_STR)
12408{
d62a17ae 12409 afi_t afi = AFI_IP6;
12410 safi_t safi = SAFI_UNICAST;
12411 int idx = 0;
36a206db 12412 bool exact_match = 0;
4d678463 12413 struct bgp *bgp = NULL;
9f049418 12414 bool uj = use_json(argc, argv);
d62a17ae 12415
ef3364f0
DA
12416 if (uj)
12417 argc--;
4d678463 12418
ef3364f0
DA
12419 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12420 &bgp, uj);
12421 if (!idx)
12422 return CMD_WARNING;
d62a17ae 12423
12424 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12425
12426 const char *clist_number_or_name = argv[++idx]->arg;
12427
12428 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12429 exact_match = 1;
12430
12431 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12432 exact_match, afi, safi, uj);
52951b63
DS
12433}
12434DEFUN (show_ip_bgp_large_community,
12435 show_ip_bgp_large_community_cmd,
36a206db 12436 "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
12437 SHOW_STR
12438 IP_STR
12439 BGP_STR
12440 BGP_INSTANCE_HELP_STR
9bedbb1e 12441 BGP_AFI_HELP_STR
4dd6177e 12442 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12443 "Display routes matching the large-communities\n"
12444 "List of large-community numbers\n"
36a206db 12445 "Exact match of the large-communities\n"
52951b63
DS
12446 JSON_STR)
12447{
d62a17ae 12448 afi_t afi = AFI_IP6;
12449 safi_t safi = SAFI_UNICAST;
12450 int idx = 0;
36a206db 12451 bool exact_match = 0;
4d678463 12452 struct bgp *bgp = NULL;
9f049418 12453 bool uj = use_json(argc, argv);
96c81f66 12454 uint16_t show_flags = 0;
d62a17ae 12455
96f3485c
MK
12456 if (uj) {
12457 argc--;
12458 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12459 }
4d678463 12460
96f3485c
MK
12461 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12462 &bgp, uj);
12463 if (!idx)
12464 return CMD_WARNING;
d62a17ae 12465
36a206db 12466 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12467 if (argv_find(argv, argc, "exact-match", &idx)) {
12468 argc--;
36a206db 12469 exact_match = 1;
1857760c 12470 }
36a206db 12471 return bgp_show_lcommunity(vty, bgp, argc, argv,
12472 exact_match, afi, safi, uj);
12473 } else
d62a17ae 12474 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12475 bgp_show_type_lcommunity_all, NULL, show_flags,
12476 RPKI_NOT_BEING_USED);
52951b63
DS
12477}
12478
71f1613a
DA
12479static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12480 safi_t safi, struct json_object *json_array);
d62a17ae 12481static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12482 safi_t safi, struct json_object *json);
e01ca200 12483
7b2ff250 12484
9ab0cf58
PG
12485DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12486 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12487 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12488 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12489{
12490 bool uj = use_json(argc, argv);
12491 struct bgp *bgp = NULL;
ec76a1d1
DA
12492 safi_t safi = SAFI_UNICAST;
12493 afi_t afi = AFI_IP6;
4265b261 12494 int idx = 0;
6c9d22e2
PG
12495 struct json_object *json_all = NULL;
12496 struct json_object *json_afi_safi = NULL;
4265b261
PG
12497
12498 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12499 &bgp, false);
71f1613a 12500 if (!idx)
4265b261 12501 return CMD_WARNING;
6c9d22e2 12502
4265b261 12503 if (uj)
6c9d22e2 12504 json_all = json_object_new_object();
4265b261 12505
9ab0cf58
PG
12506 FOREACH_AFI_SAFI (afi, safi) {
12507 /*
12508 * So limit output to those afi/safi pairs that
12509 * actually have something interesting in them
12510 */
12511 if (strmatch(get_afi_safi_str(afi, safi, true),
12512 "Unknown")) {
12513 continue;
12514 }
12515 if (uj) {
12516 json_afi_safi = json_object_new_array();
12517 json_object_object_add(
12518 json_all,
12519 get_afi_safi_str(afi, safi, true),
12520 json_afi_safi);
12521 } else {
12522 json_afi_safi = NULL;
6c9d22e2 12523 }
9ab0cf58
PG
12524
12525 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12526 }
6c9d22e2 12527
3757f964
DA
12528 if (uj)
12529 vty_json(vty, json_all);
6c9d22e2 12530
4265b261
PG
12531 return CMD_SUCCESS;
12532}
12533
7b2ff250 12534/* BGP route print out function without JSON */
14718643
PG
12535DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12536 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12537 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12538 SHOW_STR
12539 IP_STR
12540 BGP_STR
12541 BGP_INSTANCE_HELP_STR
12542 L2VPN_HELP_STR
12543 EVPN_HELP_STR
12544 "BGP RIB advertisement statistics\n"
12545 JSON_STR)
12546{
ec76a1d1
DA
12547 afi_t afi = AFI_IP6;
12548 safi_t safi = SAFI_UNICAST;
14718643
PG
12549 struct bgp *bgp = NULL;
12550 int idx = 0, ret;
12551 bool uj = use_json(argc, argv);
12552 struct json_object *json_afi_safi = NULL, *json = NULL;
12553
12554 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12555 &bgp, false);
12556 if (!idx)
12557 return CMD_WARNING;
12558
12559 if (uj)
12560 json_afi_safi = json_object_new_array();
12561 else
12562 json_afi_safi = NULL;
12563
12564 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12565
12566 if (uj) {
12567 json = json_object_new_object();
12568 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12569 json_afi_safi);
3757f964 12570 vty_json(vty, json);
14718643
PG
12571 }
12572 return ret;
12573}
12574
893cccd0 12575/* BGP route print out function without JSON */
9ab0cf58
PG
12576DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12577 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12578 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12579 "]]\
893cccd0 12580 statistics [json]",
9ab0cf58
PG
12581 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12582 BGP_SAFI_WITH_LABEL_HELP_STR
12583 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12584{
ec76a1d1
DA
12585 afi_t afi = AFI_IP6;
12586 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12587 struct bgp *bgp = NULL;
12588 int idx = 0, ret;
12589 bool uj = use_json(argc, argv);
6c9d22e2 12590 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12591
12592 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12593 &bgp, false);
12594 if (!idx)
12595 return CMD_WARNING;
6c9d22e2 12596
893cccd0 12597 if (uj)
6c9d22e2
PG
12598 json_afi_safi = json_object_new_array();
12599 else
12600 json_afi_safi = NULL;
12601
12602 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12603
12604 if (uj) {
12605 json = json_object_new_object();
12606 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12607 json_afi_safi);
3757f964 12608 vty_json(vty, json);
893cccd0
PG
12609 }
12610 return ret;
893cccd0 12611}
7b2ff250 12612
fe0f234d 12613DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12614 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12615 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12616 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12617 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12618 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12619 "Display the entries for all address families\n"
9ab0cf58
PG
12620 "Display detailed information about dampening\n"
12621 "Display detail of configured dampening parameters\n"
fe0f234d 12622 JSON_STR)
718e3744 12623{
d62a17ae 12624 afi_t afi = AFI_IP6;
12625 safi_t safi = SAFI_UNICAST;
d62a17ae 12626 struct bgp *bgp = NULL;
12627 int idx = 0;
96c81f66 12628 uint16_t show_flags = 0;
fe0f234d
RW
12629 bool uj = use_json(argc, argv);
12630
12631 if (uj) {
12632 argc--;
12633 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12634 }
96f3485c
MK
12635
12636 /* [<ipv4|ipv6> [all]] */
12637 if (all) {
12638 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12639 if (argv_find(argv, argc, "ipv4", &idx))
12640 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12641
12642 if (argv_find(argv, argc, "ipv6", &idx))
12643 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12644 }
d62a17ae 12645
12646 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12647 &bgp, false);
d62a17ae 12648 if (!idx)
12649 return CMD_WARNING;
12650
fe0f234d 12651 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12652}
12653
fe0f234d
RW
12654/* BGP route print out function */
12655DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12657 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12658 "]]\
96f3485c 12659 [all$all]\
cf4898bc
QY
12660 [cidr-only\
12661 |dampening <flap-statistics|dampened-paths>\
12662 |community [AA:NN|local-AS|no-advertise|no-export\
12663 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12664 |accept-own|accept-own-nexthop|route-filter-v6\
12665 |route-filter-v4|route-filter-translated-v6\
12666 |route-filter-translated-v4] [exact-match]\
70799983 12667 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12668 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12669 |prefix-list WORD\
ed126382 12670 |access-list ACCESSLIST_NAME\
70dd370f 12671 |route-map RMAP_NAME\
1e2ce4f1 12672 |rpki <invalid|valid|notfound>\
7d3cae70 12673 |version (1-4294967295)\
b4ad2fae 12674 |alias ALIAS_NAME\
39c3c736
RW
12675 |A.B.C.D/M longer-prefixes\
12676 |X:X::X:X/M longer-prefixes\
83856649 12677 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12678 |detail-routes$detail_routes\
67799a48 12679 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12680 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12681 BGP_SAFI_WITH_LABEL_HELP_STR
12682 "Display the entries for all address families\n"
12683 "Display only routes with non-natural netmasks\n"
12684 "Display detailed information about dampening\n"
12685 "Display flap statistics of routes\n"
12686 "Display paths suppressed due to dampening\n"
12687 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12688 "Do not send outside local AS (well-known community)\n"
12689 "Do not advertise to any peer (well-known community)\n"
12690 "Do not export to next AS (well-known community)\n"
12691 "Graceful shutdown (well-known community)\n"
12692 "Do not export to any peer (well-known community)\n"
12693 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12694 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12695 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12696 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12697 "Should accept VPN route with local nexthop (well-known community)\n"
12698 "RT VPNv6 route filtering (well-known community)\n"
12699 "RT VPNv4 route filtering (well-known community)\n"
12700 "RT translated VPNv6 route filtering (well-known community)\n"
12701 "RT translated VPNv4 route filtering (well-known community)\n"
12702 "Exact match of the communities\n"
70799983
RW
12703 "Community-list number\n"
12704 "Community-list name\n"
12705 "Display routes matching the community-list\n"
12706 "Exact match of the communities\n"
a7129347
RW
12707 "Display routes conforming to the filter-list\n"
12708 "Regular expression access list name\n"
6deaf579
RW
12709 "Display routes conforming to the prefix-list\n"
12710 "Prefix-list name\n"
ed126382
DA
12711 "Display routes conforming to the access-list\n"
12712 "Access-list name\n"
bf1a944a
RW
12713 "Display routes matching the route-map\n"
12714 "A route-map to match on\n"
a70a28a5
DA
12715 "RPKI route types\n"
12716 "A valid path as determined by rpki\n"
12717 "A invalid path as determined by rpki\n"
12718 "A path that has no rpki data\n"
12719 "Display prefixes with matching version numbers\n"
12720 "Version number and above\n"
12721 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12722 "BGP community alias\n"
12723 "IPv4 prefix\n"
12724 "Display route and more specific routes\n"
12725 "IPv6 prefix\n"
12726 "Display route and more specific routes\n"
83856649 12727 BGP_SELF_ORIG_HELP_STR
509d82bd 12728 "Display detailed version of all routes\n"
39c3c736 12729 JSON_STR
a70a28a5
DA
12730 "Display detailed version of JSON output\n"
12731 "Increase table width for longer prefixes\n")
7b2ff250
DW
12732{
12733 afi_t afi = AFI_IP6;
12734 safi_t safi = SAFI_UNICAST;
12735 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12736 void *output_arg = NULL;
7b2ff250
DW
12737 struct bgp *bgp = NULL;
12738 int idx = 0;
d0086e8e 12739 int exact_match = 0;
96f3485c
MK
12740 char *community = NULL;
12741 bool first = true;
96c81f66 12742 uint16_t show_flags = 0;
4027d19b 12743 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12744 struct prefix p;
96f3485c
MK
12745
12746 if (uj) {
9f049418 12747 argc--;
96f3485c
MK
12748 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12749 }
12750
67799a48
DA
12751 if (detail_json)
12752 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12753
509d82bd
DA
12754 if (detail_routes)
12755 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12756
96f3485c
MK
12757 /* [<ipv4|ipv6> [all]] */
12758 if (all) {
12759 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12760
12761 if (argv_find(argv, argc, "ipv4", &idx))
12762 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12763
12764 if (argv_find(argv, argc, "ipv6", &idx))
12765 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12766 }
12767
12768 if (wide)
12769 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12770
12771 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12772 &bgp, uj);
7b2ff250
DW
12773 if (!idx)
12774 return CMD_WARNING;
12775
7b2ff250 12776 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12777 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12778
12779 if (argv_find(argv, argc, "dampening", &idx)) {
12780 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12781 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12782 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12783 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12784 }
12785
12786 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12787 char *maybecomm = NULL;
d0086e8e 12788
79bc257a
RW
12789 if (idx + 1 < argc) {
12790 if (argv[idx + 1]->type == VARIABLE_TKN)
12791 maybecomm = argv[idx + 1]->arg;
12792 else
12793 maybecomm = argv[idx + 1]->text;
12794 }
12795
cf4898bc
QY
12796 if (maybecomm && !strmatch(maybecomm, "json")
12797 && !strmatch(maybecomm, "exact-match"))
12798 community = maybecomm;
d0086e8e 12799
cf4898bc
QY
12800 if (argv_find(argv, argc, "exact-match", &idx))
12801 exact_match = 1;
d0086e8e 12802
96f3485c
MK
12803 if (!community)
12804 sh_type = bgp_show_type_community_all;
12805 }
12806
70799983
RW
12807 if (argv_find(argv, argc, "community-list", &idx)) {
12808 const char *clist_number_or_name = argv[++idx]->arg;
12809 struct community_list *list;
12810
12811 if (argv_find(argv, argc, "exact-match", &idx))
12812 exact_match = 1;
12813
12814 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12815 COMMUNITY_LIST_MASTER);
12816 if (list == NULL) {
606d49a4 12817 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12818 clist_number_or_name);
12819 return CMD_WARNING;
12820 }
12821
12822 if (exact_match)
12823 sh_type = bgp_show_type_community_list_exact;
12824 else
12825 sh_type = bgp_show_type_community_list;
12826 output_arg = list;
12827 }
12828
a7129347
RW
12829 if (argv_find(argv, argc, "filter-list", &idx)) {
12830 const char *filter = argv[++idx]->arg;
12831 struct as_list *as_list;
12832
12833 as_list = as_list_lookup(filter);
12834 if (as_list == NULL) {
606d49a4 12835 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12836 filter);
12837 return CMD_WARNING;
12838 }
12839
12840 sh_type = bgp_show_type_filter_list;
12841 output_arg = as_list;
12842 }
12843
6deaf579
RW
12844 if (argv_find(argv, argc, "prefix-list", &idx)) {
12845 const char *prefix_list_str = argv[++idx]->arg;
12846 struct prefix_list *plist;
12847
12848 plist = prefix_list_lookup(afi, prefix_list_str);
12849 if (plist == NULL) {
606d49a4 12850 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12851 prefix_list_str);
12852 return CMD_WARNING;
12853 }
12854
12855 sh_type = bgp_show_type_prefix_list;
12856 output_arg = plist;
12857 }
12858
ed126382
DA
12859 if (argv_find(argv, argc, "access-list", &idx)) {
12860 const char *access_list_str = argv[++idx]->arg;
12861 struct access_list *alist;
12862
12863 alist = access_list_lookup(afi, access_list_str);
12864 if (!alist) {
606d49a4 12865 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12866 access_list_str);
12867 return CMD_WARNING;
12868 }
12869
12870 sh_type = bgp_show_type_access_list;
12871 output_arg = alist;
12872 }
12873
bf1a944a
RW
12874 if (argv_find(argv, argc, "route-map", &idx)) {
12875 const char *rmap_str = argv[++idx]->arg;
12876 struct route_map *rmap;
12877
12878 rmap = route_map_lookup_by_name(rmap_str);
12879 if (!rmap) {
606d49a4 12880 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12881 return CMD_WARNING;
12882 }
12883
12884 sh_type = bgp_show_type_route_map;
12885 output_arg = rmap;
12886 }
12887
1e2ce4f1
DS
12888 if (argv_find(argv, argc, "rpki", &idx)) {
12889 sh_type = bgp_show_type_rpki;
12890 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12891 rpki_target_state = RPKI_VALID;
1e2ce4f1 12892 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12893 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12894 }
12895
7d3cae70
DA
12896 /* Display prefixes with matching version numbers */
12897 if (argv_find(argv, argc, "version", &idx)) {
12898 sh_type = bgp_show_type_prefix_version;
2391833e 12899 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12900 }
12901
a70a28a5
DA
12902 /* Display prefixes with matching BGP community alias */
12903 if (argv_find(argv, argc, "alias", &idx)) {
12904 sh_type = bgp_show_type_community_alias;
2391833e 12905 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12906 }
12907
39c3c736
RW
12908 /* prefix-longer */
12909 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12910 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12911 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12912
12913 if (!str2prefix(prefix_str, &p)) {
12914 vty_out(vty, "%% Malformed Prefix\n");
12915 return CMD_WARNING;
12916 }
12917
12918 sh_type = bgp_show_type_prefix_longer;
12919 output_arg = &p;
a70a28a5
DA
12920 }
12921
83856649
KQ
12922 /* self originated only */
12923 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12924 sh_type = bgp_show_type_self_originated;
12925
96f3485c
MK
12926 if (!all) {
12927 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12928 if (community)
12929 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12930 exact_match, afi, safi,
12931 show_flags);
2391833e 12932 else
a70a28a5 12933 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12934 output_arg, show_flags,
a70a28a5 12935 rpki_target_state);
96f3485c 12936 } else {
fa5ac378
DA
12937 struct listnode *node;
12938 struct bgp *abgp;
96f3485c
MK
12939 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12940 * AFI_IP6 */
12941
12942 if (uj)
12943 vty_out(vty, "{\n");
12944
12945 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12946 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12947 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12948 ? AFI_IP
12949 : AFI_IP6;
fa5ac378
DA
12950 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12951 FOREACH_SAFI (safi) {
12952 if (!bgp_afi_safi_peer_exists(abgp, afi,
12953 safi))
12954 continue;
96f3485c 12955
fa5ac378
DA
12956 if (uj) {
12957 if (first)
12958 first = false;
12959 else
12960 vty_out(vty, ",\n");
12961 vty_out(vty, "\"%s\":{\n",
12962 get_afi_safi_str(afi,
12963 safi,
12964 true));
12965 } else
12966 vty_out(vty,
12967 "\nFor address family: %s\n",
12968 get_afi_safi_str(
12969 afi, safi,
12970 false));
12971
12972 if (community)
12973 bgp_show_community(
12974 vty, abgp, community,
12975 exact_match, afi, safi,
12976 show_flags);
96f3485c 12977 else
fa5ac378
DA
12978 bgp_show(vty, abgp, afi, safi,
12979 sh_type, output_arg,
12980 show_flags,
12981 rpki_target_state);
12982 if (uj)
12983 vty_out(vty, "}\n");
12984 }
96f3485c
MK
12985 }
12986 } else {
12987 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12988 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12989 FOREACH_AFI_SAFI (afi, safi) {
12990 if (!bgp_afi_safi_peer_exists(abgp, afi,
12991 safi))
12992 continue;
96f3485c 12993
fa5ac378
DA
12994 if (uj) {
12995 if (first)
12996 first = false;
12997 else
12998 vty_out(vty, ",\n");
12999
13000 vty_out(vty, "\"%s\":{\n",
13001 get_afi_safi_str(afi,
13002 safi,
13003 true));
13004 } else
13005 vty_out(vty,
13006 "\nFor address family: %s\n",
13007 get_afi_safi_str(
13008 afi, safi,
13009 false));
13010
13011 if (community)
13012 bgp_show_community(
13013 vty, abgp, community,
13014 exact_match, afi, safi,
13015 show_flags);
96f3485c 13016 else
fa5ac378
DA
13017 bgp_show(vty, abgp, afi, safi,
13018 sh_type, output_arg,
13019 show_flags,
13020 rpki_target_state);
13021 if (uj)
13022 vty_out(vty, "}\n");
13023 }
96f3485c
MK
13024 }
13025 }
13026 if (uj)
13027 vty_out(vty, "}\n");
13028 }
13029 return CMD_SUCCESS;
a636c635 13030}
47fc97cc 13031
718e3744 13032DEFUN (show_ip_bgp_route,
13033 show_ip_bgp_route_cmd,
8aa22bbb 13034 "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 13035 SHOW_STR
13036 IP_STR
13037 BGP_STR
a636c635 13038 BGP_INSTANCE_HELP_STR
4f280b15 13039 BGP_AFI_HELP_STR
4dd6177e 13040 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13041 "Network in the BGP routing table to display\n"
0c7b1b01 13042 "IPv4 prefix\n"
8c3deaae 13043 "Network in the BGP routing table to display\n"
0c7b1b01 13044 "IPv6 prefix\n"
4092b06c 13045 "Display only the bestpath\n"
b05a1c8b 13046 "Display only multipaths\n"
8aa22bbb
DS
13047 "Display only paths that match the specified rpki state\n"
13048 "A valid path as determined by rpki\n"
13049 "A invalid path as determined by rpki\n"
13050 "A path that has no rpki data\n"
9973d184 13051 JSON_STR)
4092b06c 13052{
d62a17ae 13053 int prefix_check = 0;
ae19d7dd 13054
d62a17ae 13055 afi_t afi = AFI_IP6;
13056 safi_t safi = SAFI_UNICAST;
13057 char *prefix = NULL;
13058 struct bgp *bgp = NULL;
13059 enum bgp_path_type path_type;
9f049418 13060 bool uj = use_json(argc, argv);
b05a1c8b 13061
d62a17ae 13062 int idx = 0;
ae19d7dd 13063
d62a17ae 13064 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13065 &bgp, uj);
d62a17ae 13066 if (!idx)
13067 return CMD_WARNING;
c41247f5 13068
d62a17ae 13069 if (!bgp) {
13070 vty_out(vty,
13071 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13072 return CMD_WARNING;
13073 }
a636c635 13074
d62a17ae 13075 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13076 if (argv_find(argv, argc, "A.B.C.D", &idx)
13077 || argv_find(argv, argc, "X:X::X:X", &idx))
13078 prefix_check = 0;
13079 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13080 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13081 prefix_check = 1;
13082
13083 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13084 && afi != AFI_IP6) {
13085 vty_out(vty,
13086 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13087 return CMD_WARNING;
13088 }
13089 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13090 && afi != AFI_IP) {
13091 vty_out(vty,
13092 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13093 return CMD_WARNING;
13094 }
13095
13096 prefix = argv[idx]->arg;
13097
13098 /* [<bestpath|multipath>] */
13099 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13100 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13101 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13102 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13103 else
360660c6 13104 path_type = BGP_PATH_SHOW_ALL;
a636c635 13105
d62a17ae 13106 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13107 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13108}
13109
8c3deaae
QY
13110DEFUN (show_ip_bgp_regexp,
13111 show_ip_bgp_regexp_cmd,
3e5b31b3 13112 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13113 SHOW_STR
13114 IP_STR
13115 BGP_STR
b00b230a 13116 BGP_INSTANCE_HELP_STR
4f280b15 13117 BGP_AFI_HELP_STR
4dd6177e 13118 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13119 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13120 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13121 JSON_STR)
8c3deaae 13122{
d62a17ae 13123 afi_t afi = AFI_IP6;
13124 safi_t safi = SAFI_UNICAST;
13125 struct bgp *bgp = NULL;
3e5b31b3
DA
13126 bool uj = use_json(argc, argv);
13127 char *regstr = NULL;
8c3deaae 13128
d62a17ae 13129 int idx = 0;
13130 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13131 &bgp, false);
d62a17ae 13132 if (!idx)
13133 return CMD_WARNING;
8c3deaae 13134
d62a17ae 13135 // get index of regex
3e5b31b3
DA
13136 if (argv_find(argv, argc, "REGEX", &idx))
13137 regstr = argv[idx]->arg;
8c3deaae 13138
5f71d11c 13139 assert(regstr);
3e5b31b3
DA
13140 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13141 bgp_show_type_regexp, uj);
8c3deaae
QY
13142}
13143
ae248832 13144DEFPY (show_ip_bgp_instance_all,
a636c635 13145 show_ip_bgp_instance_all_cmd,
ae248832 13146 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13147 SHOW_STR
a636c635 13148 IP_STR
4092b06c 13149 BGP_STR
a636c635 13150 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13151 BGP_AFI_HELP_STR
4dd6177e 13152 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13153 JSON_STR
13154 "Increase table width for longer prefixes\n")
4092b06c 13155{
54d05dea 13156 afi_t afi = AFI_IP6;
d62a17ae 13157 safi_t safi = SAFI_UNICAST;
13158 struct bgp *bgp = NULL;
d62a17ae 13159 int idx = 0;
96c81f66 13160 uint16_t show_flags = 0;
ae19d7dd 13161
96f3485c 13162 if (uj) {
d62a17ae 13163 argc--;
96f3485c
MK
13164 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13165 }
13166
13167 if (wide)
13168 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13169
9f049418
DS
13170 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13171 &bgp, uj);
13172 if (!idx)
13173 return CMD_WARNING;
13174
96f3485c 13175 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13176 return CMD_SUCCESS;
e3e29b32
LB
13177}
13178
a4d82a8a 13179static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13180 afi_t afi, safi_t safi, enum bgp_show_type type,
13181 bool use_json)
718e3744 13182{
d62a17ae 13183 regex_t *regex;
13184 int rc;
96c81f66 13185 uint16_t show_flags = 0;
96f3485c
MK
13186
13187 if (use_json)
13188 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13189
c3900853 13190 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13191 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13192 regstr);
13193 return CMD_WARNING_CONFIG_FAILED;
13194 }
13195
d62a17ae 13196 regex = bgp_regcomp(regstr);
13197 if (!regex) {
13198 vty_out(vty, "Can't compile regexp %s\n", regstr);
13199 return CMD_WARNING;
13200 }
a636c635 13201
1e2ce4f1
DS
13202 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13203 RPKI_NOT_BEING_USED);
d62a17ae 13204 bgp_regex_free(regex);
13205 return rc;
e3e29b32
LB
13206}
13207
7f323236
DW
13208static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13209 const char *comstr, int exact, afi_t afi,
96c81f66 13210 safi_t safi, uint16_t show_flags)
d62a17ae 13211{
13212 struct community *com;
d62a17ae 13213 int ret = 0;
13214
7f323236 13215 com = community_str2com(comstr);
d62a17ae 13216 if (!com) {
7f323236 13217 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13218 return CMD_WARNING;
13219 }
13220
13221 ret = bgp_show(vty, bgp, afi, safi,
13222 (exact ? bgp_show_type_community_exact
13223 : bgp_show_type_community),
1e2ce4f1 13224 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13225 community_free(&com);
46c3ce83 13226
d62a17ae 13227 return ret;
718e3744 13228}
13229
d62a17ae 13230enum bgp_stats {
13231 BGP_STATS_MAXBITLEN = 0,
13232 BGP_STATS_RIB,
13233 BGP_STATS_PREFIXES,
13234 BGP_STATS_TOTPLEN,
13235 BGP_STATS_UNAGGREGATEABLE,
13236 BGP_STATS_MAX_AGGREGATEABLE,
13237 BGP_STATS_AGGREGATES,
13238 BGP_STATS_SPACE,
13239 BGP_STATS_ASPATH_COUNT,
13240 BGP_STATS_ASPATH_MAXHOPS,
13241 BGP_STATS_ASPATH_TOTHOPS,
13242 BGP_STATS_ASPATH_MAXSIZE,
13243 BGP_STATS_ASPATH_TOTSIZE,
13244 BGP_STATS_ASN_HIGHEST,
13245 BGP_STATS_MAX,
a636c635 13246};
2815e61f 13247
9ab0cf58 13248#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13249#define TABLE_STATS_IDX_JSON 1
13250
13251static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13252 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13253 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13254 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13255 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13256 "unaggregateablePrefixes"},
13257 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13258 "maximumAggregateablePrefixes"},
13259 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13260 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13261 [BGP_STATS_SPACE] = {"Address space advertised",
13262 "addressSpaceAdvertised"},
9ab0cf58
PG
13263 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13264 "advertisementsWithPaths"},
13265 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13266 "longestAsPath"},
13267 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13268 "largestAsPath"},
13269 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13270 "averageAsPathLengthHops"},
13271 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13272 "averageAsPathSizeBytes"},
13273 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13274 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13275};
2815e61f 13276
d62a17ae 13277struct bgp_table_stats {
13278 struct bgp_table *table;
13279 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13280
13281 unsigned long long
13282 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13283 1];
13284
8d0ab76d 13285 double total_space;
ff7924f6
PJ
13286};
13287
9bcb3eef 13288static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13289 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13290{
9bcb3eef 13291 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13292 struct bgp_path_info *pi;
b54892e0 13293 const struct prefix *rn_p;
d62a17ae 13294
9bcb3eef 13295 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13296 return;
d62a17ae 13297
9bcb3eef 13298 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13299 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13300 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13301
0747643e 13302 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13303 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13304 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13305 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13306
9bcb3eef 13307 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13308 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13309 /* announced address space */
13310 if (space)
b54892e0 13311 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13312 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13313 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13314
9c14ec72 13315
9bcb3eef 13316 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13317 ts->counts[BGP_STATS_RIB]++;
13318
05864da7
DS
13319 if (CHECK_FLAG(pi->attr->flag,
13320 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13321 ts->counts[BGP_STATS_AGGREGATES]++;
13322
13323 /* as-path stats */
05864da7 13324 if (pi->attr->aspath) {
9c14ec72
RW
13325 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13326 unsigned int size = aspath_size(pi->attr->aspath);
13327 as_t highest = aspath_highest(pi->attr->aspath);
13328
13329 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13330
13331 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13332 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13333
13334 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13335 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13336
13337 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13338 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13339 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13340 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13341 }
13342 }
13343}
13344
e6685141 13345static void bgp_table_stats_walker(struct event *t)
9c14ec72 13346{
9bcb3eef
DS
13347 struct bgp_dest *dest, *ndest;
13348 struct bgp_dest *top;
e16d030c 13349 struct bgp_table_stats *ts = EVENT_ARG(t);
9c14ec72
RW
13350 unsigned int space = 0;
13351
13352 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13353 return;
9c14ec72
RW
13354
13355 switch (ts->table->afi) {
13356 case AFI_IP:
13357 space = IPV4_MAX_BITLEN;
13358 break;
13359 case AFI_IP6:
13360 space = IPV6_MAX_BITLEN;
13361 break;
3ba7b4af
TA
13362 case AFI_L2VPN:
13363 space = EVPN_ROUTE_PREFIXLEN;
13364 break;
58cf0823
DS
13365 case AFI_UNSPEC:
13366 case AFI_MAX:
cc9f21da 13367 return;
9c14ec72
RW
13368 }
13369
13370 ts->counts[BGP_STATS_MAXBITLEN] = space;
13371
9bcb3eef 13372 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13373 if (ts->table->safi == SAFI_MPLS_VPN
13374 || ts->table->safi == SAFI_ENCAP
13375 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13376 struct bgp_table *table;
13377
9bcb3eef 13378 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13379 if (!table)
13380 continue;
13381
13382 top = bgp_table_top(table);
9bcb3eef
DS
13383 for (ndest = bgp_table_top(table); ndest;
13384 ndest = bgp_route_next(ndest))
13385 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13386 } else {
9bcb3eef 13387 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13388 }
13389 }
2815e61f 13390}
ff7924f6 13391
71f1613a
DA
13392static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13393 struct json_object *json_array)
13394{
13395 struct listnode *node, *nnode;
13396 struct bgp *bgp;
13397
13398 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13399 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13400}
13401
13402static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13403 safi_t safi, struct json_object *json_array)
2815e61f 13404{
d62a17ae 13405 struct bgp_table_stats ts;
13406 unsigned int i;
893cccd0
PG
13407 int ret = CMD_SUCCESS;
13408 char temp_buf[20];
6c9d22e2 13409 struct json_object *json = NULL;
0747643e
AQ
13410 uint32_t bitlen = 0;
13411 struct json_object *json_bitlen;
6c9d22e2
PG
13412
13413 if (json_array)
13414 json = json_object_new_object();
019386c2 13415
d62a17ae 13416 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13417 char warning_msg[50];
13418
13419 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13420 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13421 safi);
6c9d22e2
PG
13422
13423 if (!json)
893cccd0
PG
13424 vty_out(vty, "%s\n", warning_msg);
13425 else
9ab0cf58 13426 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13427
893cccd0
PG
13428 ret = CMD_WARNING;
13429 goto end_table_stats;
d62a17ae 13430 }
019386c2 13431
893cccd0 13432 if (!json)
5290ceab
DA
13433 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13434 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13435 else
13436 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13437
d62a17ae 13438 /* labeled-unicast routes live in the unicast table */
13439 if (safi == SAFI_LABELED_UNICAST)
13440 safi = SAFI_UNICAST;
019386c2 13441
d62a17ae 13442 memset(&ts, 0, sizeof(ts));
13443 ts.table = bgp->rib[afi][safi];
8c1186d3 13444 event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13445
d62a17ae 13446 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13447 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13448 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13449 continue;
13450
13451 switch (i) {
d62a17ae 13452 case BGP_STATS_ASPATH_TOTHOPS:
13453 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13454 if (!json) {
9ab0cf58
PG
13455 snprintf(
13456 temp_buf, sizeof(temp_buf), "%12.2f",
13457 ts.counts[i]
13458 ? (float)ts.counts[i]
13459 / (float)ts.counts
13460 [BGP_STATS_ASPATH_COUNT]
13461 : 0);
893cccd0 13462 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13463 table_stats_strs[i]
13464 [TABLE_STATS_IDX_VTY],
893cccd0 13465 temp_buf);
9ab0cf58
PG
13466 } else {
13467 json_object_double_add(
13468 json,
13469 table_stats_strs[i]
13470 [TABLE_STATS_IDX_JSON],
13471 ts.counts[i]
13472 ? (double)ts.counts[i]
13473 / (double)ts.counts
d62a17ae 13474 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13475 : 0);
13476 }
d62a17ae 13477 break;
13478 case BGP_STATS_TOTPLEN:
6c9d22e2 13479 if (!json) {
9ab0cf58
PG
13480 snprintf(
13481 temp_buf, sizeof(temp_buf), "%12.2f",
13482 ts.counts[i]
13483 ? (float)ts.counts[i]
13484 / (float)ts.counts
13485 [BGP_STATS_PREFIXES]
13486 : 0);
893cccd0 13487 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13488 table_stats_strs[i]
13489 [TABLE_STATS_IDX_VTY],
893cccd0 13490 temp_buf);
9ab0cf58
PG
13491 } else {
13492 json_object_double_add(
13493 json,
13494 table_stats_strs[i]
13495 [TABLE_STATS_IDX_JSON],
13496 ts.counts[i]
13497 ? (double)ts.counts[i]
13498 / (double)ts.counts
d62a17ae 13499 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13500 : 0);
13501 }
d62a17ae 13502 break;
13503 case BGP_STATS_SPACE:
6c9d22e2
PG
13504 if (!json) {
13505 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13506 ts.total_space);
893cccd0 13507 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13508 table_stats_strs[i]
13509 [TABLE_STATS_IDX_VTY],
893cccd0 13510 temp_buf);
9ab0cf58
PG
13511 } else {
13512 json_object_double_add(
13513 json,
13514 table_stats_strs[i]
13515 [TABLE_STATS_IDX_JSON],
13516 (double)ts.total_space);
13517 }
8d0ab76d 13518 if (afi == AFI_IP6) {
6c9d22e2
PG
13519 if (!json) {
13520 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13521 "%12g",
13522 ts.total_space
13523 * pow(2.0, -128 + 32));
6c9d22e2
PG
13524 vty_out(vty, "%30s: %s\n",
13525 "/32 equivalent %s\n",
13526 temp_buf);
9ab0cf58
PG
13527 } else {
13528 json_object_double_add(
13529 json, "/32equivalent",
13530 (double)(ts.total_space
13531 * pow(2.0,
13532 -128 + 32)));
13533 }
6c9d22e2
PG
13534 if (!json) {
13535 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13536 "%12g",
13537 ts.total_space
13538 * pow(2.0, -128 + 48));
6c9d22e2
PG
13539 vty_out(vty, "%30s: %s\n",
13540 "/48 equivalent %s\n",
13541 temp_buf);
9ab0cf58
PG
13542 } else {
13543 json_object_double_add(
13544 json, "/48equivalent",
13545 (double)(ts.total_space
13546 * pow(2.0,
13547 -128 + 48)));
13548 }
8d0ab76d 13549 } else {
6c9d22e2
PG
13550 if (!json) {
13551 snprintf(temp_buf, sizeof(temp_buf),
13552 "%12.2f",
9ab0cf58
PG
13553 ts.total_space * 100.
13554 * pow(2.0, -32));
6c9d22e2 13555 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13556 "% announced ", temp_buf);
13557 } else {
13558 json_object_double_add(
13559 json, "%announced",
13560 (double)(ts.total_space * 100.
13561 * pow(2.0, -32)));
13562 }
6c9d22e2
PG
13563 if (!json) {
13564 snprintf(temp_buf, sizeof(temp_buf),
13565 "%12.2f",
9ab0cf58
PG
13566 ts.total_space
13567 * pow(2.0, -32 + 8));
6c9d22e2
PG
13568 vty_out(vty, "%30s: %s\n",
13569 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13570 } else {
13571 json_object_double_add(
13572 json, "/8equivalent",
13573 (double)(ts.total_space
13574 * pow(2.0, -32 + 8)));
13575 }
6c9d22e2
PG
13576 if (!json) {
13577 snprintf(temp_buf, sizeof(temp_buf),
13578 "%12.2f",
9ab0cf58
PG
13579 ts.total_space
13580 * pow(2.0, -32 + 24));
6c9d22e2 13581 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13582 "/24 equivalent ", temp_buf);
13583 } else {
13584 json_object_double_add(
13585 json, "/24equivalent",
13586 (double)(ts.total_space
13587 * pow(2.0, -32 + 24)));
13588 }
8d0ab76d 13589 }
d62a17ae 13590 break;
13591 default:
6c9d22e2
PG
13592 if (!json) {
13593 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13594 ts.counts[i]);
893cccd0 13595 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13596 table_stats_strs[i]
13597 [TABLE_STATS_IDX_VTY],
13598 temp_buf);
13599 } else {
13600 json_object_int_add(
13601 json,
13602 table_stats_strs[i]
13603 [TABLE_STATS_IDX_JSON],
13604 ts.counts[i]);
13605 }
d62a17ae 13606 }
893cccd0
PG
13607 if (!json)
13608 vty_out(vty, "\n");
d62a17ae 13609 }
0747643e
AQ
13610
13611 switch (afi) {
13612 case AFI_IP:
13613 bitlen = IPV4_MAX_BITLEN;
13614 break;
13615 case AFI_IP6:
13616 bitlen = IPV6_MAX_BITLEN;
13617 break;
13618 case AFI_L2VPN:
13619 bitlen = EVPN_ROUTE_PREFIXLEN;
13620 break;
58cf0823
DS
13621 case AFI_UNSPEC:
13622 case AFI_MAX:
0747643e
AQ
13623 break;
13624 }
13625
13626 if (json) {
13627 json_bitlen = json_object_new_array();
13628
13629 for (i = 0; i <= bitlen; i++) {
13630 struct json_object *ind_bit = json_object_new_object();
13631
13632 if (!ts.prefix_len_count[i])
13633 continue;
13634
13635 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13636 json_object_int_add(ind_bit, temp_buf,
13637 ts.prefix_len_count[i]);
13638 json_object_array_add(json_bitlen, ind_bit);
13639 }
13640 json_object_object_add(json, "prefixLength", json_bitlen);
13641 }
13642
9ab0cf58 13643end_table_stats:
6c9d22e2
PG
13644 if (json)
13645 json_object_array_add(json_array, json);
893cccd0 13646 return ret;
d62a17ae 13647}
13648
71f1613a
DA
13649static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13650 safi_t safi, struct json_object *json_array)
13651{
13652 if (!bgp) {
13653 bgp_table_stats_all(vty, afi, safi, json_array);
13654 return CMD_SUCCESS;
13655 }
13656
13657 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13658}
13659
d62a17ae 13660enum bgp_pcounts {
13661 PCOUNT_ADJ_IN = 0,
13662 PCOUNT_DAMPED,
13663 PCOUNT_REMOVED,
13664 PCOUNT_HISTORY,
13665 PCOUNT_STALE,
13666 PCOUNT_VALID,
13667 PCOUNT_ALL,
13668 PCOUNT_COUNTED,
7e3d9632 13669 PCOUNT_BPATH_SELECTED,
d62a17ae 13670 PCOUNT_PFCNT, /* the figure we display to users */
13671 PCOUNT_MAX,
a636c635 13672};
718e3744 13673
2b64873d 13674static const char *const pcount_strs[] = {
9d303b37
DL
13675 [PCOUNT_ADJ_IN] = "Adj-in",
13676 [PCOUNT_DAMPED] = "Damped",
13677 [PCOUNT_REMOVED] = "Removed",
13678 [PCOUNT_HISTORY] = "History",
13679 [PCOUNT_STALE] = "Stale",
13680 [PCOUNT_VALID] = "Valid",
13681 [PCOUNT_ALL] = "All RIB",
13682 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13683 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13684 [PCOUNT_PFCNT] = "Useable",
13685 [PCOUNT_MAX] = NULL,
a636c635 13686};
718e3744 13687
d62a17ae 13688struct peer_pcounts {
13689 unsigned int count[PCOUNT_MAX];
13690 const struct peer *peer;
13691 const struct bgp_table *table;
54317cba 13692 safi_t safi;
a636c635 13693};
47fc97cc 13694
9bcb3eef 13695static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13696{
54317cba
JW
13697 const struct bgp_adj_in *ain;
13698 const struct bgp_path_info *pi;
d62a17ae 13699 const struct peer *peer = pc->peer;
13700
54317cba
JW
13701 for (ain = rn->adj_in; ain; ain = ain->next)
13702 if (ain->peer == peer)
13703 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13704
9bcb3eef 13705 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13706
54317cba
JW
13707 if (pi->peer != peer)
13708 continue;
d62a17ae 13709
54317cba 13710 pc->count[PCOUNT_ALL]++;
d62a17ae 13711
54317cba
JW
13712 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13713 pc->count[PCOUNT_DAMPED]++;
13714 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13715 pc->count[PCOUNT_HISTORY]++;
13716 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13717 pc->count[PCOUNT_REMOVED]++;
13718 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13719 pc->count[PCOUNT_STALE]++;
13720 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13721 pc->count[PCOUNT_VALID]++;
13722 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13723 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13724 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13725 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13726
13727 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13728 pc->count[PCOUNT_COUNTED]++;
13729 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13730 flog_err(
13731 EC_LIB_DEVELOPMENT,
13732 "Attempting to count but flags say it is unusable");
13733 } else {
40381db7 13734 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13735 flog_err(
13736 EC_LIB_DEVELOPMENT,
13737 "Not counted but flags say we should");
d62a17ae 13738 }
13739 }
54317cba
JW
13740}
13741
e6685141 13742static void bgp_peer_count_walker(struct event *t)
54317cba 13743{
9bcb3eef 13744 struct bgp_dest *rn, *rm;
54317cba 13745 const struct bgp_table *table;
e16d030c 13746 struct peer_pcounts *pc = EVENT_ARG(t);
54317cba
JW
13747
13748 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13749 || pc->safi == SAFI_EVPN) {
13750 /* Special handling for 2-level routing tables. */
13751 for (rn = bgp_table_top(pc->table); rn;
13752 rn = bgp_route_next(rn)) {
9bcb3eef 13753 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13754 if (table != NULL)
13755 for (rm = bgp_table_top(table); rm;
13756 rm = bgp_route_next(rm))
13757 bgp_peer_count_proc(rm, pc);
13758 }
13759 } else
13760 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13761 bgp_peer_count_proc(rn, pc);
718e3744 13762}
13763
d62a17ae 13764static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13765 safi_t safi, bool use_json)
856ca177 13766{
d62a17ae 13767 struct peer_pcounts pcounts = {.peer = peer};
13768 unsigned int i;
13769 json_object *json = NULL;
13770 json_object *json_loop = NULL;
856ca177 13771
d62a17ae 13772 if (use_json) {
13773 json = json_object_new_object();
13774 json_loop = json_object_new_object();
13775 }
718e3744 13776
d62a17ae 13777 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13778 || !peer->bgp->rib[afi][safi]) {
13779 if (use_json) {
13780 json_object_string_add(
13781 json, "warning",
13782 "No such neighbor or address family");
13783 vty_out(vty, "%s\n", json_object_to_json_string(json));
13784 json_object_free(json);
d5f20468 13785 json_object_free(json_loop);
d62a17ae 13786 } else
13787 vty_out(vty, "%% No such neighbor or address family\n");
13788
13789 return CMD_WARNING;
13790 }
2a71e9ce 13791
d62a17ae 13792 memset(&pcounts, 0, sizeof(pcounts));
13793 pcounts.peer = peer;
13794 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13795 pcounts.safi = safi;
d62a17ae 13796
13797 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13798 * stats for the thread-walk (i.e. ensure this can't be blamed on
13799 * on just vty_read()).
13800 */
8c1186d3 13801 event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
d62a17ae 13802
13803 if (use_json) {
13804 json_object_string_add(json, "prefixCountsFor", peer->host);
13805 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13806 get_afi_safi_str(afi, safi, true));
d62a17ae 13807 json_object_int_add(json, "pfxCounter",
13808 peer->pcount[afi][safi]);
13809
13810 for (i = 0; i < PCOUNT_MAX; i++)
13811 json_object_int_add(json_loop, pcount_strs[i],
13812 pcounts.count[i]);
13813
13814 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13815
13816 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13817 json_object_string_add(json, "pfxctDriftFor",
13818 peer->host);
13819 json_object_string_add(
13820 json, "recommended",
13821 "Please report this bug, with the above command output");
13822 }
75eeda93 13823 vty_json(vty, json);
d62a17ae 13824 } else {
13825
13826 if (peer->hostname
892fedb6 13827 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13828 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13829 peer->hostname, peer->host,
5cb5f4d0 13830 get_afi_safi_str(afi, safi, false));
d62a17ae 13831 } else {
13832 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13833 get_afi_safi_str(afi, safi, false));
d62a17ae 13834 }
13835
6cde4b45 13836 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13837 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13838
13839 for (i = 0; i < PCOUNT_MAX; i++)
13840 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13841 pcounts.count[i]);
13842
13843 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13844 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13845 vty_out(vty,
13846 "Please report this bug, with the above command output\n");
13847 }
13848 }
13849
13850 return CMD_SUCCESS;
718e3744 13851}
13852
a636c635
DW
13853DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13854 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13855 "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 13856 SHOW_STR
13857 IP_STR
13858 BGP_STR
8386ac43 13859 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13860 BGP_AFI_HELP_STR
13861 BGP_SAFI_HELP_STR
0b16f239
DS
13862 "Detailed information on TCP and BGP neighbor connections\n"
13863 "Neighbor to display information about\n"
13864 "Neighbor to display information about\n"
91d37724 13865 "Neighbor on BGP configured interface\n"
a636c635 13866 "Display detailed prefix count information\n"
9973d184 13867 JSON_STR)
0b16f239 13868{
d62a17ae 13869 afi_t afi = AFI_IP6;
13870 safi_t safi = SAFI_UNICAST;
13871 struct peer *peer;
13872 int idx = 0;
13873 struct bgp *bgp = NULL;
9f049418
DS
13874 bool uj = use_json(argc, argv);
13875
13876 if (uj)
13877 argc--;
856ca177 13878
d62a17ae 13879 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13880 &bgp, uj);
d62a17ae 13881 if (!idx)
13882 return CMD_WARNING;
0b16f239 13883
d62a17ae 13884 argv_find(argv, argc, "neighbors", &idx);
13885 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13886 if (!peer)
13887 return CMD_WARNING;
bb46e94f 13888
29c8d9da 13889 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13890}
0b16f239 13891
d6902373
PG
13892#ifdef KEEP_OLD_VPN_COMMANDS
13893DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13894 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13895 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13896 SHOW_STR
13897 IP_STR
13898 BGP_STR
d6902373 13899 BGP_VPNVX_HELP_STR
91d37724 13900 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13901 "Detailed information on TCP and BGP neighbor connections\n"
13902 "Neighbor to display information about\n"
13903 "Neighbor to display information about\n"
91d37724 13904 "Neighbor on BGP configured interface\n"
a636c635 13905 "Display detailed prefix count information\n"
9973d184 13906 JSON_STR)
a636c635 13907{
d62a17ae 13908 int idx_peer = 6;
13909 struct peer *peer;
9f049418 13910 bool uj = use_json(argc, argv);
a636c635 13911
d62a17ae 13912 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13913 if (!peer)
13914 return CMD_WARNING;
13915
13916 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13917}
13918
d6902373
PG
13919DEFUN (show_ip_bgp_vpn_all_route_prefix,
13920 show_ip_bgp_vpn_all_route_prefix_cmd,
13921 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13922 SHOW_STR
13923 IP_STR
13924 BGP_STR
d6902373 13925 BGP_VPNVX_HELP_STR
91d37724
QY
13926 "Display information about all VPNv4 NLRIs\n"
13927 "Network in the BGP routing table to display\n"
3a2d747c 13928 "Network in the BGP routing table to display\n"
9973d184 13929 JSON_STR)
91d37724 13930{
d62a17ae 13931 int idx = 0;
13932 char *network = NULL;
13933 struct bgp *bgp = bgp_get_default();
13934 if (!bgp) {
13935 vty_out(vty, "Can't find default instance\n");
13936 return CMD_WARNING;
13937 }
87e34b58 13938
d62a17ae 13939 if (argv_find(argv, argc, "A.B.C.D", &idx))
13940 network = argv[idx]->arg;
13941 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13942 network = argv[idx]->arg;
13943 else {
13944 vty_out(vty, "Unable to figure out Network\n");
13945 return CMD_WARNING;
13946 }
87e34b58 13947
d62a17ae 13948 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13949 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13950 use_json(argc, argv));
91d37724 13951}
d6902373 13952#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13953
44c69747
LK
13954DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13955 show_bgp_l2vpn_evpn_route_prefix_cmd,
13956 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13957 SHOW_STR
4c63a661
PG
13958 BGP_STR
13959 L2VPN_HELP_STR
13960 EVPN_HELP_STR
44c69747
LK
13961 "Network in the BGP routing table to display\n"
13962 "Network in the BGP routing table to display\n"
4c63a661
PG
13963 "Network in the BGP routing table to display\n"
13964 "Network in the BGP routing table to display\n"
13965 JSON_STR)
13966{
d62a17ae 13967 int idx = 0;
13968 char *network = NULL;
44c69747 13969 int prefix_check = 0;
a636c635 13970
44c69747
LK
13971 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13972 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13973 network = argv[idx]->arg;
44c69747 13974 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13975 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13976 network = argv[idx]->arg;
44c69747
LK
13977 prefix_check = 1;
13978 } else {
d62a17ae 13979 vty_out(vty, "Unable to figure out Network\n");
13980 return CMD_WARNING;
13981 }
44c69747
LK
13982 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13983 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13984 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13985}
13986
114fc229 13987static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13988 struct bgp_table *table, int *header1,
13989 int *header2, json_object *json,
13990 json_object *json_scode,
e960b4ca
TA
13991 json_object *json_ocode, bool wide,
13992 bool detail)
2f9bc755
DS
13993{
13994 uint64_t version = table ? table->version : 0;
13995
13996 if (*header1) {
13997 if (json) {
13998 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13999 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 14000 "%pI4", &peer->bgp->router_id);
2f9bc755 14001 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
14002 peer->bgp->default_local_pref);
14003 json_object_int_add(json, "localAS",
14004 peer->change_local_as
14005 ? peer->change_local_as
14006 : peer->local_as);
2f9bc755
DS
14007 json_object_object_add(json, "bgpStatusCodes",
14008 json_scode);
14009 json_object_object_add(json, "bgpOriginCodes",
14010 json_ocode);
14011 } else {
14012 vty_out(vty,
23d0a753
DA
14013 "BGP table version is %" PRIu64
14014 ", local router ID is %pI4, vrf id ",
114fc229
DA
14015 version, &peer->bgp->router_id);
14016 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14017 vty_out(vty, "%s", VRFID_NONE_STR);
14018 else
114fc229 14019 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14020 vty_out(vty, "\n");
14021 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14022 peer->bgp->default_local_pref);
14023 vty_out(vty, "local AS %u\n",
14024 peer->change_local_as ? peer->change_local_as
14025 : peer->local_as);
e960b4ca
TA
14026 if (!detail) {
14027 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14028 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14029 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14030 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14031 }
2f9bc755
DS
14032 }
14033 *header1 = 0;
14034 }
14035 if (*header2) {
e960b4ca 14036 if (!json && !detail)
2f9bc755
DS
14037 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14038 : BGP_SHOW_HEADER));
14039 *header2 = 0;
14040 }
14041}
14042
d9478df0
TA
14043static void
14044show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14045 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14046 const char *rmap_name, json_object *json, json_object *json_ar,
14047 json_object *json_scode, json_object *json_ocode,
96c81f66 14048 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14049 const struct prefix *match, unsigned long *output_count,
14050 unsigned long *filtered_count)
d62a17ae 14051{
3880b4ec
TA
14052 struct bgp_adj_in *ain = NULL;
14053 struct bgp_adj_out *adj = NULL;
9bcb3eef 14054 struct bgp_dest *dest;
d62a17ae 14055 struct bgp *bgp;
d62a17ae 14056 struct attr attr;
14057 int ret;
14058 struct update_subgroup *subgrp;
3880b4ec 14059 struct peer_af *paf = NULL;
f99def61 14060 bool route_filtered;
e960b4ca 14061 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14062 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14063 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14064 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14065 || (safi == SAFI_EVPN))
14066 ? true
14067 : false;
e960b4ca
TA
14068 int display = 0;
14069 json_object *json_net = NULL;
a636c635 14070
d62a17ae 14071 bgp = peer->bgp;
a636c635 14072
3880b4ec
TA
14073 /* If the user supplied a prefix, look for a matching route instead
14074 * of walking the whole table.
14075 */
14076 if (match) {
14077 dest = bgp_node_match(table, match);
14078 if (!dest) {
14079 if (!use_json)
14080 vty_out(vty, "Network not in table\n");
14081 return;
14082 }
14083
14084 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14085
14086 if (rn_p->prefixlen != match->prefixlen) {
14087 if (!use_json)
14088 vty_out(vty, "Network not in table\n");
14089 bgp_dest_unlock_node(dest);
14090 return;
14091 }
14092
14093 if (type == bgp_show_adj_route_received ||
14094 type == bgp_show_adj_route_filtered) {
14095 for (ain = dest->adj_in; ain; ain = ain->next) {
14096 if (ain->peer == peer) {
14097 attr = *ain->attr;
14098 break;
14099 }
14100 }
14101 /* bail out if if adj_out is empty, or
14102 * if the prefix isn't in this peer's
14103 * adj_in
14104 */
14105 if (!ain || ain->peer != peer) {
14106 if (!use_json)
14107 vty_out(vty, "Network not in table\n");
14108 bgp_dest_unlock_node(dest);
14109 return;
14110 }
14111 } else if (type == bgp_show_adj_route_advertised) {
14112 bool peer_found = false;
14113
14114 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14115 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14116 if (paf->peer == peer && adj->attr) {
14117 attr = *adj->attr;
14118 peer_found = true;
14119 break;
14120 }
14121 }
14122 if (peer_found)
14123 break;
14124 }
14125 /* bail out if if adj_out is empty, or
14126 * if the prefix isn't in this peer's
14127 * adj_out
14128 */
14129 if (!paf || !peer_found) {
14130 if (!use_json)
14131 vty_out(vty, "Network not in table\n");
14132 bgp_dest_unlock_node(dest);
14133 return;
14134 }
14135 }
14136
14137 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14138 rmap_name);
14139
14140 if (ret != RMAP_DENY) {
14141 show_adj_route_header(vty, peer, table, header1,
14142 header2, json, json_scode,
14143 json_ocode, wide, detail);
14144
14145 if (use_json)
14146 json_net = json_object_new_object();
14147
14148 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14149 afi, safi, json_net,
14150 BGP_PATH_SHOW_ALL, &display,
14151 RPKI_NOT_BEING_USED);
14152 if (use_json)
14153 json_object_object_addf(json_ar, json_net,
14154 "%pFX", rn_p);
14155 (*output_count)++;
14156 } else
14157 (*filtered_count)++;
14158
14159 bgp_attr_flush(&attr);
14160 bgp_dest_unlock_node(dest);
14161 return;
14162 }
14163
14164
d62a17ae 14165 subgrp = peer_subgroup(peer, afi, safi);
14166
6392aaa6 14167 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14168 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14169 if (use_json) {
14170 json_object_int_add(json, "bgpTableVersion",
14171 table->version);
c949c771
DA
14172 json_object_string_addf(json, "bgpLocalRouterId",
14173 "%pI4", &bgp->router_id);
01eced22
AD
14174 json_object_int_add(json, "defaultLocPrf",
14175 bgp->default_local_pref);
114fc229
DA
14176 json_object_int_add(json, "localAS",
14177 peer->change_local_as
14178 ? peer->change_local_as
14179 : peer->local_as);
d62a17ae 14180 json_object_object_add(json, "bgpStatusCodes",
14181 json_scode);
14182 json_object_object_add(json, "bgpOriginCodes",
14183 json_ocode);
07d0c4ed
DA
14184 json_object_string_add(
14185 json, "bgpOriginatingDefaultNetwork",
14186 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14187 } else {
23d0a753
DA
14188 vty_out(vty,
14189 "BGP table version is %" PRIu64
14190 ", local router ID is %pI4, vrf id ",
14191 table->version, &bgp->router_id);
9df8b37c
PZ
14192 if (bgp->vrf_id == VRF_UNKNOWN)
14193 vty_out(vty, "%s", VRFID_NONE_STR);
14194 else
14195 vty_out(vty, "%u", bgp->vrf_id);
14196 vty_out(vty, "\n");
01eced22
AD
14197 vty_out(vty, "Default local pref %u, ",
14198 bgp->default_local_pref);
114fc229
DA
14199 vty_out(vty, "local AS %u\n",
14200 peer->change_local_as ? peer->change_local_as
14201 : peer->local_as);
e960b4ca
TA
14202 if (!detail) {
14203 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14204 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14205 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14206 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14207 }
d62a17ae 14208
07d0c4ed
DA
14209 vty_out(vty, "Originating default network %s\n\n",
14210 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14211 }
65565c9a 14212 (*output_count)++;
d9478df0 14213 *header1 = 0;
d62a17ae 14214 }
a636c635 14215
9bcb3eef 14216 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14217 if (type == bgp_show_adj_route_received
14218 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14219 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14220 if (ain->peer != peer)
ea47320b 14221 continue;
6392aaa6 14222
114fc229 14223 show_adj_route_header(vty, peer, table, header1,
d9478df0 14224 header2, json, json_scode,
e960b4ca 14225 json_ocode, wide, detail);
d9478df0
TA
14226
14227 if ((safi == SAFI_MPLS_VPN)
14228 || (safi == SAFI_ENCAP)
14229 || (safi == SAFI_EVPN)) {
14230 if (use_json)
14231 json_object_string_add(
14232 json_ar, "rd", rd_str);
14233 else if (show_rd && rd_str) {
14234 vty_out(vty,
14235 "Route Distinguisher: %s\n",
14236 rd_str);
14237 show_rd = false;
14238 }
14239 }
6392aaa6 14240
6f4f49b2 14241 attr = *ain->attr;
f99def61
AD
14242 route_filtered = false;
14243
14244 /* Filter prefix using distribute list,
14245 * filter list or prefix list
14246 */
b54892e0 14247 const struct prefix *rn_p =
9bcb3eef 14248 bgp_dest_get_prefix(dest);
b54892e0
DS
14249 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14250 safi))
14251 == FILTER_DENY)
f99def61
AD
14252 route_filtered = true;
14253
14254 /* Filter prefix using route-map */
b54892e0
DS
14255 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14256 safi, rmap_name, NULL,
14257 0, NULL);
6392aaa6 14258
13c8e163
AD
14259 if (type == bgp_show_adj_route_filtered &&
14260 !route_filtered && ret != RMAP_DENY) {
d498917e 14261 bgp_attr_flush(&attr);
6392aaa6 14262 continue;
d62a17ae 14263 }
6392aaa6 14264
d9478df0
TA
14265 if (type == bgp_show_adj_route_received
14266 && (route_filtered || ret == RMAP_DENY))
14267 (*filtered_count)++;
6392aaa6 14268
e960b4ca
TA
14269 if (detail) {
14270 if (use_json)
14271 json_net =
14272 json_object_new_object();
14273 bgp_show_path_info(
14274 NULL /* prefix_rd */, dest, vty,
14275 bgp, afi, safi, json_net,
14276 BGP_PATH_SHOW_ALL, &display,
14277 RPKI_NOT_BEING_USED);
14278 if (use_json)
14279 json_object_object_addf(
14280 json_ar, json_net,
14281 "%pFX", rn_p);
14282 } else
14283 route_vty_out_tmp(vty, dest, rn_p,
14284 &attr, safi, use_json,
14285 json_ar, wide);
d498917e 14286 bgp_attr_flush(&attr);
d9478df0 14287 (*output_count)++;
d62a17ae 14288 }
6392aaa6 14289 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14290 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14291 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14292 if (paf->peer != peer || !adj->attr)
924c3f6a 14293 continue;
d62a17ae 14294
e960b4ca
TA
14295 show_adj_route_header(
14296 vty, peer, table, header1,
14297 header2, json, json_scode,
14298 json_ocode, wide, detail);
d62a17ae 14299
b54892e0 14300 const struct prefix *rn_p =
9bcb3eef 14301 bgp_dest_get_prefix(dest);
b54892e0 14302
6f4f49b2 14303 attr = *adj->attr;
b755861b 14304 ret = bgp_output_modifier(
b54892e0 14305 peer, rn_p, &attr, afi, safi,
b755861b 14306 rmap_name);
f46d8e1e 14307
b755861b 14308 if (ret != RMAP_DENY) {
d9478df0
TA
14309 if ((safi == SAFI_MPLS_VPN)
14310 || (safi == SAFI_ENCAP)
14311 || (safi == SAFI_EVPN)) {
14312 if (use_json)
14313 json_object_string_add(
14314 json_ar,
14315 "rd",
14316 rd_str);
14317 else if (show_rd
14318 && rd_str) {
14319 vty_out(vty,
14320 "Route Distinguisher: %s\n",
14321 rd_str);
14322 show_rd = false;
14323 }
14324 }
e960b4ca
TA
14325 if (detail) {
14326 if (use_json)
14327 json_net =
14328 json_object_new_object();
14329 bgp_show_path_info(
14330 NULL /* prefix_rd
14331 */
14332 ,
14333 dest, vty, bgp,
14334 afi, safi,
14335 json_net,
14336 BGP_PATH_SHOW_ALL,
14337 &display,
14338 RPKI_NOT_BEING_USED);
14339 if (use_json)
14340 json_object_object_addf(
14341 json_ar,
14342 json_net,
14343 "%pFX",
14344 rn_p);
14345 } else
14346 route_vty_out_tmp(
14347 vty, dest, rn_p,
14348 &attr, safi,
14349 use_json,
14350 json_ar, wide);
d9478df0 14351 (*output_count)++;
b755861b 14352 } else {
d9478df0 14353 (*filtered_count)++;
a2addae8 14354 }
b755861b 14355
d498917e 14356 bgp_attr_flush(&attr);
924c3f6a 14357 }
f20ce998
DS
14358 } else if (type == bgp_show_adj_route_bestpath) {
14359 struct bgp_path_info *pi;
14360
114fc229
DA
14361 show_adj_route_header(vty, peer, table, header1,
14362 header2, json, json_scode,
e960b4ca 14363 json_ocode, wide, detail);
f20ce998 14364
aa9bf57e
TA
14365 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14366
f20ce998
DS
14367 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14368 pi = pi->next) {
14369 if (pi->peer != peer)
14370 continue;
14371
14372 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14373 continue;
14374
aa9bf57e
TA
14375 if (detail) {
14376 if (use_json)
14377 json_net =
14378 json_object_new_object();
14379 bgp_show_path_info(
14380 NULL /* prefix_rd */, dest, vty,
14381 bgp, afi, safi, json_net,
14382 BGP_PATH_SHOW_BESTPATH,
14383 &display, RPKI_NOT_BEING_USED);
14384 if (use_json)
14385 json_object_object_addf(
14386 json_ar, json_net,
14387 "%pFX", rn_p);
14388 } else
14389 route_vty_out_tmp(
14390 vty, dest, rn_p, pi->attr, safi,
14391 use_json, json_ar, wide);
d9478df0 14392 (*output_count)++;
f20ce998 14393 }
d62a17ae 14394 }
14395 }
a636c635 14396}
2a71e9ce 14397
d62a17ae 14398static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14399 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14400 const char *rmap_name, const struct prefix *match,
14401 uint16_t show_flags)
0b16f239 14402{
d9478df0
TA
14403 struct bgp *bgp;
14404 struct bgp_table *table;
d62a17ae 14405 json_object *json = NULL;
d9478df0
TA
14406 json_object *json_scode = NULL;
14407 json_object *json_ocode = NULL;
14408 json_object *json_ar = NULL;
96f3485c 14409 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14410
d9478df0
TA
14411 /* Init BGP headers here so they're only displayed once
14412 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14413 */
14414 int header1 = 1;
14415 int header2 = 1;
14416
14417 /*
14418 * Initialize variables for each RD
14419 * All prefixes under an RD is aggregated within "json_routes"
14420 */
14421 char rd_str[BUFSIZ] = {0};
14422 json_object *json_routes = NULL;
14423
14424
14425 /* For 2-tier tables, prefix counts need to be
14426 * maintained across multiple runs of show_adj_route()
14427 */
14428 unsigned long output_count_per_rd;
14429 unsigned long filtered_count_per_rd;
14430 unsigned long output_count = 0;
14431 unsigned long filtered_count = 0;
14432
14433 if (use_json) {
d62a17ae 14434 json = json_object_new_object();
d9478df0
TA
14435 json_ar = json_object_new_object();
14436 json_scode = json_object_new_object();
14437 json_ocode = json_object_new_object();
dd426a51
DA
14438#if CONFDATE > 20231208
14439CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14440#endif
d9478df0
TA
14441 json_object_string_add(json_scode, "suppressed", "s");
14442 json_object_string_add(json_scode, "damped", "d");
14443 json_object_string_add(json_scode, "history", "h");
14444 json_object_string_add(json_scode, "valid", "*");
14445 json_object_string_add(json_scode, "best", ">");
14446 json_object_string_add(json_scode, "multipath", "=");
14447 json_object_string_add(json_scode, "internal", "i");
14448 json_object_string_add(json_scode, "ribFailure", "r");
14449 json_object_string_add(json_scode, "stale", "S");
14450 json_object_string_add(json_scode, "removed", "R");
14451
dd426a51
DA
14452#if CONFDATE > 20231208
14453CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14454#endif
d9478df0
TA
14455 json_object_string_add(json_ocode, "igp", "i");
14456 json_object_string_add(json_ocode, "egp", "e");
14457 json_object_string_add(json_ocode, "incomplete", "?");
14458 }
0b16f239 14459
d62a17ae 14460 if (!peer || !peer->afc[afi][safi]) {
14461 if (use_json) {
14462 json_object_string_add(
14463 json, "warning",
14464 "No such neighbor or address family");
14465 vty_out(vty, "%s\n", json_object_to_json_string(json));
14466 json_object_free(json);
690c3134
MW
14467 json_object_free(json_ar);
14468 json_object_free(json_scode);
14469 json_object_free(json_ocode);
d62a17ae 14470 } else
14471 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14472
d62a17ae 14473 return CMD_WARNING;
14474 }
14475
6392aaa6
PM
14476 if ((type == bgp_show_adj_route_received
14477 || type == bgp_show_adj_route_filtered)
d62a17ae 14478 && !CHECK_FLAG(peer->af_flags[afi][safi],
14479 PEER_FLAG_SOFT_RECONFIG)) {
14480 if (use_json) {
14481 json_object_string_add(
14482 json, "warning",
14483 "Inbound soft reconfiguration not enabled");
14484 vty_out(vty, "%s\n", json_object_to_json_string(json));
14485 json_object_free(json);
690c3134
MW
14486 json_object_free(json_ar);
14487 json_object_free(json_scode);
14488 json_object_free(json_ocode);
d62a17ae 14489 } else
14490 vty_out(vty,
14491 "%% Inbound soft reconfiguration not enabled\n");
14492
14493 return CMD_WARNING;
14494 }
0b16f239 14495
d9478df0
TA
14496 bgp = peer->bgp;
14497
14498 /* labeled-unicast routes live in the unicast table */
14499 if (safi == SAFI_LABELED_UNICAST)
14500 table = bgp->rib[afi][SAFI_UNICAST];
14501 else
14502 table = bgp->rib[afi][safi];
14503
14504 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14505 || (safi == SAFI_EVPN)) {
14506
14507 struct bgp_dest *dest;
14508
14509 for (dest = bgp_table_top(table); dest;
14510 dest = bgp_route_next(dest)) {
14511 table = bgp_dest_get_bgp_table_info(dest);
14512 if (!table)
14513 continue;
14514
14515 output_count_per_rd = 0;
14516 filtered_count_per_rd = 0;
14517
14518 if (use_json)
14519 json_routes = json_object_new_object();
14520
14521 const struct prefix_rd *prd;
14522 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14523 dest);
14524
4a8cd6ad
PG
14525 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14526 bgp->asnotation);
d9478df0 14527
3880b4ec
TA
14528 show_adj_route(
14529 vty, peer, table, afi, safi, type, rmap_name,
14530 json, json_routes, json_scode, json_ocode,
14531 show_flags, &header1, &header2, rd_str, match,
14532 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14533
14534 /* Don't include an empty RD in the output! */
14535 if (json_routes && (output_count_per_rd > 0))
14536 json_object_object_add(json_ar, rd_str,
14537 json_routes);
14538
14539 output_count += output_count_per_rd;
14540 filtered_count += filtered_count_per_rd;
14541 }
14542 } else
14543 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14544 json, json_ar, json_scode, json_ocode,
3880b4ec 14545 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14546 &output_count, &filtered_count);
14547
14548 if (use_json) {
c1984955
TA
14549 if (type == bgp_show_adj_route_advertised)
14550 json_object_object_add(json, "advertisedRoutes",
14551 json_ar);
14552 else
14553 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14554 json_object_int_add(json, "totalPrefixCounter", output_count);
14555 json_object_int_add(json, "filteredPrefixCounter",
14556 filtered_count);
14557
690c3134
MW
14558 /*
14559 * These fields only give up ownership to `json` when `header1`
14560 * is used (set to zero). See code in `show_adj_route` and
14561 * `show_adj_route_header`.
14562 */
14563 if (header1 == 1) {
d9478df0
TA
14564 json_object_free(json_scode);
14565 json_object_free(json_ocode);
14566 }
14567
75eeda93 14568 vty_json(vty, json);
d9478df0 14569 } else if (output_count > 0) {
3880b4ec 14570 if (!match && filtered_count > 0)
d9478df0
TA
14571 vty_out(vty,
14572 "\nTotal number of prefixes %ld (%ld filtered)\n",
14573 output_count, filtered_count);
14574 else
14575 vty_out(vty, "\nTotal number of prefixes %ld\n",
14576 output_count);
14577 }
0b16f239 14578
d62a17ae 14579 return CMD_SUCCESS;
a636c635 14580}
50ef26d4 14581
f20ce998
DS
14582DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14583 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14584 "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
14585 SHOW_STR
14586 IP_STR
14587 BGP_STR
14588 BGP_INSTANCE_HELP_STR
14589 BGP_AFI_HELP_STR
14590 BGP_SAFI_WITH_LABEL_HELP_STR
14591 "Detailed information on TCP and BGP neighbor connections\n"
14592 "Neighbor to display information about\n"
14593 "Neighbor to display information about\n"
14594 "Neighbor on BGP configured interface\n"
14595 "Display the routes selected by best path\n"
aa9bf57e 14596 "Display detailed version of routes\n"
f20ce998
DS
14597 JSON_STR
14598 "Increase table width for longer prefixes\n")
14599{
14600 afi_t afi = AFI_IP6;
14601 safi_t safi = SAFI_UNICAST;
14602 char *rmap_name = NULL;
14603 char *peerstr = NULL;
14604 struct bgp *bgp = NULL;
14605 struct peer *peer;
14606 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14607 int idx = 0;
96c81f66 14608 uint16_t show_flags = 0;
96f3485c 14609
aa9bf57e
TA
14610 if (detail)
14611 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14612
96f3485c
MK
14613 if (uj)
14614 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14615
14616 if (wide)
14617 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14618
14619 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14620 &bgp, uj);
14621
14622 if (!idx)
14623 return CMD_WARNING;
14624
14625 argv_find(argv, argc, "neighbors", &idx);
14626 peerstr = argv[++idx]->arg;
14627
14628 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14629 if (!peer)
14630 return CMD_WARNING;
14631
3880b4ec 14632 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14633 show_flags);
f20ce998
DS
14634}
14635
e960b4ca
TA
14636DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14637 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14638 "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
14639 SHOW_STR
14640 IP_STR
14641 BGP_STR
14642 BGP_INSTANCE_HELP_STR
14643 BGP_AFI_HELP_STR
14644 BGP_SAFI_WITH_LABEL_HELP_STR
14645 "Display the entries for all address families\n"
14646 "Detailed information on TCP and BGP neighbor connections\n"
14647 "Neighbor to display information about\n"
14648 "Neighbor to display information about\n"
14649 "Neighbor on BGP configured interface\n"
14650 "Display the routes advertised to a BGP neighbor\n"
14651 "Display the received routes from neighbor\n"
14652 "Display the filtered routes received from neighbor\n"
14653 "Route-map to modify the attributes\n"
14654 "Name of the route map\n"
3880b4ec
TA
14655 "IPv4 prefix\n"
14656 "IPv6 prefix\n"
e960b4ca
TA
14657 "Display detailed version of routes\n"
14658 JSON_STR
14659 "Increase table width for longer prefixes\n")
718e3744 14660{
d62a17ae 14661 afi_t afi = AFI_IP6;
14662 safi_t safi = SAFI_UNICAST;
d62a17ae 14663 char *peerstr = NULL;
d62a17ae 14664 struct bgp *bgp = NULL;
14665 struct peer *peer;
6392aaa6 14666 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14667 int idx = 0;
96f3485c 14668 bool first = true;
96c81f66 14669 uint16_t show_flags = 0;
75ce3b14
DA
14670 struct listnode *node;
14671 struct bgp *abgp;
6392aaa6 14672
3880b4ec 14673 if (detail || prefix_str)
e960b4ca
TA
14674 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14675
96f3485c 14676 if (uj) {
d62a17ae 14677 argc--;
96f3485c
MK
14678 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14679 }
14680
14681 if (all) {
14682 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14683 if (argv_find(argv, argc, "ipv4", &idx))
14684 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14685
14686 if (argv_find(argv, argc, "ipv6", &idx))
14687 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14688 }
14689
14690 if (wide)
14691 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14692
9f049418
DS
14693 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14694 &bgp, uj);
14695 if (!idx)
14696 return CMD_WARNING;
14697
d62a17ae 14698 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14699 argv_find(argv, argc, "neighbors", &idx);
14700 peerstr = argv[++idx]->arg;
8c3deaae 14701
d62a17ae 14702 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14703 if (!peer)
14704 return CMD_WARNING;
856ca177 14705
d62a17ae 14706 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14707 type = bgp_show_adj_route_advertised;
14708 else if (argv_find(argv, argc, "received-routes", &idx))
14709 type = bgp_show_adj_route_received;
14710 else if (argv_find(argv, argc, "filtered-routes", &idx))
14711 type = bgp_show_adj_route_filtered;
14712
96f3485c 14713 if (!all)
70dd370f 14714 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14715 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14716 if (uj)
14717 vty_out(vty, "{\n");
14718
14719 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14720 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14721 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14722 : AFI_IP6;
75ce3b14
DA
14723 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14724 FOREACH_SAFI (safi) {
14725 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14726 continue;
96f3485c 14727
75ce3b14
DA
14728 if (uj) {
14729 if (first)
14730 first = false;
14731 else
14732 vty_out(vty, ",\n");
14733 vty_out(vty, "\"%s\":",
14734 get_afi_safi_str(afi, safi,
14735 true));
14736 } else
14737 vty_out(vty,
14738 "\nFor address family: %s\n",
14739 get_afi_safi_str(afi, safi,
14740 false));
96f3485c 14741
75ce3b14 14742 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14743 route_map, prefix, show_flags);
75ce3b14 14744 }
96f3485c
MK
14745 }
14746 } else {
75ce3b14
DA
14747 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14748 FOREACH_AFI_SAFI (afi, safi) {
14749 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14750 continue;
96f3485c 14751
75ce3b14
DA
14752 if (uj) {
14753 if (first)
14754 first = false;
14755 else
14756 vty_out(vty, ",\n");
14757 vty_out(vty, "\"%s\":",
14758 get_afi_safi_str(afi, safi,
14759 true));
14760 } else
14761 vty_out(vty,
14762 "\nFor address family: %s\n",
14763 get_afi_safi_str(afi, safi,
14764 false));
96f3485c 14765
75ce3b14 14766 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14767 route_map, prefix, show_flags);
75ce3b14 14768 }
96f3485c
MK
14769 }
14770 }
14771 if (uj)
14772 vty_out(vty, "}\n");
14773
14774 return CMD_SUCCESS;
95cbbd2a
ML
14775}
14776
718e3744 14777DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14778 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14779 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14780 SHOW_STR
14781 IP_STR
14782 BGP_STR
d3120452 14783 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14784 BGP_AF_STR
14785 BGP_AF_STR
14786 BGP_AF_MODIFIER_STR
718e3744 14787 "Detailed information on TCP and BGP neighbor connections\n"
14788 "Neighbor to display information about\n"
14789 "Neighbor to display information about\n"
91d37724 14790 "Neighbor on BGP configured interface\n"
718e3744 14791 "Display information received from a BGP neighbor\n"
856ca177 14792 "Display the prefixlist filter\n"
9973d184 14793 JSON_STR)
718e3744 14794{
d62a17ae 14795 afi_t afi = AFI_IP6;
14796 safi_t safi = SAFI_UNICAST;
14797 char *peerstr = NULL;
d62a17ae 14798 char name[BUFSIZ];
d62a17ae 14799 struct peer *peer;
d3120452 14800 int count;
d62a17ae 14801 int idx = 0;
d3120452
IR
14802 struct bgp *bgp = NULL;
14803 bool uj = use_json(argc, argv);
14804
14805 if (uj)
14806 argc--;
14807
14808 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14809 &bgp, uj);
14810 if (!idx)
14811 return CMD_WARNING;
d62a17ae 14812
d62a17ae 14813 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14814 argv_find(argv, argc, "neighbors", &idx);
14815 peerstr = argv[++idx]->arg;
14816
d3120452
IR
14817 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14818 if (!peer)
14819 return CMD_WARNING;
718e3744 14820
4ced1a2c 14821 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14822 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14823 if (count) {
14824 if (!uj)
14825 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14826 get_afi_safi_str(afi, safi, false));
d62a17ae 14827 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14828 } else {
14829 if (uj)
14830 vty_out(vty, "{}\n");
14831 else
14832 vty_out(vty, "No functional output\n");
14833 }
718e3744 14834
d62a17ae 14835 return CMD_SUCCESS;
14836}
14837
14838static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14839 afi_t afi, safi_t safi,
9f049418 14840 enum bgp_show_type type, bool use_json)
d62a17ae 14841{
96c81f66 14842 uint16_t show_flags = 0;
96f3485c
MK
14843
14844 if (use_json)
14845 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14846
d62a17ae 14847 if (!peer || !peer->afc[afi][safi]) {
14848 if (use_json) {
14849 json_object *json_no = NULL;
14850 json_no = json_object_new_object();
14851 json_object_string_add(
14852 json_no, "warning",
14853 "No such neighbor or address family");
14854 vty_out(vty, "%s\n",
14855 json_object_to_json_string(json_no));
14856 json_object_free(json_no);
14857 } else
14858 vty_out(vty, "%% No such neighbor or address family\n");
14859 return CMD_WARNING;
14860 }
47fc97cc 14861
7daf25a3
TA
14862 /* labeled-unicast routes live in the unicast table */
14863 if (safi == SAFI_LABELED_UNICAST)
14864 safi = SAFI_UNICAST;
14865
1e2ce4f1
DS
14866 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14867 RPKI_NOT_BEING_USED);
718e3744 14868}
14869
dba3c1d3
PG
14870DEFUN (show_ip_bgp_flowspec_routes_detailed,
14871 show_ip_bgp_flowspec_routes_detailed_cmd,
14872 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14873 SHOW_STR
14874 IP_STR
14875 BGP_STR
14876 BGP_INSTANCE_HELP_STR
14877 BGP_AFI_HELP_STR
14878 "SAFI Flowspec\n"
14879 "Detailed information on flowspec entries\n"
14880 JSON_STR)
14881{
458c1475 14882 afi_t afi = AFI_IP6;
dba3c1d3
PG
14883 safi_t safi = SAFI_UNICAST;
14884 struct bgp *bgp = NULL;
14885 int idx = 0;
9f049418 14886 bool uj = use_json(argc, argv);
81dcd881 14887 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14888
96f3485c 14889 if (uj) {
9f049418 14890 argc--;
96f3485c
MK
14891 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14892 }
dba3c1d3
PG
14893
14894 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14895 &bgp, uj);
dba3c1d3
PG
14896 if (!idx)
14897 return CMD_WARNING;
14898
96f3485c 14899 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14900 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14901}
14902
718e3744 14903DEFUN (show_ip_bgp_neighbor_routes,
14904 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14905 "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 14906 SHOW_STR
14907 IP_STR
14908 BGP_STR
8386ac43 14909 BGP_INSTANCE_HELP_STR
4f280b15 14910 BGP_AFI_HELP_STR
4dd6177e 14911 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14912 "Detailed information on TCP and BGP neighbor connections\n"
14913 "Neighbor to display information about\n"
14914 "Neighbor to display information about\n"
91d37724 14915 "Neighbor on BGP configured interface\n"
2525cf39 14916 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14917 "Display the dampened routes received from neighbor\n"
14918 "Display routes learned from neighbor\n"
9973d184 14919 JSON_STR)
718e3744 14920{
d62a17ae 14921 char *peerstr = NULL;
14922 struct bgp *bgp = NULL;
14923 afi_t afi = AFI_IP6;
14924 safi_t safi = SAFI_UNICAST;
14925 struct peer *peer;
14926 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14927 int idx = 0;
9f049418
DS
14928 bool uj = use_json(argc, argv);
14929
14930 if (uj)
14931 argc--;
bb46e94f 14932
d62a17ae 14933 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14934 &bgp, uj);
d62a17ae 14935 if (!idx)
14936 return CMD_WARNING;
c493f2d8 14937
d62a17ae 14938 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14939 argv_find(argv, argc, "neighbors", &idx);
14940 peerstr = argv[++idx]->arg;
8c3deaae 14941
d62a17ae 14942 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14943 if (!peer)
d62a17ae 14944 return CMD_WARNING;
bb46e94f 14945
d62a17ae 14946 if (argv_find(argv, argc, "flap-statistics", &idx))
14947 sh_type = bgp_show_type_flap_neighbor;
14948 else if (argv_find(argv, argc, "dampened-routes", &idx))
14949 sh_type = bgp_show_type_damp_neighbor;
14950 else if (argv_find(argv, argc, "routes", &idx))
14951 sh_type = bgp_show_type_neighbor;
2525cf39 14952
d62a17ae 14953 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14954}
6b0655a2 14955
734b349e 14956struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14957
d62a17ae 14958struct bgp_distance {
14959 /* Distance value for the IP source prefix. */
d7c0a89a 14960 uint8_t distance;
718e3744 14961
d62a17ae 14962 /* Name of the access-list to be matched. */
14963 char *access_list;
718e3744 14964};
14965
4f280b15
LB
14966DEFUN (show_bgp_afi_vpn_rd_route,
14967 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14968 "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
14969 SHOW_STR
14970 BGP_STR
14971 BGP_AFI_HELP_STR
00e6edb9 14972 BGP_AF_MODIFIER_STR
4f280b15
LB
14973 "Display information for a route distinguisher\n"
14974 "Route Distinguisher\n"
a111dd97 14975 "All Route Distinguishers\n"
7395a2c9
DS
14976 "Network in the BGP routing table to display\n"
14977 "Network in the BGP routing table to display\n"
14978 JSON_STR)
4f280b15 14979{
d62a17ae 14980 int ret;
14981 struct prefix_rd prd;
14982 afi_t afi = AFI_MAX;
14983 int idx = 0;
4f280b15 14984
ff6566f3
DS
14985 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14986 vty_out(vty, "%% Malformed Address Family\n");
14987 return CMD_WARNING;
14988 }
14989
a111dd97
TA
14990 if (!strcmp(argv[5]->arg, "all"))
14991 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14992 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14993 RPKI_NOT_BEING_USED,
14994 use_json(argc, argv));
14995
d62a17ae 14996 ret = str2prefix_rd(argv[5]->arg, &prd);
14997 if (!ret) {
14998 vty_out(vty, "%% Malformed Route Distinguisher\n");
14999 return CMD_WARNING;
15000 }
ff6566f3 15001
d62a17ae 15002 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
15003 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15004 use_json(argc, argv));
4f280b15
LB
15005}
15006
d62a17ae 15007static struct bgp_distance *bgp_distance_new(void)
718e3744 15008{
d62a17ae 15009 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 15010}
15011
d62a17ae 15012static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15013{
d62a17ae 15014 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15015}
15016
585f1adc
IR
15017static int bgp_distance_set(struct vty *vty, const char *distance_str,
15018 const char *ip_str, const char *access_list_str)
718e3744 15019{
d62a17ae 15020 int ret;
585f1adc
IR
15021 afi_t afi;
15022 safi_t safi;
d62a17ae 15023 struct prefix p;
585f1adc 15024 uint8_t distance;
9bcb3eef 15025 struct bgp_dest *dest;
d62a17ae 15026 struct bgp_distance *bdistance;
718e3744 15027
585f1adc
IR
15028 afi = bgp_node_afi(vty);
15029 safi = bgp_node_safi(vty);
15030
d62a17ae 15031 ret = str2prefix(ip_str, &p);
15032 if (ret == 0) {
585f1adc 15033 vty_out(vty, "Malformed prefix\n");
d62a17ae 15034 return CMD_WARNING_CONFIG_FAILED;
15035 }
718e3744 15036
585f1adc
IR
15037 distance = atoi(distance_str);
15038
d62a17ae 15039 /* Get BGP distance node. */
9bcb3eef
DS
15040 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15041 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15042 if (bdistance)
9bcb3eef 15043 bgp_dest_unlock_node(dest);
ca2e160d 15044 else {
d62a17ae 15045 bdistance = bgp_distance_new();
9bcb3eef 15046 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15047 }
718e3744 15048
d62a17ae 15049 /* Set distance value. */
15050 bdistance->distance = distance;
718e3744 15051
d62a17ae 15052 /* Reset access-list configuration. */
e1b36e13 15053 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15054 if (access_list_str)
15055 bdistance->access_list =
15056 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15057
d62a17ae 15058 return CMD_SUCCESS;
718e3744 15059}
15060
585f1adc
IR
15061static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15062 const char *ip_str, const char *access_list_str)
718e3744 15063{
d62a17ae 15064 int ret;
585f1adc
IR
15065 afi_t afi;
15066 safi_t safi;
d62a17ae 15067 struct prefix p;
585f1adc 15068 int distance;
9bcb3eef 15069 struct bgp_dest *dest;
d62a17ae 15070 struct bgp_distance *bdistance;
718e3744 15071
585f1adc
IR
15072 afi = bgp_node_afi(vty);
15073 safi = bgp_node_safi(vty);
15074
d62a17ae 15075 ret = str2prefix(ip_str, &p);
15076 if (ret == 0) {
585f1adc 15077 vty_out(vty, "Malformed prefix\n");
d62a17ae 15078 return CMD_WARNING_CONFIG_FAILED;
15079 }
718e3744 15080
9bcb3eef
DS
15081 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15082 if (!dest) {
585f1adc 15083 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15084 return CMD_WARNING_CONFIG_FAILED;
15085 }
718e3744 15086
9bcb3eef 15087 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15088 distance = atoi(distance_str);
1f9a9fff 15089
d62a17ae 15090 if (bdistance->distance != distance) {
585f1adc 15091 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15092 bgp_dest_unlock_node(dest);
d62a17ae 15093 return CMD_WARNING_CONFIG_FAILED;
15094 }
718e3744 15095
0a22ddfb 15096 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15097 bgp_distance_free(bdistance);
718e3744 15098
9bcb3eef
DS
15099 bgp_dest_set_bgp_path_info(dest, NULL);
15100 bgp_dest_unlock_node(dest);
15101 bgp_dest_unlock_node(dest);
718e3744 15102
d62a17ae 15103 return CMD_SUCCESS;
718e3744 15104}
15105
718e3744 15106/* Apply BGP information to distance method. */
b8685f9b 15107uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15108 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15109{
9bcb3eef 15110 struct bgp_dest *dest;
801bb996 15111 struct prefix q = {0};
d62a17ae 15112 struct peer *peer;
15113 struct bgp_distance *bdistance;
15114 struct access_list *alist;
15115 struct bgp_static *bgp_static;
a04f1c42 15116 struct bgp_path_info *bpi_ultimate;
d62a17ae 15117
15118 if (!bgp)
15119 return 0;
15120
40381db7 15121 peer = pinfo->peer;
d62a17ae 15122
7b7d48e5
DS
15123 if (pinfo->attr->distance)
15124 return pinfo->attr->distance;
15125
a04f1c42
PG
15126 /* get peer origin to calculate appropriate distance */
15127 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15128 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15129 peer = bpi_ultimate->peer;
15130 }
15131
801bb996
CS
15132 /* Check source address.
15133 * Note: for aggregate route, peer can have unspec af type.
15134 */
15135 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15136 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15137 return 0;
15138
9bcb3eef
DS
15139 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15140 if (dest) {
15141 bdistance = bgp_dest_get_bgp_distance_info(dest);
15142 bgp_dest_unlock_node(dest);
d62a17ae 15143
15144 if (bdistance->access_list) {
15145 alist = access_list_lookup(afi, bdistance->access_list);
15146 if (alist
15147 && access_list_apply(alist, p) == FILTER_PERMIT)
15148 return bdistance->distance;
15149 } else
15150 return bdistance->distance;
718e3744 15151 }
718e3744 15152
d62a17ae 15153 /* Backdoor check. */
9bcb3eef
DS
15154 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15155 if (dest) {
15156 bgp_static = bgp_dest_get_bgp_static_info(dest);
15157 bgp_dest_unlock_node(dest);
718e3744 15158
d62a17ae 15159 if (bgp_static->backdoor) {
15160 if (bgp->distance_local[afi][safi])
15161 return bgp->distance_local[afi][safi];
15162 else
15163 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15164 }
718e3744 15165 }
718e3744 15166
d62a17ae 15167 if (peer->sort == BGP_PEER_EBGP) {
15168 if (bgp->distance_ebgp[afi][safi])
15169 return bgp->distance_ebgp[afi][safi];
15170 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15171 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15172 if (bgp->distance_ibgp[afi][safi])
15173 return bgp->distance_ibgp[afi][safi];
15174 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15175 } else {
15176 if (bgp->distance_local[afi][safi])
15177 return bgp->distance_local[afi][safi];
15178 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15179 }
718e3744 15180}
15181
a612fb77
DA
15182/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15183 * we should tell ZEBRA update the routes for a specific
15184 * AFI/SAFI to reflect changes in RIB.
15185 */
585f1adc
IR
15186static void bgp_announce_routes_distance_update(struct bgp *bgp,
15187 afi_t update_afi,
15188 safi_t update_safi)
a612fb77
DA
15189{
15190 afi_t afi;
15191 safi_t safi;
15192
15193 FOREACH_AFI_SAFI (afi, safi) {
15194 if (!bgp_fibupd_safi(safi))
15195 continue;
15196
8b54bc30
DA
15197 if (afi != update_afi && safi != update_safi)
15198 continue;
15199
15200 if (BGP_DEBUG(zebra, ZEBRA))
15201 zlog_debug(
15202 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15203 __func__, afi, safi);
15204 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15205 }
15206}
15207
585f1adc
IR
15208DEFUN (bgp_distance,
15209 bgp_distance_cmd,
15210 "distance bgp (1-255) (1-255) (1-255)",
15211 "Define an administrative distance\n"
15212 "BGP distance\n"
15213 "Distance for routes external to the AS\n"
15214 "Distance for routes internal to the AS\n"
15215 "Distance for local routes\n")
718e3744 15216{
585f1adc 15217 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15218 int idx_number = 2;
15219 int idx_number_2 = 3;
15220 int idx_number_3 = 4;
585f1adc
IR
15221 int distance_ebgp = atoi(argv[idx_number]->arg);
15222 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15223 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15224 afi_t afi;
15225 safi_t safi;
718e3744 15226
d62a17ae 15227 afi = bgp_node_afi(vty);
15228 safi = bgp_node_safi(vty);
718e3744 15229
585f1adc
IR
15230 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15231 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15232 || bgp->distance_local[afi][safi] != distance_local) {
15233 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15234 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15235 bgp->distance_local[afi][safi] = distance_local;
15236 bgp_announce_routes_distance_update(bgp, afi, safi);
15237 }
15238 return CMD_SUCCESS;
15239}
37a87b8f 15240
585f1adc
IR
15241DEFUN (no_bgp_distance,
15242 no_bgp_distance_cmd,
15243 "no distance bgp [(1-255) (1-255) (1-255)]",
15244 NO_STR
15245 "Define an administrative distance\n"
15246 "BGP distance\n"
15247 "Distance for routes external to the AS\n"
15248 "Distance for routes internal to the AS\n"
15249 "Distance for local routes\n")
718e3744 15250{
585f1adc 15251 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15252 afi_t afi;
15253 safi_t safi;
37a87b8f
CS
15254
15255 afi = bgp_node_afi(vty);
15256 safi = bgp_node_safi(vty);
15257
585f1adc
IR
15258 if (bgp->distance_ebgp[afi][safi] != 0
15259 || bgp->distance_ibgp[afi][safi] != 0
15260 || bgp->distance_local[afi][safi] != 0) {
15261 bgp->distance_ebgp[afi][safi] = 0;
15262 bgp->distance_ibgp[afi][safi] = 0;
15263 bgp->distance_local[afi][safi] = 0;
15264 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15265 }
585f1adc
IR
15266 return CMD_SUCCESS;
15267}
37a87b8f 15268
37a87b8f 15269
585f1adc
IR
15270DEFUN (bgp_distance_source,
15271 bgp_distance_source_cmd,
15272 "distance (1-255) A.B.C.D/M",
15273 "Define an administrative distance\n"
15274 "Administrative distance\n"
15275 "IP source prefix\n")
15276{
15277 int idx_number = 1;
15278 int idx_ipv4_prefixlen = 2;
15279 bgp_distance_set(vty, argv[idx_number]->arg,
15280 argv[idx_ipv4_prefixlen]->arg, NULL);
15281 return CMD_SUCCESS;
734b349e
MZ
15282}
15283
585f1adc
IR
15284DEFUN (no_bgp_distance_source,
15285 no_bgp_distance_source_cmd,
15286 "no distance (1-255) A.B.C.D/M",
15287 NO_STR
15288 "Define an administrative distance\n"
15289 "Administrative distance\n"
15290 "IP source prefix\n")
37a87b8f 15291{
585f1adc
IR
15292 int idx_number = 2;
15293 int idx_ipv4_prefixlen = 3;
15294 bgp_distance_unset(vty, argv[idx_number]->arg,
15295 argv[idx_ipv4_prefixlen]->arg, NULL);
15296 return CMD_SUCCESS;
37a87b8f
CS
15297}
15298
585f1adc
IR
15299DEFUN (bgp_distance_source_access_list,
15300 bgp_distance_source_access_list_cmd,
15301 "distance (1-255) A.B.C.D/M WORD",
15302 "Define an administrative distance\n"
15303 "Administrative distance\n"
15304 "IP source prefix\n"
15305 "Access list name\n")
37a87b8f 15306{
585f1adc
IR
15307 int idx_number = 1;
15308 int idx_ipv4_prefixlen = 2;
15309 int idx_word = 3;
15310 bgp_distance_set(vty, argv[idx_number]->arg,
15311 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15312 return CMD_SUCCESS;
15313}
718e3744 15314
585f1adc
IR
15315DEFUN (no_bgp_distance_source_access_list,
15316 no_bgp_distance_source_access_list_cmd,
15317 "no distance (1-255) A.B.C.D/M WORD",
15318 NO_STR
15319 "Define an administrative distance\n"
15320 "Administrative distance\n"
15321 "IP source prefix\n"
15322 "Access list name\n")
15323{
15324 int idx_number = 2;
15325 int idx_ipv4_prefixlen = 3;
15326 int idx_word = 4;
15327 bgp_distance_unset(vty, argv[idx_number]->arg,
15328 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15329 return CMD_SUCCESS;
15330}
37a87b8f 15331
585f1adc
IR
15332DEFUN (ipv6_bgp_distance_source,
15333 ipv6_bgp_distance_source_cmd,
15334 "distance (1-255) X:X::X:X/M",
15335 "Define an administrative distance\n"
15336 "Administrative distance\n"
15337 "IP source prefix\n")
15338{
15339 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15340 return CMD_SUCCESS;
15341}
7ebe9748 15342
585f1adc
IR
15343DEFUN (no_ipv6_bgp_distance_source,
15344 no_ipv6_bgp_distance_source_cmd,
15345 "no distance (1-255) X:X::X:X/M",
15346 NO_STR
15347 "Define an administrative distance\n"
15348 "Administrative distance\n"
15349 "IP source prefix\n")
15350{
15351 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15352 return CMD_SUCCESS;
15353}
37a87b8f 15354
585f1adc
IR
15355DEFUN (ipv6_bgp_distance_source_access_list,
15356 ipv6_bgp_distance_source_access_list_cmd,
15357 "distance (1-255) X:X::X:X/M WORD",
15358 "Define an administrative distance\n"
15359 "Administrative distance\n"
15360 "IP source prefix\n"
15361 "Access list name\n")
15362{
15363 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15364 return CMD_SUCCESS;
718e3744 15365}
15366
585f1adc
IR
15367DEFUN (no_ipv6_bgp_distance_source_access_list,
15368 no_ipv6_bgp_distance_source_access_list_cmd,
15369 "no distance (1-255) X:X::X:X/M WORD",
15370 NO_STR
15371 "Define an administrative distance\n"
15372 "Administrative distance\n"
15373 "IP source prefix\n"
15374 "Access list name\n")
718e3744 15375{
585f1adc
IR
15376 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15377 return CMD_SUCCESS;
15378}
37a87b8f 15379
585f1adc
IR
15380DEFUN (bgp_damp_set,
15381 bgp_damp_set_cmd,
a30fec23 15382 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15383 "BGP Specific commands\n"
15384 "Enable route-flap dampening\n"
15385 "Half-life time for the penalty\n"
15386 "Value to start reusing a route\n"
15387 "Value to start suppressing a route\n"
15388 "Maximum duration to suppress a stable route\n")
15389{
15390 VTY_DECLVAR_CONTEXT(bgp, bgp);
15391 int idx_half_life = 2;
15392 int idx_reuse = 3;
15393 int idx_suppress = 4;
15394 int idx_max_suppress = 5;
37a87b8f
CS
15395 int half = DEFAULT_HALF_LIFE * 60;
15396 int reuse = DEFAULT_REUSE;
15397 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15398 int max = 4 * half;
15399
15400 if (argc == 6) {
15401 half = atoi(argv[idx_half_life]->arg) * 60;
15402 reuse = atoi(argv[idx_reuse]->arg);
15403 suppress = atoi(argv[idx_suppress]->arg);
15404 max = atoi(argv[idx_max_suppress]->arg) * 60;
15405 } else if (argc == 3) {
15406 half = atoi(argv[idx_half_life]->arg) * 60;
15407 max = 4 * half;
15408 }
15409
15410 /*
15411 * These can't be 0 but our SA doesn't understand the
15412 * way our cli is constructed
15413 */
15414 assert(reuse);
15415 assert(half);
15416 if (suppress < reuse) {
15417 vty_out(vty,
15418 "Suppress value cannot be less than reuse value \n");
15419 return 0;
15420 }
15421
15422 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15423 reuse, suppress, max);
15424}
15425
15426DEFUN (bgp_damp_unset,
15427 bgp_damp_unset_cmd,
a30fec23 15428 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15429 NO_STR
15430 "BGP Specific commands\n"
15431 "Enable route-flap dampening\n"
15432 "Half-life time for the penalty\n"
15433 "Value to start reusing a route\n"
15434 "Value to start suppressing a route\n"
15435 "Maximum duration to suppress a stable route\n")
15436{
15437 VTY_DECLVAR_CONTEXT(bgp, bgp);
15438 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15439}
15440
718e3744 15441/* Display specified route of BGP table. */
d62a17ae 15442static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15443 const char *ip_str, afi_t afi, safi_t safi,
15444 struct prefix_rd *prd, int prefix_check)
15445{
15446 int ret;
15447 struct prefix match;
9bcb3eef
DS
15448 struct bgp_dest *dest;
15449 struct bgp_dest *rm;
40381db7
DS
15450 struct bgp_path_info *pi;
15451 struct bgp_path_info *pi_temp;
d62a17ae 15452 struct bgp *bgp;
15453 struct bgp_table *table;
15454
15455 /* BGP structure lookup. */
15456 if (view_name) {
15457 bgp = bgp_lookup_by_name(view_name);
15458 if (bgp == NULL) {
15459 vty_out(vty, "%% Can't find BGP instance %s\n",
15460 view_name);
15461 return CMD_WARNING;
15462 }
15463 } else {
15464 bgp = bgp_get_default();
15465 if (bgp == NULL) {
15466 vty_out(vty, "%% No BGP process is configured\n");
15467 return CMD_WARNING;
15468 }
718e3744 15469 }
718e3744 15470
d62a17ae 15471 /* Check IP address argument. */
15472 ret = str2prefix(ip_str, &match);
15473 if (!ret) {
15474 vty_out(vty, "%% address is malformed\n");
15475 return CMD_WARNING;
15476 }
718e3744 15477
d62a17ae 15478 match.family = afi2family(afi);
15479
15480 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15481 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15482 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15483 dest = bgp_route_next(dest)) {
15484 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15485
9bcb3eef 15486 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15487 continue;
9bcb3eef 15488 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15489 if (!table)
ea47320b 15490 continue;
4953391b
DA
15491 rm = bgp_node_match(table, &match);
15492 if (rm == NULL)
ea47320b 15493 continue;
d62a17ae 15494
9bcb3eef 15495 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15496
ea47320b 15497 if (!prefix_check
b54892e0 15498 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15499 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15500 while (pi) {
15501 if (pi->extra && pi->extra->damp_info) {
15502 pi_temp = pi->next;
ea47320b 15503 bgp_damp_info_free(
19971c9a 15504 pi->extra->damp_info,
5c8846f6 15505 1, afi, safi);
40381db7 15506 pi = pi_temp;
ea47320b 15507 } else
40381db7 15508 pi = pi->next;
d62a17ae 15509 }
ea47320b
DL
15510 }
15511
9bcb3eef 15512 bgp_dest_unlock_node(rm);
d62a17ae 15513 }
15514 } else {
4953391b
DA
15515 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15516 if (dest != NULL) {
9bcb3eef 15517 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15518
d62a17ae 15519 if (!prefix_check
9bcb3eef
DS
15520 || dest_p->prefixlen == match.prefixlen) {
15521 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15522 while (pi) {
15523 if (pi->extra && pi->extra->damp_info) {
15524 pi_temp = pi->next;
d62a17ae 15525 bgp_damp_info_free(
19971c9a 15526 pi->extra->damp_info,
5c8846f6 15527 1, afi, safi);
40381db7 15528 pi = pi_temp;
d62a17ae 15529 } else
40381db7 15530 pi = pi->next;
d62a17ae 15531 }
15532 }
15533
9bcb3eef 15534 bgp_dest_unlock_node(dest);
d62a17ae 15535 }
15536 }
718e3744 15537
d62a17ae 15538 return CMD_SUCCESS;
718e3744 15539}
15540
15541DEFUN (clear_ip_bgp_dampening,
15542 clear_ip_bgp_dampening_cmd,
15543 "clear ip bgp dampening",
15544 CLEAR_STR
15545 IP_STR
15546 BGP_STR
15547 "Clear route flap dampening information\n")
15548{
b4f7f45b 15549 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15550 return CMD_SUCCESS;
718e3744 15551}
15552
15553DEFUN (clear_ip_bgp_dampening_prefix,
15554 clear_ip_bgp_dampening_prefix_cmd,
15555 "clear ip bgp dampening A.B.C.D/M",
15556 CLEAR_STR
15557 IP_STR
15558 BGP_STR
15559 "Clear route flap dampening information\n"
0c7b1b01 15560 "IPv4 prefix\n")
718e3744 15561{
d62a17ae 15562 int idx_ipv4_prefixlen = 4;
15563 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15564 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15565}
15566
15567DEFUN (clear_ip_bgp_dampening_address,
15568 clear_ip_bgp_dampening_address_cmd,
15569 "clear ip bgp dampening A.B.C.D",
15570 CLEAR_STR
15571 IP_STR
15572 BGP_STR
15573 "Clear route flap dampening information\n"
15574 "Network to clear damping information\n")
15575{
d62a17ae 15576 int idx_ipv4 = 4;
15577 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15578 SAFI_UNICAST, NULL, 0);
718e3744 15579}
15580
15581DEFUN (clear_ip_bgp_dampening_address_mask,
15582 clear_ip_bgp_dampening_address_mask_cmd,
15583 "clear ip bgp dampening A.B.C.D A.B.C.D",
15584 CLEAR_STR
15585 IP_STR
15586 BGP_STR
15587 "Clear route flap dampening information\n"
15588 "Network to clear damping information\n"
15589 "Network mask\n")
15590{
d62a17ae 15591 int idx_ipv4 = 4;
15592 int idx_ipv4_2 = 5;
15593 int ret;
15594 char prefix_str[BUFSIZ];
718e3744 15595
d62a17ae 15596 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15597 prefix_str, sizeof(prefix_str));
d62a17ae 15598 if (!ret) {
15599 vty_out(vty, "%% Inconsistent address and mask\n");
15600 return CMD_WARNING;
15601 }
718e3744 15602
d62a17ae 15603 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15604 NULL, 0);
718e3744 15605}
6b0655a2 15606
e3b78da8 15607static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15608{
15609 struct vty *vty = arg;
e3b78da8 15610 struct peer *peer = bucket->data;
825d9834 15611
47e12884 15612 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15613}
15614
2a0e69ae
DS
15615DEFUN (show_bgp_listeners,
15616 show_bgp_listeners_cmd,
15617 "show bgp listeners",
15618 SHOW_STR
15619 BGP_STR
15620 "Display Listen Sockets and who created them\n")
15621{
15622 bgp_dump_listener_info(vty);
15623
15624 return CMD_SUCCESS;
15625}
15626
825d9834
DS
15627DEFUN (show_bgp_peerhash,
15628 show_bgp_peerhash_cmd,
15629 "show bgp peerhash",
15630 SHOW_STR
15631 BGP_STR
15632 "Display information about the BGP peerhash\n")
15633{
15634 struct list *instances = bm->bgp;
15635 struct listnode *node;
15636 struct bgp *bgp;
15637
15638 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15639 vty_out(vty, "BGP: %s\n", bgp->name);
15640 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15641 vty);
15642 }
15643
15644 return CMD_SUCCESS;
15645}
15646
587ff0fd 15647/* also used for encap safi */
2b791107
DL
15648static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15649 afi_t afi, safi_t safi)
d62a17ae 15650{
9bcb3eef
DS
15651 struct bgp_dest *pdest;
15652 struct bgp_dest *dest;
d62a17ae 15653 struct bgp_table *table;
b54892e0 15654 const struct prefix *p;
d62a17ae 15655 struct bgp_static *bgp_static;
15656 mpls_label_t label;
d62a17ae 15657
15658 /* Network configuration. */
9bcb3eef
DS
15659 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15660 pdest = bgp_route_next(pdest)) {
15661 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15662 if (!table)
ea47320b 15663 continue;
d62a17ae 15664
9bcb3eef
DS
15665 for (dest = bgp_table_top(table); dest;
15666 dest = bgp_route_next(dest)) {
15667 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15668 if (bgp_static == NULL)
ea47320b 15669 continue;
d62a17ae 15670
9bcb3eef 15671 p = bgp_dest_get_prefix(dest);
d62a17ae 15672
ea47320b 15673 /* "network" configuration display. */
ea47320b
DL
15674 label = decode_label(&bgp_static->label);
15675
c1aa9e7f
PG
15676 vty_out(vty, " network %pFX rd %s", p,
15677 bgp_static->prd_pretty);
ea47320b
DL
15678 if (safi == SAFI_MPLS_VPN)
15679 vty_out(vty, " label %u", label);
15680
15681 if (bgp_static->rmap.name)
15682 vty_out(vty, " route-map %s",
15683 bgp_static->rmap.name);
e2a86ad9
DS
15684
15685 if (bgp_static->backdoor)
15686 vty_out(vty, " backdoor");
15687
ea47320b
DL
15688 vty_out(vty, "\n");
15689 }
15690 }
d62a17ae 15691}
15692
2b791107
DL
15693static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15694 afi_t afi, safi_t safi)
d62a17ae 15695{
9bcb3eef
DS
15696 struct bgp_dest *pdest;
15697 struct bgp_dest *dest;
d62a17ae 15698 struct bgp_table *table;
b54892e0 15699 const struct prefix *p;
d62a17ae 15700 struct bgp_static *bgp_static;
ff44f570 15701 char buf[PREFIX_STRLEN * 2];
d62a17ae 15702 char buf2[SU_ADDRSTRLEN];
5f933e1e 15703 char esi_buf[ESI_STR_LEN];
d62a17ae 15704
15705 /* Network configuration. */
9bcb3eef
DS
15706 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15707 pdest = bgp_route_next(pdest)) {
15708 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15709 if (!table)
ea47320b 15710 continue;
d62a17ae 15711
9bcb3eef
DS
15712 for (dest = bgp_table_top(table); dest;
15713 dest = bgp_route_next(dest)) {
15714 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15715 if (bgp_static == NULL)
ea47320b 15716 continue;
d62a17ae 15717
ea47320b 15718 char *macrouter = NULL;
d62a17ae 15719
ea47320b
DL
15720 if (bgp_static->router_mac)
15721 macrouter = prefix_mac2str(
15722 bgp_static->router_mac, NULL, 0);
15723 if (bgp_static->eth_s_id)
0a50c248
AK
15724 esi_to_str(bgp_static->eth_s_id,
15725 esi_buf, sizeof(esi_buf));
9bcb3eef 15726 p = bgp_dest_get_prefix(dest);
d62a17ae 15727
ea47320b 15728 /* "network" configuration display. */
197cb530
PG
15729 if (p->u.prefix_evpn.route_type == 5) {
15730 char local_buf[PREFIX_STRLEN];
07380148 15731
3714a385 15732 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15733 struct prefix_evpn *)p)
15734 ? AF_INET
15735 : AF_INET6;
3714a385 15736 inet_ntop(family,
07380148
DA
15737 &p->u.prefix_evpn.prefix_addr.ip.ip
15738 .addr,
15739 local_buf, sizeof(local_buf));
772270f3
QY
15740 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15741 p->u.prefix_evpn.prefix_addr
15742 .ip_prefix_length);
197cb530
PG
15743 } else {
15744 prefix2str(p, buf, sizeof(buf));
15745 }
ea47320b 15746
a4d82a8a
PZ
15747 if (bgp_static->gatewayIp.family == AF_INET
15748 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15749 inet_ntop(bgp_static->gatewayIp.family,
15750 &bgp_static->gatewayIp.u.prefix, buf2,
15751 sizeof(buf2));
ea47320b 15752 vty_out(vty,
c1aa9e7f
PG
15753 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15754 buf, bgp_static->prd_pretty,
15755 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15756 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15757 macrouter);
15758
0a22ddfb 15759 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15760 }
15761 }
3da6fcd5
PG
15762}
15763
718e3744 15764/* Configuration of static route announcement and aggregate
15765 information. */
2b791107
DL
15766void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15767 safi_t safi)
d62a17ae 15768{
9bcb3eef 15769 struct bgp_dest *dest;
b54892e0 15770 const struct prefix *p;
d62a17ae 15771 struct bgp_static *bgp_static;
15772 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15773
2b791107
DL
15774 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15775 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15776 return;
15777 }
d62a17ae 15778
2b791107
DL
15779 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15780 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15781 return;
15782 }
d62a17ae 15783
15784 /* Network configuration. */
9bcb3eef
DS
15785 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15786 dest = bgp_route_next(dest)) {
15787 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15788 if (bgp_static == NULL)
ea47320b 15789 continue;
d62a17ae 15790
9bcb3eef 15791 p = bgp_dest_get_prefix(dest);
d62a17ae 15792
8228a9a7 15793 vty_out(vty, " network %pFX", p);
d62a17ae 15794
ea47320b
DL
15795 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15796 vty_out(vty, " label-index %u",
15797 bgp_static->label_index);
d62a17ae 15798
ea47320b
DL
15799 if (bgp_static->rmap.name)
15800 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15801
15802 if (bgp_static->backdoor)
15803 vty_out(vty, " backdoor");
718e3744 15804
ea47320b
DL
15805 vty_out(vty, "\n");
15806 }
15807
d62a17ae 15808 /* Aggregate-address configuration. */
9bcb3eef
DS
15809 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15810 dest = bgp_route_next(dest)) {
15811 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15812 if (bgp_aggregate == NULL)
ea47320b 15813 continue;
d62a17ae 15814
9bcb3eef 15815 p = bgp_dest_get_prefix(dest);
d62a17ae 15816
8228a9a7 15817 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15818
ea47320b
DL
15819 if (bgp_aggregate->as_set)
15820 vty_out(vty, " as-set");
d62a17ae 15821
ea47320b
DL
15822 if (bgp_aggregate->summary_only)
15823 vty_out(vty, " summary-only");
718e3744 15824
20894f50
DA
15825 if (bgp_aggregate->rmap.name)
15826 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15827
229757f1
DA
15828 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15829 vty_out(vty, " origin %s",
15830 bgp_origin2str(bgp_aggregate->origin));
15831
6aabb15d
RZ
15832 if (bgp_aggregate->match_med)
15833 vty_out(vty, " matching-MED-only");
15834
365ab2e7
RZ
15835 if (bgp_aggregate->suppress_map_name)
15836 vty_out(vty, " suppress-map %s",
15837 bgp_aggregate->suppress_map_name);
15838
ea47320b
DL
15839 vty_out(vty, "\n");
15840 }
d62a17ae 15841}
734b349e 15842
2b791107 15843void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15844 safi_t safi)
d62a17ae 15845{
9bcb3eef 15846 struct bgp_dest *dest;
d62a17ae 15847 struct bgp_distance *bdistance;
15848
15849 /* Distance configuration. */
15850 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15851 && bgp->distance_local[afi][safi]
15852 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15853 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15854 || bgp->distance_local[afi][safi]
15855 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15856 vty_out(vty, " distance bgp %d %d %d\n",
15857 bgp->distance_ebgp[afi][safi],
15858 bgp->distance_ibgp[afi][safi],
15859 bgp->distance_local[afi][safi]);
15860 }
734b349e 15861
9bcb3eef
DS
15862 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15863 dest = bgp_route_next(dest)) {
15864 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15865 if (bdistance != NULL)
56ca3b5b 15866 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15867 bdistance->distance, dest,
d62a17ae 15868 bdistance->access_list ? bdistance->access_list
15869 : "");
ca2e160d 15870 }
718e3744 15871}
15872
15873/* Allocate routing table structure and install commands. */
d62a17ae 15874void bgp_route_init(void)
15875{
15876 afi_t afi;
15877 safi_t safi;
15878
15879 /* Init BGP distance table. */
05c7a1cc 15880 FOREACH_AFI_SAFI (afi, safi)
960035b2 15881 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15882
15883 /* IPv4 BGP commands. */
15884 install_element(BGP_NODE, &bgp_table_map_cmd);
15885 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15886 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15887
554b3b10 15888 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15889
15890 /* IPv4 unicast configuration. */
15891 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15892 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15893 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15894
554b3b10 15895 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15896
15897 /* IPv4 multicast configuration. */
15898 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15899 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15900 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15901 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15902
15903 /* IPv4 labeled-unicast configuration. */
fb985e0c 15904 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15905 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15906
d62a17ae 15907 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15908 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15909 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15910 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15911 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15912 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15913 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15914 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15915
15916 install_element(VIEW_NODE,
15917 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15918 install_element(VIEW_NODE,
15919 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15920 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15921 install_element(VIEW_NODE,
15922 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15923#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15924 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15925#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15926 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15927 install_element(VIEW_NODE,
44c69747 15928 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15929
d62a17ae 15930 /* BGP dampening clear commands */
15931 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15932 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15933
d62a17ae 15934 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15935 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15936
15937 /* prefix count */
15938 install_element(ENABLE_NODE,
15939 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15940#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15941 install_element(ENABLE_NODE,
15942 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15943#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15944
d62a17ae 15945 /* New config IPv6 BGP commands. */
15946 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15947 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15948 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15949
554b3b10 15950 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15951
15952 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15953
fb985e0c
DA
15954 /* IPv6 labeled unicast address family. */
15955 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15956 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15957
d62a17ae 15958 install_element(BGP_NODE, &bgp_distance_cmd);
15959 install_element(BGP_NODE, &no_bgp_distance_cmd);
15960 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15961 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15962 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15963 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15964 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15965 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15966 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15967 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15968 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15969 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15970 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15971 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15972 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15973 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15974 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15975 install_element(BGP_IPV4M_NODE,
15976 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15977 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15978 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15979 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15980 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15981 install_element(BGP_IPV6_NODE,
15982 &ipv6_bgp_distance_source_access_list_cmd);
15983 install_element(BGP_IPV6_NODE,
15984 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15985 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15986 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15987 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15988 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15989 install_element(BGP_IPV6M_NODE,
15990 &ipv6_bgp_distance_source_access_list_cmd);
15991 install_element(BGP_IPV6M_NODE,
15992 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15993
ef5f4b23 15994 /* BGP dampening */
585f1adc
IR
15995 install_element(BGP_NODE, &bgp_damp_set_cmd);
15996 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15997 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15998 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15999 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16000 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16001 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16002 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16003 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16004 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16005 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16006 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16007 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16008 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 16009
16010 /* Large Communities */
16011 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16012 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
16013
16014 /* show bgp ipv4 flowspec detailed */
16015 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
16016
2a0e69ae 16017 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16018 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16019}
16020
16021void bgp_route_finish(void)
16022{
16023 afi_t afi;
16024 safi_t safi;
16025
05c7a1cc
QY
16026 FOREACH_AFI_SAFI (afi, safi) {
16027 bgp_table_unlock(bgp_distance_table[afi][safi]);
16028 bgp_distance_table[afi][safi] = NULL;
16029 }
228da428 16030}