]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: fix bgp label value when static route used
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* BGP routing information
896014f4
DL
3 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 * Copyright (C) 2016 Job Snijders <job@instituut.net>
896014f4 5 */
718e3744 6
7#include <zebra.h>
8d0ab76d 8#include <math.h>
718e3744 9
2618a52e 10#include "printfrr.h"
a70a28a5 11#include "frrstr.h"
718e3744 12#include "prefix.h"
13#include "linklist.h"
14#include "memory.h"
15#include "command.h"
16#include "stream.h"
17#include "filter.h"
718e3744 18#include "log.h"
19#include "routemap.h"
20#include "buffer.h"
21#include "sockunion.h"
22#include "plist.h"
24a58196 23#include "frrevent.h"
200df115 24#include "workqueue.h"
3f9c7369 25#include "queue.h"
6e919709 26#include "memory.h"
e496b420 27#include "srv6.h"
4dcadbef 28#include "lib/json.h"
d8d084d9 29#include "lib_errors.h"
8c48b3b6 30#include "zclient.h"
718e3744 31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_table.h"
33#include "bgpd/bgp_route.h"
34#include "bgpd/bgp_attr.h"
35#include "bgpd/bgp_debug.h"
14454c9f 36#include "bgpd/bgp_errors.h"
718e3744 37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_regex.h"
39#include "bgpd/bgp_community.h"
ed0e57e3 40#include "bgpd/bgp_community_alias.h"
718e3744 41#include "bgpd/bgp_ecommunity.h"
57d187bc 42#include "bgpd/bgp_lcommunity.h"
718e3744 43#include "bgpd/bgp_clist.h"
44#include "bgpd/bgp_packet.h"
45#include "bgpd/bgp_filter.h"
46#include "bgpd/bgp_fsm.h"
47#include "bgpd/bgp_mplsvpn.h"
48#include "bgpd/bgp_nexthop.h"
49#include "bgpd/bgp_damp.h"
50#include "bgpd/bgp_advertise.h"
51#include "bgpd/bgp_zebra.h"
0a486e5f 52#include "bgpd/bgp_vty.h"
96450faf 53#include "bgpd/bgp_mpath.h"
fc9a856f 54#include "bgpd/bgp_nht.h"
3f9c7369 55#include "bgpd/bgp_updgrp.h"
cd1964ff 56#include "bgpd/bgp_label.h"
dcc68b5e 57#include "bgpd/bgp_addpath.h"
4e802e66 58#include "bgpd/bgp_mac.h"
2a0e69ae 59#include "bgpd/bgp_network.h"
6401252f 60#include "bgpd/bgp_trace.h"
fdeb5a81 61#include "bgpd/bgp_rpki.h"
718e3744 62
49e5a4a0 63#ifdef ENABLE_BGP_VNC
f8b6f499
LB
64#include "bgpd/rfapi/rfapi_backend.h"
65#include "bgpd/rfapi/vnc_import_bgp.h"
66#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 67#endif
aee875b5
PG
68#include "bgpd/bgp_encap_types.h"
69#include "bgpd/bgp_encap_tlv.h"
684a7227 70#include "bgpd/bgp_evpn.h"
0a50c248 71#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 72#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 73#include "bgpd/bgp_flowspec.h"
98a9dbc7 74#include "bgpd/bgp_flowspec_util.h"
45918cfb 75#include "bgpd/bgp_pbr.h"
65efcfce 76
e2a86ad9 77#include "bgpd/bgp_route_clippy.c"
aee875b5 78
7fd28dd2
PR
79DEFINE_HOOK(bgp_snmp_update_stats,
80 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 81 (rn, pi, added));
7fd28dd2 82
b5b99af8
DS
83DEFINE_HOOK(bgp_rpki_prefix_status,
84 (struct peer *peer, struct attr *attr,
85 const struct prefix *prefix),
8451921b 86 (peer, attr, prefix));
b5b99af8 87
718e3744 88/* Extern from bgp_dump.c */
dde72586
SH
89extern const char *bgp_origin_str[];
90extern const char *bgp_origin_long_str[];
3742de8d 91
b7d08f5a 92/* PMSI strings. */
93#define PMSI_TNLTYPE_STR_NO_INFO "No info"
94#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
95static const struct message bgp_pmsi_tnltype_str[] = {
96 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
97 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
98 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
99 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
100 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
101 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
102 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
103 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 104 {0}
105};
b7d08f5a 106
9df8b37c 107#define VRFID_NONE_STR "-"
46aeabed 108#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 109
4a11bf2c 110DEFINE_HOOK(bgp_process,
9bcb3eef
DS
111 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
112 struct peer *peer, bool withdraw),
8451921b 113 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 114
4056a5f6
RZ
115/** Test if path is suppressed. */
116static bool bgp_path_suppressed(struct bgp_path_info *pi)
117{
118 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
119 return false;
120
121 return listcount(pi->extra->aggr_suppressors) > 0;
122}
4a11bf2c 123
9bcb3eef 124struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 125 safi_t safi, const struct prefix *p,
d62a17ae 126 struct prefix_rd *prd)
127{
9bcb3eef
DS
128 struct bgp_dest *dest;
129 struct bgp_dest *pdest = NULL;
d62a17ae 130
131 assert(table);
d62a17ae 132
133 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
134 || (safi == SAFI_EVPN)) {
9bcb3eef 135 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 136
9bcb3eef
DS
137 if (!bgp_dest_has_bgp_path_info_data(pdest))
138 bgp_dest_set_bgp_table_info(
139 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 140 else
9bcb3eef
DS
141 bgp_dest_unlock_node(pdest);
142 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 143 }
718e3744 144
9bcb3eef 145 dest = bgp_node_get(table, p);
718e3744 146
d62a17ae 147 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
148 || (safi == SAFI_EVPN))
9bcb3eef 149 dest->pdest = pdest;
718e3744 150
9bcb3eef 151 return dest;
718e3744 152}
6b0655a2 153
59d6b4d6
DA
154struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table, safi_t safi,
155 const struct prefix *p,
156 struct prefix_rd *prd)
128ea8ab 157{
9bcb3eef
DS
158 struct bgp_dest *dest;
159 struct bgp_dest *pdest = NULL;
128ea8ab 160
d62a17ae 161 if (!table)
162 return NULL;
128ea8ab 163
d62a17ae 164 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
166 pdest = bgp_node_lookup(table, (struct prefix *)prd);
167 if (!pdest)
d62a17ae 168 return NULL;
128ea8ab 169
9bcb3eef
DS
170 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
171 bgp_dest_unlock_node(pdest);
d62a17ae 172 return NULL;
173 }
128ea8ab 174
9bcb3eef 175 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 176 }
128ea8ab 177
9bcb3eef 178 dest = bgp_node_lookup(table, p);
128ea8ab 179
9bcb3eef 180 return dest;
128ea8ab 181}
182
18ee8310
DS
183/* Allocate bgp_path_info_extra */
184static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 185{
4b7e6066
DS
186 struct bgp_path_info_extra *new;
187 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
188 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
189 new->label[0] = MPLS_INVALID_LABEL;
190 new->num_labels = 0;
3e3708cb
PG
191 new->bgp_fs_pbr = NULL;
192 new->bgp_fs_iprule = NULL;
d62a17ae 193 return new;
fb982c25
PJ
194}
195
a2e219fe 196void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 197{
4b7e6066 198 struct bgp_path_info_extra *e;
d62a17ae 199
c93a3b77
DS
200 if (!extra || !*extra)
201 return;
d62a17ae 202
c93a3b77 203 e = *extra;
4538f895 204 if (e->damp_info)
b4f7f45b
IR
205 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
206 e->damp_info->safi);
4538f895 207
c93a3b77
DS
208 e->damp_info = NULL;
209 if (e->parent) {
40381db7 210 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 211
40381db7 212 if (bpi->net) {
0e70e6c8
DL
213 /* FIXME: since multiple e may have the same e->parent
214 * and e->parent->net is holding a refcount for each
215 * of them, we need to do some fudging here.
216 *
40381db7
DS
217 * WARNING: if bpi->net->lock drops to 0, bpi may be
218 * freed as well (because bpi->net was holding the
219 * last reference to bpi) => write after free!
0e70e6c8
DL
220 */
221 unsigned refcount;
222
40381db7 223 bpi = bgp_path_info_lock(bpi);
c10e14e9 224 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 225 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 226 if (!refcount)
40381db7
DS
227 bpi->net = NULL;
228 bgp_path_info_unlock(bpi);
0e70e6c8 229 }
18ee8310 230 bgp_path_info_unlock(e->parent);
c93a3b77 231 e->parent = NULL;
d62a17ae 232 }
c93a3b77
DS
233
234 if (e->bgp_orig)
235 bgp_unlock(e->bgp_orig);
c26edcda 236
4cd690ae
PG
237 if (e->peer_orig)
238 peer_unlock(e->peer_orig);
239
ff3bf9a4
DS
240 if (e->aggr_suppressors)
241 list_delete(&e->aggr_suppressors);
242
60605cbc
AK
243 if (e->mh_info)
244 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 245
ce3c0614
PG
246 if ((*extra)->bgp_fs_iprule)
247 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 248 if ((*extra)->bgp_fs_pbr)
6a154c88 249 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 250 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
251}
252
18ee8310
DS
253/* Get bgp_path_info extra information for the given bgp_path_info, lazy
254 * allocated if required.
fb982c25 255 */
40381db7 256struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 257{
40381db7
DS
258 if (!pi->extra)
259 pi->extra = bgp_path_info_extra_new();
260 return pi->extra;
fb982c25
PJ
261}
262
718e3744 263/* Free bgp route information. */
eb473185
DA
264void bgp_path_info_free_with_caller(const char *name,
265 struct bgp_path_info *path)
718e3744 266{
eb473185 267 frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
05864da7 268 bgp_attr_unintern(&path->attr);
fb018d25 269
9b6d8fcf
DS
270 bgp_unlink_nexthop(path);
271 bgp_path_info_extra_free(&path->extra);
272 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
273 if (path->net)
274 bgp_addpath_free_info_data(&path->tx_addpath,
275 &path->net->tx_addpath);
718e3744 276
9b6d8fcf 277 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 278
9b6d8fcf 279 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 280}
281
9b6d8fcf 282struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 283{
9b6d8fcf
DS
284 path->lock++;
285 return path;
200df115 286}
287
9b6d8fcf 288struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 289{
9b6d8fcf
DS
290 assert(path && path->lock > 0);
291 path->lock--;
d62a17ae 292
9b6d8fcf 293 if (path->lock == 0) {
9b6d8fcf 294 bgp_path_info_free(path);
d62a17ae 295 return NULL;
296 }
200df115 297
9b6d8fcf 298 return path;
200df115 299}
300
f009ff26 301/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 302static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 303{
304 struct peer *peer;
305 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 306 bool set_flag = false;
f009ff26 307 struct bgp *bgp = NULL;
308 struct bgp_table *table = NULL;
309 afi_t afi = 0;
310 safi_t safi = 0;
f009ff26 311
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
314 */
9bcb3eef 315 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 316 return 0;
317
9bcb3eef 318 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
7fd8ca9a
DS
319 if (BGP_DEBUG(update, UPDATE_OUT)) {
320 table = bgp_dest_table(dest);
321 if (table)
322 bgp = table->bgp;
323
36235319 324 zlog_debug(
7fd8ca9a
DS
325 "Route %pBD(%s) is in workqueue and being processed, not deferred.",
326 dest, bgp ? bgp->name_pretty : "(Unknown)");
327 }
b54892e0 328
5f9c1aa2 329 return 0;
330 }
331
9bcb3eef 332 table = bgp_dest_table(dest);
f009ff26 333 if (table) {
334 bgp = table->bgp;
335 afi = table->afi;
336 safi = table->safi;
337 }
338
9bcb3eef 339 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 340 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
341 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
342 continue;
343
344 /* Route selection is deferred if there is a stale path which
345 * which indicates peer is in restart mode
346 */
36235319
QY
347 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
348 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 349 set_flag = true;
f009ff26 350 } else {
351 /* If the peer is graceful restart capable and peer is
352 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
353 */
354 peer = old_pi->peer;
36235319
QY
355 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
356 && BGP_PEER_RESTARTING_MODE(peer)
357 && (old_pi
358 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 359 set_flag = true;
f009ff26 360 }
361 }
362 if (set_flag)
363 break;
364 }
365
366 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
367 * is active
368 */
2ba1fe69 369 if (set_flag && table) {
f009ff26 370 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
371 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
372 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 373 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 374 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
375 zlog_debug("DEFER route %pBD(%s), dest %p",
376 dest, bgp->name_pretty, dest);
f009ff26 377 return 0;
378 }
379 }
380 return -1;
381}
382
eb473185
DA
383void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
384 struct bgp_path_info *pi)
718e3744 385{
c6b077a5 386 frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
4b7e6066 387 struct bgp_path_info *top;
718e3744 388
9bcb3eef 389 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 390
6f94b685 391 pi->next = top;
40381db7 392 pi->prev = NULL;
d62a17ae 393 if (top)
40381db7 394 top->prev = pi;
9bcb3eef 395 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 396
40381db7 397 bgp_path_info_lock(pi);
9bcb3eef 398 bgp_dest_lock_node(dest);
40381db7 399 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 400 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 401 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 402}
403
d62a17ae 404/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 405 completion callback *only* */
9bcb3eef 406void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 407{
40381db7
DS
408 if (pi->next)
409 pi->next->prev = pi->prev;
410 if (pi->prev)
411 pi->prev->next = pi->next;
d62a17ae 412 else
9bcb3eef 413 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 414
40381db7
DS
415 bgp_path_info_mpath_dequeue(pi);
416 bgp_path_info_unlock(pi);
7fd28dd2 417 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 418 bgp_dest_unlock_node(dest);
718e3744 419}
420
9bcb3eef 421void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 422{
9bcb3eef 423 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 424 /* set of previous already took care of pcount */
40381db7 425 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 426}
427
18ee8310 428/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
429 called when a route is deleted and then quickly re-added before the
430 deletion has been processed */
9bcb3eef 431void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 432{
9bcb3eef 433 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 434 /* unset of previous already took care of pcount */
40381db7 435 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
436}
437
d62a17ae 438/* Adjust pcount as required */
9bcb3eef 439static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 440{
d62a17ae 441 struct bgp_table *table;
67174041 442
9bcb3eef 443 assert(dest && bgp_dest_table(dest));
40381db7 444 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 445
9bcb3eef 446 table = bgp_dest_table(dest);
67174041 447
40381db7 448 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 449 return;
450
40381db7
DS
451 if (!BGP_PATH_COUNTABLE(pi)
452 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 453
40381db7 454 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 455
456 /* slight hack, but more robust against errors. */
40381db7
DS
457 if (pi->peer->pcount[table->afi][table->safi])
458 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 459 else
450971aa 460 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 461 "Asked to decrement 0 prefix count for peer");
40381db7
DS
462 } else if (BGP_PATH_COUNTABLE(pi)
463 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
464 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
465 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 466 }
1a392d46
PJ
467}
468
40381db7
DS
469static int bgp_label_index_differs(struct bgp_path_info *pi1,
470 struct bgp_path_info *pi2)
28d58fd7 471{
40381db7 472 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 473}
1a392d46 474
18ee8310 475/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
476 * This is here primarily to keep prefix-count in check.
477 */
9bcb3eef 478void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 479 uint32_t flag)
1a392d46 480{
40381db7 481 SET_FLAG(pi->flags, flag);
d62a17ae 482
483 /* early bath if we know it's not a flag that changes countability state
484 */
485 if (!CHECK_FLAG(flag,
1defdda8 486 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 487 return;
488
9bcb3eef 489 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
490}
491
9bcb3eef 492void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 493 uint32_t flag)
1a392d46 494{
40381db7 495 UNSET_FLAG(pi->flags, flag);
d62a17ae 496
497 /* early bath if we know it's not a flag that changes countability state
498 */
499 if (!CHECK_FLAG(flag,
1defdda8 500 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 501 return;
502
9bcb3eef 503 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
504}
505
718e3744 506/* Get MED value. If MED value is missing and "bgp bestpath
507 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 508static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 509{
510 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
511 return attr->med;
512 else {
892fedb6 513 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 514 return BGP_MED_MAX;
515 else
516 return 0;
517 }
718e3744 518}
519
7533cad7
QY
520void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
521 size_t buf_len)
2ec1e66f 522{
b1ff5529
PG
523 struct peer *peer;
524
525 if (pi->sub_type == BGP_ROUTE_IMPORTED &&
526 bgp_get_imported_bpi_ultimate(pi))
527 peer = bgp_get_imported_bpi_ultimate(pi)->peer;
528 else
529 peer = pi->peer;
530
40381db7 531 if (pi->addpath_rx_id)
b1ff5529
PG
532 snprintf(buf, buf_len, "path %s (addpath rxid %d)", peer->host,
533 pi->addpath_rx_id);
d62a17ae 534 else
b1ff5529 535 snprintf(buf, buf_len, "path %s", peer->host);
d62a17ae 536}
9fbdd100 537
da0c0ef7
KM
538
539/*
540 * Get the ultimate path info.
541 */
542struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
543{
544 struct bgp_path_info *bpi_ultimate;
545
546 if (info->sub_type != BGP_ROUTE_IMPORTED)
547 return info;
548
549 for (bpi_ultimate = info;
550 bpi_ultimate->extra && bpi_ultimate->extra->parent;
551 bpi_ultimate = bpi_ultimate->extra->parent)
552 ;
553
554 return bpi_ultimate;
555}
556
d62a17ae 557/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
558 */
18ee8310
DS
559static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
560 struct bgp_path_info *exist, int *paths_eq,
561 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
562 char *pfx_buf, afi_t afi, safi_t safi,
563 enum bgp_path_selection_reason *reason)
d62a17ae 564{
5df26422 565 const struct prefix *new_p;
d62a17ae 566 struct attr *newattr, *existattr;
3061acc2
DA
567 enum bgp_peer_sort new_sort;
568 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
569 uint32_t new_pref;
570 uint32_t exist_pref;
571 uint32_t new_med;
572 uint32_t exist_med;
573 uint32_t new_weight;
574 uint32_t exist_weight;
d62a17ae 575 uint32_t newm, existm;
576 struct in_addr new_id;
577 struct in_addr exist_id;
578 int new_cluster;
579 int exist_cluster;
580 int internal_as_route;
581 int confed_as_route;
04d14c8b 582 int ret = 0;
ee88563a
JM
583 int igp_metric_ret = 0;
584 int peer_sort_ret = -1;
d62a17ae 585 char new_buf[PATH_ADDPATH_STR_BUFFER];
586 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
587 uint32_t new_mm_seq;
588 uint32_t exist_mm_seq;
6d8c603a 589 int nh_cmp;
d071f237
AK
590 esi_t *exist_esi;
591 esi_t *new_esi;
592 bool same_esi;
593 bool old_proxy;
594 bool new_proxy;
33c6e933 595 bool new_origin, exist_origin;
da0c0ef7 596 struct bgp_path_info *bpi_ultimate;
cefda028 597 struct peer *peer_new, *peer_exist;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
46dbf9d0
DA
874 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
875 * extensions defined in this document, the following step is inserted
876 * after the LOCAL_PREF comparison step in the BGP decision process:
877 * When comparing a pair of routes for a BGP destination, the
878 * route with the ACCEPT_OWN community attached is preferred over
879 * the route that does not have the community.
880 * This extra step MUST only be invoked during the best path selection
881 * process of VPN-IP routes.
882 */
883 if (safi == SAFI_MPLS_VPN &&
884 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
885 CHECK_FLAG(exist->peer->af_flags[afi][safi],
886 PEER_FLAG_ACCEPT_OWN))) {
887 bool new_accept_own = false;
888 bool exist_accept_own = false;
889 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
890
891 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
892 new_accept_own = community_include(
893 bgp_attr_get_community(newattr), accept_own);
894 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
895 exist_accept_own = community_include(
896 bgp_attr_get_community(existattr), accept_own);
897
898 if (new_accept_own && !exist_accept_own) {
899 *reason = bgp_path_selection_accept_own;
900 if (debug)
901 zlog_debug(
902 "%s: %s wins over %s due to accept-own",
903 pfx_buf, new_buf, exist_buf);
904 return 1;
905 }
906
907 if (!new_accept_own && exist_accept_own) {
908 *reason = bgp_path_selection_accept_own;
909 if (debug)
910 zlog_debug(
911 "%s: %s loses to %s due to accept-own",
912 pfx_buf, new_buf, exist_buf);
913 return 0;
914 }
915 }
916
97a52c82
DA
917 /* Tie-breaker - AIGP (Metric TLV) attribute */
918 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
919 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
920 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
921 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
922 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
923
924 if (new_aigp < exist_aigp) {
925 *reason = bgp_path_selection_aigp;
926 if (debug)
927 zlog_debug(
928 "%s: %s wins over %s due to AIGP %" PRIu64
929 " < %" PRIu64,
930 pfx_buf, new_buf, exist_buf, new_aigp,
931 exist_aigp);
932 return 1;
933 }
934
935 if (new_aigp > exist_aigp) {
936 *reason = bgp_path_selection_aigp;
937 if (debug)
938 zlog_debug(
939 "%s: %s loses to %s due to AIGP %" PRIu64
940 " > %" PRIu64,
941 pfx_buf, new_buf, exist_buf, new_aigp,
942 exist_aigp);
943 return 0;
944 }
945 }
946
d62a17ae 947 /* 3. Local route check. We prefer:
948 * - BGP_ROUTE_STATIC
949 * - BGP_ROUTE_AGGREGATE
950 * - BGP_ROUTE_REDISTRIBUTE
951 */
33c6e933
DS
952 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
953 new->sub_type == BGP_ROUTE_IMPORTED);
954 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
955 exist->sub_type == BGP_ROUTE_IMPORTED);
956
957 if (new_origin && !exist_origin) {
fdf81fa0 958 *reason = bgp_path_selection_local_route;
d62a17ae 959 if (debug)
960 zlog_debug(
961 "%s: %s wins over %s due to preferred BGP_ROUTE type",
962 pfx_buf, new_buf, exist_buf);
963 return 1;
964 }
718e3744 965
33c6e933 966 if (!new_origin && exist_origin) {
fdf81fa0 967 *reason = bgp_path_selection_local_route;
d62a17ae 968 if (debug)
969 zlog_debug(
970 "%s: %s loses to %s due to preferred BGP_ROUTE type",
971 pfx_buf, new_buf, exist_buf);
972 return 0;
6811845b 973 }
718e3744 974
da0c0ef7
KM
975 /* Here if these are imported routes then get ultimate pi for
976 * path compare.
977 */
978 new = bgp_get_imported_bpi_ultimate(new);
979 exist = bgp_get_imported_bpi_ultimate(exist);
980 newattr = new->attr;
981 existattr = exist->attr;
982
d62a17ae 983 /* 4. AS path length check. */
892fedb6 984 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 985 int exist_hops = aspath_count_hops(existattr->aspath);
986 int exist_confeds = aspath_count_confeds(existattr->aspath);
987
892fedb6 988 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 989 int aspath_hops;
990
991 aspath_hops = aspath_count_hops(newattr->aspath);
992 aspath_hops += aspath_count_confeds(newattr->aspath);
993
994 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 995 *reason = bgp_path_selection_confed_as_path;
d62a17ae 996 if (debug)
997 zlog_debug(
998 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
999 pfx_buf, new_buf, exist_buf,
1000 aspath_hops,
1001 (exist_hops + exist_confeds));
1002 return 1;
1003 }
1004
1005 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1006 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1007 if (debug)
1008 zlog_debug(
1009 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1010 pfx_buf, new_buf, exist_buf,
1011 aspath_hops,
1012 (exist_hops + exist_confeds));
1013 return 0;
1014 }
1015 } else {
1016 int newhops = aspath_count_hops(newattr->aspath);
1017
1018 if (newhops < exist_hops) {
fdf81fa0 1019 *reason = bgp_path_selection_as_path;
d62a17ae 1020 if (debug)
1021 zlog_debug(
1022 "%s: %s wins over %s due to aspath hopcount %d < %d",
1023 pfx_buf, new_buf, exist_buf,
1024 newhops, exist_hops);
1025 return 1;
1026 }
1027
1028 if (newhops > exist_hops) {
fdf81fa0 1029 *reason = bgp_path_selection_as_path;
d62a17ae 1030 if (debug)
1031 zlog_debug(
1032 "%s: %s loses to %s due to aspath hopcount %d > %d",
1033 pfx_buf, new_buf, exist_buf,
1034 newhops, exist_hops);
1035 return 0;
1036 }
1037 }
1038 }
9fbdd100 1039
d62a17ae 1040 /* 5. Origin check. */
1041 if (newattr->origin < existattr->origin) {
fdf81fa0 1042 *reason = bgp_path_selection_origin;
d62a17ae 1043 if (debug)
1044 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1045 pfx_buf, new_buf, exist_buf,
1046 bgp_origin_long_str[newattr->origin],
1047 bgp_origin_long_str[existattr->origin]);
1048 return 1;
1049 }
718e3744 1050
d62a17ae 1051 if (newattr->origin > existattr->origin) {
fdf81fa0 1052 *reason = bgp_path_selection_origin;
d62a17ae 1053 if (debug)
1054 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1055 pfx_buf, new_buf, exist_buf,
1056 bgp_origin_long_str[newattr->origin],
1057 bgp_origin_long_str[existattr->origin]);
1058 return 0;
1059 }
718e3744 1060
d62a17ae 1061 /* 6. MED check. */
1062 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1063 && aspath_count_hops(existattr->aspath) == 0);
1064 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1065 && aspath_count_confeds(existattr->aspath) > 0
1066 && aspath_count_hops(newattr->aspath) == 0
1067 && aspath_count_hops(existattr->aspath) == 0);
1068
892fedb6
DA
1069 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1070 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1071 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1072 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1073 || internal_as_route) {
1074 new_med = bgp_med_value(new->attr, bgp);
1075 exist_med = bgp_med_value(exist->attr, bgp);
1076
1077 if (new_med < exist_med) {
fdf81fa0 1078 *reason = bgp_path_selection_med;
d62a17ae 1079 if (debug)
1080 zlog_debug(
1081 "%s: %s wins over %s due to MED %d < %d",
1082 pfx_buf, new_buf, exist_buf, new_med,
1083 exist_med);
1084 return 1;
1085 }
8ff56318 1086
d62a17ae 1087 if (new_med > exist_med) {
fdf81fa0 1088 *reason = bgp_path_selection_med;
d62a17ae 1089 if (debug)
1090 zlog_debug(
1091 "%s: %s loses to %s due to MED %d > %d",
1092 pfx_buf, new_buf, exist_buf, new_med,
1093 exist_med);
1094 return 0;
1095 }
1096 }
9fbdd100 1097
8cd3d070
PG
1098 if (exist->sub_type == BGP_ROUTE_IMPORTED) {
1099 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
1100 peer_exist = bpi_ultimate->peer;
1101 } else
1102 peer_exist = exist->peer;
1103
1104 if (new->sub_type == BGP_ROUTE_IMPORTED) {
1105 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
1106 peer_new = bpi_ultimate->peer;
1107 } else
1108 peer_new = new->peer;
1109
d62a17ae 1110 /* 7. Peer type check. */
8cd3d070
PG
1111 new_sort = peer_new->sort;
1112 exist_sort = peer_exist->sort;
d62a17ae 1113
1114 if (new_sort == BGP_PEER_EBGP
1115 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1116 *reason = bgp_path_selection_peer;
d62a17ae 1117 if (debug)
1118 zlog_debug(
1119 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1120 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1121 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1122 return 1;
1123 peer_sort_ret = 1;
d62a17ae 1124 }
718e3744 1125
d62a17ae 1126 if (exist_sort == BGP_PEER_EBGP
1127 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1128 *reason = bgp_path_selection_peer;
d62a17ae 1129 if (debug)
1130 zlog_debug(
1131 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1132 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1133 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1134 return 0;
1135 peer_sort_ret = 0;
d62a17ae 1136 }
8ff56318 1137
d62a17ae 1138 /* 8. IGP metric check. */
1139 newm = existm = 0;
8ff56318 1140
d62a17ae 1141 if (new->extra)
1142 newm = new->extra->igpmetric;
1143 if (exist->extra)
1144 existm = exist->extra->igpmetric;
9fbdd100 1145
d62a17ae 1146 if (newm < existm) {
ee88563a 1147 if (debug && peer_sort_ret < 0)
d62a17ae 1148 zlog_debug(
d588b995 1149 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1150 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1151 igp_metric_ret = 1;
d62a17ae 1152 }
718e3744 1153
d62a17ae 1154 if (newm > existm) {
ee88563a 1155 if (debug && peer_sort_ret < 0)
d62a17ae 1156 zlog_debug(
d588b995 1157 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1158 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1159 igp_metric_ret = 0;
5e242b0d 1160 }
5e242b0d 1161
d62a17ae 1162 /* 9. Same IGP metric. Compare the cluster list length as
1163 representative of IGP hops metric. Rewrite the metric value
1164 pair (newm, existm) with the cluster list length. Prefer the
1165 path with smaller cluster list length. */
1166 if (newm == existm) {
8cd3d070
PG
1167 if (peer_sort_lookup(peer_new) == BGP_PEER_IBGP &&
1168 peer_sort_lookup(peer_exist) == BGP_PEER_IBGP &&
aa53c036 1169 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1170 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1171 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1172
1173 if (newm < existm) {
ee88563a 1174 if (debug && peer_sort_ret < 0)
d62a17ae 1175 zlog_debug(
d588b995 1176 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1177 pfx_buf, new_buf, exist_buf,
1178 newm, existm);
ee88563a 1179 igp_metric_ret = 1;
d62a17ae 1180 }
1181
1182 if (newm > existm) {
ee88563a 1183 if (debug && peer_sort_ret < 0)
d62a17ae 1184 zlog_debug(
d588b995 1185 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1186 pfx_buf, new_buf, exist_buf,
1187 newm, existm);
ee88563a 1188 igp_metric_ret = 0;
d62a17ae 1189 }
1190 }
1191 }
31a4638f 1192
d62a17ae 1193 /* 10. confed-external vs. confed-internal */
1194 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1195 if (new_sort == BGP_PEER_CONFED
1196 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1197 *reason = bgp_path_selection_confed;
d62a17ae 1198 if (debug)
1199 zlog_debug(
1200 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1201 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1202 if (!CHECK_FLAG(bgp->flags,
1203 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1204 return 1;
1205 peer_sort_ret = 1;
d62a17ae 1206 }
718e3744 1207
d62a17ae 1208 if (exist_sort == BGP_PEER_CONFED
1209 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1210 *reason = bgp_path_selection_confed;
d62a17ae 1211 if (debug)
1212 zlog_debug(
1213 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1214 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1215 if (!CHECK_FLAG(bgp->flags,
1216 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1217 return 0;
1218 peer_sort_ret = 0;
d62a17ae 1219 }
1220 }
718e3744 1221
d62a17ae 1222 /* 11. Maximum path check. */
1223 if (newm == existm) {
1224 /* If one path has a label but the other does not, do not treat
1225 * them as equals for multipath
1226 */
d2d71b04 1227 int newl, existl;
1228
1229 newl = existl = 0;
1230
1231 if (new->extra)
1232 newl = new->extra->num_labels;
1233 if (exist->extra)
1234 existl = exist->extra->num_labels;
1235 if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
1236 (exist->extra &&
1237 bgp_is_valid_label(&exist->extra->label[0]))) ||
1238 (newl != existl)) {
d62a17ae 1239 if (debug)
1240 zlog_debug(
1241 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1242 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1243 } else if (CHECK_FLAG(bgp->flags,
1244 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1245
1246 /*
1247 * For the two paths, all comparison steps till IGP
1248 * metric
1249 * have succeeded - including AS_PATH hop count. Since
1250 * 'bgp
1251 * bestpath as-path multipath-relax' knob is on, we
1252 * don't need
1253 * an exact match of AS_PATH. Thus, mark the paths are
1254 * equal.
1255 * That will trigger both these paths to get into the
1256 * multipath
1257 * array.
1258 */
1259 *paths_eq = 1;
1260
1261 if (debug)
1262 zlog_debug(
1263 "%s: %s and %s are equal via multipath-relax",
1264 pfx_buf, new_buf, exist_buf);
8cd3d070 1265 } else if (peer_new->sort == BGP_PEER_IBGP) {
d62a17ae 1266 if (aspath_cmp(new->attr->aspath,
1267 exist->attr->aspath)) {
1268 *paths_eq = 1;
1269
1270 if (debug)
1271 zlog_debug(
1272 "%s: %s and %s are equal via matching aspaths",
1273 pfx_buf, new_buf, exist_buf);
1274 }
8cd3d070 1275 } else if (peer_new->as == peer_exist->as) {
d62a17ae 1276 *paths_eq = 1;
1277
1278 if (debug)
1279 zlog_debug(
1280 "%s: %s and %s are equal via same remote-as",
1281 pfx_buf, new_buf, exist_buf);
1282 }
1283 } else {
1284 /*
1285 * TODO: If unequal cost ibgp multipath is enabled we can
1286 * mark the paths as equal here instead of returning
1287 */
ee88563a
JM
1288
1289 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1290 * if either step 7 or 10 (peer type checks) yielded a winner,
1291 * that result was returned immediately. Returning from step 10
1292 * ignored the return value computed in steps 8 and 9 (IGP
1293 * metric checks). In order to preserve that behavior, if
1294 * peer_sort_ret is set, return that rather than igp_metric_ret.
1295 */
1296 ret = peer_sort_ret;
1297 if (peer_sort_ret < 0) {
1298 ret = igp_metric_ret;
1299 if (debug) {
1300 if (ret == 1)
1301 zlog_debug(
1302 "%s: %s wins over %s after IGP metric comparison",
1303 pfx_buf, new_buf, exist_buf);
1304 else
1305 zlog_debug(
1306 "%s: %s loses to %s after IGP metric comparison",
1307 pfx_buf, new_buf, exist_buf);
1308 }
1309 *reason = bgp_path_selection_igp_metric;
d62a17ae 1310 }
1311 return ret;
1312 }
718e3744 1313
ee88563a
JM
1314 /*
1315 * At this point, the decision whether to set *paths_eq = 1 has been
1316 * completed. If we deferred returning because of bestpath peer-type
1317 * relax configuration, return now.
1318 */
1319 if (peer_sort_ret >= 0)
1320 return peer_sort_ret;
1321
d62a17ae 1322 /* 12. If both paths are external, prefer the path that was received
1323 first (the oldest one). This step minimizes route-flap, since a
1324 newer path won't displace an older one, even if it was the
1325 preferred route based on the additional decision criteria below. */
892fedb6 1326 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1327 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1328 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1329 *reason = bgp_path_selection_older;
d62a17ae 1330 if (debug)
1331 zlog_debug(
1332 "%s: %s wins over %s due to oldest external",
1333 pfx_buf, new_buf, exist_buf);
1334 return 1;
1335 }
9fbdd100 1336
1defdda8 1337 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1338 *reason = bgp_path_selection_older;
d62a17ae 1339 if (debug)
1340 zlog_debug(
1341 "%s: %s loses to %s due to oldest external",
1342 pfx_buf, new_buf, exist_buf);
1343 return 0;
1344 }
1345 }
718e3744 1346
ce5002c6 1347 /* 13. Router-ID comparison. */
d62a17ae 1348 /* If one of the paths is "stale", the corresponding peer router-id will
1349 * be 0 and would always win over the other path. If originator id is
ce5002c6 1350 * used for the comparison, it will decide which path is better.
d62a17ae 1351 */
1352 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1353 new_id.s_addr = newattr->originator_id.s_addr;
1354 else
8cd3d070 1355 new_id.s_addr = peer_new->remote_id.s_addr;
d62a17ae 1356 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1357 exist_id.s_addr = existattr->originator_id.s_addr;
1358 else
8cd3d070 1359 exist_id.s_addr = peer_exist->remote_id.s_addr;
d62a17ae 1360
1361 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1362 *reason = bgp_path_selection_router_id;
d62a17ae 1363 if (debug)
1364 zlog_debug(
1365 "%s: %s wins over %s due to Router-ID comparison",
1366 pfx_buf, new_buf, exist_buf);
1367 return 1;
1368 }
718e3744 1369
d62a17ae 1370 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1371 *reason = bgp_path_selection_router_id;
d62a17ae 1372 if (debug)
1373 zlog_debug(
1374 "%s: %s loses to %s due to Router-ID comparison",
1375 pfx_buf, new_buf, exist_buf);
1376 return 0;
1377 }
9fbdd100 1378
ce5002c6 1379 /* 14. Cluster length comparison. */
d62a17ae 1380 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1381 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1382
1383 if (new_cluster < exist_cluster) {
fdf81fa0 1384 *reason = bgp_path_selection_cluster_length;
d62a17ae 1385 if (debug)
1386 zlog_debug(
1387 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1388 pfx_buf, new_buf, exist_buf, new_cluster,
1389 exist_cluster);
1390 return 1;
1391 }
718e3744 1392
d62a17ae 1393 if (new_cluster > exist_cluster) {
fdf81fa0 1394 *reason = bgp_path_selection_cluster_length;
d62a17ae 1395 if (debug)
1396 zlog_debug(
1397 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1398 pfx_buf, new_buf, exist_buf, new_cluster,
1399 exist_cluster);
1400 return 0;
1401 }
9fbdd100 1402
ce5002c6 1403 /* 15. Neighbor address comparison. */
d62a17ae 1404 /* Do this only if neither path is "stale" as stale paths do not have
1405 * valid peer information (as the connection may or may not be up).
1406 */
1defdda8 1407 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1408 *reason = bgp_path_selection_stale;
d62a17ae 1409 if (debug)
1410 zlog_debug(
1411 "%s: %s wins over %s due to latter path being STALE",
1412 pfx_buf, new_buf, exist_buf);
1413 return 1;
1414 }
0de5153c 1415
1defdda8 1416 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1417 *reason = bgp_path_selection_stale;
d62a17ae 1418 if (debug)
1419 zlog_debug(
1420 "%s: %s loses to %s due to former path being STALE",
1421 pfx_buf, new_buf, exist_buf);
1422 return 0;
1423 }
718e3744 1424
d62a17ae 1425 /* locally configured routes to advertise do not have su_remote */
8cd3d070 1426 if (peer_new->su_remote == NULL) {
fdf81fa0 1427 *reason = bgp_path_selection_local_configured;
d62a17ae 1428 return 0;
8cd3d070 1429 }
cefda028 1430
8cd3d070 1431 if (peer_exist->su_remote == NULL) {
fdf81fa0 1432 *reason = bgp_path_selection_local_configured;
d62a17ae 1433 return 1;
8cd3d070 1434 }
9fbdd100 1435
cefda028 1436 ret = sockunion_cmp(peer_new->su_remote, peer_exist->su_remote);
d62a17ae 1437
1438 if (ret == 1) {
fdf81fa0 1439 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1440 if (debug)
1441 zlog_debug(
1442 "%s: %s loses to %s due to Neighor IP comparison",
1443 pfx_buf, new_buf, exist_buf);
1444 return 0;
1445 }
1446
1447 if (ret == -1) {
fdf81fa0 1448 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1449 if (debug)
1450 zlog_debug(
1451 "%s: %s wins over %s due to Neighor IP comparison",
1452 pfx_buf, new_buf, exist_buf);
1453 return 1;
1454 }
9fbdd100 1455
fdf81fa0 1456 *reason = bgp_path_selection_default;
d62a17ae 1457 if (debug)
1458 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1459 pfx_buf, new_buf, exist_buf);
718e3744 1460
d62a17ae 1461 return 1;
718e3744 1462}
1463
d071f237
AK
1464
1465int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1466 struct bgp_path_info *exist, int *paths_eq)
1467{
1468 enum bgp_path_selection_reason reason;
1469 char pfx_buf[PREFIX2STR_BUFFER];
1470
1471 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1472 AFI_L2VPN, SAFI_EVPN, &reason);
1473}
1474
65efcfce
LB
1475/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1476 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1477 * multipath is enabled
65efcfce 1478 * This version is compatible with */
18ee8310
DS
1479int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1480 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1481 afi_t afi, safi_t safi,
1482 enum bgp_path_selection_reason *reason)
d62a17ae 1483{
1484 int paths_eq;
1485 int ret;
18ee8310 1486 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1487 afi, safi, reason);
d62a17ae 1488
1489 if (paths_eq)
1490 ret = 0;
1491 else {
1492 if (ret == 1)
1493 ret = -1;
1494 else
1495 ret = 1;
1496 }
1497 return ret;
65efcfce
LB
1498}
1499
5a1ae2c2
DS
1500static enum filter_type bgp_input_filter(struct peer *peer,
1501 const struct prefix *p,
d62a17ae 1502 struct attr *attr, afi_t afi,
1503 safi_t safi)
718e3744 1504{
d62a17ae 1505 struct bgp_filter *filter;
6401252f 1506 enum filter_type ret = FILTER_PERMIT;
718e3744 1507
d62a17ae 1508 filter = &peer->filter[afi][safi];
718e3744 1509
d62a17ae 1510#define FILTER_EXIST_WARN(F, f, filter) \
1511 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1512 zlog_debug("%s: Could not find configured input %s-list %s!", \
1513 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1514
1515 if (DISTRIBUTE_IN_NAME(filter)) {
1516 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1517
6401252f
QY
1518 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1519 == FILTER_DENY) {
1520 ret = FILTER_DENY;
1521 goto done;
1522 }
d62a17ae 1523 }
1524
1525 if (PREFIX_LIST_IN_NAME(filter)) {
1526 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1527
6401252f
QY
1528 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1529 == PREFIX_DENY) {
1530 ret = FILTER_DENY;
1531 goto done;
1532 }
d62a17ae 1533 }
1534
1535 if (FILTER_LIST_IN_NAME(filter)) {
1536 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1537
1538 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1539 == AS_FILTER_DENY) {
1540 ret = FILTER_DENY;
1541 goto done;
1542 }
d62a17ae 1543 }
1544
6401252f 1545done:
c7bb4f00 1546 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1547 char pfxprint[PREFIX2STR_BUFFER];
1548
1549 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1550 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1551 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1552 }
1553
1554 return ret;
650f76c2 1555#undef FILTER_EXIST_WARN
718e3744 1556}
1557
b8685f9b
DS
1558static enum filter_type bgp_output_filter(struct peer *peer,
1559 const struct prefix *p,
d62a17ae 1560 struct attr *attr, afi_t afi,
1561 safi_t safi)
718e3744 1562{
d62a17ae 1563 struct bgp_filter *filter;
6401252f 1564 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1565
1566 filter = &peer->filter[afi][safi];
1567
1568#define FILTER_EXIST_WARN(F, f, filter) \
1569 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1570 zlog_debug("%s: Could not find configured output %s-list %s!", \
1571 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1572
d62a17ae 1573 if (DISTRIBUTE_OUT_NAME(filter)) {
1574 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1575
6401252f
QY
1576 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1577 == FILTER_DENY) {
1578 ret = FILTER_DENY;
1579 goto done;
1580 }
d62a17ae 1581 }
1582
1583 if (PREFIX_LIST_OUT_NAME(filter)) {
1584 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1585
d62a17ae 1586 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1587 == PREFIX_DENY) {
1588 ret = FILTER_DENY;
1589 goto done;
1590 }
d62a17ae 1591 }
718e3744 1592
d62a17ae 1593 if (FILTER_LIST_OUT_NAME(filter)) {
1594 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1595
d62a17ae 1596 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1597 == AS_FILTER_DENY) {
1598 ret = FILTER_DENY;
1599 goto done;
1600 }
1601 }
1602
c7bb4f00 1603 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1604 char pfxprint[PREFIX2STR_BUFFER];
1605
1606 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1607 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1608 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1609 }
718e3744 1610
6401252f
QY
1611done:
1612 return ret;
650f76c2 1613#undef FILTER_EXIST_WARN
718e3744 1614}
1615
1616/* If community attribute includes no_export then return 1. */
3dc339cd 1617static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1618{
9a706b42 1619 if (bgp_attr_get_community(attr)) {
d62a17ae 1620 /* NO_ADVERTISE check. */
9a706b42
DA
1621 if (community_include(bgp_attr_get_community(attr),
1622 COMMUNITY_NO_ADVERTISE))
3dc339cd 1623 return true;
d62a17ae 1624
1625 /* NO_EXPORT check. */
9a706b42
DA
1626 if (peer->sort == BGP_PEER_EBGP &&
1627 community_include(bgp_attr_get_community(attr),
1628 COMMUNITY_NO_EXPORT))
3dc339cd 1629 return true;
d62a17ae 1630
1631 /* NO_EXPORT_SUBCONFED check. */
1632 if (peer->sort == BGP_PEER_EBGP
1633 || peer->sort == BGP_PEER_CONFED)
9a706b42 1634 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1635 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1636 return true;
d62a17ae 1637 }
3dc339cd 1638 return false;
718e3744 1639}
1640
1641/* Route reflection loop check. */
3dc339cd 1642static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1643{
d62a17ae 1644 struct in_addr cluster_id;
779fee93 1645 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1646
779fee93 1647 if (cluster) {
d62a17ae 1648 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1649 cluster_id = peer->bgp->cluster_id;
1650 else
1651 cluster_id = peer->bgp->router_id;
1652
779fee93 1653 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1654 return true;
d62a17ae 1655 }
3dc339cd 1656 return false;
718e3744 1657}
6b0655a2 1658
d864dd9e
EB
1659static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1660{
1661 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1662 if (peer->local_role == ROLE_PROVIDER ||
1663 peer->local_role == ROLE_RS_SERVER)
1664 return true;
1665 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1666 return true;
1667 return false;
1668 }
1669 if (peer->local_role == ROLE_CUSTOMER ||
1670 peer->local_role == ROLE_PEER ||
1671 peer->local_role == ROLE_RS_CLIENT) {
1672 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1673 attr->otc = peer->as;
1674 }
1675 return false;
1676}
1677
1678static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1679{
1680 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1681 if (peer->local_role == ROLE_CUSTOMER ||
1682 peer->local_role == ROLE_RS_CLIENT ||
1683 peer->local_role == ROLE_PEER)
1684 return true;
1685 return false;
1686 }
1687 if (peer->local_role == ROLE_PROVIDER ||
1688 peer->local_role == ROLE_PEER ||
1689 peer->local_role == ROLE_RS_SERVER) {
1690 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1691 attr->otc = peer->bgp->as;
1692 }
1693 return false;
1694}
1695
5a78f2bc
EB
1696static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1697{
1698 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1699}
1700
5a1ae2c2 1701static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1702 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1703 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1704 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1705{
d62a17ae 1706 struct bgp_filter *filter;
82b692c0
LK
1707 struct bgp_path_info rmap_path = { 0 };
1708 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1709 route_map_result_t ret;
1710 struct route_map *rmap = NULL;
718e3744 1711
d62a17ae 1712 filter = &peer->filter[afi][safi];
718e3744 1713
d62a17ae 1714 /* Apply default weight value. */
1715 if (peer->weight[afi][safi])
1716 attr->weight = peer->weight[afi][safi];
718e3744 1717
d62a17ae 1718 if (rmap_name) {
1719 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1720
d62a17ae 1721 if (rmap == NULL)
1722 return RMAP_DENY;
1723 } else {
1724 if (ROUTE_MAP_IN_NAME(filter)) {
1725 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1726
d62a17ae 1727 if (rmap == NULL)
1728 return RMAP_DENY;
1729 }
1730 }
0b16f239 1731
d62a17ae 1732 /* Route map apply. */
1733 if (rmap) {
6006b807 1734 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1735 /* Duplicate current value to new structure for modification. */
40381db7
DS
1736 rmap_path.peer = peer;
1737 rmap_path.attr = attr;
82b692c0 1738 rmap_path.extra = &extra;
9bcb3eef 1739 rmap_path.net = dest;
196c6b09 1740
82b692c0
LK
1741 extra.num_labels = num_labels;
1742 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1743 memcpy(extra.label, label,
1744 num_labels * sizeof(mpls_label_t));
718e3744 1745
d62a17ae 1746 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1747
d62a17ae 1748 /* Apply BGP route map to the attribute. */
1782514f 1749 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1750
d62a17ae 1751 peer->rmap_type = 0;
0b16f239 1752
1f2263be 1753 if (ret == RMAP_DENYMATCH)
d62a17ae 1754 return RMAP_DENY;
0b16f239 1755 }
d62a17ae 1756 return RMAP_PERMIT;
0b16f239
DS
1757}
1758
5f040085 1759static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1760 struct attr *attr, afi_t afi, safi_t safi,
1761 const char *rmap_name)
0b16f239 1762{
40381db7 1763 struct bgp_path_info rmap_path;
d62a17ae 1764 route_map_result_t ret;
1765 struct route_map *rmap = NULL;
d7c0a89a 1766 uint8_t rmap_type;
0b16f239 1767
b787157a
DS
1768 /*
1769 * So if we get to this point and have no rmap_name
1770 * we want to just show the output as it currently
1771 * exists.
1772 */
1773 if (!rmap_name)
1774 return RMAP_PERMIT;
0b16f239 1775
d62a17ae 1776 /* Apply default weight value. */
1777 if (peer->weight[afi][safi])
1778 attr->weight = peer->weight[afi][safi];
0b16f239 1779
b787157a 1780 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1781
b787157a
DS
1782 /*
1783 * If we have a route map name and we do not find
1784 * the routemap that means we have an implicit
1785 * deny.
1786 */
1787 if (rmap == NULL)
1788 return RMAP_DENY;
0b16f239 1789
6006b807 1790 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1791 /* Route map apply. */
544be979 1792 /* Duplicate current value to new structure for modification. */
40381db7
DS
1793 rmap_path.peer = peer;
1794 rmap_path.attr = attr;
0b16f239 1795
0f672529 1796 rmap_type = peer->rmap_type;
b787157a 1797 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1798
b787157a 1799 /* Apply BGP route map to the attribute. */
1782514f 1800 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1801
0f672529 1802 peer->rmap_type = rmap_type;
b787157a
DS
1803
1804 if (ret == RMAP_DENYMATCH)
1805 /*
1806 * caller has multiple error paths with bgp_attr_flush()
1807 */
1808 return RMAP_DENY;
ac41b2a2 1809
d62a17ae 1810 return RMAP_PERMIT;
718e3744 1811}
6b0655a2 1812
5000f21c 1813/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1814static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1815 struct peer *peer, struct attr *attr)
1816{
1817 if (peer->sort == BGP_PEER_EBGP
1818 && (peer_af_flag_check(peer, afi, safi,
1819 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1820 || peer_af_flag_check(peer, afi, safi,
1821 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1822 || peer_af_flag_check(peer, afi, safi,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1824 || peer_af_flag_check(peer, afi, safi,
1825 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1826 // Take action on the entire aspath
1827 if (peer_af_flag_check(peer, afi, safi,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1829 || peer_af_flag_check(peer, afi, safi,
1830 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1831 if (peer_af_flag_check(
1832 peer, afi, safi,
1833 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1834 attr->aspath = aspath_replace_private_asns(
bf26b80e 1835 attr->aspath, bgp->as, peer->as);
d62a17ae 1836
179d5a0e
TA
1837 /*
1838 * Even if the aspath consists of just private ASNs we
1839 * need to walk the AS-Path to maintain all instances
1840 * of the peer's ASN to break possible loops.
1841 */
d62a17ae 1842 else
1843 attr->aspath = aspath_remove_private_asns(
bf26b80e 1844 attr->aspath, peer->as);
d62a17ae 1845 }
1846
1847 // 'all' was not specified so the entire aspath must be private
1848 // ASNs
1849 // for us to do anything
1850 else if (aspath_private_as_check(attr->aspath)) {
1851 if (peer_af_flag_check(
1852 peer, afi, safi,
1853 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1854 attr->aspath = aspath_replace_private_asns(
bf26b80e 1855 attr->aspath, bgp->as, peer->as);
d62a17ae 1856 else
179d5a0e
TA
1857 /*
1858 * Walk the aspath to retain any instances of
1859 * the peer_asn
1860 */
1861 attr->aspath = aspath_remove_private_asns(
1862 attr->aspath, peer->as);
d62a17ae 1863 }
1864 }
5000f21c
DS
1865}
1866
c7122e14 1867/* If this is an EBGP peer with as-override */
d62a17ae 1868static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1869 struct peer *peer, struct attr *attr)
1870{
bbe7bc46
DA
1871 struct aspath *aspath;
1872
9bbdb457 1873 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1874 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1875 if (attr->aspath->refcnt)
1876 aspath = aspath_dup(attr->aspath);
1877 else
1878 aspath = attr->aspath;
1879
1880 attr->aspath = aspath_intern(
1881 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1882
1883 aspath_free(aspath);
1884 }
d62a17ae 1885}
1886
1479ed2f
DA
1887void bgp_attr_add_llgr_community(struct attr *attr)
1888{
1889 struct community *old;
1890 struct community *new;
1891 struct community *merge;
1892 struct community *llgr;
1893
9a706b42 1894 old = bgp_attr_get_community(attr);
1479ed2f
DA
1895 llgr = community_str2com("llgr-stale");
1896
1897 assert(llgr);
1898
1899 if (old) {
1900 merge = community_merge(community_dup(old), llgr);
1901
1902 if (old->refcnt == 0)
1903 community_free(&old);
1904
1905 new = community_uniq_sort(merge);
1906 community_free(&merge);
1907 } else {
1908 new = community_dup(llgr);
1909 }
1910
1911 community_free(&llgr);
1912
9a706b42 1913 bgp_attr_set_community(attr, new);
1479ed2f
DA
1914}
1915
7f323236
DW
1916void bgp_attr_add_gshut_community(struct attr *attr)
1917{
1918 struct community *old;
1919 struct community *new;
1920 struct community *merge;
1921 struct community *gshut;
1922
9a706b42 1923 old = bgp_attr_get_community(attr);
7f323236
DW
1924 gshut = community_str2com("graceful-shutdown");
1925
990f4f91 1926 assert(gshut);
1927
7f323236
DW
1928 if (old) {
1929 merge = community_merge(community_dup(old), gshut);
1930
a4d82a8a 1931 if (old->refcnt == 0)
3c1f53de 1932 community_free(&old);
7f323236
DW
1933
1934 new = community_uniq_sort(merge);
3c1f53de 1935 community_free(&merge);
7f323236
DW
1936 } else {
1937 new = community_dup(gshut);
1938 }
1939
3c1f53de 1940 community_free(&gshut);
9a706b42 1941 bgp_attr_set_community(attr, new);
7f323236
DW
1942
1943 /* When we add the graceful-shutdown community we must also
1944 * lower the local-preference */
1945 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1946 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1947}
1948
1949
e73c112e
MK
1950/* Notify BGP Conditional advertisement scanner process. */
1951void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1952{
e73c112e 1953 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1954 afi_t afi = SUBGRP_AFI(subgrp);
1955 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1956 struct bgp_filter *filter = &peer->filter[afi][safi];
1957
1958 if (!ADVERTISE_MAP_NAME(filter))
1959 return;
1960
52979c3b
DS
1961 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1962 return;
e73c112e 1963
52979c3b 1964 peer->advmap_table_change = true;
e73c112e
MK
1965}
1966
1967
f2ee6d5c 1968void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1969{
960035b2 1970 if (family == AF_INET) {
975a328e
DA
1971 attr->nexthop.s_addr = INADDR_ANY;
1972 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1973 }
d62a17ae 1974 if (family == AF_INET6)
1975 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1976 if (family == AF_EVPN)
1977 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1978}
1979
9bcb3eef 1980bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1981 struct update_subgroup *subgrp,
7f7940e6 1982 const struct prefix *p, struct attr *attr,
51c3a7de 1983 struct attr *post_attr)
d62a17ae 1984{
1985 struct bgp_filter *filter;
1986 struct peer *from;
1987 struct peer *peer;
1988 struct peer *onlypeer;
1989 struct bgp *bgp;
40381db7 1990 struct attr *piattr;
b68885f9 1991 route_map_result_t ret;
d62a17ae 1992 int transparent;
1993 int reflect;
1994 afi_t afi;
1995 safi_t safi;
1996 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1997 bool nh_reset = false;
1998 uint64_t cum_bw;
d62a17ae 1999
2000 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 2001 return false;
d62a17ae 2002
2003 afi = SUBGRP_AFI(subgrp);
2004 safi = SUBGRP_SAFI(subgrp);
2005 peer = SUBGRP_PEER(subgrp);
2006 onlypeer = NULL;
2007 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2008 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2009
40381db7 2010 from = pi->peer;
d62a17ae 2011 filter = &peer->filter[afi][safi];
2012 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2013 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2014 : pi->attr;
3f9c7369 2015
d0bf49ec
LS
2016 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2017 peer->pmax_out[afi][safi] != 0 &&
2018 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2019 if (BGP_DEBUG(update, UPDATE_OUT) ||
2020 BGP_DEBUG(update, UPDATE_PREFIX)) {
2021 zlog_debug("%s reached maximum prefix to be send (%u)",
2022 peer->host, peer->pmax_out[afi][safi]);
2023 }
2024 return false;
2025 }
2026
49e5a4a0 2027#ifdef ENABLE_BGP_VNC
d62a17ae 2028 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2029 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2030 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2031
2032 /*
2033 * direct and direct_ext type routes originate internally even
2034 * though they can have peer pointers that reference other
2035 * systems
2036 */
8228a9a7
DS
2037 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2038 __func__, p);
d62a17ae 2039 samepeer_safe = 1;
2040 }
65efcfce
LB
2041#endif
2042
ddb5b488
PZ
2043 if (((afi == AFI_IP) || (afi == AFI_IP6))
2044 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2045 && (pi->type == ZEBRA_ROUTE_BGP)
2046 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2047
2048 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2049
2050 samepeer_safe = 1;
2051 }
2052
d62a17ae 2053 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2054 * pi is valid */
2055 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2056 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2057 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2058 return false;
d62a17ae 2059 }
adbac85e 2060
d62a17ae 2061 /* If this is not the bestpath then check to see if there is an enabled
2062 * addpath
2063 * feature that requires us to advertise it */
8ccee4b8
DA
2064 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2065 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2066 return false;
06370dac 2067
d62a17ae 2068 /* Aggregate-address suppress check. */
4056a5f6
RZ
2069 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2070 return false;
3f9c7369 2071
13b7e7f0
DS
2072 /*
2073 * If we are doing VRF 2 VRF leaking via the import
2074 * statement, we want to prevent the route going
2075 * off box as that the RT and RD created are localy
2076 * significant and globaly useless.
2077 */
40381db7
DS
2078 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2079 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2080 return false;
13b7e7f0 2081
d62a17ae 2082 /* If it's labeled safi, make sure the route has a valid label. */
2083 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2084 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2085 if (!bgp_is_valid_label(&label)) {
2086 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2087 zlog_debug("u%" PRIu64 ":s%" PRIu64
2088 " %pFX is filtered - no label (%p)",
d62a17ae 2089 subgrp->update_group->id, subgrp->id,
8228a9a7 2090 p, &label);
3dc339cd 2091 return false;
d62a17ae 2092 }
2093 }
cd1964ff 2094
d62a17ae 2095 /* Do not send back route to sender. */
2096 if (onlypeer && from == onlypeer) {
3dc339cd 2097 return false;
d62a17ae 2098 }
3f9c7369 2099
d62a17ae 2100 /* Do not send the default route in the BGP table if the neighbor is
2101 * configured for default-originate */
2102 if (CHECK_FLAG(peer->af_flags[afi][safi],
2103 PEER_FLAG_DEFAULT_ORIGINATE)) {
2104 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2105 return false;
d62a17ae 2106 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2107 return false;
d62a17ae 2108 }
4125bb67 2109
d62a17ae 2110 /* Transparency check. */
2111 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2112 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2113 transparent = 1;
2114 else
2115 transparent = 0;
2116
2117 /* If community is not disabled check the no-export and local. */
40381db7 2118 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2119 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2120 zlog_debug("%s: community filter check fail for %pFX",
2121 __func__, p);
3dc339cd 2122 return false;
d62a17ae 2123 }
3f9c7369 2124
d62a17ae 2125 /* If the attribute has originator-id and it is same as remote
2126 peer's id. */
40381db7
DS
2127 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2128 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2129 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2130 zlog_debug(
a9f3f4f5
DA
2131 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2132 onlypeer, p);
3dc339cd 2133 return false;
d62a17ae 2134 }
3f9c7369 2135
d62a17ae 2136 /* ORF prefix-list filter check */
2137 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2138 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2139 || CHECK_FLAG(peer->af_cap[afi][safi],
2140 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2141 if (peer->orf_plist[afi][safi]) {
2142 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2143 == PREFIX_DENY) {
2144 if (bgp_debug_update(NULL, p,
2145 subgrp->update_group, 0))
2146 zlog_debug(
a9f3f4f5
DA
2147 "%pBP [Update:SEND] %pFX is filtered via ORF",
2148 peer, p);
3dc339cd 2149 return false;
d62a17ae 2150 }
2151 }
2152
2153 /* Output filter check. */
40381db7 2154 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2155 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2156 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2157 p);
3dc339cd 2158 return false;
d62a17ae 2159 }
3f9c7369 2160
d62a17ae 2161 /* AS path loop check. */
25851bf0
DA
2162 if (peer->as_path_loop_detection &&
2163 aspath_loop_check(piattr->aspath, peer->as)) {
d62a17ae 2164 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2165 zlog_debug(
a9f3f4f5 2166 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
25851bf0 2167 peer, peer->as);
3dc339cd 2168 return false;
d62a17ae 2169 }
3f9c7369 2170
d62a17ae 2171 /* If we're a CONFED we need to loop check the CONFED ID too */
2172 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2173 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2174 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2175 zlog_debug(
a9f3f4f5
DA
2176 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2177 peer, bgp->confed_id);
3dc339cd 2178 return false;
d62a17ae 2179 }
3f9c7369 2180 }
3f9c7369 2181
d62a17ae 2182 /* Route-Reflect check. */
2183 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2184 reflect = 1;
2185 else
2186 reflect = 0;
2187
2188 /* IBGP reflection check. */
2189 if (reflect && !samepeer_safe) {
2190 /* A route from a Client peer. */
2191 if (CHECK_FLAG(from->af_flags[afi][safi],
2192 PEER_FLAG_REFLECTOR_CLIENT)) {
2193 /* Reflect to all the Non-Client peers and also to the
2194 Client peers other than the originator. Originator
2195 check
2196 is already done. So there is noting to do. */
2197 /* no bgp client-to-client reflection check. */
892fedb6
DA
2198 if (CHECK_FLAG(bgp->flags,
2199 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2200 if (CHECK_FLAG(peer->af_flags[afi][safi],
2201 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2202 return false;
d62a17ae 2203 } else {
2204 /* A route from a Non-client peer. Reflect to all other
2205 clients. */
2206 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2207 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2208 return false;
d62a17ae 2209 }
2210 }
3f9c7369 2211
51c3a7de
DA
2212 /* For modify attribute, copy it to temporary structure.
2213 * post_attr comes from BGP conditional advertisements, where
2214 * attributes are already processed by advertise-map route-map,
2215 * and this needs to be saved instead of overwriting from the
2216 * path attributes.
2217 */
2218 if (post_attr)
2219 *attr = *post_attr;
2220 else
2221 *attr = *piattr;
d62a17ae 2222
2223 /* If local-preference is not set. */
2224 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2225 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2226 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2227 attr->local_pref = bgp->default_local_pref;
3f9c7369 2228 }
3f9c7369 2229
d62a17ae 2230 /* If originator-id is not set and the route is to be reflected,
2231 set the originator id */
2232 if (reflect
2233 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2234 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2235 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2236 }
3f9c7369 2237
d62a17ae 2238 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2239 */
2240 if (peer->sort == BGP_PEER_EBGP
2241 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2242 if (from != bgp->peer_self && !transparent
2243 && !CHECK_FLAG(peer->af_flags[afi][safi],
2244 PEER_FLAG_MED_UNCHANGED))
2245 attr->flag &=
2246 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2247 }
3f9c7369 2248
d62a17ae 2249 /* Since the nexthop attribute can vary per peer, it is not explicitly
2250 * set
2251 * in announce check, only certain flags and length (or number of
2252 * nexthops
2253 * -- for IPv6/MP_REACH) are set here in order to guide the update
2254 * formation
2255 * code in setting the nexthop(s) on a per peer basis in
2256 * reformat_peer().
2257 * Typically, the source nexthop in the attribute is preserved but in
2258 * the
2259 * scenarios where we know it will always be overwritten, we reset the
2260 * nexthop to "0" in an attempt to achieve better Update packing. An
2261 * example of this is when a prefix from each of 2 IBGP peers needs to
2262 * be
2263 * announced to an EBGP peer (and they have the same attributes barring
2264 * their nexthop).
2265 */
2266 if (reflect)
2267 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2268
2269#define NEXTHOP_IS_V6 \
2270 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2271 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2272 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2273 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2274
2275 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2276 * if
2277 * the peer (group) is configured to receive link-local nexthop
2278 * unchanged
c728d027
DA
2279 * and it is available in the prefix OR we're not reflecting the route,
2280 * link-local nexthop address is valid and
d62a17ae 2281 * the peer (group) to whom we're going to announce is on a shared
2282 * network
2283 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2284 * By checking if nexthop LL address is valid we are sure that
2285 * we do not announce LL address as `::`.
d62a17ae 2286 */
2287 if (NEXTHOP_IS_V6) {
2288 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2289 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2291 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2292 || (!reflect && !transparent
c728d027
DA
2293 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2294 && peer->shared_network
d62a17ae 2295 && (from == bgp->peer_self
2296 || peer->sort == BGP_PEER_EBGP))) {
f7a0eb6a
PG
2297 if (safi == SAFI_MPLS_VPN)
2298 attr->mp_nexthop_len =
2299 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2300 else
2301 attr->mp_nexthop_len =
2302 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 2303 }
3f9c7369 2304
d62a17ae 2305 /* Clear off link-local nexthop in source, whenever it is not
2306 * needed to
2307 * ensure more prefixes share the same attribute for
2308 * announcement.
2309 */
2310 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2311 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2312 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2313 }
3f9c7369 2314
5a78f2bc
EB
2315 if (bgp_check_role_applicability(afi, safi) &&
2316 bgp_otc_egress(peer, attr))
d864dd9e
EB
2317 return false;
2318
d62a17ae 2319 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2320 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2321
0655090c
QY
2322 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2323 filter->advmap.aname &&
2324 route_map_lookup_by_name(filter->advmap.aname)) {
2325 struct bgp_path_info rmap_path = {0};
2326 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2327 struct attr dummy_attr = *attr;
2328
2329 /* Fill temp path_info */
2330 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2331 pi, peer, &dummy_attr);
2332
2333 struct route_map *amap =
2334 route_map_lookup_by_name(filter->advmap.aname);
2335
2336 ret = route_map_apply(amap, p, &rmap_path);
2337
2338 bgp_attr_flush(&dummy_attr);
2339
2340 /*
2341 * The conditional advertisement mode is Withdraw and this
2342 * prefix is a conditional prefix. Don't advertise it
2343 */
2344 if (ret == RMAP_PERMITMATCH)
2345 return false;
2346 }
2347
d62a17ae 2348 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2349 if (!post_attr &&
2350 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2351 struct bgp_path_info rmap_path = {0};
2352 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2353 struct attr dummy_attr = {0};
d62a17ae 2354
e34291b8 2355 /* Fill temp path_info */
9bcb3eef
DS
2356 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2357 pi, peer, attr);
16f7ce2b 2358
d62a17ae 2359 /* don't confuse inbound and outbound setting */
2360 RESET_FLAG(attr->rmap_change_flags);
2361
2362 /*
2363 * The route reflector is not allowed to modify the attributes
2364 * of the reflected IBGP routes unless explicitly allowed.
2365 */
2366 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2367 && !CHECK_FLAG(bgp->flags,
2368 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2369 dummy_attr = *attr;
40381db7 2370 rmap_path.attr = &dummy_attr;
d62a17ae 2371 }
3f9c7369 2372
d62a17ae 2373 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2374
4056a5f6 2375 if (bgp_path_suppressed(pi))
d62a17ae 2376 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2377 &rmap_path);
d62a17ae 2378 else
2379 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2380 &rmap_path);
d62a17ae 2381
7e7639f5 2382 bgp_attr_flush(&dummy_attr);
d62a17ae 2383 peer->rmap_type = 0;
2384
2385 if (ret == RMAP_DENYMATCH) {
778048bf 2386 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2387 zlog_debug(
a9f3f4f5 2388 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
8e8ed2e1
DS
2389 peer, p,
2390 bgp_path_suppressed(pi)
2391 ? UNSUPPRESS_MAP_NAME(filter)
2392 : ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2393 bgp_attr_flush(rmap_path.attr);
3dc339cd 2394 return false;
d62a17ae 2395 }
3f9c7369 2396 }
3f9c7369 2397
9dac9fc8
DA
2398 /* RFC 8212 to prevent route leaks.
2399 * This specification intends to improve this situation by requiring the
2400 * explicit configuration of both BGP Import and Export Policies for any
2401 * External BGP (EBGP) session such as customers, peers, or
2402 * confederation boundaries for all enabled address families. Through
2403 * codification of the aforementioned requirement, operators will
2404 * benefit from consistent behavior across different BGP
2405 * implementations.
2406 */
1d3fdccf 2407 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2408 if (!bgp_outbound_policy_exists(peer, filter)) {
2409 if (monotime_since(&bgp->ebgprequirespolicywarning,
2410 NULL) > FIFTEENMINUTE2USEC ||
2411 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2412 zlog_warn(
2413 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2414 monotime(&bgp->ebgprequirespolicywarning);
2415 }
3dc339cd 2416 return false;
b17826b7 2417 }
9dac9fc8 2418
fb29348a
DA
2419 /* draft-ietf-idr-deprecate-as-set-confed-set
2420 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2421 * Eventually, This document (if approved) updates RFC 4271
2422 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2423 * and obsoletes RFC 6472.
2424 */
7f972cd8 2425 if (peer->bgp->reject_as_sets)
fb29348a 2426 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2427 return false;
fb29348a 2428
8c4d4624 2429 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2430 * SoO extended community and validate against the configured
2431 * one. If they match, do not announce, to prevent routing
2432 * loops.
2433 */
2434 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2435 peer->soo[afi][safi]) {
2436 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2437 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2438
2439 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2440 ECOMMUNITY_SITE_ORIGIN) ||
2441 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2442 ECOMMUNITY_SITE_ORIGIN) ||
2443 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2444 ECOMMUNITY_SITE_ORIGIN)) &&
2445 ecommunity_include(ecomm, ecomm_soo)) {
2446 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2447 zlog_debug(
2448 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2449 peer, p, ecommunity_str(ecomm_soo));
2450 return false;
2451 }
2452 }
2453
33d022bc
DA
2454 /* Codification of AS 0 Processing */
2455 if (aspath_check_as_zero(attr->aspath))
e2369003 2456 return false;
33d022bc 2457
637e5ba4 2458 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2459 if (peer->sort == BGP_PEER_IBGP
2460 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2461 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2462 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2463 } else {
2464 bgp_attr_add_gshut_community(attr);
2465 }
2466 }
2467
1479ed2f
DA
2468 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2469 * Capability" to a neighbor MUST perform the following upon receiving
2470 * a route from that neighbor with the "LLGR_STALE" community, or upon
2471 * attaching the "LLGR_STALE" community itself per Section 4.2:
2472 *
2473 * The route SHOULD NOT be advertised to any neighbor from which the
2474 * Long-lived Graceful Restart Capability has not been received.
2475 */
9a706b42
DA
2476 if (bgp_attr_get_community(attr) &&
2477 community_include(bgp_attr_get_community(attr),
2478 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2479 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2480 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2481 return false;
2482
d62a17ae 2483 /* After route-map has been applied, we check to see if the nexthop to
2484 * be carried in the attribute (that is used for the announcement) can
2485 * be cleared off or not. We do this in all cases where we would be
2486 * setting the nexthop to "ourselves". For IPv6, we only need to
2487 * consider
2488 * the global nexthop here; the link-local nexthop would have been
2489 * cleared
2490 * already, and if not, it is required by the update formation code.
2491 * Also see earlier comments in this function.
2492 */
2493 /*
2494 * If route-map has performed some operation on the nexthop or the peer
2495 * configuration says to pass it unchanged, we cannot reset the nexthop
2496 * here, so only attempt to do it if these aren't true. Note that the
2497 * route-map handler itself might have cleared the nexthop, if for
2498 * example,
2499 * it is configured as 'peer-address'.
2500 */
2501 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2502 piattr->rmap_change_flags)
d62a17ae 2503 && !transparent
2504 && !CHECK_FLAG(peer->af_flags[afi][safi],
2505 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2506 /* We can reset the nexthop, if setting (or forcing) it to
2507 * 'self' */
2508 if (CHECK_FLAG(peer->af_flags[afi][safi],
2509 PEER_FLAG_NEXTHOP_SELF)
2510 || CHECK_FLAG(peer->af_flags[afi][safi],
2511 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2512 if (!reflect
2513 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2514 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2515 subgroup_announce_reset_nhop(
2516 (peer_cap_enhe(peer, afi, safi)
2517 ? AF_INET6
2518 : p->family),
2519 attr);
7b651a32 2520 nh_reset = true;
2521 }
d62a17ae 2522 } else if (peer->sort == BGP_PEER_EBGP) {
2523 /* Can also reset the nexthop if announcing to EBGP, but
2524 * only if
2525 * no peer in the subgroup is on a shared subnet.
2526 * Note: 3rd party nexthop currently implemented for
2527 * IPv4 only.
2528 */
737af885
BS
2529 if ((p->family == AF_INET) &&
2530 (!bgp_subgrp_multiaccess_check_v4(
2531 piattr->nexthop,
7b651a32 2532 subgrp, from))) {
d62a17ae 2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2535 ? AF_INET6
2536 : p->family),
737af885 2537 attr);
7b651a32 2538 nh_reset = true;
2539 }
737af885
BS
2540
2541 if ((p->family == AF_INET6) &&
2542 (!bgp_subgrp_multiaccess_check_v6(
2543 piattr->mp_nexthop_global,
7b651a32 2544 subgrp, from))) {
737af885
BS
2545 subgroup_announce_reset_nhop(
2546 (peer_cap_enhe(peer, afi, safi)
2547 ? AF_INET6
2548 : p->family),
2549 attr);
7b651a32 2550 nh_reset = true;
2551 }
737af885
BS
2552
2553
2554
40381db7 2555 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2556 /*
2557 * This flag is used for leaked vpn-vrf routes
2558 */
2559 int family = p->family;
2560
2561 if (peer_cap_enhe(peer, afi, safi))
2562 family = AF_INET6;
2563
2564 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2565 zlog_debug(
6cf8a4bf
DA
2566 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2567 __func__, p, family2str(family));
960035b2 2568 subgroup_announce_reset_nhop(family, attr);
7b651a32 2569 nh_reset = true;
d62a17ae 2570 }
63696f1d 2571 }
960035b2 2572
63696f1d 2573 /* If IPv6/MP and nexthop does not have any override and happens
2574 * to
2575 * be a link-local address, reset it so that we don't pass along
2576 * the
2577 * source's link-local IPv6 address to recipients who may not be
2578 * on
2579 * the same interface.
2580 */
2581 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2582 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2583 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2584 nh_reset = true;
2585 }
d62a17ae 2586 }
3f9c7369 2587
7b27cf7b
DA
2588 /* If this is an iBGP, send Origin Validation State (OVS)
2589 * extended community (rfc8097).
2590 */
2591 if (peer->sort == BGP_PEER_IBGP) {
2592 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2593
2594 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2595
2596 if (rpki_state != RPKI_NOT_BEING_USED)
2597 bgp_attr_set_ecommunity(
2598 attr, ecommunity_add_origin_validation_state(
2599 rpki_state,
2600 bgp_attr_get_ecommunity(attr)));
2601 }
2602
7b651a32 2603 /*
2604 * When the next hop is set to ourselves, if all multipaths have
2605 * link-bandwidth announce the cumulative bandwidth as that makes
2606 * the most sense. However, don't modify if the link-bandwidth has
2607 * been explicitly set by user policy.
2608 */
2609 if (nh_reset &&
f7e1c681 2610 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2611 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2612 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2613 bgp_attr_set_ecommunity(
2614 attr,
2615 ecommunity_replace_linkbw(
2616 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2617 CHECK_FLAG(
2618 peer->flags,
2619 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2620
3dc339cd 2621 return true;
3f9c7369
DS
2622}
2623
e6685141 2624static void bgp_route_select_timer_expire(struct event *thread)
f009ff26 2625{
2626 struct afi_safi_info *info;
2627 afi_t afi;
2628 safi_t safi;
2629 struct bgp *bgp;
2630
e16d030c 2631 info = EVENT_ARG(thread);
f009ff26 2632 afi = info->afi;
2633 safi = info->safi;
2634 bgp = info->bgp;
2635
f009ff26 2636 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2637 XFREE(MTYPE_TMP, info);
2638
2639 /* Best path selection */
cc9f21da 2640 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2641}
2642
9bcb3eef 2643void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2644 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2645 struct bgp_path_info_pair *result, afi_t afi,
2646 safi_t safi)
2647{
2648 struct bgp_path_info *new_select;
2649 struct bgp_path_info *old_select;
40381db7
DS
2650 struct bgp_path_info *pi;
2651 struct bgp_path_info *pi1;
2652 struct bgp_path_info *pi2;
2653 struct bgp_path_info *nextpi = NULL;
d62a17ae 2654 int paths_eq, do_mpath, debug;
2655 struct list mp_list;
2656 char pfx_buf[PREFIX2STR_BUFFER];
2657 char path_buf[PATH_ADDPATH_STR_BUFFER];
2658
2659 bgp_mp_list_init(&mp_list);
2660 do_mpath =
2661 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2662
9bcb3eef 2663 debug = bgp_debug_bestpath(dest);
d62a17ae 2664
2665 if (debug)
9bcb3eef 2666 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2667
9bcb3eef 2668 dest->reason = bgp_path_selection_none;
d62a17ae 2669 /* bgp deterministic-med */
2670 new_select = NULL;
892fedb6 2671 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2672
1defdda8 2673 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2674 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2675 pi1 = pi1->next)
9bcb3eef 2676 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2677 BGP_PATH_DMED_SELECTED);
d62a17ae 2678
9bcb3eef 2679 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2680 pi1 = pi1->next) {
40381db7 2681 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2682 continue;
40381db7 2683 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2684 continue;
de692a4e 2685 if (pi1->peer != bgp->peer_self &&
2686 !CHECK_FLAG(pi1->peer->sflags,
2687 PEER_STATUS_NSF_WAIT)) {
feb17238 2688 if (!peer_established(pi1->peer))
d62a17ae 2689 continue;
de692a4e 2690 }
d62a17ae 2691
40381db7
DS
2692 new_select = pi1;
2693 if (pi1->next) {
2694 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2695 if (CHECK_FLAG(pi2->flags,
1defdda8 2696 BGP_PATH_DMED_CHECK))
d62a17ae 2697 continue;
40381db7 2698 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2699 continue;
ea8b2282 2700 if (pi2->peer != bgp->peer_self
d62a17ae 2701 && !CHECK_FLAG(
ea8b2282
DS
2702 pi2->peer->sflags,
2703 PEER_STATUS_NSF_WAIT))
40381db7 2704 if (pi2->peer->status
d62a17ae 2705 != Established)
2706 continue;
2707
121e245d
DS
2708 if (!aspath_cmp_left(pi1->attr->aspath,
2709 pi2->attr->aspath)
2710 && !aspath_cmp_left_confed(
40381db7 2711 pi1->attr->aspath,
121e245d
DS
2712 pi2->attr->aspath))
2713 continue;
d62a17ae 2714
121e245d
DS
2715 if (bgp_path_info_cmp(
2716 bgp, pi2, new_select,
2717 &paths_eq, mpath_cfg, debug,
fdf81fa0 2718 pfx_buf, afi, safi,
9bcb3eef 2719 &dest->reason)) {
121e245d 2720 bgp_path_info_unset_flag(
9bcb3eef 2721 dest, new_select,
121e245d
DS
2722 BGP_PATH_DMED_SELECTED);
2723 new_select = pi2;
d62a17ae 2724 }
121e245d
DS
2725
2726 bgp_path_info_set_flag(
9bcb3eef 2727 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2728 }
2729 }
9bcb3eef 2730 bgp_path_info_set_flag(dest, new_select,
18ee8310 2731 BGP_PATH_DMED_CHECK);
9bcb3eef 2732 bgp_path_info_set_flag(dest, new_select,
18ee8310 2733 BGP_PATH_DMED_SELECTED);
d62a17ae 2734
2735 if (debug) {
18ee8310 2736 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2737 new_select, path_buf, sizeof(path_buf));
8228a9a7 2738 zlog_debug(
4378495a
DS
2739 "%pBD(%s): %s is the bestpath from AS %u",
2740 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2741 aspath_get_first_as(
2742 new_select->attr->aspath));
d62a17ae 2743 }
2744 }
2745 }
96450faf 2746
d62a17ae 2747 /* Check old selected route and new selected route. */
2748 old_select = NULL;
2749 new_select = NULL;
9bcb3eef 2750 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2751 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2752 enum bgp_path_selection_reason reason;
2753
40381db7
DS
2754 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2755 old_select = pi;
d62a17ae 2756
40381db7 2757 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2758 /* reap REMOVED routes, if needs be
2759 * selected route must stay for a while longer though
2760 */
40381db7
DS
2761 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2762 && (pi != old_select))
9bcb3eef 2763 bgp_path_info_reap(dest, pi);
d62a17ae 2764
ddb5b488 2765 if (debug)
7fd8ca9a
DS
2766 zlog_debug(
2767 "%s: %pBD(%s) pi from %s in holddown",
2768 __func__, dest, bgp->name_pretty,
2769 pi->peer->host);
ddb5b488 2770
d62a17ae 2771 continue;
2772 }
96450faf 2773
40381db7
DS
2774 if (pi->peer && pi->peer != bgp->peer_self
2775 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2776 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2777
2778 if (debug)
2779 zlog_debug(
7fd8ca9a
DS
2780 "%s: %pBD(%s) non self peer %s not estab state",
2781 __func__, dest,
2782 bgp->name_pretty,
2783 pi->peer->host);
ddb5b488 2784
d62a17ae 2785 continue;
ddb5b488 2786 }
9fbdd100 2787
892fedb6 2788 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2789 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2790 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2791 if (debug)
7fd8ca9a
DS
2792 zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
2793 dest, bgp->name_pretty,
2794 pi->peer->host);
d62a17ae 2795 continue;
2796 }
9fbdd100 2797
9bcb3eef 2798 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2799
9bcb3eef 2800 reason = dest->reason;
40381db7 2801 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2802 debug, pfx_buf, afi, safi,
2803 &dest->reason)) {
19ea4cec
DS
2804 if (new_select == NULL &&
2805 reason != bgp_path_selection_none)
9bcb3eef 2806 dest->reason = reason;
40381db7 2807 new_select = pi;
d62a17ae 2808 }
2809 }
718e3744 2810
d62a17ae 2811 /* Now that we know which path is the bestpath see if any of the other
2812 * paths
2813 * qualify as multipaths
2814 */
2815 if (debug) {
2816 if (new_select)
7533cad7
QY
2817 bgp_path_info_path_with_addpath_rx_str(
2818 new_select, path_buf, sizeof(path_buf));
d62a17ae 2819 else
772270f3 2820 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2821 zlog_debug(
4378495a
DS
2822 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2823 dest, bgp->name_pretty, path_buf,
d62a17ae 2824 old_select ? old_select->peer->host : "NONE");
96450faf 2825 }
9fbdd100 2826
d62a17ae 2827 if (do_mpath && new_select) {
9bcb3eef 2828 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2829 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2830
2831 if (debug)
18ee8310 2832 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2833 pi, path_buf, sizeof(path_buf));
d62a17ae 2834
40381db7 2835 if (pi == new_select) {
d62a17ae 2836 if (debug)
2837 zlog_debug(
4378495a
DS
2838 "%pBD(%s): %s is the bestpath, add to the multipath list",
2839 dest, bgp->name_pretty,
2840 path_buf);
40381db7 2841 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2842 continue;
2843 }
2844
40381db7 2845 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2846 continue;
2847
40381db7
DS
2848 if (pi->peer && pi->peer != bgp->peer_self
2849 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2850 PEER_STATUS_NSF_WAIT))
feb17238 2851 if (!peer_established(pi->peer))
d62a17ae 2852 continue;
2853
40381db7 2854 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2855 if (debug)
2856 zlog_debug(
7fd8ca9a
DS
2857 "%pBD(%s): %s has the same nexthop as the bestpath, skip it",
2858 dest, bgp->name_pretty,
2859 path_buf);
d62a17ae 2860 continue;
2861 }
2862
40381db7 2863 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2864 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2865 &dest->reason);
d62a17ae 2866
2867 if (paths_eq) {
2868 if (debug)
2869 zlog_debug(
7fd8ca9a
DS
2870 "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list",
2871 dest, bgp->name_pretty,
2872 path_buf);
40381db7 2873 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2874 }
2875 }
2876 }
fee0f4c6 2877
4378495a 2878 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2879 mpath_cfg);
2880 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2881 bgp_mp_list_clear(&mp_list);
96450faf 2882
9bcb3eef 2883 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2884
d62a17ae 2885 result->old = old_select;
2886 result->new = new_select;
96450faf 2887
d62a17ae 2888 return;
fee0f4c6 2889}
2890
3f9c7369
DS
2891/*
2892 * A new route/change in bestpath of an existing route. Evaluate the path
2893 * for advertisement to the subgroup.
2894 */
3dc339cd
DA
2895void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2896 struct bgp_path_info *selected,
9bcb3eef 2897 struct bgp_dest *dest,
3dc339cd 2898 uint32_t addpath_tx_id)
d62a17ae 2899{
b54892e0 2900 const struct prefix *p;
d62a17ae 2901 struct peer *onlypeer;
2902 struct attr attr;
2903 afi_t afi;
2904 safi_t safi;
a77e2f4b
S
2905 struct bgp *bgp;
2906 bool advertise;
adbac85e 2907
9bcb3eef 2908 p = bgp_dest_get_prefix(dest);
d62a17ae 2909 afi = SUBGRP_AFI(subgrp);
2910 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2911 bgp = SUBGRP_INST(subgrp);
d62a17ae 2912 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2913 : NULL);
2914
2dbe669b
DA
2915 if (BGP_DEBUG(update, UPDATE_OUT))
2916 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2917
d62a17ae 2918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2919 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2920 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2921 return;
d62a17ae 2922
6006b807 2923 memset(&attr, 0, sizeof(attr));
d62a17ae 2924 /* It's initialized in bgp_announce_check() */
2925
a77e2f4b
S
2926 /* Announcement to the subgroup. If the route is filtered withdraw it.
2927 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2928 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2929 * route
d62a17ae 2930 */
a77e2f4b
S
2931 advertise = bgp_check_advertise(bgp, dest);
2932
d62a17ae 2933 if (selected) {
7f7940e6 2934 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2935 NULL)) {
a77e2f4b
S
2936 /* Route is selected, if the route is already installed
2937 * in FIB, then it is advertised
2938 */
be785e35 2939 if (advertise) {
84ef27fc
DA
2940 if (!bgp_check_withdrawal(bgp, dest)) {
2941 struct attr *adv_attr =
2942 bgp_attr_intern(&attr);
2943
2944 bgp_adj_out_set_subgroup(dest, subgrp,
2945 adv_attr,
2946 selected);
2947 } else
be785e35
DS
2948 bgp_adj_out_unset_subgroup(
2949 dest, subgrp, 1, addpath_tx_id);
2950 }
a77e2f4b 2951 } else
9bcb3eef 2952 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2953 addpath_tx_id);
d62a17ae 2954 }
2955
2956 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2957 else {
9bcb3eef 2958 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2959 }
200df115 2960}
fee0f4c6 2961
3064bf43 2962/*
e1072051 2963 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2964 * This is called at the end of route processing.
3064bf43 2965 */
9bcb3eef 2966void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2967{
40381db7 2968 struct bgp_path_info *pi;
3064bf43 2969
9bcb3eef 2970 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2971 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2972 continue;
40381db7
DS
2973 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2974 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2975 }
3064bf43 2976}
2977
2978/*
2979 * Has the route changed from the RIB's perspective? This is invoked only
2980 * if the route selection returns the same best route as earlier - to
2981 * determine if we need to update zebra or not.
2982 */
9bcb3eef 2983bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2984{
4b7e6066 2985 struct bgp_path_info *mpinfo;
d62a17ae 2986
2bb9eff4
DS
2987 /* If this is multipath, check all selected paths for any nexthop
2988 * change or attribute change. Some attribute changes (e.g., community)
2989 * aren't of relevance to the RIB, but we'll update zebra to ensure
2990 * we handle the case of BGP nexthop change. This is the behavior
2991 * when the best path has an attribute change anyway.
d62a17ae 2992 */
1defdda8 2993 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2994 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2995 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2996 return true;
d62a17ae 2997
2bb9eff4
DS
2998 /*
2999 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 3000 */
18ee8310
DS
3001 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
3002 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3003 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3004 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3005 return true;
d62a17ae 3006 }
3064bf43 3007
d62a17ae 3008 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3009 return false;
3064bf43 3010}
3011
d62a17ae 3012struct bgp_process_queue {
3013 struct bgp *bgp;
9bcb3eef 3014 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3015#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3016 unsigned int flags;
3017 unsigned int queued;
200df115 3018};
3019
3b0c17e1 3020static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3021 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3022 struct bgp_path_info *new_select,
3023 struct bgp_path_info *old_select)
3024{
9bcb3eef 3025 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3026
3027 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3028 return;
3029
3030 if (advertise_type5_routes(bgp, afi) && new_select
3031 && is_route_injectable_into_evpn(new_select)) {
3032
3033 /* apply the route-map */
3034 if (bgp->adv_cmd_rmap[afi][safi].map) {
3035 route_map_result_t ret;
3036 struct bgp_path_info rmap_path;
3037 struct bgp_path_info_extra rmap_path_extra;
3038 struct attr dummy_attr;
3039
3040 dummy_attr = *new_select->attr;
3041
3042 /* Fill temp path_info */
9bcb3eef 3043 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3044 new_select, new_select->peer,
3045 &dummy_attr);
3046
3047 RESET_FLAG(dummy_attr.rmap_change_flags);
3048
3049 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3050 p, &rmap_path);
3b0c17e1 3051
3052 if (ret == RMAP_DENYMATCH) {
3053 bgp_attr_flush(&dummy_attr);
3054 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3055 safi);
3056 } else
3057 bgp_evpn_advertise_type5_route(
3058 bgp, p, &dummy_attr, afi, safi);
3059 } else {
3060 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3061 afi, safi);
3062 }
3063 } else if (advertise_type5_routes(bgp, afi) && old_select
3064 && is_route_injectable_into_evpn(old_select))
3065 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3066}
3067
bb2ca692
MS
3068/*
3069 * Utility to determine whether a particular path_info should use
3070 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3071 * in a path where we basically _know_ this is a BGP-LU route.
3072 */
7ee70320
PG
3073static bool bgp_lu_need_null_label(struct bgp *bgp,
3074 const struct bgp_path_info *new_select,
3075 afi_t afi, mpls_label_t *label)
bb2ca692
MS
3076{
3077 /* Certain types get imp null; so do paths where the nexthop is
3078 * not labeled.
3079 */
3080 if (new_select->sub_type == BGP_ROUTE_STATIC
3081 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3082 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
f8141f4a 3083 goto need_null_label;
7ee70320
PG
3084 else if (new_select->extra &&
3085 bgp_is_valid_label(&new_select->extra->label[0]))
3086 return false;
f8141f4a 3087need_null_label:
7ee70320 3088 if (label == NULL)
bb2ca692 3089 return true;
7ee70320
PG
3090 if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
3091 /* Disable PHP : explicit-null */
3092 *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL
3093 : MPLS_LABEL_IPV6_EXPLICIT_NULL;
bb2ca692 3094 else
7ee70320
PG
3095 /* Enforced PHP popping: implicit-null */
3096 *label = MPLS_LABEL_IMPLICIT_NULL;
3097
3098 return true;
bb2ca692
MS
3099}
3100
3103e8d2
DS
3101/*
3102 * old_select = The old best path
3103 * new_select = the new best path
3104 *
3105 * if (!old_select && new_select)
3106 * We are sending new information on.
3107 *
3108 * if (old_select && new_select) {
3109 * if (new_select != old_select)
3110 * We have a new best path send a change
3111 * else
3112 * We've received a update with new attributes that needs
3113 * to be passed on.
3114 * }
3115 *
3116 * if (old_select && !new_select)
3117 * We have no eligible route that we can announce or the rn
3118 * is being removed.
3119 */
9bcb3eef 3120static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3121 afi_t afi, safi_t safi)
d62a17ae 3122{
4b7e6066
DS
3123 struct bgp_path_info *new_select;
3124 struct bgp_path_info *old_select;
3125 struct bgp_path_info_pair old_and_new;
ddb5b488 3126 int debug = 0;
7ee70320 3127 mpls_label_t mpls_label_null;
d62a17ae 3128
892fedb6 3129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3130 if (dest)
3131 debug = bgp_debug_bestpath(dest);
b54892e0 3132 if (debug)
f4c713ae 3133 zlog_debug(
7fd8ca9a
DS
3134 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3135 __func__, dest, bgp->name_pretty);
f4c713ae
LB
3136 return;
3137 }
d62a17ae 3138 /* Is it end of initial update? (after startup) */
9bcb3eef 3139 if (!dest) {
e36f61b5
DS
3140 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3141 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3142
3143 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3144 FOREACH_AFI_SAFI (afi, safi) {
3145 if (bgp_fibupd_safi(safi))
3146 bgp_zebra_announce_table(bgp, afi, safi);
3147 }
d62a17ae 3148 bgp->main_peers_update_hold = 0;
3149
3150 bgp_start_routeadv(bgp);
aac24838 3151 return;
d62a17ae 3152 }
cb1faec9 3153
9bcb3eef 3154 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3155
9bcb3eef 3156 debug = bgp_debug_bestpath(dest);
b54892e0 3157 if (debug)
7fd8ca9a 3158 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
4378495a
DS
3159 dest, bgp->name_pretty, afi2str(afi),
3160 safi2str(safi));
ddb5b488 3161
f009ff26 3162 /* The best path calculation for the route is deferred if
3163 * BGP_NODE_SELECT_DEFER is set
3164 */
9bcb3eef 3165 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3166 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
3167 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3168 dest, bgp->name_pretty);
f009ff26 3169 return;
3170 }
3171
d62a17ae 3172 /* Best path selection. */
9bcb3eef 3173 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3174 afi, safi);
3175 old_select = old_and_new.old;
3176 new_select = old_and_new.new;
3177
3178 /* Do we need to allocate or free labels?
3179 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3180 * necessary to do this upon changes to best path. Exceptions:
3181 * - label index has changed -> recalculate resulting label
7ee70320 3182 * - path_info sub_type changed -> switch to/from null label value
57592a53 3183 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3184 */
318cac96 3185 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3186 if (new_select) {
3187 if (!old_select
3188 || bgp_label_index_differs(new_select, old_select)
57592a53 3189 || new_select->sub_type != old_select->sub_type
9bcb3eef 3190 || !bgp_is_valid_label(&dest->local_label)) {
7ee70320
PG
3191 /* control label imposition for local routes,
3192 * aggregate and redistributed routes
57592a53 3193 */
7ee70320
PG
3194 mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
3195 if (bgp_lu_need_null_label(bgp, new_select, afi,
3196 &mpls_label_null)) {
d62a17ae 3197 if (CHECK_FLAG(
9bcb3eef 3198 dest->flags,
992dd67e
PR
3199 BGP_NODE_REGISTERED_FOR_LABEL)
3200 || CHECK_FLAG(
3201 dest->flags,
3202 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3203 bgp_unregister_for_label(dest);
67f67ba4 3204 dest->local_label = mpls_lse_encode(
7ee70320 3205 mpls_label_null, 0, 0, 1);
9bcb3eef 3206 bgp_set_valid_label(&dest->local_label);
d62a17ae 3207 } else
9bcb3eef
DS
3208 bgp_register_for_label(dest,
3209 new_select);
d62a17ae 3210 }
9bcb3eef 3211 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3212 BGP_NODE_REGISTERED_FOR_LABEL)
3213 || CHECK_FLAG(dest->flags,
3214 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3215 bgp_unregister_for_label(dest);
318cac96 3216 }
992dd67e
PR
3217 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3218 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3219 bgp_unregister_for_label(dest);
d62a17ae 3220 }
cd1964ff 3221
b54892e0 3222 if (debug)
ddb5b488 3223 zlog_debug(
4378495a
DS
3224 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3225 __func__, dest, bgp->name_pretty, afi2str(afi),
3226 safi2str(safi), old_select, new_select);
ddb5b488 3227
d62a17ae 3228 /* If best route remains the same and this is not due to user-initiated
3229 * clear, see exactly what needs to be done.
3230 */
d62a17ae 3231 if (old_select && old_select == new_select
9bcb3eef 3232 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3233 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3234 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3235 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3236#ifdef ENABLE_BGP_VNC
d62a17ae 3237 vnc_import_bgp_add_route(bgp, p, old_select);
3238 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3239#endif
bb744275 3240 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3241 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3242
3243 if (new_select->type == ZEBRA_ROUTE_BGP
3244 && (new_select->sub_type == BGP_ROUTE_NORMAL
3245 || new_select->sub_type
3246 == BGP_ROUTE_IMPORTED))
3247
9bcb3eef 3248 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3249 bgp, afi, safi);
3250 }
d62a17ae 3251 }
d62a17ae 3252
3253 /* If there is a change of interest to peers, reannounce the
3254 * route. */
1defdda8 3255 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3256 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3257 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3258 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3259
3260 /* unicast routes must also be annouced to
3261 * labeled-unicast update-groups */
3262 if (safi == SAFI_UNICAST)
3263 group_announce_route(bgp, afi,
9bcb3eef 3264 SAFI_LABELED_UNICAST, dest,
d62a17ae 3265 new_select);
3266
1defdda8 3267 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3268 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3269 }
fee0f4c6 3270
3b0c17e1 3271 /* advertise/withdraw type-5 routes */
3272 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3273 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3274 bgp_process_evpn_route_injection(
9bcb3eef 3275 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3276
b1875e65 3277 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3278 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3279 bgp_zebra_clear_route_change_flags(dest);
3280 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3281 return;
d62a17ae 3282 }
8ad7271d 3283
d62a17ae 3284 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3285 */
9bcb3eef 3286 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3287
3288 /* bestpath has changed; bump version */
3289 if (old_select || new_select) {
9bcb3eef 3290 bgp_bump_version(dest);
d62a17ae 3291
3292 if (!bgp->t_rmap_def_originate_eval) {
3293 bgp_lock(bgp);
907a2395 3294 event_add_timer(
d62a17ae 3295 bm->master,
3296 update_group_refresh_default_originate_route_map,
3297 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3298 &bgp->t_rmap_def_originate_eval);
3299 }
3300 }
3f9c7369 3301
d62a17ae 3302 if (old_select)
9bcb3eef 3303 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3304 if (new_select) {
ddb5b488
PZ
3305 if (debug)
3306 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3307 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3308 bgp_path_info_unset_flag(dest, new_select,
3309 BGP_PATH_ATTR_CHANGED);
1defdda8 3310 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3311 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3312 }
338b3424 3313
49e5a4a0 3314#ifdef ENABLE_BGP_VNC
d62a17ae 3315 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3316 if (old_select != new_select) {
3317 if (old_select) {
3318 vnc_import_bgp_exterior_del_route(bgp, p,
3319 old_select);
3320 vnc_import_bgp_del_route(bgp, p, old_select);
3321 }
3322 if (new_select) {
3323 vnc_import_bgp_exterior_add_route(bgp, p,
3324 new_select);
3325 vnc_import_bgp_add_route(bgp, p, new_select);
3326 }
3327 }
3328 }
65efcfce
LB
3329#endif
3330
9bcb3eef 3331 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3332
3333 /* unicast routes must also be annouced to labeled-unicast update-groups
3334 */
3335 if (safi == SAFI_UNICAST)
9bcb3eef 3336 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3337 new_select);
3338
3339 /* FIB update. */
3340 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3341 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3342
d62a17ae 3343 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3344 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3345 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3346 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3347
3348 /* if this is an evpn imported type-5 prefix,
3349 * we need to withdraw the route first to clear
3350 * the nh neigh and the RMAC entry.
3351 */
3352 if (old_select &&
3353 is_route_parent_evpn(old_select))
3354 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3355
9bcb3eef 3356 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3357 } else {
d62a17ae 3358 /* Withdraw the route from the kernel. */
3359 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3360 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3361 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3362 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3363
568e10ca 3364 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3365 }
718e3744 3366 }
3064bf43 3367
9bcb3eef 3368 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3369 old_select);
5424b7ba 3370
d62a17ae 3371 /* Clear any route change flags. */
9bcb3eef 3372 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3373
18ee8310 3374 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3375 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3376 bgp_path_info_reap(dest, old_select);
d62a17ae 3377
9bcb3eef 3378 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3379 return;
718e3744 3380}
3381
f009ff26 3382/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3383void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3384{
9bcb3eef 3385 struct bgp_dest *dest;
f009ff26 3386 int cnt = 0;
3387 struct afi_safi_info *thread_info;
f009ff26 3388
56c226e7 3389 if (bgp->gr_info[afi][safi].t_route_select) {
e6685141 3390 struct event *t = bgp->gr_info[afi][safi].t_route_select;
56c226e7 3391
e16d030c 3392 thread_info = EVENT_ARG(t);
56c226e7 3393 XFREE(MTYPE_TMP, thread_info);
e16d030c 3394 EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3395 }
f009ff26 3396
3397 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3398 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3399 get_afi_safi_str(afi, safi, false),
26742171 3400 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3401 }
3402
3403 /* Process the route list */
6338d242 3404 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3405 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3406 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3407 dest = bgp_route_next(dest)) {
3408 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3409 continue;
3410
3411 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3412 bgp->gr_info[afi][safi].gr_deferred--;
3413 bgp_process_main_one(bgp, dest, afi, safi);
3414 cnt++;
067ea165
CB
3415 }
3416 /* If iteration stopped before the entire table was traversed then the
3417 * node needs to be unlocked.
3418 */
3419 if (dest) {
3420 bgp_dest_unlock_node(dest);
3421 dest = NULL;
f009ff26 3422 }
3423
9e3b51a7 3424 /* Send EOR message when all routes are processed */
6338d242 3425 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3426 bgp_send_delayed_eor(bgp);
8c48b3b6 3427 /* Send route processing complete message to RIB */
115ccb9a 3428 bgp_zebra_update(bgp, afi, safi,
36235319 3429 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3430 return;
9e3b51a7 3431 }
f009ff26 3432
3433 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3434
3435 thread_info->afi = afi;
3436 thread_info->safi = safi;
3437 thread_info->bgp = bgp;
3438
3439 /* If there are more routes to be processed, start the
3440 * selection timer
3441 */
907a2395 3442 event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
f009ff26 3443 BGP_ROUTE_SELECT_DELAY,
3444 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3445}
3446
aac24838 3447static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3448{
aac24838
JB
3449 struct bgp_process_queue *pqnode = data;
3450 struct bgp *bgp = pqnode->bgp;
d62a17ae 3451 struct bgp_table *table;
9bcb3eef 3452 struct bgp_dest *dest;
aac24838
JB
3453
3454 /* eoiu marker */
3455 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3456 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3457 /* should always have dedicated wq call */
3458 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3459 return WQ_SUCCESS;
3460 }
3461
ac021f40 3462 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3463 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3464 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3465 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3466 table = bgp_dest_table(dest);
3467 /* note, new DESTs may be added as part of processing */
3468 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3469
9bcb3eef 3470 bgp_dest_unlock_node(dest);
d62a17ae 3471 bgp_table_unlock(table);
3472 }
aac24838
JB
3473
3474 return WQ_SUCCESS;
3475}
3476
3477static void bgp_processq_del(struct work_queue *wq, void *data)
3478{
3479 struct bgp_process_queue *pqnode = data;
3480
3481 bgp_unlock(pqnode->bgp);
3482
3483 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3484}
3485
b6c386bb 3486void bgp_process_queue_init(struct bgp *bgp)
200df115 3487{
b6c386bb
DS
3488 if (!bgp->process_queue) {
3489 char name[BUFSIZ];
3490
3491 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3492 bgp->process_queue = work_queue_new(bm->master, name);
3493 }
3494
3495 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3496 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3497 bgp->process_queue->spec.max_retries = 0;
3498 bgp->process_queue->spec.hold = 50;
d62a17ae 3499 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3500 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3501}
3502
cfe8d15a 3503static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3504{
3505 struct bgp_process_queue *pqnode;
3506
a4d82a8a
PZ
3507 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3508 sizeof(struct bgp_process_queue));
aac24838
JB
3509
3510 /* unlocked in bgp_processq_del */
3511 pqnode->bgp = bgp_lock(bgp);
3512 STAILQ_INIT(&pqnode->pqueue);
3513
aac24838
JB
3514 return pqnode;
3515}
3516
9bcb3eef 3517void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3518{
aac24838 3519#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3520 struct work_queue *wq = bgp->process_queue;
d62a17ae 3521 struct bgp_process_queue *pqnode;
cfe8d15a 3522 int pqnode_reuse = 0;
495f0b13 3523
d62a17ae 3524 /* already scheduled for processing? */
9bcb3eef 3525 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3526 return;
2e02b9b2 3527
f009ff26 3528 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3529 * the workqueue
3530 */
9bcb3eef 3531 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3532 if (BGP_DEBUG(update, UPDATE_OUT))
3533 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3534 dest);
f009ff26 3535 return;
3536 }
3537
46aeabed
LS
3538 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3539 if (BGP_DEBUG(update, UPDATE_OUT))
3540 zlog_debug(
3541 "Soft reconfigure table in progress for route %p",
3542 dest);
3543 return;
3544 }
3545
aac24838 3546 if (wq == NULL)
d62a17ae 3547 return;
3548
aac24838 3549 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3550 limit only if is from the same BGP view and it's not an EOIU marker
3551 */
aac24838
JB
3552 if (work_queue_item_count(wq)) {
3553 struct work_queue_item *item = work_queue_last_item(wq);
3554 pqnode = item->data;
228da428 3555
a4d82a8a
PZ
3556 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3557 || pqnode->bgp != bgp
3558 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3559 pqnode = bgp_processq_alloc(bgp);
3560 else
3561 pqnode_reuse = 1;
aac24838 3562 } else
cfe8d15a 3563 pqnode = bgp_processq_alloc(bgp);
aac24838 3564 /* all unlocked in bgp_process_wq */
9bcb3eef 3565 bgp_table_lock(bgp_dest_table(dest));
aac24838 3566
9bcb3eef
DS
3567 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3568 bgp_dest_lock_node(dest);
aac24838 3569
60466a63 3570 /* can't be enqueued twice */
9bcb3eef
DS
3571 assert(STAILQ_NEXT(dest, pq) == NULL);
3572 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3573 pqnode->queued++;
3574
cfe8d15a
LB
3575 if (!pqnode_reuse)
3576 work_queue_add(wq, pqnode);
3577
d62a17ae 3578 return;
fee0f4c6 3579}
0a486e5f 3580
d62a17ae 3581void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3582{
d62a17ae 3583 struct bgp_process_queue *pqnode;
cb1faec9 3584
b6c386bb 3585 if (bgp->process_queue == NULL)
d62a17ae 3586 return;
2e02b9b2 3587
cfe8d15a 3588 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3589
aac24838 3590 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3591 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3592}
3593
e6685141 3594static void bgp_maximum_prefix_restart_timer(struct event *thread)
0a486e5f 3595{
d62a17ae 3596 struct peer *peer;
0a486e5f 3597
e16d030c 3598 peer = EVENT_ARG(thread);
d62a17ae 3599 peer->t_pmax_restart = NULL;
0a486e5f 3600
d62a17ae 3601 if (bgp_debug_neighbor_events(peer))
3602 zlog_debug(
3603 "%s Maximum-prefix restart timer expired, restore peering",
3604 peer->host);
0a486e5f 3605
a9bafa95 3606 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3607 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3608}
3609
9cbd06e0
DA
3610static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3611 safi_t safi)
3612{
3613 uint32_t count = 0;
f41b0459 3614 bool filtered = false;
9cbd06e0
DA
3615 struct bgp_dest *dest;
3616 struct bgp_adj_in *ain;
40bb2ccf 3617 struct attr attr = {};
9cbd06e0
DA
3618 struct bgp_table *table = peer->bgp->rib[afi][safi];
3619
3620 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3621 for (ain = dest->adj_in; ain; ain = ain->next) {
3622 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3623
3624 attr = *ain->attr;
9cbd06e0
DA
3625
3626 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3627 == FILTER_DENY)
f41b0459
DA
3628 filtered = true;
3629
3630 if (bgp_input_modifier(
3631 peer, rn_p, &attr, afi, safi,
3632 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3633 NULL, 0, NULL)
3634 == RMAP_DENY)
3635 filtered = true;
3636
3637 if (filtered)
9cbd06e0 3638 count++;
f41b0459 3639
d498917e 3640 bgp_attr_flush(&attr);
9cbd06e0
DA
3641 }
3642 }
3643
3644 return count;
3645}
3646
3dc339cd
DA
3647bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3648 int always)
718e3744 3649{
d62a17ae 3650 iana_afi_t pkt_afi;
5c525538 3651 iana_safi_t pkt_safi;
9cbd06e0
DA
3652 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3653 PEER_FLAG_MAX_PREFIX_FORCE))
3654 ? bgp_filtered_routes_count(peer, afi, safi)
3655 + peer->pcount[afi][safi]
3656 : peer->pcount[afi][safi];
9cabb64b 3657
d62a17ae 3658 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3659 return false;
e0701b79 3660
9cbd06e0 3661 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3662 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3663 PEER_STATUS_PREFIX_LIMIT)
3664 && !always)
3dc339cd 3665 return false;
e0701b79 3666
d62a17ae 3667 zlog_info(
f70c91dc
DA
3668 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3669 get_afi_safi_str(afi, safi, false), peer, pcount,
3670 peer->pmax[afi][safi]);
d62a17ae 3671 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3672
3673 if (CHECK_FLAG(peer->af_flags[afi][safi],
3674 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3675 return false;
d62a17ae 3676
3677 /* Convert AFI, SAFI to values for packet. */
3678 pkt_afi = afi_int2iana(afi);
3679 pkt_safi = safi_int2iana(safi);
3680 {
d7c0a89a 3681 uint8_t ndata[7];
d62a17ae 3682
3683 ndata[0] = (pkt_afi >> 8);
3684 ndata[1] = pkt_afi;
3685 ndata[2] = pkt_safi;
3686 ndata[3] = (peer->pmax[afi][safi] >> 24);
3687 ndata[4] = (peer->pmax[afi][safi] >> 16);
3688 ndata[5] = (peer->pmax[afi][safi] >> 8);
3689 ndata[6] = (peer->pmax[afi][safi]);
3690
3691 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3692 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3693 BGP_NOTIFY_CEASE_MAX_PREFIX,
3694 ndata, 7);
3695 }
3696
3697 /* Dynamic peers will just close their connection. */
3698 if (peer_dynamic_neighbor(peer))
3dc339cd 3699 return true;
d62a17ae 3700
3701 /* restart timer start */
3702 if (peer->pmax_restart[afi][safi]) {
3703 peer->v_pmax_restart =
3704 peer->pmax_restart[afi][safi] * 60;
3705
3706 if (bgp_debug_neighbor_events(peer))
3707 zlog_debug(
f70c91dc
DA
3708 "%pBP Maximum-prefix restart timer started for %d secs",
3709 peer, peer->v_pmax_restart);
d62a17ae 3710
3711 BGP_TIMER_ON(peer->t_pmax_restart,
3712 bgp_maximum_prefix_restart_timer,
3713 peer->v_pmax_restart);
3714 }
3715
3dc339cd 3716 return true;
d62a17ae 3717 } else
3718 UNSET_FLAG(peer->af_sflags[afi][safi],
3719 PEER_STATUS_PREFIX_LIMIT);
3720
b1823b69
DS
3721 if (pcount
3722 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3723 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3724 PEER_STATUS_PREFIX_THRESHOLD)
3725 && !always)
3dc339cd 3726 return false;
d62a17ae 3727
3728 zlog_info(
f70c91dc
DA
3729 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3730 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3731 peer->pmax[afi][safi]);
d62a17ae 3732 SET_FLAG(peer->af_sflags[afi][safi],
3733 PEER_STATUS_PREFIX_THRESHOLD);
3734 } else
3735 UNSET_FLAG(peer->af_sflags[afi][safi],
3736 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3737 return false;
718e3744 3738}
3739
b40d939b 3740/* Unconditionally remove the route from the RIB, without taking
3741 * damping into consideration (eg, because the session went down)
3742 */
9bcb3eef 3743void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3744 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3745{
f009ff26 3746
3747 struct bgp *bgp = NULL;
3748 bool delete_route = false;
3749
9bcb3eef
DS
3750 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3751 safi);
d62a17ae 3752
f009ff26 3753 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3754 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3755
f009ff26 3756 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3757 * flag
3758 */
3759 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3760 delete_route = true;
9bcb3eef 3761 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3762 delete_route = true;
f009ff26 3763 if (delete_route) {
9bcb3eef
DS
3764 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3765 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3766 bgp = pi->peer->bgp;
26742171 3767 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3768 }
3769 }
3770 }
4a11bf2c 3771
9bcb3eef
DS
3772 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3773 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3774}
3775
9bcb3eef 3776static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3777 struct peer *peer, afi_t afi, safi_t safi,
3778 struct prefix_rd *prd)
3779{
9bcb3eef 3780 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3781
d62a17ae 3782 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3783 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3784 */
b4f7f45b
IR
3785 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3786 && peer->sort == BGP_PEER_EBGP)
3787 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3788 == BGP_DAMP_SUPPRESSED) {
3789 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3790 safi);
3791 return;
d62a17ae 3792 }
3793
49e5a4a0 3794#ifdef ENABLE_BGP_VNC
d62a17ae 3795 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3796 struct bgp_dest *pdest = NULL;
d62a17ae 3797 struct bgp_table *table = NULL;
3798
9bcb3eef
DS
3799 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3800 (struct prefix *)prd);
3801 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3802 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3803
3804 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3805 peer->bgp, prd, table, p, pi);
d62a17ae 3806 }
9bcb3eef 3807 bgp_dest_unlock_node(pdest);
d62a17ae 3808 }
3809 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3810 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3811
b54892e0
DS
3812 vnc_import_bgp_del_route(peer->bgp, p, pi);
3813 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3814 }
65efcfce 3815 }
d62a17ae 3816#endif
128ea8ab 3817
d62a17ae 3818 /* If this is an EVPN route, process for un-import. */
3819 if (safi == SAFI_EVPN)
b54892e0 3820 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3821
9bcb3eef 3822 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3823}
3824
4b7e6066
DS
3825struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3826 struct peer *peer, struct attr *attr,
9bcb3eef 3827 struct bgp_dest *dest)
fb018d25 3828{
4b7e6066 3829 struct bgp_path_info *new;
fb018d25 3830
d62a17ae 3831 /* Make new BGP info. */
4b7e6066 3832 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3833 new->type = type;
3834 new->instance = instance;
3835 new->sub_type = sub_type;
3836 new->peer = peer;
3837 new->attr = attr;
083ec940 3838 new->uptime = monotime(NULL);
9bcb3eef 3839 new->net = dest;
d62a17ae 3840 return new;
fb018d25
DS
3841}
3842
c265ee22 3843/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3844bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3845 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3846 struct bgp_dest *dest)
d62a17ae 3847{
2dbe3fa9 3848 bool ret = false;
b099a5c8
DA
3849 bool is_bgp_static_route =
3850 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3851 : false;
d62a17ae 3852
6cddc4c8
DA
3853 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3854 * as good.
3855 */
3856 if (bgp->allow_martian)
3857 return false;
3858
e8442016
DS
3859 /*
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3865 */
3866 if (is_bgp_static_route ||
3867 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3868 return false;
d62a17ae 3869
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3872 if (attr->nexthop.s_addr == INADDR_ANY ||
3873 !ipv4_unicast_valid(&attr->nexthop) ||
3874 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3875 return true;
d62a17ae 3876 }
c265ee22 3877
d62a17ae 3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
0355b41d
DA
3882 *
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
d62a17ae 3886 */
3887 if (attr->mp_nexthop_len) {
3888 switch (attr->mp_nexthop_len) {
3889 case BGP_ATTR_NHLEN_IPV4:
3890 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3891 ret = (attr->mp_nexthop_global_in.s_addr ==
3892 INADDR_ANY ||
3893 !ipv4_unicast_valid(
3894 &attr->mp_nexthop_global_in) ||
3895 bgp_nexthop_self(bgp, afi, type, stype, attr,
3896 dest));
d62a17ae 3897 break;
3898
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3901 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3902 &attr->mp_nexthop_global)
d62a17ae 3903 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3904 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3905 &attr->mp_nexthop_global)
3906 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3907 dest));
d62a17ae 3908 break;
0355b41d
DA
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3910 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr->mp_nexthop_global)
3913 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3914 dest));
0355b41d 3915 break;
d62a17ae 3916
3917 default:
3dc339cd 3918 ret = true;
d62a17ae 3919 break;
3920 }
3921 }
c265ee22 3922
d62a17ae 3923 return ret;
3924}
3925
aade37d7 3926static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3927{
3928 struct community *old;
3929 struct community *new;
3930 struct community *merge;
aade37d7 3931 struct community *no_export;
2721dd61 3932
9a706b42 3933 old = bgp_attr_get_community(attr);
aade37d7 3934 no_export = community_str2com("no-export");
2721dd61 3935
b4efa101
DA
3936 assert(no_export);
3937
2721dd61 3938 if (old) {
aade37d7 3939 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3940
3941 if (!old->refcnt)
3942 community_free(&old);
3943
3944 new = community_uniq_sort(merge);
3945 community_free(&merge);
3946 } else {
aade37d7 3947 new = community_dup(no_export);
2721dd61
DA
3948 }
3949
aade37d7 3950 community_free(&no_export);
2721dd61 3951
9a706b42 3952 bgp_attr_set_community(attr, new);
2721dd61
DA
3953}
3954
46dbf9d0
DA
3955static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3956 struct attr *attr, const struct prefix *prefix,
3957 int *sub_type)
3958{
3959 struct listnode *node, *nnode;
3960 struct bgp *bgp;
3961 bool accept_own_found = false;
3962
3963 if (safi != SAFI_MPLS_VPN)
3964 return false;
3965
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3968 return false;
3969
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3972 struct community *comm = bgp_attr_get_community(attr);
3973
3974 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3975 accept_own_found = true;
3976 }
3977
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3980 */
3981 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3982 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3983 continue;
3984
3985 if (accept_own_found &&
3986 ecommunity_include(
3987 bgp->vpn_policy[afi]
3988 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3989 bgp_attr_get_ecommunity(attr))) {
3990 if (bgp_debug_update(peer, prefix, NULL, 1))
3991 zlog_debug(
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3993 peer, prefix);
3994
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
3998 * community.
3999 */
4000 *sub_type = BGP_ROUTE_IMPORTED;
4001
4002 return true;
4003 }
4004 }
4005
4006 return false;
4007}
4008
367b458c
DS
4009void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4010 struct attr *attr, afi_t afi, safi_t safi, int type,
4011 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4012 uint32_t num_labels, int soft_reconfig,
4013 struct bgp_route_evpn *evpn)
d62a17ae 4014{
4015 int ret;
4016 int aspath_loop_count = 0;
9bcb3eef 4017 struct bgp_dest *dest;
d62a17ae 4018 struct bgp *bgp;
4019 struct attr new_attr;
4020 struct attr *attr_new;
40381db7 4021 struct bgp_path_info *pi;
819e6767 4022 struct bgp_path_info *new = NULL;
4b7e6066 4023 struct bgp_path_info_extra *extra;
d62a17ae 4024 const char *reason;
4025 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4026 int connected = 0;
4027 int do_loop_check = 1;
4028 int has_valid_label = 0;
7c312383 4029 afi_t nh_afi;
9146341f 4030 bool force_evpn_import = false;
907707db 4031 safi_t orig_safi = safi;
a486300b 4032 bool leak_success = true;
b2ac1d0d 4033 int allowas_in = 0;
949b0f24 4034
c7bb4f00 4035 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4036 char pfxprint[PREFIX2STR_BUFFER];
4037
4038 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4039 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4040 afi, safi, attr);
6401252f
QY
4041 }
4042
49e5a4a0 4043#ifdef ENABLE_BGP_VNC
d62a17ae 4044 int vnc_implicit_withdraw = 0;
65efcfce 4045#endif
d62a17ae 4046 int same_attr = 0;
f8745525 4047 const struct prefix *bgp_nht_param_prefix;
718e3744 4048
907707db
MS
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi == SAFI_LABELED_UNICAST)
4051 safi = SAFI_UNICAST;
4052
6006b807 4053 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4054 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4055 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4056
d62a17ae 4057 bgp = peer->bgp;
9bcb3eef 4058 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4061 has_valid_label = (num_labels > 0) ? 1 : 0;
4062 else
4063 has_valid_label = bgp_is_valid_label(label);
718e3744 4064
28f66de2
MS
4065 if (has_valid_label)
4066 assert(label != NULL);
4067
66ff6089
AD
4068 /* Update overlay index of the attribute */
4069 if (afi == AFI_L2VPN && evpn)
4070 memcpy(&attr->evpn_overlay, evpn,
4071 sizeof(struct bgp_route_evpn));
4072
d62a17ae 4073 /* When peer's soft reconfiguration enabled. Record input packet in
4074 Adj-RIBs-In. */
4075 if (!soft_reconfig
4076 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4077 && peer != bgp->peer_self)
9bcb3eef 4078 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4079
b2ac1d0d
MS
4080 /* Update permitted loop count */
4081 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4082 allowas_in = peer->allowas_in[afi][safi];
4083
d62a17ae 4084 /* Check previously received route. */
9bcb3eef 4085 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4086 if (pi->peer == peer && pi->type == type
4087 && pi->sub_type == sub_type
4088 && pi->addpath_rx_id == addpath_id)
d62a17ae 4089 break;
4090
4091 /* AS path local-as loop check. */
4092 if (peer->change_local_as) {
b2ac1d0d
MS
4093 if (allowas_in)
4094 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4095 else if (!CHECK_FLAG(peer->flags,
4096 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4097 aspath_loop_count = 1;
4098
4099 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4100 > aspath_loop_count) {
b4d46cc9 4101 peer->stat_pfx_aspath_loop++;
692174a1 4102 reason = "as-path contains our own AS;";
d62a17ae 4103 goto filtered;
4104 }
718e3744 4105 }
718e3744 4106
d62a17ae 4107 /* If the peer is configured for "allowas-in origin" and the last ASN in
4108 * the
4109 * as-path is our ASN then we do not need to call aspath_loop_check
4110 */
4111 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4112 if (aspath_get_last_as(attr->aspath) == bgp->as)
4113 do_loop_check = 0;
4114
f8745525
PG
4115 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4116 bgp_nht_param_prefix = NULL;
4117 else
4118 bgp_nht_param_prefix = p;
4119
d62a17ae 4120 /* AS path loop check. */
4121 if (do_loop_check) {
b0a8f709
FD
4122 if (aspath_loop_check(attr->aspath, bgp->as) >
4123 peer->allowas_in[afi][safi]) {
b4d46cc9 4124 peer->stat_pfx_aspath_loop++;
d62a17ae 4125 reason = "as-path contains our own AS;";
4126 goto filtered;
4127 }
4128 }
aac9ef6c 4129
b0a8f709
FD
4130 /* If we're a CONFED we need to loop check the CONFED ID too */
4131 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4132 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4133 peer->allowas_in[afi][safi]) {
4134 peer->stat_pfx_aspath_loop++;
4135 reason = "as-path contains our own confed AS;";
4136 goto filtered;
4137 }
4138
46dbf9d0
DA
4139 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4140 * enabled, then take care of that too.
4141 */
4142 bool accept_own = false;
4143
d62a17ae 4144 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4145 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4146 accept_own =
4147 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4148 if (!accept_own) {
4149 peer->stat_pfx_originator_loop++;
4150 reason = "originator is us;";
4151 goto filtered;
4152 }
d62a17ae 4153 }
718e3744 4154
d62a17ae 4155 /* Route reflector cluster ID check. */
4156 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4157 peer->stat_pfx_cluster_loop++;
d62a17ae 4158 reason = "reflected from the same cluster;";
4159 goto filtered;
4160 }
718e3744 4161
d62a17ae 4162 /* Apply incoming filter. */
907707db 4163 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4164 peer->stat_pfx_filter++;
d62a17ae 4165 reason = "filter;";
4166 goto filtered;
4167 }
718e3744 4168
a8b72dc6
DA
4169 /* RFC 8212 to prevent route leaks.
4170 * This specification intends to improve this situation by requiring the
4171 * explicit configuration of both BGP Import and Export Policies for any
4172 * External BGP (EBGP) session such as customers, peers, or
4173 * confederation boundaries for all enabled address families. Through
4174 * codification of the aforementioned requirement, operators will
4175 * benefit from consistent behavior across different BGP
4176 * implementations.
4177 */
1d3fdccf 4178 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4179 if (!bgp_inbound_policy_exists(peer,
4180 &peer->filter[afi][safi])) {
4181 reason = "inbound policy missing";
b17826b7
DS
4182 if (monotime_since(&bgp->ebgprequirespolicywarning,
4183 NULL) > FIFTEENMINUTE2USEC ||
4184 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4185 zlog_warn(
4186 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4187 monotime(&bgp->ebgprequirespolicywarning);
4188 }
a8b72dc6
DA
4189 goto filtered;
4190 }
4191
fb29348a
DA
4192 /* draft-ietf-idr-deprecate-as-set-confed-set
4193 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4194 * Eventually, This document (if approved) updates RFC 4271
4195 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4196 * and obsoletes RFC 6472.
4197 */
7f972cd8 4198 if (peer->bgp->reject_as_sets)
fb29348a
DA
4199 if (aspath_check_as_sets(attr->aspath)) {
4200 reason =
4201 "as-path contains AS_SET or AS_CONFED_SET type;";
4202 goto filtered;
4203 }
4204
6f4f49b2 4205 new_attr = *attr;
d62a17ae 4206
4207 /* Apply incoming route-map.
4208 * NB: new_attr may now contain newly allocated values from route-map
4209 * "set"
4210 * commands, so we need bgp_attr_flush in the error paths, until we
4211 * intern
4212 * the attr (which takes over the memory references) */
907707db 4213 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4214 num_labels, dest)
4215 == RMAP_DENY) {
b4d46cc9 4216 peer->stat_pfx_filter++;
d62a17ae 4217 reason = "route-map;";
4218 bgp_attr_flush(&new_attr);
4219 goto filtered;
4220 }
718e3744 4221
05864da7 4222 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4223 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4224 /* remove from RIB previous entry */
4225 bgp_zebra_withdraw(p, pi, bgp, safi);
4226 }
4227
7f323236
DW
4228 if (peer->sort == BGP_PEER_EBGP) {
4229
2721dd61
DA
4230 /* rfc7999:
4231 * A BGP speaker receiving an announcement tagged with the
4232 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4233 * NO_EXPORT community as defined in RFC1997, or a
4234 * similar community, to prevent propagation of the
4235 * prefix outside the local AS. The community to prevent
4236 * propagation SHOULD be chosen according to the operator's
4237 * routing policy.
4238 */
9a706b42
DA
4239 if (bgp_attr_get_community(&new_attr) &&
4240 community_include(bgp_attr_get_community(&new_attr),
4241 COMMUNITY_BLACKHOLE))
aade37d7 4242 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4243
a4d82a8a
PZ
4244 /* If we receive the graceful-shutdown community from an eBGP
4245 * peer we must lower local-preference */
9a706b42
DA
4246 if (bgp_attr_get_community(&new_attr) &&
4247 community_include(bgp_attr_get_community(&new_attr),
4248 COMMUNITY_GSHUT)) {
7f323236
DW
4249 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4250 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4251
4f770cf1
DA
4252 /* If graceful-shutdown is configured globally or
4253 * per neighbor, then add the GSHUT community to
4254 * all paths received from eBGP peers. */
4255 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4256 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4257 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4258 }
4259
d62a17ae 4260 /* next hop check. */
860ad3f9
DS
4261 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4262 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4263 &new_attr, dest)) {
b4d46cc9 4264 peer->stat_pfx_nh_invalid++;
d62a17ae 4265 reason = "martian or self next-hop;";
4266 bgp_attr_flush(&new_attr);
4267 goto filtered;
4268 }
718e3744 4269
5c14a191 4270 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4271 peer->stat_pfx_nh_invalid++;
4e802e66 4272 reason = "self mac;";
4dbf2038 4273 bgp_attr_flush(&new_attr);
4e802e66
DS
4274 goto filtered;
4275 }
4276
5a78f2bc
EB
4277 if (bgp_check_role_applicability(afi, safi) &&
4278 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4279 reason = "failing otc validation";
4280 bgp_attr_flush(&new_attr);
4281 goto filtered;
4282 }
a1b773e2 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 8358
7a70d990 8359 bgp_free_aggregate_info(aggregate);
9bcb3eef
DS
8360 bgp_dest_unlock_node(dest);
8361 bgp_dest_unlock_node(dest);
d62a17ae 8362
585f1adc 8363 return CMD_SUCCESS;
d62a17ae 8364}
8365
585f1adc
IR
8366static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8367 safi_t safi, const char *rmap,
8368 uint8_t summary_only, uint8_t as_set,
8369 uint8_t origin, bool match_med,
8370 const char *suppress_map)
d62a17ae 8371{
585f1adc 8372 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8373 int ret;
585f1adc 8374 struct prefix p;
9bcb3eef 8375 struct bgp_dest *dest;
d62a17ae 8376 struct bgp_aggregate *aggregate;
fb29348a 8377 uint8_t as_set_new = as_set;
d62a17ae 8378
365ab2e7 8379 if (suppress_map && summary_only) {
585f1adc 8380 vty_out(vty,
365ab2e7 8381 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8382 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8383 }
8384
585f1adc
IR
8385 /* Convert string to prefix structure. */
8386 ret = str2prefix(prefix_str, &p);
8387 if (!ret) {
8388 vty_out(vty, "Malformed prefix\n");
8389 return CMD_WARNING_CONFIG_FAILED;
8390 }
8391 apply_mask(&p);
d62a17ae 8392
585f1adc
IR
8393 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8394 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8395 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8396 prefix_str);
8397 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8398 }
8399
d62a17ae 8400 /* Old configuration check. */
585f1adc 8401 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8402 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8403
20894f50 8404 if (aggregate) {
585f1adc 8405 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8406 /* try to remove the old entry */
585f1adc 8407 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8408 if (ret) {
585f1adc 8409 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8410 bgp_dest_unlock_node(dest);
585f1adc 8411 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8412 }
8413 }
718e3744 8414
d62a17ae 8415 /* Make aggregate address structure. */
8416 aggregate = bgp_aggregate_new();
8417 aggregate->summary_only = summary_only;
6aabb15d 8418 aggregate->match_med = match_med;
fb29348a
DA
8419
8420 /* Network operators MUST NOT locally generate any new
8421 * announcements containing AS_SET or AS_CONFED_SET. If they have
8422 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8423 * SHOULD withdraw those routes and re-announce routes for the
8424 * aggregate or component prefixes (i.e., the more-specific routes
8425 * subsumed by the previously aggregated route) without AS_SET
8426 * or AS_CONFED_SET in the updates.
8427 */
7f972cd8 8428 if (bgp->reject_as_sets) {
fb29348a
DA
8429 if (as_set == AGGREGATE_AS_SET) {
8430 as_set_new = AGGREGATE_AS_UNSET;
8431 zlog_warn(
63efca0e 8432 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8433 __func__);
585f1adc 8434 vty_out(vty,
fb29348a
DA
8435 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8436 }
8437 }
8438
8439 aggregate->as_set = as_set_new;
d62a17ae 8440 aggregate->safi = safi;
229757f1
DA
8441 /* Override ORIGIN attribute if defined.
8442 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8443 * to IGP which is not what rfc4271 says.
8444 * This enables the same behavior, optionally.
8445 */
8446 aggregate->origin = origin;
20894f50
DA
8447
8448 if (rmap) {
8449 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8450 route_map_counter_decrement(aggregate->rmap.map);
8451 aggregate->rmap.name =
8452 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8453 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8454 route_map_counter_increment(aggregate->rmap.map);
8455 }
365ab2e7
RZ
8456
8457 if (suppress_map) {
8458 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8459 route_map_counter_decrement(aggregate->suppress_map);
8460
8461 aggregate->suppress_map_name =
8462 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8463 aggregate->suppress_map =
8464 route_map_lookup_by_name(aggregate->suppress_map_name);
8465 route_map_counter_increment(aggregate->suppress_map);
8466 }
8467
9bcb3eef 8468 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8469
d62a17ae 8470 /* Aggregate address insert into BGP routing table. */
9bea1b4b
DA
8471 if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8472 bgp_aggregate_free(aggregate);
8473 bgp_dest_unlock_node(dest);
8474 }
718e3744 8475
585f1adc 8476 return CMD_SUCCESS;
718e3744 8477}
8478
585f1adc
IR
8479DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8480 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8481 "as-set$as_set_s"
8482 "|summary-only$summary_only"
cacba915 8483 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8484 "|origin <egp|igp|incomplete>$origin_s"
8485 "|matching-MED-only$match_med"
cacba915 8486 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8487 "}]",
8488 NO_STR
8489 "Configure BGP aggregate entries\n"
764402fe
DA
8490 "Aggregate prefix\n"
8491 "Aggregate address\n"
8492 "Aggregate mask\n"
585f1adc
IR
8493 "Generate AS set path information\n"
8494 "Filter more specific routes from updates\n"
8495 "Apply route map to aggregate network\n"
8496 "Route map name\n"
8497 "BGP origin code\n"
8498 "Remote EGP\n"
8499 "Local IGP\n"
8500 "Unknown heritage\n"
8501 "Only aggregate routes with matching MED\n"
8502 "Suppress the selected more specific routes\n"
8503 "Route map with the route selectors\n")
8504{
8505 const char *prefix_s = NULL;
554b3b10 8506 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8507 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8508 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8509 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8510
554b3b10 8511 if (addr_str) {
7533cad7
QY
8512 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8513 sizeof(prefix_buf))
554b3b10
RZ
8514 == 0) {
8515 vty_out(vty, "%% Inconsistent address and mask\n");
8516 return CMD_WARNING_CONFIG_FAILED;
8517 }
585f1adc
IR
8518 prefix_s = prefix_buf;
8519 } else
8520 prefix_s = prefix_str;
37a87b8f 8521
585f1adc
IR
8522 if (origin_s) {
8523 if (strcmp(origin_s, "egp") == 0)
8524 origin = BGP_ORIGIN_EGP;
8525 else if (strcmp(origin_s, "igp") == 0)
8526 origin = BGP_ORIGIN_IGP;
8527 else if (strcmp(origin_s, "incomplete") == 0)
8528 origin = BGP_ORIGIN_INCOMPLETE;
8529 }
90e21f35 8530
585f1adc
IR
8531 if (as_set_s)
8532 as_set = AGGREGATE_AS_SET;
554b3b10 8533
585f1adc 8534 /* Handle configuration removal, otherwise installation. */
554b3b10 8535 if (no)
585f1adc
IR
8536 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8537
8538 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8539 summary_only != NULL, as_set, origin,
8540 match_med != NULL, suppress_map);
8541}
8542
7a70d990
SB
8543void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
8544{
8545 if (aggregate->community)
8546 community_free(&aggregate->community);
8547
8548 hash_clean_and_free(&aggregate->community_hash,
8549 bgp_aggr_community_remove);
8550
8551 if (aggregate->ecommunity)
8552 ecommunity_free(&aggregate->ecommunity);
8553
8554 hash_clean_and_free(&aggregate->ecommunity_hash,
8555 bgp_aggr_ecommunity_remove);
8556
8557 if (aggregate->lcommunity)
8558 lcommunity_free(&aggregate->lcommunity);
8559
8560 hash_clean_and_free(&aggregate->lcommunity_hash,
8561 bgp_aggr_lcommunity_remove);
8562
8563 if (aggregate->aspath)
8564 aspath_free(aggregate->aspath);
8565
8566 hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
8567
8568 bgp_aggregate_free(aggregate);
8569}
8570
585f1adc
IR
8571DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8572 "[no] aggregate-address X:X::X:X/M$prefix [{"
8573 "as-set$as_set_s"
8574 "|summary-only$summary_only"
cacba915 8575 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8576 "|origin <egp|igp|incomplete>$origin_s"
8577 "|matching-MED-only$match_med"
cacba915 8578 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8579 "}]",
8580 NO_STR
8581 "Configure BGP aggregate entries\n"
8582 "Aggregate prefix\n"
8583 "Generate AS set path information\n"
8584 "Filter more specific routes from updates\n"
8585 "Apply route map to aggregate network\n"
8586 "Route map name\n"
8587 "BGP origin code\n"
8588 "Remote EGP\n"
8589 "Local IGP\n"
8590 "Unknown heritage\n"
8591 "Only aggregate routes with matching MED\n"
8592 "Suppress the selected more specific routes\n"
8593 "Route map with the route selectors\n")
8594{
8595 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8596 int as_set = AGGREGATE_AS_UNSET;
8597
8598 if (origin_s) {
8599 if (strcmp(origin_s, "egp") == 0)
8600 origin = BGP_ORIGIN_EGP;
8601 else if (strcmp(origin_s, "igp") == 0)
8602 origin = BGP_ORIGIN_IGP;
8603 else if (strcmp(origin_s, "incomplete") == 0)
8604 origin = BGP_ORIGIN_INCOMPLETE;
8605 }
8606
8607 if (as_set_s)
8608 as_set = AGGREGATE_AS_SET;
8609
8610 /* Handle configuration removal, otherwise installation. */
554b3b10 8611 if (no)
585f1adc
IR
8612 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8613 SAFI_UNICAST);
554b3b10 8614
585f1adc
IR
8615 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8616 rmap_name, summary_only != NULL, as_set,
8617 origin, match_med != NULL, suppress_map);
718e3744 8618}
8619
718e3744 8620/* Redistribute route treatment. */
d62a17ae 8621void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8622 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8623 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8624 enum blackhole_type bhtype, uint32_t metric,
8625 uint8_t type, unsigned short instance,
8626 route_tag_t tag)
d62a17ae 8627{
4b7e6066 8628 struct bgp_path_info *new;
40381db7
DS
8629 struct bgp_path_info *bpi;
8630 struct bgp_path_info rmap_path;
9bcb3eef 8631 struct bgp_dest *bn;
d62a17ae 8632 struct attr attr;
8633 struct attr *new_attr;
8634 afi_t afi;
b68885f9 8635 route_map_result_t ret;
d62a17ae 8636 struct bgp_redist *red;
8637
8638 /* Make default attribute. */
0f05ea43 8639 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8640 /*
8641 * This must not be NULL to satisfy Coverity SA
8642 */
8643 assert(attr.aspath);
9de1f7ff 8644
a4d82a8a 8645 switch (nhtype) {
9de1f7ff 8646 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8647 switch (p->family) {
8648 case AF_INET:
8649 attr.nexthop.s_addr = INADDR_ANY;
8650 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8651 break;
8652 case AF_INET6:
8653 memset(&attr.mp_nexthop_global, 0,
8654 sizeof(attr.mp_nexthop_global));
8655 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8656 break;
8657 }
9de1f7ff
DS
8658 break;
8659 case NEXTHOP_TYPE_IPV4:
8660 case NEXTHOP_TYPE_IPV4_IFINDEX:
8661 attr.nexthop = nexthop->ipv4;
7226bc40 8662 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8663 break;
8664 case NEXTHOP_TYPE_IPV6:
8665 case NEXTHOP_TYPE_IPV6_IFINDEX:
8666 attr.mp_nexthop_global = nexthop->ipv6;
8667 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8668 break;
8669 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8670 switch (p->family) {
8671 case AF_INET:
9de1f7ff 8672 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8673 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8674 break;
8675 case AF_INET6:
9de1f7ff
DS
8676 memset(&attr.mp_nexthop_global, 0,
8677 sizeof(attr.mp_nexthop_global));
74489921 8678 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8679 break;
74489921 8680 }
0789eb69 8681 attr.bh_type = bhtype;
9de1f7ff 8682 break;
d62a17ae 8683 }
0789eb69 8684 attr.nh_type = nhtype;
74489921 8685 attr.nh_ifindex = ifindex;
f04a80a5 8686
d62a17ae 8687 attr.med = metric;
957f74c3 8688 attr.distance = distance;
d62a17ae 8689 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8690 attr.tag = tag;
718e3744 8691
97a52c82
DA
8692 if (metric)
8693 bgp_attr_set_aigp_metric(&attr, metric);
8694
d62a17ae 8695 afi = family2afi(p->family);
6aeb9e78 8696
d62a17ae 8697 red = bgp_redist_lookup(bgp, afi, type, instance);
8698 if (red) {
8699 struct attr attr_new;
718e3744 8700
d62a17ae 8701 /* Copy attribute for modification. */
6f4f49b2 8702 attr_new = attr;
718e3744 8703
97a52c82 8704 if (red->redist_metric_flag) {
d62a17ae 8705 attr_new.med = red->redist_metric;
97a52c82
DA
8706 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8707 }
718e3744 8708
d62a17ae 8709 /* Apply route-map. */
8710 if (red->rmap.name) {
6006b807 8711 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8712 rmap_path.peer = bgp->peer_self;
8713 rmap_path.attr = &attr_new;
718e3744 8714
d62a17ae 8715 SET_FLAG(bgp->peer_self->rmap_type,
8716 PEER_RMAP_TYPE_REDISTRIBUTE);
8717
1782514f 8718 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8719
8720 bgp->peer_self->rmap_type = 0;
8721
8722 if (ret == RMAP_DENYMATCH) {
8723 /* Free uninterned attribute. */
8724 bgp_attr_flush(&attr_new);
8725
8726 /* Unintern original. */
8727 aspath_unintern(&attr.aspath);
8728 bgp_redistribute_delete(bgp, p, type, instance);
8729 return;
8730 }
8731 }
8732
637e5ba4 8733 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8734 bgp_attr_add_gshut_community(&attr_new);
8735
d62a17ae 8736 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8737 SAFI_UNICAST, p, NULL);
8738
8739 new_attr = bgp_attr_intern(&attr_new);
8740
9bcb3eef 8741 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8742 if (bpi->peer == bgp->peer_self
8743 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8744 break;
8745
40381db7 8746 if (bpi) {
d62a17ae 8747 /* Ensure the (source route) type is updated. */
40381db7
DS
8748 bpi->type = type;
8749 if (attrhash_cmp(bpi->attr, new_attr)
8750 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8751 bgp_attr_unintern(&new_attr);
8752 aspath_unintern(&attr.aspath);
9bcb3eef 8753 bgp_dest_unlock_node(bn);
d62a17ae 8754 return;
8755 } else {
8756 /* The attribute is changed. */
40381db7 8757 bgp_path_info_set_flag(bn, bpi,
18ee8310 8758 BGP_PATH_ATTR_CHANGED);
d62a17ae 8759
8760 /* Rewrite BGP route information. */
40381db7
DS
8761 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8762 bgp_path_info_restore(bn, bpi);
d62a17ae 8763 else
40381db7
DS
8764 bgp_aggregate_decrement(
8765 bgp, p, bpi, afi, SAFI_UNICAST);
8766 bgp_attr_unintern(&bpi->attr);
8767 bpi->attr = new_attr;
083ec940 8768 bpi->uptime = monotime(NULL);
d62a17ae 8769
8770 /* Process change. */
40381db7 8771 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8772 SAFI_UNICAST);
8773 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8774 bgp_dest_unlock_node(bn);
d62a17ae 8775 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8776
8777 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8778 || (bgp->inst_type
8779 == BGP_INSTANCE_TYPE_DEFAULT)) {
8780
8781 vpn_leak_from_vrf_update(
40381db7 8782 bgp_get_default(), bgp, bpi);
ddb5b488 8783 }
d62a17ae 8784 return;
8785 }
8786 }
8787
8788 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8789 bgp->peer_self, new_attr, bn);
1defdda8 8790 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8791
8792 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8793 bgp_path_info_add(bn, new);
9bcb3eef 8794 bgp_dest_unlock_node(bn);
be785e35 8795 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8796 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8797
8798 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8799 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8800
8801 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8802 }
d62a17ae 8803 }
8804
8805 /* Unintern original. */
8806 aspath_unintern(&attr.aspath);
718e3744 8807}
8808
d7c0a89a
QY
8809void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8810 unsigned short instance)
718e3744 8811{
d62a17ae 8812 afi_t afi;
9bcb3eef 8813 struct bgp_dest *dest;
40381db7 8814 struct bgp_path_info *pi;
d62a17ae 8815 struct bgp_redist *red;
718e3744 8816
d62a17ae 8817 afi = family2afi(p->family);
718e3744 8818
d62a17ae 8819 red = bgp_redist_lookup(bgp, afi, type, instance);
8820 if (red) {
9bcb3eef
DS
8821 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8822 SAFI_UNICAST, p, NULL);
d62a17ae 8823
9bcb3eef 8824 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8825 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8826 break;
8827
40381db7 8828 if (pi) {
ddb5b488
PZ
8829 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8830 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8831
8832 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8833 bgp, pi);
ddb5b488 8834 }
40381db7 8835 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8836 bgp_path_info_delete(dest, pi);
8837 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8838 }
9bcb3eef 8839 bgp_dest_unlock_node(dest);
d62a17ae 8840 }
8841}
8842
8843/* Withdraw specified route type's route. */
8844void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8845 unsigned short instance)
d62a17ae 8846{
9bcb3eef 8847 struct bgp_dest *dest;
40381db7 8848 struct bgp_path_info *pi;
d62a17ae 8849 struct bgp_table *table;
8850
8851 table = bgp->rib[afi][SAFI_UNICAST];
8852
9bcb3eef
DS
8853 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8854 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8855 if (pi->peer == bgp->peer_self && pi->type == type
8856 && pi->instance == instance)
d62a17ae 8857 break;
8858
40381db7 8859 if (pi) {
ddb5b488
PZ
8860 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8861 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8862
8863 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8864 bgp, pi);
ddb5b488 8865 }
9bcb3eef 8866 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8867 pi, afi, SAFI_UNICAST);
9bcb3eef 8868 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8869 if (!CHECK_FLAG(bgp->flags,
8870 BGP_FLAG_DELETE_IN_PROGRESS))
8871 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8872 else
8873 bgp_path_info_reap(dest, pi);
d62a17ae 8874 }
718e3744 8875 }
718e3744 8876}
6b0655a2 8877
718e3744 8878/* Static function to display route. */
7d3cae70
DA
8879static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8880 struct vty *vty, json_object *json, bool wide)
718e3744 8881{
be054588 8882 int len = 0;
07380148 8883 char buf[INET6_ADDRSTRLEN];
718e3744 8884
d62a17ae 8885 if (p->family == AF_INET) {
c6462ff4 8886 if (!json) {
8228a9a7 8887 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8888 } else {
8889 json_object_string_add(json, "prefix",
8890 inet_ntop(p->family,
8891 &p->u.prefix, buf,
07380148 8892 sizeof(buf)));
c6462ff4 8893 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8894 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8895 json_object_int_add(json, "version", dest->version);
c6462ff4 8896 }
d62a17ae 8897 } else if (p->family == AF_ETHERNET) {
8228a9a7 8898 len = vty_out(vty, "%pFX", p);
b03b8898 8899 } else if (p->family == AF_EVPN) {
57f7feb6 8900 if (!json)
2dbe669b 8901 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8902 else
60466a63 8903 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8904 } else if (p->family == AF_FLOWSPEC) {
8905 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8906 json ?
8907 NLRI_STRING_FORMAT_JSON_SIMPLE :
8908 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8909 } else {
c6462ff4 8910 if (!json)
8228a9a7 8911 len = vty_out(vty, "%pFX", p);
50e05855
AD
8912 else {
8913 json_object_string_add(json, "prefix",
07380148
DA
8914 inet_ntop(p->family,
8915 &p->u.prefix, buf,
8916 sizeof(buf)));
50e05855 8917 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8918 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8919 json_object_int_add(json, "version", dest->version);
37d4e0df 8920 }
9c92b5f7 8921 }
d62a17ae 8922
9c92b5f7 8923 if (!json) {
ae248832 8924 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8925 if (len < 1)
8926 vty_out(vty, "\n%*s", 20, " ");
8927 else
8928 vty_out(vty, "%*s", len, " ");
8929 }
718e3744 8930}
8931
d62a17ae 8932enum bgp_display_type {
8933 normal_list,
718e3744 8934};
8935
1d7260a1 8936const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8937{
8938 switch (reason) {
8939 case bgp_path_selection_none:
8940 return "Nothing to Select";
8941 case bgp_path_selection_first:
8942 return "First path received";
8943 case bgp_path_selection_evpn_sticky_mac:
8944 return "EVPN Sticky Mac";
8945 case bgp_path_selection_evpn_seq:
8946 return "EVPN sequence number";
8947 case bgp_path_selection_evpn_lower_ip:
8948 return "EVPN lower IP";
8949 case bgp_path_selection_evpn_local_path:
8950 return "EVPN local ES path";
8951 case bgp_path_selection_evpn_non_proxy:
8952 return "EVPN non proxy";
8953 case bgp_path_selection_weight:
8954 return "Weight";
8955 case bgp_path_selection_local_pref:
8956 return "Local Pref";
46dbf9d0
DA
8957 case bgp_path_selection_accept_own:
8958 return "Accept Own";
bbb46eb5
DA
8959 case bgp_path_selection_local_route:
8960 return "Local Route";
97a52c82
DA
8961 case bgp_path_selection_aigp:
8962 return "AIGP";
bbb46eb5
DA
8963 case bgp_path_selection_confed_as_path:
8964 return "Confederation based AS Path";
8965 case bgp_path_selection_as_path:
8966 return "AS Path";
8967 case bgp_path_selection_origin:
8968 return "Origin";
8969 case bgp_path_selection_med:
8970 return "MED";
8971 case bgp_path_selection_peer:
8972 return "Peer Type";
8973 case bgp_path_selection_confed:
8974 return "Confed Peer Type";
8975 case bgp_path_selection_igp_metric:
8976 return "IGP Metric";
8977 case bgp_path_selection_older:
8978 return "Older Path";
8979 case bgp_path_selection_router_id:
8980 return "Router ID";
8981 case bgp_path_selection_cluster_length:
bcab253c 8982 return "Cluster length";
bbb46eb5
DA
8983 case bgp_path_selection_stale:
8984 return "Path Staleness";
8985 case bgp_path_selection_local_configured:
8986 return "Locally configured route";
8987 case bgp_path_selection_neighbor_ip:
8988 return "Neighbor IP";
8989 case bgp_path_selection_default:
8990 return "Nothing left to compare";
8991 }
8992 return "Invalid (internal error)";
8993}
8994
18ee8310 8995/* Print the short form route status for a bgp_path_info */
4b7e6066 8996static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8997 struct bgp_path_info *path,
82c298be 8998 const struct prefix *p,
d62a17ae 8999 json_object *json_path)
718e3744 9000{
82c298be
DA
9001 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9002
d62a17ae 9003 if (json_path) {
b05a1c8b 9004
d62a17ae 9005 /* Route status display. */
9b6d8fcf 9006 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9007 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9008
9b6d8fcf 9009 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9010 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9011
4056a5f6 9012 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9013 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9014
9b6d8fcf
DS
9015 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9016 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9017 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9018
d62a17ae 9019 /* Selected */
9b6d8fcf 9020 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9021 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9022
9b6d8fcf 9023 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9024 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9025
bbb46eb5 9026 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9027 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9028 json_object_string_add(json_path, "selectionReason",
9029 bgp_path_selection_reason2str(
9030 path->net->reason));
9031 }
b05a1c8b 9032
9b6d8fcf 9033 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9034 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9035
d62a17ae 9036 /* Internal route. */
9b6d8fcf
DS
9037 if ((path->peer->as)
9038 && (path->peer->as == path->peer->local_as))
d62a17ae 9039 json_object_string_add(json_path, "pathFrom",
9040 "internal");
9041 else
9042 json_object_string_add(json_path, "pathFrom",
9043 "external");
b05a1c8b 9044
d62a17ae 9045 return;
9046 }
b05a1c8b 9047
82c298be
DA
9048 /* RPKI validation state */
9049 rpki_state =
9050 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9051
9052 if (rpki_state == RPKI_VALID)
9053 vty_out(vty, "V");
9054 else if (rpki_state == RPKI_INVALID)
9055 vty_out(vty, "I");
9056 else if (rpki_state == RPKI_NOTFOUND)
9057 vty_out(vty, "N");
eaeba5e8
WM
9058 else
9059 vty_out(vty, " ");
82c298be 9060
d62a17ae 9061 /* Route status display. */
9b6d8fcf 9062 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9063 vty_out(vty, "R");
9b6d8fcf 9064 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9065 vty_out(vty, "S");
4056a5f6 9066 else if (bgp_path_suppressed(path))
d62a17ae 9067 vty_out(vty, "s");
9b6d8fcf
DS
9068 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9069 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9070 vty_out(vty, "*");
9071 else
9072 vty_out(vty, " ");
9073
9074 /* Selected */
9b6d8fcf 9075 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9076 vty_out(vty, "h");
9b6d8fcf 9077 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9078 vty_out(vty, "d");
9b6d8fcf 9079 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9080 vty_out(vty, ">");
9b6d8fcf 9081 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9082 vty_out(vty, "=");
9083 else
9084 vty_out(vty, " ");
718e3744 9085
d62a17ae 9086 /* Internal route. */
9b6d8fcf
DS
9087 if (path->peer && (path->peer->as)
9088 && (path->peer->as == path->peer->local_as))
d62a17ae 9089 vty_out(vty, "i");
9090 else
9091 vty_out(vty, " ");
b40d939b 9092}
9093
2ba93fd6
DA
9094static char *bgp_nexthop_hostname(struct peer *peer,
9095 struct bgp_nexthop_cache *bnc)
25b5da8d 9096{
892fedb6 9097 if (peer->hostname
aef999a2 9098 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9099 return peer->hostname;
9100 return NULL;
9101}
9102
b40d939b 9103/* called from terminal list command */
bd494ec5 9104void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9105 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9106 json_object *json_paths, bool wide)
d62a17ae 9107{
aef999a2 9108 int len;
515c2602 9109 struct attr *attr = path->attr;
d62a17ae 9110 json_object *json_path = NULL;
9111 json_object *json_nexthops = NULL;
9112 json_object *json_nexthop_global = NULL;
9113 json_object *json_nexthop_ll = NULL;
6f214dd3 9114 json_object *json_ext_community = NULL;
9df8b37c 9115 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9116 bool nexthop_self =
9b6d8fcf 9117 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9118 bool nexthop_othervrf = false;
43089216 9119 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9120 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9121 char *nexthop_hostname =
9122 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9123 char esi_buf[ESI_STR_LEN];
d62a17ae 9124
9125 if (json_paths)
9126 json_path = json_object_new_object();
9127
9128 /* short status lead text */
82c298be 9129 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9130
9131 if (!json_paths) {
9132 /* print prefix and mask */
9133 if (!display)
7d3cae70 9134 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9135 else
ae248832 9136 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9137 } else {
7d3cae70 9138 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9139 }
47fc97cc 9140
9df8b37c
PZ
9141 /*
9142 * If vrf id of nexthop is different from that of prefix,
9143 * set up printable string to append
9144 */
9b6d8fcf 9145 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9146 const char *self = "";
9147
9148 if (nexthop_self)
9149 self = "<";
9150
9151 nexthop_othervrf = true;
9b6d8fcf 9152 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9153
9b6d8fcf 9154 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9155 snprintf(vrf_id_str, sizeof(vrf_id_str),
9156 "@%s%s", VRFID_NONE_STR, self);
9157 else
9158 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9159 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9160
9b6d8fcf
DS
9161 if (path->extra->bgp_orig->inst_type
9162 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9163
9b6d8fcf 9164 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9165 } else {
9166 const char *self = "";
9167
9168 if (nexthop_self)
9169 self = "<";
9170
9171 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9172 }
9173
445c2480
DS
9174 /*
9175 * For ENCAP and EVPN routes, nexthop address family is not
9176 * neccessarily the same as the prefix address family.
9177 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9178 * EVPN routes are also exchanged with a MP nexthop. Currently,
9179 * this
9180 * is only IPv4, the value will be present in either
9181 * attr->nexthop or
9182 * attr->mp_nexthop_global_in
9183 */
9184 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9185 char nexthop[128];
9186 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9187
9188 switch (af) {
9189 case AF_INET:
07380148
DA
9190 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9191 &attr->mp_nexthop_global_in);
445c2480
DS
9192 break;
9193 case AF_INET6:
07380148
DA
9194 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9195 &attr->mp_nexthop_global);
445c2480
DS
9196 break;
9197 default:
772270f3 9198 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9199 break;
d62a17ae 9200 }
d62a17ae 9201
445c2480
DS
9202 if (json_paths) {
9203 json_nexthop_global = json_object_new_object();
9204
515c2602
DA
9205 json_object_string_add(json_nexthop_global, "ip",
9206 nexthop);
9207
939a97f4 9208 if (path->peer->hostname)
515c2602
DA
9209 json_object_string_add(json_nexthop_global,
9210 "hostname",
939a97f4 9211 path->peer->hostname);
515c2602
DA
9212
9213 json_object_string_add(json_nexthop_global, "afi",
9214 (af == AF_INET) ? "ipv4"
9215 : "ipv6");
445c2480
DS
9216 json_object_boolean_true_add(json_nexthop_global,
9217 "used");
aef999a2
DA
9218 } else {
9219 if (nexthop_hostname)
9220 len = vty_out(vty, "%s(%s)%s", nexthop,
9221 nexthop_hostname, vrf_id_str);
9222 else
9223 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9224
ae248832 9225 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9226 if (len < 1)
9227 vty_out(vty, "\n%*s", 36, " ");
9228 else
9229 vty_out(vty, "%*s", len, " ");
9230 }
445c2480
DS
9231 } else if (safi == SAFI_EVPN) {
9232 if (json_paths) {
9233 json_nexthop_global = json_object_new_object();
9234
c949c771 9235 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9236 "%pI4",
9237 &attr->mp_nexthop_global_in);
515c2602 9238
939a97f4 9239 if (path->peer->hostname)
515c2602
DA
9240 json_object_string_add(json_nexthop_global,
9241 "hostname",
939a97f4 9242 path->peer->hostname);
515c2602 9243
a4d82a8a
PZ
9244 json_object_string_add(json_nexthop_global, "afi",
9245 "ipv4");
445c2480
DS
9246 json_object_boolean_true_add(json_nexthop_global,
9247 "used");
aef999a2
DA
9248 } else {
9249 if (nexthop_hostname)
7226bc40
TA
9250 len = vty_out(vty, "%pI4(%s)%s",
9251 &attr->mp_nexthop_global_in,
aef999a2
DA
9252 nexthop_hostname, vrf_id_str);
9253 else
7226bc40
TA
9254 len = vty_out(vty, "%pI4%s",
9255 &attr->mp_nexthop_global_in,
aef999a2
DA
9256 vrf_id_str);
9257
ae248832 9258 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9259 if (len < 1)
9260 vty_out(vty, "\n%*s", 36, " ");
9261 else
9262 vty_out(vty, "%*s", len, " ");
9263 }
d33fc23b 9264 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9265 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9266 if (json_paths) {
9267 json_nexthop_global = json_object_new_object();
515c2602 9268
026b914a
PG
9269 json_object_string_add(json_nexthop_global,
9270 "afi", "ipv4");
c949c771
DA
9271 json_object_string_addf(json_nexthop_global,
9272 "ip", "%pI4",
9273 &attr->nexthop);
515c2602 9274
939a97f4 9275 if (path->peer->hostname)
515c2602
DA
9276 json_object_string_add(
9277 json_nexthop_global, "hostname",
939a97f4 9278 path->peer->hostname);
515c2602 9279
50e05855
AD
9280 json_object_boolean_true_add(
9281 json_nexthop_global,
026b914a
PG
9282 "used");
9283 } else {
aef999a2
DA
9284 if (nexthop_hostname)
9285 len = vty_out(vty, "%pI4(%s)%s",
9286 &attr->nexthop,
9287 nexthop_hostname,
9288 vrf_id_str);
9289 else
9290 len = vty_out(vty, "%pI4%s",
9291 &attr->nexthop,
9292 vrf_id_str);
9293
ae248832 9294 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9295 if (len < 1)
9296 vty_out(vty, "\n%*s", 36, " ");
9297 else
9298 vty_out(vty, "%*s", len, " ");
026b914a
PG
9299 }
9300 }
7226bc40 9301 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9302 if (json_paths) {
9303 json_nexthop_global = json_object_new_object();
d62a17ae 9304
c949c771
DA
9305 json_object_string_addf(json_nexthop_global, "ip",
9306 "%pI4", &attr->nexthop);
515c2602 9307
939a97f4 9308 if (path->peer->hostname)
515c2602
DA
9309 json_object_string_add(json_nexthop_global,
9310 "hostname",
939a97f4 9311 path->peer->hostname);
445c2480 9312
a4d82a8a
PZ
9313 json_object_string_add(json_nexthop_global, "afi",
9314 "ipv4");
445c2480
DS
9315 json_object_boolean_true_add(json_nexthop_global,
9316 "used");
9317 } else {
aef999a2
DA
9318 if (nexthop_hostname)
9319 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9320 nexthop_hostname, vrf_id_str);
9321 else
9322 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9323 vrf_id_str);
9df8b37c 9324
ae248832 9325 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9326 if (len < 1)
9327 vty_out(vty, "\n%*s", 36, " ");
9328 else
9329 vty_out(vty, "%*s", len, " ");
d62a17ae 9330 }
445c2480 9331 }
b05a1c8b 9332
445c2480 9333 /* IPv6 Next Hop */
7226bc40 9334 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9335 if (json_paths) {
9336 json_nexthop_global = json_object_new_object();
c949c771
DA
9337 json_object_string_addf(json_nexthop_global, "ip",
9338 "%pI6",
9339 &attr->mp_nexthop_global);
515c2602 9340
939a97f4 9341 if (path->peer->hostname)
515c2602
DA
9342 json_object_string_add(json_nexthop_global,
9343 "hostname",
939a97f4 9344 path->peer->hostname);
515c2602 9345
a4d82a8a
PZ
9346 json_object_string_add(json_nexthop_global, "afi",
9347 "ipv6");
9348 json_object_string_add(json_nexthop_global, "scope",
9349 "global");
445c2480
DS
9350
9351 /* We display both LL & GL if both have been
9352 * received */
0606039c
DA
9353 if ((attr->mp_nexthop_len
9354 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9355 || (path->peer->conf_if)) {
a4d82a8a 9356 json_nexthop_ll = json_object_new_object();
c949c771
DA
9357 json_object_string_addf(
9358 json_nexthop_ll, "ip", "%pI6",
9359 &attr->mp_nexthop_local);
515c2602 9360
939a97f4 9361 if (path->peer->hostname)
515c2602
DA
9362 json_object_string_add(
9363 json_nexthop_ll, "hostname",
939a97f4 9364 path->peer->hostname);
515c2602 9365
a4d82a8a
PZ
9366 json_object_string_add(json_nexthop_ll, "afi",
9367 "ipv6");
9368 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9369 "link-local");
d62a17ae 9370
a4d82a8a 9371 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9372 &attr->mp_nexthop_local)
9373 != 0)
9374 && !attr->mp_nexthop_prefer_global)
d62a17ae 9375 json_object_boolean_true_add(
a4d82a8a 9376 json_nexthop_ll, "used");
445c2480
DS
9377 else
9378 json_object_boolean_true_add(
a4d82a8a 9379 json_nexthop_global, "used");
445c2480
DS
9380 } else
9381 json_object_boolean_true_add(
9382 json_nexthop_global, "used");
9383 } else {
9384 /* Display LL if LL/Global both in table unless
9385 * prefer-global is set */
2bb8b49c
DS
9386 if (((attr->mp_nexthop_len
9387 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9388 && !attr->mp_nexthop_prefer_global)
9389 || (path->peer->conf_if)) {
9b6d8fcf 9390 if (path->peer->conf_if) {
a4d82a8a 9391 len = vty_out(vty, "%s",
9b6d8fcf 9392 path->peer->conf_if);
ae248832
MK
9393 /* len of IPv6 addr + max len of def
9394 * ifname */
9395 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9396
9397 if (len < 1)
a4d82a8a 9398 vty_out(vty, "\n%*s", 36, " ");
445c2480 9399 else
a4d82a8a 9400 vty_out(vty, "%*s", len, " ");
d62a17ae 9401 } else {
aef999a2
DA
9402 if (nexthop_hostname)
9403 len = vty_out(
9404 vty, "%pI6(%s)%s",
9405 &attr->mp_nexthop_local,
9406 nexthop_hostname,
9407 vrf_id_str);
9408 else
9409 len = vty_out(
9410 vty, "%pI6%s",
9411 &attr->mp_nexthop_local,
9412 vrf_id_str);
9413
ae248832 9414 len = wide ? (41 - len) : (16 - len);
d62a17ae 9415
9416 if (len < 1)
a4d82a8a 9417 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9418 else
a4d82a8a 9419 vty_out(vty, "%*s", len, " ");
d62a17ae 9420 }
445c2480 9421 } else {
aef999a2
DA
9422 if (nexthop_hostname)
9423 len = vty_out(vty, "%pI6(%s)%s",
9424 &attr->mp_nexthop_global,
9425 nexthop_hostname,
9426 vrf_id_str);
9427 else
9428 len = vty_out(vty, "%pI6%s",
9429 &attr->mp_nexthop_global,
9430 vrf_id_str);
9431
ae248832 9432 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9433
9434 if (len < 1)
9435 vty_out(vty, "\n%*s", 36, " ");
9436 else
9437 vty_out(vty, "%*s", len, " ");
d62a17ae 9438 }
9439 }
445c2480 9440 }
718e3744 9441
445c2480
DS
9442 /* MED/Metric */
9443 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9444 if (json_paths)
50e05855 9445 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9446 else if (wide)
9447 vty_out(vty, "%7u", attr->med);
0fbac0b4 9448 else
445c2480 9449 vty_out(vty, "%10u", attr->med);
ae248832
MK
9450 else if (!json_paths) {
9451 if (wide)
9452 vty_out(vty, "%*s", 7, " ");
9453 else
9454 vty_out(vty, "%*s", 10, " ");
9455 }
d62a17ae 9456
445c2480
DS
9457 /* Local Pref */
9458 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9459 if (json_paths)
50e05855 9460 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9461 attr->local_pref);
9462 else
445c2480
DS
9463 vty_out(vty, "%7u", attr->local_pref);
9464 else if (!json_paths)
9465 vty_out(vty, " ");
d62a17ae 9466
445c2480
DS
9467 if (json_paths)
9468 json_object_int_add(json_path, "weight", attr->weight);
9469 else
9470 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9471
47e12884
DA
9472 if (json_paths)
9473 json_object_string_addf(json_path, "peerId", "%pSU",
9474 &path->peer->su);
b05a1c8b 9475
445c2480
DS
9476 /* Print aspath */
9477 if (attr->aspath) {
0fbac0b4 9478 if (json_paths)
50e05855 9479 json_object_string_add(json_path, "path",
0fbac0b4
DA
9480 attr->aspath->str);
9481 else
e678b143 9482 aspath_print_vty(vty, attr->aspath);
d62a17ae 9483 }
f1aa5d8a 9484
445c2480
DS
9485 /* Print origin */
9486 if (json_paths)
a4d82a8a
PZ
9487 json_object_string_add(json_path, "origin",
9488 bgp_origin_long_str[attr->origin]);
445c2480
DS
9489 else
9490 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9491
9df8b37c 9492 if (json_paths) {
d071f237 9493 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9494 json_object_string_add(json_path, "esi",
9495 esi_to_str(&attr->esi,
9496 esi_buf, sizeof(esi_buf)));
9497 }
6f214dd3
CS
9498 if (safi == SAFI_EVPN &&
9499 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9500 json_ext_community = json_object_new_object();
b53e67a3
DA
9501 json_object_string_add(
9502 json_ext_community, "string",
9503 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9504 json_object_object_add(json_path,
9505 "extendedCommunity",
9506 json_ext_community);
9507 }
9508
9df8b37c
PZ
9509 if (nexthop_self)
9510 json_object_boolean_true_add(json_path,
9511 "announceNexthopSelf");
9512 if (nexthop_othervrf) {
9513 json_object_string_add(json_path, "nhVrfName",
9514 nexthop_vrfname);
9515
9516 json_object_int_add(json_path, "nhVrfId",
9517 ((nexthop_vrfid == VRF_UNKNOWN)
9518 ? -1
9519 : (int)nexthop_vrfid));
9520 }
9521 }
9522
d62a17ae 9523 if (json_paths) {
9524 if (json_nexthop_global || json_nexthop_ll) {
9525 json_nexthops = json_object_new_array();
f1aa5d8a 9526
d62a17ae 9527 if (json_nexthop_global)
9528 json_object_array_add(json_nexthops,
9529 json_nexthop_global);
f1aa5d8a 9530
d62a17ae 9531 if (json_nexthop_ll)
9532 json_object_array_add(json_nexthops,
9533 json_nexthop_ll);
f1aa5d8a 9534
d62a17ae 9535 json_object_object_add(json_path, "nexthops",
9536 json_nexthops);
9537 }
9538
9539 json_object_array_add(json_paths, json_path);
9540 } else {
9541 vty_out(vty, "\n");
6f214dd3 9542
b5e140c8 9543 if (safi == SAFI_EVPN) {
d071f237 9544 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9545 /* XXX - add these params to the json out */
b5e140c8 9546 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9547 vty_out(vty, "ESI:%s",
9548 esi_to_str(&attr->esi, esi_buf,
9549 sizeof(esi_buf)));
60605cbc 9550
229587fb 9551 vty_out(vty, "\n");
b5e140c8
AK
9552 }
9553 if (attr->flag &
9554 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9555 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9556 vty_out(vty, "%s\n",
9557 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9558 }
6f214dd3
CS
9559 }
9560
49e5a4a0 9561#ifdef ENABLE_BGP_VNC
d62a17ae 9562 /* prints an additional line, indented, with VNC info, if
9563 * present */
9564 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9565 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9566#endif
d62a17ae 9567 }
9568}
718e3744 9569
9570/* called from terminal list command */
7d3cae70
DA
9571void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9572 const struct prefix *p, struct attr *attr, safi_t safi,
9573 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9574{
9575 json_object *json_status = NULL;
9576 json_object *json_net = NULL;
aef999a2 9577 int len;
d62a17ae 9578 char buff[BUFSIZ];
dc387b0f 9579
d62a17ae 9580 /* Route status display. */
9581 if (use_json) {
9582 json_status = json_object_new_object();
9583 json_net = json_object_new_object();
9584 } else {
146c574b 9585 vty_out(vty, " *");
d62a17ae 9586 vty_out(vty, ">");
9587 vty_out(vty, " ");
9588 }
718e3744 9589
d62a17ae 9590 /* print prefix and mask */
50e05855 9591 if (use_json) {
dc387b0f
LK
9592 if (safi == SAFI_EVPN)
9593 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9594 else if (p->family == AF_INET || p->family == AF_INET6) {
9595 json_object_string_add(
9596 json_net, "addrPrefix",
9597 inet_ntop(p->family, &p->u.prefix, buff,
9598 BUFSIZ));
9599 json_object_int_add(json_net, "prefixLen",
9600 p->prefixlen);
67d7e256 9601 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9602 }
50e05855 9603 } else
7d3cae70 9604 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9605
9606 /* Print attribute */
9607 if (attr) {
9608 if (use_json) {
7226bc40
TA
9609 if (p->family == AF_INET &&
9610 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9611 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9612 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9613 json_object_string_addf(
9614 json_net, "nextHop", "%pI4",
9615 &attr->mp_nexthop_global_in);
d62a17ae 9616 else
c949c771
DA
9617 json_object_string_addf(
9618 json_net, "nextHop", "%pI4",
9619 &attr->nexthop);
7226bc40
TA
9620 } else if (p->family == AF_INET6 ||
9621 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9622 json_object_string_addf(
9623 json_net, "nextHopGlobal", "%pI6",
9624 &attr->mp_nexthop_global);
7226bc40
TA
9625 } else if (p->family == AF_EVPN &&
9626 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9627 json_object_string_addf(
9628 json_net, "nextHop", "%pI4",
9629 &attr->mp_nexthop_global_in);
23d0a753 9630 }
d62a17ae 9631
9632 if (attr->flag
9633 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9634 json_object_int_add(json_net, "metric",
9635 attr->med);
9636
0fbac0b4 9637 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9638 json_object_int_add(json_net, "locPrf",
0fbac0b4 9639 attr->local_pref);
d62a17ae 9640
9641 json_object_int_add(json_net, "weight", attr->weight);
9642
9643 /* Print aspath */
0fbac0b4 9644 if (attr->aspath)
50e05855 9645 json_object_string_add(json_net, "path",
0fbac0b4 9646 attr->aspath->str);
d62a17ae 9647
9648 /* Print origin */
dd426a51
DA
9649#if CONFDATE > 20231208
9650CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9651#endif
d62a17ae 9652 json_object_string_add(json_net, "bgpOriginCode",
9653 bgp_origin_str[attr->origin]);
dd426a51
DA
9654 json_object_string_add(
9655 json_net, "origin",
9656 bgp_origin_long_str[attr->origin]);
d62a17ae 9657 } else {
7226bc40
TA
9658 if (p->family == AF_INET &&
9659 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9660 safi == SAFI_EVPN ||
9661 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9662 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9663 || safi == SAFI_EVPN)
23d0a753
DA
9664 vty_out(vty, "%-16pI4",
9665 &attr->mp_nexthop_global_in);
ae248832 9666 else if (wide)
23d0a753 9667 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9668 else
23d0a753 9669 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9670 } else if (p->family == AF_INET6 ||
9671 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9672 len = vty_out(vty, "%pI6",
9673 &attr->mp_nexthop_global);
ae248832 9674 len = wide ? (41 - len) : (16 - len);
d62a17ae 9675 if (len < 1)
9676 vty_out(vty, "\n%*s", 36, " ");
9677 else
9678 vty_out(vty, "%*s", len, " ");
9679 }
9680 if (attr->flag
9681 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9682 if (wide)
9683 vty_out(vty, "%7u", attr->med);
9684 else
9685 vty_out(vty, "%10u", attr->med);
9686 else if (wide)
9687 vty_out(vty, " ");
d62a17ae 9688 else
9689 vty_out(vty, " ");
718e3744 9690
d62a17ae 9691 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9692 vty_out(vty, "%7u", attr->local_pref);
9693 else
9694 vty_out(vty, " ");
9695
9696 vty_out(vty, "%7u ", attr->weight);
9697
9698 /* Print aspath */
9699 if (attr->aspath)
e678b143 9700 aspath_print_vty(vty, attr->aspath);
d62a17ae 9701
9702 /* Print origin */
9703 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9704 }
9705 }
9706 if (use_json) {
4d65410c
DA
9707 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9708
dd426a51
DA
9709#if CONFDATE > 20231208
9710CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9711#endif
d62a17ae 9712 json_object_boolean_true_add(json_status, "*");
9713 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9714 json_object_boolean_true_add(json_net, "valid");
9715 json_object_boolean_true_add(json_net, "best");
4d65410c 9716
dd426a51 9717 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9718 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9719 json_object_boolean_true_add(json_net, "multipath");
9720 }
d62a17ae 9721 json_object_object_add(json_net, "appliedStatusSymbols",
9722 json_status);
511211bf 9723 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9724 } else
9725 vty_out(vty, "\n");
9726}
9727
bd494ec5 9728void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9729 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9730 json_object *json)
9731{
9732 json_object *json_out = NULL;
9733 struct attr *attr;
9734 mpls_label_t label = MPLS_INVALID_LABEL;
9735
9b6d8fcf 9736 if (!path->extra)
d62a17ae 9737 return;
9738
9739 if (json)
9740 json_out = json_object_new_object();
9741
9742 /* short status lead text */
82c298be 9743 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9744
9745 /* print prefix and mask */
9746 if (json == NULL) {
9747 if (!display)
7d3cae70 9748 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9749 else
9750 vty_out(vty, "%*s", 17, " ");
9751 }
9752
9753 /* Print attribute */
9b6d8fcf 9754 attr = path->attr;
7226bc40
TA
9755 if (((p->family == AF_INET) &&
9756 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9757 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9758 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9759 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9760 || safi == SAFI_EVPN) {
9761 if (json)
c949c771
DA
9762 json_object_string_addf(
9763 json_out, "mpNexthopGlobalIn", "%pI4",
9764 &attr->mp_nexthop_global_in);
05864da7 9765 else
23d0a753
DA
9766 vty_out(vty, "%-16pI4",
9767 &attr->mp_nexthop_global_in);
05864da7
DS
9768 } else {
9769 if (json)
c949c771
DA
9770 json_object_string_addf(json_out, "nexthop",
9771 "%pI4", &attr->nexthop);
05864da7 9772 else
23d0a753 9773 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9774 }
7226bc40
TA
9775 } else if (((p->family == AF_INET6) &&
9776 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9777 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9778 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9779 char buf_a[512];
9780
9781 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9782 if (json)
c949c771
DA
9783 json_object_string_addf(
9784 json_out, "mpNexthopGlobalIn", "%pI6",
9785 &attr->mp_nexthop_global);
05864da7
DS
9786 else
9787 vty_out(vty, "%s",
9788 inet_ntop(AF_INET6,
9789 &attr->mp_nexthop_global,
9790 buf_a, sizeof(buf_a)));
9791 } else if (attr->mp_nexthop_len
9792 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9793 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9794 &attr->mp_nexthop_global,
9795 &attr->mp_nexthop_local);
9796 if (json)
9797 json_object_string_add(json_out,
9798 "mpNexthopGlobalLocal",
9799 buf_a);
9800 else
9801 vty_out(vty, "%s", buf_a);
d62a17ae 9802 }
9803 }
9804
9b6d8fcf 9805 label = decode_label(&path->extra->label[0]);
d62a17ae 9806
9807 if (bgp_is_valid_label(&label)) {
9808 if (json) {
9809 json_object_int_add(json_out, "notag", label);
9810 json_object_array_add(json, json_out);
9811 } else {
9812 vty_out(vty, "notag/%d", label);
9813 vty_out(vty, "\n");
9814 }
700ddfed
PG
9815 } else if (!json)
9816 vty_out(vty, "\n");
d62a17ae 9817}
718e3744 9818
bd494ec5 9819void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9820 struct bgp_path_info *path, int display,
d62a17ae 9821 json_object *json_paths)
718e3744 9822{
d62a17ae 9823 struct attr *attr;
d62a17ae 9824 json_object *json_path = NULL;
14f51eba
LK
9825 json_object *json_nexthop = NULL;
9826 json_object *json_overlay = NULL;
856ca177 9827
9b6d8fcf 9828 if (!path->extra)
d62a17ae 9829 return;
718e3744 9830
14f51eba
LK
9831 if (json_paths) {
9832 json_path = json_object_new_object();
9833 json_overlay = json_object_new_object();
9834 json_nexthop = json_object_new_object();
9835 }
9836
d62a17ae 9837 /* short status lead text */
82c298be 9838 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9839
d62a17ae 9840 /* print prefix and mask */
9841 if (!display)
7d3cae70 9842 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9843 else
9844 vty_out(vty, "%*s", 17, " ");
9845
9846 /* Print attribute */
9b6d8fcf 9847 attr = path->attr;
05864da7 9848 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9849
05864da7
DS
9850 switch (af) {
9851 case AF_INET:
05864da7 9852 if (!json_path) {
db66cf7c 9853 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9854 } else {
db66cf7c
DA
9855 json_object_string_addf(json_nexthop, "ip", "%pI4",
9856 &attr->mp_nexthop_global_in);
14f51eba 9857
05864da7 9858 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9859
05864da7
DS
9860 json_object_object_add(json_path, "nexthop",
9861 json_nexthop);
9862 }
9863 break;
9864 case AF_INET6:
05864da7 9865 if (!json_path) {
db66cf7c
DA
9866 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9867 &attr->mp_nexthop_local);
05864da7 9868 } else {
db66cf7c
DA
9869 json_object_string_addf(json_nexthop, "ipv6Global",
9870 "%pI6",
9871 &attr->mp_nexthop_global);
14f51eba 9872
db66cf7c
DA
9873 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9874 "%pI6",
9875 &attr->mp_nexthop_local);
14f51eba 9876
05864da7 9877 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9878
05864da7
DS
9879 json_object_object_add(json_path, "nexthop",
9880 json_nexthop);
9881 }
9882 break;
9883 default:
9884 if (!json_path) {
9885 vty_out(vty, "?");
9886 } else {
77a2f8e5
DA
9887 json_object_string_add(json_nexthop, "error",
9888 "Unsupported address-family");
d62a17ae 9889 }
05864da7 9890 }
988258b4 9891
6c924775
DS
9892 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9893
05864da7 9894 if (!json_path)
db66cf7c 9895 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9896 else
db66cf7c 9897 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9898
b53e67a3 9899 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9900 char *mac = NULL;
9901 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9902 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9903 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9904
9905 if (routermac)
9906 mac = ecom_mac2str((char *)routermac->val);
9907 if (mac) {
9908 if (!json_path) {
c4efd0f4 9909 vty_out(vty, "/%s", mac);
05864da7
DS
9910 } else {
9911 json_object_string_add(json_overlay, "rmac",
9912 mac);
988258b4 9913 }
05864da7 9914 XFREE(MTYPE_TMP, mac);
988258b4 9915 }
05864da7 9916 }
718e3744 9917
05864da7
DS
9918 if (!json_path) {
9919 vty_out(vty, "\n");
9920 } else {
9921 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9922
05864da7 9923 json_object_array_add(json_paths, json_path);
14f51eba 9924 }
d62a17ae 9925}
718e3744 9926
d62a17ae 9927/* dampening route */
5f040085
DS
9928static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9929 struct bgp_path_info *path, int display,
9930 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9931 json_object *json_paths)
d62a17ae 9932{
e5be8c1d 9933 struct attr *attr = path->attr;
d62a17ae 9934 int len;
9935 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9936 json_object *json_path = NULL;
9937
9938 if (use_json)
9939 json_path = json_object_new_object();
d62a17ae 9940
9941 /* short status lead text */
e5be8c1d 9942 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9943
9944 /* print prefix and mask */
9945 if (!use_json) {
9946 if (!display)
7d3cae70 9947 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9948 else
9949 vty_out(vty, "%*s", 17, " ");
d62a17ae 9950
e5be8c1d
DA
9951 len = vty_out(vty, "%s", path->peer->host);
9952 len = 17 - len;
9953
9954 if (len < 1)
d62a17ae 9955 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9956 else
9957 vty_out(vty, "%*s", len, " ");
d62a17ae 9958
9b6d8fcf
DS
9959 vty_out(vty, "%s ",
9960 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9961 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9962 use_json, NULL));
d62a17ae 9963
e5be8c1d 9964 if (attr->aspath)
e678b143 9965 aspath_print_vty(vty, attr->aspath);
05864da7 9966
05864da7
DS
9967 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9968
d62a17ae 9969 vty_out(vty, "\n");
e5be8c1d
DA
9970 } else {
9971 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9972 safi, use_json, json_path);
9973
9974 if (attr->aspath)
9975 json_object_string_add(json_path, "asPath",
9976 attr->aspath->str);
9977
9978 json_object_string_add(json_path, "origin",
9979 bgp_origin_str[attr->origin]);
9980 json_object_string_add(json_path, "peerHost", path->peer->host);
9981
9982 json_object_array_add(json_paths, json_path);
9983 }
d62a17ae 9984}
718e3744 9985
d62a17ae 9986/* flap route */
5f040085
DS
9987static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9988 struct bgp_path_info *path, int display,
9989 afi_t afi, safi_t safi, bool use_json,
31258046 9990 json_object *json_paths)
784d3a42 9991{
31258046 9992 struct attr *attr = path->attr;
d62a17ae 9993 struct bgp_damp_info *bdi;
9994 char timebuf[BGP_UPTIME_LEN];
9995 int len;
31258046 9996 json_object *json_path = NULL;
784d3a42 9997
9b6d8fcf 9998 if (!path->extra)
d62a17ae 9999 return;
784d3a42 10000
31258046
DA
10001 if (use_json)
10002 json_path = json_object_new_object();
10003
9b6d8fcf 10004 bdi = path->extra->damp_info;
784d3a42 10005
d62a17ae 10006 /* short status lead text */
31258046 10007 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10008
d62a17ae 10009 if (!use_json) {
10010 if (!display)
7d3cae70 10011 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10012 else
10013 vty_out(vty, "%*s", 17, " ");
784d3a42 10014
31258046
DA
10015 len = vty_out(vty, "%s", path->peer->host);
10016 len = 16 - len;
10017 if (len < 1)
d62a17ae 10018 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10019 else
10020 vty_out(vty, "%*s", len, " ");
784d3a42 10021
31258046
DA
10022 len = vty_out(vty, "%d", bdi->flap);
10023 len = 5 - len;
10024 if (len < 1)
d62a17ae 10025 vty_out(vty, " ");
d62a17ae 10026 else
10027 vty_out(vty, "%*s", len, " ");
d62a17ae 10028
996c9314
LB
10029 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10030 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10031
31258046
DA
10032 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10033 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10034 vty_out(vty, "%s ",
9b6d8fcf 10035 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10036 BGP_UPTIME_LEN, afi,
31258046
DA
10037 safi, use_json, NULL));
10038 else
d62a17ae 10039 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10040
31258046 10041 if (attr->aspath)
e678b143 10042 aspath_print_vty(vty, attr->aspath);
05864da7 10043
05864da7
DS
10044 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10045
d62a17ae 10046 vty_out(vty, "\n");
31258046
DA
10047 } else {
10048 json_object_string_add(json_path, "peerHost", path->peer->host);
10049 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10050
10051 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10052 json_path);
10053
10054 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10055 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10056 bgp_damp_reuse_time_vty(vty, path, timebuf,
10057 BGP_UPTIME_LEN, afi, safi,
10058 use_json, json_path);
10059
10060 if (attr->aspath)
10061 json_object_string_add(json_path, "asPath",
10062 attr->aspath->str);
10063
10064 json_object_string_add(json_path, "origin",
10065 bgp_origin_str[attr->origin]);
10066
10067 json_object_array_add(json_paths, json_path);
10068 }
d62a17ae 10069}
10070
10071static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10072 int *first, const char *header,
10073 json_object *json_adv_to)
10074{
d62a17ae 10075 json_object *json_peer = NULL;
10076
10077 if (json_adv_to) {
10078 /* 'advertised-to' is a dictionary of peers we have advertised
10079 * this
10080 * prefix too. The key is the peer's IP or swpX, the value is
10081 * the
10082 * hostname if we know it and "" if not.
10083 */
10084 json_peer = json_object_new_object();
10085
10086 if (peer->hostname)
10087 json_object_string_add(json_peer, "hostname",
10088 peer->hostname);
10089
10090 if (peer->conf_if)
10091 json_object_object_add(json_adv_to, peer->conf_if,
10092 json_peer);
10093 else
47e12884
DA
10094 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10095 &peer->su);
d62a17ae 10096 } else {
10097 if (*first) {
10098 vty_out(vty, "%s", header);
10099 *first = 0;
10100 }
10101
10102 if (peer->hostname
892fedb6 10103 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10104 if (peer->conf_if)
10105 vty_out(vty, " %s(%s)", peer->hostname,
10106 peer->conf_if);
10107 else
47e12884
DA
10108 vty_out(vty, " %s(%pSU)", peer->hostname,
10109 &peer->su);
d62a17ae 10110 } else {
10111 if (peer->conf_if)
10112 vty_out(vty, " %s", peer->conf_if);
10113 else
47e12884 10114 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10115 }
10116 }
784d3a42
PG
10117}
10118
dcc68b5e
MS
10119static void route_vty_out_tx_ids(struct vty *vty,
10120 struct bgp_addpath_info_data *d)
10121{
10122 int i;
10123
10124 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10125 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10126 d->addpath_tx_id[i],
10127 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10128 }
10129}
10130
5e4d4c8a 10131static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10132 struct bgp_path_info *pi,
10133 struct attr *attr,
10134 json_object *json_path)
5e4d4c8a
AK
10135{
10136 char esi_buf[ESI_STR_LEN];
10137 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10138 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10139 ATTR_ES_PEER_ROUTER);
10140 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10141 ATTR_ES_PEER_ACTIVE);
10142 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10143 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10144 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10145 if (json_path) {
10146 json_object *json_es_info = NULL;
10147
10148 json_object_string_add(
10149 json_path, "esi",
10150 esi_buf);
10151 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10152 json_es_info = json_object_new_object();
10153 if (es_local)
10154 json_object_boolean_true_add(
10155 json_es_info, "localEs");
10156 if (peer_active)
10157 json_object_boolean_true_add(
10158 json_es_info, "peerActive");
10159 if (peer_proxy)
10160 json_object_boolean_true_add(
10161 json_es_info, "peerProxy");
10162 if (peer_router)
10163 json_object_boolean_true_add(
10164 json_es_info, "peerRouter");
10165 if (attr->mm_sync_seqnum)
10166 json_object_int_add(
10167 json_es_info, "peerSeq",
10168 attr->mm_sync_seqnum);
10169 json_object_object_add(
10170 json_path, "es_info",
10171 json_es_info);
10172 }
10173 } else {
10174 if (bgp_evpn_attr_is_sync(attr))
10175 vty_out(vty,
10176 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10177 esi_buf,
10178 es_local ? "local-es":"",
10179 peer_proxy ? "proxy " : "",
10180 peer_active ? "active ":"",
10181 peer_router ? "router ":"",
10182 attr->mm_sync_seqnum);
10183 else
10184 vty_out(vty, " ESI %s %s\n",
10185 esi_buf,
10186 es_local ? "local-es":"");
10187 }
10188}
10189
4933eaaf 10190void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10191 const struct prefix *p, struct bgp_path_info *path,
10192 afi_t afi, safi_t safi,
4027d19b
DS
10193 enum rpki_states rpki_curr_state,
10194 json_object *json_paths)
d62a17ae 10195{
10196 char buf[INET6_ADDRSTRLEN];
100290e4 10197 char tag_buf[30];
515c2602 10198 struct attr *attr = path->attr;
d62a17ae 10199 time_t tbuf;
10200 json_object *json_bestpath = NULL;
10201 json_object *json_cluster_list = NULL;
10202 json_object *json_cluster_list_list = NULL;
10203 json_object *json_ext_community = NULL;
10204 json_object *json_last_update = NULL;
7fd077aa 10205 json_object *json_pmsi = NULL;
d62a17ae 10206 json_object *json_nexthop_global = NULL;
10207 json_object *json_nexthop_ll = NULL;
10208 json_object *json_nexthops = NULL;
10209 json_object *json_path = NULL;
10210 json_object *json_peer = NULL;
10211 json_object *json_string = NULL;
10212 json_object *json_adv_to = NULL;
10213 int first = 0;
10214 struct listnode *node, *nnode;
10215 struct peer *peer;
be92fc9f 10216 bool addpath_capable;
d62a17ae 10217 int has_adj;
10218 unsigned int first_as;
1defdda8 10219 bool nexthop_self =
9b6d8fcf 10220 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10221 int i;
2ba93fd6
DA
10222 char *nexthop_hostname =
10223 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10224 uint32_t ttl = 0;
10225 uint32_t bos = 0;
10226 uint32_t exp = 0;
10227 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10228 tag_buf[0] = '\0';
f0cde006
LS
10229 struct bgp_path_info *bpi_ultimate =
10230 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10231
10232 if (json_paths) {
10233 json_path = json_object_new_object();
10234 json_peer = json_object_new_object();
10235 json_nexthop_global = json_object_new_object();
10236 }
10237
8304dabf
AD
10238 if (safi == SAFI_EVPN) {
10239 if (!json_paths)
34c7f35f 10240 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10241 }
10242
44c69747 10243 if (path->extra) {
9b6d8fcf
DS
10244 if (path->extra && path->extra->num_labels) {
10245 bgp_evpn_label2str(path->extra->label,
10246 path->extra->num_labels, tag_buf,
a4d82a8a 10247 sizeof(tag_buf));
d62a17ae 10248 }
d7325ee7 10249 if (safi == SAFI_EVPN) {
44c69747 10250 if (!json_paths) {
44c69747
LK
10251 if (tag_buf[0] != '\0')
10252 vty_out(vty, " VNI %s", tag_buf);
44c69747 10253 } else {
1ce23106 10254 if (tag_buf[0])
77a2f8e5
DA
10255 json_object_string_add(json_path, "vni",
10256 tag_buf);
44c69747 10257 }
d7325ee7 10258 }
d62a17ae 10259 }
d62a17ae 10260
8304dabf
AD
10261 if (safi == SAFI_EVPN
10262 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10263 char gwip_buf[INET6_ADDRSTRLEN];
10264
860e740b
IR
10265 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10266 sizeof(gwip_buf));
8304dabf
AD
10267
10268 if (json_paths)
10269 json_object_string_add(json_path, "gatewayIP",
10270 gwip_buf);
10271 else
10272 vty_out(vty, " Gateway IP %s", gwip_buf);
10273 }
10274
2bf9780b 10275 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10276 vty_out(vty, "\n");
10277
100290e4
SW
10278
10279 if (path->extra && path->extra->parent && !json_paths) {
10280 struct bgp_path_info *parent_ri;
10281 struct bgp_dest *dest, *pdest;
10282
10283 parent_ri = (struct bgp_path_info *)path->extra->parent;
10284 dest = parent_ri->net;
10285 if (dest && dest->pdest) {
10286 pdest = dest->pdest;
10287 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10288 vty_out(vty, " Imported from ");
10289 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10290 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10291 pdest));
10292 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10293 (struct prefix_evpn *)
10294 bgp_dest_get_prefix(dest),
10295 tag_buf);
6012963e 10296 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10297 vty_out(vty, ", L3NHG %s",
6012963e
SW
10298 CHECK_FLAG(
10299 attr->es_flags,
10300 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10301 ? "active"
10302 : "inactive");
10303 vty_out(vty, "\n");
10304
4a8cd6ad
PG
10305 } else {
10306 vty_out(vty, " Imported from ");
10307 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10308 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10309 pdest));
10310 vty_out(vty, ":%pFX\n",
100290e4
SW
10311 (struct prefix_evpn *)
10312 bgp_dest_get_prefix(dest));
4a8cd6ad 10313 }
100290e4
SW
10314 }
10315 }
10316
05864da7
DS
10317 /* Line1 display AS-path, Aggregator */
10318 if (attr->aspath) {
10319 if (json_paths) {
10320 if (!attr->aspath->json)
10321 aspath_str_update(attr->aspath, true);
10322 json_object_lock(attr->aspath->json);
10323 json_object_object_add(json_path, "aspath",
10324 attr->aspath->json);
10325 } else {
10326 if (attr->aspath->segments)
e678b143 10327 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10328 else
05864da7 10329 vty_out(vty, " Local");
d62a17ae 10330 }
05864da7 10331 }
d62a17ae 10332
05864da7
DS
10333 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10334 if (json_paths)
10335 json_object_boolean_true_add(json_path, "removed");
10336 else
10337 vty_out(vty, ", (removed)");
10338 }
d62a17ae 10339
05864da7
DS
10340 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10341 if (json_paths)
10342 json_object_boolean_true_add(json_path, "stale");
10343 else
10344 vty_out(vty, ", (stale)");
10345 }
d62a17ae 10346
05864da7
DS
10347 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10348 if (json_paths) {
10349 json_object_int_add(json_path, "aggregatorAs",
10350 attr->aggregator_as);
c949c771
DA
10351 json_object_string_addf(json_path, "aggregatorId",
10352 "%pI4", &attr->aggregator_addr);
05864da7 10353 } else {
88d495a9
DA
10354 vty_out(vty, ", (aggregated by %u %pI4)",
10355 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10356 }
05864da7 10357 }
d62a17ae 10358
05864da7
DS
10359 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10360 PEER_FLAG_REFLECTOR_CLIENT)) {
10361 if (json_paths)
10362 json_object_boolean_true_add(json_path,
10363 "rxedFromRrClient");
10364 else
10365 vty_out(vty, ", (Received from a RR-client)");
10366 }
d62a17ae 10367
05864da7
DS
10368 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10369 PEER_FLAG_RSERVER_CLIENT)) {
10370 if (json_paths)
10371 json_object_boolean_true_add(json_path,
10372 "rxedFromRsClient");
10373 else
10374 vty_out(vty, ", (Received from a RS-client)");
10375 }
d62a17ae 10376
05864da7
DS
10377 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10378 if (json_paths)
10379 json_object_boolean_true_add(json_path,
10380 "dampeningHistoryEntry");
10381 else
10382 vty_out(vty, ", (history entry)");
10383 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10384 if (json_paths)
10385 json_object_boolean_true_add(json_path,
10386 "dampeningSuppressed");
10387 else
10388 vty_out(vty, ", (suppressed due to dampening)");
10389 }
d62a17ae 10390
05864da7
DS
10391 if (!json_paths)
10392 vty_out(vty, "\n");
d62a17ae 10393
05864da7
DS
10394 /* Line2 display Next-hop, Neighbor, Router-id */
10395 /* Display the nexthop */
b54892e0 10396
34c7f35f
SW
10397 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10398 p->family == AF_EVPN) &&
7226bc40
TA
10399 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10400 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10401 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10402 || safi == SAFI_EVPN) {
515c2602 10403 if (json_paths) {
c949c771
DA
10404 json_object_string_addf(
10405 json_nexthop_global, "ip", "%pI4",
10406 &attr->mp_nexthop_global_in);
515c2602 10407
939a97f4 10408 if (path->peer->hostname)
515c2602
DA
10409 json_object_string_add(
10410 json_nexthop_global, "hostname",
939a97f4 10411 path->peer->hostname);
aef999a2
DA
10412 } else {
10413 if (nexthop_hostname)
10414 vty_out(vty, " %pI4(%s)",
10415 &attr->mp_nexthop_global_in,
10416 nexthop_hostname);
10417 else
10418 vty_out(vty, " %pI4",
10419 &attr->mp_nexthop_global_in);
10420 }
d62a17ae 10421 } else {
515c2602 10422 if (json_paths) {
c949c771
DA
10423 json_object_string_addf(json_nexthop_global,
10424 "ip", "%pI4",
10425 &attr->nexthop);
515c2602 10426
939a97f4 10427 if (path->peer->hostname)
515c2602
DA
10428 json_object_string_add(
10429 json_nexthop_global, "hostname",
939a97f4 10430 path->peer->hostname);
aef999a2
DA
10431 } else {
10432 if (nexthop_hostname)
10433 vty_out(vty, " %pI4(%s)",
10434 &attr->nexthop,
10435 nexthop_hostname);
10436 else
10437 vty_out(vty, " %pI4",
10438 &attr->nexthop);
10439 }
d62a17ae 10440 }
10441
05864da7
DS
10442 if (json_paths)
10443 json_object_string_add(json_nexthop_global, "afi",
10444 "ipv4");
10445 } else {
10446 if (json_paths) {
c949c771
DA
10447 json_object_string_addf(json_nexthop_global, "ip",
10448 "%pI6",
10449 &attr->mp_nexthop_global);
515c2602 10450
939a97f4 10451 if (path->peer->hostname)
515c2602
DA
10452 json_object_string_add(json_nexthop_global,
10453 "hostname",
939a97f4 10454 path->peer->hostname);
515c2602 10455
05864da7
DS
10456 json_object_string_add(json_nexthop_global, "afi",
10457 "ipv6");
10458 json_object_string_add(json_nexthop_global, "scope",
10459 "global");
10460 } else {
aef999a2
DA
10461 if (nexthop_hostname)
10462 vty_out(vty, " %pI6(%s)",
10463 &attr->mp_nexthop_global,
10464 nexthop_hostname);
10465 else
10466 vty_out(vty, " %pI6",
10467 &attr->mp_nexthop_global);
d62a17ae 10468 }
05864da7 10469 }
d62a17ae 10470
05864da7 10471 /* Display the IGP cost or 'inaccessible' */
f0cde006 10472 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10473 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10474
10475 if (json_paths) {
05864da7
DS
10476 json_object_boolean_false_add(json_nexthop_global,
10477 "accessible");
95ba22d5
DA
10478 json_object_boolean_add(json_nexthop_global,
10479 "importCheckEnabled", import);
10480 } else {
10481 vty_out(vty, " (inaccessible%s)",
10482 import ? ", import-check enabled" : "");
10483 }
05864da7 10484 } else {
f0cde006 10485 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10486 if (json_paths)
f0cde006
LS
10487 json_object_int_add(
10488 json_nexthop_global, "metric",
10489 bpi_ultimate->extra->igpmetric);
d62a17ae 10490 else
05864da7 10491 vty_out(vty, " (metric %u)",
f0cde006 10492 bpi_ultimate->extra->igpmetric);
d62a17ae 10493 }
10494
05864da7 10495 /* IGP cost is 0, display this only for json */
d62a17ae 10496 else {
d62a17ae 10497 if (json_paths)
05864da7
DS
10498 json_object_int_add(json_nexthop_global,
10499 "metric", 0);
d62a17ae 10500 }
d62a17ae 10501
05864da7
DS
10502 if (json_paths)
10503 json_object_boolean_true_add(json_nexthop_global,
10504 "accessible");
10505 }
d62a17ae 10506
05864da7
DS
10507 /* Display peer "from" output */
10508 /* This path was originated locally */
10509 if (path->peer == bgp->peer_self) {
d62a17ae 10510
34c7f35f 10511 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10512 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10513 if (json_paths)
05864da7
DS
10514 json_object_string_add(json_peer, "peerId",
10515 "0.0.0.0");
d62a17ae 10516 else
05864da7
DS
10517 vty_out(vty, " from 0.0.0.0 ");
10518 } else {
d62a17ae 10519 if (json_paths)
05864da7
DS
10520 json_object_string_add(json_peer, "peerId",
10521 "::");
d62a17ae 10522 else
05864da7 10523 vty_out(vty, " from :: ");
d62a17ae 10524 }
d62a17ae 10525
4e9a9863 10526 if (json_paths)
c949c771
DA
10527 json_object_string_addf(json_peer, "routerId", "%pI4",
10528 &bgp->router_id);
4e9a9863 10529 else
23d0a753 10530 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10531 }
d62a17ae 10532
05864da7
DS
10533 /* We RXed this path from one of our peers */
10534 else {
10535
10536 if (json_paths) {
47e12884
DA
10537 json_object_string_addf(json_peer, "peerId", "%pSU",
10538 &path->peer->su);
c949c771
DA
10539 json_object_string_addf(json_peer, "routerId", "%pI4",
10540 &path->peer->remote_id);
05864da7
DS
10541
10542 if (path->peer->hostname)
10543 json_object_string_add(json_peer, "hostname",
10544 path->peer->hostname);
10545
10546 if (path->peer->domainname)
10547 json_object_string_add(json_peer, "domainname",
10548 path->peer->domainname);
10549
10550 if (path->peer->conf_if)
10551 json_object_string_add(json_peer, "interface",
10552 path->peer->conf_if);
10553 } else {
10554 if (path->peer->conf_if) {
10555 if (path->peer->hostname
892fedb6
DA
10556 && CHECK_FLAG(path->peer->bgp->flags,
10557 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10558 vty_out(vty, " from %s(%s)",
10559 path->peer->hostname,
10560 path->peer->conf_if);
d62a17ae 10561 else
05864da7 10562 vty_out(vty, " from %s",
9b6d8fcf 10563 path->peer->conf_if);
d62a17ae 10564 } else {
05864da7 10565 if (path->peer->hostname
892fedb6
DA
10566 && CHECK_FLAG(path->peer->bgp->flags,
10567 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10568 vty_out(vty, " from %s(%s)",
10569 path->peer->hostname,
10570 path->peer->host);
d62a17ae 10571 else
47e12884
DA
10572 vty_out(vty, " from %pSU",
10573 &path->peer->su);
d62a17ae 10574 }
d62a17ae 10575
05864da7 10576 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10577 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10578 else
07380148 10579 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10580 }
05864da7 10581 }
9df8b37c 10582
05864da7
DS
10583 /*
10584 * Note when vrfid of nexthop is different from that of prefix
10585 */
10586 if (path->extra && path->extra->bgp_orig) {
10587 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10588
05864da7
DS
10589 if (json_paths) {
10590 const char *vn;
9df8b37c 10591
05864da7
DS
10592 if (path->extra->bgp_orig->inst_type
10593 == BGP_INSTANCE_TYPE_DEFAULT)
10594 vn = VRF_DEFAULT_NAME;
10595 else
10596 vn = path->extra->bgp_orig->name;
9df8b37c 10597
05864da7 10598 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10599
05864da7
DS
10600 if (nexthop_vrfid == VRF_UNKNOWN) {
10601 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10602 } else {
05864da7
DS
10603 json_object_int_add(json_path, "nhVrfId",
10604 (int)nexthop_vrfid);
9df8b37c 10605 }
05864da7
DS
10606 } else {
10607 if (nexthop_vrfid == VRF_UNKNOWN)
10608 vty_out(vty, " vrf ?");
137147c6
DS
10609 else {
10610 struct vrf *vrf;
10611
10612 vrf = vrf_lookup_by_id(nexthop_vrfid);
10613 vty_out(vty, " vrf %s(%u)",
10614 VRF_LOGNAME(vrf), nexthop_vrfid);
10615 }
9df8b37c 10616 }
05864da7 10617 }
9df8b37c 10618
05864da7
DS
10619 if (nexthop_self) {
10620 if (json_paths) {
10621 json_object_boolean_true_add(json_path,
10622 "announceNexthopSelf");
10623 } else {
10624 vty_out(vty, " announce-nh-self");
9df8b37c 10625 }
05864da7 10626 }
9df8b37c 10627
05864da7
DS
10628 if (!json_paths)
10629 vty_out(vty, "\n");
d62a17ae 10630
05864da7
DS
10631 /* display the link-local nexthop */
10632 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10633 if (json_paths) {
10634 json_nexthop_ll = json_object_new_object();
c949c771
DA
10635 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10636 &attr->mp_nexthop_local);
515c2602 10637
939a97f4 10638 if (path->peer->hostname)
515c2602
DA
10639 json_object_string_add(json_nexthop_ll,
10640 "hostname",
939a97f4 10641 path->peer->hostname);
515c2602 10642
05864da7
DS
10643 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10644 json_object_string_add(json_nexthop_ll, "scope",
10645 "link-local");
d62a17ae 10646
05864da7
DS
10647 json_object_boolean_true_add(json_nexthop_ll,
10648 "accessible");
d62a17ae 10649
2bb8b49c 10650 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10651 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10652 "used");
10653 else
10654 json_object_boolean_true_add(
10655 json_nexthop_global, "used");
10656 } else {
10657 vty_out(vty, " (%s) %s\n",
10658 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10659 buf, INET6_ADDRSTRLEN),
2bb8b49c 10660 attr->mp_nexthop_prefer_global
05864da7
DS
10661 ? "(prefer-global)"
10662 : "(used)");
d62a17ae 10663 }
05864da7
DS
10664 }
10665 /* If we do not have a link-local nexthop then we must flag the
10666 global as "used" */
10667 else {
10668 if (json_paths)
10669 json_object_boolean_true_add(json_nexthop_global,
10670 "used");
10671 }
d62a17ae 10672
b5e140c8 10673 if (safi == SAFI_EVPN &&
5e4d4c8a 10674 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10675 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10676 }
10677
05864da7
DS
10678 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10679 * Int/Ext/Local, Atomic, best */
10680 if (json_paths)
10681 json_object_string_add(json_path, "origin",
10682 bgp_origin_long_str[attr->origin]);
10683 else
10684 vty_out(vty, " Origin %s",
10685 bgp_origin_long_str[attr->origin]);
9df8b37c 10686
05864da7 10687 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10688 if (json_paths)
05864da7 10689 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10690 else
05864da7
DS
10691 vty_out(vty, ", metric %u", attr->med);
10692 }
9df8b37c 10693
05864da7
DS
10694 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10695 if (json_paths)
0fbac0b4 10696 json_object_int_add(json_path, "locPrf",
05864da7
DS
10697 attr->local_pref);
10698 else
10699 vty_out(vty, ", localpref %u", attr->local_pref);
10700 }
9df8b37c 10701
97a52c82
DA
10702 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10703 if (json_paths)
10704 json_object_int_add(json_path, "aigpMetric",
10705 bgp_attr_get_aigp_metric(attr));
10706 else
10707 vty_out(vty, ", aigp-metric %" PRIu64,
10708 bgp_attr_get_aigp_metric(attr));
10709 }
10710
05864da7
DS
10711 if (attr->weight != 0) {
10712 if (json_paths)
10713 json_object_int_add(json_path, "weight", attr->weight);
10714 else
10715 vty_out(vty, ", weight %u", attr->weight);
10716 }
9df8b37c 10717
05864da7
DS
10718 if (attr->tag != 0) {
10719 if (json_paths)
10720 json_object_int_add(json_path, "tag", attr->tag);
10721 else
10722 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10723 }
9df8b37c 10724
05864da7
DS
10725 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10726 if (json_paths)
10727 json_object_boolean_false_add(json_path, "valid");
10728 else
10729 vty_out(vty, ", invalid");
10730 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10731 if (json_paths)
10732 json_object_boolean_true_add(json_path, "valid");
10733 else
10734 vty_out(vty, ", valid");
10735 }
9df8b37c 10736
7d3cae70
DA
10737 if (json_paths)
10738 json_object_int_add(json_path, "version", bn->version);
10739
05864da7
DS
10740 if (path->peer != bgp->peer_self) {
10741 if (path->peer->as == path->peer->local_as) {
10742 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10743 if (json_paths)
10744 json_object_string_add(
10745 json_peer, "type",
10746 "confed-internal");
d62a17ae 10747 else
05864da7 10748 vty_out(vty, ", confed-internal");
d62a17ae 10749 } else {
05864da7
DS
10750 if (json_paths)
10751 json_object_string_add(
10752 json_peer, "type", "internal");
10753 else
10754 vty_out(vty, ", internal");
9df8b37c 10755 }
05864da7
DS
10756 } else {
10757 if (bgp_confederation_peers_check(bgp,
10758 path->peer->as)) {
10759 if (json_paths)
10760 json_object_string_add(
10761 json_peer, "type",
10762 "confed-external");
d62a17ae 10763 else
05864da7 10764 vty_out(vty, ", confed-external");
d62a17ae 10765 } else {
05864da7
DS
10766 if (json_paths)
10767 json_object_string_add(
10768 json_peer, "type", "external");
10769 else
10770 vty_out(vty, ", external");
d62a17ae 10771 }
10772 }
05864da7
DS
10773 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10774 if (json_paths) {
10775 json_object_boolean_true_add(json_path, "aggregated");
10776 json_object_boolean_true_add(json_path, "local");
10777 } else {
10778 vty_out(vty, ", aggregated, local");
10779 }
10780 } else if (path->type != ZEBRA_ROUTE_BGP) {
10781 if (json_paths)
10782 json_object_boolean_true_add(json_path, "sourced");
10783 else
10784 vty_out(vty, ", sourced");
10785 } else {
10786 if (json_paths) {
10787 json_object_boolean_true_add(json_path, "sourced");
10788 json_object_boolean_true_add(json_path, "local");
10789 } else {
10790 vty_out(vty, ", sourced, local");
d62a17ae 10791 }
05864da7 10792 }
718e3744 10793
05864da7 10794 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10795 if (json_paths)
05864da7
DS
10796 json_object_boolean_true_add(json_path,
10797 "atomicAggregate");
d62a17ae 10798 else
05864da7
DS
10799 vty_out(vty, ", atomic-aggregate");
10800 }
d62a17ae 10801
d864dd9e
EB
10802 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10803 if (json_paths)
10804 json_object_int_add(json_path, "otc", attr->otc);
10805 else
10806 vty_out(vty, ", otc %u", attr->otc);
10807 }
10808
05864da7
DS
10809 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10810 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10811 && bgp_path_info_mpath_count(path))) {
10812 if (json_paths)
10813 json_object_boolean_true_add(json_path, "multipath");
10814 else
10815 vty_out(vty, ", multipath");
10816 }
50e05855 10817
05864da7
DS
10818 // Mark the bestpath(s)
10819 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10820 first_as = aspath_get_first_as(attr->aspath);
718e3744 10821
05864da7
DS
10822 if (json_paths) {
10823 if (!json_bestpath)
10824 json_bestpath = json_object_new_object();
10825 json_object_int_add(json_bestpath, "bestpathFromAs",
10826 first_as);
10827 } else {
10828 if (first_as)
10829 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10830 else
05864da7 10831 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10832 }
05864da7 10833 }
718e3744 10834
05864da7
DS
10835 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10836 if (json_paths) {
10837 if (!json_bestpath)
10838 json_bestpath = json_object_new_object();
10839 json_object_boolean_true_add(json_bestpath, "overall");
10840 json_object_string_add(
10841 json_bestpath, "selectionReason",
10842 bgp_path_selection_reason2str(bn->reason));
10843 } else {
10844 vty_out(vty, ", best");
10845 vty_out(vty, " (%s)",
10846 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10847 }
05864da7 10848 }
718e3744 10849
4027d19b 10850 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10851 if (json_paths)
10852 json_object_string_add(
10853 json_path, "rpkiValidationState",
4027d19b 10854 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10855 else
1d327209 10856 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10857 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10858 }
10859
05864da7
DS
10860 if (json_bestpath)
10861 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10862
05864da7
DS
10863 if (!json_paths)
10864 vty_out(vty, "\n");
10865
10866 /* Line 4 display Community */
29e72930 10867 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10868 if (json_paths) {
9a706b42
DA
10869 if (!bgp_attr_get_community(attr)->json)
10870 community_str(bgp_attr_get_community(attr),
c0945b78 10871 true, true);
9a706b42
DA
10872 json_object_lock(bgp_attr_get_community(attr)->json);
10873 json_object_object_add(
10874 json_path, "community",
10875 bgp_attr_get_community(attr)->json);
05864da7
DS
10876 } else {
10877 vty_out(vty, " Community: %s\n",
9a706b42 10878 bgp_attr_get_community(attr)->str);
d62a17ae 10879 }
05864da7 10880 }
718e3744 10881
05864da7
DS
10882 /* Line 5 display Extended-community */
10883 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10884 if (json_paths) {
10885 json_ext_community = json_object_new_object();
b53e67a3
DA
10886 json_object_string_add(
10887 json_ext_community, "string",
10888 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10889 json_object_object_add(json_path, "extendedCommunity",
10890 json_ext_community);
d62a17ae 10891 } else {
05864da7 10892 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10893 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10894 }
05864da7 10895 }
718e3744 10896
05864da7
DS
10897 /* Line 6 display Large community */
10898 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10899 if (json_paths) {
1bcf3a96
DA
10900 if (!bgp_attr_get_lcommunity(attr)->json)
10901 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10902 true, true);
1bcf3a96
DA
10903 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10904 json_object_object_add(
10905 json_path, "largeCommunity",
10906 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10907 } else {
10908 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10909 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10910 }
05864da7 10911 }
718e3744 10912
05864da7
DS
10913 /* Line 7 display Originator, Cluster-id */
10914 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10915 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10916 char buf[BUFSIZ] = {0};
10917
05864da7 10918 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10919 if (json_paths)
c949c771
DA
10920 json_object_string_addf(json_path,
10921 "originatorId", "%pI4",
10922 &attr->originator_id);
d62a17ae 10923 else
23d0a753
DA
10924 vty_out(vty, " Originator: %pI4",
10925 &attr->originator_id);
d62a17ae 10926 }
856ca177 10927
05864da7 10928 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10929 struct cluster_list *cluster =
10930 bgp_attr_get_cluster(attr);
05864da7 10931 int i;
d62a17ae 10932
10933 if (json_paths) {
05864da7
DS
10934 json_cluster_list = json_object_new_object();
10935 json_cluster_list_list =
10936 json_object_new_array();
10937
779fee93 10938 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10939 json_string = json_object_new_string(
779fee93
DS
10940 inet_ntop(AF_INET,
10941 &cluster->list[i],
10942 buf, sizeof(buf)));
05864da7
DS
10943 json_object_array_add(
10944 json_cluster_list_list,
10945 json_string);
10946 }
718e3744 10947
05864da7
DS
10948 /*
10949 * struct cluster_list does not have
10950 * "str" variable like aspath and community
10951 * do. Add this someday if someone asks
10952 * for it.
10953 * json_object_string_add(json_cluster_list,
779fee93 10954 * "string", cluster->str);
05864da7
DS
10955 */
10956 json_object_object_add(json_cluster_list,
10957 "list",
10958 json_cluster_list_list);
10959 json_object_object_add(json_path, "clusterList",
10960 json_cluster_list);
0dc8ee70 10961 } else {
05864da7
DS
10962 vty_out(vty, ", Cluster list: ");
10963
779fee93 10964 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10965 vty_out(vty, "%pI4 ",
779fee93 10966 &cluster->list[i]);
05864da7 10967 }
0dc8ee70 10968 }
d62a17ae 10969 }
718e3744 10970
d62a17ae 10971 if (!json_paths)
10972 vty_out(vty, "\n");
05864da7 10973 }
d62a17ae 10974
05864da7 10975 if (path->extra && path->extra->damp_info)
b4f7f45b 10976 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10977
05864da7
DS
10978 /* Remote Label */
10979 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10980 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10981 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10982 &bos);
d62a17ae 10983
05864da7
DS
10984 if (json_paths)
10985 json_object_int_add(json_path, "remoteLabel", label);
10986 else
10987 vty_out(vty, " Remote label: %d\n", label);
10988 }
d62a17ae 10989
e496b420
HS
10990 /* Remote SID */
10991 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10992 if (json_paths)
07380148
DA
10993 json_object_string_addf(json_path, "remoteSid", "%pI6",
10994 &path->extra->sid[0].sid);
e496b420 10995 else
07380148
DA
10996 vty_out(vty, " Remote SID: %pI6\n",
10997 &path->extra->sid[0].sid);
e496b420
HS
10998 }
10999
05864da7
DS
11000 /* Label Index */
11001 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11002 if (json_paths)
11003 json_object_int_add(json_path, "labelIndex",
11004 attr->label_index);
11005 else
11006 vty_out(vty, " Label Index: %d\n",
11007 attr->label_index);
11008 }
d62a17ae 11009
05864da7
DS
11010 /* Line 8 display Addpath IDs */
11011 if (path->addpath_rx_id
11012 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11013 if (json_paths) {
11014 json_object_int_add(json_path, "addpathRxId",
11015 path->addpath_rx_id);
d62a17ae 11016
05864da7
DS
11017 /* Keep backwards compatibility with the old API
11018 * by putting TX All's ID in the old field
11019 */
11020 json_object_int_add(
11021 json_path, "addpathTxId",
11022 path->tx_addpath
11023 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11024
05864da7
DS
11025 /* ... but create a specific field for each
11026 * strategy
11027 */
11028 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11029 json_object_int_add(
11030 json_path,
11031 bgp_addpath_names(i)->id_json_name,
11032 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11033 }
05864da7
DS
11034 } else {
11035 vty_out(vty, " AddPath ID: RX %u, ",
11036 path->addpath_rx_id);
d62a17ae 11037
05864da7 11038 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11039 }
05864da7 11040 }
520d5d76 11041
05864da7
DS
11042 /* If we used addpath to TX a non-bestpath we need to display
11043 * "Advertised to" on a path-by-path basis
11044 */
11045 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11046 first = 1;
dcc68b5e 11047
05864da7
DS
11048 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11049 addpath_capable =
11050 bgp_addpath_encode_tx(peer, afi, safi);
11051 has_adj = bgp_adj_out_lookup(
11052 peer, path->net,
11053 bgp_addpath_id_for_peer(peer, afi, safi,
11054 &path->tx_addpath));
11055
11056 if ((addpath_capable && has_adj)
11057 || (!addpath_capable && has_adj
11058 && CHECK_FLAG(path->flags,
11059 BGP_PATH_SELECTED))) {
11060 if (json_path && !json_adv_to)
11061 json_adv_to = json_object_new_object();
dcc68b5e 11062
05864da7
DS
11063 route_vty_out_advertised_to(
11064 vty, peer, &first,
11065 " Advertised to:", json_adv_to);
d62a17ae 11066 }
11067 }
718e3744 11068
05864da7
DS
11069 if (json_path) {
11070 if (json_adv_to) {
11071 json_object_object_add(
11072 json_path, "advertisedTo", json_adv_to);
d62a17ae 11073 }
05864da7
DS
11074 } else {
11075 if (!first) {
11076 vty_out(vty, "\n");
d62a17ae 11077 }
11078 }
05864da7 11079 }
b05a1c8b 11080
05864da7 11081 /* Line 9 display Uptime */
083ec940 11082 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11083 if (json_paths) {
11084 json_last_update = json_object_new_object();
11085 json_object_int_add(json_last_update, "epoch", tbuf);
11086 json_object_string_add(json_last_update, "string",
11087 ctime(&tbuf));
11088 json_object_object_add(json_path, "lastUpdate",
11089 json_last_update);
11090 } else
11091 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11092
05864da7
DS
11093 /* Line 10 display PMSI tunnel attribute, if present */
11094 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11095 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11096 bgp_attr_get_pmsi_tnl_type(attr),
11097 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11098
05864da7
DS
11099 if (json_paths) {
11100 json_pmsi = json_object_new_object();
11101 json_object_string_add(json_pmsi, "tunnelType", str);
11102 json_object_int_add(json_pmsi, "label",
11103 label2vni(&attr->label));
11104 json_object_object_add(json_path, "pmsi", json_pmsi);
11105 } else
11106 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11107 str, label2vni(&attr->label));
d62a17ae 11108 }
f1aa5d8a 11109
848e8cf6
DA
11110 if (path->peer->t_gr_restart &&
11111 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11112 unsigned long gr_remaining =
4f830a07 11113 event_timer_remain_second(path->peer->t_gr_restart);
848e8cf6
DA
11114
11115 if (json_paths) {
11116 json_object_int_add(json_path,
11117 "gracefulRestartSecondsRemaining",
11118 gr_remaining);
11119 } else
11120 vty_out(vty,
11121 " Time until Graceful Restart stale route deleted: %lu\n",
11122 gr_remaining);
11123 }
11124
9a706b42
DA
11125 if (path->peer->t_llgr_stale[afi][safi] &&
11126 bgp_attr_get_community(attr) &&
11127 community_include(bgp_attr_get_community(attr),
11128 COMMUNITY_LLGR_STALE)) {
4f830a07 11129 unsigned long llgr_remaining = event_timer_remain_second(
48ebba04 11130 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11131
48ebba04
DA
11132 if (json_paths) {
11133 json_object_int_add(json_path, "llgrSecondsRemaining",
11134 llgr_remaining);
11135 } else
11136 vty_out(vty,
11137 " Time until Long-lived stale route deleted: %lu\n",
11138 llgr_remaining);
11139 }
11140
92269aa2
DS
11141 /* Output some debug about internal state of the dest flags */
11142 if (json_paths) {
11143 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11144 json_object_boolean_true_add(json_path, "processScheduled");
11145 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11146 json_object_boolean_true_add(json_path, "userCleared");
11147 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11148 json_object_boolean_true_add(json_path, "labelChanged");
11149 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11150 json_object_boolean_true_add(json_path, "registeredForLabel");
11151 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11152 json_object_boolean_true_add(json_path, "selectDefered");
11153 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11154 json_object_boolean_true_add(json_path, "fibInstalled");
11155 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11156 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11157
d62a17ae 11158 if (json_nexthop_global || json_nexthop_ll) {
11159 json_nexthops = json_object_new_array();
f1aa5d8a 11160
d62a17ae 11161 if (json_nexthop_global)
11162 json_object_array_add(json_nexthops,
11163 json_nexthop_global);
f1aa5d8a 11164
d62a17ae 11165 if (json_nexthop_ll)
11166 json_object_array_add(json_nexthops,
11167 json_nexthop_ll);
f1aa5d8a 11168
d62a17ae 11169 json_object_object_add(json_path, "nexthops",
11170 json_nexthops);
11171 }
11172
11173 json_object_object_add(json_path, "peer", json_peer);
11174 json_object_array_add(json_paths, json_path);
05864da7 11175 }
b366b518
BB
11176}
11177
96ade3ed 11178#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11179#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11180#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11181
a4d82a8a 11182static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11183 afi_t afi, safi_t safi, enum bgp_show_type type,
11184 bool use_json);
7f323236
DW
11185static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11186 const char *comstr, int exact, afi_t afi,
96c81f66 11187 safi_t safi, uint16_t show_flags);
d62a17ae 11188
1ae44dfc 11189static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11190 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11191 void *output_arg, const char *rd, int is_last,
96f3485c 11192 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11193 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11194 enum rpki_states rpki_target_state)
d62a17ae 11195{
40381db7 11196 struct bgp_path_info *pi;
9bcb3eef 11197 struct bgp_dest *dest;
2aad8c42
MS
11198 bool header = true;
11199 bool json_detail_header = false;
d62a17ae 11200 int display;
1ae44dfc
LB
11201 unsigned long output_count = 0;
11202 unsigned long total_count = 0;
d62a17ae 11203 struct prefix *p;
d62a17ae 11204 json_object *json_paths = NULL;
11205 int first = 1;
96f3485c
MK
11206 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11207 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11208 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11209 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11210 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11211
1ae44dfc 11212 if (output_cum && *output_cum != 0)
2aad8c42 11213 header = false;
1ae44dfc 11214
9386b588 11215 if (use_json && !*json_header_depth) {
96f3485c
MK
11216 if (all)
11217 *json_header_depth = 1;
11218 else {
11219 vty_out(vty, "{\n");
11220 *json_header_depth = 2;
11221 }
d62a17ae 11222 vty_out(vty,
23d0a753
DA
11223 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11224 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11225 " \"localAS\": ",
a8bf7d9c 11226 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11227 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11228 ? VRF_DEFAULT_NAME
11229 : bgp->name,
11230 table->version, &bgp->router_id,
e84c7c12
PG
11231 bgp->default_local_pref);
11232 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11233 ((bgp->asnotation == ASNOTATION_DOT) &&
11234 (bgp->as < UINT16_MAX)))
11235 vty_out(vty, "%u", bgp->as);
11236 else {
11237 vty_out(vty, "\"");
11238 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11239 vty_out(vty, "\"");
11240 }
11241 vty_out(vty, ",\n \"routes\": { ");
9386b588 11242 if (rd) {
445c2480 11243 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11244 ++*json_header_depth;
11245 }
d62a17ae 11246 }
718e3744 11247
445c2480
DS
11248 if (use_json && rd) {
11249 vty_out(vty, " \"%s\" : { ", rd);
11250 }
11251
2aad8c42 11252 /* Check for 'json detail', where we need header output once per dest */
67799a48 11253 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11254 type != bgp_show_type_damp_neighbor &&
11255 type != bgp_show_type_flap_statistics &&
11256 type != bgp_show_type_flap_neighbor)
11257 json_detail_header = true;
11258
d62a17ae 11259 /* Start processing of routes. */
9bcb3eef
DS
11260 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11261 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11262 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11263 bool json_detail_header_used = false;
b54892e0 11264
9bcb3eef 11265 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11266 if (pi == NULL)
98ce9a06 11267 continue;
d62a17ae 11268
98ce9a06 11269 display = 0;
98ce9a06
DS
11270 if (use_json)
11271 json_paths = json_object_new_array();
11272 else
11273 json_paths = NULL;
d62a17ae 11274
6f94b685 11275 for (; pi; pi = pi->next) {
9a706b42
DA
11276 struct community *picomm = NULL;
11277
11278 picomm = bgp_attr_get_community(pi->attr);
11279
98ce9a06 11280 total_count++;
1e2ce4f1 11281
7d3cae70
DA
11282 if (type == bgp_show_type_prefix_version) {
11283 uint32_t version =
11284 strtoul(output_arg, NULL, 10);
11285 if (dest->version < version)
11286 continue;
11287 }
11288
a70a28a5
DA
11289 if (type == bgp_show_type_community_alias) {
11290 char *alias = output_arg;
11291 char **communities;
11292 int num;
11293 bool found = false;
11294
9a706b42
DA
11295 if (picomm) {
11296 frrstr_split(picomm->str, " ",
11297 &communities, &num);
a70a28a5
DA
11298 for (int i = 0; i < num; i++) {
11299 const char *com2alias =
11300 bgp_community2alias(
11301 communities[i]);
cd9cc0e6
IR
11302 if (!found
11303 && strcmp(alias, com2alias)
11304 == 0)
a70a28a5 11305 found = true;
cd9cc0e6
IR
11306 XFREE(MTYPE_TMP,
11307 communities[i]);
a70a28a5 11308 }
cd9cc0e6 11309 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11310 }
11311
1bcf3a96
DA
11312 if (!found &&
11313 bgp_attr_get_lcommunity(pi->attr)) {
11314 frrstr_split(bgp_attr_get_lcommunity(
11315 pi->attr)
11316 ->str,
a70a28a5
DA
11317 " ", &communities, &num);
11318 for (int i = 0; i < num; i++) {
11319 const char *com2alias =
11320 bgp_community2alias(
11321 communities[i]);
cd9cc0e6
IR
11322 if (!found
11323 && strcmp(alias, com2alias)
11324 == 0)
a70a28a5 11325 found = true;
cd9cc0e6
IR
11326 XFREE(MTYPE_TMP,
11327 communities[i]);
a70a28a5 11328 }
cd9cc0e6 11329 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11330 }
11331
11332 if (!found)
11333 continue;
11334 }
11335
1e2ce4f1
DS
11336 if (type == bgp_show_type_rpki) {
11337 if (dest_p->family == AF_INET
11338 || dest_p->family == AF_INET6)
4027d19b 11339 rpki_curr_state = hook_call(
1e2ce4f1
DS
11340 bgp_rpki_prefix_status,
11341 pi->peer, pi->attr, dest_p);
4027d19b
DS
11342 if (rpki_target_state != RPKI_NOT_BEING_USED
11343 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11344 continue;
11345 }
11346
98ce9a06
DS
11347 if (type == bgp_show_type_flap_statistics
11348 || type == bgp_show_type_flap_neighbor
11349 || type == bgp_show_type_dampend_paths
11350 || type == bgp_show_type_damp_neighbor) {
40381db7 11351 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11352 continue;
11353 }
11354 if (type == bgp_show_type_regexp) {
11355 regex_t *regex = output_arg;
d62a17ae 11356
40381db7 11357 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11358 == REG_NOMATCH)
11359 continue;
11360 }
11361 if (type == bgp_show_type_prefix_list) {
11362 struct prefix_list *plist = output_arg;
d62a17ae 11363
9bcb3eef 11364 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11365 != PREFIX_PERMIT)
11366 continue;
11367 }
ed126382
DA
11368 if (type == bgp_show_type_access_list) {
11369 struct access_list *alist = output_arg;
11370
11371 if (access_list_apply(alist, dest_p) !=
11372 FILTER_PERMIT)
11373 continue;
11374 }
98ce9a06
DS
11375 if (type == bgp_show_type_filter_list) {
11376 struct as_list *as_list = output_arg;
d62a17ae 11377
40381db7 11378 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11379 != AS_FILTER_PERMIT)
11380 continue;
11381 }
11382 if (type == bgp_show_type_route_map) {
11383 struct route_map *rmap = output_arg;
9b6d8fcf 11384 struct bgp_path_info path;
636632c3
DA
11385 struct bgp_path_info_extra extra;
11386 struct attr dummy_attr = {};
b68885f9 11387 route_map_result_t ret;
d62a17ae 11388
6f4f49b2 11389 dummy_attr = *pi->attr;
d62a17ae 11390
636632c3
DA
11391 prep_for_rmap_apply(&path, &extra, dest, pi,
11392 pi->peer, &dummy_attr);
d62a17ae 11393
1782514f 11394 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11395 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11396 if (ret == RMAP_DENYMATCH)
11397 continue;
11398 }
11399 if (type == bgp_show_type_neighbor
11400 || type == bgp_show_type_flap_neighbor
11401 || type == bgp_show_type_damp_neighbor) {
11402 union sockunion *su = output_arg;
11403
40381db7
DS
11404 if (pi->peer == NULL
11405 || pi->peer->su_remote == NULL
11406 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11407 continue;
11408 }
11409 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11410 uint32_t destination;
d62a17ae 11411
9bcb3eef 11412 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11413 if (IN_CLASSC(destination)
9bcb3eef 11414 && dest_p->prefixlen == 24)
98ce9a06
DS
11415 continue;
11416 if (IN_CLASSB(destination)
9bcb3eef 11417 && dest_p->prefixlen == 16)
98ce9a06
DS
11418 continue;
11419 if (IN_CLASSA(destination)
9bcb3eef 11420 && dest_p->prefixlen == 8)
98ce9a06
DS
11421 continue;
11422 }
11423 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11424 p = output_arg;
9bcb3eef 11425 if (!prefix_match(p, dest_p))
98ce9a06
DS
11426 continue;
11427 }
11428 if (type == bgp_show_type_community_all) {
9a706b42 11429 if (!picomm)
98ce9a06
DS
11430 continue;
11431 }
11432 if (type == bgp_show_type_community) {
11433 struct community *com = output_arg;
d62a17ae 11434
9a706b42 11435 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11436 continue;
11437 }
11438 if (type == bgp_show_type_community_exact) {
11439 struct community *com = output_arg;
d62a17ae 11440
9a706b42 11441 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11442 continue;
11443 }
11444 if (type == bgp_show_type_community_list) {
11445 struct community_list *list = output_arg;
d62a17ae 11446
9a706b42 11447 if (!community_list_match(picomm, list))
98ce9a06
DS
11448 continue;
11449 }
a4d82a8a 11450 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11451 struct community_list *list = output_arg;
d62a17ae 11452
9a706b42 11453 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11454 continue;
11455 }
11456 if (type == bgp_show_type_lcommunity) {
11457 struct lcommunity *lcom = output_arg;
d62a17ae 11458
1bcf3a96
DA
11459 if (!bgp_attr_get_lcommunity(pi->attr) ||
11460 !lcommunity_match(
11461 bgp_attr_get_lcommunity(pi->attr),
11462 lcom))
98ce9a06
DS
11463 continue;
11464 }
36a206db 11465
11466 if (type == bgp_show_type_lcommunity_exact) {
11467 struct lcommunity *lcom = output_arg;
11468
1bcf3a96
DA
11469 if (!bgp_attr_get_lcommunity(pi->attr) ||
11470 !lcommunity_cmp(
11471 bgp_attr_get_lcommunity(pi->attr),
11472 lcom))
36a206db 11473 continue;
11474 }
98ce9a06
DS
11475 if (type == bgp_show_type_lcommunity_list) {
11476 struct community_list *list = output_arg;
d62a17ae 11477
1bcf3a96
DA
11478 if (!lcommunity_list_match(
11479 bgp_attr_get_lcommunity(pi->attr),
11480 list))
98ce9a06
DS
11481 continue;
11482 }
36a206db 11483 if (type
11484 == bgp_show_type_lcommunity_list_exact) {
11485 struct community_list *list = output_arg;
11486
11487 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11488 bgp_attr_get_lcommunity(pi->attr),
11489 list))
36a206db 11490 continue;
11491 }
98ce9a06 11492 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11493 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11494 continue;
11495 }
11496 if (type == bgp_show_type_dampend_paths
11497 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11498 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11499 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11500 continue;
11501 }
83856649
KQ
11502 if (type == bgp_show_type_self_originated) {
11503 if (pi->peer != bgp->peer_self)
11504 continue;
11505 }
98ce9a06
DS
11506
11507 if (!use_json && header) {
23d0a753
DA
11508 vty_out(vty,
11509 "BGP table version is %" PRIu64
11510 ", local router ID is %pI4, vrf id ",
11511 table->version, &bgp->router_id);
9df8b37c
PZ
11512 if (bgp->vrf_id == VRF_UNKNOWN)
11513 vty_out(vty, "%s", VRFID_NONE_STR);
11514 else
11515 vty_out(vty, "%u", bgp->vrf_id);
11516 vty_out(vty, "\n");
01eced22
AD
11517 vty_out(vty, "Default local pref %u, ",
11518 bgp->default_local_pref);
e84c7c12
PG
11519 vty_out(vty, "local AS ");
11520 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11521 &bgp->as);
11522 vty_out(vty, "\n");
509d82bd 11523 if (!detail_routes) {
9a1aae2d
DA
11524 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11525 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11526 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11527 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11528 }
d62a17ae 11529 if (type == bgp_show_type_dampend_paths
11530 || type == bgp_show_type_damp_neighbor)
98ce9a06 11531 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11532 else if (type == bgp_show_type_flap_statistics
11533 || type == bgp_show_type_flap_neighbor)
98ce9a06 11534 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11535 else if (!detail_routes)
ae248832
MK
11536 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11537 : BGP_SHOW_HEADER));
2aad8c42
MS
11538 header = false;
11539
d62a17ae 11540 }
98ce9a06
DS
11541 if (rd != NULL && !display && !output_count) {
11542 if (!use_json)
11543 vty_out(vty,
11544 "Route Distinguisher: %s\n",
11545 rd);
d62a17ae 11546 }
98ce9a06
DS
11547 if (type == bgp_show_type_dampend_paths
11548 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11549 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11550 AFI_IP, safi, use_json,
11551 json_paths);
98ce9a06
DS
11552 else if (type == bgp_show_type_flap_statistics
11553 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11554 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11555 AFI_IP, safi, use_json,
11556 json_paths);
f280c93b 11557 else {
27bb782a
DA
11558 if (detail_routes || detail_json) {
11559 const struct prefix_rd *prd = NULL;
9a1aae2d 11560
27bb782a
DA
11561 if (dest->pdest)
11562 prd = bgp_rd_from_dest(
11563 dest->pdest, safi);
9a1aae2d
DA
11564
11565 if (!use_json)
11566 route_vty_out_detail_header(
11567 vty, bgp, dest,
11568 bgp_dest_get_prefix(
11569 dest),
11570 prd, table->afi, safi,
f9f2d188 11571 NULL, false);
9a1aae2d 11572
f280c93b 11573 route_vty_out_detail(
27bb782a 11574 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11575 family2afi(dest_p->family),
11576 safi, RPKI_NOT_BEING_USED,
11577 json_paths);
9a1aae2d 11578 } else {
f280c93b
DA
11579 route_vty_out(vty, dest_p, pi, display,
11580 safi, json_paths, wide);
9a1aae2d 11581 }
f280c93b 11582 }
98ce9a06 11583 display++;
d62a17ae 11584 }
11585
98ce9a06
DS
11586 if (display) {
11587 output_count++;
11588 if (!use_json)
11589 continue;
11590
625d2931 11591 /* encode prefix */
9bcb3eef 11592 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11593 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11594
1840384b 11595
b54892e0
DS
11596 bgp_fs_nlri_get_string(
11597 (unsigned char *)
9bcb3eef
DS
11598 dest_p->u.prefix_flowspec.ptr,
11599 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11600 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11601 family2afi(dest_p->u
11602 .prefix_flowspec.family));
625d2931 11603 if (first)
b54892e0 11604 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11605 dest_p->u.prefix_flowspec
b54892e0 11606 .prefixlen);
625d2931 11607 else
b54892e0 11608 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11609 dest_p->u.prefix_flowspec
b54892e0 11610 .prefixlen);
625d2931 11611 } else {
625d2931 11612 if (first)
1b78780b 11613 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11614 else
1b78780b 11615 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11616 }
f9f2d188 11617
8ed85db6
TA
11618 /* This is used for 'json detail' vty keywords.
11619 *
11620 * In plain 'json' the per-prefix header is encoded
11621 * as a standalone dictionary in the first json_paths
11622 * array element:
11623 * "<prefix>": [{header}, {path-1}, {path-N}]
11624 * (which is confusing and borderline broken)
11625 *
11626 * For 'json detail' this changes the value
11627 * of each prefix-key to be a dictionary where each
11628 * header item has its own key, and json_paths is
11629 * tucked under the "paths" key:
11630 * "<prefix>": {
11631 * "<header-key-1>": <header-val-1>,
11632 * "<header-key-N>": <header-val-N>,
11633 * "paths": [{path-1}, {path-N}]
11634 * }
11635 */
f9f2d188
TA
11636 if (json_detail_header && json_paths != NULL) {
11637 const struct prefix_rd *prd;
11638
8ed85db6 11639 /* Start per-prefix dictionary */
f9f2d188
TA
11640 vty_out(vty, "{\n");
11641
11642 prd = bgp_rd_from_dest(dest, safi);
11643
11644 route_vty_out_detail_header(
11645 vty, bgp, dest,
11646 bgp_dest_get_prefix(dest), prd,
11647 table->afi, safi, json_paths, true);
11648
11649 vty_out(vty, "\"paths\": ");
11650 json_detail_header_used = true;
11651 }
11652
d7c6467b
DS
11653 /*
11654 * We are using no_pretty here because under
11655 * extremely high settings( say lots and lots of
11656 * routes with lots and lots of ways to reach
11657 * that route via different paths ) this can
11658 * save several minutes of output when FRR
11659 * is run on older cpu's or more underperforming
11660 * routers out there
11661 */
11662 vty_json_no_pretty(vty, json_paths);
f9f2d188 11663
8ed85db6 11664 /* End per-prefix dictionary */
f9f2d188
TA
11665 if (json_detail_header_used)
11666 vty_out(vty, "} ");
11667
449feb8e 11668 json_paths = NULL;
98ce9a06 11669 first = 0;
1f83ed02
DS
11670 } else
11671 json_object_free(json_paths);
98ce9a06
DS
11672 }
11673
1ae44dfc
LB
11674 if (output_cum) {
11675 output_count += *output_cum;
11676 *output_cum = output_count;
11677 }
11678 if (total_cum) {
11679 total_count += *total_cum;
11680 *total_cum = total_count;
11681 }
d62a17ae 11682 if (use_json) {
9386b588 11683 if (rd) {
a4d82a8a 11684 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11685 }
11686 if (is_last) {
a4d82a8a
PZ
11687 unsigned long i;
11688 for (i = 0; i < *json_header_depth; ++i)
11689 vty_out(vty, " } ");
96f3485c
MK
11690 if (!all)
11691 vty_out(vty, "\n");
9386b588 11692 }
d62a17ae 11693 } else {
1ae44dfc
LB
11694 if (is_last) {
11695 /* No route is displayed */
11696 if (output_count == 0) {
11697 if (type == bgp_show_type_normal)
11698 vty_out(vty,
11699 "No BGP prefixes displayed, %ld exist\n",
11700 total_count);
11701 } else
d62a17ae 11702 vty_out(vty,
1ae44dfc
LB
11703 "\nDisplayed %ld routes and %ld total paths\n",
11704 output_count, total_count);
11705 }
d62a17ae 11706 }
718e3744 11707
d62a17ae 11708 return CMD_SUCCESS;
718e3744 11709}
11710
1ae44dfc
LB
11711int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11712 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11713 enum bgp_show_type type, void *output_arg,
11714 uint16_t show_flags)
1ae44dfc 11715{
9bcb3eef 11716 struct bgp_dest *dest, *next;
1ae44dfc
LB
11717 unsigned long output_cum = 0;
11718 unsigned long total_cum = 0;
9386b588 11719 unsigned long json_header_depth = 0;
67009e22 11720 struct bgp_table *itable;
0136788c 11721 bool show_msg;
27bb782a 11722 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11723
11724 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11725
9bcb3eef
DS
11726 for (dest = bgp_table_top(table); dest; dest = next) {
11727 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11728
9bcb3eef
DS
11729 next = bgp_route_next(dest);
11730 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11731 continue;
67009e22 11732
9bcb3eef 11733 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11734 if (itable != NULL) {
1ae44dfc 11735 struct prefix_rd prd;
06b9f471 11736 char rd[RD_ADDRSTRLEN];
1ae44dfc 11737
9bcb3eef 11738 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11739 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11740 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11741 rd, next == NULL, &output_cum,
11742 &total_cum, &json_header_depth,
1e2ce4f1 11743 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11744 if (next == NULL)
11745 show_msg = false;
1ae44dfc
LB
11746 }
11747 }
0136788c
LB
11748 if (show_msg) {
11749 if (output_cum == 0)
11750 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11751 total_cum);
11752 else
11753 vty_out(vty,
11754 "\nDisplayed %ld routes and %ld total paths\n",
11755 output_cum, total_cum);
0224b329
DA
11756 } else {
11757 if (use_json && output_cum == 0)
11758 vty_out(vty, "{}\n");
0136788c 11759 }
1ae44dfc
LB
11760 return CMD_SUCCESS;
11761}
2aad8c42 11762
d62a17ae 11763static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11764 enum bgp_show_type type, void *output_arg,
96c81f66 11765 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11766{
d62a17ae 11767 struct bgp_table *table;
9386b588 11768 unsigned long json_header_depth = 0;
96f3485c 11769 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11770
d62a17ae 11771 if (bgp == NULL) {
11772 bgp = bgp_get_default();
11773 }
fee0f4c6 11774
d62a17ae 11775 if (bgp == NULL) {
11776 if (!use_json)
11777 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11778 else
11779 vty_out(vty, "{}\n");
d62a17ae 11780 return CMD_WARNING;
11781 }
4dd6177e 11782
cd8c2a27
MS
11783 /* Labeled-unicast routes live in the unicast table. */
11784 if (safi == SAFI_LABELED_UNICAST)
11785 safi = SAFI_UNICAST;
11786
1ae44dfc 11787 table = bgp->rib[afi][safi];
d62a17ae 11788 /* use MPLS and ENCAP specific shows until they are merged */
11789 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11790 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11791 output_arg, show_flags);
d62a17ae 11792 }
dba3c1d3
PG
11793
11794 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11795 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11796 output_arg, use_json,
11797 1, NULL, NULL);
11798 }
fee0f4c6 11799
0adc5bbb
LS
11800 if (safi == SAFI_EVPN)
11801 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11802
96f3485c 11803 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11804 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11805 rpki_target_state);
fee0f4c6 11806}
11807
d62a17ae 11808static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11809 safi_t safi, uint16_t show_flags)
f186de26 11810{
d62a17ae 11811 struct listnode *node, *nnode;
11812 struct bgp *bgp;
11813 int is_first = 1;
9f049418 11814 bool route_output = false;
96f3485c 11815 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11816
d62a17ae 11817 if (use_json)
11818 vty_out(vty, "{\n");
9f689658 11819
d62a17ae 11820 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11821 route_output = true;
d62a17ae 11822 if (use_json) {
11823 if (!is_first)
11824 vty_out(vty, ",\n");
11825 else
11826 is_first = 0;
11827
11828 vty_out(vty, "\"%s\":",
11829 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11830 ? VRF_DEFAULT_NAME
d62a17ae 11831 : bgp->name);
11832 } else {
11833 vty_out(vty, "\nInstance %s:\n",
11834 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11835 ? VRF_DEFAULT_NAME
d62a17ae 11836 : bgp->name);
11837 }
11838 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11839 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11840 }
9f689658 11841
d62a17ae 11842 if (use_json)
11843 vty_out(vty, "}\n");
9f049418
DS
11844 else if (!route_output)
11845 vty_out(vty, "%% BGP instance not found\n");
f186de26 11846}
11847
718e3744 11848/* Header of detailed BGP route information */
d62a17ae 11849void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11850 struct bgp_dest *dest, const struct prefix *p,
11851 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11852 safi_t safi, json_object *json,
11853 bool incremental_print)
d62a17ae 11854{
40381db7 11855 struct bgp_path_info *pi;
d62a17ae 11856 struct peer *peer;
11857 struct listnode *node, *nnode;
06b9f471 11858 char buf1[RD_ADDRSTRLEN];
d62a17ae 11859 int count = 0;
11860 int best = 0;
11861 int suppress = 0;
c5f1e1b2
C
11862 int accept_own = 0;
11863 int route_filter_translated_v4 = 0;
11864 int route_filter_v4 = 0;
11865 int route_filter_translated_v6 = 0;
11866 int route_filter_v6 = 0;
11867 int llgr_stale = 0;
11868 int no_llgr = 0;
11869 int accept_own_nexthop = 0;
11870 int blackhole = 0;
d62a17ae 11871 int no_export = 0;
11872 int no_advertise = 0;
11873 int local_as = 0;
c5f1e1b2 11874 int no_peer = 0;
d62a17ae 11875 int first = 1;
11876 int has_valid_label = 0;
11877 mpls_label_t label = 0;
11878 json_object *json_adv_to = NULL;
67f67ba4
DA
11879 uint32_t ttl = 0;
11880 uint32_t bos = 0;
11881 uint32_t exp = 0;
9bedbb1e 11882
67f67ba4 11883 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11884
67f67ba4 11885 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11886
44c69747 11887 if (safi == SAFI_EVPN) {
44c69747 11888 if (!json) {
2dbe669b 11889 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11890 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11891 bgp->asnotation)
f137734b 11892 : "",
2dbe669b 11893 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11894 } else {
4a8cd6ad
PG
11895 json_object_string_add(
11896 json, "rd",
11897 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11898 bgp->asnotation)
11899 : "");
44c69747
LK
11900 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11901 }
11902 } else {
11903 if (!json) {
9119ef3a
DA
11904 vty_out(vty,
11905 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11906 "\n",
d62a17ae 11907 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11908 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11909 sizeof(buf1),
11910 bgp->asnotation)
8228a9a7 11911 : ""),
9119ef3a
DA
11912 safi == SAFI_MPLS_VPN ? ":" : "", p,
11913 dest->version);
cd1964ff 11914
9119ef3a 11915 } else {
f9f2d188
TA
11916 if (incremental_print) {
11917 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11918 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11919 dest->version);
11920 } else {
11921 json_object_string_addf(json, "prefix", "%pFX",
11922 p);
11923 json_object_int_add(json, "version",
11924 dest->version);
11925 }
9119ef3a 11926 }
44c69747
LK
11927 }
11928
11929 if (has_valid_label) {
f9f2d188
TA
11930 if (json) {
11931 if (incremental_print)
11932 vty_out(vty, "\"localLabel\": \"%u\",\n",
11933 label);
11934 else
11935 json_object_int_add(json, "localLabel", label);
11936 } else
d62a17ae 11937 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11938 }
11939
11940 if (!json)
d62a17ae 11941 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11942 vty_out(vty, "not allocated\n");
718e3744 11943
9bcb3eef 11944 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11945 struct community *picomm = NULL;
11946
11947 picomm = bgp_attr_get_community(pi->attr);
11948
d62a17ae 11949 count++;
40381db7 11950 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11951 best = count;
4056a5f6 11952 if (bgp_path_suppressed(pi))
d62a17ae 11953 suppress = 1;
cee9c031 11954
9a706b42 11955 if (!picomm)
cee9c031
QY
11956 continue;
11957
11958 no_advertise += community_include(
9a706b42
DA
11959 picomm, COMMUNITY_NO_ADVERTISE);
11960 no_export +=
11961 community_include(picomm, COMMUNITY_NO_EXPORT);
11962 local_as +=
11963 community_include(picomm, COMMUNITY_LOCAL_AS);
11964 accept_own +=
11965 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11966 route_filter_translated_v4 += community_include(
9a706b42 11967 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11968 route_filter_translated_v6 += community_include(
9a706b42 11969 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11970 route_filter_v4 += community_include(
9a706b42 11971 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11972 route_filter_v6 += community_include(
9a706b42
DA
11973 picomm, COMMUNITY_ROUTE_FILTER_v6);
11974 llgr_stale +=
11975 community_include(picomm, COMMUNITY_LLGR_STALE);
11976 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11977 accept_own_nexthop += community_include(
11978 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11979 blackhole +=
11980 community_include(picomm, COMMUNITY_BLACKHOLE);
11981 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11982 }
718e3744 11983 }
718e3744 11984
d62a17ae 11985 if (!json) {
11986 vty_out(vty, "Paths: (%d available", count);
11987 if (best) {
11988 vty_out(vty, ", best #%d", best);
b84060bb
PG
11989 if (safi == SAFI_UNICAST) {
11990 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11991 vty_out(vty, ", table %s",
11992 VRF_DEFAULT_NAME);
11993 else
11994 vty_out(vty, ", vrf %s",
11995 bgp->name);
11996 }
d62a17ae 11997 } else
11998 vty_out(vty, ", no best path");
11999
c5f1e1b2
C
12000 if (accept_own)
12001 vty_out(vty,
12002 ", accept own local route exported and imported in different VRF");
12003 else if (route_filter_translated_v4)
12004 vty_out(vty,
12005 ", mark translated RTs for VPNv4 route filtering");
12006 else if (route_filter_v4)
12007 vty_out(vty,
12008 ", attach RT as-is for VPNv4 route filtering");
12009 else if (route_filter_translated_v6)
12010 vty_out(vty,
12011 ", mark translated RTs for VPNv6 route filtering");
12012 else if (route_filter_v6)
12013 vty_out(vty,
12014 ", attach RT as-is for VPNv6 route filtering");
12015 else if (llgr_stale)
12016 vty_out(vty,
1479ed2f 12017 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
12018 else if (no_llgr)
12019 vty_out(vty,
12020 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12021 else if (accept_own_nexthop)
12022 vty_out(vty,
12023 ", accept local nexthop");
12024 else if (blackhole)
12025 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 12026 else if (no_export)
12027 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
12028 else if (no_advertise)
12029 vty_out(vty, ", not advertised to any peer");
d62a17ae 12030 else if (local_as)
12031 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
12032 else if (no_peer)
12033 vty_out(vty,
12034 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 12035
12036 if (suppress)
12037 vty_out(vty,
12038 ", Advertisements suppressed by an aggregate.");
12039 vty_out(vty, ")\n");
12040 }
718e3744 12041
d62a17ae 12042 /* If we are not using addpath then we can display Advertised to and
12043 * that will
12044 * show what peers we advertised the bestpath to. If we are using
12045 * addpath
12046 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12047 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12048 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12049 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12050 if (json && !json_adv_to)
12051 json_adv_to = json_object_new_object();
12052
12053 route_vty_out_advertised_to(
12054 vty, peer, &first,
12055 " Advertised to non peer-group peers:\n ",
12056 json_adv_to);
12057 }
12058 }
12059
f9f2d188
TA
12060 if (json && json_adv_to) {
12061 if (incremental_print) {
12062 vty_out(vty, "\"advertisedTo\": ");
12063 vty_json(vty, json_adv_to);
12064 vty_out(vty, ",");
12065 } else
d62a17ae 12066 json_object_object_add(json, "advertisedTo",
12067 json_adv_to);
d62a17ae 12068 } else {
f9f2d188 12069 if (!json && first)
d62a17ae 12070 vty_out(vty, " Not advertised to any peer");
12071 vty_out(vty, "\n");
12072 }
12073 }
718e3744 12074}
12075
edfee30d 12076static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12077 struct bgp_dest *bgp_node, struct vty *vty,
12078 struct bgp *bgp, afi_t afi, safi_t safi,
12079 json_object *json, enum bgp_path_type pathtype,
4027d19b 12080 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12081{
12082 struct bgp_path_info *pi;
12083 int header = 1;
44c69747
LK
12084 json_object *json_header = NULL;
12085 json_object *json_paths = NULL;
4933eaaf 12086 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12087
9bcb3eef 12088 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12089 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12090
12091 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12092 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12093 pi->peer, pi->attr, p);
4933eaaf 12094
4027d19b
DS
12095 if (rpki_target_state != RPKI_NOT_BEING_USED
12096 && rpki_curr_state != rpki_target_state)
4933eaaf 12097 continue;
44c69747
LK
12098
12099 if (json && !json_paths) {
12100 /* Instantiate json_paths only if path is valid */
12101 json_paths = json_object_new_array();
c4f64ea9 12102 if (pfx_rd)
44c69747 12103 json_header = json_object_new_object();
c4f64ea9 12104 else
44c69747
LK
12105 json_header = json;
12106 }
12107
12108 if (header) {
12109 route_vty_out_detail_header(
34c7f35f
SW
12110 vty, bgp, bgp_node,
12111 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12112 safi, json_header, false);
44c69747
LK
12113 header = 0;
12114 }
12115 (*display)++;
12116
12117 if (pathtype == BGP_PATH_SHOW_ALL
12118 || (pathtype == BGP_PATH_SHOW_BESTPATH
12119 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12120 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12121 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12122 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12123 route_vty_out_detail(vty, bgp, bgp_node,
12124 bgp_dest_get_prefix(bgp_node), pi,
12125 AFI_IP, safi, rpki_curr_state,
12126 json_paths);
44c69747
LK
12127 }
12128
12129 if (json && json_paths) {
12130 json_object_object_add(json_header, "paths", json_paths);
12131
12132 if (pfx_rd)
4a8cd6ad
PG
12133 json_object_object_addf(
12134 json, json_header,
12135 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12136 }
12137}
12138
2aad8c42
MS
12139/*
12140 * Return rd based on safi
12141 */
46dbf9d0
DA
12142const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12143 safi_t safi)
2aad8c42
MS
12144{
12145 switch (safi) {
12146 case SAFI_MPLS_VPN:
12147 case SAFI_ENCAP:
12148 case SAFI_EVPN:
12149 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12150 case SAFI_UNSPEC:
12151 case SAFI_UNICAST:
12152 case SAFI_MULTICAST:
12153 case SAFI_LABELED_UNICAST:
12154 case SAFI_FLOWSPEC:
12155 case SAFI_MAX:
2aad8c42 12156 return NULL;
2aad8c42 12157 }
58cf0823
DS
12158
12159 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12160}
12161
718e3744 12162/* Display specified route of BGP table. */
d62a17ae 12163static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12164 struct bgp_table *rib, const char *ip_str,
12165 afi_t afi, safi_t safi,
4027d19b 12166 enum rpki_states rpki_target_state,
d62a17ae 12167 struct prefix_rd *prd, int prefix_check,
9f049418 12168 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12169{
12170 int ret;
d62a17ae 12171 int display = 0;
12172 struct prefix match;
9bcb3eef
DS
12173 struct bgp_dest *dest;
12174 struct bgp_dest *rm;
d62a17ae 12175 struct bgp_table *table;
12176 json_object *json = NULL;
12177 json_object *json_paths = NULL;
12178
12179 /* Check IP address argument. */
12180 ret = str2prefix(ip_str, &match);
12181 if (!ret) {
12182 vty_out(vty, "address is malformed\n");
12183 return CMD_WARNING;
12184 }
718e3744 12185
d62a17ae 12186 match.family = afi2family(afi);
b05a1c8b 12187
44c69747 12188 if (use_json)
d62a17ae 12189 json = json_object_new_object();
718e3744 12190
44c69747 12191 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12192 for (dest = bgp_table_top(rib); dest;
12193 dest = bgp_route_next(dest)) {
12194 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12195
9bcb3eef 12196 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12197 continue;
9bcb3eef 12198 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12199 if (!table)
ea47320b 12200 continue;
d62a17ae 12201
4953391b
DA
12202 rm = bgp_node_match(table, &match);
12203 if (rm == NULL)
ea47320b 12204 continue;
d62a17ae 12205
9bcb3eef 12206 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12207 if (prefix_check
b54892e0 12208 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12209 bgp_dest_unlock_node(rm);
ea47320b
DL
12210 continue;
12211 }
d62a17ae 12212
9bcb3eef 12213 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12214 bgp, afi, safi, json, pathtype,
4027d19b 12215 &display, rpki_target_state);
44c69747 12216
9bcb3eef 12217 bgp_dest_unlock_node(rm);
44c69747
LK
12218 }
12219 } else if (safi == SAFI_EVPN) {
9bcb3eef 12220 struct bgp_dest *longest_pfx;
cded3b72 12221 bool is_exact_pfxlen_match = false;
44c69747 12222
9bcb3eef
DS
12223 for (dest = bgp_table_top(rib); dest;
12224 dest = bgp_route_next(dest)) {
12225 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12226
9bcb3eef 12227 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12228 continue;
9bcb3eef 12229 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12230 if (!table)
12231 continue;
12232
12233 longest_pfx = NULL;
cded3b72 12234 is_exact_pfxlen_match = false;
44c69747
LK
12235 /*
12236 * Search through all the prefixes for a match. The
12237 * pfx's are enumerated in ascending order of pfxlens.
12238 * So, the last pfx match is the longest match. Set
12239 * is_exact_pfxlen_match when we get exact pfxlen match
12240 */
12241 for (rm = bgp_table_top(table); rm;
12242 rm = bgp_route_next(rm)) {
b54892e0 12243 const struct prefix *rm_p =
9bcb3eef 12244 bgp_dest_get_prefix(rm);
44c69747
LK
12245 /*
12246 * Get prefixlen of the ip-prefix within type5
12247 * evpn route
12248 */
b54892e0
DS
12249 if (evpn_type5_prefix_match(rm_p, &match)
12250 && rm->info) {
44c69747
LK
12251 longest_pfx = rm;
12252 int type5_pfxlen =
b54892e0
DS
12253 bgp_evpn_get_type5_prefixlen(
12254 rm_p);
44c69747 12255 if (type5_pfxlen == match.prefixlen) {
cded3b72 12256 is_exact_pfxlen_match = true;
9bcb3eef 12257 bgp_dest_unlock_node(rm);
44c69747
LK
12258 break;
12259 }
d62a17ae 12260 }
12261 }
ea47320b 12262
44c69747
LK
12263 if (!longest_pfx)
12264 continue;
12265
12266 if (prefix_check && !is_exact_pfxlen_match)
12267 continue;
12268
12269 rm = longest_pfx;
9bcb3eef 12270 bgp_dest_lock_node(rm);
44c69747 12271
9bcb3eef 12272 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12273 bgp, afi, safi, json, pathtype,
4027d19b 12274 &display, rpki_target_state);
44c69747 12275
9bcb3eef 12276 bgp_dest_unlock_node(rm);
d62a17ae 12277 }
98a9dbc7 12278 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12279 if (use_json)
12280 json_paths = json_object_new_array();
12281
63a0b7a9
PG
12282 display = bgp_flowspec_display_match_per_ip(afi, rib,
12283 &match, prefix_check,
12284 vty,
12285 use_json,
12286 json_paths);
d5f20468
SP
12287 if (use_json) {
12288 if (display)
12289 json_object_object_add(json, "paths",
12290 json_paths);
12291 else
12292 json_object_free(json_paths);
12293 }
d62a17ae 12294 } else {
4953391b
DA
12295 dest = bgp_node_match(rib, &match);
12296 if (dest != NULL) {
9bcb3eef 12297 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12298 if (!prefix_check
9bcb3eef
DS
12299 || dest_p->prefixlen == match.prefixlen) {
12300 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12301 safi, json, pathtype,
4027d19b 12302 &display, rpki_target_state);
d62a17ae 12303 }
12304
9bcb3eef 12305 bgp_dest_unlock_node(dest);
d62a17ae 12306 }
12307 }
e5eee9af 12308
d62a17ae 12309 if (use_json) {
75eeda93 12310 vty_json(vty, json);
d62a17ae 12311 } else {
12312 if (!display) {
12313 vty_out(vty, "%% Network not in table\n");
12314 return CMD_WARNING;
12315 }
12316 }
b05a1c8b 12317
d62a17ae 12318 return CMD_SUCCESS;
718e3744 12319}
12320
fee0f4c6 12321/* Display specified route of Main RIB */
d62a17ae 12322static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12323 afi_t afi, safi_t safi, struct prefix_rd *prd,
12324 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12325 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12326{
9b86009a 12327 if (!bgp) {
d62a17ae 12328 bgp = bgp_get_default();
9b86009a
RW
12329 if (!bgp) {
12330 if (!use_json)
12331 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12332 else
12333 vty_out(vty, "{}\n");
9b86009a
RW
12334 return CMD_WARNING;
12335 }
12336 }
d62a17ae 12337
12338 /* labeled-unicast routes live in the unicast table */
12339 if (safi == SAFI_LABELED_UNICAST)
12340 safi = SAFI_UNICAST;
12341
12342 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12343 afi, safi, rpki_target_state, prd,
8aa22bbb 12344 prefix_check, pathtype, use_json);
d62a17ae 12345}
12346
12347static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12348 struct cmd_token **argv, bool exact, afi_t afi,
12349 safi_t safi, bool uj)
d62a17ae 12350{
12351 struct lcommunity *lcom;
12352 struct buffer *b;
12353 int i;
12354 char *str;
12355 int first = 0;
96c81f66 12356 uint16_t show_flags = 0;
4f28b2b5 12357 int ret;
96f3485c
MK
12358
12359 if (uj)
12360 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12361
12362 b = buffer_new(1024);
12363 for (i = 0; i < argc; i++) {
12364 if (first)
12365 buffer_putc(b, ' ');
12366 else {
12367 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12368 first = 1;
12369 buffer_putstr(b, argv[i]->arg);
12370 }
12371 }
12372 }
12373 buffer_putc(b, '\0');
57d187bc 12374
d62a17ae 12375 str = buffer_getstr(b);
12376 buffer_free(b);
57d187bc 12377
d62a17ae 12378 lcom = lcommunity_str2com(str);
12379 XFREE(MTYPE_TMP, str);
12380 if (!lcom) {
12381 vty_out(vty, "%% Large-community malformed\n");
12382 return CMD_WARNING;
12383 }
57d187bc 12384
4f28b2b5 12385 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12386 (exact ? bgp_show_type_lcommunity_exact
12387 : bgp_show_type_lcommunity),
12388 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12389
12390 lcommunity_free(&lcom);
12391 return ret;
57d187bc
JS
12392}
12393
d62a17ae 12394static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12395 const char *lcom, bool exact, afi_t afi,
12396 safi_t safi, bool uj)
57d187bc 12397{
d62a17ae 12398 struct community_list *list;
96c81f66 12399 uint16_t show_flags = 0;
96f3485c
MK
12400
12401 if (uj)
12402 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12403
57d187bc 12404
e237b0d2 12405 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12406 LARGE_COMMUNITY_LIST_MASTER);
12407 if (list == NULL) {
12408 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12409 lcom);
12410 return CMD_WARNING;
12411 }
57d187bc 12412
36a206db 12413 return bgp_show(vty, bgp, afi, safi,
12414 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12415 : bgp_show_type_lcommunity_list),
1e2ce4f1 12416 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12417}
12418
52951b63
DS
12419DEFUN (show_ip_bgp_large_community_list,
12420 show_ip_bgp_large_community_list_cmd,
77a3a95e 12421 "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
12422 SHOW_STR
12423 IP_STR
12424 BGP_STR
12425 BGP_INSTANCE_HELP_STR
9bedbb1e 12426 BGP_AFI_HELP_STR
4dd6177e 12427 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12428 "Display routes matching the large-community-list\n"
12429 "large-community-list number\n"
12430 "large-community-list name\n"
36a206db 12431 "Exact match of the large-communities\n"
52951b63
DS
12432 JSON_STR)
12433{
d62a17ae 12434 afi_t afi = AFI_IP6;
12435 safi_t safi = SAFI_UNICAST;
12436 int idx = 0;
36a206db 12437 bool exact_match = 0;
4d678463 12438 struct bgp *bgp = NULL;
9f049418 12439 bool uj = use_json(argc, argv);
d62a17ae 12440
ef3364f0
DA
12441 if (uj)
12442 argc--;
4d678463 12443
ef3364f0
DA
12444 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12445 &bgp, uj);
12446 if (!idx)
12447 return CMD_WARNING;
d62a17ae 12448
12449 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12450
12451 const char *clist_number_or_name = argv[++idx]->arg;
12452
12453 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12454 exact_match = 1;
12455
12456 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12457 exact_match, afi, safi, uj);
52951b63
DS
12458}
12459DEFUN (show_ip_bgp_large_community,
12460 show_ip_bgp_large_community_cmd,
36a206db 12461 "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
12462 SHOW_STR
12463 IP_STR
12464 BGP_STR
12465 BGP_INSTANCE_HELP_STR
9bedbb1e 12466 BGP_AFI_HELP_STR
4dd6177e 12467 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12468 "Display routes matching the large-communities\n"
12469 "List of large-community numbers\n"
36a206db 12470 "Exact match of the large-communities\n"
52951b63
DS
12471 JSON_STR)
12472{
d62a17ae 12473 afi_t afi = AFI_IP6;
12474 safi_t safi = SAFI_UNICAST;
12475 int idx = 0;
36a206db 12476 bool exact_match = 0;
4d678463 12477 struct bgp *bgp = NULL;
9f049418 12478 bool uj = use_json(argc, argv);
96c81f66 12479 uint16_t show_flags = 0;
d62a17ae 12480
96f3485c
MK
12481 if (uj) {
12482 argc--;
12483 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12484 }
4d678463 12485
96f3485c
MK
12486 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12487 &bgp, uj);
12488 if (!idx)
12489 return CMD_WARNING;
d62a17ae 12490
36a206db 12491 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12492 if (argv_find(argv, argc, "exact-match", &idx)) {
12493 argc--;
36a206db 12494 exact_match = 1;
1857760c 12495 }
36a206db 12496 return bgp_show_lcommunity(vty, bgp, argc, argv,
12497 exact_match, afi, safi, uj);
12498 } else
d62a17ae 12499 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12500 bgp_show_type_lcommunity_all, NULL, show_flags,
12501 RPKI_NOT_BEING_USED);
52951b63
DS
12502}
12503
71f1613a
DA
12504static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12505 safi_t safi, struct json_object *json_array);
d62a17ae 12506static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12507 safi_t safi, struct json_object *json);
e01ca200 12508
7b2ff250 12509
9ab0cf58
PG
12510DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12511 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12512 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12513 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12514{
12515 bool uj = use_json(argc, argv);
12516 struct bgp *bgp = NULL;
ec76a1d1
DA
12517 safi_t safi = SAFI_UNICAST;
12518 afi_t afi = AFI_IP6;
4265b261 12519 int idx = 0;
6c9d22e2
PG
12520 struct json_object *json_all = NULL;
12521 struct json_object *json_afi_safi = NULL;
4265b261
PG
12522
12523 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12524 &bgp, false);
71f1613a 12525 if (!idx)
4265b261 12526 return CMD_WARNING;
6c9d22e2 12527
4265b261 12528 if (uj)
6c9d22e2 12529 json_all = json_object_new_object();
4265b261 12530
9ab0cf58
PG
12531 FOREACH_AFI_SAFI (afi, safi) {
12532 /*
12533 * So limit output to those afi/safi pairs that
12534 * actually have something interesting in them
12535 */
12536 if (strmatch(get_afi_safi_str(afi, safi, true),
12537 "Unknown")) {
12538 continue;
12539 }
12540 if (uj) {
12541 json_afi_safi = json_object_new_array();
12542 json_object_object_add(
12543 json_all,
12544 get_afi_safi_str(afi, safi, true),
12545 json_afi_safi);
12546 } else {
12547 json_afi_safi = NULL;
6c9d22e2 12548 }
9ab0cf58
PG
12549
12550 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12551 }
6c9d22e2 12552
3757f964
DA
12553 if (uj)
12554 vty_json(vty, json_all);
6c9d22e2 12555
4265b261
PG
12556 return CMD_SUCCESS;
12557}
12558
7b2ff250 12559/* BGP route print out function without JSON */
14718643
PG
12560DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12561 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12562 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12563 SHOW_STR
12564 IP_STR
12565 BGP_STR
12566 BGP_INSTANCE_HELP_STR
12567 L2VPN_HELP_STR
12568 EVPN_HELP_STR
12569 "BGP RIB advertisement statistics\n"
12570 JSON_STR)
12571{
ec76a1d1
DA
12572 afi_t afi = AFI_IP6;
12573 safi_t safi = SAFI_UNICAST;
14718643
PG
12574 struct bgp *bgp = NULL;
12575 int idx = 0, ret;
12576 bool uj = use_json(argc, argv);
12577 struct json_object *json_afi_safi = NULL, *json = NULL;
12578
12579 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12580 &bgp, false);
12581 if (!idx)
12582 return CMD_WARNING;
12583
12584 if (uj)
12585 json_afi_safi = json_object_new_array();
12586 else
12587 json_afi_safi = NULL;
12588
12589 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12590
12591 if (uj) {
12592 json = json_object_new_object();
12593 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12594 json_afi_safi);
3757f964 12595 vty_json(vty, json);
14718643
PG
12596 }
12597 return ret;
12598}
12599
893cccd0 12600/* BGP route print out function without JSON */
9ab0cf58
PG
12601DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12602 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12603 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12604 "]]\
893cccd0 12605 statistics [json]",
9ab0cf58
PG
12606 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12607 BGP_SAFI_WITH_LABEL_HELP_STR
12608 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12609{
ec76a1d1
DA
12610 afi_t afi = AFI_IP6;
12611 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12612 struct bgp *bgp = NULL;
12613 int idx = 0, ret;
12614 bool uj = use_json(argc, argv);
6c9d22e2 12615 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12616
12617 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12618 &bgp, false);
12619 if (!idx)
12620 return CMD_WARNING;
6c9d22e2 12621
893cccd0 12622 if (uj)
6c9d22e2
PG
12623 json_afi_safi = json_object_new_array();
12624 else
12625 json_afi_safi = NULL;
12626
12627 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12628
12629 if (uj) {
12630 json = json_object_new_object();
12631 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12632 json_afi_safi);
3757f964 12633 vty_json(vty, json);
893cccd0
PG
12634 }
12635 return ret;
893cccd0 12636}
7b2ff250 12637
fe0f234d 12638DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12639 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12640 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12641 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12642 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12643 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12644 "Display the entries for all address families\n"
9ab0cf58
PG
12645 "Display detailed information about dampening\n"
12646 "Display detail of configured dampening parameters\n"
fe0f234d 12647 JSON_STR)
718e3744 12648{
d62a17ae 12649 afi_t afi = AFI_IP6;
12650 safi_t safi = SAFI_UNICAST;
d62a17ae 12651 struct bgp *bgp = NULL;
12652 int idx = 0;
96c81f66 12653 uint16_t show_flags = 0;
fe0f234d
RW
12654 bool uj = use_json(argc, argv);
12655
12656 if (uj) {
12657 argc--;
12658 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12659 }
96f3485c
MK
12660
12661 /* [<ipv4|ipv6> [all]] */
12662 if (all) {
12663 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12664 if (argv_find(argv, argc, "ipv4", &idx))
12665 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12666
12667 if (argv_find(argv, argc, "ipv6", &idx))
12668 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12669 }
d62a17ae 12670
12671 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12672 &bgp, false);
d62a17ae 12673 if (!idx)
12674 return CMD_WARNING;
12675
fe0f234d 12676 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12677}
12678
fe0f234d
RW
12679/* BGP route print out function */
12680DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12681 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12682 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12683 "]]\
96f3485c 12684 [all$all]\
cf4898bc
QY
12685 [cidr-only\
12686 |dampening <flap-statistics|dampened-paths>\
12687 |community [AA:NN|local-AS|no-advertise|no-export\
12688 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12689 |accept-own|accept-own-nexthop|route-filter-v6\
12690 |route-filter-v4|route-filter-translated-v6\
12691 |route-filter-translated-v4] [exact-match]\
70799983 12692 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12693 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12694 |prefix-list WORD\
ed126382 12695 |access-list ACCESSLIST_NAME\
70dd370f 12696 |route-map RMAP_NAME\
1e2ce4f1 12697 |rpki <invalid|valid|notfound>\
7d3cae70 12698 |version (1-4294967295)\
b4ad2fae 12699 |alias ALIAS_NAME\
39c3c736
RW
12700 |A.B.C.D/M longer-prefixes\
12701 |X:X::X:X/M longer-prefixes\
83856649 12702 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12703 |detail-routes$detail_routes\
67799a48 12704 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12705 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12706 BGP_SAFI_WITH_LABEL_HELP_STR
12707 "Display the entries for all address families\n"
12708 "Display only routes with non-natural netmasks\n"
12709 "Display detailed information about dampening\n"
12710 "Display flap statistics of routes\n"
12711 "Display paths suppressed due to dampening\n"
12712 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12713 "Do not send outside local AS (well-known community)\n"
12714 "Do not advertise to any peer (well-known community)\n"
12715 "Do not export to next AS (well-known community)\n"
12716 "Graceful shutdown (well-known community)\n"
12717 "Do not export to any peer (well-known community)\n"
12718 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12719 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12720 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12721 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12722 "Should accept VPN route with local nexthop (well-known community)\n"
12723 "RT VPNv6 route filtering (well-known community)\n"
12724 "RT VPNv4 route filtering (well-known community)\n"
12725 "RT translated VPNv6 route filtering (well-known community)\n"
12726 "RT translated VPNv4 route filtering (well-known community)\n"
12727 "Exact match of the communities\n"
70799983
RW
12728 "Community-list number\n"
12729 "Community-list name\n"
12730 "Display routes matching the community-list\n"
12731 "Exact match of the communities\n"
a7129347
RW
12732 "Display routes conforming to the filter-list\n"
12733 "Regular expression access list name\n"
6deaf579
RW
12734 "Display routes conforming to the prefix-list\n"
12735 "Prefix-list name\n"
ed126382
DA
12736 "Display routes conforming to the access-list\n"
12737 "Access-list name\n"
bf1a944a
RW
12738 "Display routes matching the route-map\n"
12739 "A route-map to match on\n"
a70a28a5
DA
12740 "RPKI route types\n"
12741 "A valid path as determined by rpki\n"
12742 "A invalid path as determined by rpki\n"
12743 "A path that has no rpki data\n"
12744 "Display prefixes with matching version numbers\n"
12745 "Version number and above\n"
12746 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12747 "BGP community alias\n"
12748 "IPv4 prefix\n"
12749 "Display route and more specific routes\n"
12750 "IPv6 prefix\n"
12751 "Display route and more specific routes\n"
83856649 12752 BGP_SELF_ORIG_HELP_STR
509d82bd 12753 "Display detailed version of all routes\n"
39c3c736 12754 JSON_STR
a70a28a5
DA
12755 "Display detailed version of JSON output\n"
12756 "Increase table width for longer prefixes\n")
7b2ff250
DW
12757{
12758 afi_t afi = AFI_IP6;
12759 safi_t safi = SAFI_UNICAST;
12760 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12761 void *output_arg = NULL;
7b2ff250
DW
12762 struct bgp *bgp = NULL;
12763 int idx = 0;
d0086e8e 12764 int exact_match = 0;
96f3485c
MK
12765 char *community = NULL;
12766 bool first = true;
96c81f66 12767 uint16_t show_flags = 0;
4027d19b 12768 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12769 struct prefix p;
96f3485c
MK
12770
12771 if (uj) {
9f049418 12772 argc--;
96f3485c
MK
12773 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12774 }
12775
67799a48
DA
12776 if (detail_json)
12777 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12778
509d82bd
DA
12779 if (detail_routes)
12780 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12781
96f3485c
MK
12782 /* [<ipv4|ipv6> [all]] */
12783 if (all) {
12784 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12785
12786 if (argv_find(argv, argc, "ipv4", &idx))
12787 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12788
12789 if (argv_find(argv, argc, "ipv6", &idx))
12790 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12791 }
12792
12793 if (wide)
12794 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12795
12796 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12797 &bgp, uj);
7b2ff250
DW
12798 if (!idx)
12799 return CMD_WARNING;
12800
7b2ff250 12801 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12802 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12803
12804 if (argv_find(argv, argc, "dampening", &idx)) {
12805 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12806 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12807 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12808 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12809 }
12810
12811 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12812 char *maybecomm = NULL;
d0086e8e 12813
79bc257a
RW
12814 if (idx + 1 < argc) {
12815 if (argv[idx + 1]->type == VARIABLE_TKN)
12816 maybecomm = argv[idx + 1]->arg;
12817 else
12818 maybecomm = argv[idx + 1]->text;
12819 }
12820
cf4898bc
QY
12821 if (maybecomm && !strmatch(maybecomm, "json")
12822 && !strmatch(maybecomm, "exact-match"))
12823 community = maybecomm;
d0086e8e 12824
cf4898bc
QY
12825 if (argv_find(argv, argc, "exact-match", &idx))
12826 exact_match = 1;
d0086e8e 12827
96f3485c
MK
12828 if (!community)
12829 sh_type = bgp_show_type_community_all;
12830 }
12831
70799983
RW
12832 if (argv_find(argv, argc, "community-list", &idx)) {
12833 const char *clist_number_or_name = argv[++idx]->arg;
12834 struct community_list *list;
12835
12836 if (argv_find(argv, argc, "exact-match", &idx))
12837 exact_match = 1;
12838
12839 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12840 COMMUNITY_LIST_MASTER);
12841 if (list == NULL) {
606d49a4 12842 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12843 clist_number_or_name);
12844 return CMD_WARNING;
12845 }
12846
12847 if (exact_match)
12848 sh_type = bgp_show_type_community_list_exact;
12849 else
12850 sh_type = bgp_show_type_community_list;
12851 output_arg = list;
12852 }
12853
a7129347
RW
12854 if (argv_find(argv, argc, "filter-list", &idx)) {
12855 const char *filter = argv[++idx]->arg;
12856 struct as_list *as_list;
12857
12858 as_list = as_list_lookup(filter);
12859 if (as_list == NULL) {
606d49a4 12860 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12861 filter);
12862 return CMD_WARNING;
12863 }
12864
12865 sh_type = bgp_show_type_filter_list;
12866 output_arg = as_list;
12867 }
12868
6deaf579
RW
12869 if (argv_find(argv, argc, "prefix-list", &idx)) {
12870 const char *prefix_list_str = argv[++idx]->arg;
12871 struct prefix_list *plist;
12872
12873 plist = prefix_list_lookup(afi, prefix_list_str);
12874 if (plist == NULL) {
606d49a4 12875 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12876 prefix_list_str);
12877 return CMD_WARNING;
12878 }
12879
12880 sh_type = bgp_show_type_prefix_list;
12881 output_arg = plist;
12882 }
12883
ed126382
DA
12884 if (argv_find(argv, argc, "access-list", &idx)) {
12885 const char *access_list_str = argv[++idx]->arg;
12886 struct access_list *alist;
12887
12888 alist = access_list_lookup(afi, access_list_str);
12889 if (!alist) {
606d49a4 12890 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12891 access_list_str);
12892 return CMD_WARNING;
12893 }
12894
12895 sh_type = bgp_show_type_access_list;
12896 output_arg = alist;
12897 }
12898
bf1a944a
RW
12899 if (argv_find(argv, argc, "route-map", &idx)) {
12900 const char *rmap_str = argv[++idx]->arg;
12901 struct route_map *rmap;
12902
12903 rmap = route_map_lookup_by_name(rmap_str);
12904 if (!rmap) {
606d49a4 12905 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12906 return CMD_WARNING;
12907 }
12908
12909 sh_type = bgp_show_type_route_map;
12910 output_arg = rmap;
12911 }
12912
1e2ce4f1
DS
12913 if (argv_find(argv, argc, "rpki", &idx)) {
12914 sh_type = bgp_show_type_rpki;
12915 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12916 rpki_target_state = RPKI_VALID;
1e2ce4f1 12917 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12918 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12919 }
12920
7d3cae70
DA
12921 /* Display prefixes with matching version numbers */
12922 if (argv_find(argv, argc, "version", &idx)) {
12923 sh_type = bgp_show_type_prefix_version;
2391833e 12924 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12925 }
12926
a70a28a5
DA
12927 /* Display prefixes with matching BGP community alias */
12928 if (argv_find(argv, argc, "alias", &idx)) {
12929 sh_type = bgp_show_type_community_alias;
2391833e 12930 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12931 }
12932
39c3c736
RW
12933 /* prefix-longer */
12934 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12935 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12936 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12937
12938 if (!str2prefix(prefix_str, &p)) {
12939 vty_out(vty, "%% Malformed Prefix\n");
12940 return CMD_WARNING;
12941 }
12942
12943 sh_type = bgp_show_type_prefix_longer;
12944 output_arg = &p;
a70a28a5
DA
12945 }
12946
83856649
KQ
12947 /* self originated only */
12948 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12949 sh_type = bgp_show_type_self_originated;
12950
96f3485c
MK
12951 if (!all) {
12952 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12953 if (community)
12954 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12955 exact_match, afi, safi,
12956 show_flags);
2391833e 12957 else
a70a28a5 12958 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12959 output_arg, show_flags,
a70a28a5 12960 rpki_target_state);
96f3485c 12961 } else {
fa5ac378
DA
12962 struct listnode *node;
12963 struct bgp *abgp;
96f3485c
MK
12964 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12965 * AFI_IP6 */
12966
12967 if (uj)
12968 vty_out(vty, "{\n");
12969
12970 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12971 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12972 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12973 ? AFI_IP
12974 : AFI_IP6;
fa5ac378
DA
12975 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12976 FOREACH_SAFI (safi) {
12977 if (!bgp_afi_safi_peer_exists(abgp, afi,
12978 safi))
12979 continue;
96f3485c 12980
fa5ac378
DA
12981 if (uj) {
12982 if (first)
12983 first = false;
12984 else
12985 vty_out(vty, ",\n");
12986 vty_out(vty, "\"%s\":{\n",
12987 get_afi_safi_str(afi,
12988 safi,
12989 true));
12990 } else
12991 vty_out(vty,
12992 "\nFor address family: %s\n",
12993 get_afi_safi_str(
12994 afi, safi,
12995 false));
12996
12997 if (community)
12998 bgp_show_community(
12999 vty, abgp, community,
13000 exact_match, afi, safi,
13001 show_flags);
96f3485c 13002 else
fa5ac378
DA
13003 bgp_show(vty, abgp, afi, safi,
13004 sh_type, output_arg,
13005 show_flags,
13006 rpki_target_state);
13007 if (uj)
13008 vty_out(vty, "}\n");
13009 }
96f3485c
MK
13010 }
13011 } else {
13012 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
13013 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13014 FOREACH_AFI_SAFI (afi, safi) {
13015 if (!bgp_afi_safi_peer_exists(abgp, afi,
13016 safi))
13017 continue;
96f3485c 13018
fa5ac378
DA
13019 if (uj) {
13020 if (first)
13021 first = false;
13022 else
13023 vty_out(vty, ",\n");
13024
13025 vty_out(vty, "\"%s\":{\n",
13026 get_afi_safi_str(afi,
13027 safi,
13028 true));
13029 } else
13030 vty_out(vty,
13031 "\nFor address family: %s\n",
13032 get_afi_safi_str(
13033 afi, safi,
13034 false));
13035
13036 if (community)
13037 bgp_show_community(
13038 vty, abgp, community,
13039 exact_match, afi, safi,
13040 show_flags);
96f3485c 13041 else
fa5ac378
DA
13042 bgp_show(vty, abgp, afi, safi,
13043 sh_type, output_arg,
13044 show_flags,
13045 rpki_target_state);
13046 if (uj)
13047 vty_out(vty, "}\n");
13048 }
96f3485c
MK
13049 }
13050 }
13051 if (uj)
13052 vty_out(vty, "}\n");
13053 }
13054 return CMD_SUCCESS;
a636c635 13055}
47fc97cc 13056
718e3744 13057DEFUN (show_ip_bgp_route,
13058 show_ip_bgp_route_cmd,
8aa22bbb 13059 "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 13060 SHOW_STR
13061 IP_STR
13062 BGP_STR
a636c635 13063 BGP_INSTANCE_HELP_STR
4f280b15 13064 BGP_AFI_HELP_STR
4dd6177e 13065 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13066 "Network in the BGP routing table to display\n"
0c7b1b01 13067 "IPv4 prefix\n"
8c3deaae 13068 "Network in the BGP routing table to display\n"
0c7b1b01 13069 "IPv6 prefix\n"
4092b06c 13070 "Display only the bestpath\n"
b05a1c8b 13071 "Display only multipaths\n"
8aa22bbb
DS
13072 "Display only paths that match the specified rpki state\n"
13073 "A valid path as determined by rpki\n"
13074 "A invalid path as determined by rpki\n"
13075 "A path that has no rpki data\n"
9973d184 13076 JSON_STR)
4092b06c 13077{
d62a17ae 13078 int prefix_check = 0;
ae19d7dd 13079
d62a17ae 13080 afi_t afi = AFI_IP6;
13081 safi_t safi = SAFI_UNICAST;
13082 char *prefix = NULL;
13083 struct bgp *bgp = NULL;
13084 enum bgp_path_type path_type;
9f049418 13085 bool uj = use_json(argc, argv);
b05a1c8b 13086
d62a17ae 13087 int idx = 0;
ae19d7dd 13088
d62a17ae 13089 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13090 &bgp, uj);
d62a17ae 13091 if (!idx)
13092 return CMD_WARNING;
c41247f5 13093
d62a17ae 13094 if (!bgp) {
13095 vty_out(vty,
13096 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13097 return CMD_WARNING;
13098 }
a636c635 13099
d62a17ae 13100 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13101 if (argv_find(argv, argc, "A.B.C.D", &idx)
13102 || argv_find(argv, argc, "X:X::X:X", &idx))
13103 prefix_check = 0;
13104 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13105 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13106 prefix_check = 1;
13107
13108 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13109 && afi != AFI_IP6) {
13110 vty_out(vty,
13111 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13112 return CMD_WARNING;
13113 }
13114 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13115 && afi != AFI_IP) {
13116 vty_out(vty,
13117 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13118 return CMD_WARNING;
13119 }
13120
13121 prefix = argv[idx]->arg;
13122
13123 /* [<bestpath|multipath>] */
13124 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13125 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13126 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13127 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13128 else
360660c6 13129 path_type = BGP_PATH_SHOW_ALL;
a636c635 13130
d62a17ae 13131 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13132 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13133}
13134
8c3deaae
QY
13135DEFUN (show_ip_bgp_regexp,
13136 show_ip_bgp_regexp_cmd,
3e5b31b3 13137 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13138 SHOW_STR
13139 IP_STR
13140 BGP_STR
b00b230a 13141 BGP_INSTANCE_HELP_STR
4f280b15 13142 BGP_AFI_HELP_STR
4dd6177e 13143 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13144 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13145 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13146 JSON_STR)
8c3deaae 13147{
d62a17ae 13148 afi_t afi = AFI_IP6;
13149 safi_t safi = SAFI_UNICAST;
13150 struct bgp *bgp = NULL;
3e5b31b3
DA
13151 bool uj = use_json(argc, argv);
13152 char *regstr = NULL;
8c3deaae 13153
d62a17ae 13154 int idx = 0;
13155 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13156 &bgp, false);
d62a17ae 13157 if (!idx)
13158 return CMD_WARNING;
8c3deaae 13159
d62a17ae 13160 // get index of regex
3e5b31b3
DA
13161 if (argv_find(argv, argc, "REGEX", &idx))
13162 regstr = argv[idx]->arg;
8c3deaae 13163
5f71d11c 13164 assert(regstr);
3e5b31b3
DA
13165 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13166 bgp_show_type_regexp, uj);
8c3deaae
QY
13167}
13168
ae248832 13169DEFPY (show_ip_bgp_instance_all,
a636c635 13170 show_ip_bgp_instance_all_cmd,
ae248832 13171 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13172 SHOW_STR
a636c635 13173 IP_STR
4092b06c 13174 BGP_STR
a636c635 13175 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13176 BGP_AFI_HELP_STR
4dd6177e 13177 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13178 JSON_STR
13179 "Increase table width for longer prefixes\n")
4092b06c 13180{
54d05dea 13181 afi_t afi = AFI_IP6;
d62a17ae 13182 safi_t safi = SAFI_UNICAST;
13183 struct bgp *bgp = NULL;
d62a17ae 13184 int idx = 0;
96c81f66 13185 uint16_t show_flags = 0;
ae19d7dd 13186
96f3485c 13187 if (uj) {
d62a17ae 13188 argc--;
96f3485c
MK
13189 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13190 }
13191
13192 if (wide)
13193 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13194
9f049418
DS
13195 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13196 &bgp, uj);
13197 if (!idx)
13198 return CMD_WARNING;
13199
96f3485c 13200 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13201 return CMD_SUCCESS;
e3e29b32
LB
13202}
13203
a4d82a8a 13204static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13205 afi_t afi, safi_t safi, enum bgp_show_type type,
13206 bool use_json)
718e3744 13207{
d62a17ae 13208 regex_t *regex;
13209 int rc;
96c81f66 13210 uint16_t show_flags = 0;
96f3485c
MK
13211
13212 if (use_json)
13213 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13214
c3900853 13215 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13216 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13217 regstr);
13218 return CMD_WARNING_CONFIG_FAILED;
13219 }
13220
d62a17ae 13221 regex = bgp_regcomp(regstr);
13222 if (!regex) {
13223 vty_out(vty, "Can't compile regexp %s\n", regstr);
13224 return CMD_WARNING;
13225 }
a636c635 13226
1e2ce4f1
DS
13227 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13228 RPKI_NOT_BEING_USED);
d62a17ae 13229 bgp_regex_free(regex);
13230 return rc;
e3e29b32
LB
13231}
13232
7f323236
DW
13233static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13234 const char *comstr, int exact, afi_t afi,
96c81f66 13235 safi_t safi, uint16_t show_flags)
d62a17ae 13236{
13237 struct community *com;
d62a17ae 13238 int ret = 0;
13239
7f323236 13240 com = community_str2com(comstr);
d62a17ae 13241 if (!com) {
7f323236 13242 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13243 return CMD_WARNING;
13244 }
13245
13246 ret = bgp_show(vty, bgp, afi, safi,
13247 (exact ? bgp_show_type_community_exact
13248 : bgp_show_type_community),
1e2ce4f1 13249 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13250 community_free(&com);
46c3ce83 13251
d62a17ae 13252 return ret;
718e3744 13253}
13254
d62a17ae 13255enum bgp_stats {
13256 BGP_STATS_MAXBITLEN = 0,
13257 BGP_STATS_RIB,
13258 BGP_STATS_PREFIXES,
13259 BGP_STATS_TOTPLEN,
13260 BGP_STATS_UNAGGREGATEABLE,
13261 BGP_STATS_MAX_AGGREGATEABLE,
13262 BGP_STATS_AGGREGATES,
13263 BGP_STATS_SPACE,
13264 BGP_STATS_ASPATH_COUNT,
13265 BGP_STATS_ASPATH_MAXHOPS,
13266 BGP_STATS_ASPATH_TOTHOPS,
13267 BGP_STATS_ASPATH_MAXSIZE,
13268 BGP_STATS_ASPATH_TOTSIZE,
13269 BGP_STATS_ASN_HIGHEST,
13270 BGP_STATS_MAX,
a636c635 13271};
2815e61f 13272
9ab0cf58 13273#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13274#define TABLE_STATS_IDX_JSON 1
13275
13276static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13277 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13278 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13279 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13280 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13281 "unaggregateablePrefixes"},
13282 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13283 "maximumAggregateablePrefixes"},
13284 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13285 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13286 [BGP_STATS_SPACE] = {"Address space advertised",
13287 "addressSpaceAdvertised"},
9ab0cf58
PG
13288 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13289 "advertisementsWithPaths"},
13290 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13291 "longestAsPath"},
13292 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13293 "largestAsPath"},
13294 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13295 "averageAsPathLengthHops"},
13296 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13297 "averageAsPathSizeBytes"},
13298 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13299 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13300};
2815e61f 13301
d62a17ae 13302struct bgp_table_stats {
13303 struct bgp_table *table;
13304 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13305
13306 unsigned long long
13307 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13308 1];
13309
8d0ab76d 13310 double total_space;
ff7924f6
PJ
13311};
13312
9bcb3eef 13313static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13314 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13315{
9bcb3eef 13316 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13317 struct bgp_path_info *pi;
b54892e0 13318 const struct prefix *rn_p;
d62a17ae 13319
9bcb3eef 13320 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13321 return;
d62a17ae 13322
9bcb3eef 13323 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13324 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13325 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13326
0747643e 13327 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13328 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13329 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13330 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13331
9bcb3eef 13332 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13333 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13334 /* announced address space */
13335 if (space)
b54892e0 13336 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13337 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13338 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13339
9c14ec72 13340
9bcb3eef 13341 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13342 ts->counts[BGP_STATS_RIB]++;
13343
05864da7
DS
13344 if (CHECK_FLAG(pi->attr->flag,
13345 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13346 ts->counts[BGP_STATS_AGGREGATES]++;
13347
13348 /* as-path stats */
05864da7 13349 if (pi->attr->aspath) {
9c14ec72
RW
13350 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13351 unsigned int size = aspath_size(pi->attr->aspath);
13352 as_t highest = aspath_highest(pi->attr->aspath);
13353
13354 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13355
13356 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13357 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13358
13359 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13360 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13361
13362 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13363 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13364 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13365 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13366 }
13367 }
13368}
13369
e6685141 13370static void bgp_table_stats_walker(struct event *t)
9c14ec72 13371{
9bcb3eef
DS
13372 struct bgp_dest *dest, *ndest;
13373 struct bgp_dest *top;
e16d030c 13374 struct bgp_table_stats *ts = EVENT_ARG(t);
9c14ec72
RW
13375 unsigned int space = 0;
13376
13377 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13378 return;
9c14ec72
RW
13379
13380 switch (ts->table->afi) {
13381 case AFI_IP:
13382 space = IPV4_MAX_BITLEN;
13383 break;
13384 case AFI_IP6:
13385 space = IPV6_MAX_BITLEN;
13386 break;
3ba7b4af
TA
13387 case AFI_L2VPN:
13388 space = EVPN_ROUTE_PREFIXLEN;
13389 break;
58cf0823
DS
13390 case AFI_UNSPEC:
13391 case AFI_MAX:
cc9f21da 13392 return;
9c14ec72
RW
13393 }
13394
13395 ts->counts[BGP_STATS_MAXBITLEN] = space;
13396
9bcb3eef 13397 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13398 if (ts->table->safi == SAFI_MPLS_VPN
13399 || ts->table->safi == SAFI_ENCAP
13400 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13401 struct bgp_table *table;
13402
9bcb3eef 13403 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13404 if (!table)
13405 continue;
13406
13407 top = bgp_table_top(table);
9bcb3eef
DS
13408 for (ndest = bgp_table_top(table); ndest;
13409 ndest = bgp_route_next(ndest))
13410 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13411 } else {
9bcb3eef 13412 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13413 }
13414 }
2815e61f 13415}
ff7924f6 13416
71f1613a
DA
13417static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13418 struct json_object *json_array)
13419{
13420 struct listnode *node, *nnode;
13421 struct bgp *bgp;
13422
13423 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13424 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13425}
13426
13427static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13428 safi_t safi, struct json_object *json_array)
2815e61f 13429{
d62a17ae 13430 struct bgp_table_stats ts;
13431 unsigned int i;
893cccd0
PG
13432 int ret = CMD_SUCCESS;
13433 char temp_buf[20];
6c9d22e2 13434 struct json_object *json = NULL;
0747643e
AQ
13435 uint32_t bitlen = 0;
13436 struct json_object *json_bitlen;
6c9d22e2
PG
13437
13438 if (json_array)
13439 json = json_object_new_object();
019386c2 13440
d62a17ae 13441 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13442 char warning_msg[50];
13443
13444 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13445 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13446 safi);
6c9d22e2
PG
13447
13448 if (!json)
893cccd0
PG
13449 vty_out(vty, "%s\n", warning_msg);
13450 else
9ab0cf58 13451 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13452
893cccd0
PG
13453 ret = CMD_WARNING;
13454 goto end_table_stats;
d62a17ae 13455 }
019386c2 13456
893cccd0 13457 if (!json)
5290ceab
DA
13458 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13459 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13460 else
13461 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13462
d62a17ae 13463 /* labeled-unicast routes live in the unicast table */
13464 if (safi == SAFI_LABELED_UNICAST)
13465 safi = SAFI_UNICAST;
019386c2 13466
d62a17ae 13467 memset(&ts, 0, sizeof(ts));
13468 ts.table = bgp->rib[afi][safi];
8c1186d3 13469 event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13470
d62a17ae 13471 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13472 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13473 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13474 continue;
13475
13476 switch (i) {
d62a17ae 13477 case BGP_STATS_ASPATH_TOTHOPS:
13478 case BGP_STATS_ASPATH_TOTSIZE:
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_ASPATH_COUNT]
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_ASPATH_COUNT]
9ab0cf58
PG
13500 : 0);
13501 }
d62a17ae 13502 break;
13503 case BGP_STATS_TOTPLEN:
6c9d22e2 13504 if (!json) {
9ab0cf58
PG
13505 snprintf(
13506 temp_buf, sizeof(temp_buf), "%12.2f",
13507 ts.counts[i]
13508 ? (float)ts.counts[i]
13509 / (float)ts.counts
13510 [BGP_STATS_PREFIXES]
13511 : 0);
893cccd0 13512 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13513 table_stats_strs[i]
13514 [TABLE_STATS_IDX_VTY],
893cccd0 13515 temp_buf);
9ab0cf58
PG
13516 } else {
13517 json_object_double_add(
13518 json,
13519 table_stats_strs[i]
13520 [TABLE_STATS_IDX_JSON],
13521 ts.counts[i]
13522 ? (double)ts.counts[i]
13523 / (double)ts.counts
d62a17ae 13524 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13525 : 0);
13526 }
d62a17ae 13527 break;
13528 case BGP_STATS_SPACE:
6c9d22e2
PG
13529 if (!json) {
13530 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13531 ts.total_space);
893cccd0 13532 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13533 table_stats_strs[i]
13534 [TABLE_STATS_IDX_VTY],
893cccd0 13535 temp_buf);
9ab0cf58
PG
13536 } else {
13537 json_object_double_add(
13538 json,
13539 table_stats_strs[i]
13540 [TABLE_STATS_IDX_JSON],
13541 (double)ts.total_space);
13542 }
8d0ab76d 13543 if (afi == AFI_IP6) {
6c9d22e2
PG
13544 if (!json) {
13545 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13546 "%12g",
13547 ts.total_space
13548 * pow(2.0, -128 + 32));
6c9d22e2
PG
13549 vty_out(vty, "%30s: %s\n",
13550 "/32 equivalent %s\n",
13551 temp_buf);
9ab0cf58
PG
13552 } else {
13553 json_object_double_add(
13554 json, "/32equivalent",
13555 (double)(ts.total_space
13556 * pow(2.0,
13557 -128 + 32)));
13558 }
6c9d22e2
PG
13559 if (!json) {
13560 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13561 "%12g",
13562 ts.total_space
13563 * pow(2.0, -128 + 48));
6c9d22e2
PG
13564 vty_out(vty, "%30s: %s\n",
13565 "/48 equivalent %s\n",
13566 temp_buf);
9ab0cf58
PG
13567 } else {
13568 json_object_double_add(
13569 json, "/48equivalent",
13570 (double)(ts.total_space
13571 * pow(2.0,
13572 -128 + 48)));
13573 }
8d0ab76d 13574 } else {
6c9d22e2
PG
13575 if (!json) {
13576 snprintf(temp_buf, sizeof(temp_buf),
13577 "%12.2f",
9ab0cf58
PG
13578 ts.total_space * 100.
13579 * pow(2.0, -32));
6c9d22e2 13580 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13581 "% announced ", temp_buf);
13582 } else {
13583 json_object_double_add(
13584 json, "%announced",
13585 (double)(ts.total_space * 100.
13586 * pow(2.0, -32)));
13587 }
6c9d22e2
PG
13588 if (!json) {
13589 snprintf(temp_buf, sizeof(temp_buf),
13590 "%12.2f",
9ab0cf58
PG
13591 ts.total_space
13592 * pow(2.0, -32 + 8));
6c9d22e2
PG
13593 vty_out(vty, "%30s: %s\n",
13594 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13595 } else {
13596 json_object_double_add(
13597 json, "/8equivalent",
13598 (double)(ts.total_space
13599 * pow(2.0, -32 + 8)));
13600 }
6c9d22e2
PG
13601 if (!json) {
13602 snprintf(temp_buf, sizeof(temp_buf),
13603 "%12.2f",
9ab0cf58
PG
13604 ts.total_space
13605 * pow(2.0, -32 + 24));
6c9d22e2 13606 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13607 "/24 equivalent ", temp_buf);
13608 } else {
13609 json_object_double_add(
13610 json, "/24equivalent",
13611 (double)(ts.total_space
13612 * pow(2.0, -32 + 24)));
13613 }
8d0ab76d 13614 }
d62a17ae 13615 break;
13616 default:
6c9d22e2
PG
13617 if (!json) {
13618 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13619 ts.counts[i]);
893cccd0 13620 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13621 table_stats_strs[i]
13622 [TABLE_STATS_IDX_VTY],
13623 temp_buf);
13624 } else {
13625 json_object_int_add(
13626 json,
13627 table_stats_strs[i]
13628 [TABLE_STATS_IDX_JSON],
13629 ts.counts[i]);
13630 }
d62a17ae 13631 }
893cccd0
PG
13632 if (!json)
13633 vty_out(vty, "\n");
d62a17ae 13634 }
0747643e
AQ
13635
13636 switch (afi) {
13637 case AFI_IP:
13638 bitlen = IPV4_MAX_BITLEN;
13639 break;
13640 case AFI_IP6:
13641 bitlen = IPV6_MAX_BITLEN;
13642 break;
13643 case AFI_L2VPN:
13644 bitlen = EVPN_ROUTE_PREFIXLEN;
13645 break;
58cf0823
DS
13646 case AFI_UNSPEC:
13647 case AFI_MAX:
0747643e
AQ
13648 break;
13649 }
13650
13651 if (json) {
13652 json_bitlen = json_object_new_array();
13653
13654 for (i = 0; i <= bitlen; i++) {
13655 struct json_object *ind_bit = json_object_new_object();
13656
13657 if (!ts.prefix_len_count[i])
13658 continue;
13659
13660 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13661 json_object_int_add(ind_bit, temp_buf,
13662 ts.prefix_len_count[i]);
13663 json_object_array_add(json_bitlen, ind_bit);
13664 }
13665 json_object_object_add(json, "prefixLength", json_bitlen);
13666 }
13667
9ab0cf58 13668end_table_stats:
6c9d22e2
PG
13669 if (json)
13670 json_object_array_add(json_array, json);
893cccd0 13671 return ret;
d62a17ae 13672}
13673
71f1613a
DA
13674static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13675 safi_t safi, struct json_object *json_array)
13676{
13677 if (!bgp) {
13678 bgp_table_stats_all(vty, afi, safi, json_array);
13679 return CMD_SUCCESS;
13680 }
13681
13682 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13683}
13684
d62a17ae 13685enum bgp_pcounts {
13686 PCOUNT_ADJ_IN = 0,
13687 PCOUNT_DAMPED,
13688 PCOUNT_REMOVED,
13689 PCOUNT_HISTORY,
13690 PCOUNT_STALE,
13691 PCOUNT_VALID,
13692 PCOUNT_ALL,
13693 PCOUNT_COUNTED,
7e3d9632 13694 PCOUNT_BPATH_SELECTED,
d62a17ae 13695 PCOUNT_PFCNT, /* the figure we display to users */
13696 PCOUNT_MAX,
a636c635 13697};
718e3744 13698
2b64873d 13699static const char *const pcount_strs[] = {
9d303b37
DL
13700 [PCOUNT_ADJ_IN] = "Adj-in",
13701 [PCOUNT_DAMPED] = "Damped",
13702 [PCOUNT_REMOVED] = "Removed",
13703 [PCOUNT_HISTORY] = "History",
13704 [PCOUNT_STALE] = "Stale",
13705 [PCOUNT_VALID] = "Valid",
13706 [PCOUNT_ALL] = "All RIB",
13707 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13708 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13709 [PCOUNT_PFCNT] = "Useable",
13710 [PCOUNT_MAX] = NULL,
a636c635 13711};
718e3744 13712
d62a17ae 13713struct peer_pcounts {
13714 unsigned int count[PCOUNT_MAX];
13715 const struct peer *peer;
13716 const struct bgp_table *table;
54317cba 13717 safi_t safi;
a636c635 13718};
47fc97cc 13719
9bcb3eef 13720static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13721{
54317cba
JW
13722 const struct bgp_adj_in *ain;
13723 const struct bgp_path_info *pi;
d62a17ae 13724 const struct peer *peer = pc->peer;
13725
54317cba
JW
13726 for (ain = rn->adj_in; ain; ain = ain->next)
13727 if (ain->peer == peer)
13728 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13729
9bcb3eef 13730 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13731
54317cba
JW
13732 if (pi->peer != peer)
13733 continue;
d62a17ae 13734
54317cba 13735 pc->count[PCOUNT_ALL]++;
d62a17ae 13736
54317cba
JW
13737 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13738 pc->count[PCOUNT_DAMPED]++;
13739 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13740 pc->count[PCOUNT_HISTORY]++;
13741 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13742 pc->count[PCOUNT_REMOVED]++;
13743 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13744 pc->count[PCOUNT_STALE]++;
13745 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13746 pc->count[PCOUNT_VALID]++;
13747 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13748 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13749 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13750 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13751
13752 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13753 pc->count[PCOUNT_COUNTED]++;
13754 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13755 flog_err(
13756 EC_LIB_DEVELOPMENT,
13757 "Attempting to count but flags say it is unusable");
13758 } else {
40381db7 13759 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13760 flog_err(
13761 EC_LIB_DEVELOPMENT,
13762 "Not counted but flags say we should");
d62a17ae 13763 }
13764 }
54317cba
JW
13765}
13766
e6685141 13767static void bgp_peer_count_walker(struct event *t)
54317cba 13768{
9bcb3eef 13769 struct bgp_dest *rn, *rm;
54317cba 13770 const struct bgp_table *table;
e16d030c 13771 struct peer_pcounts *pc = EVENT_ARG(t);
54317cba
JW
13772
13773 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13774 || pc->safi == SAFI_EVPN) {
13775 /* Special handling for 2-level routing tables. */
13776 for (rn = bgp_table_top(pc->table); rn;
13777 rn = bgp_route_next(rn)) {
9bcb3eef 13778 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13779 if (table != NULL)
13780 for (rm = bgp_table_top(table); rm;
13781 rm = bgp_route_next(rm))
13782 bgp_peer_count_proc(rm, pc);
13783 }
13784 } else
13785 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13786 bgp_peer_count_proc(rn, pc);
718e3744 13787}
13788
d62a17ae 13789static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13790 safi_t safi, bool use_json)
856ca177 13791{
d62a17ae 13792 struct peer_pcounts pcounts = {.peer = peer};
13793 unsigned int i;
13794 json_object *json = NULL;
13795 json_object *json_loop = NULL;
856ca177 13796
d62a17ae 13797 if (use_json) {
13798 json = json_object_new_object();
13799 json_loop = json_object_new_object();
13800 }
718e3744 13801
d62a17ae 13802 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13803 || !peer->bgp->rib[afi][safi]) {
13804 if (use_json) {
13805 json_object_string_add(
13806 json, "warning",
13807 "No such neighbor or address family");
13808 vty_out(vty, "%s\n", json_object_to_json_string(json));
13809 json_object_free(json);
d5f20468 13810 json_object_free(json_loop);
d62a17ae 13811 } else
13812 vty_out(vty, "%% No such neighbor or address family\n");
13813
13814 return CMD_WARNING;
13815 }
2a71e9ce 13816
d62a17ae 13817 memset(&pcounts, 0, sizeof(pcounts));
13818 pcounts.peer = peer;
13819 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13820 pcounts.safi = safi;
d62a17ae 13821
13822 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13823 * stats for the thread-walk (i.e. ensure this can't be blamed on
13824 * on just vty_read()).
13825 */
8c1186d3 13826 event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
d62a17ae 13827
13828 if (use_json) {
13829 json_object_string_add(json, "prefixCountsFor", peer->host);
13830 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13831 get_afi_safi_str(afi, safi, true));
d62a17ae 13832 json_object_int_add(json, "pfxCounter",
13833 peer->pcount[afi][safi]);
13834
13835 for (i = 0; i < PCOUNT_MAX; i++)
13836 json_object_int_add(json_loop, pcount_strs[i],
13837 pcounts.count[i]);
13838
13839 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13840
13841 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13842 json_object_string_add(json, "pfxctDriftFor",
13843 peer->host);
13844 json_object_string_add(
13845 json, "recommended",
13846 "Please report this bug, with the above command output");
13847 }
75eeda93 13848 vty_json(vty, json);
d62a17ae 13849 } else {
13850
13851 if (peer->hostname
892fedb6 13852 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13853 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13854 peer->hostname, peer->host,
5cb5f4d0 13855 get_afi_safi_str(afi, safi, false));
d62a17ae 13856 } else {
13857 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13858 get_afi_safi_str(afi, safi, false));
d62a17ae 13859 }
13860
6cde4b45 13861 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13862 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13863
13864 for (i = 0; i < PCOUNT_MAX; i++)
13865 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13866 pcounts.count[i]);
13867
13868 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13869 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13870 vty_out(vty,
13871 "Please report this bug, with the above command output\n");
13872 }
13873 }
13874
13875 return CMD_SUCCESS;
718e3744 13876}
13877
a636c635
DW
13878DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13879 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13880 "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 13881 SHOW_STR
13882 IP_STR
13883 BGP_STR
8386ac43 13884 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13885 BGP_AFI_HELP_STR
13886 BGP_SAFI_HELP_STR
0b16f239
DS
13887 "Detailed information on TCP and BGP neighbor connections\n"
13888 "Neighbor to display information about\n"
13889 "Neighbor to display information about\n"
91d37724 13890 "Neighbor on BGP configured interface\n"
a636c635 13891 "Display detailed prefix count information\n"
9973d184 13892 JSON_STR)
0b16f239 13893{
d62a17ae 13894 afi_t afi = AFI_IP6;
13895 safi_t safi = SAFI_UNICAST;
13896 struct peer *peer;
13897 int idx = 0;
13898 struct bgp *bgp = NULL;
9f049418
DS
13899 bool uj = use_json(argc, argv);
13900
13901 if (uj)
13902 argc--;
856ca177 13903
d62a17ae 13904 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13905 &bgp, uj);
d62a17ae 13906 if (!idx)
13907 return CMD_WARNING;
0b16f239 13908
d62a17ae 13909 argv_find(argv, argc, "neighbors", &idx);
13910 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13911 if (!peer)
13912 return CMD_WARNING;
bb46e94f 13913
29c8d9da 13914 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13915}
0b16f239 13916
d6902373
PG
13917#ifdef KEEP_OLD_VPN_COMMANDS
13918DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13919 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13920 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13921 SHOW_STR
13922 IP_STR
13923 BGP_STR
d6902373 13924 BGP_VPNVX_HELP_STR
91d37724 13925 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13926 "Detailed information on TCP and BGP neighbor connections\n"
13927 "Neighbor to display information about\n"
13928 "Neighbor to display information about\n"
91d37724 13929 "Neighbor on BGP configured interface\n"
a636c635 13930 "Display detailed prefix count information\n"
9973d184 13931 JSON_STR)
a636c635 13932{
d62a17ae 13933 int idx_peer = 6;
13934 struct peer *peer;
9f049418 13935 bool uj = use_json(argc, argv);
a636c635 13936
d62a17ae 13937 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13938 if (!peer)
13939 return CMD_WARNING;
13940
13941 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13942}
13943
d6902373
PG
13944DEFUN (show_ip_bgp_vpn_all_route_prefix,
13945 show_ip_bgp_vpn_all_route_prefix_cmd,
13946 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13947 SHOW_STR
13948 IP_STR
13949 BGP_STR
d6902373 13950 BGP_VPNVX_HELP_STR
91d37724
QY
13951 "Display information about all VPNv4 NLRIs\n"
13952 "Network in the BGP routing table to display\n"
3a2d747c 13953 "Network in the BGP routing table to display\n"
9973d184 13954 JSON_STR)
91d37724 13955{
d62a17ae 13956 int idx = 0;
13957 char *network = NULL;
13958 struct bgp *bgp = bgp_get_default();
13959 if (!bgp) {
13960 vty_out(vty, "Can't find default instance\n");
13961 return CMD_WARNING;
13962 }
87e34b58 13963
d62a17ae 13964 if (argv_find(argv, argc, "A.B.C.D", &idx))
13965 network = argv[idx]->arg;
13966 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13967 network = argv[idx]->arg;
13968 else {
13969 vty_out(vty, "Unable to figure out Network\n");
13970 return CMD_WARNING;
13971 }
87e34b58 13972
d62a17ae 13973 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13974 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13975 use_json(argc, argv));
91d37724 13976}
d6902373 13977#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13978
44c69747
LK
13979DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13980 show_bgp_l2vpn_evpn_route_prefix_cmd,
13981 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13982 SHOW_STR
4c63a661
PG
13983 BGP_STR
13984 L2VPN_HELP_STR
13985 EVPN_HELP_STR
44c69747
LK
13986 "Network in the BGP routing table to display\n"
13987 "Network in the BGP routing table to display\n"
4c63a661
PG
13988 "Network in the BGP routing table to display\n"
13989 "Network in the BGP routing table to display\n"
13990 JSON_STR)
13991{
d62a17ae 13992 int idx = 0;
13993 char *network = NULL;
44c69747 13994 int prefix_check = 0;
a636c635 13995
44c69747
LK
13996 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13997 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13998 network = argv[idx]->arg;
44c69747 13999 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 14000 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 14001 network = argv[idx]->arg;
44c69747
LK
14002 prefix_check = 1;
14003 } else {
d62a17ae 14004 vty_out(vty, "Unable to figure out Network\n");
14005 return CMD_WARNING;
14006 }
44c69747
LK
14007 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
14008 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 14009 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 14010}
14011
114fc229 14012static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
14013 struct bgp_table *table, int *header1,
14014 int *header2, json_object *json,
14015 json_object *json_scode,
e960b4ca
TA
14016 json_object *json_ocode, bool wide,
14017 bool detail)
2f9bc755
DS
14018{
14019 uint64_t version = table ? table->version : 0;
14020
14021 if (*header1) {
14022 if (json) {
14023 json_object_int_add(json, "bgpTableVersion", version);
c949c771 14024 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 14025 "%pI4", &peer->bgp->router_id);
2f9bc755 14026 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
14027 peer->bgp->default_local_pref);
14028 json_object_int_add(json, "localAS",
14029 peer->change_local_as
14030 ? peer->change_local_as
14031 : peer->local_as);
2f9bc755
DS
14032 json_object_object_add(json, "bgpStatusCodes",
14033 json_scode);
14034 json_object_object_add(json, "bgpOriginCodes",
14035 json_ocode);
14036 } else {
14037 vty_out(vty,
23d0a753
DA
14038 "BGP table version is %" PRIu64
14039 ", local router ID is %pI4, vrf id ",
114fc229
DA
14040 version, &peer->bgp->router_id);
14041 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14042 vty_out(vty, "%s", VRFID_NONE_STR);
14043 else
114fc229 14044 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14045 vty_out(vty, "\n");
14046 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14047 peer->bgp->default_local_pref);
14048 vty_out(vty, "local AS %u\n",
14049 peer->change_local_as ? peer->change_local_as
14050 : peer->local_as);
e960b4ca
TA
14051 if (!detail) {
14052 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14053 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14054 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14055 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14056 }
2f9bc755
DS
14057 }
14058 *header1 = 0;
14059 }
14060 if (*header2) {
e960b4ca 14061 if (!json && !detail)
2f9bc755
DS
14062 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14063 : BGP_SHOW_HEADER));
14064 *header2 = 0;
14065 }
14066}
14067
d9478df0
TA
14068static void
14069show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14070 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14071 const char *rmap_name, json_object *json, json_object *json_ar,
14072 json_object *json_scode, json_object *json_ocode,
96c81f66 14073 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14074 const struct prefix *match, unsigned long *output_count,
14075 unsigned long *filtered_count)
d62a17ae 14076{
3880b4ec
TA
14077 struct bgp_adj_in *ain = NULL;
14078 struct bgp_adj_out *adj = NULL;
9bcb3eef 14079 struct bgp_dest *dest;
d62a17ae 14080 struct bgp *bgp;
d62a17ae 14081 struct attr attr;
14082 int ret;
14083 struct update_subgroup *subgrp;
3880b4ec 14084 struct peer_af *paf = NULL;
f99def61 14085 bool route_filtered;
e960b4ca 14086 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14087 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14088 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14089 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14090 || (safi == SAFI_EVPN))
14091 ? true
14092 : false;
e960b4ca
TA
14093 int display = 0;
14094 json_object *json_net = NULL;
a636c635 14095
d62a17ae 14096 bgp = peer->bgp;
a636c635 14097
3880b4ec
TA
14098 /* If the user supplied a prefix, look for a matching route instead
14099 * of walking the whole table.
14100 */
14101 if (match) {
14102 dest = bgp_node_match(table, match);
14103 if (!dest) {
14104 if (!use_json)
14105 vty_out(vty, "Network not in table\n");
14106 return;
14107 }
14108
14109 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14110
14111 if (rn_p->prefixlen != match->prefixlen) {
14112 if (!use_json)
14113 vty_out(vty, "Network not in table\n");
14114 bgp_dest_unlock_node(dest);
14115 return;
14116 }
14117
14118 if (type == bgp_show_adj_route_received ||
14119 type == bgp_show_adj_route_filtered) {
14120 for (ain = dest->adj_in; ain; ain = ain->next) {
14121 if (ain->peer == peer) {
14122 attr = *ain->attr;
14123 break;
14124 }
14125 }
14126 /* bail out if if adj_out is empty, or
14127 * if the prefix isn't in this peer's
14128 * adj_in
14129 */
14130 if (!ain || ain->peer != peer) {
14131 if (!use_json)
14132 vty_out(vty, "Network not in table\n");
14133 bgp_dest_unlock_node(dest);
14134 return;
14135 }
14136 } else if (type == bgp_show_adj_route_advertised) {
14137 bool peer_found = false;
14138
14139 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14140 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14141 if (paf->peer == peer && adj->attr) {
14142 attr = *adj->attr;
14143 peer_found = true;
14144 break;
14145 }
14146 }
14147 if (peer_found)
14148 break;
14149 }
14150 /* bail out if if adj_out is empty, or
14151 * if the prefix isn't in this peer's
14152 * adj_out
14153 */
14154 if (!paf || !peer_found) {
14155 if (!use_json)
14156 vty_out(vty, "Network not in table\n");
14157 bgp_dest_unlock_node(dest);
14158 return;
14159 }
14160 }
14161
14162 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14163 rmap_name);
14164
14165 if (ret != RMAP_DENY) {
14166 show_adj_route_header(vty, peer, table, header1,
14167 header2, json, json_scode,
14168 json_ocode, wide, detail);
14169
14170 if (use_json)
14171 json_net = json_object_new_object();
14172
14173 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14174 afi, safi, json_net,
14175 BGP_PATH_SHOW_ALL, &display,
14176 RPKI_NOT_BEING_USED);
14177 if (use_json)
14178 json_object_object_addf(json_ar, json_net,
14179 "%pFX", rn_p);
14180 (*output_count)++;
14181 } else
14182 (*filtered_count)++;
14183
14184 bgp_attr_flush(&attr);
14185 bgp_dest_unlock_node(dest);
14186 return;
14187 }
14188
14189
d62a17ae 14190 subgrp = peer_subgroup(peer, afi, safi);
14191
6392aaa6 14192 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14193 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14194 if (use_json) {
14195 json_object_int_add(json, "bgpTableVersion",
14196 table->version);
c949c771
DA
14197 json_object_string_addf(json, "bgpLocalRouterId",
14198 "%pI4", &bgp->router_id);
01eced22
AD
14199 json_object_int_add(json, "defaultLocPrf",
14200 bgp->default_local_pref);
114fc229
DA
14201 json_object_int_add(json, "localAS",
14202 peer->change_local_as
14203 ? peer->change_local_as
14204 : peer->local_as);
d62a17ae 14205 json_object_object_add(json, "bgpStatusCodes",
14206 json_scode);
14207 json_object_object_add(json, "bgpOriginCodes",
14208 json_ocode);
07d0c4ed
DA
14209 json_object_string_add(
14210 json, "bgpOriginatingDefaultNetwork",
14211 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14212 } else {
23d0a753
DA
14213 vty_out(vty,
14214 "BGP table version is %" PRIu64
14215 ", local router ID is %pI4, vrf id ",
14216 table->version, &bgp->router_id);
9df8b37c
PZ
14217 if (bgp->vrf_id == VRF_UNKNOWN)
14218 vty_out(vty, "%s", VRFID_NONE_STR);
14219 else
14220 vty_out(vty, "%u", bgp->vrf_id);
14221 vty_out(vty, "\n");
01eced22
AD
14222 vty_out(vty, "Default local pref %u, ",
14223 bgp->default_local_pref);
114fc229
DA
14224 vty_out(vty, "local AS %u\n",
14225 peer->change_local_as ? peer->change_local_as
14226 : peer->local_as);
e960b4ca
TA
14227 if (!detail) {
14228 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14229 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14230 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14231 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14232 }
d62a17ae 14233
07d0c4ed
DA
14234 vty_out(vty, "Originating default network %s\n\n",
14235 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14236 }
65565c9a 14237 (*output_count)++;
d9478df0 14238 *header1 = 0;
d62a17ae 14239 }
a636c635 14240
9bcb3eef 14241 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14242 if (type == bgp_show_adj_route_received
14243 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14244 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14245 if (ain->peer != peer)
ea47320b 14246 continue;
6392aaa6 14247
114fc229 14248 show_adj_route_header(vty, peer, table, header1,
d9478df0 14249 header2, json, json_scode,
e960b4ca 14250 json_ocode, wide, detail);
d9478df0
TA
14251
14252 if ((safi == SAFI_MPLS_VPN)
14253 || (safi == SAFI_ENCAP)
14254 || (safi == SAFI_EVPN)) {
14255 if (use_json)
14256 json_object_string_add(
14257 json_ar, "rd", rd_str);
14258 else if (show_rd && rd_str) {
14259 vty_out(vty,
14260 "Route Distinguisher: %s\n",
14261 rd_str);
14262 show_rd = false;
14263 }
14264 }
6392aaa6 14265
6f4f49b2 14266 attr = *ain->attr;
f99def61
AD
14267 route_filtered = false;
14268
14269 /* Filter prefix using distribute list,
14270 * filter list or prefix list
14271 */
b54892e0 14272 const struct prefix *rn_p =
9bcb3eef 14273 bgp_dest_get_prefix(dest);
b54892e0
DS
14274 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14275 safi))
14276 == FILTER_DENY)
f99def61
AD
14277 route_filtered = true;
14278
14279 /* Filter prefix using route-map */
b54892e0
DS
14280 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14281 safi, rmap_name, NULL,
14282 0, NULL);
6392aaa6 14283
13c8e163
AD
14284 if (type == bgp_show_adj_route_filtered &&
14285 !route_filtered && ret != RMAP_DENY) {
d498917e 14286 bgp_attr_flush(&attr);
6392aaa6 14287 continue;
d62a17ae 14288 }
6392aaa6 14289
d9478df0
TA
14290 if (type == bgp_show_adj_route_received
14291 && (route_filtered || ret == RMAP_DENY))
14292 (*filtered_count)++;
6392aaa6 14293
e960b4ca
TA
14294 if (detail) {
14295 if (use_json)
14296 json_net =
14297 json_object_new_object();
14298 bgp_show_path_info(
14299 NULL /* prefix_rd */, dest, vty,
14300 bgp, afi, safi, json_net,
14301 BGP_PATH_SHOW_ALL, &display,
14302 RPKI_NOT_BEING_USED);
14303 if (use_json)
14304 json_object_object_addf(
14305 json_ar, json_net,
14306 "%pFX", rn_p);
14307 } else
14308 route_vty_out_tmp(vty, dest, rn_p,
14309 &attr, safi, use_json,
14310 json_ar, wide);
d498917e 14311 bgp_attr_flush(&attr);
d9478df0 14312 (*output_count)++;
d62a17ae 14313 }
6392aaa6 14314 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14315 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14316 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14317 if (paf->peer != peer || !adj->attr)
924c3f6a 14318 continue;
d62a17ae 14319
e960b4ca
TA
14320 show_adj_route_header(
14321 vty, peer, table, header1,
14322 header2, json, json_scode,
14323 json_ocode, wide, detail);
d62a17ae 14324
b54892e0 14325 const struct prefix *rn_p =
9bcb3eef 14326 bgp_dest_get_prefix(dest);
b54892e0 14327
6f4f49b2 14328 attr = *adj->attr;
b755861b 14329 ret = bgp_output_modifier(
b54892e0 14330 peer, rn_p, &attr, afi, safi,
b755861b 14331 rmap_name);
f46d8e1e 14332
b755861b 14333 if (ret != RMAP_DENY) {
d9478df0
TA
14334 if ((safi == SAFI_MPLS_VPN)
14335 || (safi == SAFI_ENCAP)
14336 || (safi == SAFI_EVPN)) {
14337 if (use_json)
14338 json_object_string_add(
14339 json_ar,
14340 "rd",
14341 rd_str);
14342 else if (show_rd
14343 && rd_str) {
14344 vty_out(vty,
14345 "Route Distinguisher: %s\n",
14346 rd_str);
14347 show_rd = false;
14348 }
14349 }
e960b4ca
TA
14350 if (detail) {
14351 if (use_json)
14352 json_net =
14353 json_object_new_object();
14354 bgp_show_path_info(
14355 NULL /* prefix_rd
14356 */
14357 ,
14358 dest, vty, bgp,
14359 afi, safi,
14360 json_net,
14361 BGP_PATH_SHOW_ALL,
14362 &display,
14363 RPKI_NOT_BEING_USED);
14364 if (use_json)
14365 json_object_object_addf(
14366 json_ar,
14367 json_net,
14368 "%pFX",
14369 rn_p);
14370 } else
14371 route_vty_out_tmp(
14372 vty, dest, rn_p,
14373 &attr, safi,
14374 use_json,
14375 json_ar, wide);
d9478df0 14376 (*output_count)++;
b755861b 14377 } else {
d9478df0 14378 (*filtered_count)++;
a2addae8 14379 }
b755861b 14380
d498917e 14381 bgp_attr_flush(&attr);
924c3f6a 14382 }
f20ce998
DS
14383 } else if (type == bgp_show_adj_route_bestpath) {
14384 struct bgp_path_info *pi;
14385
114fc229
DA
14386 show_adj_route_header(vty, peer, table, header1,
14387 header2, json, json_scode,
e960b4ca 14388 json_ocode, wide, detail);
f20ce998 14389
aa9bf57e
TA
14390 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14391
f20ce998
DS
14392 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14393 pi = pi->next) {
14394 if (pi->peer != peer)
14395 continue;
14396
14397 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14398 continue;
14399
aa9bf57e
TA
14400 if (detail) {
14401 if (use_json)
14402 json_net =
14403 json_object_new_object();
14404 bgp_show_path_info(
14405 NULL /* prefix_rd */, dest, vty,
14406 bgp, afi, safi, json_net,
14407 BGP_PATH_SHOW_BESTPATH,
14408 &display, RPKI_NOT_BEING_USED);
14409 if (use_json)
14410 json_object_object_addf(
14411 json_ar, json_net,
14412 "%pFX", rn_p);
14413 } else
14414 route_vty_out_tmp(
14415 vty, dest, rn_p, pi->attr, safi,
14416 use_json, json_ar, wide);
d9478df0 14417 (*output_count)++;
f20ce998 14418 }
d62a17ae 14419 }
14420 }
a636c635 14421}
2a71e9ce 14422
d62a17ae 14423static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14424 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14425 const char *rmap_name, const struct prefix *match,
14426 uint16_t show_flags)
0b16f239 14427{
d9478df0
TA
14428 struct bgp *bgp;
14429 struct bgp_table *table;
d62a17ae 14430 json_object *json = NULL;
d9478df0
TA
14431 json_object *json_scode = NULL;
14432 json_object *json_ocode = NULL;
14433 json_object *json_ar = NULL;
96f3485c 14434 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14435
d9478df0
TA
14436 /* Init BGP headers here so they're only displayed once
14437 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14438 */
14439 int header1 = 1;
14440 int header2 = 1;
14441
14442 /*
14443 * Initialize variables for each RD
14444 * All prefixes under an RD is aggregated within "json_routes"
14445 */
14446 char rd_str[BUFSIZ] = {0};
14447 json_object *json_routes = NULL;
14448
14449
14450 /* For 2-tier tables, prefix counts need to be
14451 * maintained across multiple runs of show_adj_route()
14452 */
14453 unsigned long output_count_per_rd;
14454 unsigned long filtered_count_per_rd;
14455 unsigned long output_count = 0;
14456 unsigned long filtered_count = 0;
14457
14458 if (use_json) {
d62a17ae 14459 json = json_object_new_object();
d9478df0
TA
14460 json_ar = json_object_new_object();
14461 json_scode = json_object_new_object();
14462 json_ocode = json_object_new_object();
dd426a51
DA
14463#if CONFDATE > 20231208
14464CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14465#endif
d9478df0
TA
14466 json_object_string_add(json_scode, "suppressed", "s");
14467 json_object_string_add(json_scode, "damped", "d");
14468 json_object_string_add(json_scode, "history", "h");
14469 json_object_string_add(json_scode, "valid", "*");
14470 json_object_string_add(json_scode, "best", ">");
14471 json_object_string_add(json_scode, "multipath", "=");
14472 json_object_string_add(json_scode, "internal", "i");
14473 json_object_string_add(json_scode, "ribFailure", "r");
14474 json_object_string_add(json_scode, "stale", "S");
14475 json_object_string_add(json_scode, "removed", "R");
14476
dd426a51
DA
14477#if CONFDATE > 20231208
14478CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14479#endif
d9478df0
TA
14480 json_object_string_add(json_ocode, "igp", "i");
14481 json_object_string_add(json_ocode, "egp", "e");
14482 json_object_string_add(json_ocode, "incomplete", "?");
14483 }
0b16f239 14484
d62a17ae 14485 if (!peer || !peer->afc[afi][safi]) {
14486 if (use_json) {
14487 json_object_string_add(
14488 json, "warning",
14489 "No such neighbor or address family");
14490 vty_out(vty, "%s\n", json_object_to_json_string(json));
14491 json_object_free(json);
690c3134
MW
14492 json_object_free(json_ar);
14493 json_object_free(json_scode);
14494 json_object_free(json_ocode);
d62a17ae 14495 } else
14496 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14497
d62a17ae 14498 return CMD_WARNING;
14499 }
14500
6392aaa6
PM
14501 if ((type == bgp_show_adj_route_received
14502 || type == bgp_show_adj_route_filtered)
d62a17ae 14503 && !CHECK_FLAG(peer->af_flags[afi][safi],
14504 PEER_FLAG_SOFT_RECONFIG)) {
14505 if (use_json) {
14506 json_object_string_add(
14507 json, "warning",
14508 "Inbound soft reconfiguration not enabled");
14509 vty_out(vty, "%s\n", json_object_to_json_string(json));
14510 json_object_free(json);
690c3134
MW
14511 json_object_free(json_ar);
14512 json_object_free(json_scode);
14513 json_object_free(json_ocode);
d62a17ae 14514 } else
14515 vty_out(vty,
14516 "%% Inbound soft reconfiguration not enabled\n");
14517
14518 return CMD_WARNING;
14519 }
0b16f239 14520
d9478df0
TA
14521 bgp = peer->bgp;
14522
14523 /* labeled-unicast routes live in the unicast table */
14524 if (safi == SAFI_LABELED_UNICAST)
14525 table = bgp->rib[afi][SAFI_UNICAST];
14526 else
14527 table = bgp->rib[afi][safi];
14528
14529 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14530 || (safi == SAFI_EVPN)) {
14531
14532 struct bgp_dest *dest;
14533
14534 for (dest = bgp_table_top(table); dest;
14535 dest = bgp_route_next(dest)) {
14536 table = bgp_dest_get_bgp_table_info(dest);
14537 if (!table)
14538 continue;
14539
14540 output_count_per_rd = 0;
14541 filtered_count_per_rd = 0;
14542
14543 if (use_json)
14544 json_routes = json_object_new_object();
14545
14546 const struct prefix_rd *prd;
14547 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14548 dest);
14549
4a8cd6ad
PG
14550 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14551 bgp->asnotation);
d9478df0 14552
3880b4ec
TA
14553 show_adj_route(
14554 vty, peer, table, afi, safi, type, rmap_name,
14555 json, json_routes, json_scode, json_ocode,
14556 show_flags, &header1, &header2, rd_str, match,
14557 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14558
14559 /* Don't include an empty RD in the output! */
14560 if (json_routes && (output_count_per_rd > 0))
14561 json_object_object_add(json_ar, rd_str,
14562 json_routes);
14563
14564 output_count += output_count_per_rd;
14565 filtered_count += filtered_count_per_rd;
14566 }
14567 } else
14568 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14569 json, json_ar, json_scode, json_ocode,
3880b4ec 14570 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14571 &output_count, &filtered_count);
14572
14573 if (use_json) {
c1984955
TA
14574 if (type == bgp_show_adj_route_advertised)
14575 json_object_object_add(json, "advertisedRoutes",
14576 json_ar);
14577 else
14578 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14579 json_object_int_add(json, "totalPrefixCounter", output_count);
14580 json_object_int_add(json, "filteredPrefixCounter",
14581 filtered_count);
14582
690c3134
MW
14583 /*
14584 * These fields only give up ownership to `json` when `header1`
14585 * is used (set to zero). See code in `show_adj_route` and
14586 * `show_adj_route_header`.
14587 */
14588 if (header1 == 1) {
d9478df0
TA
14589 json_object_free(json_scode);
14590 json_object_free(json_ocode);
14591 }
14592
75eeda93 14593 vty_json(vty, json);
d9478df0 14594 } else if (output_count > 0) {
3880b4ec 14595 if (!match && filtered_count > 0)
d9478df0
TA
14596 vty_out(vty,
14597 "\nTotal number of prefixes %ld (%ld filtered)\n",
14598 output_count, filtered_count);
14599 else
14600 vty_out(vty, "\nTotal number of prefixes %ld\n",
14601 output_count);
14602 }
0b16f239 14603
d62a17ae 14604 return CMD_SUCCESS;
a636c635 14605}
50ef26d4 14606
f20ce998
DS
14607DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14608 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14609 "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
14610 SHOW_STR
14611 IP_STR
14612 BGP_STR
14613 BGP_INSTANCE_HELP_STR
14614 BGP_AFI_HELP_STR
14615 BGP_SAFI_WITH_LABEL_HELP_STR
14616 "Detailed information on TCP and BGP neighbor connections\n"
14617 "Neighbor to display information about\n"
14618 "Neighbor to display information about\n"
14619 "Neighbor on BGP configured interface\n"
14620 "Display the routes selected by best path\n"
aa9bf57e 14621 "Display detailed version of routes\n"
f20ce998
DS
14622 JSON_STR
14623 "Increase table width for longer prefixes\n")
14624{
14625 afi_t afi = AFI_IP6;
14626 safi_t safi = SAFI_UNICAST;
14627 char *rmap_name = NULL;
14628 char *peerstr = NULL;
14629 struct bgp *bgp = NULL;
14630 struct peer *peer;
14631 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14632 int idx = 0;
96c81f66 14633 uint16_t show_flags = 0;
96f3485c 14634
aa9bf57e
TA
14635 if (detail)
14636 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14637
96f3485c
MK
14638 if (uj)
14639 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14640
14641 if (wide)
14642 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14643
14644 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14645 &bgp, uj);
14646
14647 if (!idx)
14648 return CMD_WARNING;
14649
14650 argv_find(argv, argc, "neighbors", &idx);
14651 peerstr = argv[++idx]->arg;
14652
14653 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14654 if (!peer)
14655 return CMD_WARNING;
14656
3880b4ec 14657 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14658 show_flags);
f20ce998
DS
14659}
14660
e960b4ca
TA
14661DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14662 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14663 "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
14664 SHOW_STR
14665 IP_STR
14666 BGP_STR
14667 BGP_INSTANCE_HELP_STR
14668 BGP_AFI_HELP_STR
14669 BGP_SAFI_WITH_LABEL_HELP_STR
14670 "Display the entries for all address families\n"
14671 "Detailed information on TCP and BGP neighbor connections\n"
14672 "Neighbor to display information about\n"
14673 "Neighbor to display information about\n"
14674 "Neighbor on BGP configured interface\n"
14675 "Display the routes advertised to a BGP neighbor\n"
14676 "Display the received routes from neighbor\n"
14677 "Display the filtered routes received from neighbor\n"
14678 "Route-map to modify the attributes\n"
14679 "Name of the route map\n"
3880b4ec
TA
14680 "IPv4 prefix\n"
14681 "IPv6 prefix\n"
e960b4ca
TA
14682 "Display detailed version of routes\n"
14683 JSON_STR
14684 "Increase table width for longer prefixes\n")
718e3744 14685{
d62a17ae 14686 afi_t afi = AFI_IP6;
14687 safi_t safi = SAFI_UNICAST;
d62a17ae 14688 char *peerstr = NULL;
d62a17ae 14689 struct bgp *bgp = NULL;
14690 struct peer *peer;
6392aaa6 14691 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14692 int idx = 0;
96f3485c 14693 bool first = true;
96c81f66 14694 uint16_t show_flags = 0;
75ce3b14
DA
14695 struct listnode *node;
14696 struct bgp *abgp;
6392aaa6 14697
3880b4ec 14698 if (detail || prefix_str)
e960b4ca
TA
14699 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14700
96f3485c 14701 if (uj) {
d62a17ae 14702 argc--;
96f3485c
MK
14703 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14704 }
14705
14706 if (all) {
14707 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14708 if (argv_find(argv, argc, "ipv4", &idx))
14709 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14710
14711 if (argv_find(argv, argc, "ipv6", &idx))
14712 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14713 }
14714
14715 if (wide)
14716 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14717
9f049418
DS
14718 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14719 &bgp, uj);
14720 if (!idx)
14721 return CMD_WARNING;
14722
d62a17ae 14723 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14724 argv_find(argv, argc, "neighbors", &idx);
14725 peerstr = argv[++idx]->arg;
8c3deaae 14726
d62a17ae 14727 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14728 if (!peer)
14729 return CMD_WARNING;
856ca177 14730
d62a17ae 14731 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14732 type = bgp_show_adj_route_advertised;
14733 else if (argv_find(argv, argc, "received-routes", &idx))
14734 type = bgp_show_adj_route_received;
14735 else if (argv_find(argv, argc, "filtered-routes", &idx))
14736 type = bgp_show_adj_route_filtered;
14737
96f3485c 14738 if (!all)
70dd370f 14739 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14740 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14741 if (uj)
14742 vty_out(vty, "{\n");
14743
14744 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14745 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14746 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14747 : AFI_IP6;
75ce3b14
DA
14748 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14749 FOREACH_SAFI (safi) {
14750 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14751 continue;
96f3485c 14752
75ce3b14
DA
14753 if (uj) {
14754 if (first)
14755 first = false;
14756 else
14757 vty_out(vty, ",\n");
14758 vty_out(vty, "\"%s\":",
14759 get_afi_safi_str(afi, safi,
14760 true));
14761 } else
14762 vty_out(vty,
14763 "\nFor address family: %s\n",
14764 get_afi_safi_str(afi, safi,
14765 false));
96f3485c 14766
75ce3b14 14767 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14768 route_map, prefix, show_flags);
75ce3b14 14769 }
96f3485c
MK
14770 }
14771 } else {
75ce3b14
DA
14772 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14773 FOREACH_AFI_SAFI (afi, safi) {
14774 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14775 continue;
96f3485c 14776
75ce3b14
DA
14777 if (uj) {
14778 if (first)
14779 first = false;
14780 else
14781 vty_out(vty, ",\n");
14782 vty_out(vty, "\"%s\":",
14783 get_afi_safi_str(afi, safi,
14784 true));
14785 } else
14786 vty_out(vty,
14787 "\nFor address family: %s\n",
14788 get_afi_safi_str(afi, safi,
14789 false));
96f3485c 14790
75ce3b14 14791 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14792 route_map, prefix, show_flags);
75ce3b14 14793 }
96f3485c
MK
14794 }
14795 }
14796 if (uj)
14797 vty_out(vty, "}\n");
14798
14799 return CMD_SUCCESS;
95cbbd2a
ML
14800}
14801
718e3744 14802DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14803 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14804 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14805 SHOW_STR
14806 IP_STR
14807 BGP_STR
d3120452 14808 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14809 BGP_AF_STR
14810 BGP_AF_STR
14811 BGP_AF_MODIFIER_STR
718e3744 14812 "Detailed information on TCP and BGP neighbor connections\n"
14813 "Neighbor to display information about\n"
14814 "Neighbor to display information about\n"
91d37724 14815 "Neighbor on BGP configured interface\n"
718e3744 14816 "Display information received from a BGP neighbor\n"
856ca177 14817 "Display the prefixlist filter\n"
9973d184 14818 JSON_STR)
718e3744 14819{
d62a17ae 14820 afi_t afi = AFI_IP6;
14821 safi_t safi = SAFI_UNICAST;
14822 char *peerstr = NULL;
d62a17ae 14823 char name[BUFSIZ];
d62a17ae 14824 struct peer *peer;
d3120452 14825 int count;
d62a17ae 14826 int idx = 0;
d3120452
IR
14827 struct bgp *bgp = NULL;
14828 bool uj = use_json(argc, argv);
14829
14830 if (uj)
14831 argc--;
14832
14833 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14834 &bgp, uj);
14835 if (!idx)
14836 return CMD_WARNING;
d62a17ae 14837
d62a17ae 14838 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14839 argv_find(argv, argc, "neighbors", &idx);
14840 peerstr = argv[++idx]->arg;
14841
d3120452
IR
14842 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14843 if (!peer)
14844 return CMD_WARNING;
718e3744 14845
4ced1a2c 14846 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14847 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14848 if (count) {
14849 if (!uj)
14850 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14851 get_afi_safi_str(afi, safi, false));
d62a17ae 14852 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14853 } else {
14854 if (uj)
14855 vty_out(vty, "{}\n");
14856 else
14857 vty_out(vty, "No functional output\n");
14858 }
718e3744 14859
d62a17ae 14860 return CMD_SUCCESS;
14861}
14862
14863static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14864 afi_t afi, safi_t safi,
9f049418 14865 enum bgp_show_type type, bool use_json)
d62a17ae 14866{
96c81f66 14867 uint16_t show_flags = 0;
96f3485c
MK
14868
14869 if (use_json)
14870 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14871
d62a17ae 14872 if (!peer || !peer->afc[afi][safi]) {
14873 if (use_json) {
14874 json_object *json_no = NULL;
14875 json_no = json_object_new_object();
14876 json_object_string_add(
14877 json_no, "warning",
14878 "No such neighbor or address family");
14879 vty_out(vty, "%s\n",
14880 json_object_to_json_string(json_no));
14881 json_object_free(json_no);
14882 } else
14883 vty_out(vty, "%% No such neighbor or address family\n");
14884 return CMD_WARNING;
14885 }
47fc97cc 14886
7daf25a3
TA
14887 /* labeled-unicast routes live in the unicast table */
14888 if (safi == SAFI_LABELED_UNICAST)
14889 safi = SAFI_UNICAST;
14890
1e2ce4f1
DS
14891 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14892 RPKI_NOT_BEING_USED);
718e3744 14893}
14894
dba3c1d3
PG
14895DEFUN (show_ip_bgp_flowspec_routes_detailed,
14896 show_ip_bgp_flowspec_routes_detailed_cmd,
14897 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14898 SHOW_STR
14899 IP_STR
14900 BGP_STR
14901 BGP_INSTANCE_HELP_STR
14902 BGP_AFI_HELP_STR
14903 "SAFI Flowspec\n"
14904 "Detailed information on flowspec entries\n"
14905 JSON_STR)
14906{
458c1475 14907 afi_t afi = AFI_IP6;
dba3c1d3
PG
14908 safi_t safi = SAFI_UNICAST;
14909 struct bgp *bgp = NULL;
14910 int idx = 0;
9f049418 14911 bool uj = use_json(argc, argv);
81dcd881 14912 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14913
96f3485c 14914 if (uj) {
9f049418 14915 argc--;
96f3485c
MK
14916 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14917 }
dba3c1d3
PG
14918
14919 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14920 &bgp, uj);
dba3c1d3
PG
14921 if (!idx)
14922 return CMD_WARNING;
14923
96f3485c 14924 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14925 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14926}
14927
718e3744 14928DEFUN (show_ip_bgp_neighbor_routes,
14929 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14930 "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 14931 SHOW_STR
14932 IP_STR
14933 BGP_STR
8386ac43 14934 BGP_INSTANCE_HELP_STR
4f280b15 14935 BGP_AFI_HELP_STR
4dd6177e 14936 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14937 "Detailed information on TCP and BGP neighbor connections\n"
14938 "Neighbor to display information about\n"
14939 "Neighbor to display information about\n"
91d37724 14940 "Neighbor on BGP configured interface\n"
2525cf39 14941 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14942 "Display the dampened routes received from neighbor\n"
14943 "Display routes learned from neighbor\n"
9973d184 14944 JSON_STR)
718e3744 14945{
d62a17ae 14946 char *peerstr = NULL;
14947 struct bgp *bgp = NULL;
14948 afi_t afi = AFI_IP6;
14949 safi_t safi = SAFI_UNICAST;
14950 struct peer *peer;
14951 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14952 int idx = 0;
9f049418
DS
14953 bool uj = use_json(argc, argv);
14954
14955 if (uj)
14956 argc--;
bb46e94f 14957
d62a17ae 14958 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14959 &bgp, uj);
d62a17ae 14960 if (!idx)
14961 return CMD_WARNING;
c493f2d8 14962
d62a17ae 14963 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14964 argv_find(argv, argc, "neighbors", &idx);
14965 peerstr = argv[++idx]->arg;
8c3deaae 14966
d62a17ae 14967 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14968 if (!peer)
d62a17ae 14969 return CMD_WARNING;
bb46e94f 14970
d62a17ae 14971 if (argv_find(argv, argc, "flap-statistics", &idx))
14972 sh_type = bgp_show_type_flap_neighbor;
14973 else if (argv_find(argv, argc, "dampened-routes", &idx))
14974 sh_type = bgp_show_type_damp_neighbor;
14975 else if (argv_find(argv, argc, "routes", &idx))
14976 sh_type = bgp_show_type_neighbor;
2525cf39 14977
d62a17ae 14978 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14979}
6b0655a2 14980
734b349e 14981struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14982
d62a17ae 14983struct bgp_distance {
14984 /* Distance value for the IP source prefix. */
d7c0a89a 14985 uint8_t distance;
718e3744 14986
d62a17ae 14987 /* Name of the access-list to be matched. */
14988 char *access_list;
718e3744 14989};
14990
4f280b15
LB
14991DEFUN (show_bgp_afi_vpn_rd_route,
14992 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14993 "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
14994 SHOW_STR
14995 BGP_STR
14996 BGP_AFI_HELP_STR
00e6edb9 14997 BGP_AF_MODIFIER_STR
4f280b15
LB
14998 "Display information for a route distinguisher\n"
14999 "Route Distinguisher\n"
a111dd97 15000 "All Route Distinguishers\n"
7395a2c9
DS
15001 "Network in the BGP routing table to display\n"
15002 "Network in the BGP routing table to display\n"
15003 JSON_STR)
4f280b15 15004{
d62a17ae 15005 int ret;
15006 struct prefix_rd prd;
15007 afi_t afi = AFI_MAX;
15008 int idx = 0;
4f280b15 15009
ff6566f3
DS
15010 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
15011 vty_out(vty, "%% Malformed Address Family\n");
15012 return CMD_WARNING;
15013 }
15014
a111dd97
TA
15015 if (!strcmp(argv[5]->arg, "all"))
15016 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
15017 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
15018 RPKI_NOT_BEING_USED,
15019 use_json(argc, argv));
15020
d62a17ae 15021 ret = str2prefix_rd(argv[5]->arg, &prd);
15022 if (!ret) {
15023 vty_out(vty, "%% Malformed Route Distinguisher\n");
15024 return CMD_WARNING;
15025 }
ff6566f3 15026
d62a17ae 15027 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
15028 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15029 use_json(argc, argv));
4f280b15
LB
15030}
15031
d62a17ae 15032static struct bgp_distance *bgp_distance_new(void)
718e3744 15033{
d62a17ae 15034 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 15035}
15036
d62a17ae 15037static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15038{
d62a17ae 15039 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15040}
15041
585f1adc
IR
15042static int bgp_distance_set(struct vty *vty, const char *distance_str,
15043 const char *ip_str, const char *access_list_str)
718e3744 15044{
d62a17ae 15045 int ret;
585f1adc
IR
15046 afi_t afi;
15047 safi_t safi;
d62a17ae 15048 struct prefix p;
585f1adc 15049 uint8_t distance;
9bcb3eef 15050 struct bgp_dest *dest;
d62a17ae 15051 struct bgp_distance *bdistance;
718e3744 15052
585f1adc
IR
15053 afi = bgp_node_afi(vty);
15054 safi = bgp_node_safi(vty);
15055
d62a17ae 15056 ret = str2prefix(ip_str, &p);
15057 if (ret == 0) {
585f1adc 15058 vty_out(vty, "Malformed prefix\n");
d62a17ae 15059 return CMD_WARNING_CONFIG_FAILED;
15060 }
718e3744 15061
585f1adc
IR
15062 distance = atoi(distance_str);
15063
d62a17ae 15064 /* Get BGP distance node. */
9bcb3eef
DS
15065 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15066 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15067 if (bdistance)
9bcb3eef 15068 bgp_dest_unlock_node(dest);
ca2e160d 15069 else {
d62a17ae 15070 bdistance = bgp_distance_new();
9bcb3eef 15071 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15072 }
718e3744 15073
d62a17ae 15074 /* Set distance value. */
15075 bdistance->distance = distance;
718e3744 15076
d62a17ae 15077 /* Reset access-list configuration. */
e1b36e13 15078 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15079 if (access_list_str)
15080 bdistance->access_list =
15081 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15082
d62a17ae 15083 return CMD_SUCCESS;
718e3744 15084}
15085
585f1adc
IR
15086static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15087 const char *ip_str, const char *access_list_str)
718e3744 15088{
d62a17ae 15089 int ret;
585f1adc
IR
15090 afi_t afi;
15091 safi_t safi;
d62a17ae 15092 struct prefix p;
585f1adc 15093 int distance;
9bcb3eef 15094 struct bgp_dest *dest;
d62a17ae 15095 struct bgp_distance *bdistance;
718e3744 15096
585f1adc
IR
15097 afi = bgp_node_afi(vty);
15098 safi = bgp_node_safi(vty);
15099
d62a17ae 15100 ret = str2prefix(ip_str, &p);
15101 if (ret == 0) {
585f1adc 15102 vty_out(vty, "Malformed prefix\n");
d62a17ae 15103 return CMD_WARNING_CONFIG_FAILED;
15104 }
718e3744 15105
9bcb3eef
DS
15106 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15107 if (!dest) {
585f1adc 15108 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15109 return CMD_WARNING_CONFIG_FAILED;
15110 }
718e3744 15111
9bcb3eef 15112 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15113 distance = atoi(distance_str);
1f9a9fff 15114
d62a17ae 15115 if (bdistance->distance != distance) {
585f1adc 15116 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15117 bgp_dest_unlock_node(dest);
d62a17ae 15118 return CMD_WARNING_CONFIG_FAILED;
15119 }
718e3744 15120
0a22ddfb 15121 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15122 bgp_distance_free(bdistance);
718e3744 15123
9bcb3eef
DS
15124 bgp_dest_set_bgp_path_info(dest, NULL);
15125 bgp_dest_unlock_node(dest);
15126 bgp_dest_unlock_node(dest);
718e3744 15127
d62a17ae 15128 return CMD_SUCCESS;
718e3744 15129}
15130
718e3744 15131/* Apply BGP information to distance method. */
b8685f9b 15132uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15133 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15134{
9bcb3eef 15135 struct bgp_dest *dest;
801bb996 15136 struct prefix q = {0};
d62a17ae 15137 struct peer *peer;
15138 struct bgp_distance *bdistance;
15139 struct access_list *alist;
15140 struct bgp_static *bgp_static;
a04f1c42 15141 struct bgp_path_info *bpi_ultimate;
d62a17ae 15142
15143 if (!bgp)
15144 return 0;
15145
40381db7 15146 peer = pinfo->peer;
d62a17ae 15147
7b7d48e5
DS
15148 if (pinfo->attr->distance)
15149 return pinfo->attr->distance;
15150
a04f1c42
PG
15151 /* get peer origin to calculate appropriate distance */
15152 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15153 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15154 peer = bpi_ultimate->peer;
15155 }
15156
801bb996
CS
15157 /* Check source address.
15158 * Note: for aggregate route, peer can have unspec af type.
15159 */
15160 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15161 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15162 return 0;
15163
9bcb3eef
DS
15164 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15165 if (dest) {
15166 bdistance = bgp_dest_get_bgp_distance_info(dest);
15167 bgp_dest_unlock_node(dest);
d62a17ae 15168
15169 if (bdistance->access_list) {
15170 alist = access_list_lookup(afi, bdistance->access_list);
15171 if (alist
15172 && access_list_apply(alist, p) == FILTER_PERMIT)
15173 return bdistance->distance;
15174 } else
15175 return bdistance->distance;
718e3744 15176 }
718e3744 15177
d62a17ae 15178 /* Backdoor check. */
9bcb3eef
DS
15179 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15180 if (dest) {
15181 bgp_static = bgp_dest_get_bgp_static_info(dest);
15182 bgp_dest_unlock_node(dest);
718e3744 15183
d62a17ae 15184 if (bgp_static->backdoor) {
15185 if (bgp->distance_local[afi][safi])
15186 return bgp->distance_local[afi][safi];
15187 else
15188 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15189 }
718e3744 15190 }
718e3744 15191
d62a17ae 15192 if (peer->sort == BGP_PEER_EBGP) {
15193 if (bgp->distance_ebgp[afi][safi])
15194 return bgp->distance_ebgp[afi][safi];
15195 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15196 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15197 if (bgp->distance_ibgp[afi][safi])
15198 return bgp->distance_ibgp[afi][safi];
15199 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15200 } else {
15201 if (bgp->distance_local[afi][safi])
15202 return bgp->distance_local[afi][safi];
15203 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15204 }
718e3744 15205}
15206
a612fb77
DA
15207/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15208 * we should tell ZEBRA update the routes for a specific
15209 * AFI/SAFI to reflect changes in RIB.
15210 */
585f1adc
IR
15211static void bgp_announce_routes_distance_update(struct bgp *bgp,
15212 afi_t update_afi,
15213 safi_t update_safi)
a612fb77
DA
15214{
15215 afi_t afi;
15216 safi_t safi;
15217
15218 FOREACH_AFI_SAFI (afi, safi) {
15219 if (!bgp_fibupd_safi(safi))
15220 continue;
15221
8b54bc30
DA
15222 if (afi != update_afi && safi != update_safi)
15223 continue;
15224
15225 if (BGP_DEBUG(zebra, ZEBRA))
15226 zlog_debug(
15227 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15228 __func__, afi, safi);
15229 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15230 }
15231}
15232
585f1adc
IR
15233DEFUN (bgp_distance,
15234 bgp_distance_cmd,
15235 "distance bgp (1-255) (1-255) (1-255)",
15236 "Define an administrative distance\n"
15237 "BGP distance\n"
15238 "Distance for routes external to the AS\n"
15239 "Distance for routes internal to the AS\n"
15240 "Distance for local routes\n")
718e3744 15241{
585f1adc 15242 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15243 int idx_number = 2;
15244 int idx_number_2 = 3;
15245 int idx_number_3 = 4;
585f1adc
IR
15246 int distance_ebgp = atoi(argv[idx_number]->arg);
15247 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15248 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15249 afi_t afi;
15250 safi_t safi;
718e3744 15251
d62a17ae 15252 afi = bgp_node_afi(vty);
15253 safi = bgp_node_safi(vty);
718e3744 15254
585f1adc
IR
15255 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15256 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15257 || bgp->distance_local[afi][safi] != distance_local) {
15258 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15259 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15260 bgp->distance_local[afi][safi] = distance_local;
15261 bgp_announce_routes_distance_update(bgp, afi, safi);
15262 }
15263 return CMD_SUCCESS;
15264}
37a87b8f 15265
585f1adc
IR
15266DEFUN (no_bgp_distance,
15267 no_bgp_distance_cmd,
15268 "no distance bgp [(1-255) (1-255) (1-255)]",
15269 NO_STR
15270 "Define an administrative distance\n"
15271 "BGP distance\n"
15272 "Distance for routes external to the AS\n"
15273 "Distance for routes internal to the AS\n"
15274 "Distance for local routes\n")
718e3744 15275{
585f1adc 15276 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15277 afi_t afi;
15278 safi_t safi;
37a87b8f
CS
15279
15280 afi = bgp_node_afi(vty);
15281 safi = bgp_node_safi(vty);
15282
585f1adc
IR
15283 if (bgp->distance_ebgp[afi][safi] != 0
15284 || bgp->distance_ibgp[afi][safi] != 0
15285 || bgp->distance_local[afi][safi] != 0) {
15286 bgp->distance_ebgp[afi][safi] = 0;
15287 bgp->distance_ibgp[afi][safi] = 0;
15288 bgp->distance_local[afi][safi] = 0;
15289 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15290 }
585f1adc
IR
15291 return CMD_SUCCESS;
15292}
37a87b8f 15293
37a87b8f 15294
585f1adc
IR
15295DEFUN (bgp_distance_source,
15296 bgp_distance_source_cmd,
15297 "distance (1-255) A.B.C.D/M",
15298 "Define an administrative distance\n"
15299 "Administrative distance\n"
15300 "IP source prefix\n")
15301{
15302 int idx_number = 1;
15303 int idx_ipv4_prefixlen = 2;
15304 bgp_distance_set(vty, argv[idx_number]->arg,
15305 argv[idx_ipv4_prefixlen]->arg, NULL);
15306 return CMD_SUCCESS;
734b349e
MZ
15307}
15308
585f1adc
IR
15309DEFUN (no_bgp_distance_source,
15310 no_bgp_distance_source_cmd,
15311 "no distance (1-255) A.B.C.D/M",
15312 NO_STR
15313 "Define an administrative distance\n"
15314 "Administrative distance\n"
15315 "IP source prefix\n")
37a87b8f 15316{
585f1adc
IR
15317 int idx_number = 2;
15318 int idx_ipv4_prefixlen = 3;
15319 bgp_distance_unset(vty, argv[idx_number]->arg,
15320 argv[idx_ipv4_prefixlen]->arg, NULL);
15321 return CMD_SUCCESS;
37a87b8f
CS
15322}
15323
585f1adc
IR
15324DEFUN (bgp_distance_source_access_list,
15325 bgp_distance_source_access_list_cmd,
15326 "distance (1-255) A.B.C.D/M WORD",
15327 "Define an administrative distance\n"
15328 "Administrative distance\n"
15329 "IP source prefix\n"
15330 "Access list name\n")
37a87b8f 15331{
585f1adc
IR
15332 int idx_number = 1;
15333 int idx_ipv4_prefixlen = 2;
15334 int idx_word = 3;
15335 bgp_distance_set(vty, argv[idx_number]->arg,
15336 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15337 return CMD_SUCCESS;
15338}
718e3744 15339
585f1adc
IR
15340DEFUN (no_bgp_distance_source_access_list,
15341 no_bgp_distance_source_access_list_cmd,
15342 "no distance (1-255) A.B.C.D/M WORD",
15343 NO_STR
15344 "Define an administrative distance\n"
15345 "Administrative distance\n"
15346 "IP source prefix\n"
15347 "Access list name\n")
15348{
15349 int idx_number = 2;
15350 int idx_ipv4_prefixlen = 3;
15351 int idx_word = 4;
15352 bgp_distance_unset(vty, argv[idx_number]->arg,
15353 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15354 return CMD_SUCCESS;
15355}
37a87b8f 15356
585f1adc
IR
15357DEFUN (ipv6_bgp_distance_source,
15358 ipv6_bgp_distance_source_cmd,
15359 "distance (1-255) X:X::X:X/M",
15360 "Define an administrative distance\n"
15361 "Administrative distance\n"
15362 "IP source prefix\n")
15363{
15364 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15365 return CMD_SUCCESS;
15366}
7ebe9748 15367
585f1adc
IR
15368DEFUN (no_ipv6_bgp_distance_source,
15369 no_ipv6_bgp_distance_source_cmd,
15370 "no distance (1-255) X:X::X:X/M",
15371 NO_STR
15372 "Define an administrative distance\n"
15373 "Administrative distance\n"
15374 "IP source prefix\n")
15375{
15376 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15377 return CMD_SUCCESS;
15378}
37a87b8f 15379
585f1adc
IR
15380DEFUN (ipv6_bgp_distance_source_access_list,
15381 ipv6_bgp_distance_source_access_list_cmd,
15382 "distance (1-255) X:X::X:X/M WORD",
15383 "Define an administrative distance\n"
15384 "Administrative distance\n"
15385 "IP source prefix\n"
15386 "Access list name\n")
15387{
15388 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15389 return CMD_SUCCESS;
718e3744 15390}
15391
585f1adc
IR
15392DEFUN (no_ipv6_bgp_distance_source_access_list,
15393 no_ipv6_bgp_distance_source_access_list_cmd,
15394 "no distance (1-255) X:X::X:X/M WORD",
15395 NO_STR
15396 "Define an administrative distance\n"
15397 "Administrative distance\n"
15398 "IP source prefix\n"
15399 "Access list name\n")
718e3744 15400{
585f1adc
IR
15401 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15402 return CMD_SUCCESS;
15403}
37a87b8f 15404
585f1adc
IR
15405DEFUN (bgp_damp_set,
15406 bgp_damp_set_cmd,
a30fec23 15407 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15408 "BGP Specific commands\n"
15409 "Enable route-flap dampening\n"
15410 "Half-life time for the penalty\n"
15411 "Value to start reusing a route\n"
15412 "Value to start suppressing a route\n"
15413 "Maximum duration to suppress a stable route\n")
15414{
15415 VTY_DECLVAR_CONTEXT(bgp, bgp);
15416 int idx_half_life = 2;
15417 int idx_reuse = 3;
15418 int idx_suppress = 4;
15419 int idx_max_suppress = 5;
37a87b8f
CS
15420 int half = DEFAULT_HALF_LIFE * 60;
15421 int reuse = DEFAULT_REUSE;
15422 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15423 int max = 4 * half;
15424
15425 if (argc == 6) {
15426 half = atoi(argv[idx_half_life]->arg) * 60;
15427 reuse = atoi(argv[idx_reuse]->arg);
15428 suppress = atoi(argv[idx_suppress]->arg);
15429 max = atoi(argv[idx_max_suppress]->arg) * 60;
15430 } else if (argc == 3) {
15431 half = atoi(argv[idx_half_life]->arg) * 60;
15432 max = 4 * half;
15433 }
15434
15435 /*
15436 * These can't be 0 but our SA doesn't understand the
15437 * way our cli is constructed
15438 */
15439 assert(reuse);
15440 assert(half);
15441 if (suppress < reuse) {
15442 vty_out(vty,
15443 "Suppress value cannot be less than reuse value \n");
15444 return 0;
15445 }
15446
15447 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15448 reuse, suppress, max);
15449}
15450
15451DEFUN (bgp_damp_unset,
15452 bgp_damp_unset_cmd,
a30fec23 15453 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15454 NO_STR
15455 "BGP Specific commands\n"
15456 "Enable route-flap dampening\n"
15457 "Half-life time for the penalty\n"
15458 "Value to start reusing a route\n"
15459 "Value to start suppressing a route\n"
15460 "Maximum duration to suppress a stable route\n")
15461{
15462 VTY_DECLVAR_CONTEXT(bgp, bgp);
15463 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15464}
15465
718e3744 15466/* Display specified route of BGP table. */
d62a17ae 15467static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15468 const char *ip_str, afi_t afi, safi_t safi,
15469 struct prefix_rd *prd, int prefix_check)
15470{
15471 int ret;
15472 struct prefix match;
9bcb3eef
DS
15473 struct bgp_dest *dest;
15474 struct bgp_dest *rm;
40381db7
DS
15475 struct bgp_path_info *pi;
15476 struct bgp_path_info *pi_temp;
d62a17ae 15477 struct bgp *bgp;
15478 struct bgp_table *table;
15479
15480 /* BGP structure lookup. */
15481 if (view_name) {
15482 bgp = bgp_lookup_by_name(view_name);
15483 if (bgp == NULL) {
15484 vty_out(vty, "%% Can't find BGP instance %s\n",
15485 view_name);
15486 return CMD_WARNING;
15487 }
15488 } else {
15489 bgp = bgp_get_default();
15490 if (bgp == NULL) {
15491 vty_out(vty, "%% No BGP process is configured\n");
15492 return CMD_WARNING;
15493 }
718e3744 15494 }
718e3744 15495
d62a17ae 15496 /* Check IP address argument. */
15497 ret = str2prefix(ip_str, &match);
15498 if (!ret) {
15499 vty_out(vty, "%% address is malformed\n");
15500 return CMD_WARNING;
15501 }
718e3744 15502
d62a17ae 15503 match.family = afi2family(afi);
15504
15505 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15506 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15507 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15508 dest = bgp_route_next(dest)) {
15509 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15510
9bcb3eef 15511 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15512 continue;
9bcb3eef 15513 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15514 if (!table)
ea47320b 15515 continue;
4953391b
DA
15516 rm = bgp_node_match(table, &match);
15517 if (rm == NULL)
ea47320b 15518 continue;
d62a17ae 15519
9bcb3eef 15520 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15521
ea47320b 15522 if (!prefix_check
b54892e0 15523 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15524 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15525 while (pi) {
15526 if (pi->extra && pi->extra->damp_info) {
15527 pi_temp = pi->next;
ea47320b 15528 bgp_damp_info_free(
19971c9a 15529 pi->extra->damp_info,
5c8846f6 15530 1, afi, safi);
40381db7 15531 pi = pi_temp;
ea47320b 15532 } else
40381db7 15533 pi = pi->next;
d62a17ae 15534 }
ea47320b
DL
15535 }
15536
9bcb3eef 15537 bgp_dest_unlock_node(rm);
d62a17ae 15538 }
15539 } else {
4953391b
DA
15540 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15541 if (dest != NULL) {
9bcb3eef 15542 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15543
d62a17ae 15544 if (!prefix_check
9bcb3eef
DS
15545 || dest_p->prefixlen == match.prefixlen) {
15546 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15547 while (pi) {
15548 if (pi->extra && pi->extra->damp_info) {
15549 pi_temp = pi->next;
d62a17ae 15550 bgp_damp_info_free(
19971c9a 15551 pi->extra->damp_info,
5c8846f6 15552 1, afi, safi);
40381db7 15553 pi = pi_temp;
d62a17ae 15554 } else
40381db7 15555 pi = pi->next;
d62a17ae 15556 }
15557 }
15558
9bcb3eef 15559 bgp_dest_unlock_node(dest);
d62a17ae 15560 }
15561 }
718e3744 15562
d62a17ae 15563 return CMD_SUCCESS;
718e3744 15564}
15565
15566DEFUN (clear_ip_bgp_dampening,
15567 clear_ip_bgp_dampening_cmd,
15568 "clear ip bgp dampening",
15569 CLEAR_STR
15570 IP_STR
15571 BGP_STR
15572 "Clear route flap dampening information\n")
15573{
b4f7f45b 15574 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15575 return CMD_SUCCESS;
718e3744 15576}
15577
15578DEFUN (clear_ip_bgp_dampening_prefix,
15579 clear_ip_bgp_dampening_prefix_cmd,
15580 "clear ip bgp dampening A.B.C.D/M",
15581 CLEAR_STR
15582 IP_STR
15583 BGP_STR
15584 "Clear route flap dampening information\n"
0c7b1b01 15585 "IPv4 prefix\n")
718e3744 15586{
d62a17ae 15587 int idx_ipv4_prefixlen = 4;
15588 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15589 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15590}
15591
15592DEFUN (clear_ip_bgp_dampening_address,
15593 clear_ip_bgp_dampening_address_cmd,
15594 "clear ip bgp dampening A.B.C.D",
15595 CLEAR_STR
15596 IP_STR
15597 BGP_STR
15598 "Clear route flap dampening information\n"
15599 "Network to clear damping information\n")
15600{
d62a17ae 15601 int idx_ipv4 = 4;
15602 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15603 SAFI_UNICAST, NULL, 0);
718e3744 15604}
15605
15606DEFUN (clear_ip_bgp_dampening_address_mask,
15607 clear_ip_bgp_dampening_address_mask_cmd,
15608 "clear ip bgp dampening A.B.C.D A.B.C.D",
15609 CLEAR_STR
15610 IP_STR
15611 BGP_STR
15612 "Clear route flap dampening information\n"
15613 "Network to clear damping information\n"
15614 "Network mask\n")
15615{
d62a17ae 15616 int idx_ipv4 = 4;
15617 int idx_ipv4_2 = 5;
15618 int ret;
15619 char prefix_str[BUFSIZ];
718e3744 15620
d62a17ae 15621 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15622 prefix_str, sizeof(prefix_str));
d62a17ae 15623 if (!ret) {
15624 vty_out(vty, "%% Inconsistent address and mask\n");
15625 return CMD_WARNING;
15626 }
718e3744 15627
d62a17ae 15628 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15629 NULL, 0);
718e3744 15630}
6b0655a2 15631
e3b78da8 15632static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15633{
15634 struct vty *vty = arg;
e3b78da8 15635 struct peer *peer = bucket->data;
825d9834 15636
47e12884 15637 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15638}
15639
2a0e69ae
DS
15640DEFUN (show_bgp_listeners,
15641 show_bgp_listeners_cmd,
15642 "show bgp listeners",
15643 SHOW_STR
15644 BGP_STR
15645 "Display Listen Sockets and who created them\n")
15646{
15647 bgp_dump_listener_info(vty);
15648
15649 return CMD_SUCCESS;
15650}
15651
825d9834
DS
15652DEFUN (show_bgp_peerhash,
15653 show_bgp_peerhash_cmd,
15654 "show bgp peerhash",
15655 SHOW_STR
15656 BGP_STR
15657 "Display information about the BGP peerhash\n")
15658{
15659 struct list *instances = bm->bgp;
15660 struct listnode *node;
15661 struct bgp *bgp;
15662
15663 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15664 vty_out(vty, "BGP: %s\n", bgp->name);
15665 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15666 vty);
15667 }
15668
15669 return CMD_SUCCESS;
15670}
15671
587ff0fd 15672/* also used for encap safi */
2b791107
DL
15673static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15674 afi_t afi, safi_t safi)
d62a17ae 15675{
9bcb3eef
DS
15676 struct bgp_dest *pdest;
15677 struct bgp_dest *dest;
d62a17ae 15678 struct bgp_table *table;
b54892e0 15679 const struct prefix *p;
d62a17ae 15680 struct bgp_static *bgp_static;
15681 mpls_label_t label;
d62a17ae 15682
15683 /* Network configuration. */
9bcb3eef
DS
15684 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15685 pdest = bgp_route_next(pdest)) {
15686 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15687 if (!table)
ea47320b 15688 continue;
d62a17ae 15689
9bcb3eef
DS
15690 for (dest = bgp_table_top(table); dest;
15691 dest = bgp_route_next(dest)) {
15692 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15693 if (bgp_static == NULL)
ea47320b 15694 continue;
d62a17ae 15695
9bcb3eef 15696 p = bgp_dest_get_prefix(dest);
d62a17ae 15697
ea47320b 15698 /* "network" configuration display. */
ea47320b
DL
15699 label = decode_label(&bgp_static->label);
15700
c1aa9e7f
PG
15701 vty_out(vty, " network %pFX rd %s", p,
15702 bgp_static->prd_pretty);
ea47320b
DL
15703 if (safi == SAFI_MPLS_VPN)
15704 vty_out(vty, " label %u", label);
15705
15706 if (bgp_static->rmap.name)
15707 vty_out(vty, " route-map %s",
15708 bgp_static->rmap.name);
e2a86ad9
DS
15709
15710 if (bgp_static->backdoor)
15711 vty_out(vty, " backdoor");
15712
ea47320b
DL
15713 vty_out(vty, "\n");
15714 }
15715 }
d62a17ae 15716}
15717
2b791107
DL
15718static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15719 afi_t afi, safi_t safi)
d62a17ae 15720{
9bcb3eef
DS
15721 struct bgp_dest *pdest;
15722 struct bgp_dest *dest;
d62a17ae 15723 struct bgp_table *table;
b54892e0 15724 const struct prefix *p;
d62a17ae 15725 struct bgp_static *bgp_static;
ff44f570 15726 char buf[PREFIX_STRLEN * 2];
d62a17ae 15727 char buf2[SU_ADDRSTRLEN];
5f933e1e 15728 char esi_buf[ESI_STR_LEN];
d62a17ae 15729
15730 /* Network configuration. */
9bcb3eef
DS
15731 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15732 pdest = bgp_route_next(pdest)) {
15733 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15734 if (!table)
ea47320b 15735 continue;
d62a17ae 15736
9bcb3eef
DS
15737 for (dest = bgp_table_top(table); dest;
15738 dest = bgp_route_next(dest)) {
15739 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15740 if (bgp_static == NULL)
ea47320b 15741 continue;
d62a17ae 15742
ea47320b 15743 char *macrouter = NULL;
d62a17ae 15744
ea47320b
DL
15745 if (bgp_static->router_mac)
15746 macrouter = prefix_mac2str(
15747 bgp_static->router_mac, NULL, 0);
15748 if (bgp_static->eth_s_id)
0a50c248
AK
15749 esi_to_str(bgp_static->eth_s_id,
15750 esi_buf, sizeof(esi_buf));
9bcb3eef 15751 p = bgp_dest_get_prefix(dest);
d62a17ae 15752
ea47320b 15753 /* "network" configuration display. */
197cb530
PG
15754 if (p->u.prefix_evpn.route_type == 5) {
15755 char local_buf[PREFIX_STRLEN];
07380148 15756
3714a385 15757 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15758 struct prefix_evpn *)p)
15759 ? AF_INET
15760 : AF_INET6;
3714a385 15761 inet_ntop(family,
07380148
DA
15762 &p->u.prefix_evpn.prefix_addr.ip.ip
15763 .addr,
15764 local_buf, sizeof(local_buf));
772270f3
QY
15765 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15766 p->u.prefix_evpn.prefix_addr
15767 .ip_prefix_length);
197cb530
PG
15768 } else {
15769 prefix2str(p, buf, sizeof(buf));
15770 }
ea47320b 15771
a4d82a8a
PZ
15772 if (bgp_static->gatewayIp.family == AF_INET
15773 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15774 inet_ntop(bgp_static->gatewayIp.family,
15775 &bgp_static->gatewayIp.u.prefix, buf2,
15776 sizeof(buf2));
ea47320b 15777 vty_out(vty,
c1aa9e7f
PG
15778 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15779 buf, bgp_static->prd_pretty,
15780 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15781 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15782 macrouter);
15783
0a22ddfb 15784 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15785 }
15786 }
3da6fcd5
PG
15787}
15788
718e3744 15789/* Configuration of static route announcement and aggregate
15790 information. */
2b791107
DL
15791void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15792 safi_t safi)
d62a17ae 15793{
9bcb3eef 15794 struct bgp_dest *dest;
b54892e0 15795 const struct prefix *p;
d62a17ae 15796 struct bgp_static *bgp_static;
15797 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15798
2b791107
DL
15799 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15800 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15801 return;
15802 }
d62a17ae 15803
2b791107
DL
15804 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15805 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15806 return;
15807 }
d62a17ae 15808
15809 /* Network configuration. */
9bcb3eef
DS
15810 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15811 dest = bgp_route_next(dest)) {
15812 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15813 if (bgp_static == NULL)
ea47320b 15814 continue;
d62a17ae 15815
9bcb3eef 15816 p = bgp_dest_get_prefix(dest);
d62a17ae 15817
8228a9a7 15818 vty_out(vty, " network %pFX", p);
d62a17ae 15819
ea47320b
DL
15820 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15821 vty_out(vty, " label-index %u",
15822 bgp_static->label_index);
d62a17ae 15823
ea47320b
DL
15824 if (bgp_static->rmap.name)
15825 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15826
15827 if (bgp_static->backdoor)
15828 vty_out(vty, " backdoor");
718e3744 15829
ea47320b
DL
15830 vty_out(vty, "\n");
15831 }
15832
d62a17ae 15833 /* Aggregate-address configuration. */
9bcb3eef
DS
15834 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15835 dest = bgp_route_next(dest)) {
15836 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15837 if (bgp_aggregate == NULL)
ea47320b 15838 continue;
d62a17ae 15839
9bcb3eef 15840 p = bgp_dest_get_prefix(dest);
d62a17ae 15841
8228a9a7 15842 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15843
ea47320b
DL
15844 if (bgp_aggregate->as_set)
15845 vty_out(vty, " as-set");
d62a17ae 15846
ea47320b
DL
15847 if (bgp_aggregate->summary_only)
15848 vty_out(vty, " summary-only");
718e3744 15849
20894f50
DA
15850 if (bgp_aggregate->rmap.name)
15851 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15852
229757f1
DA
15853 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15854 vty_out(vty, " origin %s",
15855 bgp_origin2str(bgp_aggregate->origin));
15856
6aabb15d
RZ
15857 if (bgp_aggregate->match_med)
15858 vty_out(vty, " matching-MED-only");
15859
365ab2e7
RZ
15860 if (bgp_aggregate->suppress_map_name)
15861 vty_out(vty, " suppress-map %s",
15862 bgp_aggregate->suppress_map_name);
15863
ea47320b
DL
15864 vty_out(vty, "\n");
15865 }
d62a17ae 15866}
734b349e 15867
2b791107 15868void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15869 safi_t safi)
d62a17ae 15870{
9bcb3eef 15871 struct bgp_dest *dest;
d62a17ae 15872 struct bgp_distance *bdistance;
15873
15874 /* Distance configuration. */
15875 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15876 && bgp->distance_local[afi][safi]
15877 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15878 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15879 || bgp->distance_local[afi][safi]
15880 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15881 vty_out(vty, " distance bgp %d %d %d\n",
15882 bgp->distance_ebgp[afi][safi],
15883 bgp->distance_ibgp[afi][safi],
15884 bgp->distance_local[afi][safi]);
15885 }
734b349e 15886
9bcb3eef
DS
15887 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15888 dest = bgp_route_next(dest)) {
15889 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15890 if (bdistance != NULL)
56ca3b5b 15891 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15892 bdistance->distance, dest,
d62a17ae 15893 bdistance->access_list ? bdistance->access_list
15894 : "");
ca2e160d 15895 }
718e3744 15896}
15897
15898/* Allocate routing table structure and install commands. */
d62a17ae 15899void bgp_route_init(void)
15900{
15901 afi_t afi;
15902 safi_t safi;
15903
15904 /* Init BGP distance table. */
05c7a1cc 15905 FOREACH_AFI_SAFI (afi, safi)
960035b2 15906 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15907
15908 /* IPv4 BGP commands. */
15909 install_element(BGP_NODE, &bgp_table_map_cmd);
15910 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15911 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15912
554b3b10 15913 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15914
15915 /* IPv4 unicast configuration. */
15916 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15917 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15918 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15919
554b3b10 15920 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15921
15922 /* IPv4 multicast configuration. */
15923 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15924 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15925 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15926 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15927
15928 /* IPv4 labeled-unicast configuration. */
fb985e0c 15929 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15930 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15931
d62a17ae 15932 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15933 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15934 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15935 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15936 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15937 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15938 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15939 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15940
15941 install_element(VIEW_NODE,
15942 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15943 install_element(VIEW_NODE,
15944 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15945 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15946 install_element(VIEW_NODE,
15947 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15948#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15949 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15950#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15951 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15952 install_element(VIEW_NODE,
44c69747 15953 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15954
d62a17ae 15955 /* BGP dampening clear commands */
15956 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15957 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15958
d62a17ae 15959 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15960 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15961
15962 /* prefix count */
15963 install_element(ENABLE_NODE,
15964 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15965#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15966 install_element(ENABLE_NODE,
15967 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15968#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15969
d62a17ae 15970 /* New config IPv6 BGP commands. */
15971 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15972 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15973 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15974
554b3b10 15975 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15976
15977 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15978
fb985e0c
DA
15979 /* IPv6 labeled unicast address family. */
15980 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15981 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15982
d62a17ae 15983 install_element(BGP_NODE, &bgp_distance_cmd);
15984 install_element(BGP_NODE, &no_bgp_distance_cmd);
15985 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15986 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15987 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15988 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15989 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15990 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15991 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15992 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15993 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15994 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15995 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15996 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15997 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15998 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15999 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
16000 install_element(BGP_IPV4M_NODE,
16001 &no_bgp_distance_source_access_list_cmd);
d62a17ae 16002 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
16003 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16004 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
16005 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
16006 install_element(BGP_IPV6_NODE,
16007 &ipv6_bgp_distance_source_access_list_cmd);
16008 install_element(BGP_IPV6_NODE,
16009 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16010 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
16011 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16012 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
16013 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
16014 install_element(BGP_IPV6M_NODE,
16015 &ipv6_bgp_distance_source_access_list_cmd);
16016 install_element(BGP_IPV6M_NODE,
16017 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16018
ef5f4b23 16019 /* BGP dampening */
585f1adc
IR
16020 install_element(BGP_NODE, &bgp_damp_set_cmd);
16021 install_element(BGP_NODE, &bgp_damp_unset_cmd);
16022 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
16023 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
16024 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16025 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16026 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16027 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16028 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16029 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16030 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16031 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16032 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16033 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 16034
16035 /* Large Communities */
16036 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16037 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
16038
16039 /* show bgp ipv4 flowspec detailed */
16040 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
16041
2a0e69ae 16042 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16043 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16044}
16045
16046void bgp_route_finish(void)
16047{
16048 afi_t afi;
16049 safi_t safi;
16050
05c7a1cc
QY
16051 FOREACH_AFI_SAFI (afi, safi) {
16052 bgp_table_unlock(bgp_distance_table[afi][safi]);
16053 bgp_distance_table[afi][safi] = NULL;
16054 }
228da428 16055}