]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #13564 from chiragshah6/fdev1
[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;
e0b1c8cc 1469 char pfx_buf[PREFIX2STR_BUFFER] = {};
d071f237
AK
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;
e0b1c8cc 2656 char pfx_buf[PREFIX2STR_BUFFER] = {};
d62a17ae 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;
cf1c7e30
PG
3090 /* Disable PHP : explicit-null */
3091 if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
3092 afi == AFI_IP)
3093 *label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
3094 else if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL) &&
3095 afi == AFI_IP6)
3096 *label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
bb2ca692 3097 else
7ee70320
PG
3098 /* Enforced PHP popping: implicit-null */
3099 *label = MPLS_LABEL_IMPLICIT_NULL;
3100
3101 return true;
bb2ca692
MS
3102}
3103
3103e8d2
DS
3104/*
3105 * old_select = The old best path
3106 * new_select = the new best path
3107 *
3108 * if (!old_select && new_select)
3109 * We are sending new information on.
3110 *
3111 * if (old_select && new_select) {
3112 * if (new_select != old_select)
3113 * We have a new best path send a change
3114 * else
3115 * We've received a update with new attributes that needs
3116 * to be passed on.
3117 * }
3118 *
3119 * if (old_select && !new_select)
3120 * We have no eligible route that we can announce or the rn
3121 * is being removed.
3122 */
9bcb3eef 3123static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3124 afi_t afi, safi_t safi)
d62a17ae 3125{
4b7e6066
DS
3126 struct bgp_path_info *new_select;
3127 struct bgp_path_info *old_select;
3128 struct bgp_path_info_pair old_and_new;
ddb5b488 3129 int debug = 0;
7ee70320 3130 mpls_label_t mpls_label_null;
d62a17ae 3131
892fedb6 3132 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3133 if (dest)
3134 debug = bgp_debug_bestpath(dest);
b54892e0 3135 if (debug)
f4c713ae 3136 zlog_debug(
7fd8ca9a
DS
3137 "%s: bgp delete in progress, ignoring event, p=%pBD(%s)",
3138 __func__, dest, bgp->name_pretty);
f4c713ae
LB
3139 return;
3140 }
d62a17ae 3141 /* Is it end of initial update? (after startup) */
9bcb3eef 3142 if (!dest) {
e36f61b5
DS
3143 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3144 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3145
3146 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3147 FOREACH_AFI_SAFI (afi, safi) {
3148 if (bgp_fibupd_safi(safi))
3149 bgp_zebra_announce_table(bgp, afi, safi);
3150 }
d62a17ae 3151 bgp->main_peers_update_hold = 0;
3152
3153 bgp_start_routeadv(bgp);
aac24838 3154 return;
d62a17ae 3155 }
cb1faec9 3156
9bcb3eef 3157 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3158
9bcb3eef 3159 debug = bgp_debug_bestpath(dest);
b54892e0 3160 if (debug)
7fd8ca9a 3161 zlog_debug("%s: p=%pBD(%s) afi=%s, safi=%s start", __func__,
4378495a
DS
3162 dest, bgp->name_pretty, afi2str(afi),
3163 safi2str(safi));
ddb5b488 3164
f009ff26 3165 /* The best path calculation for the route is deferred if
3166 * BGP_NODE_SELECT_DEFER is set
3167 */
9bcb3eef 3168 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3169 if (BGP_DEBUG(update, UPDATE_OUT))
7fd8ca9a
DS
3170 zlog_debug("SELECT_DEFER flag set for route %p(%s)",
3171 dest, bgp->name_pretty);
f009ff26 3172 return;
3173 }
3174
d62a17ae 3175 /* Best path selection. */
9bcb3eef 3176 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3177 afi, safi);
3178 old_select = old_and_new.old;
3179 new_select = old_and_new.new;
3180
3181 /* Do we need to allocate or free labels?
3182 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3183 * necessary to do this upon changes to best path. Exceptions:
3184 * - label index has changed -> recalculate resulting label
7ee70320 3185 * - path_info sub_type changed -> switch to/from null label value
57592a53 3186 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3187 */
318cac96 3188 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3189 if (new_select) {
3190 if (!old_select
3191 || bgp_label_index_differs(new_select, old_select)
57592a53 3192 || new_select->sub_type != old_select->sub_type
9bcb3eef 3193 || !bgp_is_valid_label(&dest->local_label)) {
7ee70320
PG
3194 /* control label imposition for local routes,
3195 * aggregate and redistributed routes
57592a53 3196 */
7ee70320
PG
3197 mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
3198 if (bgp_lu_need_null_label(bgp, new_select, afi,
3199 &mpls_label_null)) {
d62a17ae 3200 if (CHECK_FLAG(
9bcb3eef 3201 dest->flags,
992dd67e
PR
3202 BGP_NODE_REGISTERED_FOR_LABEL)
3203 || CHECK_FLAG(
3204 dest->flags,
3205 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3206 bgp_unregister_for_label(dest);
67f67ba4 3207 dest->local_label = mpls_lse_encode(
7ee70320 3208 mpls_label_null, 0, 0, 1);
9bcb3eef 3209 bgp_set_valid_label(&dest->local_label);
d62a17ae 3210 } else
9bcb3eef
DS
3211 bgp_register_for_label(dest,
3212 new_select);
d62a17ae 3213 }
9bcb3eef 3214 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3215 BGP_NODE_REGISTERED_FOR_LABEL)
3216 || CHECK_FLAG(dest->flags,
3217 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3218 bgp_unregister_for_label(dest);
318cac96 3219 }
992dd67e
PR
3220 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3221 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3222 bgp_unregister_for_label(dest);
d62a17ae 3223 }
cd1964ff 3224
b54892e0 3225 if (debug)
ddb5b488 3226 zlog_debug(
4378495a
DS
3227 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3228 __func__, dest, bgp->name_pretty, afi2str(afi),
3229 safi2str(safi), old_select, new_select);
ddb5b488 3230
d62a17ae 3231 /* If best route remains the same and this is not due to user-initiated
3232 * clear, see exactly what needs to be done.
3233 */
d62a17ae 3234 if (old_select && old_select == new_select
9bcb3eef 3235 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3236 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3237 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3238 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3239#ifdef ENABLE_BGP_VNC
d62a17ae 3240 vnc_import_bgp_add_route(bgp, p, old_select);
3241 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3242#endif
bb744275 3243 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3244 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3245
3246 if (new_select->type == ZEBRA_ROUTE_BGP
3247 && (new_select->sub_type == BGP_ROUTE_NORMAL
3248 || new_select->sub_type
3249 == BGP_ROUTE_IMPORTED))
3250
9bcb3eef 3251 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3252 bgp, afi, safi);
3253 }
d62a17ae 3254 }
d62a17ae 3255
3256 /* If there is a change of interest to peers, reannounce the
3257 * route. */
1defdda8 3258 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3259 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3260 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3261 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3262
3263 /* unicast routes must also be annouced to
3264 * labeled-unicast update-groups */
3265 if (safi == SAFI_UNICAST)
3266 group_announce_route(bgp, afi,
9bcb3eef 3267 SAFI_LABELED_UNICAST, dest,
d62a17ae 3268 new_select);
3269
1defdda8 3270 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3271 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3272 }
fee0f4c6 3273
3b0c17e1 3274 /* advertise/withdraw type-5 routes */
3275 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3276 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3277 bgp_process_evpn_route_injection(
9bcb3eef 3278 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3279
b1875e65 3280 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3281 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3282 bgp_zebra_clear_route_change_flags(dest);
3283 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3284 return;
d62a17ae 3285 }
8ad7271d 3286
d62a17ae 3287 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3288 */
9bcb3eef 3289 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3290
3291 /* bestpath has changed; bump version */
3292 if (old_select || new_select) {
9bcb3eef 3293 bgp_bump_version(dest);
d62a17ae 3294
3295 if (!bgp->t_rmap_def_originate_eval) {
3296 bgp_lock(bgp);
907a2395 3297 event_add_timer(
d62a17ae 3298 bm->master,
3299 update_group_refresh_default_originate_route_map,
3300 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3301 &bgp->t_rmap_def_originate_eval);
3302 }
3303 }
3f9c7369 3304
d62a17ae 3305 if (old_select)
9bcb3eef 3306 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3307 if (new_select) {
ddb5b488
PZ
3308 if (debug)
3309 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3310 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3311 bgp_path_info_unset_flag(dest, new_select,
3312 BGP_PATH_ATTR_CHANGED);
1defdda8 3313 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3314 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3315 }
338b3424 3316
49e5a4a0 3317#ifdef ENABLE_BGP_VNC
d62a17ae 3318 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3319 if (old_select != new_select) {
3320 if (old_select) {
3321 vnc_import_bgp_exterior_del_route(bgp, p,
3322 old_select);
3323 vnc_import_bgp_del_route(bgp, p, old_select);
3324 }
3325 if (new_select) {
3326 vnc_import_bgp_exterior_add_route(bgp, p,
3327 new_select);
3328 vnc_import_bgp_add_route(bgp, p, new_select);
3329 }
3330 }
3331 }
65efcfce
LB
3332#endif
3333
9bcb3eef 3334 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3335
3336 /* unicast routes must also be annouced to labeled-unicast update-groups
3337 */
3338 if (safi == SAFI_UNICAST)
9bcb3eef 3339 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3340 new_select);
3341
3342 /* FIB update. */
3343 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3344 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3345
d62a17ae 3346 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3347 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3348 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3349 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3350
3351 /* if this is an evpn imported type-5 prefix,
3352 * we need to withdraw the route first to clear
3353 * the nh neigh and the RMAC entry.
3354 */
3355 if (old_select &&
3356 is_route_parent_evpn(old_select))
3357 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3358
9bcb3eef 3359 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3360 } else {
d62a17ae 3361 /* Withdraw the route from the kernel. */
3362 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3363 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3364 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3365 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3366
568e10ca 3367 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3368 }
718e3744 3369 }
3064bf43 3370
9bcb3eef 3371 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3372 old_select);
5424b7ba 3373
d62a17ae 3374 /* Clear any route change flags. */
9bcb3eef 3375 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3376
18ee8310 3377 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3378 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3379 bgp_path_info_reap(dest, old_select);
d62a17ae 3380
9bcb3eef 3381 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3382 return;
718e3744 3383}
3384
f009ff26 3385/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3386void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3387{
9bcb3eef 3388 struct bgp_dest *dest;
f009ff26 3389 int cnt = 0;
3390 struct afi_safi_info *thread_info;
f009ff26 3391
56c226e7 3392 if (bgp->gr_info[afi][safi].t_route_select) {
e6685141 3393 struct event *t = bgp->gr_info[afi][safi].t_route_select;
56c226e7 3394
e16d030c 3395 thread_info = EVENT_ARG(t);
56c226e7 3396 XFREE(MTYPE_TMP, thread_info);
e16d030c 3397 EVENT_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3398 }
f009ff26 3399
3400 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3401 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3402 get_afi_safi_str(afi, safi, false),
26742171 3403 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3404 }
3405
3406 /* Process the route list */
6338d242 3407 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3408 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3409 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3410 dest = bgp_route_next(dest)) {
3411 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3412 continue;
3413
3414 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3415 bgp->gr_info[afi][safi].gr_deferred--;
3416 bgp_process_main_one(bgp, dest, afi, safi);
3417 cnt++;
067ea165
CB
3418 }
3419 /* If iteration stopped before the entire table was traversed then the
3420 * node needs to be unlocked.
3421 */
3422 if (dest) {
3423 bgp_dest_unlock_node(dest);
3424 dest = NULL;
f009ff26 3425 }
3426
9e3b51a7 3427 /* Send EOR message when all routes are processed */
6338d242 3428 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3429 bgp_send_delayed_eor(bgp);
8c48b3b6 3430 /* Send route processing complete message to RIB */
115ccb9a 3431 bgp_zebra_update(bgp, afi, safi,
36235319 3432 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3433 return;
9e3b51a7 3434 }
f009ff26 3435
3436 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3437
3438 thread_info->afi = afi;
3439 thread_info->safi = safi;
3440 thread_info->bgp = bgp;
3441
3442 /* If there are more routes to be processed, start the
3443 * selection timer
3444 */
907a2395 3445 event_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
f009ff26 3446 BGP_ROUTE_SELECT_DELAY,
3447 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3448}
3449
aac24838 3450static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3451{
aac24838
JB
3452 struct bgp_process_queue *pqnode = data;
3453 struct bgp *bgp = pqnode->bgp;
d62a17ae 3454 struct bgp_table *table;
9bcb3eef 3455 struct bgp_dest *dest;
aac24838
JB
3456
3457 /* eoiu marker */
3458 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3459 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3460 /* should always have dedicated wq call */
3461 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3462 return WQ_SUCCESS;
3463 }
3464
ac021f40 3465 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3466 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3467 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3468 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3469 table = bgp_dest_table(dest);
3470 /* note, new DESTs may be added as part of processing */
3471 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3472
9bcb3eef 3473 bgp_dest_unlock_node(dest);
d62a17ae 3474 bgp_table_unlock(table);
3475 }
aac24838
JB
3476
3477 return WQ_SUCCESS;
3478}
3479
3480static void bgp_processq_del(struct work_queue *wq, void *data)
3481{
3482 struct bgp_process_queue *pqnode = data;
3483
3484 bgp_unlock(pqnode->bgp);
3485
3486 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3487}
3488
b6c386bb 3489void bgp_process_queue_init(struct bgp *bgp)
200df115 3490{
b6c386bb
DS
3491 if (!bgp->process_queue) {
3492 char name[BUFSIZ];
3493
3494 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3495 bgp->process_queue = work_queue_new(bm->master, name);
3496 }
3497
3498 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3499 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3500 bgp->process_queue->spec.max_retries = 0;
3501 bgp->process_queue->spec.hold = 50;
d62a17ae 3502 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3503 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3504}
3505
cfe8d15a 3506static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3507{
3508 struct bgp_process_queue *pqnode;
3509
a4d82a8a
PZ
3510 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3511 sizeof(struct bgp_process_queue));
aac24838
JB
3512
3513 /* unlocked in bgp_processq_del */
3514 pqnode->bgp = bgp_lock(bgp);
3515 STAILQ_INIT(&pqnode->pqueue);
3516
aac24838
JB
3517 return pqnode;
3518}
3519
9bcb3eef 3520void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3521{
aac24838 3522#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3523 struct work_queue *wq = bgp->process_queue;
d62a17ae 3524 struct bgp_process_queue *pqnode;
cfe8d15a 3525 int pqnode_reuse = 0;
495f0b13 3526
d62a17ae 3527 /* already scheduled for processing? */
9bcb3eef 3528 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3529 return;
2e02b9b2 3530
f009ff26 3531 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3532 * the workqueue
3533 */
9bcb3eef 3534 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3535 if (BGP_DEBUG(update, UPDATE_OUT))
3536 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3537 dest);
f009ff26 3538 return;
3539 }
3540
46aeabed
LS
3541 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3542 if (BGP_DEBUG(update, UPDATE_OUT))
3543 zlog_debug(
3544 "Soft reconfigure table in progress for route %p",
3545 dest);
3546 return;
3547 }
3548
aac24838 3549 if (wq == NULL)
d62a17ae 3550 return;
3551
aac24838 3552 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3553 limit only if is from the same BGP view and it's not an EOIU marker
3554 */
aac24838
JB
3555 if (work_queue_item_count(wq)) {
3556 struct work_queue_item *item = work_queue_last_item(wq);
3557 pqnode = item->data;
228da428 3558
a4d82a8a
PZ
3559 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3560 || pqnode->bgp != bgp
3561 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3562 pqnode = bgp_processq_alloc(bgp);
3563 else
3564 pqnode_reuse = 1;
aac24838 3565 } else
cfe8d15a 3566 pqnode = bgp_processq_alloc(bgp);
aac24838 3567 /* all unlocked in bgp_process_wq */
9bcb3eef 3568 bgp_table_lock(bgp_dest_table(dest));
aac24838 3569
9bcb3eef
DS
3570 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3571 bgp_dest_lock_node(dest);
aac24838 3572
60466a63 3573 /* can't be enqueued twice */
9bcb3eef
DS
3574 assert(STAILQ_NEXT(dest, pq) == NULL);
3575 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3576 pqnode->queued++;
3577
cfe8d15a
LB
3578 if (!pqnode_reuse)
3579 work_queue_add(wq, pqnode);
3580
d62a17ae 3581 return;
fee0f4c6 3582}
0a486e5f 3583
d62a17ae 3584void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3585{
d62a17ae 3586 struct bgp_process_queue *pqnode;
cb1faec9 3587
b6c386bb 3588 if (bgp->process_queue == NULL)
d62a17ae 3589 return;
2e02b9b2 3590
cfe8d15a 3591 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3592
aac24838 3593 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3594 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3595}
3596
e6685141 3597static void bgp_maximum_prefix_restart_timer(struct event *thread)
0a486e5f 3598{
d62a17ae 3599 struct peer *peer;
0a486e5f 3600
e16d030c 3601 peer = EVENT_ARG(thread);
d62a17ae 3602 peer->t_pmax_restart = NULL;
0a486e5f 3603
d62a17ae 3604 if (bgp_debug_neighbor_events(peer))
3605 zlog_debug(
3606 "%s Maximum-prefix restart timer expired, restore peering",
3607 peer->host);
0a486e5f 3608
a9bafa95 3609 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3610 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3611}
3612
9cbd06e0
DA
3613static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3614 safi_t safi)
3615{
3616 uint32_t count = 0;
f41b0459 3617 bool filtered = false;
9cbd06e0
DA
3618 struct bgp_dest *dest;
3619 struct bgp_adj_in *ain;
40bb2ccf 3620 struct attr attr = {};
9cbd06e0
DA
3621 struct bgp_table *table = peer->bgp->rib[afi][safi];
3622
3623 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3624 for (ain = dest->adj_in; ain; ain = ain->next) {
3625 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3626
3627 attr = *ain->attr;
9cbd06e0
DA
3628
3629 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3630 == FILTER_DENY)
f41b0459
DA
3631 filtered = true;
3632
3633 if (bgp_input_modifier(
3634 peer, rn_p, &attr, afi, safi,
3635 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3636 NULL, 0, NULL)
3637 == RMAP_DENY)
3638 filtered = true;
3639
3640 if (filtered)
9cbd06e0 3641 count++;
f41b0459 3642
d498917e 3643 bgp_attr_flush(&attr);
9cbd06e0
DA
3644 }
3645 }
3646
3647 return count;
3648}
3649
3dc339cd
DA
3650bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3651 int always)
718e3744 3652{
d62a17ae 3653 iana_afi_t pkt_afi;
5c525538 3654 iana_safi_t pkt_safi;
9cbd06e0
DA
3655 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3656 PEER_FLAG_MAX_PREFIX_FORCE))
3657 ? bgp_filtered_routes_count(peer, afi, safi)
3658 + peer->pcount[afi][safi]
3659 : peer->pcount[afi][safi];
9cabb64b 3660
d62a17ae 3661 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3662 return false;
e0701b79 3663
9cbd06e0 3664 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3665 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3666 PEER_STATUS_PREFIX_LIMIT)
3667 && !always)
3dc339cd 3668 return false;
e0701b79 3669
d62a17ae 3670 zlog_info(
f70c91dc
DA
3671 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3672 get_afi_safi_str(afi, safi, false), peer, pcount,
3673 peer->pmax[afi][safi]);
d62a17ae 3674 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3675
3676 if (CHECK_FLAG(peer->af_flags[afi][safi],
3677 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3678 return false;
d62a17ae 3679
3680 /* Convert AFI, SAFI to values for packet. */
3681 pkt_afi = afi_int2iana(afi);
3682 pkt_safi = safi_int2iana(safi);
3683 {
d7c0a89a 3684 uint8_t ndata[7];
d62a17ae 3685
3686 ndata[0] = (pkt_afi >> 8);
3687 ndata[1] = pkt_afi;
3688 ndata[2] = pkt_safi;
3689 ndata[3] = (peer->pmax[afi][safi] >> 24);
3690 ndata[4] = (peer->pmax[afi][safi] >> 16);
3691 ndata[5] = (peer->pmax[afi][safi] >> 8);
3692 ndata[6] = (peer->pmax[afi][safi]);
3693
3694 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3695 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3696 BGP_NOTIFY_CEASE_MAX_PREFIX,
3697 ndata, 7);
3698 }
3699
3700 /* Dynamic peers will just close their connection. */
3701 if (peer_dynamic_neighbor(peer))
3dc339cd 3702 return true;
d62a17ae 3703
3704 /* restart timer start */
3705 if (peer->pmax_restart[afi][safi]) {
3706 peer->v_pmax_restart =
3707 peer->pmax_restart[afi][safi] * 60;
3708
3709 if (bgp_debug_neighbor_events(peer))
3710 zlog_debug(
f70c91dc
DA
3711 "%pBP Maximum-prefix restart timer started for %d secs",
3712 peer, peer->v_pmax_restart);
d62a17ae 3713
3714 BGP_TIMER_ON(peer->t_pmax_restart,
3715 bgp_maximum_prefix_restart_timer,
3716 peer->v_pmax_restart);
3717 }
3718
3dc339cd 3719 return true;
d62a17ae 3720 } else
3721 UNSET_FLAG(peer->af_sflags[afi][safi],
3722 PEER_STATUS_PREFIX_LIMIT);
3723
b1823b69
DS
3724 if (pcount
3725 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3726 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3727 PEER_STATUS_PREFIX_THRESHOLD)
3728 && !always)
3dc339cd 3729 return false;
d62a17ae 3730
3731 zlog_info(
f70c91dc
DA
3732 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3733 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3734 peer->pmax[afi][safi]);
d62a17ae 3735 SET_FLAG(peer->af_sflags[afi][safi],
3736 PEER_STATUS_PREFIX_THRESHOLD);
3737 } else
3738 UNSET_FLAG(peer->af_sflags[afi][safi],
3739 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3740 return false;
718e3744 3741}
3742
b40d939b 3743/* Unconditionally remove the route from the RIB, without taking
3744 * damping into consideration (eg, because the session went down)
3745 */
9bcb3eef 3746void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3747 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3748{
f009ff26 3749
3750 struct bgp *bgp = NULL;
3751 bool delete_route = false;
3752
9bcb3eef
DS
3753 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3754 safi);
d62a17ae 3755
f009ff26 3756 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3757 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3758
f009ff26 3759 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3760 * flag
3761 */
3762 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3763 delete_route = true;
9bcb3eef 3764 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3765 delete_route = true;
f009ff26 3766 if (delete_route) {
9bcb3eef
DS
3767 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3768 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3769 bgp = pi->peer->bgp;
26742171 3770 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3771 }
3772 }
3773 }
4a11bf2c 3774
9bcb3eef
DS
3775 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3776 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3777}
3778
9bcb3eef 3779static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3780 struct peer *peer, afi_t afi, safi_t safi,
3781 struct prefix_rd *prd)
3782{
9bcb3eef 3783 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3784
d62a17ae 3785 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3786 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3787 */
b4f7f45b
IR
3788 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3789 && peer->sort == BGP_PEER_EBGP)
3790 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3791 == BGP_DAMP_SUPPRESSED) {
3792 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3793 safi);
3794 return;
d62a17ae 3795 }
3796
49e5a4a0 3797#ifdef ENABLE_BGP_VNC
d62a17ae 3798 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3799 struct bgp_dest *pdest = NULL;
d62a17ae 3800 struct bgp_table *table = NULL;
3801
9bcb3eef
DS
3802 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3803 (struct prefix *)prd);
3804 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3805 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3806
3807 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3808 peer->bgp, prd, table, p, pi);
d62a17ae 3809 }
9bcb3eef 3810 bgp_dest_unlock_node(pdest);
d62a17ae 3811 }
3812 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3813 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3814
b54892e0
DS
3815 vnc_import_bgp_del_route(peer->bgp, p, pi);
3816 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3817 }
65efcfce 3818 }
d62a17ae 3819#endif
128ea8ab 3820
d62a17ae 3821 /* If this is an EVPN route, process for un-import. */
3822 if (safi == SAFI_EVPN)
b54892e0 3823 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3824
9bcb3eef 3825 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3826}
3827
4b7e6066
DS
3828struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3829 struct peer *peer, struct attr *attr,
9bcb3eef 3830 struct bgp_dest *dest)
fb018d25 3831{
4b7e6066 3832 struct bgp_path_info *new;
fb018d25 3833
d62a17ae 3834 /* Make new BGP info. */
4b7e6066 3835 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3836 new->type = type;
3837 new->instance = instance;
3838 new->sub_type = sub_type;
3839 new->peer = peer;
3840 new->attr = attr;
083ec940 3841 new->uptime = monotime(NULL);
9bcb3eef 3842 new->net = dest;
d62a17ae 3843 return new;
fb018d25
DS
3844}
3845
c265ee22 3846/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3847bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3848 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3849 struct bgp_dest *dest)
d62a17ae 3850{
2dbe3fa9 3851 bool ret = false;
b099a5c8
DA
3852 bool is_bgp_static_route =
3853 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3854 : false;
d62a17ae 3855
6cddc4c8
DA
3856 /* If `bgp allow-martian-nexthop` is turned on, return next-hop
3857 * as good.
3858 */
3859 if (bgp->allow_martian)
3860 return false;
3861
e8442016
DS
3862 /*
3863 * Only validated for unicast and multicast currently.
3864 * Also valid for EVPN where the nexthop is an IP address.
3865 * If we are a bgp static route being checked then there is
3866 * no need to check to see if the nexthop is martian as
3867 * that it should be ok.
3868 */
3869 if (is_bgp_static_route ||
3870 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3871 return false;
d62a17ae 3872
3873 /* If NEXT_HOP is present, validate it. */
3874 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3875 if (attr->nexthop.s_addr == INADDR_ANY ||
3876 !ipv4_unicast_valid(&attr->nexthop) ||
3877 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3878 return true;
d62a17ae 3879 }
c265ee22 3880
d62a17ae 3881 /* If MP_NEXTHOP is present, validate it. */
3882 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3883 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3884 * it is not an IPv6 link-local address.
0355b41d
DA
3885 *
3886 * If we receive an UPDATE with nexthop length set to 32 bytes
3887 * we shouldn't discard an UPDATE if it's set to (::).
3888 * The link-local (2st) is validated along the code path later.
d62a17ae 3889 */
3890 if (attr->mp_nexthop_len) {
3891 switch (attr->mp_nexthop_len) {
3892 case BGP_ATTR_NHLEN_IPV4:
3893 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3894 ret = (attr->mp_nexthop_global_in.s_addr ==
3895 INADDR_ANY ||
3896 !ipv4_unicast_valid(
3897 &attr->mp_nexthop_global_in) ||
3898 bgp_nexthop_self(bgp, afi, type, stype, attr,
3899 dest));
d62a17ae 3900 break;
3901
3902 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3903 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3904 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3905 &attr->mp_nexthop_global)
d62a17ae 3906 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3907 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3908 &attr->mp_nexthop_global)
3909 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3910 dest));
d62a17ae 3911 break;
0355b41d
DA
3912 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3913 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3914 || IN6_IS_ADDR_MULTICAST(
3915 &attr->mp_nexthop_global)
3916 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3917 dest));
0355b41d 3918 break;
d62a17ae 3919
3920 default:
3dc339cd 3921 ret = true;
d62a17ae 3922 break;
3923 }
3924 }
c265ee22 3925
d62a17ae 3926 return ret;
3927}
3928
aade37d7 3929static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3930{
3931 struct community *old;
3932 struct community *new;
3933 struct community *merge;
aade37d7 3934 struct community *no_export;
2721dd61 3935
9a706b42 3936 old = bgp_attr_get_community(attr);
aade37d7 3937 no_export = community_str2com("no-export");
2721dd61 3938
b4efa101
DA
3939 assert(no_export);
3940
2721dd61 3941 if (old) {
aade37d7 3942 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3943
3944 if (!old->refcnt)
3945 community_free(&old);
3946
3947 new = community_uniq_sort(merge);
3948 community_free(&merge);
3949 } else {
aade37d7 3950 new = community_dup(no_export);
2721dd61
DA
3951 }
3952
aade37d7 3953 community_free(&no_export);
2721dd61 3954
9a706b42 3955 bgp_attr_set_community(attr, new);
2721dd61
DA
3956}
3957
46dbf9d0
DA
3958static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3959 struct attr *attr, const struct prefix *prefix,
3960 int *sub_type)
3961{
3962 struct listnode *node, *nnode;
3963 struct bgp *bgp;
3964 bool accept_own_found = false;
3965
3966 if (safi != SAFI_MPLS_VPN)
3967 return false;
3968
3969 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3970 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3971 return false;
3972
3973 /* The route in question carries the ACCEPT_OWN community */
3974 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3975 struct community *comm = bgp_attr_get_community(attr);
3976
3977 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3978 accept_own_found = true;
3979 }
3980
3981 /* The route in question is targeted to one or more destination VRFs
3982 * on the router (as determined by inspecting the Route Target(s)).
3983 */
3984 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3985 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3986 continue;
3987
3988 if (accept_own_found &&
3989 ecommunity_include(
3990 bgp->vpn_policy[afi]
3991 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3992 bgp_attr_get_ecommunity(attr))) {
3993 if (bgp_debug_update(peer, prefix, NULL, 1))
3994 zlog_debug(
3995 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3996 peer, prefix);
3997
3998 /* Treat this route as imported, because it's leaked
3999 * already from another VRF, and we got an updated
4000 * version from route-reflector with ACCEPT_OWN
4001 * community.
4002 */
4003 *sub_type = BGP_ROUTE_IMPORTED;
4004
4005 return true;
4006 }
4007 }
4008
4009 return false;
4010}
4011
367b458c
DS
4012void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
4013 struct attr *attr, afi_t afi, safi_t safi, int type,
4014 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4015 uint32_t num_labels, int soft_reconfig,
4016 struct bgp_route_evpn *evpn)
d62a17ae 4017{
4018 int ret;
4019 int aspath_loop_count = 0;
9bcb3eef 4020 struct bgp_dest *dest;
d62a17ae 4021 struct bgp *bgp;
4022 struct attr new_attr;
4023 struct attr *attr_new;
40381db7 4024 struct bgp_path_info *pi;
819e6767 4025 struct bgp_path_info *new = NULL;
4b7e6066 4026 struct bgp_path_info_extra *extra;
d62a17ae 4027 const char *reason;
4028 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4029 int connected = 0;
4030 int do_loop_check = 1;
4031 int has_valid_label = 0;
7c312383 4032 afi_t nh_afi;
9146341f 4033 bool force_evpn_import = false;
907707db 4034 safi_t orig_safi = safi;
a486300b 4035 bool leak_success = true;
b2ac1d0d 4036 int allowas_in = 0;
949b0f24 4037
c7bb4f00 4038 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4039 char pfxprint[PREFIX2STR_BUFFER];
4040
4041 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4042 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4043 afi, safi, attr);
6401252f
QY
4044 }
4045
49e5a4a0 4046#ifdef ENABLE_BGP_VNC
d62a17ae 4047 int vnc_implicit_withdraw = 0;
65efcfce 4048#endif
d62a17ae 4049 int same_attr = 0;
f8745525 4050 const struct prefix *bgp_nht_param_prefix;
718e3744 4051
907707db
MS
4052 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4053 if (orig_safi == SAFI_LABELED_UNICAST)
4054 safi = SAFI_UNICAST;
4055
6006b807 4056 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4057 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4058 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4059
d62a17ae 4060 bgp = peer->bgp;
9bcb3eef 4061 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4062 /* TODO: Check to see if we can get rid of "is_valid_label" */
4063 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4064 has_valid_label = (num_labels > 0) ? 1 : 0;
4065 else
4066 has_valid_label = bgp_is_valid_label(label);
718e3744 4067
28f66de2
MS
4068 if (has_valid_label)
4069 assert(label != NULL);
4070
66ff6089 4071
d62a17ae 4072 /* When peer's soft reconfiguration enabled. Record input packet in
4073 Adj-RIBs-In. */
6e076ba5
PJD
4074 if (!soft_reconfig &&
4075 CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) &&
4076 peer != bgp->peer_self) {
4077 /*
4078 * If the trigger is not from soft_reconfig and if
4079 * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
4080 * will not be interned. In which case, it is ok to update the
4081 * attr->evpn_overlay, so that, this can be stored in adj_in.
4082 */
4083 if ((afi == AFI_L2VPN) && evpn) {
4084 memcpy(&attr->evpn_overlay, evpn,
4085 sizeof(struct bgp_route_evpn));
4086 }
9bcb3eef 4087 bgp_adj_in_set(dest, peer, attr, addpath_id);
6e076ba5 4088 }
d62a17ae 4089
b2ac1d0d
MS
4090 /* Update permitted loop count */
4091 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4092 allowas_in = peer->allowas_in[afi][safi];
4093
d62a17ae 4094 /* Check previously received route. */
9bcb3eef 4095 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4096 if (pi->peer == peer && pi->type == type
4097 && pi->sub_type == sub_type
4098 && pi->addpath_rx_id == addpath_id)
d62a17ae 4099 break;
4100
4101 /* AS path local-as loop check. */
4102 if (peer->change_local_as) {
b2ac1d0d
MS
4103 if (allowas_in)
4104 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4105 else if (!CHECK_FLAG(peer->flags,
4106 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4107 aspath_loop_count = 1;
4108
4109 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4110 > aspath_loop_count) {
b4d46cc9 4111 peer->stat_pfx_aspath_loop++;
692174a1 4112 reason = "as-path contains our own AS;";
d62a17ae 4113 goto filtered;
4114 }
718e3744 4115 }
718e3744 4116
d62a17ae 4117 /* If the peer is configured for "allowas-in origin" and the last ASN in
4118 * the
4119 * as-path is our ASN then we do not need to call aspath_loop_check
4120 */
4121 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4122 if (aspath_get_last_as(attr->aspath) == bgp->as)
4123 do_loop_check = 0;
4124
f8745525
PG
4125 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4126 bgp_nht_param_prefix = NULL;
4127 else
4128 bgp_nht_param_prefix = p;
4129
d62a17ae 4130 /* AS path loop check. */
4131 if (do_loop_check) {
b0a8f709
FD
4132 if (aspath_loop_check(attr->aspath, bgp->as) >
4133 peer->allowas_in[afi][safi]) {
b4d46cc9 4134 peer->stat_pfx_aspath_loop++;
d62a17ae 4135 reason = "as-path contains our own AS;";
4136 goto filtered;
4137 }
4138 }
aac9ef6c 4139
b0a8f709
FD
4140 /* If we're a CONFED we need to loop check the CONFED ID too */
4141 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4142 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4143 peer->allowas_in[afi][safi]) {
4144 peer->stat_pfx_aspath_loop++;
4145 reason = "as-path contains our own confed AS;";
4146 goto filtered;
4147 }
4148
46dbf9d0
DA
4149 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4150 * enabled, then take care of that too.
4151 */
4152 bool accept_own = false;
4153
d62a17ae 4154 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4155 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4156 accept_own =
4157 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4158 if (!accept_own) {
4159 peer->stat_pfx_originator_loop++;
4160 reason = "originator is us;";
4161 goto filtered;
4162 }
d62a17ae 4163 }
718e3744 4164
d62a17ae 4165 /* Route reflector cluster ID check. */
4166 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4167 peer->stat_pfx_cluster_loop++;
d62a17ae 4168 reason = "reflected from the same cluster;";
4169 goto filtered;
4170 }
718e3744 4171
d62a17ae 4172 /* Apply incoming filter. */
907707db 4173 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4174 peer->stat_pfx_filter++;
d62a17ae 4175 reason = "filter;";
4176 goto filtered;
4177 }
718e3744 4178
c9a25614
DA
4179 /* If the route has Node Target Extended Communities, check
4180 * if it's allowed to be installed locally.
4181 */
4182 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4183 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
4184
4185 if (ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
4186 ECOMMUNITY_NODE_TARGET) &&
4187 !ecommunity_node_target_match(ecomm, &peer->local_id)) {
4188 reason =
4189 "Node-Target Extended Communities do not contain own BGP Identifier;";
4190 goto filtered;
4191 }
4192 }
4193
a8b72dc6
DA
4194 /* RFC 8212 to prevent route leaks.
4195 * This specification intends to improve this situation by requiring the
4196 * explicit configuration of both BGP Import and Export Policies for any
4197 * External BGP (EBGP) session such as customers, peers, or
4198 * confederation boundaries for all enabled address families. Through
4199 * codification of the aforementioned requirement, operators will
4200 * benefit from consistent behavior across different BGP
4201 * implementations.
4202 */
1d3fdccf 4203 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4204 if (!bgp_inbound_policy_exists(peer,
4205 &peer->filter[afi][safi])) {
4206 reason = "inbound policy missing";
b17826b7
DS
4207 if (monotime_since(&bgp->ebgprequirespolicywarning,
4208 NULL) > FIFTEENMINUTE2USEC ||
4209 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4210 zlog_warn(
4211 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4212 monotime(&bgp->ebgprequirespolicywarning);
4213 }
a8b72dc6
DA
4214 goto filtered;
4215 }
4216
fb29348a
DA
4217 /* draft-ietf-idr-deprecate-as-set-confed-set
4218 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4219 * Eventually, This document (if approved) updates RFC 4271
4220 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4221 * and obsoletes RFC 6472.
4222 */
7f972cd8 4223 if (peer->bgp->reject_as_sets)
fb29348a
DA
4224 if (aspath_check_as_sets(attr->aspath)) {
4225 reason =
4226 "as-path contains AS_SET or AS_CONFED_SET type;";
4227 goto filtered;
4228 }
4229
6f4f49b2 4230 new_attr = *attr;
6e076ba5
PJD
4231 /*
4232 * If bgp_update is called with soft_reconfig set then
4233 * attr is interned. In this case, do not overwrite the
4234 * attr->evpn_overlay with evpn directly. Instead memcpy
4235 * evpn to new_atr.evpn_overlay before it is interned.
4236 */
4237 if (soft_reconfig && (afi == AFI_L2VPN) && evpn)
4238 memcpy(&new_attr.evpn_overlay, evpn,
4239 sizeof(struct bgp_route_evpn));
d62a17ae 4240
4241 /* Apply incoming route-map.
4242 * NB: new_attr may now contain newly allocated values from route-map
4243 * "set"
4244 * commands, so we need bgp_attr_flush in the error paths, until we
4245 * intern
4246 * the attr (which takes over the memory references) */
907707db 4247 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4248 num_labels, dest)
4249 == RMAP_DENY) {
b4d46cc9 4250 peer->stat_pfx_filter++;
d62a17ae 4251 reason = "route-map;";
4252 bgp_attr_flush(&new_attr);
4253 goto filtered;
4254 }
718e3744 4255
05864da7 4256 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4257 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4258 /* remove from RIB previous entry */
4259 bgp_zebra_withdraw(p, pi, bgp, safi);
4260 }
4261
7f323236
DW
4262 if (peer->sort == BGP_PEER_EBGP) {
4263
2721dd61
DA
4264 /* rfc7999:
4265 * A BGP speaker receiving an announcement tagged with the
4266 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4267 * NO_EXPORT community as defined in RFC1997, or a
4268 * similar community, to prevent propagation of the
4269 * prefix outside the local AS. The community to prevent
4270 * propagation SHOULD be chosen according to the operator's
4271 * routing policy.
4272 */
9a706b42
DA
4273 if (bgp_attr_get_community(&new_attr) &&
4274 community_include(bgp_attr_get_community(&new_attr),
4275 COMMUNITY_BLACKHOLE))
aade37d7 4276 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4277
a4d82a8a
PZ
4278 /* If we receive the graceful-shutdown community from an eBGP
4279 * peer we must lower local-preference */
9a706b42
DA
4280 if (bgp_attr_get_community(&new_attr) &&
4281 community_include(bgp_attr_get_community(&new_attr),
4282 COMMUNITY_GSHUT)) {
7f323236
DW
4283 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4284 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4285
4f770cf1
DA
4286 /* If graceful-shutdown is configured globally or
4287 * per neighbor, then add the GSHUT community to
4288 * all paths received from eBGP peers. */
4289 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4290 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4291 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4292 }
4293
d62a17ae 4294 /* next hop check. */
860ad3f9
DS
4295 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4296 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4297 &new_attr, dest)) {
b4d46cc9 4298 peer->stat_pfx_nh_invalid++;
d62a17ae 4299 reason = "martian or self next-hop;";
4300 bgp_attr_flush(&new_attr);
4301 goto filtered;
4302 }
718e3744 4303
5c14a191 4304 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4305 peer->stat_pfx_nh_invalid++;
4e802e66 4306 reason = "self mac;";
4dbf2038 4307 bgp_attr_flush(&new_attr);
4e802e66
DS
4308 goto filtered;
4309 }
4310
5a78f2bc
EB
4311 if (bgp_check_role_applicability(afi, safi) &&
4312 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4313 reason = "failing otc validation";
4314 bgp_attr_flush(&new_attr);
4315 goto filtered;
4316 }
a1b773e2 4317
01da2d26
DA
4318 /* If neighbor soo is configured, tag all incoming routes with
4319 * this SoO tag and then filter out advertisements in
4320 * subgroup_announce_check() if it matches the configured SoO
4321 * on the other peer.
4322 */
4323 if (peer->soo[afi][safi]) {
4324 struct ecommunity *old_ecomm =
4325 bgp_attr_get_ecommunity(&new_attr);
4326 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4327 struct ecommunity *new_ecomm;
4328
4329 if (old_ecomm) {
4330 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4331 ecomm_soo);
4332
4333 if (!old_ecomm->refcnt)
4334 ecommunity_free(&old_ecomm);
4335 } else {
4336 new_ecomm = ecommunity_dup(ecomm_soo);
4337 }
4338
4339 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4340 }
4341
4dbf2038 4342 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4343
d62a17ae 4344 /* If the update is implicit withdraw. */
40381db7 4345 if (pi) {
083ec940 4346 pi->uptime = monotime(NULL);
40381db7 4347 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4348
9bcb3eef 4349 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4350
d62a17ae 4351 /* Same attribute comes in. */
40381db7 4352 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4353 && same_attr
d62a17ae 4354 && (!has_valid_label
40381db7 4355 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4356 num_labels * sizeof(mpls_label_t))
66ff6089 4357 == 0)) {
b4f7f45b
IR
4358 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4359 BGP_CONFIG_DAMPENING)
d62a17ae 4360 && peer->sort == BGP_PEER_EBGP
40381db7 4361 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4362 if (bgp_debug_update(peer, p, NULL, 1)) {
4363 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4364 afi, safi, prd, p, label,
4365 num_labels, addpath_id ? 1 : 0,
66ff6089 4366 addpath_id, evpn, pfx_buf,
a4d82a8a 4367 sizeof(pfx_buf));
f70c91dc 4368 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4369 pfx_buf);
4370 }
4371
9bcb3eef 4372 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4373 != BGP_DAMP_SUPPRESSED) {
40381db7 4374 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4375 safi);
9bcb3eef 4376 bgp_process(bgp, dest, afi, safi);
d62a17ae 4377 }
4378 } else /* Duplicate - odd */
4379 {
4380 if (bgp_debug_update(peer, p, NULL, 1)) {
4381 if (!peer->rcvd_attr_printed) {
4382 zlog_debug(
f70c91dc
DA
4383 "%pBP rcvd UPDATE w/ attr: %s",
4384 peer,
d62a17ae 4385 peer->rcvd_attr_str);
4386 peer->rcvd_attr_printed = 1;
4387 }
4388
4389 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4390 afi, safi, prd, p, label,
4391 num_labels, addpath_id ? 1 : 0,
66ff6089 4392 addpath_id, evpn, pfx_buf,
a4d82a8a 4393 sizeof(pfx_buf));
d62a17ae 4394 zlog_debug(
f70c91dc
DA
4395 "%pBP rcvd %s...duplicate ignored",
4396 peer, pfx_buf);
d62a17ae 4397 }
4398
4399 /* graceful restart STALE flag unset. */
40381db7 4400 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4401 bgp_path_info_unset_flag(
9bcb3eef
DS
4402 dest, pi, BGP_PATH_STALE);
4403 bgp_dest_set_defer_flag(dest, false);
4404 bgp_process(bgp, dest, afi, safi);
d62a17ae 4405 }
4406 }
4407
9bcb3eef 4408 bgp_dest_unlock_node(dest);
d62a17ae 4409 bgp_attr_unintern(&attr_new);
4410
367b458c 4411 return;
d62a17ae 4412 }
718e3744 4413
d62a17ae 4414 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4415 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4416 if (bgp_debug_update(peer, p, NULL, 1)) {
4417 bgp_debug_rdpfxpath2str(
a4d82a8a 4418 afi, safi, prd, p, label, num_labels,
66ff6089 4419 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4420 pfx_buf, sizeof(pfx_buf));
d62a17ae 4421 zlog_debug(
f70c91dc
DA
4422 "%pBP rcvd %s, flapped quicker than processing",
4423 peer, pfx_buf);
d62a17ae 4424 }
4425
9bcb3eef 4426 bgp_path_info_restore(dest, pi);
9146341f 4427
4428 /*
4429 * If the BGP_PATH_REMOVED flag is set, then EVPN
4430 * routes would have been unimported already when a
4431 * prior BGP withdraw processing happened. Such routes
4432 * need to be imported again, so flag accordingly.
4433 */
4434 force_evpn_import = true;
704e189e 4435 } else {
4436 /* implicit withdraw, decrement aggregate and pcount
4437 * here. only if update is accepted, they'll increment
4438 * below.
4439 */
4440 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4441 }
718e3744 4442
d62a17ae 4443 /* Received Logging. */
4444 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4445 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4446 num_labels, addpath_id ? 1 : 0,
66ff6089 4447 addpath_id, evpn, pfx_buf,
a4d82a8a 4448 sizeof(pfx_buf));
f70c91dc 4449 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4450 }
718e3744 4451
d62a17ae 4452 /* graceful restart STALE flag unset. */
f009ff26 4453 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4455 bgp_dest_set_defer_flag(dest, false);
f009ff26 4456 }
d62a17ae 4457
4458 /* The attribute is changed. */
9bcb3eef 4459 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4460
d62a17ae 4461 /* Update bgp route dampening information. */
b4f7f45b 4462 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4463 && peer->sort == BGP_PEER_EBGP) {
4464 /* This is implicit withdraw so we should update
b4f7f45b
IR
4465 dampening
4466 information. */
40381db7 4467 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4468 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4469 }
49e5a4a0 4470#ifdef ENABLE_BGP_VNC
d62a17ae 4471 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4472 struct bgp_dest *pdest = NULL;
d62a17ae 4473 struct bgp_table *table = NULL;
4474
9bcb3eef
DS
4475 pdest = bgp_node_get(bgp->rib[afi][safi],
4476 (struct prefix *)prd);
4477 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4478 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4479
4480 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4481 bgp, prd, table, p, pi);
d62a17ae 4482 }
9bcb3eef 4483 bgp_dest_unlock_node(pdest);
d62a17ae 4484 }
4485 if ((afi == AFI_IP || afi == AFI_IP6)
4486 && (safi == SAFI_UNICAST)) {
40381db7 4487 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4488 /*
4489 * Implicit withdraw case.
4490 */
4491 ++vnc_implicit_withdraw;
40381db7
DS
4492 vnc_import_bgp_del_route(bgp, p, pi);
4493 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4494 }
4495 }
65efcfce 4496#endif
128ea8ab 4497
d62a17ae 4498 /* Special handling for EVPN update of an existing route. If the
4499 * extended community attribute has changed, we need to
4500 * un-import
4501 * the route using its existing extended community. It will be
4502 * subsequently processed for import with the new extended
4503 * community.
4504 */
6f8c9c11
PR
4505 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4506 && !same_attr) {
40381db7 4507 if ((pi->attr->flag
d62a17ae 4508 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4509 && (attr_new->flag
4510 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4511 int cmp;
4512
b53e67a3
DA
4513 cmp = ecommunity_cmp(
4514 bgp_attr_get_ecommunity(pi->attr),
4515 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4516 if (!cmp) {
4517 if (bgp_debug_update(peer, p, NULL, 1))
4518 zlog_debug(
4519 "Change in EXT-COMM, existing %s new %s",
4520 ecommunity_str(
b53e67a3
DA
4521 bgp_attr_get_ecommunity(
4522 pi->attr)),
d62a17ae 4523 ecommunity_str(
b53e67a3
DA
4524 bgp_attr_get_ecommunity(
4525 attr_new)));
6f8c9c11
PR
4526 if (safi == SAFI_EVPN)
4527 bgp_evpn_unimport_route(
4528 bgp, afi, safi, p, pi);
4529 else /* SAFI_MPLS_VPN */
1aa2c93e 4530 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4531 }
4532 }
4533 }
718e3744 4534
d62a17ae 4535 /* Update to new attribute. */
40381db7
DS
4536 bgp_attr_unintern(&pi->attr);
4537 pi->attr = attr_new;
d62a17ae 4538
4539 /* Update MPLS label */
4540 if (has_valid_label) {
40381db7 4541 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4542 if (extra->label != label) {
4543 memcpy(&extra->label, label,
dbd587da 4544 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4545 extra->num_labels = num_labels;
4546 }
b57ba6d2
MK
4547 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4548 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4549 }
718e3744 4550
e496b420
HS
4551 /* Update SRv6 SID */
4552 if (attr->srv6_l3vpn) {
4553 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4554 if (sid_diff(&extra->sid[0].sid,
4555 &attr->srv6_l3vpn->sid)) {
4556 sid_copy(&extra->sid[0].sid,
e496b420
HS
4557 &attr->srv6_l3vpn->sid);
4558 extra->num_sids = 1;
cc8f05df 4559
16f3db2d
RS
4560 extra->sid[0].loc_block_len = 0;
4561 extra->sid[0].loc_node_len = 0;
4562 extra->sid[0].func_len = 0;
4563 extra->sid[0].arg_len = 0;
ea7cd161
RS
4564 extra->sid[0].transposition_len = 0;
4565 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4566
4567 if (attr->srv6_l3vpn->loc_block_len != 0) {
4568 extra->sid[0].loc_block_len =
4569 attr->srv6_l3vpn->loc_block_len;
4570 extra->sid[0].loc_node_len =
4571 attr->srv6_l3vpn->loc_node_len;
4572 extra->sid[0].func_len =
4573 attr->srv6_l3vpn->func_len;
4574 extra->sid[0].arg_len =
4575 attr->srv6_l3vpn->arg_len;
ea7cd161 4576 extra->sid[0].transposition_len =
cc8f05df 4577 attr->srv6_l3vpn
ea7cd161
RS
4578 ->transposition_len;
4579 extra->sid[0].transposition_offset =
cc8f05df 4580 attr->srv6_l3vpn
ea7cd161
RS
4581 ->transposition_offset;
4582 }
e496b420
HS
4583 }
4584 } else if (attr->srv6_vpn) {
4585 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4586 if (sid_diff(&extra->sid[0].sid,
4587 &attr->srv6_vpn->sid)) {
4588 sid_copy(&extra->sid[0].sid,
4589 &attr->srv6_vpn->sid);
e496b420
HS
4590 extra->num_sids = 1;
4591 }
4592 }
4593
49e5a4a0 4594#ifdef ENABLE_BGP_VNC
d62a17ae 4595 if ((afi == AFI_IP || afi == AFI_IP6)
4596 && (safi == SAFI_UNICAST)) {
4597 if (vnc_implicit_withdraw) {
4598 /*
4599 * Add back the route with its new attributes
4600 * (e.g., nexthop).
4601 * The route is still selected, until the route
4602 * selection
4603 * queued by bgp_process actually runs. We have
4604 * to make this
4605 * update to the VNC side immediately to avoid
4606 * racing against
4607 * configuration changes (e.g., route-map
4608 * changes) which
4609 * trigger re-importation of the entire RIB.
4610 */
40381db7
DS
4611 vnc_import_bgp_add_route(bgp, p, pi);
4612 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4613 }
4614 }
65efcfce
LB
4615#endif
4616
d62a17ae 4617 /* Update bgp route dampening information. */
b4f7f45b 4618 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4619 && peer->sort == BGP_PEER_EBGP) {
4620 /* Now we do normal update dampening. */
9bcb3eef 4621 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4622 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4623 bgp_dest_unlock_node(dest);
367b458c 4624 return;
d62a17ae 4625 }
4626 }
128ea8ab 4627
d62a17ae 4628 /* Nexthop reachability check - for unicast and
4629 * labeled-unicast.. */
7c312383
AD
4630 if (((afi == AFI_IP || afi == AFI_IP6)
4631 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4632 || (safi == SAFI_EVPN &&
4633 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4634 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4635 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4636 && !CHECK_FLAG(peer->flags,
4637 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4638 && !CHECK_FLAG(bgp->flags,
4639 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4640 connected = 1;
4641 else
4642 connected = 0;
4643
960035b2
PZ
4644 struct bgp *bgp_nexthop = bgp;
4645
40381db7
DS
4646 if (pi->extra && pi->extra->bgp_orig)
4647 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4648
7c312383
AD
4649 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4650
4651 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4652 safi, pi, NULL, connected,
f8745525
PG
4653 bgp_nht_param_prefix) ||
4654 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4655 bgp_path_info_set_flag(dest, pi,
4656 BGP_PATH_VALID);
d62a17ae 4657 else {
4658 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4659 zlog_debug("%s(%pI4): NH unresolved",
4660 __func__,
4661 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4662 }
9bcb3eef 4663 bgp_path_info_unset_flag(dest, pi,
18ee8310 4664 BGP_PATH_VALID);
d62a17ae 4665 }
46dbf9d0
DA
4666 } else {
4667 if (accept_own)
4668 bgp_path_info_set_flag(dest, pi,
4669 BGP_PATH_ACCEPT_OWN);
4670
9bcb3eef 4671 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4672 }
d62a17ae 4673
49e5a4a0 4674#ifdef ENABLE_BGP_VNC
d62a17ae 4675 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4676 struct bgp_dest *pdest = NULL;
d62a17ae 4677 struct bgp_table *table = NULL;
4678
9bcb3eef
DS
4679 pdest = bgp_node_get(bgp->rib[afi][safi],
4680 (struct prefix *)prd);
4681 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4682 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4683
4684 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4685 bgp, prd, table, p, pi);
d62a17ae 4686 }
9bcb3eef 4687 bgp_dest_unlock_node(pdest);
d62a17ae 4688 }
4689#endif
718e3744 4690
d62a17ae 4691 /* If this is an EVPN route and some attribute has changed,
9146341f 4692 * or we are explicitly told to perform a route import, process
d62a17ae 4693 * route for import. If the extended community has changed, we
4694 * would
4695 * have done the un-import earlier and the import would result
4696 * in the
4697 * route getting injected into appropriate L2 VNIs. If it is
4698 * just
4699 * some other attribute change, the import will result in
4700 * updating
4701 * the attributes for the route in the VNI(s).
4702 */
9146341f 4703 if (safi == SAFI_EVPN &&
4704 (!same_attr || force_evpn_import) &&
7c312383 4705 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4706 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4707
4708 /* Process change. */
40381db7 4709 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4710
9bcb3eef
DS
4711 bgp_process(bgp, dest, afi, safi);
4712 bgp_dest_unlock_node(dest);
558d1fec 4713
ddb5b488
PZ
4714 if (SAFI_UNICAST == safi
4715 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4716 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4717
40381db7 4718 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4719 }
4720 if ((SAFI_MPLS_VPN == safi)
4721 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4722 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4723 }
4724
49e5a4a0 4725#ifdef ENABLE_BGP_VNC
d62a17ae 4726 if (SAFI_MPLS_VPN == safi) {
4727 mpls_label_t label_decoded = decode_label(label);
28070ee3 4728
d62a17ae 4729 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4730 type, sub_type, &label_decoded);
4731 }
4732 if (SAFI_ENCAP == safi) {
4733 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4734 type, sub_type, NULL);
4735 }
28070ee3 4736#endif
a486300b
PG
4737 if ((safi == SAFI_MPLS_VPN) &&
4738 !CHECK_FLAG(bgp->af_flags[afi][safi],
4739 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4740 !leak_success) {
4741 bgp_unlink_nexthop(pi);
4742 bgp_path_info_delete(dest, pi);
4743 }
367b458c 4744 return;
d62a17ae 4745 } // End of implicit withdraw
718e3744 4746
d62a17ae 4747 /* Received Logging. */
4748 if (bgp_debug_update(peer, p, NULL, 1)) {
4749 if (!peer->rcvd_attr_printed) {
f70c91dc 4750 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4751 peer->rcvd_attr_str);
4752 peer->rcvd_attr_printed = 1;
4753 }
718e3744 4754
a4d82a8a 4755 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4756 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4757 pfx_buf, sizeof(pfx_buf));
f70c91dc 4758 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4759 }
718e3744 4760
d62a17ae 4761 /* Make new BGP info. */
9bcb3eef 4762 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4763
d62a17ae 4764 /* Update MPLS label */
4765 if (has_valid_label) {
18ee8310 4766 extra = bgp_path_info_extra_get(new);
8ba71050 4767 if (extra->label != label) {
dbd587da
QY
4768 memcpy(&extra->label, label,
4769 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4770 extra->num_labels = num_labels;
4771 }
b57ba6d2
MK
4772 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4773 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4774 }
718e3744 4775
e496b420
HS
4776 /* Update SRv6 SID */
4777 if (safi == SAFI_MPLS_VPN) {
4778 extra = bgp_path_info_extra_get(new);
4779 if (attr->srv6_l3vpn) {
16f3db2d 4780 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4781 extra->num_sids = 1;
cc8f05df 4782
16f3db2d
RS
4783 extra->sid[0].loc_block_len =
4784 attr->srv6_l3vpn->loc_block_len;
4785 extra->sid[0].loc_node_len =
4786 attr->srv6_l3vpn->loc_node_len;
4787 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4788 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4789 extra->sid[0].transposition_len =
4790 attr->srv6_l3vpn->transposition_len;
4791 extra->sid[0].transposition_offset =
4792 attr->srv6_l3vpn->transposition_offset;
e496b420 4793 } else if (attr->srv6_vpn) {
16f3db2d 4794 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4795 extra->num_sids = 1;
4796 }
4797 }
4798
d62a17ae 4799 /* Nexthop reachability check. */
7c312383
AD
4800 if (((afi == AFI_IP || afi == AFI_IP6)
4801 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4802 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4803 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4804 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4805 && !CHECK_FLAG(peer->flags,
4806 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4807 && !CHECK_FLAG(bgp->flags,
4808 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4809 connected = 1;
4810 else
4811 connected = 0;
4812
7c312383
AD
4813 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4814
4053e952 4815 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4816 connected, bgp_nht_param_prefix) ||
4817 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4818 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4819 else {
07380148
DA
4820 if (BGP_DEBUG(nht, NHT))
4821 zlog_debug("%s(%pI4): NH unresolved", __func__,
4822 &attr_new->nexthop);
9bcb3eef 4823 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4824 }
46dbf9d0
DA
4825 } else {
4826 if (accept_own)
4827 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4828
9bcb3eef 4829 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4830 }
a82478b9 4831
b381ed97
DA
4832 /* If maximum prefix count is configured and current prefix
4833 * count exeed it.
4834 */
4835 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4836 reason = "maximum-prefix overflow";
4837 bgp_attr_flush(&new_attr);
b381ed97
DA
4838 goto filtered;
4839 }
4840
d62a17ae 4841 /* Addpath ID */
4842 new->addpath_rx_id = addpath_id;
4843
4844 /* Increment prefix */
4845 bgp_aggregate_increment(bgp, p, new, afi, safi);
4846
4847 /* Register new BGP information. */
9bcb3eef 4848 bgp_path_info_add(dest, new);
d62a17ae 4849
4850 /* route_node_get lock */
9bcb3eef 4851 bgp_dest_unlock_node(dest);
558d1fec 4852
49e5a4a0 4853#ifdef ENABLE_BGP_VNC
d62a17ae 4854 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4855 struct bgp_dest *pdest = NULL;
d62a17ae 4856 struct bgp_table *table = NULL;
4857
9bcb3eef
DS
4858 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4859 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4860 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4861
4862 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4863 bgp, prd, table, p, new);
4864 }
9bcb3eef 4865 bgp_dest_unlock_node(pdest);
d62a17ae 4866 }
65efcfce
LB
4867#endif
4868
d62a17ae 4869 /* If this is an EVPN route, process for import. */
7c312383 4870 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4871 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4872
9bcb3eef 4873 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4874
d62a17ae 4875 /* Process change. */
9bcb3eef 4876 bgp_process(bgp, dest, afi, safi);
718e3744 4877
ddb5b488
PZ
4878 if (SAFI_UNICAST == safi
4879 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4880 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4881 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4882 }
4883 if ((SAFI_MPLS_VPN == safi)
4884 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4885 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4886 }
49e5a4a0 4887#ifdef ENABLE_BGP_VNC
d62a17ae 4888 if (SAFI_MPLS_VPN == safi) {
4889 mpls_label_t label_decoded = decode_label(label);
28070ee3 4890
d62a17ae 4891 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4892 sub_type, &label_decoded);
4893 }
4894 if (SAFI_ENCAP == safi) {
4895 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4896 sub_type, NULL);
4897 }
28070ee3 4898#endif
a486300b
PG
4899 if ((safi == SAFI_MPLS_VPN) &&
4900 !CHECK_FLAG(bgp->af_flags[afi][safi],
4901 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4902 !leak_success) {
4903 bgp_unlink_nexthop(new);
4904 bgp_path_info_delete(dest, new);
4905 }
28070ee3 4906
367b458c 4907 return;
718e3744 4908
d62a17ae 4909/* This BGP update is filtered. Log the reason then update BGP
4910 entry. */
4911filtered:
819e6767
DA
4912 if (new) {
4913 bgp_unlink_nexthop(new);
4914 bgp_path_info_delete(dest, new);
4915 bgp_path_info_extra_free(&new->extra);
4916 XFREE(MTYPE_BGP_ROUTE, new);
4917 }
4918
9bcb3eef 4919 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4920
d62a17ae 4921 if (bgp_debug_update(peer, p, NULL, 1)) {
4922 if (!peer->rcvd_attr_printed) {
f70c91dc 4923 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4924 peer->rcvd_attr_str);
4925 peer->rcvd_attr_printed = 1;
4926 }
718e3744 4927
a4d82a8a 4928 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4929 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4930 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4931 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4932 peer, pfx_buf, reason);
d62a17ae 4933 }
128ea8ab 4934
40381db7 4935 if (pi) {
d62a17ae 4936 /* If this is an EVPN route, un-import it as it is now filtered.
4937 */
4938 if (safi == SAFI_EVPN)
40381db7 4939 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4940
ddb5b488
PZ
4941 if (SAFI_UNICAST == safi
4942 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4943 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4944
40381db7 4945 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4946 }
4947 if ((SAFI_MPLS_VPN == safi)
4948 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4949
1aa2c93e 4950 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4951 }
4952
9bcb3eef 4953 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4954 }
4955
9bcb3eef 4956 bgp_dest_unlock_node(dest);
558d1fec 4957
49e5a4a0 4958#ifdef ENABLE_BGP_VNC
d62a17ae 4959 /*
4960 * Filtered update is treated as an implicit withdrawal (see
4961 * bgp_rib_remove()
4962 * a few lines above)
4963 */
4964 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4965 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4966 0);
4967 }
97736e32
PZ
4968#endif
4969
367b458c 4970 return;
718e3744 4971}
4972
367b458c 4973void bgp_withdraw(struct peer *peer, const struct prefix *p,
bf0c6163
DA
4974 uint32_t addpath_id, afi_t afi, safi_t safi, int type,
4975 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
4976 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4977{
d62a17ae 4978 struct bgp *bgp;
4979 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4980 struct bgp_dest *dest;
40381db7 4981 struct bgp_path_info *pi;
718e3744 4982
49e5a4a0 4983#ifdef ENABLE_BGP_VNC
d62a17ae 4984 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4985 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4986 0);
4987 }
28070ee3
PZ
4988#endif
4989
d62a17ae 4990 bgp = peer->bgp;
4991
4992 /* Lookup node. */
9bcb3eef 4993 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4994
4995 /* If peer is soft reconfiguration enabled. Record input packet for
4996 * further calculation.
4997 *
4998 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4999 * routes that are filtered. This tanks out Quagga RS pretty badly due
5000 * to
5001 * the iteration over all RS clients.
5002 * Since we need to remove the entry from adj_in anyway, do that first
5003 * and
5004 * if there was no entry, we don't need to do anything more.
5005 */
5006 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
5007 && peer != bgp->peer_self)
9bcb3eef 5008 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
5009 peer->stat_pfx_dup_withdraw++;
5010
d62a17ae 5011 if (bgp_debug_update(peer, p, NULL, 1)) {
5012 bgp_debug_rdpfxpath2str(
a4d82a8a 5013 afi, safi, prd, p, label, num_labels,
6c995628
AD
5014 addpath_id ? 1 : 0, addpath_id, NULL,
5015 pfx_buf, sizeof(pfx_buf));
d62a17ae 5016 zlog_debug(
5017 "%s withdrawing route %s not in adj-in",
5018 peer->host, pfx_buf);
5019 }
9bcb3eef 5020 bgp_dest_unlock_node(dest);
367b458c 5021 return;
d62a17ae 5022 }
cd808e74 5023
d62a17ae 5024 /* Lookup withdrawn route. */
9bcb3eef 5025 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5026 if (pi->peer == peer && pi->type == type
5027 && pi->sub_type == sub_type
5028 && pi->addpath_rx_id == addpath_id)
d62a17ae 5029 break;
5030
5031 /* Logging. */
5032 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5033 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5034 addpath_id ? 1 : 0, addpath_id, NULL,
5035 pfx_buf, sizeof(pfx_buf));
f70c91dc 5036 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 5037 pfx_buf);
5038 }
718e3744 5039
d62a17ae 5040 /* Withdraw specified route from routing table. */
40381db7 5041 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5042 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5043 if (SAFI_UNICAST == safi
5044 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5045 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5046 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5047 }
5048 if ((SAFI_MPLS_VPN == safi)
5049 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5050
1aa2c93e 5051 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
5052 }
5053 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5054 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5055 addpath_id ? 1 : 0, addpath_id, NULL,
5056 pfx_buf, sizeof(pfx_buf));
d62a17ae 5057 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5058 }
718e3744 5059
d62a17ae 5060 /* Unlock bgp_node_get() lock. */
9bcb3eef 5061 bgp_dest_unlock_node(dest);
d62a17ae 5062
367b458c 5063 return;
718e3744 5064}
6b0655a2 5065
d62a17ae 5066void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5067 int withdraw)
718e3744 5068{
d62a17ae 5069 struct update_subgroup *subgrp;
5070 subgrp = peer_subgroup(peer, afi, safi);
5071 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5072}
6182d65b 5073
718e3744 5074
3f9c7369
DS
5075/*
5076 * bgp_stop_announce_route_timer
5077 */
d62a17ae 5078void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5079{
d62a17ae 5080 if (!paf->t_announce_route)
5081 return;
5082
e16d030c 5083 EVENT_OFF(paf->t_announce_route);
718e3744 5084}
6b0655a2 5085
3f9c7369
DS
5086/*
5087 * bgp_announce_route_timer_expired
5088 *
5089 * Callback that is invoked when the route announcement timer for a
5090 * peer_af expires.
5091 */
e6685141 5092static void bgp_announce_route_timer_expired(struct event *t)
718e3744 5093{
d62a17ae 5094 struct peer_af *paf;
5095 struct peer *peer;
558d1fec 5096
e16d030c 5097 paf = EVENT_ARG(t);
d62a17ae 5098 peer = paf->peer;
718e3744 5099
feb17238 5100 if (!peer_established(peer))
cc9f21da 5101 return;
3f9c7369 5102
d62a17ae 5103 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5104 return;
3f9c7369 5105
d62a17ae 5106 peer_af_announce_route(paf, 1);
c5aec50b
MK
5107
5108 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5109 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5110}
5111
3f9c7369
DS
5112/*
5113 * bgp_announce_route
5114 *
5115 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5116 *
5117 * if force is true we will force an update even if the update
5118 * limiting code is attempted to kick in.
3f9c7369 5119 */
e1a32ec1 5120void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5121{
5122 struct peer_af *paf;
5123 struct update_subgroup *subgrp;
5124
5125 paf = peer_af_find(peer, afi, safi);
5126 if (!paf)
5127 return;
5128 subgrp = PAF_SUBGRP(paf);
5129
5130 /*
5131 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5132 * or a refresh has already been triggered.
5133 */
5134 if (!subgrp || paf->t_announce_route)
5135 return;
5136
e1a32ec1
DS
5137 if (force)
5138 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5139
d62a17ae 5140 /*
5141 * Start a timer to stagger/delay the announce. This serves
5142 * two purposes - announcement can potentially be combined for
5143 * multiple peers and the announcement doesn't happen in the
5144 * vty context.
5145 */
907a2395
DS
5146 event_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5147 (subgrp->peer_count == 1)
5148 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5149 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5150 &paf->t_announce_route);
3f9c7369
DS
5151}
5152
5153/*
5154 * Announce routes from all AF tables to a peer.
5155 *
5156 * This should ONLY be called when there is a need to refresh the
5157 * routes to the peer based on a policy change for this peer alone
5158 * or a route refresh request received from the peer.
5159 * The operation will result in splitting the peer from its existing
5160 * subgroups and putting it in new subgroups.
5161 */
d62a17ae 5162void bgp_announce_route_all(struct peer *peer)
718e3744 5163{
d62a17ae 5164 afi_t afi;
5165 safi_t safi;
5166
05c7a1cc 5167 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5168 bgp_announce_route(peer, afi, safi, false);
718e3744 5169}
6b0655a2 5170
46aeabed
LS
5171/* Flag or unflag bgp_dest to determine whether it should be treated by
5172 * bgp_soft_reconfig_table_task.
5173 * Flag if flag is true. Unflag if flag is false.
5174 */
5175static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5176{
5177 struct bgp_dest *dest;
5178 struct bgp_adj_in *ain;
5179
5180 if (!table)
5181 return;
5182
5183 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5184 for (ain = dest->adj_in; ain; ain = ain->next) {
5185 if (ain->peer != NULL)
5186 break;
5187 }
5188 if (flag && ain != NULL && ain->peer != NULL)
5189 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5190 else
5191 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5192 }
5193}
5194
367b458c
DS
5195static void bgp_soft_reconfig_table_update(struct peer *peer,
5196 struct bgp_dest *dest,
5197 struct bgp_adj_in *ain, afi_t afi,
5198 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5199{
5200 struct bgp_path_info *pi;
5201 uint32_t num_labels = 0;
5202 mpls_label_t *label_pnt = NULL;
5203 struct bgp_route_evpn evpn;
5204
5205 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5206 if (pi->peer == peer)
5207 break;
5208
5209 if (pi && pi->extra)
5210 num_labels = pi->extra->num_labels;
5211 if (num_labels)
5212 label_pnt = &pi->extra->label[0];
5213 if (pi)
5214 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5215 sizeof(evpn));
5216 else
5217 memset(&evpn, 0, sizeof(evpn));
5218
367b458c
DS
5219 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5220 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5221 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5222}
5223
d62a17ae 5224static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5225 struct bgp_table *table,
5226 struct prefix_rd *prd)
718e3744 5227{
9bcb3eef 5228 struct bgp_dest *dest;
d62a17ae 5229 struct bgp_adj_in *ain;
718e3744 5230
d62a17ae 5231 if (!table)
5232 table = peer->bgp->rib[afi][safi];
718e3744 5233
9bcb3eef
DS
5234 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5235 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5236 if (ain->peer != peer)
5237 continue;
8692c506 5238
367b458c
DS
5239 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5240 safi, prd);
d62a17ae 5241 }
718e3744 5242}
5243
46aeabed
LS
5244/* Do soft reconfig table per bgp table.
5245 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5246 * when BGP_NODE_SOFT_RECONFIG is set,
5247 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5248 * Schedule a new thread to continue the job.
5249 * Without splitting the full job into several part,
5250 * vtysh waits for the job to finish before responding to a BGP command
5251 */
e6685141 5252static void bgp_soft_reconfig_table_task(struct event *thread)
46aeabed
LS
5253{
5254 uint32_t iter, max_iter;
46aeabed
LS
5255 struct bgp_dest *dest;
5256 struct bgp_adj_in *ain;
5257 struct peer *peer;
5258 struct bgp_table *table;
5259 struct prefix_rd *prd;
5260 struct listnode *node, *nnode;
5261
e16d030c 5262 table = EVENT_ARG(thread);
46aeabed
LS
5263 prd = NULL;
5264
5265 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5266 if (table->soft_reconfig_init) {
5267 /* first call of the function with a new srta structure.
5268 * Don't do any treatment this time on nodes
5269 * in order vtysh to respond quickly
5270 */
5271 max_iter = 0;
5272 }
5273
5274 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5275 dest = bgp_route_next(dest)) {
5276 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5277 continue;
5278
5279 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5280
5281 for (ain = dest->adj_in; ain; ain = ain->next) {
5282 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5283 nnode, peer)) {
5284 if (ain->peer != peer)
5285 continue;
5286
367b458c 5287 bgp_soft_reconfig_table_update(
46aeabed
LS
5288 peer, dest, ain, table->afi,
5289 table->safi, prd);
5290 iter++;
46aeabed
LS
5291 }
5292 }
5293 }
5294
5295 /* we're either starting the initial iteration,
5296 * or we're going to continue an ongoing iteration
5297 */
5298 if (dest || table->soft_reconfig_init) {
5299 table->soft_reconfig_init = false;
907a2395
DS
5300 event_add_event(bm->master, bgp_soft_reconfig_table_task, table,
5301 0, &table->soft_reconfig_thread);
cc9f21da 5302 return;
46aeabed
LS
5303 }
5304 /* we're done, clean up the background iteration context info and
5305 schedule route annoucement
5306 */
5307 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5308 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5309 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5310 }
5311
5312 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5313}
5314
5315
5316/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5317 * and peer.
5318 * - bgp cannot be NULL
5319 * - if table and peer are NULL, cancel all threads within the bgp instance
5320 * - if table is NULL and peer is not,
5321 * remove peer in all threads within the bgp instance
5322 * - if peer is NULL, cancel all threads matching table within the bgp instance
5323 */
5324void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5325 const struct bgp_table *table,
5326 const struct peer *peer)
5327{
5328 struct peer *npeer;
5329 struct listnode *node, *nnode;
5330 int afi, safi;
5331 struct bgp_table *ntable;
5332
5333 if (!bgp)
5334 return;
5335
5336 FOREACH_AFI_SAFI (afi, safi) {
5337 ntable = bgp->rib[afi][safi];
5338 if (!ntable)
5339 continue;
5340 if (table && table != ntable)
5341 continue;
5342
5343 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5344 npeer)) {
5345 if (peer && peer != npeer)
5346 continue;
5347 listnode_delete(ntable->soft_reconfig_peers, npeer);
5348 }
5349
5350 if (!ntable->soft_reconfig_peers
5351 || !list_isempty(ntable->soft_reconfig_peers))
5352 continue;
5353
5354 list_delete(&ntable->soft_reconfig_peers);
5355 bgp_soft_reconfig_table_flag(ntable, false);
e16d030c 5356 EVENT_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5357 }
5358}
5359
89c73443
DS
5360/*
5361 * Returns false if the peer is not configured for soft reconfig in
5362 */
5363bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5364{
9bcb3eef 5365 struct bgp_dest *dest;
d62a17ae 5366 struct bgp_table *table;
46aeabed
LS
5367 struct listnode *node, *nnode;
5368 struct peer *npeer;
5369 struct peer_af *paf;
718e3744 5370
89c73443
DS
5371 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5372 return false;
718e3744 5373
d62a17ae 5374 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5375 && (safi != SAFI_EVPN)) {
5376 table = peer->bgp->rib[afi][safi];
5377 if (!table)
89c73443 5378 return true;
46aeabed
LS
5379
5380 table->soft_reconfig_init = true;
5381
5382 if (!table->soft_reconfig_peers)
5383 table->soft_reconfig_peers = list_new();
5384 npeer = NULL;
5385 /* add peer to the table soft_reconfig_peers if not already
5386 * there
5387 */
5388 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5389 npeer)) {
5390 if (peer == npeer)
5391 break;
5392 }
5393 if (peer != npeer)
5394 listnode_add(table->soft_reconfig_peers, peer);
5395
5396 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5397 * on table would start back at the beginning.
5398 */
5399 bgp_soft_reconfig_table_flag(table, true);
5400
5401 if (!table->soft_reconfig_thread)
907a2395
DS
5402 event_add_event(bm->master,
5403 bgp_soft_reconfig_table_task, table, 0,
5404 &table->soft_reconfig_thread);
46aeabed
LS
5405 /* Cancel bgp_announce_route_timer_expired threads.
5406 * bgp_announce_route_timer_expired threads have been scheduled
5407 * to announce routes as soon as the soft_reconfigure process
5408 * finishes.
5409 * In this case, soft_reconfigure is also scheduled by using
5410 * a thread but is planned after the
5411 * bgp_announce_route_timer_expired threads. It means that,
5412 * without cancelling the threads, the route announcement task
5413 * would run before the soft reconfiguration one. That would
5414 * useless and would block vtysh during several seconds. Route
5415 * announcements are rescheduled as soon as the soft_reconfigure
5416 * process finishes.
5417 */
5418 paf = peer_af_find(peer, afi, safi);
5419 if (paf)
5420 bgp_stop_announce_route_timer(paf);
5421 } else
9bcb3eef
DS
5422 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5423 dest = bgp_route_next(dest)) {
5424 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5425
b54892e0
DS
5426 if (table == NULL)
5427 continue;
8692c506 5428
9bcb3eef 5429 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5430 struct prefix_rd prd;
5431
5432 prd.family = AF_UNSPEC;
5433 prd.prefixlen = 64;
5434 memcpy(&prd.val, p->u.val, 8);
5435
5436 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5437 }
89c73443
DS
5438
5439 return true;
718e3744 5440}
6b0655a2 5441
228da428 5442
d62a17ae 5443struct bgp_clear_node_queue {
9bcb3eef 5444 struct bgp_dest *dest;
228da428
CC
5445};
5446
d62a17ae 5447static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5448{
d62a17ae 5449 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5450 struct bgp_dest *dest = cnq->dest;
d62a17ae 5451 struct peer *peer = wq->spec.data;
40381db7 5452 struct bgp_path_info *pi;
3103e8d2 5453 struct bgp *bgp;
9bcb3eef
DS
5454 afi_t afi = bgp_dest_table(dest)->afi;
5455 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5456
9bcb3eef 5457 assert(dest && peer);
3103e8d2 5458 bgp = peer->bgp;
d62a17ae 5459
5460 /* It is possible that we have multiple paths for a prefix from a peer
5461 * if that peer is using AddPath.
5462 */
9bcb3eef 5463 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5464 if (pi->peer != peer)
ea47320b
DL
5465 continue;
5466
5467 /* graceful restart STALE flag set. */
9af52ccf
DA
5468 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5469 && peer->nsf[afi][safi])
5470 || CHECK_FLAG(peer->af_sflags[afi][safi],
5471 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5472 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5473 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5474 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5475 else {
5476 /* If this is an EVPN route, process for
5477 * un-import. */
5478 if (safi == SAFI_EVPN)
9bcb3eef
DS
5479 bgp_evpn_unimport_route(
5480 bgp, afi, safi,
5481 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5482 /* Handle withdraw for VRF route-leaking and L3VPN */
5483 if (SAFI_UNICAST == safi
5484 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5485 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5486 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5487 bgp, pi);
960035b2 5488 }
3103e8d2 5489 if (SAFI_MPLS_VPN == safi &&
960035b2 5490 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5491 vpn_leak_to_vrf_withdraw(pi);
960035b2 5492 }
3103e8d2 5493
9bcb3eef 5494 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5495 }
ea47320b 5496 }
d62a17ae 5497 return WQ_SUCCESS;
200df115 5498}
5499
d62a17ae 5500static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5501{
d62a17ae 5502 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5503 struct bgp_dest *dest = cnq->dest;
5504 struct bgp_table *table = bgp_dest_table(dest);
228da428 5505
9bcb3eef 5506 bgp_dest_unlock_node(dest);
d62a17ae 5507 bgp_table_unlock(table);
5508 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5509}
5510
d62a17ae 5511static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5512{
d62a17ae 5513 struct peer *peer = wq->spec.data;
64e580a7 5514
d62a17ae 5515 /* Tickle FSM to start moving again */
5516 BGP_EVENT_ADD(peer, Clearing_Completed);
5517
5518 peer_unlock(peer); /* bgp_clear_route */
200df115 5519}
718e3744 5520
d62a17ae 5521static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5522{
d62a17ae 5523 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5524
5525 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5526#undef CLEAR_QUEUE_NAME_LEN
5527
0ce1ca80 5528 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5529 peer->clear_node_queue->spec.hold = 10;
5530 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5531 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5532 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5533 peer->clear_node_queue->spec.max_retries = 0;
5534
5535 /* we only 'lock' this peer reference when the queue is actually active
5536 */
5537 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5538}
5539
d62a17ae 5540static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5541 struct bgp_table *table)
65ca75e0 5542{
9bcb3eef 5543 struct bgp_dest *dest;
b6c386bb 5544 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5545
d62a17ae 5546 if (!table)
5547 table = peer->bgp->rib[afi][safi];
dc83d712 5548
d62a17ae 5549 /* If still no table => afi/safi isn't configured at all or smth. */
5550 if (!table)
5551 return;
dc83d712 5552
9bcb3eef 5553 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5554 struct bgp_path_info *pi, *next;
d62a17ae 5555 struct bgp_adj_in *ain;
5556 struct bgp_adj_in *ain_next;
5557
5558 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5559 * queued for every clearing peer, regardless of whether it is
5560 * relevant to the peer at hand.
5561 *
5562 * Overview: There are 3 different indices which need to be
5563 * scrubbed, potentially, when a peer is removed:
5564 *
5565 * 1 peer's routes visible via the RIB (ie accepted routes)
5566 * 2 peer's routes visible by the (optional) peer's adj-in index
5567 * 3 other routes visible by the peer's adj-out index
5568 *
5569 * 3 there is no hurry in scrubbing, once the struct peer is
5570 * removed from bgp->peer, we could just GC such deleted peer's
5571 * adj-outs at our leisure.
5572 *
5573 * 1 and 2 must be 'scrubbed' in some way, at least made
5574 * invisible via RIB index before peer session is allowed to be
5575 * brought back up. So one needs to know when such a 'search' is
5576 * complete.
5577 *
5578 * Ideally:
5579 *
5580 * - there'd be a single global queue or a single RIB walker
5581 * - rather than tracking which route_nodes still need to be
5582 * examined on a peer basis, we'd track which peers still
5583 * aren't cleared
5584 *
5585 * Given that our per-peer prefix-counts now should be reliable,
5586 * this may actually be achievable. It doesn't seem to be a huge
5587 * problem at this time,
5588 *
5589 * It is possible that we have multiple paths for a prefix from
5590 * a peer
5591 * if that peer is using AddPath.
5592 */
9bcb3eef 5593 ain = dest->adj_in;
d62a17ae 5594 while (ain) {
5595 ain_next = ain->next;
5596
6a840fd9 5597 if (ain->peer == peer)
9bcb3eef 5598 bgp_adj_in_remove(dest, ain);
d62a17ae 5599
5600 ain = ain_next;
5601 }
5602
9bcb3eef 5603 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5604 next = pi->next;
5605 if (pi->peer != peer)
d62a17ae 5606 continue;
5607
5608 if (force)
9bcb3eef 5609 bgp_path_info_reap(dest, pi);
d62a17ae 5610 else {
5611 struct bgp_clear_node_queue *cnq;
5612
5613 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5614 bgp_table_lock(bgp_dest_table(dest));
5615 bgp_dest_lock_node(dest);
d62a17ae 5616 cnq = XCALLOC(
5617 MTYPE_BGP_CLEAR_NODE_QUEUE,
5618 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5619 cnq->dest = dest;
d62a17ae 5620 work_queue_add(peer->clear_node_queue, cnq);
5621 break;
5622 }
5623 }
5624 }
5625 return;
5626}
5627
5628void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5629{
9bcb3eef 5630 struct bgp_dest *dest;
d62a17ae 5631 struct bgp_table *table;
5632
5633 if (peer->clear_node_queue == NULL)
5634 bgp_clear_node_queue_init(peer);
5635
5636 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5637 * Idle until it receives a Clearing_Completed event. This protects
5638 * against peers which flap faster than we can we clear, which could
5639 * lead to:
5640 *
5641 * a) race with routes from the new session being installed before
5642 * clear_route_node visits the node (to delete the route of that
5643 * peer)
5644 * b) resource exhaustion, clear_route_node likely leads to an entry
5645 * on the process_main queue. Fast-flapping could cause that queue
5646 * to grow and grow.
5647 */
5648
5649 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5650 * the unlock will happen upon work-queue completion; other wise, the
5651 * unlock happens at the end of this function.
5652 */
5653 if (!peer->clear_node_queue->thread)
5654 peer_lock(peer);
5655
5656 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5657 bgp_clear_route_table(peer, afi, safi, NULL);
5658 else
9bcb3eef
DS
5659 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5660 dest = bgp_route_next(dest)) {
5661 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5662 if (!table)
5663 continue;
5664
5665 bgp_clear_route_table(peer, afi, safi, table);
5666 }
d62a17ae 5667
5668 /* unlock if no nodes got added to the clear-node-queue. */
5669 if (!peer->clear_node_queue->thread)
5670 peer_unlock(peer);
718e3744 5671}
d62a17ae 5672
5673void bgp_clear_route_all(struct peer *peer)
718e3744 5674{
d62a17ae 5675 afi_t afi;
5676 safi_t safi;
718e3744 5677
05c7a1cc
QY
5678 FOREACH_AFI_SAFI (afi, safi)
5679 bgp_clear_route(peer, afi, safi);
65efcfce 5680
49e5a4a0 5681#ifdef ENABLE_BGP_VNC
d62a17ae 5682 rfapiProcessPeerDown(peer);
65efcfce 5683#endif
718e3744 5684}
5685
d62a17ae 5686void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5687{
d62a17ae 5688 struct bgp_table *table;
9bcb3eef 5689 struct bgp_dest *dest;
d62a17ae 5690 struct bgp_adj_in *ain;
5691 struct bgp_adj_in *ain_next;
718e3744 5692
d62a17ae 5693 table = peer->bgp->rib[afi][safi];
718e3744 5694
d62a17ae 5695 /* It is possible that we have multiple paths for a prefix from a peer
5696 * if that peer is using AddPath.
5697 */
9bcb3eef
DS
5698 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5699 ain = dest->adj_in;
43143c8f 5700
d62a17ae 5701 while (ain) {
5702 ain_next = ain->next;
43143c8f 5703
6a840fd9 5704 if (ain->peer == peer)
9bcb3eef 5705 bgp_adj_in_remove(dest, ain);
43143c8f 5706
d62a17ae 5707 ain = ain_next;
5708 }
5709 }
718e3744 5710}
93406d87 5711
1479ed2f
DA
5712/* If any of the routes from the peer have been marked with the NO_LLGR
5713 * community, either as sent by the peer, or as the result of a configured
5714 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5715 * operation of [RFC4271].
5716 */
d62a17ae 5717void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5718{
9bcb3eef 5719 struct bgp_dest *dest;
40381db7 5720 struct bgp_path_info *pi;
d62a17ae 5721 struct bgp_table *table;
5722
9af52ccf 5723 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5724 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5725 dest = bgp_route_next(dest)) {
5726 struct bgp_dest *rm;
d62a17ae 5727
5728 /* look for neighbor in tables */
9bcb3eef 5729 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5730 if (!table)
ea47320b
DL
5731 continue;
5732
5733 for (rm = bgp_table_top(table); rm;
5734 rm = bgp_route_next(rm))
9bcb3eef 5735 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5736 pi = pi->next) {
40381db7 5737 if (pi->peer != peer)
ea47320b 5738 continue;
1479ed2f
DA
5739 if (CHECK_FLAG(
5740 peer->af_sflags[afi][safi],
5741 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5742 bgp_attr_get_community(pi->attr) &&
1479ed2f 5743 !community_include(
9a706b42
DA
5744 bgp_attr_get_community(
5745 pi->attr),
1479ed2f 5746 COMMUNITY_NO_LLGR))
e3015d91 5747 continue;
40381db7 5748 if (!CHECK_FLAG(pi->flags,
1defdda8 5749 BGP_PATH_STALE))
e3015d91 5750 continue;
ea47320b 5751
641065d4
KM
5752 /*
5753 * If this is VRF leaked route
5754 * process for withdraw.
5755 */
5756 if (pi->sub_type ==
5757 BGP_ROUTE_IMPORTED &&
5758 peer->bgp->inst_type ==
5759 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5760 vpn_leak_to_vrf_withdraw(pi);
641065d4 5761
40381db7 5762 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5763 break;
5764 }
d62a17ae 5765 }
5766 } else {
9bcb3eef
DS
5767 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5768 dest = bgp_route_next(dest))
5769 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5770 pi = pi->next) {
40381db7 5771 if (pi->peer != peer)
ea47320b 5772 continue;
1479ed2f
DA
5773 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5774 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5775 bgp_attr_get_community(pi->attr) &&
5776 !community_include(
5777 bgp_attr_get_community(pi->attr),
5778 COMMUNITY_NO_LLGR))
e3015d91 5779 continue;
40381db7 5780 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5781 continue;
641065d4
KM
5782 if (safi == SAFI_UNICAST &&
5783 (peer->bgp->inst_type ==
5784 BGP_INSTANCE_TYPE_VRF ||
5785 peer->bgp->inst_type ==
5786 BGP_INSTANCE_TYPE_DEFAULT))
5787 vpn_leak_from_vrf_withdraw(
5788 bgp_get_default(), peer->bgp,
5789 pi);
5790
9bcb3eef 5791 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5792 break;
5793 }
d62a17ae 5794 }
93406d87 5795}
6b0655a2 5796
9af52ccf
DA
5797void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5798{
5799 struct bgp_dest *dest, *ndest;
5800 struct bgp_path_info *pi;
5801 struct bgp_table *table;
5802
5803 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5804 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5805 dest = bgp_route_next(dest)) {
5806 table = bgp_dest_get_bgp_table_info(dest);
5807 if (!table)
5808 continue;
5809
5810 for (ndest = bgp_table_top(table); ndest;
5811 ndest = bgp_route_next(ndest)) {
5812 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5813 pi = pi->next) {
5814 if (pi->peer != peer)
5815 continue;
5816
5817 if ((CHECK_FLAG(
5818 peer->af_sflags[afi][safi],
5819 PEER_STATUS_ENHANCED_REFRESH))
5820 && !CHECK_FLAG(pi->flags,
5821 BGP_PATH_STALE)
5822 && !CHECK_FLAG(
5823 pi->flags,
5824 BGP_PATH_UNUSEABLE)) {
5825 if (bgp_debug_neighbor_events(
5826 peer))
5827 zlog_debug(
58e111f6
DA
5828 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5829 peer,
9af52ccf
DA
5830 afi2str(afi),
5831 safi2str(safi),
5832 bgp_dest_get_prefix(
5833 ndest));
5834
5835 bgp_path_info_set_flag(
5836 ndest, pi,
5837 BGP_PATH_STALE);
5838 }
5839 }
5840 }
5841 }
5842 } else {
5843 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5844 dest = bgp_route_next(dest)) {
5845 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5846 pi = pi->next) {
5847 if (pi->peer != peer)
5848 continue;
5849
5850 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5851 PEER_STATUS_ENHANCED_REFRESH))
5852 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5853 && !CHECK_FLAG(pi->flags,
5854 BGP_PATH_UNUSEABLE)) {
5855 if (bgp_debug_neighbor_events(peer))
5856 zlog_debug(
58e111f6
DA
5857 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5858 peer, afi2str(afi),
9af52ccf
DA
5859 safi2str(safi),
5860 bgp_dest_get_prefix(
5861 dest));
5862
5863 bgp_path_info_set_flag(dest, pi,
5864 BGP_PATH_STALE);
5865 }
5866 }
5867 }
5868 }
5869}
5870
3dc339cd 5871bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5872{
e0df4c04 5873 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5874 return true;
e0df4c04 5875
9dac9fc8
DA
5876 if (peer->sort == BGP_PEER_EBGP
5877 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5878 || FILTER_LIST_OUT_NAME(filter)
5879 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5880 return true;
5881 return false;
9dac9fc8
DA
5882}
5883
3dc339cd 5884bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5885{
e0df4c04 5886 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5887 return true;
e0df4c04 5888
9dac9fc8
DA
5889 if (peer->sort == BGP_PEER_EBGP
5890 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5891 || FILTER_LIST_IN_NAME(filter)
5892 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5893 return true;
5894 return false;
9dac9fc8
DA
5895}
5896
568e10ca 5897static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5898 safi_t safi)
bb86c601 5899{
9bcb3eef 5900 struct bgp_dest *dest;
40381db7 5901 struct bgp_path_info *pi;
4b7e6066 5902 struct bgp_path_info *next;
bb86c601 5903
9bcb3eef
DS
5904 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5905 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5906 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5907
40381db7 5908 next = pi->next;
1b7bb747
CS
5909
5910 /* Unimport EVPN routes from VRFs */
5911 if (safi == SAFI_EVPN)
5912 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5913 SAFI_EVPN, p, pi);
1b7bb747 5914
40381db7
DS
5915 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5916 && pi->type == ZEBRA_ROUTE_BGP
5917 && (pi->sub_type == BGP_ROUTE_NORMAL
5918 || pi->sub_type == BGP_ROUTE_AGGREGATE
5919 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5920
d62a17ae 5921 if (bgp_fibupd_safi(safi))
b54892e0 5922 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5923 }
9514b37d 5924
9bcb3eef 5925 bgp_path_info_reap(dest, pi);
d62a17ae 5926 }
bb86c601
LB
5927}
5928
718e3744 5929/* Delete all kernel routes. */
d62a17ae 5930void bgp_cleanup_routes(struct bgp *bgp)
5931{
5932 afi_t afi;
9bcb3eef 5933 struct bgp_dest *dest;
67009e22 5934 struct bgp_table *table;
d62a17ae 5935
5936 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5937 if (afi == AFI_L2VPN)
5938 continue;
568e10ca 5939 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5940 SAFI_UNICAST);
d62a17ae 5941 /*
5942 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5943 */
5944 if (afi != AFI_L2VPN) {
5945 safi_t safi;
5946 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5947 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5948 dest = bgp_route_next(dest)) {
5949 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5950 if (table != NULL) {
5951 bgp_cleanup_table(bgp, table, safi);
5952 bgp_table_finish(&table);
9bcb3eef
DS
5953 bgp_dest_set_bgp_table_info(dest, NULL);
5954 bgp_dest_unlock_node(dest);
d62a17ae 5955 }
5956 }
5957 safi = SAFI_ENCAP;
9bcb3eef
DS
5958 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5959 dest = bgp_route_next(dest)) {
5960 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5961 if (table != NULL) {
5962 bgp_cleanup_table(bgp, table, safi);
5963 bgp_table_finish(&table);
9bcb3eef
DS
5964 bgp_dest_set_bgp_table_info(dest, NULL);
5965 bgp_dest_unlock_node(dest);
d62a17ae 5966 }
5967 }
5968 }
5969 }
9bcb3eef
DS
5970 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5971 dest = bgp_route_next(dest)) {
5972 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5973 if (table != NULL) {
5974 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5975 bgp_table_finish(&table);
9bcb3eef
DS
5976 bgp_dest_set_bgp_table_info(dest, NULL);
5977 bgp_dest_unlock_node(dest);
d62a17ae 5978 }
bb86c601 5979 }
718e3744 5980}
5981
d62a17ae 5982void bgp_reset(void)
718e3744 5983{
d62a17ae 5984 vty_reset();
5985 bgp_zclient_reset();
5986 access_list_reset();
5987 prefix_list_reset();
718e3744 5988}
6b0655a2 5989
be92fc9f 5990bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5991{
d62a17ae 5992 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5993 && CHECK_FLAG(peer->af_cap[afi][safi],
5994 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5995}
5996
718e3744 5997/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5998 value. */
d62a17ae 5999int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
6000 struct bgp_nlri *packet)
6001{
d7c0a89a
QY
6002 uint8_t *pnt;
6003 uint8_t *lim;
d62a17ae 6004 struct prefix p;
6005 int psize;
d62a17ae 6006 afi_t afi;
6007 safi_t safi;
be92fc9f 6008 bool addpath_capable;
d7c0a89a 6009 uint32_t addpath_id;
d62a17ae 6010
d62a17ae 6011 pnt = packet->nlri;
6012 lim = pnt + packet->length;
6013 afi = packet->afi;
6014 safi = packet->safi;
6015 addpath_id = 0;
be92fc9f 6016 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 6017
6018 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6019 syntactic validity. If the field is syntactically incorrect,
6020 then the Error Subcode is set to Invalid Network Field. */
6021 for (; pnt < lim; pnt += psize) {
6022 /* Clear prefix structure. */
6006b807 6023 memset(&p, 0, sizeof(p));
d62a17ae 6024
be92fc9f 6025 if (addpath_capable) {
d62a17ae 6026
6027 /* When packet overflow occurs return immediately. */
761ed665 6028 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6029 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6030
a3a850a1 6031 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6032 addpath_id = ntohl(addpath_id);
d62a17ae 6033 pnt += BGP_ADDPATH_ID_LEN;
6034 }
718e3744 6035
d62a17ae 6036 /* Fetch prefix length. */
6037 p.prefixlen = *pnt++;
6038 /* afi/safi validity already verified by caller,
6039 * bgp_update_receive */
6040 p.family = afi2family(afi);
6041
6042 /* Prefix length check. */
6043 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6044 flog_err(
e50f7cfd 6045 EC_BGP_UPDATE_RCV,
14454c9f 6046 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6047 peer->host, p.prefixlen, packet->afi);
513386b5 6048 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6049 }
6b0655a2 6050
d62a17ae 6051 /* Packet size overflow check. */
6052 psize = PSIZE(p.prefixlen);
6053
6054 /* When packet overflow occur return immediately. */
6055 if (pnt + psize > lim) {
af4c2728 6056 flog_err(
e50f7cfd 6057 EC_BGP_UPDATE_RCV,
d62a17ae 6058 "%s [Error] Update packet error (prefix length %d overflows packet)",
6059 peer->host, p.prefixlen);
513386b5 6060 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6061 }
6062
6063 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6064 * prefix for the v4 and v6 afi's and unicast/multicast */
6065 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6066 flog_err(
e50f7cfd 6067 EC_BGP_UPDATE_RCV,
d62a17ae 6068 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6069 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6070 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6071 }
6072
6073 /* Fetch prefix from NLRI packet. */
a85297a7 6074 memcpy(p.u.val, pnt, psize);
d62a17ae 6075
6076 /* Check address. */
6077 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6078 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6079 /* From RFC4271 Section 6.3:
6080 *
6081 * If a prefix in the NLRI field is semantically
6082 * incorrect
6083 * (e.g., an unexpected multicast IP address),
6084 * an error SHOULD
6085 * be logged locally, and the prefix SHOULD be
6086 * ignored.
a4d82a8a 6087 */
af4c2728 6088 flog_err(
e50f7cfd 6089 EC_BGP_UPDATE_RCV,
23d0a753
DA
6090 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6091 peer->host, &p.u.prefix4);
d62a17ae 6092 continue;
6093 }
6094 }
6095
6096 /* Check address. */
6097 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6098 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6099 flog_err(
e50f7cfd 6100 EC_BGP_UPDATE_RCV,
c0d72166
DS
6101 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6102 peer->host, &p.u.prefix6);
d62a17ae 6103
6104 continue;
6105 }
6106 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6107 flog_err(
e50f7cfd 6108 EC_BGP_UPDATE_RCV,
c0d72166
DS
6109 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6110 peer->host, &p.u.prefix6);
d62a17ae 6111
6112 continue;
6113 }
6114 }
6115
6116 /* Normal process. */
6117 if (attr)
367b458c
DS
6118 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6119 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6120 NULL, 0, 0, NULL);
d62a17ae 6121 else
bf0c6163 6122 bgp_withdraw(peer, &p, addpath_id, afi, safi,
367b458c
DS
6123 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6124 NULL, 0, NULL);
d62a17ae 6125
513386b5
DA
6126 /* Do not send BGP notification twice when maximum-prefix count
6127 * overflow. */
6128 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6129 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6130 }
6131
6132 /* Packet length consistency check. */
6133 if (pnt != lim) {
af4c2728 6134 flog_err(
e50f7cfd 6135 EC_BGP_UPDATE_RCV,
d62a17ae 6136 "%s [Error] Update packet error (prefix length mismatch with total length)",
6137 peer->host);
513386b5 6138 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6139 }
6b0655a2 6140
513386b5 6141 return BGP_NLRI_PARSE_OK;
718e3744 6142}
6143
d62a17ae 6144static struct bgp_static *bgp_static_new(void)
718e3744 6145{
d62a17ae 6146 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6147}
6148
d62a17ae 6149static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6150{
0a22ddfb 6151 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6152 route_map_counter_decrement(bgp_static->rmap.map);
6153
c1aa9e7f
PG
6154 if (bgp_static->prd_pretty)
6155 XFREE(MTYPE_BGP, bgp_static->prd_pretty);
0a22ddfb 6156 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6157 XFREE(MTYPE_BGP_STATIC, bgp_static);
6158}
6159
5f040085 6160void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6161 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6162{
9bcb3eef 6163 struct bgp_dest *dest;
40381db7 6164 struct bgp_path_info *pi;
4b7e6066 6165 struct bgp_path_info *new;
40381db7 6166 struct bgp_path_info rmap_path;
d62a17ae 6167 struct attr attr;
6168 struct attr *attr_new;
b68885f9 6169 route_map_result_t ret;
49e5a4a0 6170#ifdef ENABLE_BGP_VNC
d62a17ae 6171 int vnc_implicit_withdraw = 0;
65efcfce 6172#endif
fee0f4c6 6173
d62a17ae 6174 assert(bgp_static);
dd8103a9 6175
9bcb3eef 6176 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6177
0f05ea43 6178 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6179
d62a17ae 6180 attr.nexthop = bgp_static->igpnexthop;
6181 attr.med = bgp_static->igpmetric;
6182 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6183
7226bc40
TA
6184 if (afi == AFI_IP)
6185 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6186
97a52c82
DA
6187 if (bgp_static->igpmetric)
6188 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6189
d62a17ae 6190 if (bgp_static->atomic)
6191 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6192
d62a17ae 6193 /* Store label index, if required. */
6194 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6195 attr.label_index = bgp_static->label_index;
6196 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6197 }
718e3744 6198
d62a17ae 6199 /* Apply route-map. */
6200 if (bgp_static->rmap.name) {
6201 struct attr attr_tmp = attr;
80ced710 6202
6006b807 6203 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6204 rmap_path.peer = bgp->peer_self;
6205 rmap_path.attr = &attr_tmp;
fee0f4c6 6206
d62a17ae 6207 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6208
1782514f 6209 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6210
d62a17ae 6211 bgp->peer_self->rmap_type = 0;
718e3744 6212
d62a17ae 6213 if (ret == RMAP_DENYMATCH) {
6214 /* Free uninterned attribute. */
6215 bgp_attr_flush(&attr_tmp);
718e3744 6216
d62a17ae 6217 /* Unintern original. */
6218 aspath_unintern(&attr.aspath);
6219 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6220 bgp_dest_unlock_node(dest);
d62a17ae 6221 return;
6222 }
7f323236 6223
637e5ba4 6224 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6225 bgp_attr_add_gshut_community(&attr_tmp);
6226
d62a17ae 6227 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6228 } else {
6229
637e5ba4 6230 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6231 bgp_attr_add_gshut_community(&attr);
6232
d62a17ae 6233 attr_new = bgp_attr_intern(&attr);
7f323236 6234 }
718e3744 6235
9bcb3eef 6236 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6237 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6238 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6239 break;
6240
40381db7
DS
6241 if (pi) {
6242 if (attrhash_cmp(pi->attr, attr_new)
6243 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6244 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6245 bgp_dest_unlock_node(dest);
d62a17ae 6246 bgp_attr_unintern(&attr_new);
6247 aspath_unintern(&attr.aspath);
6248 return;
6249 } else {
6250 /* The attribute is changed. */
9bcb3eef 6251 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6252
6253 /* Rewrite BGP route information. */
40381db7 6254 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6255 bgp_path_info_restore(dest, pi);
d62a17ae 6256 else
40381db7 6257 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6258#ifdef ENABLE_BGP_VNC
d62a17ae 6259 if ((afi == AFI_IP || afi == AFI_IP6)
6260 && (safi == SAFI_UNICAST)) {
40381db7 6261 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6262 /*
6263 * Implicit withdraw case.
40381db7 6264 * We have to do this before pi is
d62a17ae 6265 * changed
6266 */
6267 ++vnc_implicit_withdraw;
40381db7 6268 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6269 vnc_import_bgp_exterior_del_route(
40381db7 6270 bgp, p, pi);
d62a17ae 6271 }
6272 }
65efcfce 6273#endif
40381db7
DS
6274 bgp_attr_unintern(&pi->attr);
6275 pi->attr = attr_new;
083ec940 6276 pi->uptime = monotime(NULL);
49e5a4a0 6277#ifdef ENABLE_BGP_VNC
d62a17ae 6278 if ((afi == AFI_IP || afi == AFI_IP6)
6279 && (safi == SAFI_UNICAST)) {
6280 if (vnc_implicit_withdraw) {
40381db7 6281 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6282 vnc_import_bgp_exterior_add_route(
40381db7 6283 bgp, p, pi);
d62a17ae 6284 }
6285 }
65efcfce 6286#endif
718e3744 6287
d62a17ae 6288 /* Nexthop reachability check. */
892fedb6 6289 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6290 && (safi == SAFI_UNICAST
6291 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6292
6293 struct bgp *bgp_nexthop = bgp;
6294
40381db7
DS
6295 if (pi->extra && pi->extra->bgp_orig)
6296 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6297
6298 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6299 afi, safi, pi, NULL,
654a5978 6300 0, p))
9bcb3eef 6301 bgp_path_info_set_flag(dest, pi,
18ee8310 6302 BGP_PATH_VALID);
d62a17ae 6303 else {
6304 if (BGP_DEBUG(nht, NHT)) {
6305 char buf1[INET6_ADDRSTRLEN];
6306 inet_ntop(p->family,
6307 &p->u.prefix, buf1,
07380148 6308 sizeof(buf1));
d62a17ae 6309 zlog_debug(
6310 "%s(%s): Route not in table, not advertising",
15569c58 6311 __func__, buf1);
d62a17ae 6312 }
18ee8310 6313 bgp_path_info_unset_flag(
9bcb3eef 6314 dest, pi, BGP_PATH_VALID);
d62a17ae 6315 }
6316 } else {
6317 /* Delete the NHT structure if any, if we're
6318 * toggling between
6319 * enabling/disabling import check. We
6320 * deregister the route
6321 * from NHT to avoid overloading NHT and the
6322 * process interaction
6323 */
40381db7 6324 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6325 bgp_path_info_set_flag(dest, pi,
6326 BGP_PATH_VALID);
d62a17ae 6327 }
6328 /* Process change. */
40381db7 6329 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6330 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6331
6332 if (SAFI_UNICAST == safi
6333 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6334 || bgp->inst_type
6335 == BGP_INSTANCE_TYPE_DEFAULT)) {
6336 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6337 pi);
ddb5b488
PZ
6338 }
6339
9bcb3eef 6340 bgp_dest_unlock_node(dest);
d62a17ae 6341 aspath_unintern(&attr.aspath);
6342 return;
6343 }
718e3744 6344 }
718e3744 6345
d62a17ae 6346 /* Make new BGP info. */
6347 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6348 attr_new, dest);
d62a17ae 6349 /* Nexthop reachability check. */
892fedb6 6350 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6351 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6352 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6353 p))
9bcb3eef 6354 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6355 else {
6356 if (BGP_DEBUG(nht, NHT)) {
6357 char buf1[INET6_ADDRSTRLEN];
07380148 6358
d62a17ae 6359 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6360 sizeof(buf1));
d62a17ae 6361 zlog_debug(
6362 "%s(%s): Route not in table, not advertising",
15569c58 6363 __func__, buf1);
d62a17ae 6364 }
9bcb3eef 6365 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6366 }
6367 } else {
6368 /* Delete the NHT structure if any, if we're toggling between
6369 * enabling/disabling import check. We deregister the route
6370 * from NHT to avoid overloading NHT and the process interaction
6371 */
6372 bgp_unlink_nexthop(new);
6373
9bcb3eef 6374 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6375 }
078430f6 6376
d62a17ae 6377 /* Aggregate address increment. */
6378 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6379
d62a17ae 6380 /* Register new BGP information. */
9bcb3eef 6381 bgp_path_info_add(dest, new);
718e3744 6382
d62a17ae 6383 /* route_node_get lock */
9bcb3eef 6384 bgp_dest_unlock_node(dest);
d62a17ae 6385
6386 /* Process change. */
9bcb3eef 6387 bgp_process(bgp, dest, afi, safi);
d62a17ae 6388
ddb5b488
PZ
6389 if (SAFI_UNICAST == safi
6390 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6391 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6392 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6393 }
6394
d62a17ae 6395 /* Unintern original. */
6396 aspath_unintern(&attr.aspath);
718e3744 6397}
6398
5f040085 6399void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6400 safi_t safi)
718e3744 6401{
9bcb3eef 6402 struct bgp_dest *dest;
40381db7 6403 struct bgp_path_info *pi;
718e3744 6404
9bcb3eef 6405 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6406
d62a17ae 6407 /* Check selected route and self inserted route. */
9bcb3eef 6408 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6409 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6410 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6411 break;
6412
6413 /* Withdraw static BGP route from routing table. */
40381db7 6414 if (pi) {
ddb5b488
PZ
6415 if (SAFI_UNICAST == safi
6416 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6417 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6418 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6419 }
40381db7
DS
6420 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6421 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6422 bgp_path_info_delete(dest, pi);
6423 bgp_process(bgp, dest, afi, safi);
d62a17ae 6424 }
718e3744 6425
d62a17ae 6426 /* Unlock bgp_node_lookup. */
9bcb3eef 6427 bgp_dest_unlock_node(dest);
718e3744 6428}
6429
137446f9
LB
6430/*
6431 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6432 */
5f040085 6433static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6434 afi_t afi, safi_t safi,
6435 struct prefix_rd *prd)
718e3744 6436{
9bcb3eef 6437 struct bgp_dest *dest;
40381db7 6438 struct bgp_path_info *pi;
718e3744 6439
9bcb3eef 6440 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6441
d62a17ae 6442 /* Check selected route and self inserted route. */
9bcb3eef 6443 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6444 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6445 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6446 break;
718e3744 6447
d62a17ae 6448 /* Withdraw static BGP route from routing table. */
40381db7 6449 if (pi) {
49e5a4a0 6450#ifdef ENABLE_BGP_VNC
d62a17ae 6451 rfapiProcessWithdraw(
40381db7 6452 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6453 1); /* Kill, since it is an administrative change */
65efcfce 6454#endif
ddb5b488
PZ
6455 if (SAFI_MPLS_VPN == safi
6456 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6457 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6458 }
40381db7 6459 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6460 bgp_path_info_delete(dest, pi);
6461 bgp_process(bgp, dest, afi, safi);
d62a17ae 6462 }
718e3744 6463
d62a17ae 6464 /* Unlock bgp_node_lookup. */
9bcb3eef 6465 bgp_dest_unlock_node(dest);
718e3744 6466}
6467
5f040085 6468static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6469 struct bgp_static *bgp_static, afi_t afi,
6470 safi_t safi)
137446f9 6471{
9bcb3eef 6472 struct bgp_dest *dest;
4b7e6066 6473 struct bgp_path_info *new;
d62a17ae 6474 struct attr *attr_new;
6475 struct attr attr = {0};
40381db7 6476 struct bgp_path_info *pi;
49e5a4a0 6477#ifdef ENABLE_BGP_VNC
d62a17ae 6478 mpls_label_t label = 0;
65efcfce 6479#endif
d7c0a89a 6480 uint32_t num_labels = 0;
137446f9 6481
d62a17ae 6482 assert(bgp_static);
137446f9 6483
b57ba6d2
MK
6484 if (bgp_static->label != MPLS_INVALID_LABEL)
6485 num_labels = 1;
9bcb3eef
DS
6486 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6487 &bgp_static->prd);
137446f9 6488
0f05ea43 6489 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6490
d62a17ae 6491 attr.nexthop = bgp_static->igpnexthop;
6492 attr.med = bgp_static->igpmetric;
6493 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6494
d62a17ae 6495 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6496 || (safi == SAFI_ENCAP)) {
6497 if (afi == AFI_IP) {
6498 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6499 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6500 }
6501 }
6502 if (afi == AFI_L2VPN) {
b04c1e99
IR
6503 if (bgp_static->gatewayIp.family == AF_INET) {
6504 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6505 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6506 &bgp_static->gatewayIp.u.prefix4,
6507 IPV4_MAX_BYTELEN);
b04c1e99
IR
6508 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6509 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6510 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6511 &bgp_static->gatewayIp.u.prefix6,
6512 IPV6_MAX_BYTELEN);
b04c1e99 6513 }
0a50c248 6514 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6515 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6516 struct bgp_encap_type_vxlan bet;
6006b807 6517 memset(&bet, 0, sizeof(bet));
3714a385 6518 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6519 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6520 }
6521 if (bgp_static->router_mac) {
6522 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6523 }
6524 }
6525 /* Apply route-map. */
6526 if (bgp_static->rmap.name) {
6527 struct attr attr_tmp = attr;
40381db7 6528 struct bgp_path_info rmap_path;
b68885f9 6529 route_map_result_t ret;
137446f9 6530
40381db7
DS
6531 rmap_path.peer = bgp->peer_self;
6532 rmap_path.attr = &attr_tmp;
137446f9 6533
d62a17ae 6534 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6535
1782514f 6536 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6537
d62a17ae 6538 bgp->peer_self->rmap_type = 0;
137446f9 6539
d62a17ae 6540 if (ret == RMAP_DENYMATCH) {
6541 /* Free uninterned attribute. */
6542 bgp_attr_flush(&attr_tmp);
137446f9 6543
d62a17ae 6544 /* Unintern original. */
6545 aspath_unintern(&attr.aspath);
6546 bgp_static_withdraw_safi(bgp, p, afi, safi,
6547 &bgp_static->prd);
bbc52106 6548 bgp_dest_unlock_node(dest);
d62a17ae 6549 return;
6550 }
137446f9 6551
d62a17ae 6552 attr_new = bgp_attr_intern(&attr_tmp);
6553 } else {
6554 attr_new = bgp_attr_intern(&attr);
6555 }
137446f9 6556
9bcb3eef 6557 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6558 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6559 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6560 break;
6561
40381db7 6562 if (pi) {
40381db7 6563 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6564 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6565 bgp_dest_unlock_node(dest);
d62a17ae 6566 bgp_attr_unintern(&attr_new);
6567 aspath_unintern(&attr.aspath);
6568 return;
6569 } else {
6570 /* The attribute is changed. */
9bcb3eef 6571 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6572
6573 /* Rewrite BGP route information. */
40381db7 6574 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6575 bgp_path_info_restore(dest, pi);
d62a17ae 6576 else
40381db7
DS
6577 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6578 bgp_attr_unintern(&pi->attr);
6579 pi->attr = attr_new;
083ec940 6580 pi->uptime = monotime(NULL);
49e5a4a0 6581#ifdef ENABLE_BGP_VNC
40381db7
DS
6582 if (pi->extra)
6583 label = decode_label(&pi->extra->label[0]);
65efcfce 6584#endif
137446f9 6585
d62a17ae 6586 /* Process change. */
40381db7 6587 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6588 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6589
6590 if (SAFI_MPLS_VPN == safi
6591 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6592 vpn_leak_to_vrf_update(bgp, pi,
6593 &bgp_static->prd);
ddb5b488 6594 }
49e5a4a0 6595#ifdef ENABLE_BGP_VNC
40381db7
DS
6596 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6597 pi->attr, afi, safi, pi->type,
6598 pi->sub_type, &label);
65efcfce 6599#endif
9bcb3eef 6600 bgp_dest_unlock_node(dest);
d62a17ae 6601 aspath_unintern(&attr.aspath);
6602 return;
6603 }
6604 }
137446f9
LB
6605
6606
d62a17ae 6607 /* Make new BGP info. */
6608 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6609 attr_new, dest);
1defdda8 6610 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6611 bgp_path_info_extra_get(new);
b57ba6d2
MK
6612 if (num_labels) {
6613 new->extra->label[0] = bgp_static->label;
6614 new->extra->num_labels = num_labels;
6615 }
49e5a4a0 6616#ifdef ENABLE_BGP_VNC
d62a17ae 6617 label = decode_label(&bgp_static->label);
65efcfce 6618#endif
137446f9 6619
d62a17ae 6620 /* Aggregate address increment. */
6621 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6622
d62a17ae 6623 /* Register new BGP information. */
9bcb3eef 6624 bgp_path_info_add(dest, new);
d62a17ae 6625 /* route_node_get lock */
9bcb3eef 6626 bgp_dest_unlock_node(dest);
137446f9 6627
d62a17ae 6628 /* Process change. */
9bcb3eef 6629 bgp_process(bgp, dest, afi, safi);
137446f9 6630
ddb5b488
PZ
6631 if (SAFI_MPLS_VPN == safi
6632 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6633 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6634 }
49e5a4a0 6635#ifdef ENABLE_BGP_VNC
d62a17ae 6636 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6637 safi, new->type, new->sub_type, &label);
65efcfce
LB
6638#endif
6639
d62a17ae 6640 /* Unintern original. */
6641 aspath_unintern(&attr.aspath);
137446f9
LB
6642}
6643
718e3744 6644/* Configure static BGP network. When user don't run zebra, static
6645 route should be installed as valid. */
585f1adc
IR
6646static int bgp_static_set(struct vty *vty, const char *negate,
6647 const char *ip_str, afi_t afi, safi_t safi,
6648 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6649{
585f1adc
IR
6650 VTY_DECLVAR_CONTEXT(bgp, bgp);
6651 int ret;
d62a17ae 6652 struct prefix p;
6653 struct bgp_static *bgp_static;
9bcb3eef 6654 struct bgp_dest *dest;
d7c0a89a 6655 uint8_t need_update = 0;
d62a17ae 6656
585f1adc
IR
6657 /* Convert IP prefix string to struct prefix. */
6658 ret = str2prefix(ip_str, &p);
6659 if (!ret) {
6660 vty_out(vty, "%% Malformed prefix\n");
6661 return CMD_WARNING_CONFIG_FAILED;
6662 }
6663 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6664 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6665 return CMD_WARNING_CONFIG_FAILED;
6666 }
6667
d62a17ae 6668 apply_mask(&p);
718e3744 6669
e2a86ad9 6670 if (negate) {
718e3744 6671
e2a86ad9 6672 /* Set BGP static route configuration. */
9bcb3eef 6673 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6674
9bcb3eef 6675 if (!dest) {
585f1adc
IR
6676 vty_out(vty, "%% Can't find static route specified\n");
6677 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6678 }
6679
9bcb3eef 6680 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6681
e2a86ad9
DS
6682 if ((label_index != BGP_INVALID_LABEL_INDEX)
6683 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6684 vty_out(vty,
6685 "%% label-index doesn't match static route\n");
70d9b134 6686 bgp_dest_unlock_node(dest);
585f1adc 6687 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6688 }
d62a17ae 6689
e2a86ad9
DS
6690 if ((rmap && bgp_static->rmap.name)
6691 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6692 vty_out(vty,
6693 "%% route-map name doesn't match static route\n");
70d9b134 6694 bgp_dest_unlock_node(dest);
585f1adc 6695 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6696 }
718e3744 6697
e2a86ad9
DS
6698 /* Update BGP RIB. */
6699 if (!bgp_static->backdoor)
6700 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6701
e2a86ad9
DS
6702 /* Clear configuration. */
6703 bgp_static_free(bgp_static);
9bcb3eef
DS
6704 bgp_dest_set_bgp_static_info(dest, NULL);
6705 bgp_dest_unlock_node(dest);
6706 bgp_dest_unlock_node(dest);
e2a86ad9 6707 } else {
718e3744 6708
e2a86ad9 6709 /* Set BGP static route configuration. */
9bcb3eef
DS
6710 dest = bgp_node_get(bgp->route[afi][safi], &p);
6711 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6712 if (bgp_static) {
e2a86ad9 6713 /* Configuration change. */
e2a86ad9
DS
6714 /* Label index cannot be changed. */
6715 if (bgp_static->label_index != label_index) {
585f1adc 6716 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6717 bgp_dest_unlock_node(dest);
585f1adc 6718 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6719 }
d62a17ae 6720
e2a86ad9 6721 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6722 if (bgp_static->valid
6723 && bgp_static->backdoor != backdoor)
e2a86ad9 6724 need_update = 1;
718e3744 6725
e2a86ad9 6726 bgp_static->backdoor = backdoor;
718e3744 6727
e2a86ad9 6728 if (rmap) {
0a22ddfb
QY
6729 XFREE(MTYPE_ROUTE_MAP_NAME,
6730 bgp_static->rmap.name);
b4897fa5 6731 route_map_counter_decrement(
6732 bgp_static->rmap.map);
e2a86ad9
DS
6733 bgp_static->rmap.name =
6734 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6735 bgp_static->rmap.map =
6736 route_map_lookup_by_name(rmap);
b4897fa5 6737 route_map_counter_increment(
6738 bgp_static->rmap.map);
e2a86ad9 6739 } else {
0a22ddfb
QY
6740 XFREE(MTYPE_ROUTE_MAP_NAME,
6741 bgp_static->rmap.name);
b4897fa5 6742 route_map_counter_decrement(
6743 bgp_static->rmap.map);
e2a86ad9
DS
6744 bgp_static->rmap.map = NULL;
6745 bgp_static->valid = 0;
6746 }
9bcb3eef 6747 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6748 } else {
6749 /* New configuration. */
6750 bgp_static = bgp_static_new();
6751 bgp_static->backdoor = backdoor;
6752 bgp_static->valid = 0;
6753 bgp_static->igpmetric = 0;
975a328e 6754 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6755 bgp_static->label_index = label_index;
718e3744 6756
e2a86ad9 6757 if (rmap) {
0a22ddfb
QY
6758 XFREE(MTYPE_ROUTE_MAP_NAME,
6759 bgp_static->rmap.name);
b4897fa5 6760 route_map_counter_decrement(
6761 bgp_static->rmap.map);
e2a86ad9
DS
6762 bgp_static->rmap.name =
6763 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6764 bgp_static->rmap.map =
6765 route_map_lookup_by_name(rmap);
b4897fa5 6766 route_map_counter_increment(
6767 bgp_static->rmap.map);
e2a86ad9 6768 }
9bcb3eef 6769 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6770 }
d62a17ae 6771
e2a86ad9
DS
6772 bgp_static->valid = 1;
6773 if (need_update)
6774 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6775
e2a86ad9
DS
6776 if (!bgp_static->backdoor)
6777 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6778 }
d62a17ae 6779
585f1adc 6780 return CMD_SUCCESS;
d62a17ae 6781}
6782
6783void bgp_static_add(struct bgp *bgp)
6784{
6785 afi_t afi;
6786 safi_t safi;
9bcb3eef
DS
6787 struct bgp_dest *dest;
6788 struct bgp_dest *rm;
d62a17ae 6789 struct bgp_table *table;
6790 struct bgp_static *bgp_static;
6791
47fc6261 6792 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6793 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6794 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6795 dest = bgp_route_next(dest)) {
6796 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6797 continue;
ea47320b 6798
05c7a1cc
QY
6799 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6800 || (safi == SAFI_EVPN)) {
9bcb3eef 6801 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6802
6803 for (rm = bgp_table_top(table); rm;
6804 rm = bgp_route_next(rm)) {
a78beeb5 6805 bgp_static =
9bcb3eef 6806 bgp_dest_get_bgp_static_info(
5a8ba9fc 6807 rm);
9bcb3eef
DS
6808 bgp_static_update_safi(
6809 bgp, bgp_dest_get_prefix(rm),
6810 bgp_static, afi, safi);
d62a17ae 6811 }
05c7a1cc 6812 } else {
5a8ba9fc 6813 bgp_static_update(
9bcb3eef
DS
6814 bgp, bgp_dest_get_prefix(dest),
6815 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6816 safi);
ea47320b 6817 }
05c7a1cc 6818 }
47fc6261 6819 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6820}
6821
718e3744 6822/* Called from bgp_delete(). Delete all static routes from the BGP
6823 instance. */
d62a17ae 6824void bgp_static_delete(struct bgp *bgp)
6825{
6826 afi_t afi;
6827 safi_t safi;
9bcb3eef
DS
6828 struct bgp_dest *dest;
6829 struct bgp_dest *rm;
d62a17ae 6830 struct bgp_table *table;
6831 struct bgp_static *bgp_static;
6832
05c7a1cc 6833 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6834 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6835 dest = bgp_route_next(dest)) {
6836 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6837 continue;
ea47320b 6838
05c7a1cc
QY
6839 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6840 || (safi == SAFI_EVPN)) {
9bcb3eef 6841 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6842
6843 for (rm = bgp_table_top(table); rm;
6844 rm = bgp_route_next(rm)) {
a78beeb5 6845 bgp_static =
9bcb3eef 6846 bgp_dest_get_bgp_static_info(
5a8ba9fc 6847 rm);
c7d14ba6
PG
6848 if (!bgp_static)
6849 continue;
6850
05c7a1cc 6851 bgp_static_withdraw_safi(
9bcb3eef 6852 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6853 AFI_IP, safi,
6854 (struct prefix_rd *)
9bcb3eef
DS
6855 bgp_dest_get_prefix(
6856 dest));
ea47320b 6857 bgp_static_free(bgp_static);
811c6797 6858 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6859 NULL);
811c6797 6860 bgp_dest_unlock_node(rm);
d62a17ae 6861 }
05c7a1cc 6862 } else {
9bcb3eef 6863 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6864 bgp_static_withdraw(bgp,
9bcb3eef 6865 bgp_dest_get_prefix(dest),
b54892e0 6866 afi, safi);
05c7a1cc 6867 bgp_static_free(bgp_static);
9bcb3eef
DS
6868 bgp_dest_set_bgp_static_info(dest, NULL);
6869 bgp_dest_unlock_node(dest);
ea47320b 6870 }
05c7a1cc 6871 }
d62a17ae 6872}
6873
6874void bgp_static_redo_import_check(struct bgp *bgp)
6875{
6876 afi_t afi;
6877 safi_t safi;
9bcb3eef
DS
6878 struct bgp_dest *dest;
6879 struct bgp_dest *rm;
d62a17ae 6880 struct bgp_table *table;
6881 struct bgp_static *bgp_static;
6882
6883 /* Use this flag to force reprocessing of the route */
892fedb6 6884 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6885 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6886 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6887 dest = bgp_route_next(dest)) {
6888 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6889 continue;
ea47320b 6890
05c7a1cc
QY
6891 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6892 || (safi == SAFI_EVPN)) {
9bcb3eef 6893 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6894
6895 for (rm = bgp_table_top(table); rm;
6896 rm = bgp_route_next(rm)) {
a78beeb5 6897 bgp_static =
9bcb3eef 6898 bgp_dest_get_bgp_static_info(
5a8ba9fc 6899 rm);
9bcb3eef
DS
6900 bgp_static_update_safi(
6901 bgp, bgp_dest_get_prefix(rm),
6902 bgp_static, afi, safi);
d62a17ae 6903 }
05c7a1cc 6904 } else {
9bcb3eef
DS
6905 bgp_static = bgp_dest_get_bgp_static_info(dest);
6906 bgp_static_update(bgp,
6907 bgp_dest_get_prefix(dest),
6908 bgp_static, afi, safi);
ea47320b 6909 }
05c7a1cc
QY
6910 }
6911 }
892fedb6 6912 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6913}
6914
6915static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6916 safi_t safi)
6917{
6918 struct bgp_table *table;
9bcb3eef 6919 struct bgp_dest *dest;
40381db7 6920 struct bgp_path_info *pi;
d62a17ae 6921
dfb6fd1d
NT
6922 /* Do not install the aggregate route if BGP is in the
6923 * process of termination.
6924 */
892fedb6
DA
6925 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6926 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6927 return;
6928
d62a17ae 6929 table = bgp->rib[afi][safi];
9bcb3eef
DS
6930 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6931 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6932 if (pi->peer == bgp->peer_self
6933 && ((pi->type == ZEBRA_ROUTE_BGP
6934 && pi->sub_type == BGP_ROUTE_STATIC)
6935 || (pi->type != ZEBRA_ROUTE_BGP
6936 && pi->sub_type
d62a17ae 6937 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6938 bgp_aggregate_decrement(
6939 bgp, bgp_dest_get_prefix(dest), pi, afi,
6940 safi);
40381db7 6941 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6942 bgp_path_info_delete(dest, pi);
6943 bgp_process(bgp, dest, afi, safi);
d62a17ae 6944 }
6945 }
6946 }
ad4cbda1 6947}
6948
6949/*
6950 * Purge all networks and redistributed routes from routing table.
6951 * Invoked upon the instance going down.
6952 */
d62a17ae 6953void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6954{
d62a17ae 6955 afi_t afi;
6956 safi_t safi;
ad4cbda1 6957
05c7a1cc
QY
6958 FOREACH_AFI_SAFI (afi, safi)
6959 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6960}
6961
137446f9
LB
6962/*
6963 * gpz 110624
6964 * Currently this is used to set static routes for VPN and ENCAP.
6965 * I think it can probably be factored with bgp_static_set.
6966 */
d62a17ae 6967int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6968 const char *ip_str, const char *rd_str,
6969 const char *label_str, const char *rmap_str,
6970 int evpn_type, const char *esi, const char *gwip,
6971 const char *ethtag, const char *routermac)
6972{
6973 VTY_DECLVAR_CONTEXT(bgp, bgp);
6974 int ret;
6975 struct prefix p;
6976 struct prefix_rd prd;
9bcb3eef
DS
6977 struct bgp_dest *pdest;
6978 struct bgp_dest *dest;
d62a17ae 6979 struct bgp_table *table;
6980 struct bgp_static *bgp_static;
6981 mpls_label_t label = MPLS_INVALID_LABEL;
6982 struct prefix gw_ip;
6983
6984 /* validate ip prefix */
6985 ret = str2prefix(ip_str, &p);
6986 if (!ret) {
6987 vty_out(vty, "%% Malformed prefix\n");
6988 return CMD_WARNING_CONFIG_FAILED;
6989 }
6990 apply_mask(&p);
6991 if ((afi == AFI_L2VPN)
6992 && (bgp_build_evpn_prefix(evpn_type,
6993 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6994 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6995 return CMD_WARNING_CONFIG_FAILED;
6996 }
718e3744 6997
d62a17ae 6998 ret = str2prefix_rd(rd_str, &prd);
6999 if (!ret) {
7000 vty_out(vty, "%% Malformed rd\n");
7001 return CMD_WARNING_CONFIG_FAILED;
7002 }
718e3744 7003
d62a17ae 7004 if (label_str) {
7005 unsigned long label_val;
7006 label_val = strtoul(label_str, NULL, 10);
7007 encode_label(label_val, &label);
7008 }
9bedbb1e 7009
d62a17ae 7010 if (safi == SAFI_EVPN) {
7011 if (esi && str2esi(esi, NULL) == 0) {
7012 vty_out(vty, "%% Malformed ESI\n");
7013 return CMD_WARNING_CONFIG_FAILED;
7014 }
7015 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7016 vty_out(vty, "%% Malformed Router MAC\n");
7017 return CMD_WARNING_CONFIG_FAILED;
7018 }
7019 if (gwip) {
6006b807 7020 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7021 ret = str2prefix(gwip, &gw_ip);
7022 if (!ret) {
7023 vty_out(vty, "%% Malformed GatewayIp\n");
7024 return CMD_WARNING_CONFIG_FAILED;
7025 }
7026 if ((gw_ip.family == AF_INET
3714a385 7027 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7028 (struct prefix_evpn *)&p))
7029 || (gw_ip.family == AF_INET6
3714a385 7030 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7031 (struct prefix_evpn *)&p))) {
7032 vty_out(vty,
7033 "%% GatewayIp family differs with IP prefix\n");
7034 return CMD_WARNING_CONFIG_FAILED;
7035 }
7036 }
7037 }
9bcb3eef
DS
7038 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7039 if (!bgp_dest_has_bgp_path_info_data(pdest))
7040 bgp_dest_set_bgp_table_info(pdest,
67009e22 7041 bgp_table_init(bgp, afi, safi));
9bcb3eef 7042 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7043
9bcb3eef 7044 dest = bgp_node_get(table, &p);
d62a17ae 7045
9bcb3eef 7046 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7047 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7048 bgp_dest_unlock_node(dest);
d62a17ae 7049 } else {
7050 /* New configuration. */
7051 bgp_static = bgp_static_new();
7052 bgp_static->backdoor = 0;
7053 bgp_static->valid = 0;
7054 bgp_static->igpmetric = 0;
975a328e 7055 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7056 bgp_static->label = label;
7057 bgp_static->prd = prd;
7058
852f96eb
DS
7059 bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
7060
d62a17ae 7061 if (rmap_str) {
0a22ddfb 7062 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7063 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7064 bgp_static->rmap.name =
7065 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7066 bgp_static->rmap.map =
7067 route_map_lookup_by_name(rmap_str);
b4897fa5 7068 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7069 }
718e3744 7070
d62a17ae 7071 if (safi == SAFI_EVPN) {
7072 if (esi) {
7073 bgp_static->eth_s_id =
7074 XCALLOC(MTYPE_ATTR,
0a50c248 7075 sizeof(esi_t));
d62a17ae 7076 str2esi(esi, bgp_static->eth_s_id);
7077 }
7078 if (routermac) {
7079 bgp_static->router_mac =
28328ea9 7080 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7081 (void)prefix_str2mac(routermac,
7082 bgp_static->router_mac);
d62a17ae 7083 }
7084 if (gwip)
7085 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7086 }
9bcb3eef 7087 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7088
d62a17ae 7089 bgp_static->valid = 1;
7090 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7091 }
718e3744 7092
d62a17ae 7093 return CMD_SUCCESS;
718e3744 7094}
7095
7096/* Configure static BGP network. */
d62a17ae 7097int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7098 const char *ip_str, const char *rd_str,
7099 const char *label_str, int evpn_type, const char *esi,
7100 const char *gwip, const char *ethtag)
7101{
7102 VTY_DECLVAR_CONTEXT(bgp, bgp);
7103 int ret;
7104 struct prefix p;
7105 struct prefix_rd prd;
9bcb3eef
DS
7106 struct bgp_dest *pdest;
7107 struct bgp_dest *dest;
d62a17ae 7108 struct bgp_table *table;
7109 struct bgp_static *bgp_static;
7110 mpls_label_t label = MPLS_INVALID_LABEL;
7111
7112 /* Convert IP prefix string to struct prefix. */
7113 ret = str2prefix(ip_str, &p);
7114 if (!ret) {
7115 vty_out(vty, "%% Malformed prefix\n");
7116 return CMD_WARNING_CONFIG_FAILED;
7117 }
7118 apply_mask(&p);
7119 if ((afi == AFI_L2VPN)
7120 && (bgp_build_evpn_prefix(evpn_type,
7121 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7122 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7123 return CMD_WARNING_CONFIG_FAILED;
7124 }
7125 ret = str2prefix_rd(rd_str, &prd);
7126 if (!ret) {
7127 vty_out(vty, "%% Malformed rd\n");
7128 return CMD_WARNING_CONFIG_FAILED;
7129 }
718e3744 7130
d62a17ae 7131 if (label_str) {
7132 unsigned long label_val;
7133 label_val = strtoul(label_str, NULL, 10);
7134 encode_label(label_val, &label);
7135 }
718e3744 7136
9bcb3eef
DS
7137 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7138 if (!bgp_dest_has_bgp_path_info_data(pdest))
7139 bgp_dest_set_bgp_table_info(pdest,
67009e22 7140 bgp_table_init(bgp, afi, safi));
d62a17ae 7141 else
9bcb3eef
DS
7142 bgp_dest_unlock_node(pdest);
7143 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7144
9bcb3eef 7145 dest = bgp_node_lookup(table, &p);
6b0655a2 7146
9bcb3eef 7147 if (dest) {
d62a17ae 7148 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7149
9bcb3eef 7150 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7151 bgp_static_free(bgp_static);
9bcb3eef
DS
7152 bgp_dest_set_bgp_static_info(dest, NULL);
7153 bgp_dest_unlock_node(dest);
7154 bgp_dest_unlock_node(dest);
d62a17ae 7155 } else
7156 vty_out(vty, "%% Can't find the route\n");
7157
7158 return CMD_SUCCESS;
7159}
7160
7161static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7162 const char *rmap_name)
7163{
7164 VTY_DECLVAR_CONTEXT(bgp, bgp);
7165 struct bgp_rmap *rmap;
7166
7167 rmap = &bgp->table_map[afi][safi];
7168 if (rmap_name) {
0a22ddfb 7169 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7170 route_map_counter_decrement(rmap->map);
d62a17ae 7171 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7172 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7173 route_map_counter_increment(rmap->map);
d62a17ae 7174 } else {
0a22ddfb 7175 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7176 route_map_counter_decrement(rmap->map);
d62a17ae 7177 rmap->map = NULL;
7178 }
73ac8160 7179
d62a17ae 7180 if (bgp_fibupd_safi(safi))
7181 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7182
d62a17ae 7183 return CMD_SUCCESS;
73ac8160
DS
7184}
7185
d62a17ae 7186static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7187 const char *rmap_name)
73ac8160 7188{
d62a17ae 7189 VTY_DECLVAR_CONTEXT(bgp, bgp);
7190 struct bgp_rmap *rmap;
73ac8160 7191
d62a17ae 7192 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7193 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7194 route_map_counter_decrement(rmap->map);
d62a17ae 7195 rmap->map = NULL;
73ac8160 7196
d62a17ae 7197 if (bgp_fibupd_safi(safi))
7198 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7199
d62a17ae 7200 return CMD_SUCCESS;
73ac8160
DS
7201}
7202
2b791107 7203void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7204 safi_t safi)
73ac8160 7205{
d62a17ae 7206 if (bgp->table_map[afi][safi].name) {
d62a17ae 7207 vty_out(vty, " table-map %s\n",
7208 bgp->table_map[afi][safi].name);
7209 }
73ac8160
DS
7210}
7211
73ac8160
DS
7212DEFUN (bgp_table_map,
7213 bgp_table_map_cmd,
7214 "table-map WORD",
7215 "BGP table to RIB route download filter\n"
7216 "Name of the route map\n")
7217{
d62a17ae 7218 int idx_word = 1;
7219 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7220 argv[idx_word]->arg);
73ac8160
DS
7221}
7222DEFUN (no_bgp_table_map,
7223 no_bgp_table_map_cmd,
7224 "no table-map WORD",
3a2d747c 7225 NO_STR
73ac8160
DS
7226 "BGP table to RIB route download filter\n"
7227 "Name of the route map\n")
7228{
d62a17ae 7229 int idx_word = 2;
7230 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7231 argv[idx_word]->arg);
73ac8160
DS
7232}
7233
585f1adc
IR
7234DEFPY(bgp_network,
7235 bgp_network_cmd,
7236 "[no] network \
7237 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7238 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7239 backdoor$backdoor}]",
7240 NO_STR
7241 "Specify a network to announce via BGP\n"
7242 "IPv4 prefix\n"
7243 "Network number\n"
7244 "Network mask\n"
7245 "Network mask\n"
7246 "Route-map to modify the attributes\n"
7247 "Name of the route map\n"
7248 "Label index to associate with the prefix\n"
7249 "Label index value\n"
7250 "Specify a BGP backdoor route\n")
7251{
7252 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7253
7254 if (address_str) {
7255 int ret;
718e3744 7256
e2a86ad9 7257 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7258 addr_prefix_str,
7259 sizeof(addr_prefix_str));
e2a86ad9
DS
7260 if (!ret) {
7261 vty_out(vty, "%% Inconsistent address and mask\n");
7262 return CMD_WARNING_CONFIG_FAILED;
7263 }
d62a17ae 7264 }
718e3744 7265
585f1adc
IR
7266 return bgp_static_set(
7267 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7268 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7269 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7270}
7271
585f1adc
IR
7272DEFPY(ipv6_bgp_network,
7273 ipv6_bgp_network_cmd,
7274 "[no] network X:X::X:X/M$prefix \
70dd370f 7275 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7276 NO_STR
7277 "Specify a network to announce via BGP\n"
7278 "IPv6 prefix\n"
7279 "Route-map to modify the attributes\n"
7280 "Name of the route map\n"
7281 "Label index to associate with the prefix\n"
7282 "Label index value\n")
37a87b8f 7283{
585f1adc
IR
7284 return bgp_static_set(
7285 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7286 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7287}
7288
d62a17ae 7289static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7290{
d62a17ae 7291 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7292}
7293
9bea1b4b 7294void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7295{
365ab2e7
RZ
7296 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7297 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7298 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7299 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7300 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7301}
718e3744 7302
365ab2e7
RZ
7303/**
7304 * Helper function to avoid repeated code: prepare variables for a
7305 * `route_map_apply` call.
7306 *
7307 * \returns `true` on route map match, otherwise `false`.
7308 */
7309static bool aggr_suppress_map_test(struct bgp *bgp,
7310 struct bgp_aggregate *aggregate,
7311 struct bgp_path_info *pi)
7312{
7313 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7314 route_map_result_t rmr = RMAP_DENYMATCH;
7315 struct bgp_path_info rmap_path = {};
7316 struct attr attr = {};
7317
7318 /* No route map entries created, just don't match. */
7319 if (aggregate->suppress_map == NULL)
7320 return false;
7321
7322 /* Call route map matching and return result. */
17571c4a 7323 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7324 rmap_path.peer = bgp->peer_self;
7325 rmap_path.attr = &attr;
7326
7327 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7328 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7329 bgp->peer_self->rmap_type = 0;
7330
7331 bgp_attr_flush(&attr);
afb254d7 7332 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7333
7334 return rmr == RMAP_PERMITMATCH;
7335}
7336
4056a5f6
RZ
7337/** Test whether the aggregation has suppressed this path or not. */
7338static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7339 struct bgp_path_info *pi)
7340{
7341 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7342 return false;
7343
7344 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7345}
7346
7347/**
7348 * Suppress this path and keep the reference.
7349 *
7350 * \returns `true` if needs processing otherwise `false`.
7351 */
7352static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7353 struct bgp_path_info *pi)
7354{
7355 struct bgp_path_info_extra *pie;
7356
7357 /* Path is already suppressed by this aggregation. */
7358 if (aggr_suppress_exists(aggregate, pi))
7359 return false;
7360
7361 pie = bgp_path_info_extra_get(pi);
7362
7363 /* This is the first suppression, allocate memory and list it. */
7364 if (pie->aggr_suppressors == NULL)
7365 pie->aggr_suppressors = list_new();
7366
7367 listnode_add(pie->aggr_suppressors, aggregate);
7368
7369 /* Only mark for processing if suppressed. */
7370 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7371 if (BGP_DEBUG(update, UPDATE_OUT))
7372 zlog_debug("aggregate-address suppressing: %pFX",
7373 bgp_dest_get_prefix(pi->net));
7374
4056a5f6
RZ
7375 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7376 return true;
7377 }
7378
7379 return false;
7380}
7381
7382/**
7383 * Unsuppress this path and remove the reference.
7384 *
7385 * \returns `true` if needs processing otherwise `false`.
7386 */
7387static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7388 struct bgp_path_info *pi)
7389{
7390 /* Path wasn't suppressed. */
7391 if (!aggr_suppress_exists(aggregate, pi))
7392 return false;
7393
7394 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7395
7396 /* Unsuppress and free extra memory if last item. */
7397 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7398 if (BGP_DEBUG(update, UPDATE_OUT))
7399 zlog_debug("aggregate-address unsuppressing: %pFX",
7400 bgp_dest_get_prefix(pi->net));
7401
4056a5f6
RZ
7402 list_delete(&pi->extra->aggr_suppressors);
7403 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7404 return true;
7405 }
7406
7407 return false;
7408}
7409
3dc339cd
DA
7410static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7411 struct aspath *aspath,
7412 struct community *comm,
7413 struct ecommunity *ecomm,
7414 struct lcommunity *lcomm)
eaaf8adb
DS
7415{
7416 static struct aspath *ae = NULL;
17571c4a
PG
7417 enum asnotation_mode asnotation;
7418
7419 asnotation = bgp_get_asnotation(NULL);
eaaf8adb 7420
e38e8edc 7421 if (!aspath)
17571c4a 7422 ae = aspath_empty(asnotation);
eaaf8adb 7423
40381db7 7424 if (!pi)
3dc339cd 7425 return false;
eaaf8adb 7426
40381db7 7427 if (origin != pi->attr->origin)
3dc339cd 7428 return false;
eaaf8adb 7429
40381db7 7430 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7431 return false;
29f7d023 7432
9a706b42 7433 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7434 return false;
eaaf8adb 7435
b53e67a3 7436 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7437 return false;
eaaf8adb 7438
1bcf3a96 7439 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7440 return false;
dd18c5a9 7441
40381db7 7442 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7443 return false;
7ce8a8e0 7444
3dc339cd 7445 return true;
eaaf8adb
DS
7446}
7447
5f040085
DS
7448static void bgp_aggregate_install(
7449 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7450 uint8_t origin, struct aspath *aspath, struct community *community,
7451 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7452 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7453{
9bcb3eef 7454 struct bgp_dest *dest;
c701010e 7455 struct bgp_table *table;
6f94b685 7456 struct bgp_path_info *pi, *orig, *new;
20894f50 7457 struct attr *attr;
c701010e
DS
7458
7459 table = bgp->rib[afi][safi];
7460
9bcb3eef 7461 dest = bgp_node_get(table, p);
eaaf8adb 7462
9bcb3eef 7463 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7464 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7465 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7466 break;
7467
6aabb15d
RZ
7468 /*
7469 * If we have paths with different MEDs, then don't install
7470 * (or uninstall) the aggregate route.
7471 */
7472 if (aggregate->match_med && aggregate->med_mismatched)
7473 goto uninstall_aggregate_route;
7474
c701010e 7475 if (aggregate->count > 0) {
eaaf8adb
DS
7476 /*
7477 * If the aggregate information has not changed
7478 * no need to re-install it again.
7479 */
cd845be6
CS
7480 if (pi && bgp_aggregate_info_same(pi, origin, aspath, community,
7481 ecommunity, lcommunity)) {
9bcb3eef 7482 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7483
7484 if (aspath)
7485 aspath_free(aspath);
7486 if (community)
3c1f53de 7487 community_free(&community);
3da2cc32
DS
7488 if (ecommunity)
7489 ecommunity_free(&ecommunity);
dd18c5a9
DS
7490 if (lcommunity)
7491 lcommunity_free(&lcommunity);
eaaf8adb
DS
7492
7493 return;
7494 }
7495
7496 /*
7497 * Mark the old as unusable
7498 */
40381db7 7499 if (pi)
9bcb3eef 7500 bgp_path_info_delete(dest, pi);
eaaf8adb 7501
20894f50
DA
7502 attr = bgp_attr_aggregate_intern(
7503 bgp, origin, aspath, community, ecommunity, lcommunity,
7504 aggregate, atomic_aggregate, p);
7505
7506 if (!attr) {
e11791f4
DA
7507 aspath_free(aspath);
7508 community_free(&community);
7509 ecommunity_free(&ecommunity);
7510 lcommunity_free(&lcommunity);
8c0044f3 7511 bgp_dest_unlock_node(dest);
20894f50 7512 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7513 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7514 zlog_debug("%s: %pFX null attribute", __func__,
7515 p);
20894f50
DA
7516 return;
7517 }
7518
3da2cc32 7519 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7520 bgp->peer_self, attr, dest);
20894f50 7521
1defdda8 7522 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7523
9bcb3eef
DS
7524 bgp_path_info_add(dest, new);
7525 bgp_process(bgp, dest, afi, safi);
c701010e 7526 } else {
6aabb15d 7527 uninstall_aggregate_route:
6f94b685 7528 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7529 if (pi->peer == bgp->peer_self
7530 && pi->type == ZEBRA_ROUTE_BGP
7531 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7532 break;
7533
7534 /* Withdraw static BGP route from routing table. */
40381db7 7535 if (pi) {
9bcb3eef
DS
7536 bgp_path_info_delete(dest, pi);
7537 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7538 }
7539 }
7540
9bcb3eef 7541 bgp_dest_unlock_node(dest);
c701010e
DS
7542}
7543
6aabb15d
RZ
7544/**
7545 * Check if the current path has different MED than other known paths.
7546 *
7547 * \returns `true` if the MED matched the others else `false`.
7548 */
7549static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7550 struct bgp *bgp, struct bgp_path_info *pi)
7551{
7552 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7553
7554 /* This is the first route being analyzed. */
7555 if (!aggregate->med_initialized) {
7556 aggregate->med_initialized = true;
7557 aggregate->med_mismatched = false;
7558 aggregate->med_matched_value = cur_med;
7559 } else {
7560 /* Check if routes with different MED showed up. */
7561 if (cur_med != aggregate->med_matched_value)
7562 aggregate->med_mismatched = true;
7563 }
7564
7565 return !aggregate->med_mismatched;
7566}
7567
7568/**
7569 * Initializes and tests all routes in the aggregate address path for MED
7570 * values.
7571 *
7572 * \returns `true` if all MEDs are the same otherwise `false`.
7573 */
7574static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7575 struct bgp *bgp, const struct prefix *p,
7576 afi_t afi, safi_t safi)
7577{
7578 struct bgp_table *table = bgp->rib[afi][safi];
7579 const struct prefix *dest_p;
7580 struct bgp_dest *dest, *top;
7581 struct bgp_path_info *pi;
7582 bool med_matched = true;
7583
7584 aggregate->med_initialized = false;
7585
7586 top = bgp_node_get(table, p);
7587 for (dest = bgp_node_get(table, p); dest;
7588 dest = bgp_route_next_until(dest, top)) {
7589 dest_p = bgp_dest_get_prefix(dest);
7590 if (dest_p->prefixlen <= p->prefixlen)
7591 continue;
7592
7593 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7594 if (BGP_PATH_HOLDDOWN(pi))
7595 continue;
7596 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7597 continue;
7598 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7599 med_matched = false;
7600 break;
7601 }
7602 }
7603 if (!med_matched)
7604 break;
7605 }
7606 bgp_dest_unlock_node(top);
7607
7608 return med_matched;
7609}
7610
7611/**
7612 * Toggles the route suppression status for this aggregate address
7613 * configuration.
7614 */
4056a5f6
RZ
7615void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7616 struct bgp *bgp, const struct prefix *p,
7617 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7618{
7619 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7620 const struct prefix *dest_p;
7621 struct bgp_dest *dest, *top;
7622 struct bgp_path_info *pi;
7623 bool toggle_suppression;
7624
7625 /* We've found a different MED we must revert any suppressed routes. */
7626 top = bgp_node_get(table, p);
7627 for (dest = bgp_node_get(table, p); dest;
7628 dest = bgp_route_next_until(dest, top)) {
7629 dest_p = bgp_dest_get_prefix(dest);
7630 if (dest_p->prefixlen <= p->prefixlen)
7631 continue;
7632
7633 toggle_suppression = false;
7634 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7635 if (BGP_PATH_HOLDDOWN(pi))
7636 continue;
7637 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7638 continue;
7639
6aabb15d
RZ
7640 /* We are toggling suppression back. */
7641 if (suppress) {
6aabb15d 7642 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7643 if (aggr_suppress_path(aggregate, pi))
7644 toggle_suppression = true;
6aabb15d
RZ
7645 continue;
7646 }
7647
6aabb15d 7648 /* Install route if there is no more suppression. */
4056a5f6 7649 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7650 toggle_suppression = true;
6aabb15d
RZ
7651 }
7652
7653 if (toggle_suppression)
7654 bgp_process(bgp, dest, afi, safi);
7655 }
7656 bgp_dest_unlock_node(top);
7657}
7658
7659/**
7660 * Aggregate address MED matching incremental test: this function is called
7661 * when the initial aggregation occurred and we are only testing a single
7662 * new path.
7663 *
7664 * In addition to testing and setting the MED validity it also installs back
7665 * suppressed routes (if summary is configured).
7666 *
7667 * Must not be called in `bgp_aggregate_route`.
7668 */
7669static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7670 struct bgp *bgp, const struct prefix *p,
7671 afi_t afi, safi_t safi,
f66624f5 7672 struct bgp_path_info *pi)
6aabb15d
RZ
7673{
7674 /* MED matching disabled. */
7675 if (!aggregate->match_med)
7676 return;
7677
f66624f5
DA
7678 /* Aggregation with different MED, recheck if we have got equal MEDs
7679 * now.
6aabb15d 7680 */
f66624f5
DA
7681 if (aggregate->med_mismatched &&
7682 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7683 aggregate->summary_only)
7684 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7685 true);
7686 else
6aabb15d
RZ
7687 bgp_aggregate_med_match(aggregate, bgp, pi);
7688
7689 /* No mismatches, just quit. */
7690 if (!aggregate->med_mismatched)
7691 return;
7692
7693 /* Route summarization is disabled. */
7694 if (!aggregate->summary_only)
7695 return;
7696
7697 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7698}
7699
b5d58c32 7700/* Update an aggregate as routes are added/removed from the BGP table */
9bea1b4b 7701bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
5f040085 7702 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7703{
7704 struct bgp_table *table;
9bcb3eef
DS
7705 struct bgp_dest *top;
7706 struct bgp_dest *dest;
d7c0a89a 7707 uint8_t origin;
d62a17ae 7708 struct aspath *aspath = NULL;
d62a17ae 7709 struct community *community = NULL;
3da2cc32 7710 struct ecommunity *ecommunity = NULL;
dd18c5a9 7711 struct lcommunity *lcommunity = NULL;
40381db7 7712 struct bgp_path_info *pi;
d62a17ae 7713 unsigned long match = 0;
d7c0a89a 7714 uint8_t atomic_aggregate = 0;
d62a17ae 7715
9f822fa2
S
7716 /* If the bgp instance is being deleted or self peer is deleted
7717 * then do not create aggregate route
7718 */
69a9680a 7719 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
9bea1b4b
DA
7720 bgp->peer_self == NULL)
7721 return false;
9f822fa2 7722
6aabb15d
RZ
7723 /* Initialize and test routes for MED difference. */
7724 if (aggregate->match_med)
7725 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7726
4056a5f6
RZ
7727 /*
7728 * Reset aggregate count: we might've been called from route map
7729 * update so in that case we must retest all more specific routes.
7730 *
7731 * \see `bgp_route_map_process_update`.
7732 */
7733 aggregate->count = 0;
7734 aggregate->incomplete_origin_count = 0;
7735 aggregate->incomplete_origin_count = 0;
7736 aggregate->egp_origin_count = 0;
7737
d62a17ae 7738 /* ORIGIN attribute: If at least one route among routes that are
7739 aggregated has ORIGIN with the value INCOMPLETE, then the
7740 aggregated route must have the ORIGIN attribute with the value
7741 INCOMPLETE. Otherwise, if at least one route among routes that
7742 are aggregated has ORIGIN with the value EGP, then the aggregated
7743 route must have the origin attribute with the value EGP. In all
7744 other case the value of the ORIGIN attribute of the aggregated
7745 route is INTERNAL. */
7746 origin = BGP_ORIGIN_IGP;
718e3744 7747
d62a17ae 7748 table = bgp->rib[afi][safi];
718e3744 7749
d62a17ae 7750 top = bgp_node_get(table, p);
9bcb3eef
DS
7751 for (dest = bgp_node_get(table, p); dest;
7752 dest = bgp_route_next_until(dest, top)) {
7753 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7754
9bcb3eef 7755 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7756 continue;
d62a17ae 7757
a77e2f4b
S
7758 /* If suppress fib is enabled and route not installed
7759 * in FIB, skip the route
7760 */
7761 if (!bgp_check_advertise(bgp, dest))
7762 continue;
7763
c2ff8b3e 7764 match = 0;
d62a17ae 7765
9bcb3eef 7766 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7767 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7768 continue;
718e3744 7769
40381db7 7770 if (pi->attr->flag
c2ff8b3e
DS
7771 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7772 atomic_aggregate = 1;
d62a17ae 7773
40381db7 7774 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7775 continue;
d62a17ae 7776
f273fef1
DS
7777 /*
7778 * summary-only aggregate route suppress
7779 * aggregated route announcements.
6aabb15d
RZ
7780 *
7781 * MED matching:
7782 * Don't create summaries if MED didn't match
7783 * otherwise neither the specific routes and the
7784 * aggregation will be announced.
f273fef1 7785 */
6aabb15d
RZ
7786 if (aggregate->summary_only
7787 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7788 if (aggr_suppress_path(aggregate, pi))
7789 match++;
d62a17ae 7790 }
c2ff8b3e 7791
365ab2e7
RZ
7792 /*
7793 * Suppress more specific routes that match the route
7794 * map results.
7795 *
7796 * MED matching:
7797 * Don't suppress routes if MED matching is enabled and
7798 * it mismatched otherwise we might end up with no
7799 * routes for this path.
7800 */
7801 if (aggregate->suppress_map_name
7802 && AGGREGATE_MED_VALID(aggregate)
7803 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7804 if (aggr_suppress_path(aggregate, pi))
7805 match++;
d62a17ae 7806 }
c2ff8b3e
DS
7807
7808 aggregate->count++;
7809
f273fef1
DS
7810 /*
7811 * If at least one route among routes that are
7812 * aggregated has ORIGIN with the value INCOMPLETE,
7813 * then the aggregated route MUST have the ORIGIN
7814 * attribute with the value INCOMPLETE. Otherwise, if
7815 * at least one route among routes that are aggregated
7816 * has ORIGIN with the value EGP, then the aggregated
7817 * route MUST have the ORIGIN attribute with the value
7818 * EGP.
7819 */
fc968841
NT
7820 switch (pi->attr->origin) {
7821 case BGP_ORIGIN_INCOMPLETE:
7822 aggregate->incomplete_origin_count++;
7823 break;
7824 case BGP_ORIGIN_EGP:
7825 aggregate->egp_origin_count++;
7826 break;
7827 default:
7828 /*Do nothing.
7829 */
7830 break;
7831 }
c2ff8b3e
DS
7832
7833 if (!aggregate->as_set)
7834 continue;
7835
f273fef1
DS
7836 /*
7837 * as-set aggregate route generate origin, as path,
7838 * and community aggregation.
7839 */
fc968841
NT
7840 /* Compute aggregate route's as-path.
7841 */
ef51a7d8 7842 bgp_compute_aggregate_aspath_hash(aggregate,
7843 pi->attr->aspath);
c2ff8b3e 7844
fc968841
NT
7845 /* Compute aggregate route's community.
7846 */
9a706b42 7847 if (bgp_attr_get_community(pi->attr))
21fec674 7848 bgp_compute_aggregate_community_hash(
9a706b42
DA
7849 aggregate,
7850 bgp_attr_get_community(pi->attr));
dd18c5a9 7851
fc968841
NT
7852 /* Compute aggregate route's extended community.
7853 */
b53e67a3 7854 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7855 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7856 aggregate,
7857 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7858
7859 /* Compute aggregate route's large community.
7860 */
1bcf3a96 7861 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7862 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7863 aggregate,
7864 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7865 }
c2ff8b3e 7866 if (match)
9bcb3eef 7867 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7868 }
21fec674 7869 if (aggregate->as_set) {
ef51a7d8 7870 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7871 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7872 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7873 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7874 }
7875
f1eb1f05 7876
9bcb3eef 7877 bgp_dest_unlock_node(top);
718e3744 7878
718e3744 7879
fc968841
NT
7880 if (aggregate->incomplete_origin_count > 0)
7881 origin = BGP_ORIGIN_INCOMPLETE;
7882 else if (aggregate->egp_origin_count > 0)
7883 origin = BGP_ORIGIN_EGP;
d62a17ae 7884
229757f1
DA
7885 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7886 origin = aggregate->origin;
7887
fc968841
NT
7888 if (aggregate->as_set) {
7889 if (aggregate->aspath)
7890 /* Retrieve aggregate route's as-path.
7891 */
7892 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7893
fc968841
NT
7894 if (aggregate->community)
7895 /* Retrieve aggregate route's community.
7896 */
7897 community = community_dup(aggregate->community);
3da2cc32 7898
fc968841
NT
7899 if (aggregate->ecommunity)
7900 /* Retrieve aggregate route's ecommunity.
7901 */
7902 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7903
fc968841
NT
7904 if (aggregate->lcommunity)
7905 /* Retrieve aggregate route's lcommunity.
7906 */
7907 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7908 }
718e3744 7909
c701010e 7910 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7911 ecommunity, lcommunity, atomic_aggregate,
7912 aggregate);
9bea1b4b
DA
7913
7914 return true;
718e3744 7915}
7916
5f040085
DS
7917void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7918 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7919{
7920 struct bgp_table *table;
9bcb3eef
DS
7921 struct bgp_dest *top;
7922 struct bgp_dest *dest;
40381db7 7923 struct bgp_path_info *pi;
3b7db173
DS
7924 unsigned long match;
7925
7926 table = bgp->rib[afi][safi];
7927
7928 /* If routes exists below this node, generate aggregate routes. */
7929 top = bgp_node_get(table, p);
9bcb3eef
DS
7930 for (dest = bgp_node_get(table, p); dest;
7931 dest = bgp_route_next_until(dest, top)) {
7932 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7933
9bcb3eef 7934 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7935 continue;
7936 match = 0;
7937
9bcb3eef 7938 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7939 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7940 continue;
7941
40381db7 7942 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7943 continue;
7944
92b175bd
RZ
7945 /*
7946 * This route is suppressed: attempt to unsuppress it.
7947 *
7948 * `aggr_unsuppress_path` will fail if this particular
7949 * aggregate route was not the suppressor.
7950 */
7951 if (pi->extra && pi->extra->aggr_suppressors &&
7952 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7953 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7954 match++;
3b7db173 7955 }
365ab2e7 7956
3b7db173 7957 aggregate->count--;
fc968841
NT
7958
7959 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7960 aggregate->incomplete_origin_count--;
7961 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7962 aggregate->egp_origin_count--;
7963
7964 if (aggregate->as_set) {
7965 /* Remove as-path from aggregate.
7966 */
ef51a7d8 7967 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7968 aggregate,
7969 pi->attr->aspath);
7970
9a706b42 7971 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7972 /* Remove community from aggregate.
7973 */
21fec674 7974 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7975 aggregate,
7976 bgp_attr_get_community(
7977 pi->attr));
fc968841 7978
b53e67a3 7979 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7980 /* Remove ecommunity from aggregate.
7981 */
4edd83f9 7982 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7983 aggregate,
7984 bgp_attr_get_ecommunity(
7985 pi->attr));
fc968841 7986
1bcf3a96 7987 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7988 /* Remove lcommunity from aggregate.
7989 */
f1eb1f05 7990 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7991 aggregate,
7992 bgp_attr_get_lcommunity(
7993 pi->attr));
fc968841 7994 }
3b7db173
DS
7995 }
7996
7997 /* If this node was suppressed, process the change. */
7998 if (match)
9bcb3eef 7999 bgp_process(bgp, dest, afi, safi);
3b7db173 8000 }
f1eb1f05 8001 if (aggregate->as_set) {
ef51a7d8 8002 aspath_free(aggregate->aspath);
8003 aggregate->aspath = NULL;
21fec674 8004 if (aggregate->community)
8005 community_free(&aggregate->community);
4edd83f9 8006 if (aggregate->ecommunity)
8007 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 8008 if (aggregate->lcommunity)
8009 lcommunity_free(&aggregate->lcommunity);
8010 }
8011
9bcb3eef 8012 bgp_dest_unlock_node(top);
3b7db173 8013}
718e3744 8014
5f040085
DS
8015static void bgp_add_route_to_aggregate(struct bgp *bgp,
8016 const struct prefix *aggr_p,
fc968841
NT
8017 struct bgp_path_info *pinew, afi_t afi,
8018 safi_t safi,
8019 struct bgp_aggregate *aggregate)
8020{
8021 uint8_t origin;
8022 struct aspath *aspath = NULL;
8023 uint8_t atomic_aggregate = 0;
8024 struct community *community = NULL;
8025 struct ecommunity *ecommunity = NULL;
8026 struct lcommunity *lcommunity = NULL;
8027
a4559740 8028 /* If the bgp instance is being deleted or self peer is deleted
8029 * then do not create aggregate route
8030 */
8031 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8032 || (bgp->peer_self == NULL))
8033 return;
8034
fc968841
NT
8035 /* ORIGIN attribute: If at least one route among routes that are
8036 * aggregated has ORIGIN with the value INCOMPLETE, then the
8037 * aggregated route must have the ORIGIN attribute with the value
8038 * INCOMPLETE. Otherwise, if at least one route among routes that
8039 * are aggregated has ORIGIN with the value EGP, then the aggregated
8040 * route must have the origin attribute with the value EGP. In all
8041 * other case the value of the ORIGIN attribute of the aggregated
8042 * route is INTERNAL.
8043 */
8044 origin = BGP_ORIGIN_IGP;
8045
8046 aggregate->count++;
8047
6aabb15d
RZ
8048 /*
8049 * This must be called before `summary` check to avoid
8050 * "suppressing" twice.
8051 */
8052 if (aggregate->match_med)
8053 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8054 pinew);
6aabb15d
RZ
8055
8056 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8057 aggr_suppress_path(aggregate, pinew);
fc968841 8058
365ab2e7
RZ
8059 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8060 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8061 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8062
8063 switch (pinew->attr->origin) {
8064 case BGP_ORIGIN_INCOMPLETE:
8065 aggregate->incomplete_origin_count++;
8066 break;
8067 case BGP_ORIGIN_EGP:
8068 aggregate->egp_origin_count++;
8069 break;
8070 default:
8071 /* Do nothing.
8072 */
8073 break;
8074 }
8075
8076 if (aggregate->incomplete_origin_count > 0)
8077 origin = BGP_ORIGIN_INCOMPLETE;
8078 else if (aggregate->egp_origin_count > 0)
8079 origin = BGP_ORIGIN_EGP;
8080
229757f1
DA
8081 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8082 origin = aggregate->origin;
8083
fc968841
NT
8084 if (aggregate->as_set) {
8085 /* Compute aggregate route's as-path.
8086 */
8087 bgp_compute_aggregate_aspath(aggregate,
8088 pinew->attr->aspath);
8089
8090 /* Compute aggregate route's community.
8091 */
9a706b42 8092 if (bgp_attr_get_community(pinew->attr))
fc968841 8093 bgp_compute_aggregate_community(
9a706b42 8094 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8095
8096 /* Compute aggregate route's extended community.
8097 */
b53e67a3 8098 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8099 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8100 aggregate,
8101 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8102
8103 /* Compute aggregate route's large community.
8104 */
1bcf3a96 8105 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8106 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8107 aggregate,
8108 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8109
8110 /* Retrieve aggregate route's as-path.
8111 */
8112 if (aggregate->aspath)
8113 aspath = aspath_dup(aggregate->aspath);
8114
8115 /* Retrieve aggregate route's community.
8116 */
8117 if (aggregate->community)
8118 community = community_dup(aggregate->community);
8119
8120 /* Retrieve aggregate route's ecommunity.
8121 */
8122 if (aggregate->ecommunity)
8123 ecommunity = ecommunity_dup(aggregate->ecommunity);
8124
8125 /* Retrieve aggregate route's lcommunity.
8126 */
8127 if (aggregate->lcommunity)
8128 lcommunity = lcommunity_dup(aggregate->lcommunity);
8129 }
8130
8131 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8132 aspath, community, ecommunity,
8133 lcommunity, atomic_aggregate, aggregate);
8134}
8135
8136static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8137 safi_t safi,
8138 struct bgp_path_info *pi,
8139 struct bgp_aggregate *aggregate,
5f040085 8140 const struct prefix *aggr_p)
fc968841
NT
8141{
8142 uint8_t origin;
8143 struct aspath *aspath = NULL;
8144 uint8_t atomic_aggregate = 0;
8145 struct community *community = NULL;
8146 struct ecommunity *ecommunity = NULL;
8147 struct lcommunity *lcommunity = NULL;
8148 unsigned long match = 0;
8149
a4559740 8150 /* If the bgp instance is being deleted or self peer is deleted
8151 * then do not create aggregate route
8152 */
8153 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8154 || (bgp->peer_self == NULL))
8155 return;
8156
fc968841
NT
8157 if (BGP_PATH_HOLDDOWN(pi))
8158 return;
8159
8160 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8161 return;
8162
4056a5f6
RZ
8163 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8164 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8165 match++;
fc968841 8166
365ab2e7 8167 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8168 && aggr_suppress_map_test(bgp, aggregate, pi))
8169 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8170 match++;
fc968841 8171
6aabb15d 8172 /*
365ab2e7 8173 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8174 * "unsuppressing" twice.
8175 */
8176 if (aggregate->match_med)
f66624f5 8177 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8178
fc968841
NT
8179 if (aggregate->count > 0)
8180 aggregate->count--;
8181
8182 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8183 aggregate->incomplete_origin_count--;
8184 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8185 aggregate->egp_origin_count--;
8186
8187 if (aggregate->as_set) {
8188 /* Remove as-path from aggregate.
8189 */
8190 bgp_remove_aspath_from_aggregate(aggregate,
8191 pi->attr->aspath);
8192
9a706b42 8193 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8194 /* Remove community from aggregate.
8195 */
8196 bgp_remove_community_from_aggregate(
9a706b42 8197 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8198
b53e67a3 8199 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8200 /* Remove ecommunity from aggregate.
8201 */
8202 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8203 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8204
1bcf3a96 8205 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8206 /* Remove lcommunity from aggregate.
8207 */
8208 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8209 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8210 }
8211
8212 /* If this node was suppressed, process the change. */
8213 if (match)
8214 bgp_process(bgp, pi->net, afi, safi);
8215
8216 origin = BGP_ORIGIN_IGP;
8217 if (aggregate->incomplete_origin_count > 0)
8218 origin = BGP_ORIGIN_INCOMPLETE;
8219 else if (aggregate->egp_origin_count > 0)
8220 origin = BGP_ORIGIN_EGP;
8221
229757f1
DA
8222 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8223 origin = aggregate->origin;
8224
fc968841
NT
8225 if (aggregate->as_set) {
8226 /* Retrieve aggregate route's as-path.
8227 */
8228 if (aggregate->aspath)
8229 aspath = aspath_dup(aggregate->aspath);
8230
8231 /* Retrieve aggregate route's community.
8232 */
8233 if (aggregate->community)
8234 community = community_dup(aggregate->community);
8235
8236 /* Retrieve aggregate route's ecommunity.
8237 */
8238 if (aggregate->ecommunity)
8239 ecommunity = ecommunity_dup(aggregate->ecommunity);
8240
8241 /* Retrieve aggregate route's lcommunity.
8242 */
8243 if (aggregate->lcommunity)
8244 lcommunity = lcommunity_dup(aggregate->lcommunity);
8245 }
8246
8247 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8248 aspath, community, ecommunity,
8249 lcommunity, atomic_aggregate, aggregate);
8250}
8251
5a1ae2c2 8252void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8253 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8254{
9bcb3eef
DS
8255 struct bgp_dest *child;
8256 struct bgp_dest *dest;
d62a17ae 8257 struct bgp_aggregate *aggregate;
8258 struct bgp_table *table;
718e3744 8259
d62a17ae 8260 table = bgp->aggregate[afi][safi];
f018db83 8261
d62a17ae 8262 /* No aggregates configured. */
8263 if (bgp_table_top_nolock(table) == NULL)
8264 return;
f018db83 8265
d62a17ae 8266 if (p->prefixlen == 0)
8267 return;
718e3744 8268
40381db7 8269 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8270 return;
718e3744 8271
a77e2f4b
S
8272 /* If suppress fib is enabled and route not installed
8273 * in FIB, do not update the aggregate route
8274 */
8275 if (!bgp_check_advertise(bgp, pi->net))
8276 return;
8277
d62a17ae 8278 child = bgp_node_get(table, p);
718e3744 8279
d62a17ae 8280 /* Aggregate address configuration check. */
9bcb3eef
DS
8281 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8282 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8283
9bcb3eef
DS
8284 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8285 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8286 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8287 aggregate);
d62a17ae 8288 }
b1e62edd 8289 }
9bcb3eef 8290 bgp_dest_unlock_node(child);
718e3744 8291}
8292
5a1ae2c2 8293void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8294 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8295{
9bcb3eef
DS
8296 struct bgp_dest *child;
8297 struct bgp_dest *dest;
d62a17ae 8298 struct bgp_aggregate *aggregate;
8299 struct bgp_table *table;
718e3744 8300
d62a17ae 8301 table = bgp->aggregate[afi][safi];
718e3744 8302
d62a17ae 8303 /* No aggregates configured. */
8304 if (bgp_table_top_nolock(table) == NULL)
8305 return;
718e3744 8306
d62a17ae 8307 if (p->prefixlen == 0)
8308 return;
718e3744 8309
d62a17ae 8310 child = bgp_node_get(table, p);
718e3744 8311
d62a17ae 8312 /* Aggregate address configuration check. */
9bcb3eef
DS
8313 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8314 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8315
9bcb3eef
DS
8316 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8317 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8318 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8319 aggregate, dest_p);
d62a17ae 8320 }
b1e62edd 8321 }
9bcb3eef 8322 bgp_dest_unlock_node(child);
d62a17ae 8323}
718e3744 8324
718e3744 8325/* Aggregate route attribute. */
8326#define AGGREGATE_SUMMARY_ONLY 1
8327#define AGGREGATE_AS_SET 1
fb29348a 8328#define AGGREGATE_AS_UNSET 0
718e3744 8329
229757f1
DA
8330static const char *bgp_origin2str(uint8_t origin)
8331{
8332 switch (origin) {
8333 case BGP_ORIGIN_IGP:
8334 return "igp";
8335 case BGP_ORIGIN_EGP:
8336 return "egp";
8337 case BGP_ORIGIN_INCOMPLETE:
8338 return "incomplete";
8339 }
8340 return "n/a";
8341}
8342
fdeb5a81 8343static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8344{
8345 switch (v_state) {
fdeb5a81
DS
8346 case RPKI_NOT_BEING_USED:
8347 return "not used";
8348 case RPKI_VALID:
b5b99af8 8349 return "valid";
fdeb5a81 8350 case RPKI_NOTFOUND:
b5b99af8 8351 return "not found";
fdeb5a81 8352 case RPKI_INVALID:
b5b99af8 8353 return "invalid";
b5b99af8 8354 }
fdeb5a81
DS
8355
8356 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8357 return "ERROR";
8358}
8359
585f1adc
IR
8360static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8361 afi_t afi, safi_t safi)
718e3744 8362{
585f1adc
IR
8363 VTY_DECLVAR_CONTEXT(bgp, bgp);
8364 int ret;
8365 struct prefix p;
9bcb3eef 8366 struct bgp_dest *dest;
d62a17ae 8367 struct bgp_aggregate *aggregate;
718e3744 8368
585f1adc
IR
8369 /* Convert string to prefix structure. */
8370 ret = str2prefix(prefix_str, &p);
8371 if (!ret) {
8372 vty_out(vty, "Malformed prefix\n");
8373 return CMD_WARNING_CONFIG_FAILED;
8374 }
8375 apply_mask(&p);
a4559740 8376
d62a17ae 8377 /* Old configuration check. */
585f1adc 8378 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8379 if (!dest) {
585f1adc
IR
8380 vty_out(vty,
8381 "%% There is no aggregate-address configuration.\n");
8382 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8383 }
f6269b4f 8384
9bcb3eef 8385 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8386 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8387 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8388 NULL, NULL, 0, aggregate);
d62a17ae 8389
8390 /* Unlock aggregate address configuration. */
9bcb3eef 8391 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841 8392
7a70d990 8393 bgp_free_aggregate_info(aggregate);
9bcb3eef
DS
8394 bgp_dest_unlock_node(dest);
8395 bgp_dest_unlock_node(dest);
d62a17ae 8396
585f1adc 8397 return CMD_SUCCESS;
d62a17ae 8398}
8399
585f1adc
IR
8400static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8401 safi_t safi, const char *rmap,
8402 uint8_t summary_only, uint8_t as_set,
8403 uint8_t origin, bool match_med,
8404 const char *suppress_map)
d62a17ae 8405{
585f1adc 8406 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8407 int ret;
585f1adc 8408 struct prefix p;
9bcb3eef 8409 struct bgp_dest *dest;
d62a17ae 8410 struct bgp_aggregate *aggregate;
fb29348a 8411 uint8_t as_set_new = as_set;
d62a17ae 8412
365ab2e7 8413 if (suppress_map && summary_only) {
585f1adc 8414 vty_out(vty,
365ab2e7 8415 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8416 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8417 }
8418
585f1adc
IR
8419 /* Convert string to prefix structure. */
8420 ret = str2prefix(prefix_str, &p);
8421 if (!ret) {
8422 vty_out(vty, "Malformed prefix\n");
8423 return CMD_WARNING_CONFIG_FAILED;
8424 }
8425 apply_mask(&p);
d62a17ae 8426
585f1adc
IR
8427 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8428 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8429 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8430 prefix_str);
8431 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8432 }
8433
d62a17ae 8434 /* Old configuration check. */
585f1adc 8435 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8436 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8437
20894f50 8438 if (aggregate) {
585f1adc 8439 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8440 /* try to remove the old entry */
585f1adc 8441 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8442 if (ret) {
585f1adc 8443 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8444 bgp_dest_unlock_node(dest);
585f1adc 8445 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8446 }
8447 }
718e3744 8448
d62a17ae 8449 /* Make aggregate address structure. */
8450 aggregate = bgp_aggregate_new();
8451 aggregate->summary_only = summary_only;
6aabb15d 8452 aggregate->match_med = match_med;
fb29348a
DA
8453
8454 /* Network operators MUST NOT locally generate any new
8455 * announcements containing AS_SET or AS_CONFED_SET. If they have
8456 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8457 * SHOULD withdraw those routes and re-announce routes for the
8458 * aggregate or component prefixes (i.e., the more-specific routes
8459 * subsumed by the previously aggregated route) without AS_SET
8460 * or AS_CONFED_SET in the updates.
8461 */
7f972cd8 8462 if (bgp->reject_as_sets) {
fb29348a
DA
8463 if (as_set == AGGREGATE_AS_SET) {
8464 as_set_new = AGGREGATE_AS_UNSET;
8465 zlog_warn(
63efca0e 8466 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8467 __func__);
585f1adc 8468 vty_out(vty,
fb29348a
DA
8469 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8470 }
8471 }
8472
8473 aggregate->as_set = as_set_new;
d62a17ae 8474 aggregate->safi = safi;
229757f1
DA
8475 /* Override ORIGIN attribute if defined.
8476 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8477 * to IGP which is not what rfc4271 says.
8478 * This enables the same behavior, optionally.
8479 */
8480 aggregate->origin = origin;
20894f50
DA
8481
8482 if (rmap) {
8483 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8484 route_map_counter_decrement(aggregate->rmap.map);
8485 aggregate->rmap.name =
8486 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8487 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8488 route_map_counter_increment(aggregate->rmap.map);
8489 }
365ab2e7
RZ
8490
8491 if (suppress_map) {
8492 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8493 route_map_counter_decrement(aggregate->suppress_map);
8494
8495 aggregate->suppress_map_name =
8496 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8497 aggregate->suppress_map =
8498 route_map_lookup_by_name(aggregate->suppress_map_name);
8499 route_map_counter_increment(aggregate->suppress_map);
8500 }
8501
9bcb3eef 8502 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8503
d62a17ae 8504 /* Aggregate address insert into BGP routing table. */
9bea1b4b
DA
8505 if (!bgp_aggregate_route(bgp, &p, afi, safi, aggregate)) {
8506 bgp_aggregate_free(aggregate);
8507 bgp_dest_unlock_node(dest);
8508 }
718e3744 8509
585f1adc 8510 return CMD_SUCCESS;
718e3744 8511}
8512
585f1adc
IR
8513DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8514 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8515 "as-set$as_set_s"
8516 "|summary-only$summary_only"
cacba915 8517 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8518 "|origin <egp|igp|incomplete>$origin_s"
8519 "|matching-MED-only$match_med"
cacba915 8520 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8521 "}]",
8522 NO_STR
8523 "Configure BGP aggregate entries\n"
764402fe
DA
8524 "Aggregate prefix\n"
8525 "Aggregate address\n"
8526 "Aggregate mask\n"
585f1adc
IR
8527 "Generate AS set path information\n"
8528 "Filter more specific routes from updates\n"
8529 "Apply route map to aggregate network\n"
8530 "Route map name\n"
8531 "BGP origin code\n"
8532 "Remote EGP\n"
8533 "Local IGP\n"
8534 "Unknown heritage\n"
8535 "Only aggregate routes with matching MED\n"
8536 "Suppress the selected more specific routes\n"
8537 "Route map with the route selectors\n")
8538{
8539 const char *prefix_s = NULL;
554b3b10 8540 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8541 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8542 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8543 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8544
554b3b10 8545 if (addr_str) {
7533cad7
QY
8546 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8547 sizeof(prefix_buf))
554b3b10
RZ
8548 == 0) {
8549 vty_out(vty, "%% Inconsistent address and mask\n");
8550 return CMD_WARNING_CONFIG_FAILED;
8551 }
585f1adc
IR
8552 prefix_s = prefix_buf;
8553 } else
8554 prefix_s = prefix_str;
37a87b8f 8555
585f1adc
IR
8556 if (origin_s) {
8557 if (strcmp(origin_s, "egp") == 0)
8558 origin = BGP_ORIGIN_EGP;
8559 else if (strcmp(origin_s, "igp") == 0)
8560 origin = BGP_ORIGIN_IGP;
8561 else if (strcmp(origin_s, "incomplete") == 0)
8562 origin = BGP_ORIGIN_INCOMPLETE;
8563 }
90e21f35 8564
585f1adc
IR
8565 if (as_set_s)
8566 as_set = AGGREGATE_AS_SET;
554b3b10 8567
585f1adc 8568 /* Handle configuration removal, otherwise installation. */
554b3b10 8569 if (no)
585f1adc
IR
8570 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8571
8572 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8573 summary_only != NULL, as_set, origin,
8574 match_med != NULL, suppress_map);
8575}
8576
7a70d990
SB
8577void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
8578{
8579 if (aggregate->community)
8580 community_free(&aggregate->community);
8581
8582 hash_clean_and_free(&aggregate->community_hash,
8583 bgp_aggr_community_remove);
8584
8585 if (aggregate->ecommunity)
8586 ecommunity_free(&aggregate->ecommunity);
8587
8588 hash_clean_and_free(&aggregate->ecommunity_hash,
8589 bgp_aggr_ecommunity_remove);
8590
8591 if (aggregate->lcommunity)
8592 lcommunity_free(&aggregate->lcommunity);
8593
8594 hash_clean_and_free(&aggregate->lcommunity_hash,
8595 bgp_aggr_lcommunity_remove);
8596
8597 if (aggregate->aspath)
8598 aspath_free(aggregate->aspath);
8599
8600 hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
8601
8602 bgp_aggregate_free(aggregate);
8603}
8604
585f1adc
IR
8605DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8606 "[no] aggregate-address X:X::X:X/M$prefix [{"
8607 "as-set$as_set_s"
8608 "|summary-only$summary_only"
cacba915 8609 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8610 "|origin <egp|igp|incomplete>$origin_s"
8611 "|matching-MED-only$match_med"
cacba915 8612 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8613 "}]",
8614 NO_STR
8615 "Configure BGP aggregate entries\n"
8616 "Aggregate prefix\n"
8617 "Generate AS set path information\n"
8618 "Filter more specific routes from updates\n"
8619 "Apply route map to aggregate network\n"
8620 "Route map name\n"
8621 "BGP origin code\n"
8622 "Remote EGP\n"
8623 "Local IGP\n"
8624 "Unknown heritage\n"
8625 "Only aggregate routes with matching MED\n"
8626 "Suppress the selected more specific routes\n"
8627 "Route map with the route selectors\n")
8628{
8629 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8630 int as_set = AGGREGATE_AS_UNSET;
8631
8632 if (origin_s) {
8633 if (strcmp(origin_s, "egp") == 0)
8634 origin = BGP_ORIGIN_EGP;
8635 else if (strcmp(origin_s, "igp") == 0)
8636 origin = BGP_ORIGIN_IGP;
8637 else if (strcmp(origin_s, "incomplete") == 0)
8638 origin = BGP_ORIGIN_INCOMPLETE;
8639 }
8640
8641 if (as_set_s)
8642 as_set = AGGREGATE_AS_SET;
8643
8644 /* Handle configuration removal, otherwise installation. */
554b3b10 8645 if (no)
585f1adc
IR
8646 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8647 SAFI_UNICAST);
554b3b10 8648
585f1adc
IR
8649 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8650 rmap_name, summary_only != NULL, as_set,
8651 origin, match_med != NULL, suppress_map);
718e3744 8652}
8653
718e3744 8654/* Redistribute route treatment. */
d62a17ae 8655void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8656 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8657 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8658 enum blackhole_type bhtype, uint32_t metric,
8659 uint8_t type, unsigned short instance,
8660 route_tag_t tag)
d62a17ae 8661{
4b7e6066 8662 struct bgp_path_info *new;
40381db7
DS
8663 struct bgp_path_info *bpi;
8664 struct bgp_path_info rmap_path;
9bcb3eef 8665 struct bgp_dest *bn;
d62a17ae 8666 struct attr attr;
8667 struct attr *new_attr;
8668 afi_t afi;
b68885f9 8669 route_map_result_t ret;
d62a17ae 8670 struct bgp_redist *red;
8671
8672 /* Make default attribute. */
0f05ea43 8673 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8674 /*
8675 * This must not be NULL to satisfy Coverity SA
8676 */
8677 assert(attr.aspath);
9de1f7ff 8678
83b50eff
PG
8679 if (p->family == AF_INET6)
8680 UNSET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
8681
a4d82a8a 8682 switch (nhtype) {
9de1f7ff 8683 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8684 switch (p->family) {
8685 case AF_INET:
8686 attr.nexthop.s_addr = INADDR_ANY;
8687 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5dba2592 8688 attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
6fc4929e
PG
8689 break;
8690 case AF_INET6:
8691 memset(&attr.mp_nexthop_global, 0,
8692 sizeof(attr.mp_nexthop_global));
8693 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8694 break;
8695 }
9de1f7ff
DS
8696 break;
8697 case NEXTHOP_TYPE_IPV4:
8698 case NEXTHOP_TYPE_IPV4_IFINDEX:
8699 attr.nexthop = nexthop->ipv4;
7226bc40 8700 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5dba2592 8701 attr.mp_nexthop_global_in = nexthop->ipv4;
9de1f7ff
DS
8702 break;
8703 case NEXTHOP_TYPE_IPV6:
8704 case NEXTHOP_TYPE_IPV6_IFINDEX:
8705 attr.mp_nexthop_global = nexthop->ipv6;
8706 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8707 break;
8708 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8709 switch (p->family) {
8710 case AF_INET:
9de1f7ff 8711 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8712 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5dba2592 8713 attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
74489921
RW
8714 break;
8715 case AF_INET6:
9de1f7ff
DS
8716 memset(&attr.mp_nexthop_global, 0,
8717 sizeof(attr.mp_nexthop_global));
74489921 8718 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8719 break;
74489921 8720 }
0789eb69 8721 attr.bh_type = bhtype;
9de1f7ff 8722 break;
d62a17ae 8723 }
0789eb69 8724 attr.nh_type = nhtype;
74489921 8725 attr.nh_ifindex = ifindex;
f04a80a5 8726
d62a17ae 8727 attr.med = metric;
957f74c3 8728 attr.distance = distance;
d62a17ae 8729 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8730 attr.tag = tag;
718e3744 8731
97a52c82
DA
8732 if (metric)
8733 bgp_attr_set_aigp_metric(&attr, metric);
8734
d62a17ae 8735 afi = family2afi(p->family);
6aeb9e78 8736
d62a17ae 8737 red = bgp_redist_lookup(bgp, afi, type, instance);
8738 if (red) {
8739 struct attr attr_new;
718e3744 8740
d62a17ae 8741 /* Copy attribute for modification. */
6f4f49b2 8742 attr_new = attr;
718e3744 8743
97a52c82 8744 if (red->redist_metric_flag) {
d62a17ae 8745 attr_new.med = red->redist_metric;
97a52c82
DA
8746 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8747 }
718e3744 8748
d62a17ae 8749 /* Apply route-map. */
8750 if (red->rmap.name) {
6006b807 8751 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8752 rmap_path.peer = bgp->peer_self;
8753 rmap_path.attr = &attr_new;
718e3744 8754
d62a17ae 8755 SET_FLAG(bgp->peer_self->rmap_type,
8756 PEER_RMAP_TYPE_REDISTRIBUTE);
8757
1782514f 8758 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8759
8760 bgp->peer_self->rmap_type = 0;
8761
8762 if (ret == RMAP_DENYMATCH) {
8763 /* Free uninterned attribute. */
8764 bgp_attr_flush(&attr_new);
8765
8766 /* Unintern original. */
8767 aspath_unintern(&attr.aspath);
8768 bgp_redistribute_delete(bgp, p, type, instance);
8769 return;
8770 }
8771 }
8772
637e5ba4 8773 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8774 bgp_attr_add_gshut_community(&attr_new);
8775
d62a17ae 8776 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8777 SAFI_UNICAST, p, NULL);
8778
8779 new_attr = bgp_attr_intern(&attr_new);
8780
9bcb3eef 8781 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8782 if (bpi->peer == bgp->peer_self
8783 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8784 break;
8785
40381db7 8786 if (bpi) {
d62a17ae 8787 /* Ensure the (source route) type is updated. */
40381db7
DS
8788 bpi->type = type;
8789 if (attrhash_cmp(bpi->attr, new_attr)
8790 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8791 bgp_attr_unintern(&new_attr);
8792 aspath_unintern(&attr.aspath);
9bcb3eef 8793 bgp_dest_unlock_node(bn);
d62a17ae 8794 return;
8795 } else {
8796 /* The attribute is changed. */
40381db7 8797 bgp_path_info_set_flag(bn, bpi,
18ee8310 8798 BGP_PATH_ATTR_CHANGED);
d62a17ae 8799
8800 /* Rewrite BGP route information. */
40381db7
DS
8801 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8802 bgp_path_info_restore(bn, bpi);
d62a17ae 8803 else
40381db7
DS
8804 bgp_aggregate_decrement(
8805 bgp, p, bpi, afi, SAFI_UNICAST);
8806 bgp_attr_unintern(&bpi->attr);
8807 bpi->attr = new_attr;
083ec940 8808 bpi->uptime = monotime(NULL);
d62a17ae 8809
8810 /* Process change. */
40381db7 8811 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8812 SAFI_UNICAST);
8813 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8814 bgp_dest_unlock_node(bn);
d62a17ae 8815 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8816
8817 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8818 || (bgp->inst_type
8819 == BGP_INSTANCE_TYPE_DEFAULT)) {
8820
8821 vpn_leak_from_vrf_update(
40381db7 8822 bgp_get_default(), bgp, bpi);
ddb5b488 8823 }
d62a17ae 8824 return;
8825 }
8826 }
8827
8828 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8829 bgp->peer_self, new_attr, bn);
1defdda8 8830 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8831
8832 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8833 bgp_path_info_add(bn, new);
9bcb3eef 8834 bgp_dest_unlock_node(bn);
be785e35 8835 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8836 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8837
8838 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8839 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8840
8841 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8842 }
d62a17ae 8843 }
8844
8845 /* Unintern original. */
8846 aspath_unintern(&attr.aspath);
718e3744 8847}
8848
d7c0a89a
QY
8849void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8850 unsigned short instance)
718e3744 8851{
d62a17ae 8852 afi_t afi;
9bcb3eef 8853 struct bgp_dest *dest;
40381db7 8854 struct bgp_path_info *pi;
d62a17ae 8855 struct bgp_redist *red;
718e3744 8856
d62a17ae 8857 afi = family2afi(p->family);
718e3744 8858
d62a17ae 8859 red = bgp_redist_lookup(bgp, afi, type, instance);
8860 if (red) {
9bcb3eef
DS
8861 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8862 SAFI_UNICAST, p, NULL);
d62a17ae 8863
9bcb3eef 8864 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8865 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8866 break;
8867
40381db7 8868 if (pi) {
ddb5b488
PZ
8869 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8870 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8871
8872 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8873 bgp, pi);
ddb5b488 8874 }
40381db7 8875 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8876 bgp_path_info_delete(dest, pi);
8877 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8878 }
9bcb3eef 8879 bgp_dest_unlock_node(dest);
d62a17ae 8880 }
8881}
8882
8883/* Withdraw specified route type's route. */
8884void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8885 unsigned short instance)
d62a17ae 8886{
9bcb3eef 8887 struct bgp_dest *dest;
40381db7 8888 struct bgp_path_info *pi;
d62a17ae 8889 struct bgp_table *table;
8890
8891 table = bgp->rib[afi][SAFI_UNICAST];
8892
9bcb3eef
DS
8893 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8894 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8895 if (pi->peer == bgp->peer_self && pi->type == type
8896 && pi->instance == instance)
d62a17ae 8897 break;
8898
40381db7 8899 if (pi) {
ddb5b488
PZ
8900 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8901 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8902
8903 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8904 bgp, pi);
ddb5b488 8905 }
9bcb3eef 8906 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8907 pi, afi, SAFI_UNICAST);
9bcb3eef 8908 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8909 if (!CHECK_FLAG(bgp->flags,
8910 BGP_FLAG_DELETE_IN_PROGRESS))
8911 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8912 else
8913 bgp_path_info_reap(dest, pi);
d62a17ae 8914 }
718e3744 8915 }
718e3744 8916}
6b0655a2 8917
718e3744 8918/* Static function to display route. */
7d3cae70
DA
8919static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8920 struct vty *vty, json_object *json, bool wide)
718e3744 8921{
be054588 8922 int len = 0;
07380148 8923 char buf[INET6_ADDRSTRLEN];
718e3744 8924
d62a17ae 8925 if (p->family == AF_INET) {
c6462ff4 8926 if (!json) {
8228a9a7 8927 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8928 } else {
8929 json_object_string_add(json, "prefix",
8930 inet_ntop(p->family,
8931 &p->u.prefix, buf,
07380148 8932 sizeof(buf)));
c6462ff4 8933 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8934 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8935 json_object_int_add(json, "version", dest->version);
c6462ff4 8936 }
d62a17ae 8937 } else if (p->family == AF_ETHERNET) {
8228a9a7 8938 len = vty_out(vty, "%pFX", p);
b03b8898 8939 } else if (p->family == AF_EVPN) {
57f7feb6 8940 if (!json)
2dbe669b 8941 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8942 else
60466a63 8943 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8944 } else if (p->family == AF_FLOWSPEC) {
8945 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8946 json ?
8947 NLRI_STRING_FORMAT_JSON_SIMPLE :
8948 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8949 } else {
c6462ff4 8950 if (!json)
8228a9a7 8951 len = vty_out(vty, "%pFX", p);
50e05855
AD
8952 else {
8953 json_object_string_add(json, "prefix",
07380148
DA
8954 inet_ntop(p->family,
8955 &p->u.prefix, buf,
8956 sizeof(buf)));
50e05855 8957 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8958 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8959 json_object_int_add(json, "version", dest->version);
37d4e0df 8960 }
9c92b5f7 8961 }
d62a17ae 8962
9c92b5f7 8963 if (!json) {
ae248832 8964 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8965 if (len < 1)
8966 vty_out(vty, "\n%*s", 20, " ");
8967 else
8968 vty_out(vty, "%*s", len, " ");
8969 }
718e3744 8970}
8971
d62a17ae 8972enum bgp_display_type {
8973 normal_list,
718e3744 8974};
8975
1d7260a1 8976const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8977{
8978 switch (reason) {
8979 case bgp_path_selection_none:
8980 return "Nothing to Select";
8981 case bgp_path_selection_first:
8982 return "First path received";
8983 case bgp_path_selection_evpn_sticky_mac:
8984 return "EVPN Sticky Mac";
8985 case bgp_path_selection_evpn_seq:
8986 return "EVPN sequence number";
8987 case bgp_path_selection_evpn_lower_ip:
8988 return "EVPN lower IP";
8989 case bgp_path_selection_evpn_local_path:
8990 return "EVPN local ES path";
8991 case bgp_path_selection_evpn_non_proxy:
8992 return "EVPN non proxy";
8993 case bgp_path_selection_weight:
8994 return "Weight";
8995 case bgp_path_selection_local_pref:
8996 return "Local Pref";
46dbf9d0
DA
8997 case bgp_path_selection_accept_own:
8998 return "Accept Own";
bbb46eb5
DA
8999 case bgp_path_selection_local_route:
9000 return "Local Route";
97a52c82
DA
9001 case bgp_path_selection_aigp:
9002 return "AIGP";
bbb46eb5
DA
9003 case bgp_path_selection_confed_as_path:
9004 return "Confederation based AS Path";
9005 case bgp_path_selection_as_path:
9006 return "AS Path";
9007 case bgp_path_selection_origin:
9008 return "Origin";
9009 case bgp_path_selection_med:
9010 return "MED";
9011 case bgp_path_selection_peer:
9012 return "Peer Type";
9013 case bgp_path_selection_confed:
9014 return "Confed Peer Type";
9015 case bgp_path_selection_igp_metric:
9016 return "IGP Metric";
9017 case bgp_path_selection_older:
9018 return "Older Path";
9019 case bgp_path_selection_router_id:
9020 return "Router ID";
9021 case bgp_path_selection_cluster_length:
bcab253c 9022 return "Cluster length";
bbb46eb5
DA
9023 case bgp_path_selection_stale:
9024 return "Path Staleness";
9025 case bgp_path_selection_local_configured:
9026 return "Locally configured route";
9027 case bgp_path_selection_neighbor_ip:
9028 return "Neighbor IP";
9029 case bgp_path_selection_default:
9030 return "Nothing left to compare";
9031 }
9032 return "Invalid (internal error)";
9033}
9034
18ee8310 9035/* Print the short form route status for a bgp_path_info */
4b7e6066 9036static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9037 struct bgp_path_info *path,
82c298be 9038 const struct prefix *p,
d62a17ae 9039 json_object *json_path)
718e3744 9040{
82c298be
DA
9041 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9042
d62a17ae 9043 if (json_path) {
b05a1c8b 9044
d62a17ae 9045 /* Route status display. */
9b6d8fcf 9046 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9047 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9048
9b6d8fcf 9049 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9050 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9051
4056a5f6 9052 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9053 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9054
9b6d8fcf
DS
9055 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9056 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9057 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9058
d62a17ae 9059 /* Selected */
9b6d8fcf 9060 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9061 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9062
9b6d8fcf 9063 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9064 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9065
bbb46eb5 9066 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9067 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9068 json_object_string_add(json_path, "selectionReason",
9069 bgp_path_selection_reason2str(
9070 path->net->reason));
9071 }
b05a1c8b 9072
9b6d8fcf 9073 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9074 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9075
d62a17ae 9076 /* Internal route. */
9b6d8fcf
DS
9077 if ((path->peer->as)
9078 && (path->peer->as == path->peer->local_as))
d62a17ae 9079 json_object_string_add(json_path, "pathFrom",
9080 "internal");
9081 else
9082 json_object_string_add(json_path, "pathFrom",
9083 "external");
b05a1c8b 9084
d62a17ae 9085 return;
9086 }
b05a1c8b 9087
82c298be
DA
9088 /* RPKI validation state */
9089 rpki_state =
9090 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9091
9092 if (rpki_state == RPKI_VALID)
9093 vty_out(vty, "V");
9094 else if (rpki_state == RPKI_INVALID)
9095 vty_out(vty, "I");
9096 else if (rpki_state == RPKI_NOTFOUND)
9097 vty_out(vty, "N");
eaeba5e8
WM
9098 else
9099 vty_out(vty, " ");
82c298be 9100
d62a17ae 9101 /* Route status display. */
9b6d8fcf 9102 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9103 vty_out(vty, "R");
9b6d8fcf 9104 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9105 vty_out(vty, "S");
4056a5f6 9106 else if (bgp_path_suppressed(path))
d62a17ae 9107 vty_out(vty, "s");
9b6d8fcf
DS
9108 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9109 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9110 vty_out(vty, "*");
9111 else
9112 vty_out(vty, " ");
9113
9114 /* Selected */
9b6d8fcf 9115 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9116 vty_out(vty, "h");
9b6d8fcf 9117 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9118 vty_out(vty, "d");
9b6d8fcf 9119 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9120 vty_out(vty, ">");
9b6d8fcf 9121 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9122 vty_out(vty, "=");
9123 else
9124 vty_out(vty, " ");
718e3744 9125
d62a17ae 9126 /* Internal route. */
9b6d8fcf
DS
9127 if (path->peer && (path->peer->as)
9128 && (path->peer->as == path->peer->local_as))
d62a17ae 9129 vty_out(vty, "i");
9130 else
9131 vty_out(vty, " ");
b40d939b 9132}
9133
2ba93fd6
DA
9134static char *bgp_nexthop_hostname(struct peer *peer,
9135 struct bgp_nexthop_cache *bnc)
25b5da8d 9136{
892fedb6 9137 if (peer->hostname
aef999a2 9138 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9139 return peer->hostname;
9140 return NULL;
9141}
9142
b40d939b 9143/* called from terminal list command */
bd494ec5 9144void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9145 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9146 json_object *json_paths, bool wide)
d62a17ae 9147{
aef999a2 9148 int len;
515c2602 9149 struct attr *attr = path->attr;
d62a17ae 9150 json_object *json_path = NULL;
9151 json_object *json_nexthops = NULL;
9152 json_object *json_nexthop_global = NULL;
9153 json_object *json_nexthop_ll = NULL;
6f214dd3 9154 json_object *json_ext_community = NULL;
9df8b37c 9155 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9156 bool nexthop_self =
9b6d8fcf 9157 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9158 bool nexthop_othervrf = false;
43089216 9159 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9160 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9161 char *nexthop_hostname =
9162 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9163 char esi_buf[ESI_STR_LEN];
d62a17ae 9164
9165 if (json_paths)
9166 json_path = json_object_new_object();
9167
9168 /* short status lead text */
82c298be 9169 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9170
9171 if (!json_paths) {
9172 /* print prefix and mask */
9173 if (!display)
7d3cae70 9174 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9175 else
ae248832 9176 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9177 } else {
7d3cae70 9178 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9179 }
47fc97cc 9180
9df8b37c
PZ
9181 /*
9182 * If vrf id of nexthop is different from that of prefix,
9183 * set up printable string to append
9184 */
9b6d8fcf 9185 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9186 const char *self = "";
9187
9188 if (nexthop_self)
9189 self = "<";
9190
9191 nexthop_othervrf = true;
9b6d8fcf 9192 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9193
9b6d8fcf 9194 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9195 snprintf(vrf_id_str, sizeof(vrf_id_str),
9196 "@%s%s", VRFID_NONE_STR, self);
9197 else
9198 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9199 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9200
9b6d8fcf
DS
9201 if (path->extra->bgp_orig->inst_type
9202 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9203
9b6d8fcf 9204 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9205 } else {
9206 const char *self = "";
9207
9208 if (nexthop_self)
9209 self = "<";
9210
9211 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9212 }
9213
445c2480
DS
9214 /*
9215 * For ENCAP and EVPN routes, nexthop address family is not
9216 * neccessarily the same as the prefix address family.
9217 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9218 * EVPN routes are also exchanged with a MP nexthop. Currently,
9219 * this
9220 * is only IPv4, the value will be present in either
9221 * attr->nexthop or
9222 * attr->mp_nexthop_global_in
9223 */
9224 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9225 char nexthop[128];
9226 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9227
9228 switch (af) {
9229 case AF_INET:
07380148
DA
9230 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9231 &attr->mp_nexthop_global_in);
445c2480
DS
9232 break;
9233 case AF_INET6:
07380148
DA
9234 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9235 &attr->mp_nexthop_global);
445c2480
DS
9236 break;
9237 default:
772270f3 9238 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9239 break;
d62a17ae 9240 }
d62a17ae 9241
445c2480
DS
9242 if (json_paths) {
9243 json_nexthop_global = json_object_new_object();
9244
515c2602
DA
9245 json_object_string_add(json_nexthop_global, "ip",
9246 nexthop);
9247
939a97f4 9248 if (path->peer->hostname)
515c2602
DA
9249 json_object_string_add(json_nexthop_global,
9250 "hostname",
939a97f4 9251 path->peer->hostname);
515c2602
DA
9252
9253 json_object_string_add(json_nexthop_global, "afi",
9254 (af == AF_INET) ? "ipv4"
9255 : "ipv6");
445c2480
DS
9256 json_object_boolean_true_add(json_nexthop_global,
9257 "used");
aef999a2
DA
9258 } else {
9259 if (nexthop_hostname)
9260 len = vty_out(vty, "%s(%s)%s", nexthop,
9261 nexthop_hostname, vrf_id_str);
9262 else
9263 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9264
ae248832 9265 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9266 if (len < 1)
9267 vty_out(vty, "\n%*s", 36, " ");
9268 else
9269 vty_out(vty, "%*s", len, " ");
9270 }
445c2480
DS
9271 } else if (safi == SAFI_EVPN) {
9272 if (json_paths) {
9273 json_nexthop_global = json_object_new_object();
9274
c949c771 9275 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9276 "%pI4",
9277 &attr->mp_nexthop_global_in);
515c2602 9278
939a97f4 9279 if (path->peer->hostname)
515c2602
DA
9280 json_object_string_add(json_nexthop_global,
9281 "hostname",
939a97f4 9282 path->peer->hostname);
515c2602 9283
a4d82a8a
PZ
9284 json_object_string_add(json_nexthop_global, "afi",
9285 "ipv4");
445c2480
DS
9286 json_object_boolean_true_add(json_nexthop_global,
9287 "used");
aef999a2
DA
9288 } else {
9289 if (nexthop_hostname)
7226bc40
TA
9290 len = vty_out(vty, "%pI4(%s)%s",
9291 &attr->mp_nexthop_global_in,
aef999a2
DA
9292 nexthop_hostname, vrf_id_str);
9293 else
7226bc40
TA
9294 len = vty_out(vty, "%pI4%s",
9295 &attr->mp_nexthop_global_in,
aef999a2
DA
9296 vrf_id_str);
9297
ae248832 9298 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9299 if (len < 1)
9300 vty_out(vty, "\n%*s", 36, " ");
9301 else
9302 vty_out(vty, "%*s", len, " ");
9303 }
d33fc23b 9304 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9305 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9306 if (json_paths) {
9307 json_nexthop_global = json_object_new_object();
515c2602 9308
026b914a
PG
9309 json_object_string_add(json_nexthop_global,
9310 "afi", "ipv4");
c949c771
DA
9311 json_object_string_addf(json_nexthop_global,
9312 "ip", "%pI4",
9313 &attr->nexthop);
515c2602 9314
939a97f4 9315 if (path->peer->hostname)
515c2602
DA
9316 json_object_string_add(
9317 json_nexthop_global, "hostname",
939a97f4 9318 path->peer->hostname);
515c2602 9319
50e05855
AD
9320 json_object_boolean_true_add(
9321 json_nexthop_global,
026b914a
PG
9322 "used");
9323 } else {
aef999a2
DA
9324 if (nexthop_hostname)
9325 len = vty_out(vty, "%pI4(%s)%s",
9326 &attr->nexthop,
9327 nexthop_hostname,
9328 vrf_id_str);
9329 else
9330 len = vty_out(vty, "%pI4%s",
9331 &attr->nexthop,
9332 vrf_id_str);
9333
ae248832 9334 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9335 if (len < 1)
9336 vty_out(vty, "\n%*s", 36, " ");
9337 else
9338 vty_out(vty, "%*s", len, " ");
026b914a
PG
9339 }
9340 }
7226bc40 9341 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9342 if (json_paths) {
9343 json_nexthop_global = json_object_new_object();
d62a17ae 9344
c949c771
DA
9345 json_object_string_addf(json_nexthop_global, "ip",
9346 "%pI4", &attr->nexthop);
515c2602 9347
939a97f4 9348 if (path->peer->hostname)
515c2602
DA
9349 json_object_string_add(json_nexthop_global,
9350 "hostname",
939a97f4 9351 path->peer->hostname);
445c2480 9352
a4d82a8a
PZ
9353 json_object_string_add(json_nexthop_global, "afi",
9354 "ipv4");
445c2480
DS
9355 json_object_boolean_true_add(json_nexthop_global,
9356 "used");
9357 } else {
aef999a2
DA
9358 if (nexthop_hostname)
9359 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9360 nexthop_hostname, vrf_id_str);
9361 else
9362 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9363 vrf_id_str);
9df8b37c 9364
ae248832 9365 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9366 if (len < 1)
9367 vty_out(vty, "\n%*s", 36, " ");
9368 else
9369 vty_out(vty, "%*s", len, " ");
d62a17ae 9370 }
445c2480 9371 }
b05a1c8b 9372
445c2480 9373 /* IPv6 Next Hop */
7226bc40 9374 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9375 if (json_paths) {
9376 json_nexthop_global = json_object_new_object();
c949c771
DA
9377 json_object_string_addf(json_nexthop_global, "ip",
9378 "%pI6",
9379 &attr->mp_nexthop_global);
515c2602 9380
939a97f4 9381 if (path->peer->hostname)
515c2602
DA
9382 json_object_string_add(json_nexthop_global,
9383 "hostname",
939a97f4 9384 path->peer->hostname);
515c2602 9385
a4d82a8a
PZ
9386 json_object_string_add(json_nexthop_global, "afi",
9387 "ipv6");
9388 json_object_string_add(json_nexthop_global, "scope",
9389 "global");
445c2480
DS
9390
9391 /* We display both LL & GL if both have been
9392 * received */
0606039c
DA
9393 if ((attr->mp_nexthop_len
9394 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9395 || (path->peer->conf_if)) {
a4d82a8a 9396 json_nexthop_ll = json_object_new_object();
c949c771
DA
9397 json_object_string_addf(
9398 json_nexthop_ll, "ip", "%pI6",
9399 &attr->mp_nexthop_local);
515c2602 9400
939a97f4 9401 if (path->peer->hostname)
515c2602
DA
9402 json_object_string_add(
9403 json_nexthop_ll, "hostname",
939a97f4 9404 path->peer->hostname);
515c2602 9405
a4d82a8a
PZ
9406 json_object_string_add(json_nexthop_ll, "afi",
9407 "ipv6");
9408 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9409 "link-local");
d62a17ae 9410
a4d82a8a 9411 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9412 &attr->mp_nexthop_local)
9413 != 0)
9414 && !attr->mp_nexthop_prefer_global)
d62a17ae 9415 json_object_boolean_true_add(
a4d82a8a 9416 json_nexthop_ll, "used");
445c2480
DS
9417 else
9418 json_object_boolean_true_add(
a4d82a8a 9419 json_nexthop_global, "used");
445c2480
DS
9420 } else
9421 json_object_boolean_true_add(
9422 json_nexthop_global, "used");
9423 } else {
9424 /* Display LL if LL/Global both in table unless
9425 * prefer-global is set */
2bb8b49c
DS
9426 if (((attr->mp_nexthop_len
9427 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9428 && !attr->mp_nexthop_prefer_global)
9429 || (path->peer->conf_if)) {
9b6d8fcf 9430 if (path->peer->conf_if) {
a4d82a8a 9431 len = vty_out(vty, "%s",
9b6d8fcf 9432 path->peer->conf_if);
ae248832
MK
9433 /* len of IPv6 addr + max len of def
9434 * ifname */
9435 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9436
9437 if (len < 1)
a4d82a8a 9438 vty_out(vty, "\n%*s", 36, " ");
445c2480 9439 else
a4d82a8a 9440 vty_out(vty, "%*s", len, " ");
d62a17ae 9441 } else {
aef999a2
DA
9442 if (nexthop_hostname)
9443 len = vty_out(
9444 vty, "%pI6(%s)%s",
9445 &attr->mp_nexthop_local,
9446 nexthop_hostname,
9447 vrf_id_str);
9448 else
9449 len = vty_out(
9450 vty, "%pI6%s",
9451 &attr->mp_nexthop_local,
9452 vrf_id_str);
9453
ae248832 9454 len = wide ? (41 - len) : (16 - len);
d62a17ae 9455
9456 if (len < 1)
a4d82a8a 9457 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9458 else
a4d82a8a 9459 vty_out(vty, "%*s", len, " ");
d62a17ae 9460 }
445c2480 9461 } else {
aef999a2
DA
9462 if (nexthop_hostname)
9463 len = vty_out(vty, "%pI6(%s)%s",
9464 &attr->mp_nexthop_global,
9465 nexthop_hostname,
9466 vrf_id_str);
9467 else
9468 len = vty_out(vty, "%pI6%s",
9469 &attr->mp_nexthop_global,
9470 vrf_id_str);
9471
ae248832 9472 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9473
9474 if (len < 1)
9475 vty_out(vty, "\n%*s", 36, " ");
9476 else
9477 vty_out(vty, "%*s", len, " ");
d62a17ae 9478 }
9479 }
445c2480 9480 }
718e3744 9481
445c2480
DS
9482 /* MED/Metric */
9483 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9484 if (json_paths)
50e05855 9485 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9486 else if (wide)
9487 vty_out(vty, "%7u", attr->med);
0fbac0b4 9488 else
445c2480 9489 vty_out(vty, "%10u", attr->med);
ae248832
MK
9490 else if (!json_paths) {
9491 if (wide)
9492 vty_out(vty, "%*s", 7, " ");
9493 else
9494 vty_out(vty, "%*s", 10, " ");
9495 }
d62a17ae 9496
445c2480
DS
9497 /* Local Pref */
9498 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9499 if (json_paths)
50e05855 9500 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9501 attr->local_pref);
9502 else
445c2480
DS
9503 vty_out(vty, "%7u", attr->local_pref);
9504 else if (!json_paths)
9505 vty_out(vty, " ");
d62a17ae 9506
445c2480
DS
9507 if (json_paths)
9508 json_object_int_add(json_path, "weight", attr->weight);
9509 else
9510 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9511
47e12884
DA
9512 if (json_paths)
9513 json_object_string_addf(json_path, "peerId", "%pSU",
9514 &path->peer->su);
b05a1c8b 9515
445c2480
DS
9516 /* Print aspath */
9517 if (attr->aspath) {
0fbac0b4 9518 if (json_paths)
50e05855 9519 json_object_string_add(json_path, "path",
0fbac0b4
DA
9520 attr->aspath->str);
9521 else
e678b143 9522 aspath_print_vty(vty, attr->aspath);
d62a17ae 9523 }
f1aa5d8a 9524
445c2480
DS
9525 /* Print origin */
9526 if (json_paths)
a4d82a8a
PZ
9527 json_object_string_add(json_path, "origin",
9528 bgp_origin_long_str[attr->origin]);
445c2480
DS
9529 else
9530 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9531
9df8b37c 9532 if (json_paths) {
d071f237 9533 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9534 json_object_string_add(json_path, "esi",
9535 esi_to_str(&attr->esi,
9536 esi_buf, sizeof(esi_buf)));
9537 }
6f214dd3
CS
9538 if (safi == SAFI_EVPN &&
9539 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9540 json_ext_community = json_object_new_object();
b53e67a3
DA
9541 json_object_string_add(
9542 json_ext_community, "string",
9543 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9544 json_object_object_add(json_path,
9545 "extendedCommunity",
9546 json_ext_community);
9547 }
9548
9df8b37c
PZ
9549 if (nexthop_self)
9550 json_object_boolean_true_add(json_path,
9551 "announceNexthopSelf");
9552 if (nexthop_othervrf) {
9553 json_object_string_add(json_path, "nhVrfName",
9554 nexthop_vrfname);
9555
9556 json_object_int_add(json_path, "nhVrfId",
9557 ((nexthop_vrfid == VRF_UNKNOWN)
9558 ? -1
9559 : (int)nexthop_vrfid));
9560 }
9561 }
9562
d62a17ae 9563 if (json_paths) {
9564 if (json_nexthop_global || json_nexthop_ll) {
9565 json_nexthops = json_object_new_array();
f1aa5d8a 9566
d62a17ae 9567 if (json_nexthop_global)
9568 json_object_array_add(json_nexthops,
9569 json_nexthop_global);
f1aa5d8a 9570
d62a17ae 9571 if (json_nexthop_ll)
9572 json_object_array_add(json_nexthops,
9573 json_nexthop_ll);
f1aa5d8a 9574
d62a17ae 9575 json_object_object_add(json_path, "nexthops",
9576 json_nexthops);
9577 }
9578
9579 json_object_array_add(json_paths, json_path);
9580 } else {
9581 vty_out(vty, "\n");
6f214dd3 9582
b5e140c8 9583 if (safi == SAFI_EVPN) {
d071f237 9584 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9585 /* XXX - add these params to the json out */
b5e140c8 9586 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9587 vty_out(vty, "ESI:%s",
9588 esi_to_str(&attr->esi, esi_buf,
9589 sizeof(esi_buf)));
60605cbc 9590
229587fb 9591 vty_out(vty, "\n");
b5e140c8
AK
9592 }
9593 if (attr->flag &
9594 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9595 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9596 vty_out(vty, "%s\n",
9597 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9598 }
6f214dd3
CS
9599 }
9600
49e5a4a0 9601#ifdef ENABLE_BGP_VNC
d62a17ae 9602 /* prints an additional line, indented, with VNC info, if
9603 * present */
9604 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9605 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9606#endif
d62a17ae 9607 }
9608}
718e3744 9609
9610/* called from terminal list command */
7d3cae70
DA
9611void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9612 const struct prefix *p, struct attr *attr, safi_t safi,
9613 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9614{
9615 json_object *json_status = NULL;
9616 json_object *json_net = NULL;
aef999a2 9617 int len;
d62a17ae 9618 char buff[BUFSIZ];
dc387b0f 9619
d62a17ae 9620 /* Route status display. */
9621 if (use_json) {
9622 json_status = json_object_new_object();
9623 json_net = json_object_new_object();
9624 } else {
146c574b 9625 vty_out(vty, " *");
d62a17ae 9626 vty_out(vty, ">");
9627 vty_out(vty, " ");
9628 }
718e3744 9629
d62a17ae 9630 /* print prefix and mask */
50e05855 9631 if (use_json) {
dc387b0f
LK
9632 if (safi == SAFI_EVPN)
9633 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9634 else if (p->family == AF_INET || p->family == AF_INET6) {
9635 json_object_string_add(
9636 json_net, "addrPrefix",
9637 inet_ntop(p->family, &p->u.prefix, buff,
9638 BUFSIZ));
9639 json_object_int_add(json_net, "prefixLen",
9640 p->prefixlen);
67d7e256 9641 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9642 }
50e05855 9643 } else
7d3cae70 9644 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9645
9646 /* Print attribute */
9647 if (attr) {
9648 if (use_json) {
7226bc40
TA
9649 if (p->family == AF_INET &&
9650 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9651 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9652 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9653 json_object_string_addf(
9654 json_net, "nextHop", "%pI4",
9655 &attr->mp_nexthop_global_in);
d62a17ae 9656 else
c949c771
DA
9657 json_object_string_addf(
9658 json_net, "nextHop", "%pI4",
9659 &attr->nexthop);
7226bc40
TA
9660 } else if (p->family == AF_INET6 ||
9661 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9662 json_object_string_addf(
9663 json_net, "nextHopGlobal", "%pI6",
9664 &attr->mp_nexthop_global);
7226bc40
TA
9665 } else if (p->family == AF_EVPN &&
9666 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9667 json_object_string_addf(
9668 json_net, "nextHop", "%pI4",
9669 &attr->mp_nexthop_global_in);
23d0a753 9670 }
d62a17ae 9671
9672 if (attr->flag
9673 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9674 json_object_int_add(json_net, "metric",
9675 attr->med);
9676
0fbac0b4 9677 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9678 json_object_int_add(json_net, "locPrf",
0fbac0b4 9679 attr->local_pref);
d62a17ae 9680
9681 json_object_int_add(json_net, "weight", attr->weight);
9682
9683 /* Print aspath */
0fbac0b4 9684 if (attr->aspath)
50e05855 9685 json_object_string_add(json_net, "path",
0fbac0b4 9686 attr->aspath->str);
d62a17ae 9687
9688 /* Print origin */
dd426a51
DA
9689#if CONFDATE > 20231208
9690CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9691#endif
d62a17ae 9692 json_object_string_add(json_net, "bgpOriginCode",
9693 bgp_origin_str[attr->origin]);
dd426a51
DA
9694 json_object_string_add(
9695 json_net, "origin",
9696 bgp_origin_long_str[attr->origin]);
d62a17ae 9697 } else {
7226bc40
TA
9698 if (p->family == AF_INET &&
9699 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9700 safi == SAFI_EVPN ||
9701 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9702 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9703 || safi == SAFI_EVPN)
23d0a753
DA
9704 vty_out(vty, "%-16pI4",
9705 &attr->mp_nexthop_global_in);
ae248832 9706 else if (wide)
23d0a753 9707 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9708 else
23d0a753 9709 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9710 } else if (p->family == AF_INET6 ||
9711 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9712 len = vty_out(vty, "%pI6",
9713 &attr->mp_nexthop_global);
ae248832 9714 len = wide ? (41 - len) : (16 - len);
d62a17ae 9715 if (len < 1)
9716 vty_out(vty, "\n%*s", 36, " ");
9717 else
9718 vty_out(vty, "%*s", len, " ");
9719 }
9720 if (attr->flag
9721 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9722 if (wide)
9723 vty_out(vty, "%7u", attr->med);
9724 else
9725 vty_out(vty, "%10u", attr->med);
9726 else if (wide)
9727 vty_out(vty, " ");
d62a17ae 9728 else
9729 vty_out(vty, " ");
718e3744 9730
d62a17ae 9731 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9732 vty_out(vty, "%7u", attr->local_pref);
9733 else
9734 vty_out(vty, " ");
9735
9736 vty_out(vty, "%7u ", attr->weight);
9737
9738 /* Print aspath */
9739 if (attr->aspath)
e678b143 9740 aspath_print_vty(vty, attr->aspath);
d62a17ae 9741
9742 /* Print origin */
9743 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9744 }
9745 }
9746 if (use_json) {
4d65410c
DA
9747 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9748
dd426a51
DA
9749#if CONFDATE > 20231208
9750CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9751#endif
d62a17ae 9752 json_object_boolean_true_add(json_status, "*");
9753 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9754 json_object_boolean_true_add(json_net, "valid");
9755 json_object_boolean_true_add(json_net, "best");
4d65410c 9756
dd426a51 9757 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9758 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9759 json_object_boolean_true_add(json_net, "multipath");
9760 }
d62a17ae 9761 json_object_object_add(json_net, "appliedStatusSymbols",
9762 json_status);
511211bf 9763 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9764 } else
9765 vty_out(vty, "\n");
9766}
9767
bd494ec5 9768void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9769 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9770 json_object *json)
9771{
9772 json_object *json_out = NULL;
9773 struct attr *attr;
9774 mpls_label_t label = MPLS_INVALID_LABEL;
9775
9b6d8fcf 9776 if (!path->extra)
d62a17ae 9777 return;
9778
9779 if (json)
9780 json_out = json_object_new_object();
9781
9782 /* short status lead text */
82c298be 9783 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9784
9785 /* print prefix and mask */
9786 if (json == NULL) {
9787 if (!display)
7d3cae70 9788 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9789 else
9790 vty_out(vty, "%*s", 17, " ");
9791 }
9792
9793 /* Print attribute */
9b6d8fcf 9794 attr = path->attr;
7226bc40
TA
9795 if (((p->family == AF_INET) &&
9796 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9797 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9798 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9799 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9800 || safi == SAFI_EVPN) {
9801 if (json)
c949c771
DA
9802 json_object_string_addf(
9803 json_out, "mpNexthopGlobalIn", "%pI4",
9804 &attr->mp_nexthop_global_in);
05864da7 9805 else
23d0a753
DA
9806 vty_out(vty, "%-16pI4",
9807 &attr->mp_nexthop_global_in);
05864da7
DS
9808 } else {
9809 if (json)
c949c771
DA
9810 json_object_string_addf(json_out, "nexthop",
9811 "%pI4", &attr->nexthop);
05864da7 9812 else
23d0a753 9813 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9814 }
7226bc40
TA
9815 } else if (((p->family == AF_INET6) &&
9816 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9817 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9818 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9819 char buf_a[512];
9820
9821 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9822 if (json)
c949c771
DA
9823 json_object_string_addf(
9824 json_out, "mpNexthopGlobalIn", "%pI6",
9825 &attr->mp_nexthop_global);
05864da7
DS
9826 else
9827 vty_out(vty, "%s",
9828 inet_ntop(AF_INET6,
9829 &attr->mp_nexthop_global,
9830 buf_a, sizeof(buf_a)));
9831 } else if (attr->mp_nexthop_len
9832 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9833 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9834 &attr->mp_nexthop_global,
9835 &attr->mp_nexthop_local);
9836 if (json)
9837 json_object_string_add(json_out,
9838 "mpNexthopGlobalLocal",
9839 buf_a);
9840 else
9841 vty_out(vty, "%s", buf_a);
d62a17ae 9842 }
9843 }
9844
9b6d8fcf 9845 label = decode_label(&path->extra->label[0]);
d62a17ae 9846
9847 if (bgp_is_valid_label(&label)) {
9848 if (json) {
9849 json_object_int_add(json_out, "notag", label);
9850 json_object_array_add(json, json_out);
9851 } else {
9852 vty_out(vty, "notag/%d", label);
9853 vty_out(vty, "\n");
9854 }
700ddfed
PG
9855 } else if (!json)
9856 vty_out(vty, "\n");
d62a17ae 9857}
718e3744 9858
bd494ec5 9859void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9860 struct bgp_path_info *path, int display,
d62a17ae 9861 json_object *json_paths)
718e3744 9862{
d62a17ae 9863 struct attr *attr;
d62a17ae 9864 json_object *json_path = NULL;
14f51eba
LK
9865 json_object *json_nexthop = NULL;
9866 json_object *json_overlay = NULL;
856ca177 9867
9b6d8fcf 9868 if (!path->extra)
d62a17ae 9869 return;
718e3744 9870
14f51eba
LK
9871 if (json_paths) {
9872 json_path = json_object_new_object();
9873 json_overlay = json_object_new_object();
9874 json_nexthop = json_object_new_object();
9875 }
9876
d62a17ae 9877 /* short status lead text */
82c298be 9878 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9879
d62a17ae 9880 /* print prefix and mask */
9881 if (!display)
7d3cae70 9882 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9883 else
9884 vty_out(vty, "%*s", 17, " ");
9885
9886 /* Print attribute */
9b6d8fcf 9887 attr = path->attr;
05864da7 9888 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9889
05864da7
DS
9890 switch (af) {
9891 case AF_INET:
05864da7 9892 if (!json_path) {
db66cf7c 9893 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9894 } else {
db66cf7c
DA
9895 json_object_string_addf(json_nexthop, "ip", "%pI4",
9896 &attr->mp_nexthop_global_in);
14f51eba 9897
05864da7 9898 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9899
05864da7
DS
9900 json_object_object_add(json_path, "nexthop",
9901 json_nexthop);
9902 }
9903 break;
9904 case AF_INET6:
05864da7 9905 if (!json_path) {
db66cf7c
DA
9906 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9907 &attr->mp_nexthop_local);
05864da7 9908 } else {
db66cf7c
DA
9909 json_object_string_addf(json_nexthop, "ipv6Global",
9910 "%pI6",
9911 &attr->mp_nexthop_global);
14f51eba 9912
db66cf7c
DA
9913 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9914 "%pI6",
9915 &attr->mp_nexthop_local);
14f51eba 9916
05864da7 9917 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9918
05864da7
DS
9919 json_object_object_add(json_path, "nexthop",
9920 json_nexthop);
9921 }
9922 break;
9923 default:
9924 if (!json_path) {
9925 vty_out(vty, "?");
9926 } else {
77a2f8e5
DA
9927 json_object_string_add(json_nexthop, "error",
9928 "Unsupported address-family");
d62a17ae 9929 }
05864da7 9930 }
988258b4 9931
6c924775
DS
9932 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9933
05864da7 9934 if (!json_path)
db66cf7c 9935 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9936 else
db66cf7c 9937 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9938
b53e67a3 9939 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9940 char *mac = NULL;
9941 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9942 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9943 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9944
9945 if (routermac)
9946 mac = ecom_mac2str((char *)routermac->val);
9947 if (mac) {
9948 if (!json_path) {
c4efd0f4 9949 vty_out(vty, "/%s", mac);
05864da7
DS
9950 } else {
9951 json_object_string_add(json_overlay, "rmac",
9952 mac);
988258b4 9953 }
05864da7 9954 XFREE(MTYPE_TMP, mac);
988258b4 9955 }
05864da7 9956 }
718e3744 9957
05864da7
DS
9958 if (!json_path) {
9959 vty_out(vty, "\n");
9960 } else {
9961 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9962
05864da7 9963 json_object_array_add(json_paths, json_path);
14f51eba 9964 }
d62a17ae 9965}
718e3744 9966
d62a17ae 9967/* dampening route */
5f040085
DS
9968static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9969 struct bgp_path_info *path, int display,
9970 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9971 json_object *json_paths)
d62a17ae 9972{
e5be8c1d 9973 struct attr *attr = path->attr;
d62a17ae 9974 int len;
9975 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9976 json_object *json_path = NULL;
9977
9978 if (use_json)
9979 json_path = json_object_new_object();
d62a17ae 9980
9981 /* short status lead text */
e5be8c1d 9982 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9983
9984 /* print prefix and mask */
9985 if (!use_json) {
9986 if (!display)
7d3cae70 9987 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9988 else
9989 vty_out(vty, "%*s", 17, " ");
d62a17ae 9990
e5be8c1d
DA
9991 len = vty_out(vty, "%s", path->peer->host);
9992 len = 17 - len;
9993
9994 if (len < 1)
d62a17ae 9995 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9996 else
9997 vty_out(vty, "%*s", len, " ");
d62a17ae 9998
9b6d8fcf
DS
9999 vty_out(vty, "%s ",
10000 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10001 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 10002 use_json, NULL));
d62a17ae 10003
e5be8c1d 10004 if (attr->aspath)
e678b143 10005 aspath_print_vty(vty, attr->aspath);
05864da7 10006
05864da7
DS
10007 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10008
d62a17ae 10009 vty_out(vty, "\n");
e5be8c1d
DA
10010 } else {
10011 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
10012 safi, use_json, json_path);
10013
10014 if (attr->aspath)
10015 json_object_string_add(json_path, "asPath",
10016 attr->aspath->str);
10017
10018 json_object_string_add(json_path, "origin",
10019 bgp_origin_str[attr->origin]);
10020 json_object_string_add(json_path, "peerHost", path->peer->host);
10021
10022 json_object_array_add(json_paths, json_path);
10023 }
d62a17ae 10024}
718e3744 10025
d62a17ae 10026/* flap route */
5f040085
DS
10027static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10028 struct bgp_path_info *path, int display,
10029 afi_t afi, safi_t safi, bool use_json,
31258046 10030 json_object *json_paths)
784d3a42 10031{
31258046 10032 struct attr *attr = path->attr;
d62a17ae 10033 struct bgp_damp_info *bdi;
10034 char timebuf[BGP_UPTIME_LEN];
10035 int len;
31258046 10036 json_object *json_path = NULL;
784d3a42 10037
9b6d8fcf 10038 if (!path->extra)
d62a17ae 10039 return;
784d3a42 10040
31258046
DA
10041 if (use_json)
10042 json_path = json_object_new_object();
10043
9b6d8fcf 10044 bdi = path->extra->damp_info;
784d3a42 10045
d62a17ae 10046 /* short status lead text */
31258046 10047 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10048
d62a17ae 10049 if (!use_json) {
10050 if (!display)
7d3cae70 10051 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10052 else
10053 vty_out(vty, "%*s", 17, " ");
784d3a42 10054
31258046
DA
10055 len = vty_out(vty, "%s", path->peer->host);
10056 len = 16 - len;
10057 if (len < 1)
d62a17ae 10058 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10059 else
10060 vty_out(vty, "%*s", len, " ");
784d3a42 10061
31258046
DA
10062 len = vty_out(vty, "%d", bdi->flap);
10063 len = 5 - len;
10064 if (len < 1)
d62a17ae 10065 vty_out(vty, " ");
d62a17ae 10066 else
10067 vty_out(vty, "%*s", len, " ");
d62a17ae 10068
996c9314
LB
10069 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10070 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10071
31258046
DA
10072 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10073 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10074 vty_out(vty, "%s ",
9b6d8fcf 10075 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10076 BGP_UPTIME_LEN, afi,
31258046
DA
10077 safi, use_json, NULL));
10078 else
d62a17ae 10079 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10080
31258046 10081 if (attr->aspath)
e678b143 10082 aspath_print_vty(vty, attr->aspath);
05864da7 10083
05864da7
DS
10084 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10085
d62a17ae 10086 vty_out(vty, "\n");
31258046
DA
10087 } else {
10088 json_object_string_add(json_path, "peerHost", path->peer->host);
10089 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10090
10091 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10092 json_path);
10093
10094 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10095 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10096 bgp_damp_reuse_time_vty(vty, path, timebuf,
10097 BGP_UPTIME_LEN, afi, safi,
10098 use_json, json_path);
10099
10100 if (attr->aspath)
10101 json_object_string_add(json_path, "asPath",
10102 attr->aspath->str);
10103
10104 json_object_string_add(json_path, "origin",
10105 bgp_origin_str[attr->origin]);
10106
10107 json_object_array_add(json_paths, json_path);
10108 }
d62a17ae 10109}
10110
10111static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10112 int *first, const char *header,
10113 json_object *json_adv_to)
10114{
d62a17ae 10115 json_object *json_peer = NULL;
10116
10117 if (json_adv_to) {
10118 /* 'advertised-to' is a dictionary of peers we have advertised
10119 * this
10120 * prefix too. The key is the peer's IP or swpX, the value is
10121 * the
10122 * hostname if we know it and "" if not.
10123 */
10124 json_peer = json_object_new_object();
10125
10126 if (peer->hostname)
10127 json_object_string_add(json_peer, "hostname",
10128 peer->hostname);
10129
10130 if (peer->conf_if)
10131 json_object_object_add(json_adv_to, peer->conf_if,
10132 json_peer);
10133 else
47e12884
DA
10134 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10135 &peer->su);
d62a17ae 10136 } else {
10137 if (*first) {
10138 vty_out(vty, "%s", header);
10139 *first = 0;
10140 }
10141
10142 if (peer->hostname
892fedb6 10143 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10144 if (peer->conf_if)
10145 vty_out(vty, " %s(%s)", peer->hostname,
10146 peer->conf_if);
10147 else
47e12884
DA
10148 vty_out(vty, " %s(%pSU)", peer->hostname,
10149 &peer->su);
d62a17ae 10150 } else {
10151 if (peer->conf_if)
10152 vty_out(vty, " %s", peer->conf_if);
10153 else
47e12884 10154 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10155 }
10156 }
784d3a42
PG
10157}
10158
dcc68b5e
MS
10159static void route_vty_out_tx_ids(struct vty *vty,
10160 struct bgp_addpath_info_data *d)
10161{
10162 int i;
10163
10164 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10165 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10166 d->addpath_tx_id[i],
10167 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10168 }
10169}
10170
5e4d4c8a 10171static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10172 struct bgp_path_info *pi,
10173 struct attr *attr,
10174 json_object *json_path)
5e4d4c8a
AK
10175{
10176 char esi_buf[ESI_STR_LEN];
10177 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10178 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10179 ATTR_ES_PEER_ROUTER);
10180 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10181 ATTR_ES_PEER_ACTIVE);
10182 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10183 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10184 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10185 if (json_path) {
10186 json_object *json_es_info = NULL;
10187
10188 json_object_string_add(
10189 json_path, "esi",
10190 esi_buf);
10191 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10192 json_es_info = json_object_new_object();
10193 if (es_local)
10194 json_object_boolean_true_add(
10195 json_es_info, "localEs");
10196 if (peer_active)
10197 json_object_boolean_true_add(
10198 json_es_info, "peerActive");
10199 if (peer_proxy)
10200 json_object_boolean_true_add(
10201 json_es_info, "peerProxy");
10202 if (peer_router)
10203 json_object_boolean_true_add(
10204 json_es_info, "peerRouter");
10205 if (attr->mm_sync_seqnum)
10206 json_object_int_add(
10207 json_es_info, "peerSeq",
10208 attr->mm_sync_seqnum);
10209 json_object_object_add(
10210 json_path, "es_info",
10211 json_es_info);
10212 }
10213 } else {
10214 if (bgp_evpn_attr_is_sync(attr))
10215 vty_out(vty,
10216 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10217 esi_buf,
10218 es_local ? "local-es":"",
10219 peer_proxy ? "proxy " : "",
10220 peer_active ? "active ":"",
10221 peer_router ? "router ":"",
10222 attr->mm_sync_seqnum);
10223 else
10224 vty_out(vty, " ESI %s %s\n",
10225 esi_buf,
10226 es_local ? "local-es":"");
10227 }
10228}
10229
4933eaaf 10230void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10231 const struct prefix *p, struct bgp_path_info *path,
10232 afi_t afi, safi_t safi,
4027d19b
DS
10233 enum rpki_states rpki_curr_state,
10234 json_object *json_paths)
d62a17ae 10235{
10236 char buf[INET6_ADDRSTRLEN];
100290e4 10237 char tag_buf[30];
515c2602 10238 struct attr *attr = path->attr;
d62a17ae 10239 time_t tbuf;
10240 json_object *json_bestpath = NULL;
10241 json_object *json_cluster_list = NULL;
10242 json_object *json_cluster_list_list = NULL;
10243 json_object *json_ext_community = NULL;
10244 json_object *json_last_update = NULL;
7fd077aa 10245 json_object *json_pmsi = NULL;
d62a17ae 10246 json_object *json_nexthop_global = NULL;
10247 json_object *json_nexthop_ll = NULL;
10248 json_object *json_nexthops = NULL;
10249 json_object *json_path = NULL;
10250 json_object *json_peer = NULL;
10251 json_object *json_string = NULL;
10252 json_object *json_adv_to = NULL;
10253 int first = 0;
10254 struct listnode *node, *nnode;
10255 struct peer *peer;
be92fc9f 10256 bool addpath_capable;
d62a17ae 10257 int has_adj;
10258 unsigned int first_as;
1defdda8 10259 bool nexthop_self =
9b6d8fcf 10260 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10261 int i;
2ba93fd6
DA
10262 char *nexthop_hostname =
10263 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10264 uint32_t ttl = 0;
10265 uint32_t bos = 0;
10266 uint32_t exp = 0;
10267 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10268 tag_buf[0] = '\0';
f0cde006
LS
10269 struct bgp_path_info *bpi_ultimate =
10270 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10271
10272 if (json_paths) {
10273 json_path = json_object_new_object();
10274 json_peer = json_object_new_object();
10275 json_nexthop_global = json_object_new_object();
10276 }
10277
8304dabf
AD
10278 if (safi == SAFI_EVPN) {
10279 if (!json_paths)
34c7f35f 10280 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10281 }
10282
44c69747 10283 if (path->extra) {
9b6d8fcf
DS
10284 if (path->extra && path->extra->num_labels) {
10285 bgp_evpn_label2str(path->extra->label,
10286 path->extra->num_labels, tag_buf,
a4d82a8a 10287 sizeof(tag_buf));
d62a17ae 10288 }
d7325ee7 10289 if (safi == SAFI_EVPN) {
44c69747 10290 if (!json_paths) {
44c69747
LK
10291 if (tag_buf[0] != '\0')
10292 vty_out(vty, " VNI %s", tag_buf);
44c69747 10293 } else {
1ce23106 10294 if (tag_buf[0])
77a2f8e5
DA
10295 json_object_string_add(json_path, "vni",
10296 tag_buf);
44c69747 10297 }
d7325ee7 10298 }
d62a17ae 10299 }
d62a17ae 10300
8304dabf
AD
10301 if (safi == SAFI_EVPN
10302 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10303 char gwip_buf[INET6_ADDRSTRLEN];
10304
860e740b
IR
10305 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10306 sizeof(gwip_buf));
8304dabf
AD
10307
10308 if (json_paths)
10309 json_object_string_add(json_path, "gatewayIP",
10310 gwip_buf);
10311 else
10312 vty_out(vty, " Gateway IP %s", gwip_buf);
10313 }
10314
2bf9780b 10315 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10316 vty_out(vty, "\n");
10317
100290e4
SW
10318
10319 if (path->extra && path->extra->parent && !json_paths) {
10320 struct bgp_path_info *parent_ri;
10321 struct bgp_dest *dest, *pdest;
10322
10323 parent_ri = (struct bgp_path_info *)path->extra->parent;
10324 dest = parent_ri->net;
10325 if (dest && dest->pdest) {
10326 pdest = dest->pdest;
10327 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10328 vty_out(vty, " Imported from ");
10329 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10330 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10331 pdest));
10332 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10333 (struct prefix_evpn *)
10334 bgp_dest_get_prefix(dest),
10335 tag_buf);
6012963e 10336 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10337 vty_out(vty, ", L3NHG %s",
6012963e
SW
10338 CHECK_FLAG(
10339 attr->es_flags,
10340 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10341 ? "active"
10342 : "inactive");
10343 vty_out(vty, "\n");
10344
4a8cd6ad
PG
10345 } else {
10346 vty_out(vty, " Imported from ");
10347 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10348 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10349 pdest));
10350 vty_out(vty, ":%pFX\n",
100290e4
SW
10351 (struct prefix_evpn *)
10352 bgp_dest_get_prefix(dest));
4a8cd6ad 10353 }
100290e4
SW
10354 }
10355 }
10356
05864da7
DS
10357 /* Line1 display AS-path, Aggregator */
10358 if (attr->aspath) {
10359 if (json_paths) {
10360 if (!attr->aspath->json)
10361 aspath_str_update(attr->aspath, true);
10362 json_object_lock(attr->aspath->json);
10363 json_object_object_add(json_path, "aspath",
10364 attr->aspath->json);
10365 } else {
10366 if (attr->aspath->segments)
e678b143 10367 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10368 else
05864da7 10369 vty_out(vty, " Local");
d62a17ae 10370 }
05864da7 10371 }
d62a17ae 10372
05864da7
DS
10373 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10374 if (json_paths)
10375 json_object_boolean_true_add(json_path, "removed");
10376 else
10377 vty_out(vty, ", (removed)");
10378 }
d62a17ae 10379
05864da7
DS
10380 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10381 if (json_paths)
10382 json_object_boolean_true_add(json_path, "stale");
10383 else
10384 vty_out(vty, ", (stale)");
10385 }
d62a17ae 10386
05864da7
DS
10387 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10388 if (json_paths) {
10389 json_object_int_add(json_path, "aggregatorAs",
10390 attr->aggregator_as);
c949c771
DA
10391 json_object_string_addf(json_path, "aggregatorId",
10392 "%pI4", &attr->aggregator_addr);
05864da7 10393 } else {
88d495a9
DA
10394 vty_out(vty, ", (aggregated by %u %pI4)",
10395 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10396 }
05864da7 10397 }
d62a17ae 10398
05864da7
DS
10399 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10400 PEER_FLAG_REFLECTOR_CLIENT)) {
10401 if (json_paths)
10402 json_object_boolean_true_add(json_path,
10403 "rxedFromRrClient");
10404 else
10405 vty_out(vty, ", (Received from a RR-client)");
10406 }
d62a17ae 10407
05864da7
DS
10408 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10409 PEER_FLAG_RSERVER_CLIENT)) {
10410 if (json_paths)
10411 json_object_boolean_true_add(json_path,
10412 "rxedFromRsClient");
10413 else
10414 vty_out(vty, ", (Received from a RS-client)");
10415 }
d62a17ae 10416
05864da7
DS
10417 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10418 if (json_paths)
10419 json_object_boolean_true_add(json_path,
10420 "dampeningHistoryEntry");
10421 else
10422 vty_out(vty, ", (history entry)");
10423 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10424 if (json_paths)
10425 json_object_boolean_true_add(json_path,
10426 "dampeningSuppressed");
10427 else
10428 vty_out(vty, ", (suppressed due to dampening)");
10429 }
d62a17ae 10430
05864da7
DS
10431 if (!json_paths)
10432 vty_out(vty, "\n");
d62a17ae 10433
05864da7
DS
10434 /* Line2 display Next-hop, Neighbor, Router-id */
10435 /* Display the nexthop */
b54892e0 10436
34c7f35f
SW
10437 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10438 p->family == AF_EVPN) &&
7226bc40
TA
10439 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10440 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10441 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10442 || safi == SAFI_EVPN) {
515c2602 10443 if (json_paths) {
c949c771
DA
10444 json_object_string_addf(
10445 json_nexthop_global, "ip", "%pI4",
10446 &attr->mp_nexthop_global_in);
515c2602 10447
939a97f4 10448 if (path->peer->hostname)
515c2602
DA
10449 json_object_string_add(
10450 json_nexthop_global, "hostname",
939a97f4 10451 path->peer->hostname);
aef999a2
DA
10452 } else {
10453 if (nexthop_hostname)
10454 vty_out(vty, " %pI4(%s)",
10455 &attr->mp_nexthop_global_in,
10456 nexthop_hostname);
10457 else
10458 vty_out(vty, " %pI4",
10459 &attr->mp_nexthop_global_in);
10460 }
d62a17ae 10461 } else {
515c2602 10462 if (json_paths) {
c949c771
DA
10463 json_object_string_addf(json_nexthop_global,
10464 "ip", "%pI4",
10465 &attr->nexthop);
515c2602 10466
939a97f4 10467 if (path->peer->hostname)
515c2602
DA
10468 json_object_string_add(
10469 json_nexthop_global, "hostname",
939a97f4 10470 path->peer->hostname);
aef999a2
DA
10471 } else {
10472 if (nexthop_hostname)
10473 vty_out(vty, " %pI4(%s)",
10474 &attr->nexthop,
10475 nexthop_hostname);
10476 else
10477 vty_out(vty, " %pI4",
10478 &attr->nexthop);
10479 }
d62a17ae 10480 }
10481
05864da7
DS
10482 if (json_paths)
10483 json_object_string_add(json_nexthop_global, "afi",
10484 "ipv4");
10485 } else {
10486 if (json_paths) {
c949c771
DA
10487 json_object_string_addf(json_nexthop_global, "ip",
10488 "%pI6",
10489 &attr->mp_nexthop_global);
515c2602 10490
939a97f4 10491 if (path->peer->hostname)
515c2602
DA
10492 json_object_string_add(json_nexthop_global,
10493 "hostname",
939a97f4 10494 path->peer->hostname);
515c2602 10495
05864da7
DS
10496 json_object_string_add(json_nexthop_global, "afi",
10497 "ipv6");
10498 json_object_string_add(json_nexthop_global, "scope",
10499 "global");
10500 } else {
aef999a2
DA
10501 if (nexthop_hostname)
10502 vty_out(vty, " %pI6(%s)",
10503 &attr->mp_nexthop_global,
10504 nexthop_hostname);
10505 else
10506 vty_out(vty, " %pI6",
10507 &attr->mp_nexthop_global);
d62a17ae 10508 }
05864da7 10509 }
d62a17ae 10510
05864da7 10511 /* Display the IGP cost or 'inaccessible' */
f0cde006 10512 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10513 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10514
10515 if (json_paths) {
05864da7
DS
10516 json_object_boolean_false_add(json_nexthop_global,
10517 "accessible");
95ba22d5
DA
10518 json_object_boolean_add(json_nexthop_global,
10519 "importCheckEnabled", import);
10520 } else {
10521 vty_out(vty, " (inaccessible%s)",
10522 import ? ", import-check enabled" : "");
10523 }
05864da7 10524 } else {
f0cde006 10525 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10526 if (json_paths)
f0cde006
LS
10527 json_object_int_add(
10528 json_nexthop_global, "metric",
10529 bpi_ultimate->extra->igpmetric);
d62a17ae 10530 else
05864da7 10531 vty_out(vty, " (metric %u)",
f0cde006 10532 bpi_ultimate->extra->igpmetric);
d62a17ae 10533 }
10534
05864da7 10535 /* IGP cost is 0, display this only for json */
d62a17ae 10536 else {
d62a17ae 10537 if (json_paths)
05864da7
DS
10538 json_object_int_add(json_nexthop_global,
10539 "metric", 0);
d62a17ae 10540 }
d62a17ae 10541
05864da7
DS
10542 if (json_paths)
10543 json_object_boolean_true_add(json_nexthop_global,
10544 "accessible");
10545 }
d62a17ae 10546
05864da7
DS
10547 /* Display peer "from" output */
10548 /* This path was originated locally */
10549 if (path->peer == bgp->peer_self) {
d62a17ae 10550
34c7f35f 10551 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10552 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10553 if (json_paths)
05864da7
DS
10554 json_object_string_add(json_peer, "peerId",
10555 "0.0.0.0");
d62a17ae 10556 else
05864da7
DS
10557 vty_out(vty, " from 0.0.0.0 ");
10558 } else {
d62a17ae 10559 if (json_paths)
05864da7
DS
10560 json_object_string_add(json_peer, "peerId",
10561 "::");
d62a17ae 10562 else
05864da7 10563 vty_out(vty, " from :: ");
d62a17ae 10564 }
d62a17ae 10565
4e9a9863 10566 if (json_paths)
c949c771
DA
10567 json_object_string_addf(json_peer, "routerId", "%pI4",
10568 &bgp->router_id);
4e9a9863 10569 else
23d0a753 10570 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10571 }
d62a17ae 10572
05864da7
DS
10573 /* We RXed this path from one of our peers */
10574 else {
10575
10576 if (json_paths) {
47e12884
DA
10577 json_object_string_addf(json_peer, "peerId", "%pSU",
10578 &path->peer->su);
c949c771
DA
10579 json_object_string_addf(json_peer, "routerId", "%pI4",
10580 &path->peer->remote_id);
05864da7
DS
10581
10582 if (path->peer->hostname)
10583 json_object_string_add(json_peer, "hostname",
10584 path->peer->hostname);
10585
10586 if (path->peer->domainname)
10587 json_object_string_add(json_peer, "domainname",
10588 path->peer->domainname);
10589
10590 if (path->peer->conf_if)
10591 json_object_string_add(json_peer, "interface",
10592 path->peer->conf_if);
10593 } else {
10594 if (path->peer->conf_if) {
10595 if (path->peer->hostname
892fedb6
DA
10596 && CHECK_FLAG(path->peer->bgp->flags,
10597 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10598 vty_out(vty, " from %s(%s)",
10599 path->peer->hostname,
10600 path->peer->conf_if);
d62a17ae 10601 else
05864da7 10602 vty_out(vty, " from %s",
9b6d8fcf 10603 path->peer->conf_if);
d62a17ae 10604 } else {
05864da7 10605 if (path->peer->hostname
892fedb6
DA
10606 && CHECK_FLAG(path->peer->bgp->flags,
10607 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10608 vty_out(vty, " from %s(%s)",
10609 path->peer->hostname,
10610 path->peer->host);
d62a17ae 10611 else
47e12884
DA
10612 vty_out(vty, " from %pSU",
10613 &path->peer->su);
d62a17ae 10614 }
d62a17ae 10615
05864da7 10616 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10617 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10618 else
07380148 10619 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10620 }
05864da7 10621 }
9df8b37c 10622
05864da7
DS
10623 /*
10624 * Note when vrfid of nexthop is different from that of prefix
10625 */
10626 if (path->extra && path->extra->bgp_orig) {
10627 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10628
05864da7
DS
10629 if (json_paths) {
10630 const char *vn;
9df8b37c 10631
05864da7
DS
10632 if (path->extra->bgp_orig->inst_type
10633 == BGP_INSTANCE_TYPE_DEFAULT)
10634 vn = VRF_DEFAULT_NAME;
10635 else
10636 vn = path->extra->bgp_orig->name;
9df8b37c 10637
05864da7 10638 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10639
05864da7
DS
10640 if (nexthop_vrfid == VRF_UNKNOWN) {
10641 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10642 } else {
05864da7
DS
10643 json_object_int_add(json_path, "nhVrfId",
10644 (int)nexthop_vrfid);
9df8b37c 10645 }
05864da7
DS
10646 } else {
10647 if (nexthop_vrfid == VRF_UNKNOWN)
10648 vty_out(vty, " vrf ?");
137147c6
DS
10649 else {
10650 struct vrf *vrf;
10651
10652 vrf = vrf_lookup_by_id(nexthop_vrfid);
10653 vty_out(vty, " vrf %s(%u)",
10654 VRF_LOGNAME(vrf), nexthop_vrfid);
10655 }
9df8b37c 10656 }
05864da7 10657 }
9df8b37c 10658
05864da7
DS
10659 if (nexthop_self) {
10660 if (json_paths) {
10661 json_object_boolean_true_add(json_path,
10662 "announceNexthopSelf");
10663 } else {
10664 vty_out(vty, " announce-nh-self");
9df8b37c 10665 }
05864da7 10666 }
9df8b37c 10667
05864da7
DS
10668 if (!json_paths)
10669 vty_out(vty, "\n");
d62a17ae 10670
05864da7
DS
10671 /* display the link-local nexthop */
10672 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10673 if (json_paths) {
10674 json_nexthop_ll = json_object_new_object();
c949c771
DA
10675 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10676 &attr->mp_nexthop_local);
515c2602 10677
939a97f4 10678 if (path->peer->hostname)
515c2602
DA
10679 json_object_string_add(json_nexthop_ll,
10680 "hostname",
939a97f4 10681 path->peer->hostname);
515c2602 10682
05864da7
DS
10683 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10684 json_object_string_add(json_nexthop_ll, "scope",
10685 "link-local");
d62a17ae 10686
05864da7
DS
10687 json_object_boolean_true_add(json_nexthop_ll,
10688 "accessible");
d62a17ae 10689
2bb8b49c 10690 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10691 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10692 "used");
10693 else
10694 json_object_boolean_true_add(
10695 json_nexthop_global, "used");
10696 } else {
10697 vty_out(vty, " (%s) %s\n",
10698 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10699 buf, INET6_ADDRSTRLEN),
2bb8b49c 10700 attr->mp_nexthop_prefer_global
05864da7
DS
10701 ? "(prefer-global)"
10702 : "(used)");
d62a17ae 10703 }
05864da7
DS
10704 }
10705 /* If we do not have a link-local nexthop then we must flag the
10706 global as "used" */
10707 else {
10708 if (json_paths)
10709 json_object_boolean_true_add(json_nexthop_global,
10710 "used");
10711 }
d62a17ae 10712
b5e140c8 10713 if (safi == SAFI_EVPN &&
5e4d4c8a 10714 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10715 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10716 }
10717
05864da7
DS
10718 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10719 * Int/Ext/Local, Atomic, best */
10720 if (json_paths)
10721 json_object_string_add(json_path, "origin",
10722 bgp_origin_long_str[attr->origin]);
10723 else
10724 vty_out(vty, " Origin %s",
10725 bgp_origin_long_str[attr->origin]);
9df8b37c 10726
05864da7 10727 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10728 if (json_paths)
05864da7 10729 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10730 else
05864da7
DS
10731 vty_out(vty, ", metric %u", attr->med);
10732 }
9df8b37c 10733
05864da7
DS
10734 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10735 if (json_paths)
0fbac0b4 10736 json_object_int_add(json_path, "locPrf",
05864da7
DS
10737 attr->local_pref);
10738 else
10739 vty_out(vty, ", localpref %u", attr->local_pref);
10740 }
9df8b37c 10741
97a52c82
DA
10742 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10743 if (json_paths)
10744 json_object_int_add(json_path, "aigpMetric",
10745 bgp_attr_get_aigp_metric(attr));
10746 else
10747 vty_out(vty, ", aigp-metric %" PRIu64,
10748 bgp_attr_get_aigp_metric(attr));
10749 }
10750
05864da7
DS
10751 if (attr->weight != 0) {
10752 if (json_paths)
10753 json_object_int_add(json_path, "weight", attr->weight);
10754 else
10755 vty_out(vty, ", weight %u", attr->weight);
10756 }
9df8b37c 10757
05864da7
DS
10758 if (attr->tag != 0) {
10759 if (json_paths)
10760 json_object_int_add(json_path, "tag", attr->tag);
10761 else
10762 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10763 }
9df8b37c 10764
05864da7
DS
10765 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10766 if (json_paths)
10767 json_object_boolean_false_add(json_path, "valid");
10768 else
10769 vty_out(vty, ", invalid");
10770 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10771 if (json_paths)
10772 json_object_boolean_true_add(json_path, "valid");
10773 else
10774 vty_out(vty, ", valid");
10775 }
9df8b37c 10776
7d3cae70
DA
10777 if (json_paths)
10778 json_object_int_add(json_path, "version", bn->version);
10779
05864da7
DS
10780 if (path->peer != bgp->peer_self) {
10781 if (path->peer->as == path->peer->local_as) {
10782 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10783 if (json_paths)
10784 json_object_string_add(
10785 json_peer, "type",
10786 "confed-internal");
d62a17ae 10787 else
05864da7 10788 vty_out(vty, ", confed-internal");
d62a17ae 10789 } else {
05864da7
DS
10790 if (json_paths)
10791 json_object_string_add(
10792 json_peer, "type", "internal");
10793 else
10794 vty_out(vty, ", internal");
9df8b37c 10795 }
05864da7
DS
10796 } else {
10797 if (bgp_confederation_peers_check(bgp,
10798 path->peer->as)) {
10799 if (json_paths)
10800 json_object_string_add(
10801 json_peer, "type",
10802 "confed-external");
d62a17ae 10803 else
05864da7 10804 vty_out(vty, ", confed-external");
d62a17ae 10805 } else {
05864da7
DS
10806 if (json_paths)
10807 json_object_string_add(
10808 json_peer, "type", "external");
10809 else
10810 vty_out(vty, ", external");
d62a17ae 10811 }
10812 }
05864da7
DS
10813 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10814 if (json_paths) {
10815 json_object_boolean_true_add(json_path, "aggregated");
10816 json_object_boolean_true_add(json_path, "local");
10817 } else {
10818 vty_out(vty, ", aggregated, local");
10819 }
10820 } else if (path->type != ZEBRA_ROUTE_BGP) {
10821 if (json_paths)
10822 json_object_boolean_true_add(json_path, "sourced");
10823 else
10824 vty_out(vty, ", sourced");
10825 } else {
10826 if (json_paths) {
10827 json_object_boolean_true_add(json_path, "sourced");
10828 json_object_boolean_true_add(json_path, "local");
10829 } else {
10830 vty_out(vty, ", sourced, local");
d62a17ae 10831 }
05864da7 10832 }
718e3744 10833
05864da7 10834 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10835 if (json_paths)
05864da7
DS
10836 json_object_boolean_true_add(json_path,
10837 "atomicAggregate");
d62a17ae 10838 else
05864da7
DS
10839 vty_out(vty, ", atomic-aggregate");
10840 }
d62a17ae 10841
d864dd9e
EB
10842 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10843 if (json_paths)
10844 json_object_int_add(json_path, "otc", attr->otc);
10845 else
10846 vty_out(vty, ", otc %u", attr->otc);
10847 }
10848
05864da7
DS
10849 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10850 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10851 && bgp_path_info_mpath_count(path))) {
10852 if (json_paths)
10853 json_object_boolean_true_add(json_path, "multipath");
10854 else
10855 vty_out(vty, ", multipath");
10856 }
50e05855 10857
05864da7
DS
10858 // Mark the bestpath(s)
10859 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10860 first_as = aspath_get_first_as(attr->aspath);
718e3744 10861
05864da7
DS
10862 if (json_paths) {
10863 if (!json_bestpath)
10864 json_bestpath = json_object_new_object();
10865 json_object_int_add(json_bestpath, "bestpathFromAs",
10866 first_as);
10867 } else {
10868 if (first_as)
10869 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10870 else
05864da7 10871 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10872 }
05864da7 10873 }
718e3744 10874
05864da7
DS
10875 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10876 if (json_paths) {
10877 if (!json_bestpath)
10878 json_bestpath = json_object_new_object();
10879 json_object_boolean_true_add(json_bestpath, "overall");
10880 json_object_string_add(
10881 json_bestpath, "selectionReason",
10882 bgp_path_selection_reason2str(bn->reason));
10883 } else {
10884 vty_out(vty, ", best");
10885 vty_out(vty, " (%s)",
10886 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10887 }
05864da7 10888 }
718e3744 10889
4027d19b 10890 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10891 if (json_paths)
10892 json_object_string_add(
10893 json_path, "rpkiValidationState",
4027d19b 10894 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10895 else
1d327209 10896 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10897 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10898 }
10899
05864da7
DS
10900 if (json_bestpath)
10901 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10902
05864da7
DS
10903 if (!json_paths)
10904 vty_out(vty, "\n");
10905
10906 /* Line 4 display Community */
29e72930 10907 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10908 if (json_paths) {
9a706b42
DA
10909 if (!bgp_attr_get_community(attr)->json)
10910 community_str(bgp_attr_get_community(attr),
c0945b78 10911 true, true);
9a706b42
DA
10912 json_object_lock(bgp_attr_get_community(attr)->json);
10913 json_object_object_add(
10914 json_path, "community",
10915 bgp_attr_get_community(attr)->json);
05864da7
DS
10916 } else {
10917 vty_out(vty, " Community: %s\n",
9a706b42 10918 bgp_attr_get_community(attr)->str);
d62a17ae 10919 }
05864da7 10920 }
718e3744 10921
05864da7
DS
10922 /* Line 5 display Extended-community */
10923 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10924 if (json_paths) {
10925 json_ext_community = json_object_new_object();
b53e67a3
DA
10926 json_object_string_add(
10927 json_ext_community, "string",
10928 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10929 json_object_object_add(json_path, "extendedCommunity",
10930 json_ext_community);
d62a17ae 10931 } else {
05864da7 10932 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10933 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10934 }
05864da7 10935 }
718e3744 10936
05864da7
DS
10937 /* Line 6 display Large community */
10938 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10939 if (json_paths) {
1bcf3a96
DA
10940 if (!bgp_attr_get_lcommunity(attr)->json)
10941 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10942 true, true);
1bcf3a96
DA
10943 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10944 json_object_object_add(
10945 json_path, "largeCommunity",
10946 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10947 } else {
10948 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10949 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10950 }
05864da7 10951 }
718e3744 10952
05864da7
DS
10953 /* Line 7 display Originator, Cluster-id */
10954 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10955 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10956 char buf[BUFSIZ] = {0};
10957
05864da7 10958 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10959 if (json_paths)
c949c771
DA
10960 json_object_string_addf(json_path,
10961 "originatorId", "%pI4",
10962 &attr->originator_id);
d62a17ae 10963 else
23d0a753
DA
10964 vty_out(vty, " Originator: %pI4",
10965 &attr->originator_id);
d62a17ae 10966 }
856ca177 10967
05864da7 10968 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10969 struct cluster_list *cluster =
10970 bgp_attr_get_cluster(attr);
05864da7 10971 int i;
d62a17ae 10972
10973 if (json_paths) {
05864da7
DS
10974 json_cluster_list = json_object_new_object();
10975 json_cluster_list_list =
10976 json_object_new_array();
10977
779fee93 10978 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10979 json_string = json_object_new_string(
779fee93
DS
10980 inet_ntop(AF_INET,
10981 &cluster->list[i],
10982 buf, sizeof(buf)));
05864da7
DS
10983 json_object_array_add(
10984 json_cluster_list_list,
10985 json_string);
10986 }
718e3744 10987
05864da7
DS
10988 /*
10989 * struct cluster_list does not have
10990 * "str" variable like aspath and community
10991 * do. Add this someday if someone asks
10992 * for it.
10993 * json_object_string_add(json_cluster_list,
779fee93 10994 * "string", cluster->str);
05864da7
DS
10995 */
10996 json_object_object_add(json_cluster_list,
10997 "list",
10998 json_cluster_list_list);
10999 json_object_object_add(json_path, "clusterList",
11000 json_cluster_list);
0dc8ee70 11001 } else {
05864da7
DS
11002 vty_out(vty, ", Cluster list: ");
11003
779fee93 11004 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 11005 vty_out(vty, "%pI4 ",
779fee93 11006 &cluster->list[i]);
05864da7 11007 }
0dc8ee70 11008 }
d62a17ae 11009 }
718e3744 11010
d62a17ae 11011 if (!json_paths)
11012 vty_out(vty, "\n");
05864da7 11013 }
d62a17ae 11014
05864da7 11015 if (path->extra && path->extra->damp_info)
b4f7f45b 11016 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 11017
05864da7
DS
11018 /* Remote Label */
11019 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
11020 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
11021 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
11022 &bos);
d62a17ae 11023
05864da7
DS
11024 if (json_paths)
11025 json_object_int_add(json_path, "remoteLabel", label);
11026 else
11027 vty_out(vty, " Remote label: %d\n", label);
11028 }
d62a17ae 11029
e496b420
HS
11030 /* Remote SID */
11031 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 11032 if (json_paths)
07380148
DA
11033 json_object_string_addf(json_path, "remoteSid", "%pI6",
11034 &path->extra->sid[0].sid);
e496b420 11035 else
07380148
DA
11036 vty_out(vty, " Remote SID: %pI6\n",
11037 &path->extra->sid[0].sid);
e496b420
HS
11038 }
11039
05864da7
DS
11040 /* Label Index */
11041 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11042 if (json_paths)
11043 json_object_int_add(json_path, "labelIndex",
11044 attr->label_index);
11045 else
11046 vty_out(vty, " Label Index: %d\n",
11047 attr->label_index);
11048 }
d62a17ae 11049
05864da7
DS
11050 /* Line 8 display Addpath IDs */
11051 if (path->addpath_rx_id
11052 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11053 if (json_paths) {
11054 json_object_int_add(json_path, "addpathRxId",
11055 path->addpath_rx_id);
d62a17ae 11056
05864da7
DS
11057 /* Keep backwards compatibility with the old API
11058 * by putting TX All's ID in the old field
11059 */
11060 json_object_int_add(
11061 json_path, "addpathTxId",
11062 path->tx_addpath
11063 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11064
05864da7
DS
11065 /* ... but create a specific field for each
11066 * strategy
11067 */
11068 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11069 json_object_int_add(
11070 json_path,
11071 bgp_addpath_names(i)->id_json_name,
11072 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11073 }
05864da7
DS
11074 } else {
11075 vty_out(vty, " AddPath ID: RX %u, ",
11076 path->addpath_rx_id);
d62a17ae 11077
05864da7 11078 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11079 }
05864da7 11080 }
520d5d76 11081
05864da7
DS
11082 /* If we used addpath to TX a non-bestpath we need to display
11083 * "Advertised to" on a path-by-path basis
11084 */
11085 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11086 first = 1;
dcc68b5e 11087
05864da7
DS
11088 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11089 addpath_capable =
11090 bgp_addpath_encode_tx(peer, afi, safi);
11091 has_adj = bgp_adj_out_lookup(
11092 peer, path->net,
11093 bgp_addpath_id_for_peer(peer, afi, safi,
11094 &path->tx_addpath));
11095
11096 if ((addpath_capable && has_adj)
11097 || (!addpath_capable && has_adj
11098 && CHECK_FLAG(path->flags,
11099 BGP_PATH_SELECTED))) {
11100 if (json_path && !json_adv_to)
11101 json_adv_to = json_object_new_object();
dcc68b5e 11102
05864da7
DS
11103 route_vty_out_advertised_to(
11104 vty, peer, &first,
11105 " Advertised to:", json_adv_to);
d62a17ae 11106 }
11107 }
718e3744 11108
05864da7
DS
11109 if (json_path) {
11110 if (json_adv_to) {
11111 json_object_object_add(
11112 json_path, "advertisedTo", json_adv_to);
d62a17ae 11113 }
05864da7
DS
11114 } else {
11115 if (!first) {
11116 vty_out(vty, "\n");
d62a17ae 11117 }
11118 }
05864da7 11119 }
b05a1c8b 11120
05864da7 11121 /* Line 9 display Uptime */
083ec940 11122 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11123 if (json_paths) {
11124 json_last_update = json_object_new_object();
11125 json_object_int_add(json_last_update, "epoch", tbuf);
11126 json_object_string_add(json_last_update, "string",
11127 ctime(&tbuf));
11128 json_object_object_add(json_path, "lastUpdate",
11129 json_last_update);
11130 } else
11131 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11132
05864da7
DS
11133 /* Line 10 display PMSI tunnel attribute, if present */
11134 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11135 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11136 bgp_attr_get_pmsi_tnl_type(attr),
11137 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11138
05864da7
DS
11139 if (json_paths) {
11140 json_pmsi = json_object_new_object();
11141 json_object_string_add(json_pmsi, "tunnelType", str);
11142 json_object_int_add(json_pmsi, "label",
11143 label2vni(&attr->label));
11144 json_object_object_add(json_path, "pmsi", json_pmsi);
11145 } else
11146 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11147 str, label2vni(&attr->label));
d62a17ae 11148 }
f1aa5d8a 11149
848e8cf6
DA
11150 if (path->peer->t_gr_restart &&
11151 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11152 unsigned long gr_remaining =
4f830a07 11153 event_timer_remain_second(path->peer->t_gr_restart);
848e8cf6
DA
11154
11155 if (json_paths) {
11156 json_object_int_add(json_path,
11157 "gracefulRestartSecondsRemaining",
11158 gr_remaining);
11159 } else
11160 vty_out(vty,
11161 " Time until Graceful Restart stale route deleted: %lu\n",
11162 gr_remaining);
11163 }
11164
9a706b42
DA
11165 if (path->peer->t_llgr_stale[afi][safi] &&
11166 bgp_attr_get_community(attr) &&
11167 community_include(bgp_attr_get_community(attr),
11168 COMMUNITY_LLGR_STALE)) {
4f830a07 11169 unsigned long llgr_remaining = event_timer_remain_second(
48ebba04 11170 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11171
48ebba04
DA
11172 if (json_paths) {
11173 json_object_int_add(json_path, "llgrSecondsRemaining",
11174 llgr_remaining);
11175 } else
11176 vty_out(vty,
11177 " Time until Long-lived stale route deleted: %lu\n",
11178 llgr_remaining);
11179 }
11180
92269aa2
DS
11181 /* Output some debug about internal state of the dest flags */
11182 if (json_paths) {
11183 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11184 json_object_boolean_true_add(json_path, "processScheduled");
11185 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11186 json_object_boolean_true_add(json_path, "userCleared");
11187 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11188 json_object_boolean_true_add(json_path, "labelChanged");
11189 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11190 json_object_boolean_true_add(json_path, "registeredForLabel");
11191 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11192 json_object_boolean_true_add(json_path, "selectDefered");
11193 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11194 json_object_boolean_true_add(json_path, "fibInstalled");
11195 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11196 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11197
d62a17ae 11198 if (json_nexthop_global || json_nexthop_ll) {
11199 json_nexthops = json_object_new_array();
f1aa5d8a 11200
d62a17ae 11201 if (json_nexthop_global)
11202 json_object_array_add(json_nexthops,
11203 json_nexthop_global);
f1aa5d8a 11204
d62a17ae 11205 if (json_nexthop_ll)
11206 json_object_array_add(json_nexthops,
11207 json_nexthop_ll);
f1aa5d8a 11208
d62a17ae 11209 json_object_object_add(json_path, "nexthops",
11210 json_nexthops);
11211 }
11212
11213 json_object_object_add(json_path, "peer", json_peer);
11214 json_object_array_add(json_paths, json_path);
05864da7 11215 }
b366b518
BB
11216}
11217
96ade3ed 11218#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11219#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11220#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11221
a4d82a8a 11222static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11223 afi_t afi, safi_t safi, enum bgp_show_type type,
11224 bool use_json);
7f323236
DW
11225static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11226 const char *comstr, int exact, afi_t afi,
96c81f66 11227 safi_t safi, uint16_t show_flags);
d62a17ae 11228
1ae44dfc 11229static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11230 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11231 void *output_arg, const char *rd, int is_last,
96f3485c 11232 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11233 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11234 enum rpki_states rpki_target_state)
d62a17ae 11235{
40381db7 11236 struct bgp_path_info *pi;
9bcb3eef 11237 struct bgp_dest *dest;
2aad8c42
MS
11238 bool header = true;
11239 bool json_detail_header = false;
d62a17ae 11240 int display;
1ae44dfc
LB
11241 unsigned long output_count = 0;
11242 unsigned long total_count = 0;
d62a17ae 11243 struct prefix *p;
d62a17ae 11244 json_object *json_paths = NULL;
11245 int first = 1;
96f3485c
MK
11246 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11247 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11248 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11249 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11250 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11251
1ae44dfc 11252 if (output_cum && *output_cum != 0)
2aad8c42 11253 header = false;
1ae44dfc 11254
9386b588 11255 if (use_json && !*json_header_depth) {
96f3485c
MK
11256 if (all)
11257 *json_header_depth = 1;
11258 else {
11259 vty_out(vty, "{\n");
11260 *json_header_depth = 2;
11261 }
d62a17ae 11262 vty_out(vty,
23d0a753
DA
11263 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11264 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11265 " \"localAS\": ",
a8bf7d9c 11266 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11267 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11268 ? VRF_DEFAULT_NAME
11269 : bgp->name,
11270 table->version, &bgp->router_id,
e84c7c12
PG
11271 bgp->default_local_pref);
11272 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11273 ((bgp->asnotation == ASNOTATION_DOT) &&
11274 (bgp->as < UINT16_MAX)))
11275 vty_out(vty, "%u", bgp->as);
11276 else {
11277 vty_out(vty, "\"");
11278 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11279 vty_out(vty, "\"");
11280 }
11281 vty_out(vty, ",\n \"routes\": { ");
9386b588 11282 if (rd) {
445c2480 11283 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11284 ++*json_header_depth;
11285 }
d62a17ae 11286 }
718e3744 11287
445c2480
DS
11288 if (use_json && rd) {
11289 vty_out(vty, " \"%s\" : { ", rd);
11290 }
11291
2aad8c42 11292 /* Check for 'json detail', where we need header output once per dest */
67799a48 11293 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11294 type != bgp_show_type_damp_neighbor &&
11295 type != bgp_show_type_flap_statistics &&
11296 type != bgp_show_type_flap_neighbor)
11297 json_detail_header = true;
11298
d62a17ae 11299 /* Start processing of routes. */
9bcb3eef
DS
11300 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11301 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11302 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
f9f2d188 11303 bool json_detail_header_used = false;
b54892e0 11304
9bcb3eef 11305 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11306 if (pi == NULL)
98ce9a06 11307 continue;
d62a17ae 11308
98ce9a06 11309 display = 0;
98ce9a06
DS
11310 if (use_json)
11311 json_paths = json_object_new_array();
11312 else
11313 json_paths = NULL;
d62a17ae 11314
6f94b685 11315 for (; pi; pi = pi->next) {
9a706b42
DA
11316 struct community *picomm = NULL;
11317
11318 picomm = bgp_attr_get_community(pi->attr);
11319
98ce9a06 11320 total_count++;
1e2ce4f1 11321
7d3cae70
DA
11322 if (type == bgp_show_type_prefix_version) {
11323 uint32_t version =
11324 strtoul(output_arg, NULL, 10);
11325 if (dest->version < version)
11326 continue;
11327 }
11328
a70a28a5
DA
11329 if (type == bgp_show_type_community_alias) {
11330 char *alias = output_arg;
11331 char **communities;
11332 int num;
11333 bool found = false;
11334
9a706b42
DA
11335 if (picomm) {
11336 frrstr_split(picomm->str, " ",
11337 &communities, &num);
a70a28a5
DA
11338 for (int i = 0; i < num; i++) {
11339 const char *com2alias =
11340 bgp_community2alias(
11341 communities[i]);
cd9cc0e6
IR
11342 if (!found
11343 && strcmp(alias, com2alias)
11344 == 0)
a70a28a5 11345 found = true;
cd9cc0e6
IR
11346 XFREE(MTYPE_TMP,
11347 communities[i]);
a70a28a5 11348 }
cd9cc0e6 11349 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11350 }
11351
1bcf3a96
DA
11352 if (!found &&
11353 bgp_attr_get_lcommunity(pi->attr)) {
11354 frrstr_split(bgp_attr_get_lcommunity(
11355 pi->attr)
11356 ->str,
a70a28a5
DA
11357 " ", &communities, &num);
11358 for (int i = 0; i < num; i++) {
11359 const char *com2alias =
11360 bgp_community2alias(
11361 communities[i]);
cd9cc0e6
IR
11362 if (!found
11363 && strcmp(alias, com2alias)
11364 == 0)
a70a28a5 11365 found = true;
cd9cc0e6
IR
11366 XFREE(MTYPE_TMP,
11367 communities[i]);
a70a28a5 11368 }
cd9cc0e6 11369 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11370 }
11371
11372 if (!found)
11373 continue;
11374 }
11375
1e2ce4f1
DS
11376 if (type == bgp_show_type_rpki) {
11377 if (dest_p->family == AF_INET
11378 || dest_p->family == AF_INET6)
4027d19b 11379 rpki_curr_state = hook_call(
1e2ce4f1
DS
11380 bgp_rpki_prefix_status,
11381 pi->peer, pi->attr, dest_p);
4027d19b
DS
11382 if (rpki_target_state != RPKI_NOT_BEING_USED
11383 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11384 continue;
11385 }
11386
98ce9a06
DS
11387 if (type == bgp_show_type_flap_statistics
11388 || type == bgp_show_type_flap_neighbor
11389 || type == bgp_show_type_dampend_paths
11390 || type == bgp_show_type_damp_neighbor) {
40381db7 11391 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11392 continue;
11393 }
11394 if (type == bgp_show_type_regexp) {
11395 regex_t *regex = output_arg;
d62a17ae 11396
40381db7 11397 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11398 == REG_NOMATCH)
11399 continue;
11400 }
11401 if (type == bgp_show_type_prefix_list) {
11402 struct prefix_list *plist = output_arg;
d62a17ae 11403
9bcb3eef 11404 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11405 != PREFIX_PERMIT)
11406 continue;
11407 }
ed126382
DA
11408 if (type == bgp_show_type_access_list) {
11409 struct access_list *alist = output_arg;
11410
11411 if (access_list_apply(alist, dest_p) !=
11412 FILTER_PERMIT)
11413 continue;
11414 }
98ce9a06
DS
11415 if (type == bgp_show_type_filter_list) {
11416 struct as_list *as_list = output_arg;
d62a17ae 11417
40381db7 11418 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11419 != AS_FILTER_PERMIT)
11420 continue;
11421 }
11422 if (type == bgp_show_type_route_map) {
11423 struct route_map *rmap = output_arg;
9b6d8fcf 11424 struct bgp_path_info path;
636632c3
DA
11425 struct bgp_path_info_extra extra;
11426 struct attr dummy_attr = {};
b68885f9 11427 route_map_result_t ret;
d62a17ae 11428
6f4f49b2 11429 dummy_attr = *pi->attr;
d62a17ae 11430
636632c3
DA
11431 prep_for_rmap_apply(&path, &extra, dest, pi,
11432 pi->peer, &dummy_attr);
d62a17ae 11433
1782514f 11434 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11435 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11436 if (ret == RMAP_DENYMATCH)
11437 continue;
11438 }
11439 if (type == bgp_show_type_neighbor
11440 || type == bgp_show_type_flap_neighbor
11441 || type == bgp_show_type_damp_neighbor) {
11442 union sockunion *su = output_arg;
11443
40381db7
DS
11444 if (pi->peer == NULL
11445 || pi->peer->su_remote == NULL
11446 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11447 continue;
11448 }
11449 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11450 uint32_t destination;
d62a17ae 11451
9bcb3eef 11452 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11453 if (IN_CLASSC(destination)
9bcb3eef 11454 && dest_p->prefixlen == 24)
98ce9a06
DS
11455 continue;
11456 if (IN_CLASSB(destination)
9bcb3eef 11457 && dest_p->prefixlen == 16)
98ce9a06
DS
11458 continue;
11459 if (IN_CLASSA(destination)
9bcb3eef 11460 && dest_p->prefixlen == 8)
98ce9a06
DS
11461 continue;
11462 }
11463 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11464 p = output_arg;
9bcb3eef 11465 if (!prefix_match(p, dest_p))
98ce9a06
DS
11466 continue;
11467 }
11468 if (type == bgp_show_type_community_all) {
9a706b42 11469 if (!picomm)
98ce9a06
DS
11470 continue;
11471 }
11472 if (type == bgp_show_type_community) {
11473 struct community *com = output_arg;
d62a17ae 11474
9a706b42 11475 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11476 continue;
11477 }
11478 if (type == bgp_show_type_community_exact) {
11479 struct community *com = output_arg;
d62a17ae 11480
9a706b42 11481 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11482 continue;
11483 }
11484 if (type == bgp_show_type_community_list) {
11485 struct community_list *list = output_arg;
d62a17ae 11486
9a706b42 11487 if (!community_list_match(picomm, list))
98ce9a06
DS
11488 continue;
11489 }
a4d82a8a 11490 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11491 struct community_list *list = output_arg;
d62a17ae 11492
9a706b42 11493 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11494 continue;
11495 }
11496 if (type == bgp_show_type_lcommunity) {
11497 struct lcommunity *lcom = output_arg;
d62a17ae 11498
1bcf3a96
DA
11499 if (!bgp_attr_get_lcommunity(pi->attr) ||
11500 !lcommunity_match(
11501 bgp_attr_get_lcommunity(pi->attr),
11502 lcom))
98ce9a06
DS
11503 continue;
11504 }
36a206db 11505
11506 if (type == bgp_show_type_lcommunity_exact) {
11507 struct lcommunity *lcom = output_arg;
11508
1bcf3a96
DA
11509 if (!bgp_attr_get_lcommunity(pi->attr) ||
11510 !lcommunity_cmp(
11511 bgp_attr_get_lcommunity(pi->attr),
11512 lcom))
36a206db 11513 continue;
11514 }
98ce9a06
DS
11515 if (type == bgp_show_type_lcommunity_list) {
11516 struct community_list *list = output_arg;
d62a17ae 11517
1bcf3a96
DA
11518 if (!lcommunity_list_match(
11519 bgp_attr_get_lcommunity(pi->attr),
11520 list))
98ce9a06
DS
11521 continue;
11522 }
36a206db 11523 if (type
11524 == bgp_show_type_lcommunity_list_exact) {
11525 struct community_list *list = output_arg;
11526
11527 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11528 bgp_attr_get_lcommunity(pi->attr),
11529 list))
36a206db 11530 continue;
11531 }
98ce9a06 11532 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11533 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11534 continue;
11535 }
11536 if (type == bgp_show_type_dampend_paths
11537 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11538 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11539 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11540 continue;
11541 }
83856649
KQ
11542 if (type == bgp_show_type_self_originated) {
11543 if (pi->peer != bgp->peer_self)
11544 continue;
11545 }
98ce9a06
DS
11546
11547 if (!use_json && header) {
23d0a753
DA
11548 vty_out(vty,
11549 "BGP table version is %" PRIu64
11550 ", local router ID is %pI4, vrf id ",
11551 table->version, &bgp->router_id);
9df8b37c
PZ
11552 if (bgp->vrf_id == VRF_UNKNOWN)
11553 vty_out(vty, "%s", VRFID_NONE_STR);
11554 else
11555 vty_out(vty, "%u", bgp->vrf_id);
11556 vty_out(vty, "\n");
01eced22
AD
11557 vty_out(vty, "Default local pref %u, ",
11558 bgp->default_local_pref);
e84c7c12
PG
11559 vty_out(vty, "local AS ");
11560 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11561 &bgp->as);
11562 vty_out(vty, "\n");
509d82bd 11563 if (!detail_routes) {
9a1aae2d
DA
11564 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11565 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11566 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11567 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11568 }
d62a17ae 11569 if (type == bgp_show_type_dampend_paths
11570 || type == bgp_show_type_damp_neighbor)
98ce9a06 11571 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11572 else if (type == bgp_show_type_flap_statistics
11573 || type == bgp_show_type_flap_neighbor)
98ce9a06 11574 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11575 else if (!detail_routes)
ae248832
MK
11576 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11577 : BGP_SHOW_HEADER));
2aad8c42
MS
11578 header = false;
11579
d62a17ae 11580 }
98ce9a06
DS
11581 if (rd != NULL && !display && !output_count) {
11582 if (!use_json)
11583 vty_out(vty,
11584 "Route Distinguisher: %s\n",
11585 rd);
d62a17ae 11586 }
98ce9a06
DS
11587 if (type == bgp_show_type_dampend_paths
11588 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11589 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11590 AFI_IP, safi, use_json,
11591 json_paths);
98ce9a06
DS
11592 else if (type == bgp_show_type_flap_statistics
11593 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11594 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11595 AFI_IP, safi, use_json,
11596 json_paths);
f280c93b 11597 else {
27bb782a
DA
11598 if (detail_routes || detail_json) {
11599 const struct prefix_rd *prd = NULL;
9a1aae2d 11600
27bb782a
DA
11601 if (dest->pdest)
11602 prd = bgp_rd_from_dest(
11603 dest->pdest, safi);
9a1aae2d
DA
11604
11605 if (!use_json)
11606 route_vty_out_detail_header(
11607 vty, bgp, dest,
11608 bgp_dest_get_prefix(
11609 dest),
11610 prd, table->afi, safi,
f9f2d188 11611 NULL, false);
9a1aae2d 11612
f280c93b 11613 route_vty_out_detail(
27bb782a 11614 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11615 family2afi(dest_p->family),
11616 safi, RPKI_NOT_BEING_USED,
11617 json_paths);
9a1aae2d 11618 } else {
f280c93b
DA
11619 route_vty_out(vty, dest_p, pi, display,
11620 safi, json_paths, wide);
9a1aae2d 11621 }
f280c93b 11622 }
98ce9a06 11623 display++;
d62a17ae 11624 }
11625
98ce9a06
DS
11626 if (display) {
11627 output_count++;
11628 if (!use_json)
11629 continue;
11630
625d2931 11631 /* encode prefix */
9bcb3eef 11632 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11633 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11634
1840384b 11635
b54892e0
DS
11636 bgp_fs_nlri_get_string(
11637 (unsigned char *)
9bcb3eef
DS
11638 dest_p->u.prefix_flowspec.ptr,
11639 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11640 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11641 family2afi(dest_p->u
11642 .prefix_flowspec.family));
625d2931 11643 if (first)
b54892e0 11644 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11645 dest_p->u.prefix_flowspec
b54892e0 11646 .prefixlen);
625d2931 11647 else
b54892e0 11648 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11649 dest_p->u.prefix_flowspec
b54892e0 11650 .prefixlen);
625d2931 11651 } else {
625d2931 11652 if (first)
1b78780b 11653 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11654 else
1b78780b 11655 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11656 }
f9f2d188 11657
8ed85db6
TA
11658 /* This is used for 'json detail' vty keywords.
11659 *
11660 * In plain 'json' the per-prefix header is encoded
11661 * as a standalone dictionary in the first json_paths
11662 * array element:
11663 * "<prefix>": [{header}, {path-1}, {path-N}]
11664 * (which is confusing and borderline broken)
11665 *
11666 * For 'json detail' this changes the value
11667 * of each prefix-key to be a dictionary where each
11668 * header item has its own key, and json_paths is
11669 * tucked under the "paths" key:
11670 * "<prefix>": {
11671 * "<header-key-1>": <header-val-1>,
11672 * "<header-key-N>": <header-val-N>,
11673 * "paths": [{path-1}, {path-N}]
11674 * }
11675 */
f9f2d188
TA
11676 if (json_detail_header && json_paths != NULL) {
11677 const struct prefix_rd *prd;
11678
8ed85db6 11679 /* Start per-prefix dictionary */
f9f2d188
TA
11680 vty_out(vty, "{\n");
11681
11682 prd = bgp_rd_from_dest(dest, safi);
11683
11684 route_vty_out_detail_header(
11685 vty, bgp, dest,
11686 bgp_dest_get_prefix(dest), prd,
11687 table->afi, safi, json_paths, true);
11688
11689 vty_out(vty, "\"paths\": ");
11690 json_detail_header_used = true;
11691 }
11692
d7c6467b
DS
11693 /*
11694 * We are using no_pretty here because under
11695 * extremely high settings( say lots and lots of
11696 * routes with lots and lots of ways to reach
11697 * that route via different paths ) this can
11698 * save several minutes of output when FRR
11699 * is run on older cpu's or more underperforming
11700 * routers out there
11701 */
11702 vty_json_no_pretty(vty, json_paths);
f9f2d188 11703
8ed85db6 11704 /* End per-prefix dictionary */
f9f2d188
TA
11705 if (json_detail_header_used)
11706 vty_out(vty, "} ");
11707
449feb8e 11708 json_paths = NULL;
98ce9a06 11709 first = 0;
1f83ed02
DS
11710 } else
11711 json_object_free(json_paths);
98ce9a06
DS
11712 }
11713
1ae44dfc
LB
11714 if (output_cum) {
11715 output_count += *output_cum;
11716 *output_cum = output_count;
11717 }
11718 if (total_cum) {
11719 total_count += *total_cum;
11720 *total_cum = total_count;
11721 }
d62a17ae 11722 if (use_json) {
9386b588 11723 if (rd) {
a4d82a8a 11724 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11725 }
11726 if (is_last) {
a4d82a8a
PZ
11727 unsigned long i;
11728 for (i = 0; i < *json_header_depth; ++i)
11729 vty_out(vty, " } ");
96f3485c
MK
11730 if (!all)
11731 vty_out(vty, "\n");
9386b588 11732 }
d62a17ae 11733 } else {
1ae44dfc
LB
11734 if (is_last) {
11735 /* No route is displayed */
11736 if (output_count == 0) {
11737 if (type == bgp_show_type_normal)
11738 vty_out(vty,
11739 "No BGP prefixes displayed, %ld exist\n",
11740 total_count);
11741 } else
d62a17ae 11742 vty_out(vty,
1ae44dfc
LB
11743 "\nDisplayed %ld routes and %ld total paths\n",
11744 output_count, total_count);
11745 }
d62a17ae 11746 }
718e3744 11747
d62a17ae 11748 return CMD_SUCCESS;
718e3744 11749}
11750
1ae44dfc
LB
11751int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11752 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11753 enum bgp_show_type type, void *output_arg,
11754 uint16_t show_flags)
1ae44dfc 11755{
9bcb3eef 11756 struct bgp_dest *dest, *next;
1ae44dfc
LB
11757 unsigned long output_cum = 0;
11758 unsigned long total_cum = 0;
9386b588 11759 unsigned long json_header_depth = 0;
67009e22 11760 struct bgp_table *itable;
0136788c 11761 bool show_msg;
27bb782a 11762 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11763
11764 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11765
9bcb3eef
DS
11766 for (dest = bgp_table_top(table); dest; dest = next) {
11767 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11768
9bcb3eef
DS
11769 next = bgp_route_next(dest);
11770 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11771 continue;
67009e22 11772
9bcb3eef 11773 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11774 if (itable != NULL) {
1ae44dfc 11775 struct prefix_rd prd;
06b9f471 11776 char rd[RD_ADDRSTRLEN];
1ae44dfc 11777
9bcb3eef 11778 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11779 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11780 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11781 rd, next == NULL, &output_cum,
11782 &total_cum, &json_header_depth,
1e2ce4f1 11783 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11784 if (next == NULL)
11785 show_msg = false;
1ae44dfc
LB
11786 }
11787 }
0136788c
LB
11788 if (show_msg) {
11789 if (output_cum == 0)
11790 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11791 total_cum);
11792 else
11793 vty_out(vty,
11794 "\nDisplayed %ld routes and %ld total paths\n",
11795 output_cum, total_cum);
0224b329
DA
11796 } else {
11797 if (use_json && output_cum == 0)
11798 vty_out(vty, "{}\n");
0136788c 11799 }
1ae44dfc
LB
11800 return CMD_SUCCESS;
11801}
2aad8c42 11802
d62a17ae 11803static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11804 enum bgp_show_type type, void *output_arg,
96c81f66 11805 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11806{
d62a17ae 11807 struct bgp_table *table;
9386b588 11808 unsigned long json_header_depth = 0;
96f3485c 11809 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11810
d62a17ae 11811 if (bgp == NULL) {
11812 bgp = bgp_get_default();
11813 }
fee0f4c6 11814
d62a17ae 11815 if (bgp == NULL) {
11816 if (!use_json)
11817 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11818 else
11819 vty_out(vty, "{}\n");
d62a17ae 11820 return CMD_WARNING;
11821 }
4dd6177e 11822
cd8c2a27
MS
11823 /* Labeled-unicast routes live in the unicast table. */
11824 if (safi == SAFI_LABELED_UNICAST)
11825 safi = SAFI_UNICAST;
11826
1ae44dfc 11827 table = bgp->rib[afi][safi];
d62a17ae 11828 /* use MPLS and ENCAP specific shows until they are merged */
11829 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11830 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11831 output_arg, show_flags);
d62a17ae 11832 }
dba3c1d3
PG
11833
11834 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11835 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11836 output_arg, use_json,
11837 1, NULL, NULL);
11838 }
fee0f4c6 11839
0adc5bbb
LS
11840 if (safi == SAFI_EVPN)
11841 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11842
96f3485c 11843 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11844 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11845 rpki_target_state);
fee0f4c6 11846}
11847
d62a17ae 11848static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11849 safi_t safi, uint16_t show_flags)
f186de26 11850{
d62a17ae 11851 struct listnode *node, *nnode;
11852 struct bgp *bgp;
11853 int is_first = 1;
9f049418 11854 bool route_output = false;
96f3485c 11855 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11856
d62a17ae 11857 if (use_json)
11858 vty_out(vty, "{\n");
9f689658 11859
d62a17ae 11860 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11861 route_output = true;
d62a17ae 11862 if (use_json) {
11863 if (!is_first)
11864 vty_out(vty, ",\n");
11865 else
11866 is_first = 0;
11867
11868 vty_out(vty, "\"%s\":",
11869 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11870 ? VRF_DEFAULT_NAME
d62a17ae 11871 : bgp->name);
11872 } else {
11873 vty_out(vty, "\nInstance %s:\n",
11874 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11875 ? VRF_DEFAULT_NAME
d62a17ae 11876 : bgp->name);
11877 }
11878 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11879 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11880 }
9f689658 11881
d62a17ae 11882 if (use_json)
11883 vty_out(vty, "}\n");
9f049418
DS
11884 else if (!route_output)
11885 vty_out(vty, "%% BGP instance not found\n");
f186de26 11886}
11887
718e3744 11888/* Header of detailed BGP route information */
d62a17ae 11889void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11890 struct bgp_dest *dest, const struct prefix *p,
11891 const struct prefix_rd *prd, afi_t afi,
f9f2d188
TA
11892 safi_t safi, json_object *json,
11893 bool incremental_print)
d62a17ae 11894{
40381db7 11895 struct bgp_path_info *pi;
d62a17ae 11896 struct peer *peer;
11897 struct listnode *node, *nnode;
06b9f471 11898 char buf1[RD_ADDRSTRLEN];
d62a17ae 11899 int count = 0;
11900 int best = 0;
11901 int suppress = 0;
c5f1e1b2
C
11902 int accept_own = 0;
11903 int route_filter_translated_v4 = 0;
11904 int route_filter_v4 = 0;
11905 int route_filter_translated_v6 = 0;
11906 int route_filter_v6 = 0;
11907 int llgr_stale = 0;
11908 int no_llgr = 0;
11909 int accept_own_nexthop = 0;
11910 int blackhole = 0;
d62a17ae 11911 int no_export = 0;
11912 int no_advertise = 0;
11913 int local_as = 0;
c5f1e1b2 11914 int no_peer = 0;
d62a17ae 11915 int first = 1;
11916 int has_valid_label = 0;
11917 mpls_label_t label = 0;
11918 json_object *json_adv_to = NULL;
67f67ba4
DA
11919 uint32_t ttl = 0;
11920 uint32_t bos = 0;
11921 uint32_t exp = 0;
9bedbb1e 11922
67f67ba4 11923 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11924
67f67ba4 11925 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11926
44c69747 11927 if (safi == SAFI_EVPN) {
44c69747 11928 if (!json) {
2dbe669b 11929 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11930 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11931 bgp->asnotation)
f137734b 11932 : "",
2dbe669b 11933 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11934 } else {
4a8cd6ad
PG
11935 json_object_string_add(
11936 json, "rd",
11937 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11938 bgp->asnotation)
11939 : "");
44c69747
LK
11940 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11941 }
11942 } else {
11943 if (!json) {
9119ef3a
DA
11944 vty_out(vty,
11945 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11946 "\n",
ea5a8e4d
DA
11947 (((safi == SAFI_MPLS_VPN ||
11948 safi == SAFI_ENCAP) &&
11949 prd)
8228a9a7 11950 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11951 sizeof(buf1),
11952 bgp->asnotation)
8228a9a7 11953 : ""),
ea5a8e4d 11954 safi == SAFI_MPLS_VPN && prd ? ":" : "", p,
9119ef3a 11955 dest->version);
cd1964ff 11956
9119ef3a 11957 } else {
f9f2d188
TA
11958 if (incremental_print) {
11959 vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
11960 vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
11961 dest->version);
11962 } else {
11963 json_object_string_addf(json, "prefix", "%pFX",
11964 p);
11965 json_object_int_add(json, "version",
11966 dest->version);
11967 }
9119ef3a 11968 }
44c69747
LK
11969 }
11970
11971 if (has_valid_label) {
f9f2d188
TA
11972 if (json) {
11973 if (incremental_print)
11974 vty_out(vty, "\"localLabel\": \"%u\",\n",
11975 label);
11976 else
11977 json_object_int_add(json, "localLabel", label);
11978 } else
d62a17ae 11979 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11980 }
11981
11982 if (!json)
d62a17ae 11983 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11984 vty_out(vty, "not allocated\n");
718e3744 11985
9bcb3eef 11986 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11987 struct community *picomm = NULL;
11988
11989 picomm = bgp_attr_get_community(pi->attr);
11990
d62a17ae 11991 count++;
40381db7 11992 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11993 best = count;
4056a5f6 11994 if (bgp_path_suppressed(pi))
d62a17ae 11995 suppress = 1;
cee9c031 11996
9a706b42 11997 if (!picomm)
cee9c031
QY
11998 continue;
11999
12000 no_advertise += community_include(
9a706b42
DA
12001 picomm, COMMUNITY_NO_ADVERTISE);
12002 no_export +=
12003 community_include(picomm, COMMUNITY_NO_EXPORT);
12004 local_as +=
12005 community_include(picomm, COMMUNITY_LOCAL_AS);
12006 accept_own +=
12007 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 12008 route_filter_translated_v4 += community_include(
9a706b42 12009 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 12010 route_filter_translated_v6 += community_include(
9a706b42 12011 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 12012 route_filter_v4 += community_include(
9a706b42 12013 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 12014 route_filter_v6 += community_include(
9a706b42
DA
12015 picomm, COMMUNITY_ROUTE_FILTER_v6);
12016 llgr_stale +=
12017 community_include(picomm, COMMUNITY_LLGR_STALE);
12018 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
12019 accept_own_nexthop += community_include(
12020 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
12021 blackhole +=
12022 community_include(picomm, COMMUNITY_BLACKHOLE);
12023 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 12024 }
718e3744 12025 }
718e3744 12026
d62a17ae 12027 if (!json) {
12028 vty_out(vty, "Paths: (%d available", count);
12029 if (best) {
12030 vty_out(vty, ", best #%d", best);
b84060bb
PG
12031 if (safi == SAFI_UNICAST) {
12032 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
12033 vty_out(vty, ", table %s",
12034 VRF_DEFAULT_NAME);
12035 else
12036 vty_out(vty, ", vrf %s",
12037 bgp->name);
12038 }
d62a17ae 12039 } else
12040 vty_out(vty, ", no best path");
12041
c5f1e1b2
C
12042 if (accept_own)
12043 vty_out(vty,
12044 ", accept own local route exported and imported in different VRF");
12045 else if (route_filter_translated_v4)
12046 vty_out(vty,
12047 ", mark translated RTs for VPNv4 route filtering");
12048 else if (route_filter_v4)
12049 vty_out(vty,
12050 ", attach RT as-is for VPNv4 route filtering");
12051 else if (route_filter_translated_v6)
12052 vty_out(vty,
12053 ", mark translated RTs for VPNv6 route filtering");
12054 else if (route_filter_v6)
12055 vty_out(vty,
12056 ", attach RT as-is for VPNv6 route filtering");
12057 else if (llgr_stale)
12058 vty_out(vty,
1479ed2f 12059 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
12060 else if (no_llgr)
12061 vty_out(vty,
12062 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
12063 else if (accept_own_nexthop)
12064 vty_out(vty,
12065 ", accept local nexthop");
12066 else if (blackhole)
12067 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 12068 else if (no_export)
12069 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
12070 else if (no_advertise)
12071 vty_out(vty, ", not advertised to any peer");
d62a17ae 12072 else if (local_as)
12073 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
12074 else if (no_peer)
12075 vty_out(vty,
12076 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 12077
12078 if (suppress)
12079 vty_out(vty,
12080 ", Advertisements suppressed by an aggregate.");
12081 vty_out(vty, ")\n");
12082 }
718e3744 12083
d62a17ae 12084 /* If we are not using addpath then we can display Advertised to and
12085 * that will
12086 * show what peers we advertised the bestpath to. If we are using
12087 * addpath
12088 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12089 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12090 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12091 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12092 if (json && !json_adv_to)
12093 json_adv_to = json_object_new_object();
12094
12095 route_vty_out_advertised_to(
12096 vty, peer, &first,
12097 " Advertised to non peer-group peers:\n ",
12098 json_adv_to);
12099 }
12100 }
12101
f9f2d188
TA
12102 if (json && json_adv_to) {
12103 if (incremental_print) {
12104 vty_out(vty, "\"advertisedTo\": ");
12105 vty_json(vty, json_adv_to);
12106 vty_out(vty, ",");
12107 } else
d62a17ae 12108 json_object_object_add(json, "advertisedTo",
12109 json_adv_to);
d62a17ae 12110 } else {
f9f2d188 12111 if (!json && first)
d62a17ae 12112 vty_out(vty, " Not advertised to any peer");
12113 vty_out(vty, "\n");
12114 }
12115 }
718e3744 12116}
12117
edfee30d 12118static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12119 struct bgp_dest *bgp_node, struct vty *vty,
12120 struct bgp *bgp, afi_t afi, safi_t safi,
12121 json_object *json, enum bgp_path_type pathtype,
4027d19b 12122 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12123{
12124 struct bgp_path_info *pi;
12125 int header = 1;
44c69747
LK
12126 json_object *json_header = NULL;
12127 json_object *json_paths = NULL;
4933eaaf 12128 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12129
9bcb3eef 12130 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12131 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12132
12133 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12134 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12135 pi->peer, pi->attr, p);
4933eaaf 12136
4027d19b
DS
12137 if (rpki_target_state != RPKI_NOT_BEING_USED
12138 && rpki_curr_state != rpki_target_state)
4933eaaf 12139 continue;
44c69747
LK
12140
12141 if (json && !json_paths) {
12142 /* Instantiate json_paths only if path is valid */
12143 json_paths = json_object_new_array();
c4f64ea9 12144 if (pfx_rd)
44c69747 12145 json_header = json_object_new_object();
c4f64ea9 12146 else
44c69747
LK
12147 json_header = json;
12148 }
12149
12150 if (header) {
12151 route_vty_out_detail_header(
34c7f35f
SW
12152 vty, bgp, bgp_node,
12153 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
f9f2d188 12154 safi, json_header, false);
44c69747
LK
12155 header = 0;
12156 }
12157 (*display)++;
12158
12159 if (pathtype == BGP_PATH_SHOW_ALL
12160 || (pathtype == BGP_PATH_SHOW_BESTPATH
12161 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12162 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12163 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12164 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12165 route_vty_out_detail(vty, bgp, bgp_node,
12166 bgp_dest_get_prefix(bgp_node), pi,
12167 AFI_IP, safi, rpki_curr_state,
12168 json_paths);
44c69747
LK
12169 }
12170
12171 if (json && json_paths) {
12172 json_object_object_add(json_header, "paths", json_paths);
12173
12174 if (pfx_rd)
4a8cd6ad
PG
12175 json_object_object_addf(
12176 json, json_header,
12177 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12178 }
12179}
12180
2aad8c42
MS
12181/*
12182 * Return rd based on safi
12183 */
46dbf9d0
DA
12184const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12185 safi_t safi)
2aad8c42
MS
12186{
12187 switch (safi) {
12188 case SAFI_MPLS_VPN:
12189 case SAFI_ENCAP:
12190 case SAFI_EVPN:
12191 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12192 case SAFI_UNSPEC:
12193 case SAFI_UNICAST:
12194 case SAFI_MULTICAST:
12195 case SAFI_LABELED_UNICAST:
12196 case SAFI_FLOWSPEC:
12197 case SAFI_MAX:
2aad8c42 12198 return NULL;
2aad8c42 12199 }
58cf0823
DS
12200
12201 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12202}
12203
718e3744 12204/* Display specified route of BGP table. */
d62a17ae 12205static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12206 struct bgp_table *rib, const char *ip_str,
12207 afi_t afi, safi_t safi,
4027d19b 12208 enum rpki_states rpki_target_state,
d62a17ae 12209 struct prefix_rd *prd, int prefix_check,
9f049418 12210 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12211{
12212 int ret;
d62a17ae 12213 int display = 0;
12214 struct prefix match;
9bcb3eef
DS
12215 struct bgp_dest *dest;
12216 struct bgp_dest *rm;
d62a17ae 12217 struct bgp_table *table;
12218 json_object *json = NULL;
12219 json_object *json_paths = NULL;
12220
12221 /* Check IP address argument. */
12222 ret = str2prefix(ip_str, &match);
12223 if (!ret) {
12224 vty_out(vty, "address is malformed\n");
12225 return CMD_WARNING;
12226 }
718e3744 12227
d62a17ae 12228 match.family = afi2family(afi);
b05a1c8b 12229
44c69747 12230 if (use_json)
d62a17ae 12231 json = json_object_new_object();
718e3744 12232
44c69747 12233 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12234 for (dest = bgp_table_top(rib); dest;
12235 dest = bgp_route_next(dest)) {
12236 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12237
9bcb3eef 12238 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12239 continue;
9bcb3eef 12240 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12241 if (!table)
ea47320b 12242 continue;
d62a17ae 12243
4953391b
DA
12244 rm = bgp_node_match(table, &match);
12245 if (rm == NULL)
ea47320b 12246 continue;
d62a17ae 12247
9bcb3eef 12248 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12249 if (prefix_check
b54892e0 12250 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12251 bgp_dest_unlock_node(rm);
ea47320b
DL
12252 continue;
12253 }
d62a17ae 12254
9bcb3eef 12255 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12256 bgp, afi, safi, json, pathtype,
4027d19b 12257 &display, rpki_target_state);
44c69747 12258
9bcb3eef 12259 bgp_dest_unlock_node(rm);
44c69747
LK
12260 }
12261 } else if (safi == SAFI_EVPN) {
9bcb3eef 12262 struct bgp_dest *longest_pfx;
cded3b72 12263 bool is_exact_pfxlen_match = false;
44c69747 12264
9bcb3eef
DS
12265 for (dest = bgp_table_top(rib); dest;
12266 dest = bgp_route_next(dest)) {
12267 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12268
9bcb3eef 12269 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12270 continue;
9bcb3eef 12271 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12272 if (!table)
12273 continue;
12274
12275 longest_pfx = NULL;
cded3b72 12276 is_exact_pfxlen_match = false;
44c69747
LK
12277 /*
12278 * Search through all the prefixes for a match. The
12279 * pfx's are enumerated in ascending order of pfxlens.
12280 * So, the last pfx match is the longest match. Set
12281 * is_exact_pfxlen_match when we get exact pfxlen match
12282 */
12283 for (rm = bgp_table_top(table); rm;
12284 rm = bgp_route_next(rm)) {
b54892e0 12285 const struct prefix *rm_p =
9bcb3eef 12286 bgp_dest_get_prefix(rm);
44c69747
LK
12287 /*
12288 * Get prefixlen of the ip-prefix within type5
12289 * evpn route
12290 */
b54892e0
DS
12291 if (evpn_type5_prefix_match(rm_p, &match)
12292 && rm->info) {
44c69747
LK
12293 longest_pfx = rm;
12294 int type5_pfxlen =
b54892e0
DS
12295 bgp_evpn_get_type5_prefixlen(
12296 rm_p);
44c69747 12297 if (type5_pfxlen == match.prefixlen) {
cded3b72 12298 is_exact_pfxlen_match = true;
9bcb3eef 12299 bgp_dest_unlock_node(rm);
44c69747
LK
12300 break;
12301 }
d62a17ae 12302 }
12303 }
ea47320b 12304
44c69747
LK
12305 if (!longest_pfx)
12306 continue;
12307
12308 if (prefix_check && !is_exact_pfxlen_match)
12309 continue;
12310
12311 rm = longest_pfx;
9bcb3eef 12312 bgp_dest_lock_node(rm);
44c69747 12313
9bcb3eef 12314 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12315 bgp, afi, safi, json, pathtype,
4027d19b 12316 &display, rpki_target_state);
44c69747 12317
9bcb3eef 12318 bgp_dest_unlock_node(rm);
d62a17ae 12319 }
98a9dbc7 12320 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12321 if (use_json)
12322 json_paths = json_object_new_array();
12323
63a0b7a9
PG
12324 display = bgp_flowspec_display_match_per_ip(afi, rib,
12325 &match, prefix_check,
12326 vty,
12327 use_json,
12328 json_paths);
d5f20468
SP
12329 if (use_json) {
12330 if (display)
12331 json_object_object_add(json, "paths",
12332 json_paths);
12333 else
12334 json_object_free(json_paths);
12335 }
d62a17ae 12336 } else {
4953391b
DA
12337 dest = bgp_node_match(rib, &match);
12338 if (dest != NULL) {
9bcb3eef 12339 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12340 if (!prefix_check
9bcb3eef
DS
12341 || dest_p->prefixlen == match.prefixlen) {
12342 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12343 safi, json, pathtype,
4027d19b 12344 &display, rpki_target_state);
d62a17ae 12345 }
12346
9bcb3eef 12347 bgp_dest_unlock_node(dest);
d62a17ae 12348 }
12349 }
e5eee9af 12350
d62a17ae 12351 if (use_json) {
75eeda93 12352 vty_json(vty, json);
d62a17ae 12353 } else {
12354 if (!display) {
12355 vty_out(vty, "%% Network not in table\n");
12356 return CMD_WARNING;
12357 }
12358 }
b05a1c8b 12359
d62a17ae 12360 return CMD_SUCCESS;
718e3744 12361}
12362
fee0f4c6 12363/* Display specified route of Main RIB */
d62a17ae 12364static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12365 afi_t afi, safi_t safi, struct prefix_rd *prd,
12366 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12367 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12368{
9b86009a 12369 if (!bgp) {
d62a17ae 12370 bgp = bgp_get_default();
9b86009a
RW
12371 if (!bgp) {
12372 if (!use_json)
12373 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12374 else
12375 vty_out(vty, "{}\n");
9b86009a
RW
12376 return CMD_WARNING;
12377 }
12378 }
d62a17ae 12379
12380 /* labeled-unicast routes live in the unicast table */
12381 if (safi == SAFI_LABELED_UNICAST)
12382 safi = SAFI_UNICAST;
12383
12384 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12385 afi, safi, rpki_target_state, prd,
8aa22bbb 12386 prefix_check, pathtype, use_json);
d62a17ae 12387}
12388
12389static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12390 struct cmd_token **argv, bool exact, afi_t afi,
12391 safi_t safi, bool uj)
d62a17ae 12392{
12393 struct lcommunity *lcom;
12394 struct buffer *b;
12395 int i;
12396 char *str;
12397 int first = 0;
96c81f66 12398 uint16_t show_flags = 0;
4f28b2b5 12399 int ret;
96f3485c
MK
12400
12401 if (uj)
12402 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12403
12404 b = buffer_new(1024);
12405 for (i = 0; i < argc; i++) {
12406 if (first)
12407 buffer_putc(b, ' ');
12408 else {
12409 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12410 first = 1;
12411 buffer_putstr(b, argv[i]->arg);
12412 }
12413 }
12414 }
12415 buffer_putc(b, '\0');
57d187bc 12416
d62a17ae 12417 str = buffer_getstr(b);
12418 buffer_free(b);
57d187bc 12419
d62a17ae 12420 lcom = lcommunity_str2com(str);
12421 XFREE(MTYPE_TMP, str);
12422 if (!lcom) {
12423 vty_out(vty, "%% Large-community malformed\n");
12424 return CMD_WARNING;
12425 }
57d187bc 12426
4f28b2b5 12427 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12428 (exact ? bgp_show_type_lcommunity_exact
12429 : bgp_show_type_lcommunity),
12430 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12431
12432 lcommunity_free(&lcom);
12433 return ret;
57d187bc
JS
12434}
12435
d62a17ae 12436static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12437 const char *lcom, bool exact, afi_t afi,
12438 safi_t safi, bool uj)
57d187bc 12439{
d62a17ae 12440 struct community_list *list;
96c81f66 12441 uint16_t show_flags = 0;
96f3485c
MK
12442
12443 if (uj)
12444 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12445
57d187bc 12446
e237b0d2 12447 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12448 LARGE_COMMUNITY_LIST_MASTER);
12449 if (list == NULL) {
12450 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12451 lcom);
12452 return CMD_WARNING;
12453 }
57d187bc 12454
36a206db 12455 return bgp_show(vty, bgp, afi, safi,
12456 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12457 : bgp_show_type_lcommunity_list),
1e2ce4f1 12458 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12459}
12460
52951b63
DS
12461DEFUN (show_ip_bgp_large_community_list,
12462 show_ip_bgp_large_community_list_cmd,
77a3a95e 12463 "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
12464 SHOW_STR
12465 IP_STR
12466 BGP_STR
12467 BGP_INSTANCE_HELP_STR
9bedbb1e 12468 BGP_AFI_HELP_STR
4dd6177e 12469 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12470 "Display routes matching the large-community-list\n"
12471 "large-community-list number\n"
12472 "large-community-list name\n"
36a206db 12473 "Exact match of the large-communities\n"
52951b63
DS
12474 JSON_STR)
12475{
d62a17ae 12476 afi_t afi = AFI_IP6;
12477 safi_t safi = SAFI_UNICAST;
12478 int idx = 0;
36a206db 12479 bool exact_match = 0;
4d678463 12480 struct bgp *bgp = NULL;
9f049418 12481 bool uj = use_json(argc, argv);
d62a17ae 12482
ef3364f0
DA
12483 if (uj)
12484 argc--;
4d678463 12485
ef3364f0
DA
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
12491 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12492
12493 const char *clist_number_or_name = argv[++idx]->arg;
12494
12495 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12496 exact_match = 1;
12497
12498 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12499 exact_match, afi, safi, uj);
52951b63
DS
12500}
12501DEFUN (show_ip_bgp_large_community,
12502 show_ip_bgp_large_community_cmd,
36a206db 12503 "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
12504 SHOW_STR
12505 IP_STR
12506 BGP_STR
12507 BGP_INSTANCE_HELP_STR
9bedbb1e 12508 BGP_AFI_HELP_STR
4dd6177e 12509 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12510 "Display routes matching the large-communities\n"
12511 "List of large-community numbers\n"
36a206db 12512 "Exact match of the large-communities\n"
52951b63
DS
12513 JSON_STR)
12514{
d62a17ae 12515 afi_t afi = AFI_IP6;
12516 safi_t safi = SAFI_UNICAST;
12517 int idx = 0;
36a206db 12518 bool exact_match = 0;
4d678463 12519 struct bgp *bgp = NULL;
9f049418 12520 bool uj = use_json(argc, argv);
96c81f66 12521 uint16_t show_flags = 0;
d62a17ae 12522
96f3485c
MK
12523 if (uj) {
12524 argc--;
12525 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12526 }
4d678463 12527
96f3485c
MK
12528 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12529 &bgp, uj);
12530 if (!idx)
12531 return CMD_WARNING;
d62a17ae 12532
36a206db 12533 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12534 if (argv_find(argv, argc, "exact-match", &idx)) {
12535 argc--;
36a206db 12536 exact_match = 1;
1857760c 12537 }
36a206db 12538 return bgp_show_lcommunity(vty, bgp, argc, argv,
12539 exact_match, afi, safi, uj);
12540 } else
d62a17ae 12541 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12542 bgp_show_type_lcommunity_all, NULL, show_flags,
12543 RPKI_NOT_BEING_USED);
52951b63
DS
12544}
12545
71f1613a
DA
12546static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12547 safi_t safi, struct json_object *json_array);
d62a17ae 12548static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12549 safi_t safi, struct json_object *json);
e01ca200 12550
7b2ff250 12551
9ab0cf58
PG
12552DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12553 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12554 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12555 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12556{
12557 bool uj = use_json(argc, argv);
12558 struct bgp *bgp = NULL;
ec76a1d1
DA
12559 safi_t safi = SAFI_UNICAST;
12560 afi_t afi = AFI_IP6;
4265b261 12561 int idx = 0;
6c9d22e2
PG
12562 struct json_object *json_all = NULL;
12563 struct json_object *json_afi_safi = NULL;
4265b261
PG
12564
12565 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12566 &bgp, false);
71f1613a 12567 if (!idx)
4265b261 12568 return CMD_WARNING;
6c9d22e2 12569
4265b261 12570 if (uj)
6c9d22e2 12571 json_all = json_object_new_object();
4265b261 12572
9ab0cf58
PG
12573 FOREACH_AFI_SAFI (afi, safi) {
12574 /*
12575 * So limit output to those afi/safi pairs that
12576 * actually have something interesting in them
12577 */
12578 if (strmatch(get_afi_safi_str(afi, safi, true),
12579 "Unknown")) {
12580 continue;
12581 }
12582 if (uj) {
12583 json_afi_safi = json_object_new_array();
12584 json_object_object_add(
12585 json_all,
12586 get_afi_safi_str(afi, safi, true),
12587 json_afi_safi);
12588 } else {
12589 json_afi_safi = NULL;
6c9d22e2 12590 }
9ab0cf58
PG
12591
12592 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12593 }
6c9d22e2 12594
3757f964
DA
12595 if (uj)
12596 vty_json(vty, json_all);
6c9d22e2 12597
4265b261
PG
12598 return CMD_SUCCESS;
12599}
12600
7b2ff250 12601/* BGP route print out function without JSON */
14718643
PG
12602DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12603 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12604 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12605 SHOW_STR
12606 IP_STR
12607 BGP_STR
12608 BGP_INSTANCE_HELP_STR
12609 L2VPN_HELP_STR
12610 EVPN_HELP_STR
12611 "BGP RIB advertisement statistics\n"
12612 JSON_STR)
12613{
ec76a1d1
DA
12614 afi_t afi = AFI_IP6;
12615 safi_t safi = SAFI_UNICAST;
14718643
PG
12616 struct bgp *bgp = NULL;
12617 int idx = 0, ret;
12618 bool uj = use_json(argc, argv);
12619 struct json_object *json_afi_safi = NULL, *json = NULL;
12620
12621 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12622 &bgp, false);
12623 if (!idx)
12624 return CMD_WARNING;
12625
12626 if (uj)
12627 json_afi_safi = json_object_new_array();
12628 else
12629 json_afi_safi = NULL;
12630
12631 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12632
12633 if (uj) {
12634 json = json_object_new_object();
12635 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12636 json_afi_safi);
3757f964 12637 vty_json(vty, json);
14718643
PG
12638 }
12639 return ret;
12640}
12641
893cccd0 12642/* BGP route print out function without JSON */
9ab0cf58
PG
12643DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12644 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12645 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12646 "]]\
893cccd0 12647 statistics [json]",
9ab0cf58
PG
12648 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12649 BGP_SAFI_WITH_LABEL_HELP_STR
12650 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12651{
ec76a1d1
DA
12652 afi_t afi = AFI_IP6;
12653 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12654 struct bgp *bgp = NULL;
12655 int idx = 0, ret;
12656 bool uj = use_json(argc, argv);
6c9d22e2 12657 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12658
12659 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12660 &bgp, false);
12661 if (!idx)
12662 return CMD_WARNING;
6c9d22e2 12663
893cccd0 12664 if (uj)
6c9d22e2
PG
12665 json_afi_safi = json_object_new_array();
12666 else
12667 json_afi_safi = NULL;
12668
12669 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12670
12671 if (uj) {
12672 json = json_object_new_object();
12673 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12674 json_afi_safi);
3757f964 12675 vty_json(vty, json);
893cccd0
PG
12676 }
12677 return ret;
893cccd0 12678}
7b2ff250 12679
fe0f234d 12680DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12681 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12682 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12683 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12684 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12685 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12686 "Display the entries for all address families\n"
9ab0cf58
PG
12687 "Display detailed information about dampening\n"
12688 "Display detail of configured dampening parameters\n"
fe0f234d 12689 JSON_STR)
718e3744 12690{
d62a17ae 12691 afi_t afi = AFI_IP6;
12692 safi_t safi = SAFI_UNICAST;
d62a17ae 12693 struct bgp *bgp = NULL;
12694 int idx = 0;
96c81f66 12695 uint16_t show_flags = 0;
fe0f234d
RW
12696 bool uj = use_json(argc, argv);
12697
12698 if (uj) {
12699 argc--;
12700 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12701 }
96f3485c
MK
12702
12703 /* [<ipv4|ipv6> [all]] */
12704 if (all) {
12705 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12706 if (argv_find(argv, argc, "ipv4", &idx))
12707 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12708
12709 if (argv_find(argv, argc, "ipv6", &idx))
12710 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12711 }
d62a17ae 12712
12713 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12714 &bgp, false);
d62a17ae 12715 if (!idx)
12716 return CMD_WARNING;
12717
fe0f234d 12718 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12719}
12720
fe0f234d
RW
12721/* BGP route print out function */
12722DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12723 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12724 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12725 "]]\
96f3485c 12726 [all$all]\
cf4898bc
QY
12727 [cidr-only\
12728 |dampening <flap-statistics|dampened-paths>\
12729 |community [AA:NN|local-AS|no-advertise|no-export\
12730 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12731 |accept-own|accept-own-nexthop|route-filter-v6\
12732 |route-filter-v4|route-filter-translated-v6\
12733 |route-filter-translated-v4] [exact-match]\
70799983 12734 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12735 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12736 |prefix-list WORD\
ed126382 12737 |access-list ACCESSLIST_NAME\
70dd370f 12738 |route-map RMAP_NAME\
1e2ce4f1 12739 |rpki <invalid|valid|notfound>\
7d3cae70 12740 |version (1-4294967295)\
b4ad2fae 12741 |alias ALIAS_NAME\
39c3c736
RW
12742 |A.B.C.D/M longer-prefixes\
12743 |X:X::X:X/M longer-prefixes\
83856649 12744 |"BGP_SELF_ORIG_CMD_STR"\
509d82bd 12745 |detail-routes$detail_routes\
67799a48 12746 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12747 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12748 BGP_SAFI_WITH_LABEL_HELP_STR
12749 "Display the entries for all address families\n"
12750 "Display only routes with non-natural netmasks\n"
12751 "Display detailed information about dampening\n"
12752 "Display flap statistics of routes\n"
12753 "Display paths suppressed due to dampening\n"
12754 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12755 "Do not send outside local AS (well-known community)\n"
12756 "Do not advertise to any peer (well-known community)\n"
12757 "Do not export to next AS (well-known community)\n"
12758 "Graceful shutdown (well-known community)\n"
12759 "Do not export to any peer (well-known community)\n"
12760 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12761 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12762 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12763 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12764 "Should accept VPN route with local nexthop (well-known community)\n"
12765 "RT VPNv6 route filtering (well-known community)\n"
12766 "RT VPNv4 route filtering (well-known community)\n"
12767 "RT translated VPNv6 route filtering (well-known community)\n"
12768 "RT translated VPNv4 route filtering (well-known community)\n"
12769 "Exact match of the communities\n"
70799983
RW
12770 "Community-list number\n"
12771 "Community-list name\n"
12772 "Display routes matching the community-list\n"
12773 "Exact match of the communities\n"
a7129347
RW
12774 "Display routes conforming to the filter-list\n"
12775 "Regular expression access list name\n"
6deaf579
RW
12776 "Display routes conforming to the prefix-list\n"
12777 "Prefix-list name\n"
ed126382
DA
12778 "Display routes conforming to the access-list\n"
12779 "Access-list name\n"
bf1a944a
RW
12780 "Display routes matching the route-map\n"
12781 "A route-map to match on\n"
a70a28a5
DA
12782 "RPKI route types\n"
12783 "A valid path as determined by rpki\n"
12784 "A invalid path as determined by rpki\n"
12785 "A path that has no rpki data\n"
12786 "Display prefixes with matching version numbers\n"
12787 "Version number and above\n"
12788 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12789 "BGP community alias\n"
12790 "IPv4 prefix\n"
12791 "Display route and more specific routes\n"
12792 "IPv6 prefix\n"
12793 "Display route and more specific routes\n"
83856649 12794 BGP_SELF_ORIG_HELP_STR
509d82bd 12795 "Display detailed version of all routes\n"
39c3c736 12796 JSON_STR
a70a28a5
DA
12797 "Display detailed version of JSON output\n"
12798 "Increase table width for longer prefixes\n")
7b2ff250
DW
12799{
12800 afi_t afi = AFI_IP6;
12801 safi_t safi = SAFI_UNICAST;
12802 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12803 void *output_arg = NULL;
7b2ff250
DW
12804 struct bgp *bgp = NULL;
12805 int idx = 0;
d0086e8e 12806 int exact_match = 0;
96f3485c
MK
12807 char *community = NULL;
12808 bool first = true;
96c81f66 12809 uint16_t show_flags = 0;
4027d19b 12810 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12811 struct prefix p;
96f3485c
MK
12812
12813 if (uj) {
9f049418 12814 argc--;
96f3485c
MK
12815 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12816 }
12817
67799a48
DA
12818 if (detail_json)
12819 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12820
509d82bd
DA
12821 if (detail_routes)
12822 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12823
96f3485c
MK
12824 /* [<ipv4|ipv6> [all]] */
12825 if (all) {
12826 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12827
12828 if (argv_find(argv, argc, "ipv4", &idx))
12829 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12830
12831 if (argv_find(argv, argc, "ipv6", &idx))
12832 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12833 }
12834
12835 if (wide)
12836 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12837
12838 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12839 &bgp, uj);
7b2ff250
DW
12840 if (!idx)
12841 return CMD_WARNING;
12842
7b2ff250 12843 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12844 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12845
12846 if (argv_find(argv, argc, "dampening", &idx)) {
12847 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12848 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12849 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12850 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12851 }
12852
12853 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12854 char *maybecomm = NULL;
d0086e8e 12855
79bc257a
RW
12856 if (idx + 1 < argc) {
12857 if (argv[idx + 1]->type == VARIABLE_TKN)
12858 maybecomm = argv[idx + 1]->arg;
12859 else
12860 maybecomm = argv[idx + 1]->text;
12861 }
12862
cf4898bc
QY
12863 if (maybecomm && !strmatch(maybecomm, "json")
12864 && !strmatch(maybecomm, "exact-match"))
12865 community = maybecomm;
d0086e8e 12866
cf4898bc
QY
12867 if (argv_find(argv, argc, "exact-match", &idx))
12868 exact_match = 1;
d0086e8e 12869
96f3485c
MK
12870 if (!community)
12871 sh_type = bgp_show_type_community_all;
12872 }
12873
70799983
RW
12874 if (argv_find(argv, argc, "community-list", &idx)) {
12875 const char *clist_number_or_name = argv[++idx]->arg;
12876 struct community_list *list;
12877
12878 if (argv_find(argv, argc, "exact-match", &idx))
12879 exact_match = 1;
12880
12881 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12882 COMMUNITY_LIST_MASTER);
12883 if (list == NULL) {
606d49a4 12884 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12885 clist_number_or_name);
12886 return CMD_WARNING;
12887 }
12888
12889 if (exact_match)
12890 sh_type = bgp_show_type_community_list_exact;
12891 else
12892 sh_type = bgp_show_type_community_list;
12893 output_arg = list;
12894 }
12895
a7129347
RW
12896 if (argv_find(argv, argc, "filter-list", &idx)) {
12897 const char *filter = argv[++idx]->arg;
12898 struct as_list *as_list;
12899
12900 as_list = as_list_lookup(filter);
12901 if (as_list == NULL) {
606d49a4 12902 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12903 filter);
12904 return CMD_WARNING;
12905 }
12906
12907 sh_type = bgp_show_type_filter_list;
12908 output_arg = as_list;
12909 }
12910
6deaf579
RW
12911 if (argv_find(argv, argc, "prefix-list", &idx)) {
12912 const char *prefix_list_str = argv[++idx]->arg;
12913 struct prefix_list *plist;
12914
12915 plist = prefix_list_lookup(afi, prefix_list_str);
12916 if (plist == NULL) {
606d49a4 12917 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12918 prefix_list_str);
12919 return CMD_WARNING;
12920 }
12921
12922 sh_type = bgp_show_type_prefix_list;
12923 output_arg = plist;
12924 }
12925
ed126382
DA
12926 if (argv_find(argv, argc, "access-list", &idx)) {
12927 const char *access_list_str = argv[++idx]->arg;
12928 struct access_list *alist;
12929
12930 alist = access_list_lookup(afi, access_list_str);
12931 if (!alist) {
606d49a4 12932 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12933 access_list_str);
12934 return CMD_WARNING;
12935 }
12936
12937 sh_type = bgp_show_type_access_list;
12938 output_arg = alist;
12939 }
12940
bf1a944a
RW
12941 if (argv_find(argv, argc, "route-map", &idx)) {
12942 const char *rmap_str = argv[++idx]->arg;
12943 struct route_map *rmap;
12944
12945 rmap = route_map_lookup_by_name(rmap_str);
12946 if (!rmap) {
606d49a4 12947 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12948 return CMD_WARNING;
12949 }
12950
12951 sh_type = bgp_show_type_route_map;
12952 output_arg = rmap;
12953 }
12954
1e2ce4f1
DS
12955 if (argv_find(argv, argc, "rpki", &idx)) {
12956 sh_type = bgp_show_type_rpki;
12957 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12958 rpki_target_state = RPKI_VALID;
1e2ce4f1 12959 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12960 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12961 }
12962
7d3cae70
DA
12963 /* Display prefixes with matching version numbers */
12964 if (argv_find(argv, argc, "version", &idx)) {
12965 sh_type = bgp_show_type_prefix_version;
2391833e 12966 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12967 }
12968
a70a28a5
DA
12969 /* Display prefixes with matching BGP community alias */
12970 if (argv_find(argv, argc, "alias", &idx)) {
12971 sh_type = bgp_show_type_community_alias;
2391833e 12972 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12973 }
12974
39c3c736
RW
12975 /* prefix-longer */
12976 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12977 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12978 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12979
12980 if (!str2prefix(prefix_str, &p)) {
12981 vty_out(vty, "%% Malformed Prefix\n");
12982 return CMD_WARNING;
12983 }
12984
12985 sh_type = bgp_show_type_prefix_longer;
12986 output_arg = &p;
a70a28a5
DA
12987 }
12988
83856649
KQ
12989 /* self originated only */
12990 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &idx))
12991 sh_type = bgp_show_type_self_originated;
12992
96f3485c
MK
12993 if (!all) {
12994 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12995 if (community)
12996 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12997 exact_match, afi, safi,
12998 show_flags);
2391833e 12999 else
a70a28a5 13000 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 13001 output_arg, show_flags,
a70a28a5 13002 rpki_target_state);
96f3485c 13003 } else {
fa5ac378
DA
13004 struct listnode *node;
13005 struct bgp *abgp;
96f3485c
MK
13006 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
13007 * AFI_IP6 */
13008
13009 if (uj)
13010 vty_out(vty, "{\n");
13011
13012 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13013 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13014 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13015 ? AFI_IP
13016 : AFI_IP6;
fa5ac378
DA
13017 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13018 FOREACH_SAFI (safi) {
13019 if (!bgp_afi_safi_peer_exists(abgp, afi,
13020 safi))
13021 continue;
96f3485c 13022
fa5ac378
DA
13023 if (uj) {
13024 if (first)
13025 first = false;
13026 else
13027 vty_out(vty, ",\n");
13028 vty_out(vty, "\"%s\":{\n",
13029 get_afi_safi_str(afi,
13030 safi,
13031 true));
13032 } else
13033 vty_out(vty,
13034 "\nFor address family: %s\n",
13035 get_afi_safi_str(
13036 afi, safi,
13037 false));
13038
13039 if (community)
13040 bgp_show_community(
13041 vty, abgp, community,
13042 exact_match, afi, safi,
13043 show_flags);
96f3485c 13044 else
fa5ac378
DA
13045 bgp_show(vty, abgp, afi, safi,
13046 sh_type, output_arg,
13047 show_flags,
13048 rpki_target_state);
13049 if (uj)
13050 vty_out(vty, "}\n");
13051 }
96f3485c
MK
13052 }
13053 } else {
13054 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
13055 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
13056 FOREACH_AFI_SAFI (afi, safi) {
13057 if (!bgp_afi_safi_peer_exists(abgp, afi,
13058 safi))
13059 continue;
96f3485c 13060
fa5ac378
DA
13061 if (uj) {
13062 if (first)
13063 first = false;
13064 else
13065 vty_out(vty, ",\n");
13066
13067 vty_out(vty, "\"%s\":{\n",
13068 get_afi_safi_str(afi,
13069 safi,
13070 true));
13071 } else
13072 vty_out(vty,
13073 "\nFor address family: %s\n",
13074 get_afi_safi_str(
13075 afi, safi,
13076 false));
13077
13078 if (community)
13079 bgp_show_community(
13080 vty, abgp, community,
13081 exact_match, afi, safi,
13082 show_flags);
96f3485c 13083 else
fa5ac378
DA
13084 bgp_show(vty, abgp, afi, safi,
13085 sh_type, output_arg,
13086 show_flags,
13087 rpki_target_state);
13088 if (uj)
13089 vty_out(vty, "}\n");
13090 }
96f3485c
MK
13091 }
13092 }
13093 if (uj)
13094 vty_out(vty, "}\n");
13095 }
13096 return CMD_SUCCESS;
a636c635 13097}
47fc97cc 13098
718e3744 13099DEFUN (show_ip_bgp_route,
13100 show_ip_bgp_route_cmd,
8aa22bbb 13101 "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 13102 SHOW_STR
13103 IP_STR
13104 BGP_STR
a636c635 13105 BGP_INSTANCE_HELP_STR
4f280b15 13106 BGP_AFI_HELP_STR
4dd6177e 13107 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13108 "Network in the BGP routing table to display\n"
0c7b1b01 13109 "IPv4 prefix\n"
8c3deaae 13110 "Network in the BGP routing table to display\n"
0c7b1b01 13111 "IPv6 prefix\n"
4092b06c 13112 "Display only the bestpath\n"
b05a1c8b 13113 "Display only multipaths\n"
8aa22bbb
DS
13114 "Display only paths that match the specified rpki state\n"
13115 "A valid path as determined by rpki\n"
13116 "A invalid path as determined by rpki\n"
13117 "A path that has no rpki data\n"
9973d184 13118 JSON_STR)
4092b06c 13119{
d62a17ae 13120 int prefix_check = 0;
ae19d7dd 13121
d62a17ae 13122 afi_t afi = AFI_IP6;
13123 safi_t safi = SAFI_UNICAST;
13124 char *prefix = NULL;
13125 struct bgp *bgp = NULL;
13126 enum bgp_path_type path_type;
9f049418 13127 bool uj = use_json(argc, argv);
b05a1c8b 13128
d62a17ae 13129 int idx = 0;
ae19d7dd 13130
d62a17ae 13131 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13132 &bgp, uj);
d62a17ae 13133 if (!idx)
13134 return CMD_WARNING;
c41247f5 13135
d62a17ae 13136 if (!bgp) {
13137 vty_out(vty,
13138 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13139 return CMD_WARNING;
13140 }
a636c635 13141
d62a17ae 13142 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13143 if (argv_find(argv, argc, "A.B.C.D", &idx)
13144 || argv_find(argv, argc, "X:X::X:X", &idx))
13145 prefix_check = 0;
13146 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13147 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13148 prefix_check = 1;
13149
13150 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13151 && afi != AFI_IP6) {
13152 vty_out(vty,
13153 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13154 return CMD_WARNING;
13155 }
13156 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13157 && afi != AFI_IP) {
13158 vty_out(vty,
13159 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13160 return CMD_WARNING;
13161 }
13162
13163 prefix = argv[idx]->arg;
13164
13165 /* [<bestpath|multipath>] */
13166 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13167 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13168 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13169 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13170 else
360660c6 13171 path_type = BGP_PATH_SHOW_ALL;
a636c635 13172
d62a17ae 13173 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13174 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13175}
13176
8c3deaae
QY
13177DEFUN (show_ip_bgp_regexp,
13178 show_ip_bgp_regexp_cmd,
3e5b31b3 13179 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13180 SHOW_STR
13181 IP_STR
13182 BGP_STR
b00b230a 13183 BGP_INSTANCE_HELP_STR
4f280b15 13184 BGP_AFI_HELP_STR
4dd6177e 13185 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13186 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13187 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13188 JSON_STR)
8c3deaae 13189{
d62a17ae 13190 afi_t afi = AFI_IP6;
13191 safi_t safi = SAFI_UNICAST;
13192 struct bgp *bgp = NULL;
3e5b31b3
DA
13193 bool uj = use_json(argc, argv);
13194 char *regstr = NULL;
8c3deaae 13195
d62a17ae 13196 int idx = 0;
13197 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13198 &bgp, false);
d62a17ae 13199 if (!idx)
13200 return CMD_WARNING;
8c3deaae 13201
d62a17ae 13202 // get index of regex
3e5b31b3
DA
13203 if (argv_find(argv, argc, "REGEX", &idx))
13204 regstr = argv[idx]->arg;
8c3deaae 13205
5f71d11c 13206 assert(regstr);
3e5b31b3
DA
13207 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13208 bgp_show_type_regexp, uj);
8c3deaae
QY
13209}
13210
ae248832 13211DEFPY (show_ip_bgp_instance_all,
a636c635 13212 show_ip_bgp_instance_all_cmd,
ae248832 13213 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13214 SHOW_STR
a636c635 13215 IP_STR
4092b06c 13216 BGP_STR
a636c635 13217 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13218 BGP_AFI_HELP_STR
4dd6177e 13219 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13220 JSON_STR
13221 "Increase table width for longer prefixes\n")
4092b06c 13222{
54d05dea 13223 afi_t afi = AFI_IP6;
d62a17ae 13224 safi_t safi = SAFI_UNICAST;
13225 struct bgp *bgp = NULL;
d62a17ae 13226 int idx = 0;
96c81f66 13227 uint16_t show_flags = 0;
ae19d7dd 13228
96f3485c 13229 if (uj) {
d62a17ae 13230 argc--;
96f3485c
MK
13231 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13232 }
13233
13234 if (wide)
13235 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13236
9f049418
DS
13237 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13238 &bgp, uj);
13239 if (!idx)
13240 return CMD_WARNING;
13241
96f3485c 13242 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13243 return CMD_SUCCESS;
e3e29b32
LB
13244}
13245
a4d82a8a 13246static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13247 afi_t afi, safi_t safi, enum bgp_show_type type,
13248 bool use_json)
718e3744 13249{
d62a17ae 13250 regex_t *regex;
13251 int rc;
96c81f66 13252 uint16_t show_flags = 0;
96f3485c
MK
13253
13254 if (use_json)
13255 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13256
c3900853 13257 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13258 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13259 regstr);
13260 return CMD_WARNING_CONFIG_FAILED;
13261 }
13262
d62a17ae 13263 regex = bgp_regcomp(regstr);
13264 if (!regex) {
13265 vty_out(vty, "Can't compile regexp %s\n", regstr);
13266 return CMD_WARNING;
13267 }
a636c635 13268
1e2ce4f1
DS
13269 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13270 RPKI_NOT_BEING_USED);
d62a17ae 13271 bgp_regex_free(regex);
13272 return rc;
e3e29b32
LB
13273}
13274
7f323236
DW
13275static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13276 const char *comstr, int exact, afi_t afi,
96c81f66 13277 safi_t safi, uint16_t show_flags)
d62a17ae 13278{
13279 struct community *com;
d62a17ae 13280 int ret = 0;
13281
7f323236 13282 com = community_str2com(comstr);
d62a17ae 13283 if (!com) {
7f323236 13284 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13285 return CMD_WARNING;
13286 }
13287
13288 ret = bgp_show(vty, bgp, afi, safi,
13289 (exact ? bgp_show_type_community_exact
13290 : bgp_show_type_community),
1e2ce4f1 13291 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13292 community_free(&com);
46c3ce83 13293
d62a17ae 13294 return ret;
718e3744 13295}
13296
d62a17ae 13297enum bgp_stats {
13298 BGP_STATS_MAXBITLEN = 0,
13299 BGP_STATS_RIB,
13300 BGP_STATS_PREFIXES,
13301 BGP_STATS_TOTPLEN,
13302 BGP_STATS_UNAGGREGATEABLE,
13303 BGP_STATS_MAX_AGGREGATEABLE,
13304 BGP_STATS_AGGREGATES,
13305 BGP_STATS_SPACE,
13306 BGP_STATS_ASPATH_COUNT,
13307 BGP_STATS_ASPATH_MAXHOPS,
13308 BGP_STATS_ASPATH_TOTHOPS,
13309 BGP_STATS_ASPATH_MAXSIZE,
13310 BGP_STATS_ASPATH_TOTSIZE,
13311 BGP_STATS_ASN_HIGHEST,
13312 BGP_STATS_MAX,
a636c635 13313};
2815e61f 13314
9ab0cf58 13315#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13316#define TABLE_STATS_IDX_JSON 1
13317
13318static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13319 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13320 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13321 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13322 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13323 "unaggregateablePrefixes"},
13324 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13325 "maximumAggregateablePrefixes"},
13326 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13327 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13328 [BGP_STATS_SPACE] = {"Address space advertised",
13329 "addressSpaceAdvertised"},
9ab0cf58
PG
13330 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13331 "advertisementsWithPaths"},
13332 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13333 "longestAsPath"},
13334 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13335 "largestAsPath"},
13336 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13337 "averageAsPathLengthHops"},
13338 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13339 "averageAsPathSizeBytes"},
13340 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13341 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13342};
2815e61f 13343
d62a17ae 13344struct bgp_table_stats {
13345 struct bgp_table *table;
13346 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13347
13348 unsigned long long
13349 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13350 1];
13351
8d0ab76d 13352 double total_space;
ff7924f6
PJ
13353};
13354
9bcb3eef 13355static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13356 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13357{
9bcb3eef 13358 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13359 struct bgp_path_info *pi;
b54892e0 13360 const struct prefix *rn_p;
d62a17ae 13361
9bcb3eef 13362 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13363 return;
d62a17ae 13364
9bcb3eef 13365 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13366 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13367 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13368
0747643e 13369 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13370 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13371 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13372 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13373
9bcb3eef 13374 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13375 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13376 /* announced address space */
13377 if (space)
b54892e0 13378 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13379 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13380 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13381
9c14ec72 13382
9bcb3eef 13383 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13384 ts->counts[BGP_STATS_RIB]++;
13385
05864da7
DS
13386 if (CHECK_FLAG(pi->attr->flag,
13387 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13388 ts->counts[BGP_STATS_AGGREGATES]++;
13389
13390 /* as-path stats */
05864da7 13391 if (pi->attr->aspath) {
9c14ec72
RW
13392 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13393 unsigned int size = aspath_size(pi->attr->aspath);
13394 as_t highest = aspath_highest(pi->attr->aspath);
13395
13396 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13397
13398 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13399 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13400
13401 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13402 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13403
13404 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13405 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13406 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13407 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13408 }
13409 }
13410}
13411
e6685141 13412static void bgp_table_stats_walker(struct event *t)
9c14ec72 13413{
9bcb3eef
DS
13414 struct bgp_dest *dest, *ndest;
13415 struct bgp_dest *top;
e16d030c 13416 struct bgp_table_stats *ts = EVENT_ARG(t);
9c14ec72
RW
13417 unsigned int space = 0;
13418
13419 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13420 return;
9c14ec72
RW
13421
13422 switch (ts->table->afi) {
13423 case AFI_IP:
13424 space = IPV4_MAX_BITLEN;
13425 break;
13426 case AFI_IP6:
13427 space = IPV6_MAX_BITLEN;
13428 break;
3ba7b4af
TA
13429 case AFI_L2VPN:
13430 space = EVPN_ROUTE_PREFIXLEN;
13431 break;
58cf0823
DS
13432 case AFI_UNSPEC:
13433 case AFI_MAX:
cc9f21da 13434 return;
9c14ec72
RW
13435 }
13436
13437 ts->counts[BGP_STATS_MAXBITLEN] = space;
13438
9bcb3eef 13439 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13440 if (ts->table->safi == SAFI_MPLS_VPN
13441 || ts->table->safi == SAFI_ENCAP
13442 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13443 struct bgp_table *table;
13444
9bcb3eef 13445 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13446 if (!table)
13447 continue;
13448
13449 top = bgp_table_top(table);
9bcb3eef
DS
13450 for (ndest = bgp_table_top(table); ndest;
13451 ndest = bgp_route_next(ndest))
13452 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13453 } else {
9bcb3eef 13454 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13455 }
13456 }
2815e61f 13457}
ff7924f6 13458
71f1613a
DA
13459static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13460 struct json_object *json_array)
13461{
13462 struct listnode *node, *nnode;
13463 struct bgp *bgp;
13464
13465 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13466 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13467}
13468
13469static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13470 safi_t safi, struct json_object *json_array)
2815e61f 13471{
d62a17ae 13472 struct bgp_table_stats ts;
13473 unsigned int i;
893cccd0
PG
13474 int ret = CMD_SUCCESS;
13475 char temp_buf[20];
6c9d22e2 13476 struct json_object *json = NULL;
0747643e
AQ
13477 uint32_t bitlen = 0;
13478 struct json_object *json_bitlen;
6c9d22e2
PG
13479
13480 if (json_array)
13481 json = json_object_new_object();
019386c2 13482
d62a17ae 13483 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13484 char warning_msg[50];
13485
13486 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13487 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13488 safi);
6c9d22e2
PG
13489
13490 if (!json)
893cccd0
PG
13491 vty_out(vty, "%s\n", warning_msg);
13492 else
9ab0cf58 13493 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13494
893cccd0
PG
13495 ret = CMD_WARNING;
13496 goto end_table_stats;
d62a17ae 13497 }
019386c2 13498
893cccd0 13499 if (!json)
5290ceab
DA
13500 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13501 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13502 else
13503 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13504
d62a17ae 13505 /* labeled-unicast routes live in the unicast table */
13506 if (safi == SAFI_LABELED_UNICAST)
13507 safi = SAFI_UNICAST;
019386c2 13508
d62a17ae 13509 memset(&ts, 0, sizeof(ts));
13510 ts.table = bgp->rib[afi][safi];
8c1186d3 13511 event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13512
d62a17ae 13513 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13514 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13515 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13516 continue;
13517
13518 switch (i) {
d62a17ae 13519 case BGP_STATS_ASPATH_TOTHOPS:
13520 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13521 if (!json) {
9ab0cf58
PG
13522 snprintf(
13523 temp_buf, sizeof(temp_buf), "%12.2f",
13524 ts.counts[i]
13525 ? (float)ts.counts[i]
13526 / (float)ts.counts
13527 [BGP_STATS_ASPATH_COUNT]
13528 : 0);
893cccd0 13529 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13530 table_stats_strs[i]
13531 [TABLE_STATS_IDX_VTY],
893cccd0 13532 temp_buf);
9ab0cf58
PG
13533 } else {
13534 json_object_double_add(
13535 json,
13536 table_stats_strs[i]
13537 [TABLE_STATS_IDX_JSON],
13538 ts.counts[i]
13539 ? (double)ts.counts[i]
13540 / (double)ts.counts
d62a17ae 13541 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13542 : 0);
13543 }
d62a17ae 13544 break;
13545 case BGP_STATS_TOTPLEN:
6c9d22e2 13546 if (!json) {
9ab0cf58
PG
13547 snprintf(
13548 temp_buf, sizeof(temp_buf), "%12.2f",
13549 ts.counts[i]
13550 ? (float)ts.counts[i]
13551 / (float)ts.counts
13552 [BGP_STATS_PREFIXES]
13553 : 0);
893cccd0 13554 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13555 table_stats_strs[i]
13556 [TABLE_STATS_IDX_VTY],
893cccd0 13557 temp_buf);
9ab0cf58
PG
13558 } else {
13559 json_object_double_add(
13560 json,
13561 table_stats_strs[i]
13562 [TABLE_STATS_IDX_JSON],
13563 ts.counts[i]
13564 ? (double)ts.counts[i]
13565 / (double)ts.counts
d62a17ae 13566 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13567 : 0);
13568 }
d62a17ae 13569 break;
13570 case BGP_STATS_SPACE:
6c9d22e2
PG
13571 if (!json) {
13572 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13573 ts.total_space);
893cccd0 13574 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13575 table_stats_strs[i]
13576 [TABLE_STATS_IDX_VTY],
893cccd0 13577 temp_buf);
9ab0cf58
PG
13578 } else {
13579 json_object_double_add(
13580 json,
13581 table_stats_strs[i]
13582 [TABLE_STATS_IDX_JSON],
13583 (double)ts.total_space);
13584 }
8d0ab76d 13585 if (afi == AFI_IP6) {
6c9d22e2
PG
13586 if (!json) {
13587 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13588 "%12g",
13589 ts.total_space
13590 * pow(2.0, -128 + 32));
6c9d22e2
PG
13591 vty_out(vty, "%30s: %s\n",
13592 "/32 equivalent %s\n",
13593 temp_buf);
9ab0cf58
PG
13594 } else {
13595 json_object_double_add(
13596 json, "/32equivalent",
13597 (double)(ts.total_space
13598 * pow(2.0,
13599 -128 + 32)));
13600 }
6c9d22e2
PG
13601 if (!json) {
13602 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13603 "%12g",
13604 ts.total_space
13605 * pow(2.0, -128 + 48));
6c9d22e2
PG
13606 vty_out(vty, "%30s: %s\n",
13607 "/48 equivalent %s\n",
13608 temp_buf);
9ab0cf58
PG
13609 } else {
13610 json_object_double_add(
13611 json, "/48equivalent",
13612 (double)(ts.total_space
13613 * pow(2.0,
13614 -128 + 48)));
13615 }
8d0ab76d 13616 } else {
6c9d22e2
PG
13617 if (!json) {
13618 snprintf(temp_buf, sizeof(temp_buf),
13619 "%12.2f",
9ab0cf58
PG
13620 ts.total_space * 100.
13621 * pow(2.0, -32));
6c9d22e2 13622 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13623 "% announced ", temp_buf);
13624 } else {
13625 json_object_double_add(
13626 json, "%announced",
13627 (double)(ts.total_space * 100.
13628 * pow(2.0, -32)));
13629 }
6c9d22e2
PG
13630 if (!json) {
13631 snprintf(temp_buf, sizeof(temp_buf),
13632 "%12.2f",
9ab0cf58
PG
13633 ts.total_space
13634 * pow(2.0, -32 + 8));
6c9d22e2
PG
13635 vty_out(vty, "%30s: %s\n",
13636 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13637 } else {
13638 json_object_double_add(
13639 json, "/8equivalent",
13640 (double)(ts.total_space
13641 * pow(2.0, -32 + 8)));
13642 }
6c9d22e2
PG
13643 if (!json) {
13644 snprintf(temp_buf, sizeof(temp_buf),
13645 "%12.2f",
9ab0cf58
PG
13646 ts.total_space
13647 * pow(2.0, -32 + 24));
6c9d22e2 13648 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13649 "/24 equivalent ", temp_buf);
13650 } else {
13651 json_object_double_add(
13652 json, "/24equivalent",
13653 (double)(ts.total_space
13654 * pow(2.0, -32 + 24)));
13655 }
8d0ab76d 13656 }
d62a17ae 13657 break;
13658 default:
6c9d22e2
PG
13659 if (!json) {
13660 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13661 ts.counts[i]);
893cccd0 13662 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13663 table_stats_strs[i]
13664 [TABLE_STATS_IDX_VTY],
13665 temp_buf);
13666 } else {
13667 json_object_int_add(
13668 json,
13669 table_stats_strs[i]
13670 [TABLE_STATS_IDX_JSON],
13671 ts.counts[i]);
13672 }
d62a17ae 13673 }
893cccd0
PG
13674 if (!json)
13675 vty_out(vty, "\n");
d62a17ae 13676 }
0747643e
AQ
13677
13678 switch (afi) {
13679 case AFI_IP:
13680 bitlen = IPV4_MAX_BITLEN;
13681 break;
13682 case AFI_IP6:
13683 bitlen = IPV6_MAX_BITLEN;
13684 break;
13685 case AFI_L2VPN:
13686 bitlen = EVPN_ROUTE_PREFIXLEN;
13687 break;
58cf0823
DS
13688 case AFI_UNSPEC:
13689 case AFI_MAX:
0747643e
AQ
13690 break;
13691 }
13692
13693 if (json) {
13694 json_bitlen = json_object_new_array();
13695
13696 for (i = 0; i <= bitlen; i++) {
13697 struct json_object *ind_bit = json_object_new_object();
13698
13699 if (!ts.prefix_len_count[i])
13700 continue;
13701
13702 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13703 json_object_int_add(ind_bit, temp_buf,
13704 ts.prefix_len_count[i]);
13705 json_object_array_add(json_bitlen, ind_bit);
13706 }
13707 json_object_object_add(json, "prefixLength", json_bitlen);
13708 }
13709
9ab0cf58 13710end_table_stats:
6c9d22e2
PG
13711 if (json)
13712 json_object_array_add(json_array, json);
893cccd0 13713 return ret;
d62a17ae 13714}
13715
71f1613a
DA
13716static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13717 safi_t safi, struct json_object *json_array)
13718{
13719 if (!bgp) {
13720 bgp_table_stats_all(vty, afi, safi, json_array);
13721 return CMD_SUCCESS;
13722 }
13723
13724 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13725}
13726
d62a17ae 13727enum bgp_pcounts {
13728 PCOUNT_ADJ_IN = 0,
13729 PCOUNT_DAMPED,
13730 PCOUNT_REMOVED,
13731 PCOUNT_HISTORY,
13732 PCOUNT_STALE,
13733 PCOUNT_VALID,
13734 PCOUNT_ALL,
13735 PCOUNT_COUNTED,
7e3d9632 13736 PCOUNT_BPATH_SELECTED,
d62a17ae 13737 PCOUNT_PFCNT, /* the figure we display to users */
13738 PCOUNT_MAX,
a636c635 13739};
718e3744 13740
2b64873d 13741static const char *const pcount_strs[] = {
9d303b37
DL
13742 [PCOUNT_ADJ_IN] = "Adj-in",
13743 [PCOUNT_DAMPED] = "Damped",
13744 [PCOUNT_REMOVED] = "Removed",
13745 [PCOUNT_HISTORY] = "History",
13746 [PCOUNT_STALE] = "Stale",
13747 [PCOUNT_VALID] = "Valid",
13748 [PCOUNT_ALL] = "All RIB",
13749 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13750 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13751 [PCOUNT_PFCNT] = "Useable",
13752 [PCOUNT_MAX] = NULL,
a636c635 13753};
718e3744 13754
d62a17ae 13755struct peer_pcounts {
13756 unsigned int count[PCOUNT_MAX];
13757 const struct peer *peer;
13758 const struct bgp_table *table;
54317cba 13759 safi_t safi;
a636c635 13760};
47fc97cc 13761
9bcb3eef 13762static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13763{
54317cba
JW
13764 const struct bgp_adj_in *ain;
13765 const struct bgp_path_info *pi;
d62a17ae 13766 const struct peer *peer = pc->peer;
13767
54317cba
JW
13768 for (ain = rn->adj_in; ain; ain = ain->next)
13769 if (ain->peer == peer)
13770 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13771
9bcb3eef 13772 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13773
54317cba
JW
13774 if (pi->peer != peer)
13775 continue;
d62a17ae 13776
54317cba 13777 pc->count[PCOUNT_ALL]++;
d62a17ae 13778
54317cba
JW
13779 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13780 pc->count[PCOUNT_DAMPED]++;
13781 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13782 pc->count[PCOUNT_HISTORY]++;
13783 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13784 pc->count[PCOUNT_REMOVED]++;
13785 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13786 pc->count[PCOUNT_STALE]++;
13787 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13788 pc->count[PCOUNT_VALID]++;
13789 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13790 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13791 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13792 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13793
13794 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13795 pc->count[PCOUNT_COUNTED]++;
13796 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13797 flog_err(
13798 EC_LIB_DEVELOPMENT,
13799 "Attempting to count but flags say it is unusable");
13800 } else {
40381db7 13801 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13802 flog_err(
13803 EC_LIB_DEVELOPMENT,
13804 "Not counted but flags say we should");
d62a17ae 13805 }
13806 }
54317cba
JW
13807}
13808
e6685141 13809static void bgp_peer_count_walker(struct event *t)
54317cba 13810{
9bcb3eef 13811 struct bgp_dest *rn, *rm;
54317cba 13812 const struct bgp_table *table;
e16d030c 13813 struct peer_pcounts *pc = EVENT_ARG(t);
54317cba
JW
13814
13815 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13816 || pc->safi == SAFI_EVPN) {
13817 /* Special handling for 2-level routing tables. */
13818 for (rn = bgp_table_top(pc->table); rn;
13819 rn = bgp_route_next(rn)) {
9bcb3eef 13820 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13821 if (table != NULL)
13822 for (rm = bgp_table_top(table); rm;
13823 rm = bgp_route_next(rm))
13824 bgp_peer_count_proc(rm, pc);
13825 }
13826 } else
13827 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13828 bgp_peer_count_proc(rn, pc);
718e3744 13829}
13830
d62a17ae 13831static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13832 safi_t safi, bool use_json)
856ca177 13833{
d62a17ae 13834 struct peer_pcounts pcounts = {.peer = peer};
13835 unsigned int i;
13836 json_object *json = NULL;
13837 json_object *json_loop = NULL;
856ca177 13838
d62a17ae 13839 if (use_json) {
13840 json = json_object_new_object();
13841 json_loop = json_object_new_object();
13842 }
718e3744 13843
d62a17ae 13844 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13845 || !peer->bgp->rib[afi][safi]) {
13846 if (use_json) {
13847 json_object_string_add(
13848 json, "warning",
13849 "No such neighbor or address family");
13850 vty_out(vty, "%s\n", json_object_to_json_string(json));
13851 json_object_free(json);
d5f20468 13852 json_object_free(json_loop);
d62a17ae 13853 } else
13854 vty_out(vty, "%% No such neighbor or address family\n");
13855
13856 return CMD_WARNING;
13857 }
2a71e9ce 13858
d62a17ae 13859 memset(&pcounts, 0, sizeof(pcounts));
13860 pcounts.peer = peer;
13861 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13862 pcounts.safi = safi;
d62a17ae 13863
13864 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13865 * stats for the thread-walk (i.e. ensure this can't be blamed on
13866 * on just vty_read()).
13867 */
8c1186d3 13868 event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
d62a17ae 13869
13870 if (use_json) {
13871 json_object_string_add(json, "prefixCountsFor", peer->host);
13872 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13873 get_afi_safi_str(afi, safi, true));
d62a17ae 13874 json_object_int_add(json, "pfxCounter",
13875 peer->pcount[afi][safi]);
13876
13877 for (i = 0; i < PCOUNT_MAX; i++)
13878 json_object_int_add(json_loop, pcount_strs[i],
13879 pcounts.count[i]);
13880
13881 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13882
13883 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13884 json_object_string_add(json, "pfxctDriftFor",
13885 peer->host);
13886 json_object_string_add(
13887 json, "recommended",
13888 "Please report this bug, with the above command output");
13889 }
75eeda93 13890 vty_json(vty, json);
d62a17ae 13891 } else {
13892
13893 if (peer->hostname
892fedb6 13894 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13895 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13896 peer->hostname, peer->host,
5cb5f4d0 13897 get_afi_safi_str(afi, safi, false));
d62a17ae 13898 } else {
13899 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13900 get_afi_safi_str(afi, safi, false));
d62a17ae 13901 }
13902
6cde4b45 13903 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13904 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13905
13906 for (i = 0; i < PCOUNT_MAX; i++)
13907 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13908 pcounts.count[i]);
13909
13910 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13911 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13912 vty_out(vty,
13913 "Please report this bug, with the above command output\n");
13914 }
13915 }
13916
13917 return CMD_SUCCESS;
718e3744 13918}
13919
a636c635
DW
13920DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13921 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13922 "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 13923 SHOW_STR
13924 IP_STR
13925 BGP_STR
8386ac43 13926 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13927 BGP_AFI_HELP_STR
13928 BGP_SAFI_HELP_STR
0b16f239
DS
13929 "Detailed information on TCP and BGP neighbor connections\n"
13930 "Neighbor to display information about\n"
13931 "Neighbor to display information about\n"
91d37724 13932 "Neighbor on BGP configured interface\n"
a636c635 13933 "Display detailed prefix count information\n"
9973d184 13934 JSON_STR)
0b16f239 13935{
d62a17ae 13936 afi_t afi = AFI_IP6;
13937 safi_t safi = SAFI_UNICAST;
13938 struct peer *peer;
13939 int idx = 0;
13940 struct bgp *bgp = NULL;
9f049418
DS
13941 bool uj = use_json(argc, argv);
13942
13943 if (uj)
13944 argc--;
856ca177 13945
d62a17ae 13946 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13947 &bgp, uj);
d62a17ae 13948 if (!idx)
13949 return CMD_WARNING;
0b16f239 13950
d62a17ae 13951 argv_find(argv, argc, "neighbors", &idx);
13952 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13953 if (!peer)
13954 return CMD_WARNING;
bb46e94f 13955
29c8d9da 13956 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13957}
0b16f239 13958
d6902373
PG
13959#ifdef KEEP_OLD_VPN_COMMANDS
13960DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13961 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13962 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13963 SHOW_STR
13964 IP_STR
13965 BGP_STR
d6902373 13966 BGP_VPNVX_HELP_STR
91d37724 13967 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13968 "Detailed information on TCP and BGP neighbor connections\n"
13969 "Neighbor to display information about\n"
13970 "Neighbor to display information about\n"
91d37724 13971 "Neighbor on BGP configured interface\n"
a636c635 13972 "Display detailed prefix count information\n"
9973d184 13973 JSON_STR)
a636c635 13974{
d62a17ae 13975 int idx_peer = 6;
13976 struct peer *peer;
9f049418 13977 bool uj = use_json(argc, argv);
a636c635 13978
d62a17ae 13979 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13980 if (!peer)
13981 return CMD_WARNING;
13982
13983 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13984}
13985
d6902373
PG
13986DEFUN (show_ip_bgp_vpn_all_route_prefix,
13987 show_ip_bgp_vpn_all_route_prefix_cmd,
13988 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13989 SHOW_STR
13990 IP_STR
13991 BGP_STR
d6902373 13992 BGP_VPNVX_HELP_STR
91d37724
QY
13993 "Display information about all VPNv4 NLRIs\n"
13994 "Network in the BGP routing table to display\n"
3a2d747c 13995 "Network in the BGP routing table to display\n"
9973d184 13996 JSON_STR)
91d37724 13997{
d62a17ae 13998 int idx = 0;
13999 char *network = NULL;
14000 struct bgp *bgp = bgp_get_default();
14001 if (!bgp) {
14002 vty_out(vty, "Can't find default instance\n");
14003 return CMD_WARNING;
14004 }
87e34b58 14005
d62a17ae 14006 if (argv_find(argv, argc, "A.B.C.D", &idx))
14007 network = argv[idx]->arg;
14008 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
14009 network = argv[idx]->arg;
14010 else {
14011 vty_out(vty, "Unable to figure out Network\n");
14012 return CMD_WARNING;
14013 }
87e34b58 14014
d62a17ae 14015 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
14016 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14017 use_json(argc, argv));
91d37724 14018}
d6902373 14019#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 14020
44c69747
LK
14021DEFUN (show_bgp_l2vpn_evpn_route_prefix,
14022 show_bgp_l2vpn_evpn_route_prefix_cmd,
14023 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 14024 SHOW_STR
4c63a661
PG
14025 BGP_STR
14026 L2VPN_HELP_STR
14027 EVPN_HELP_STR
44c69747
LK
14028 "Network in the BGP routing table to display\n"
14029 "Network in the BGP routing table to display\n"
4c63a661
PG
14030 "Network in the BGP routing table to display\n"
14031 "Network in the BGP routing table to display\n"
14032 JSON_STR)
14033{
d62a17ae 14034 int idx = 0;
14035 char *network = NULL;
44c69747 14036 int prefix_check = 0;
a636c635 14037
44c69747
LK
14038 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
14039 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 14040 network = argv[idx]->arg;
44c69747 14041 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 14042 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 14043 network = argv[idx]->arg;
44c69747
LK
14044 prefix_check = 1;
14045 } else {
d62a17ae 14046 vty_out(vty, "Unable to figure out Network\n");
14047 return CMD_WARNING;
14048 }
44c69747
LK
14049 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
14050 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 14051 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 14052}
14053
114fc229 14054static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
14055 struct bgp_table *table, int *header1,
14056 int *header2, json_object *json,
14057 json_object *json_scode,
e960b4ca
TA
14058 json_object *json_ocode, bool wide,
14059 bool detail)
2f9bc755
DS
14060{
14061 uint64_t version = table ? table->version : 0;
14062
14063 if (*header1) {
14064 if (json) {
14065 json_object_int_add(json, "bgpTableVersion", version);
c949c771 14066 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 14067 "%pI4", &peer->bgp->router_id);
2f9bc755 14068 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
14069 peer->bgp->default_local_pref);
14070 json_object_int_add(json, "localAS",
14071 peer->change_local_as
14072 ? peer->change_local_as
14073 : peer->local_as);
2f9bc755
DS
14074 json_object_object_add(json, "bgpStatusCodes",
14075 json_scode);
14076 json_object_object_add(json, "bgpOriginCodes",
14077 json_ocode);
14078 } else {
14079 vty_out(vty,
23d0a753
DA
14080 "BGP table version is %" PRIu64
14081 ", local router ID is %pI4, vrf id ",
114fc229
DA
14082 version, &peer->bgp->router_id);
14083 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
14084 vty_out(vty, "%s", VRFID_NONE_STR);
14085 else
114fc229 14086 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14087 vty_out(vty, "\n");
14088 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14089 peer->bgp->default_local_pref);
14090 vty_out(vty, "local AS %u\n",
14091 peer->change_local_as ? peer->change_local_as
14092 : peer->local_as);
e960b4ca
TA
14093 if (!detail) {
14094 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14095 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14096 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14097 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14098 }
2f9bc755
DS
14099 }
14100 *header1 = 0;
14101 }
14102 if (*header2) {
e960b4ca 14103 if (!json && !detail)
2f9bc755
DS
14104 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14105 : BGP_SHOW_HEADER));
14106 *header2 = 0;
14107 }
14108}
14109
d9478df0
TA
14110static void
14111show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14112 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14113 const char *rmap_name, json_object *json, json_object *json_ar,
14114 json_object *json_scode, json_object *json_ocode,
96c81f66 14115 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14116 const struct prefix *match, unsigned long *output_count,
14117 unsigned long *filtered_count)
d62a17ae 14118{
3880b4ec
TA
14119 struct bgp_adj_in *ain = NULL;
14120 struct bgp_adj_out *adj = NULL;
9bcb3eef 14121 struct bgp_dest *dest;
d62a17ae 14122 struct bgp *bgp;
d62a17ae 14123 struct attr attr;
14124 int ret;
14125 struct update_subgroup *subgrp;
3880b4ec 14126 struct peer_af *paf = NULL;
f99def61 14127 bool route_filtered;
e960b4ca 14128 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14129 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14130 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14131 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14132 || (safi == SAFI_EVPN))
14133 ? true
14134 : false;
e960b4ca
TA
14135 int display = 0;
14136 json_object *json_net = NULL;
a636c635 14137
d62a17ae 14138 bgp = peer->bgp;
a636c635 14139
3880b4ec
TA
14140 /* If the user supplied a prefix, look for a matching route instead
14141 * of walking the whole table.
14142 */
14143 if (match) {
14144 dest = bgp_node_match(table, match);
14145 if (!dest) {
14146 if (!use_json)
14147 vty_out(vty, "Network not in table\n");
14148 return;
14149 }
14150
14151 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14152
14153 if (rn_p->prefixlen != match->prefixlen) {
14154 if (!use_json)
14155 vty_out(vty, "Network not in table\n");
14156 bgp_dest_unlock_node(dest);
14157 return;
14158 }
14159
14160 if (type == bgp_show_adj_route_received ||
14161 type == bgp_show_adj_route_filtered) {
14162 for (ain = dest->adj_in; ain; ain = ain->next) {
14163 if (ain->peer == peer) {
14164 attr = *ain->attr;
14165 break;
14166 }
14167 }
14168 /* bail out if if adj_out is empty, or
14169 * if the prefix isn't in this peer's
14170 * adj_in
14171 */
14172 if (!ain || ain->peer != peer) {
14173 if (!use_json)
14174 vty_out(vty, "Network not in table\n");
14175 bgp_dest_unlock_node(dest);
14176 return;
14177 }
14178 } else if (type == bgp_show_adj_route_advertised) {
14179 bool peer_found = false;
14180
14181 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14182 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14183 if (paf->peer == peer && adj->attr) {
14184 attr = *adj->attr;
14185 peer_found = true;
14186 break;
14187 }
14188 }
14189 if (peer_found)
14190 break;
14191 }
14192 /* bail out if if adj_out is empty, or
14193 * if the prefix isn't in this peer's
14194 * adj_out
14195 */
14196 if (!paf || !peer_found) {
14197 if (!use_json)
14198 vty_out(vty, "Network not in table\n");
14199 bgp_dest_unlock_node(dest);
14200 return;
14201 }
14202 }
14203
14204 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14205 rmap_name);
14206
14207 if (ret != RMAP_DENY) {
14208 show_adj_route_header(vty, peer, table, header1,
14209 header2, json, json_scode,
14210 json_ocode, wide, detail);
14211
14212 if (use_json)
14213 json_net = json_object_new_object();
14214
14215 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14216 afi, safi, json_net,
14217 BGP_PATH_SHOW_ALL, &display,
14218 RPKI_NOT_BEING_USED);
14219 if (use_json)
14220 json_object_object_addf(json_ar, json_net,
14221 "%pFX", rn_p);
14222 (*output_count)++;
14223 } else
14224 (*filtered_count)++;
14225
14226 bgp_attr_flush(&attr);
14227 bgp_dest_unlock_node(dest);
14228 return;
14229 }
14230
14231
d62a17ae 14232 subgrp = peer_subgroup(peer, afi, safi);
14233
6392aaa6 14234 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14235 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14236 if (use_json) {
14237 json_object_int_add(json, "bgpTableVersion",
14238 table->version);
c949c771
DA
14239 json_object_string_addf(json, "bgpLocalRouterId",
14240 "%pI4", &bgp->router_id);
01eced22
AD
14241 json_object_int_add(json, "defaultLocPrf",
14242 bgp->default_local_pref);
114fc229
DA
14243 json_object_int_add(json, "localAS",
14244 peer->change_local_as
14245 ? peer->change_local_as
14246 : peer->local_as);
d62a17ae 14247 json_object_object_add(json, "bgpStatusCodes",
14248 json_scode);
14249 json_object_object_add(json, "bgpOriginCodes",
14250 json_ocode);
07d0c4ed
DA
14251 json_object_string_add(
14252 json, "bgpOriginatingDefaultNetwork",
14253 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14254 } else {
23d0a753
DA
14255 vty_out(vty,
14256 "BGP table version is %" PRIu64
14257 ", local router ID is %pI4, vrf id ",
14258 table->version, &bgp->router_id);
9df8b37c
PZ
14259 if (bgp->vrf_id == VRF_UNKNOWN)
14260 vty_out(vty, "%s", VRFID_NONE_STR);
14261 else
14262 vty_out(vty, "%u", bgp->vrf_id);
14263 vty_out(vty, "\n");
01eced22
AD
14264 vty_out(vty, "Default local pref %u, ",
14265 bgp->default_local_pref);
114fc229
DA
14266 vty_out(vty, "local AS %u\n",
14267 peer->change_local_as ? peer->change_local_as
14268 : peer->local_as);
e960b4ca
TA
14269 if (!detail) {
14270 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14271 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14272 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14273 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14274 }
d62a17ae 14275
07d0c4ed
DA
14276 vty_out(vty, "Originating default network %s\n\n",
14277 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14278 }
65565c9a 14279 (*output_count)++;
d9478df0 14280 *header1 = 0;
d62a17ae 14281 }
a636c635 14282
9bcb3eef 14283 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14284 if (type == bgp_show_adj_route_received
14285 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14286 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14287 if (ain->peer != peer)
ea47320b 14288 continue;
114fc229 14289 show_adj_route_header(vty, peer, table, header1,
d9478df0 14290 header2, json, json_scode,
e960b4ca 14291 json_ocode, wide, detail);
d9478df0
TA
14292
14293 if ((safi == SAFI_MPLS_VPN)
14294 || (safi == SAFI_ENCAP)
14295 || (safi == SAFI_EVPN)) {
14296 if (use_json)
14297 json_object_string_add(
14298 json_ar, "rd", rd_str);
14299 else if (show_rd && rd_str) {
14300 vty_out(vty,
14301 "Route Distinguisher: %s\n",
14302 rd_str);
14303 show_rd = false;
14304 }
14305 }
6392aaa6 14306
6f4f49b2 14307 attr = *ain->attr;
f99def61
AD
14308 route_filtered = false;
14309
14310 /* Filter prefix using distribute list,
14311 * filter list or prefix list
14312 */
b54892e0 14313 const struct prefix *rn_p =
9bcb3eef 14314 bgp_dest_get_prefix(dest);
b54892e0
DS
14315 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14316 safi))
14317 == FILTER_DENY)
f99def61
AD
14318 route_filtered = true;
14319
14320 /* Filter prefix using route-map */
b54892e0
DS
14321 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14322 safi, rmap_name, NULL,
14323 0, NULL);
6392aaa6 14324
13c8e163
AD
14325 if (type == bgp_show_adj_route_filtered &&
14326 !route_filtered && ret != RMAP_DENY) {
d498917e 14327 bgp_attr_flush(&attr);
6392aaa6 14328 continue;
d62a17ae 14329 }
6392aaa6 14330
d9478df0
TA
14331 if (type == bgp_show_adj_route_received
14332 && (route_filtered || ret == RMAP_DENY))
14333 (*filtered_count)++;
6392aaa6 14334
e960b4ca
TA
14335 if (detail) {
14336 if (use_json)
14337 json_net =
14338 json_object_new_object();
24dede9b
DS
14339
14340 struct bgp_path_info bpi;
14341 struct bgp_dest buildit = *dest;
14342 struct bgp_dest *pass_in;
14343
14344 if (route_filtered ||
14345 ret == RMAP_DENY) {
14346 bpi.attr = &attr;
14347 bpi.peer = peer;
14348 buildit.info = &bpi;
14349
14350 pass_in = &buildit;
14351 } else
14352 pass_in = dest;
e960b4ca 14353 bgp_show_path_info(
24dede9b
DS
14354 NULL, pass_in, vty, bgp, afi,
14355 safi, json_net,
e960b4ca
TA
14356 BGP_PATH_SHOW_ALL, &display,
14357 RPKI_NOT_BEING_USED);
14358 if (use_json)
14359 json_object_object_addf(
14360 json_ar, json_net,
14361 "%pFX", rn_p);
14362 } else
14363 route_vty_out_tmp(vty, dest, rn_p,
14364 &attr, safi, use_json,
14365 json_ar, wide);
d498917e 14366 bgp_attr_flush(&attr);
d9478df0 14367 (*output_count)++;
d62a17ae 14368 }
6392aaa6 14369 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14370 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14371 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14372 if (paf->peer != peer || !adj->attr)
924c3f6a 14373 continue;
d62a17ae 14374
e960b4ca
TA
14375 show_adj_route_header(
14376 vty, peer, table, header1,
14377 header2, json, json_scode,
14378 json_ocode, wide, detail);
d62a17ae 14379
b54892e0 14380 const struct prefix *rn_p =
9bcb3eef 14381 bgp_dest_get_prefix(dest);
b54892e0 14382
6f4f49b2 14383 attr = *adj->attr;
b755861b 14384 ret = bgp_output_modifier(
b54892e0 14385 peer, rn_p, &attr, afi, safi,
b755861b 14386 rmap_name);
f46d8e1e 14387
b755861b 14388 if (ret != RMAP_DENY) {
d9478df0
TA
14389 if ((safi == SAFI_MPLS_VPN)
14390 || (safi == SAFI_ENCAP)
14391 || (safi == SAFI_EVPN)) {
14392 if (use_json)
14393 json_object_string_add(
14394 json_ar,
14395 "rd",
14396 rd_str);
14397 else if (show_rd
14398 && rd_str) {
14399 vty_out(vty,
14400 "Route Distinguisher: %s\n",
14401 rd_str);
14402 show_rd = false;
14403 }
14404 }
e960b4ca
TA
14405 if (detail) {
14406 if (use_json)
14407 json_net =
14408 json_object_new_object();
14409 bgp_show_path_info(
14410 NULL /* prefix_rd
14411 */
14412 ,
14413 dest, vty, bgp,
14414 afi, safi,
14415 json_net,
14416 BGP_PATH_SHOW_ALL,
14417 &display,
14418 RPKI_NOT_BEING_USED);
14419 if (use_json)
14420 json_object_object_addf(
14421 json_ar,
14422 json_net,
14423 "%pFX",
14424 rn_p);
14425 } else
14426 route_vty_out_tmp(
14427 vty, dest, rn_p,
14428 &attr, safi,
14429 use_json,
14430 json_ar, wide);
d9478df0 14431 (*output_count)++;
b755861b 14432 } else {
d9478df0 14433 (*filtered_count)++;
a2addae8 14434 }
b755861b 14435
d498917e 14436 bgp_attr_flush(&attr);
924c3f6a 14437 }
f20ce998
DS
14438 } else if (type == bgp_show_adj_route_bestpath) {
14439 struct bgp_path_info *pi;
14440
114fc229
DA
14441 show_adj_route_header(vty, peer, table, header1,
14442 header2, json, json_scode,
e960b4ca 14443 json_ocode, wide, detail);
f20ce998 14444
aa9bf57e
TA
14445 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14446
f20ce998
DS
14447 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14448 pi = pi->next) {
14449 if (pi->peer != peer)
14450 continue;
14451
14452 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14453 continue;
14454
aa9bf57e
TA
14455 if (detail) {
14456 if (use_json)
14457 json_net =
14458 json_object_new_object();
14459 bgp_show_path_info(
14460 NULL /* prefix_rd */, dest, vty,
14461 bgp, afi, safi, json_net,
14462 BGP_PATH_SHOW_BESTPATH,
14463 &display, RPKI_NOT_BEING_USED);
14464 if (use_json)
14465 json_object_object_addf(
14466 json_ar, json_net,
14467 "%pFX", rn_p);
14468 } else
14469 route_vty_out_tmp(
14470 vty, dest, rn_p, pi->attr, safi,
14471 use_json, json_ar, wide);
d9478df0 14472 (*output_count)++;
f20ce998 14473 }
d62a17ae 14474 }
14475 }
a636c635 14476}
2a71e9ce 14477
d62a17ae 14478static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14479 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14480 const char *rmap_name, const struct prefix *match,
14481 uint16_t show_flags)
0b16f239 14482{
d9478df0
TA
14483 struct bgp *bgp;
14484 struct bgp_table *table;
d62a17ae 14485 json_object *json = NULL;
d9478df0
TA
14486 json_object *json_scode = NULL;
14487 json_object *json_ocode = NULL;
14488 json_object *json_ar = NULL;
96f3485c 14489 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14490
d9478df0
TA
14491 /* Init BGP headers here so they're only displayed once
14492 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14493 */
14494 int header1 = 1;
14495 int header2 = 1;
14496
14497 /*
14498 * Initialize variables for each RD
14499 * All prefixes under an RD is aggregated within "json_routes"
14500 */
14501 char rd_str[BUFSIZ] = {0};
14502 json_object *json_routes = NULL;
14503
14504
14505 /* For 2-tier tables, prefix counts need to be
14506 * maintained across multiple runs of show_adj_route()
14507 */
14508 unsigned long output_count_per_rd;
14509 unsigned long filtered_count_per_rd;
14510 unsigned long output_count = 0;
14511 unsigned long filtered_count = 0;
14512
14513 if (use_json) {
d62a17ae 14514 json = json_object_new_object();
d9478df0
TA
14515 json_ar = json_object_new_object();
14516 json_scode = json_object_new_object();
14517 json_ocode = json_object_new_object();
dd426a51
DA
14518#if CONFDATE > 20231208
14519CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14520#endif
d9478df0
TA
14521 json_object_string_add(json_scode, "suppressed", "s");
14522 json_object_string_add(json_scode, "damped", "d");
14523 json_object_string_add(json_scode, "history", "h");
14524 json_object_string_add(json_scode, "valid", "*");
14525 json_object_string_add(json_scode, "best", ">");
14526 json_object_string_add(json_scode, "multipath", "=");
14527 json_object_string_add(json_scode, "internal", "i");
14528 json_object_string_add(json_scode, "ribFailure", "r");
14529 json_object_string_add(json_scode, "stale", "S");
14530 json_object_string_add(json_scode, "removed", "R");
14531
dd426a51
DA
14532#if CONFDATE > 20231208
14533CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14534#endif
d9478df0
TA
14535 json_object_string_add(json_ocode, "igp", "i");
14536 json_object_string_add(json_ocode, "egp", "e");
14537 json_object_string_add(json_ocode, "incomplete", "?");
14538 }
0b16f239 14539
d62a17ae 14540 if (!peer || !peer->afc[afi][safi]) {
14541 if (use_json) {
14542 json_object_string_add(
14543 json, "warning",
14544 "No such neighbor or address family");
14545 vty_out(vty, "%s\n", json_object_to_json_string(json));
14546 json_object_free(json);
690c3134
MW
14547 json_object_free(json_ar);
14548 json_object_free(json_scode);
14549 json_object_free(json_ocode);
d62a17ae 14550 } else
14551 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14552
d62a17ae 14553 return CMD_WARNING;
14554 }
14555
6392aaa6
PM
14556 if ((type == bgp_show_adj_route_received
14557 || type == bgp_show_adj_route_filtered)
d62a17ae 14558 && !CHECK_FLAG(peer->af_flags[afi][safi],
14559 PEER_FLAG_SOFT_RECONFIG)) {
14560 if (use_json) {
14561 json_object_string_add(
14562 json, "warning",
14563 "Inbound soft reconfiguration not enabled");
14564 vty_out(vty, "%s\n", json_object_to_json_string(json));
14565 json_object_free(json);
690c3134
MW
14566 json_object_free(json_ar);
14567 json_object_free(json_scode);
14568 json_object_free(json_ocode);
d62a17ae 14569 } else
14570 vty_out(vty,
14571 "%% Inbound soft reconfiguration not enabled\n");
14572
14573 return CMD_WARNING;
14574 }
0b16f239 14575
d9478df0
TA
14576 bgp = peer->bgp;
14577
14578 /* labeled-unicast routes live in the unicast table */
14579 if (safi == SAFI_LABELED_UNICAST)
14580 table = bgp->rib[afi][SAFI_UNICAST];
14581 else
14582 table = bgp->rib[afi][safi];
14583
14584 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14585 || (safi == SAFI_EVPN)) {
14586
14587 struct bgp_dest *dest;
14588
14589 for (dest = bgp_table_top(table); dest;
14590 dest = bgp_route_next(dest)) {
14591 table = bgp_dest_get_bgp_table_info(dest);
14592 if (!table)
14593 continue;
14594
14595 output_count_per_rd = 0;
14596 filtered_count_per_rd = 0;
14597
14598 if (use_json)
14599 json_routes = json_object_new_object();
14600
14601 const struct prefix_rd *prd;
14602 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14603 dest);
14604
4a8cd6ad
PG
14605 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14606 bgp->asnotation);
d9478df0 14607
3880b4ec
TA
14608 show_adj_route(
14609 vty, peer, table, afi, safi, type, rmap_name,
14610 json, json_routes, json_scode, json_ocode,
14611 show_flags, &header1, &header2, rd_str, match,
14612 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14613
14614 /* Don't include an empty RD in the output! */
14615 if (json_routes && (output_count_per_rd > 0))
14616 json_object_object_add(json_ar, rd_str,
14617 json_routes);
14618
14619 output_count += output_count_per_rd;
14620 filtered_count += filtered_count_per_rd;
14621 }
14622 } else
14623 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14624 json, json_ar, json_scode, json_ocode,
3880b4ec 14625 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14626 &output_count, &filtered_count);
14627
14628 if (use_json) {
c1984955
TA
14629 if (type == bgp_show_adj_route_advertised)
14630 json_object_object_add(json, "advertisedRoutes",
14631 json_ar);
14632 else
14633 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14634 json_object_int_add(json, "totalPrefixCounter", output_count);
14635 json_object_int_add(json, "filteredPrefixCounter",
14636 filtered_count);
14637
690c3134
MW
14638 /*
14639 * These fields only give up ownership to `json` when `header1`
14640 * is used (set to zero). See code in `show_adj_route` and
14641 * `show_adj_route_header`.
14642 */
14643 if (header1 == 1) {
d9478df0
TA
14644 json_object_free(json_scode);
14645 json_object_free(json_ocode);
14646 }
14647
75eeda93 14648 vty_json(vty, json);
d9478df0 14649 } else if (output_count > 0) {
3880b4ec 14650 if (!match && filtered_count > 0)
d9478df0
TA
14651 vty_out(vty,
14652 "\nTotal number of prefixes %ld (%ld filtered)\n",
14653 output_count, filtered_count);
14654 else
14655 vty_out(vty, "\nTotal number of prefixes %ld\n",
14656 output_count);
14657 }
0b16f239 14658
d62a17ae 14659 return CMD_SUCCESS;
a636c635 14660}
50ef26d4 14661
f20ce998
DS
14662DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14663 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14664 "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
14665 SHOW_STR
14666 IP_STR
14667 BGP_STR
14668 BGP_INSTANCE_HELP_STR
14669 BGP_AFI_HELP_STR
14670 BGP_SAFI_WITH_LABEL_HELP_STR
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 selected by best path\n"
aa9bf57e 14676 "Display detailed version of routes\n"
f20ce998
DS
14677 JSON_STR
14678 "Increase table width for longer prefixes\n")
14679{
14680 afi_t afi = AFI_IP6;
14681 safi_t safi = SAFI_UNICAST;
14682 char *rmap_name = NULL;
14683 char *peerstr = NULL;
14684 struct bgp *bgp = NULL;
14685 struct peer *peer;
14686 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14687 int idx = 0;
96c81f66 14688 uint16_t show_flags = 0;
96f3485c 14689
aa9bf57e
TA
14690 if (detail)
14691 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14692
96f3485c
MK
14693 if (uj)
14694 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14695
14696 if (wide)
14697 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14698
14699 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14700 &bgp, uj);
14701
14702 if (!idx)
14703 return CMD_WARNING;
14704
14705 argv_find(argv, argc, "neighbors", &idx);
14706 peerstr = argv[++idx]->arg;
14707
14708 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14709 if (!peer)
14710 return CMD_WARNING;
14711
3880b4ec 14712 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14713 show_flags);
f20ce998
DS
14714}
14715
e960b4ca
TA
14716DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14717 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14718 "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
14719 SHOW_STR
14720 IP_STR
14721 BGP_STR
14722 BGP_INSTANCE_HELP_STR
14723 BGP_AFI_HELP_STR
14724 BGP_SAFI_WITH_LABEL_HELP_STR
14725 "Display the entries for all address families\n"
14726 "Detailed information on TCP and BGP neighbor connections\n"
14727 "Neighbor to display information about\n"
14728 "Neighbor to display information about\n"
14729 "Neighbor on BGP configured interface\n"
14730 "Display the routes advertised to a BGP neighbor\n"
14731 "Display the received routes from neighbor\n"
14732 "Display the filtered routes received from neighbor\n"
14733 "Route-map to modify the attributes\n"
14734 "Name of the route map\n"
3880b4ec
TA
14735 "IPv4 prefix\n"
14736 "IPv6 prefix\n"
e960b4ca
TA
14737 "Display detailed version of routes\n"
14738 JSON_STR
14739 "Increase table width for longer prefixes\n")
718e3744 14740{
d62a17ae 14741 afi_t afi = AFI_IP6;
14742 safi_t safi = SAFI_UNICAST;
d62a17ae 14743 char *peerstr = NULL;
d62a17ae 14744 struct bgp *bgp = NULL;
14745 struct peer *peer;
6392aaa6 14746 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14747 int idx = 0;
96f3485c 14748 bool first = true;
96c81f66 14749 uint16_t show_flags = 0;
75ce3b14
DA
14750 struct listnode *node;
14751 struct bgp *abgp;
6392aaa6 14752
3880b4ec 14753 if (detail || prefix_str)
e960b4ca
TA
14754 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14755
96f3485c 14756 if (uj) {
d62a17ae 14757 argc--;
96f3485c
MK
14758 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14759 }
14760
14761 if (all) {
14762 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14763 if (argv_find(argv, argc, "ipv4", &idx))
14764 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14765
14766 if (argv_find(argv, argc, "ipv6", &idx))
14767 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14768 }
14769
14770 if (wide)
14771 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14772
9f049418
DS
14773 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14774 &bgp, uj);
14775 if (!idx)
14776 return CMD_WARNING;
14777
d62a17ae 14778 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14779 argv_find(argv, argc, "neighbors", &idx);
14780 peerstr = argv[++idx]->arg;
8c3deaae 14781
d62a17ae 14782 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14783 if (!peer)
14784 return CMD_WARNING;
856ca177 14785
d62a17ae 14786 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14787 type = bgp_show_adj_route_advertised;
14788 else if (argv_find(argv, argc, "received-routes", &idx))
14789 type = bgp_show_adj_route_received;
14790 else if (argv_find(argv, argc, "filtered-routes", &idx))
14791 type = bgp_show_adj_route_filtered;
14792
96f3485c 14793 if (!all)
70dd370f 14794 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14795 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14796 if (uj)
14797 vty_out(vty, "{\n");
14798
14799 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14800 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14801 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14802 : AFI_IP6;
75ce3b14
DA
14803 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14804 FOREACH_SAFI (safi) {
14805 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14806 continue;
96f3485c 14807
75ce3b14
DA
14808 if (uj) {
14809 if (first)
14810 first = false;
14811 else
14812 vty_out(vty, ",\n");
14813 vty_out(vty, "\"%s\":",
14814 get_afi_safi_str(afi, safi,
14815 true));
14816 } else
14817 vty_out(vty,
14818 "\nFor address family: %s\n",
14819 get_afi_safi_str(afi, safi,
14820 false));
96f3485c 14821
75ce3b14 14822 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14823 route_map, prefix, show_flags);
75ce3b14 14824 }
96f3485c
MK
14825 }
14826 } else {
75ce3b14
DA
14827 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14828 FOREACH_AFI_SAFI (afi, safi) {
14829 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14830 continue;
96f3485c 14831
75ce3b14
DA
14832 if (uj) {
14833 if (first)
14834 first = false;
14835 else
14836 vty_out(vty, ",\n");
14837 vty_out(vty, "\"%s\":",
14838 get_afi_safi_str(afi, safi,
14839 true));
14840 } else
14841 vty_out(vty,
14842 "\nFor address family: %s\n",
14843 get_afi_safi_str(afi, safi,
14844 false));
96f3485c 14845
75ce3b14 14846 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14847 route_map, prefix, show_flags);
75ce3b14 14848 }
96f3485c
MK
14849 }
14850 }
14851 if (uj)
14852 vty_out(vty, "}\n");
14853
14854 return CMD_SUCCESS;
95cbbd2a
ML
14855}
14856
718e3744 14857DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14858 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14859 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14860 SHOW_STR
14861 IP_STR
14862 BGP_STR
d3120452 14863 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14864 BGP_AF_STR
14865 BGP_AF_STR
14866 BGP_AF_MODIFIER_STR
718e3744 14867 "Detailed information on TCP and BGP neighbor connections\n"
14868 "Neighbor to display information about\n"
14869 "Neighbor to display information about\n"
91d37724 14870 "Neighbor on BGP configured interface\n"
718e3744 14871 "Display information received from a BGP neighbor\n"
856ca177 14872 "Display the prefixlist filter\n"
9973d184 14873 JSON_STR)
718e3744 14874{
d62a17ae 14875 afi_t afi = AFI_IP6;
14876 safi_t safi = SAFI_UNICAST;
14877 char *peerstr = NULL;
d62a17ae 14878 char name[BUFSIZ];
d62a17ae 14879 struct peer *peer;
d3120452 14880 int count;
d62a17ae 14881 int idx = 0;
d3120452
IR
14882 struct bgp *bgp = NULL;
14883 bool uj = use_json(argc, argv);
14884
14885 if (uj)
14886 argc--;
14887
14888 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14889 &bgp, uj);
14890 if (!idx)
14891 return CMD_WARNING;
d62a17ae 14892
d62a17ae 14893 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14894 argv_find(argv, argc, "neighbors", &idx);
14895 peerstr = argv[++idx]->arg;
14896
d3120452
IR
14897 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14898 if (!peer)
14899 return CMD_WARNING;
718e3744 14900
4ced1a2c 14901 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14902 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14903 if (count) {
14904 if (!uj)
14905 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14906 get_afi_safi_str(afi, safi, false));
d62a17ae 14907 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14908 } else {
14909 if (uj)
14910 vty_out(vty, "{}\n");
14911 else
14912 vty_out(vty, "No functional output\n");
14913 }
718e3744 14914
d62a17ae 14915 return CMD_SUCCESS;
14916}
14917
14918static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14919 afi_t afi, safi_t safi,
9f049418 14920 enum bgp_show_type type, bool use_json)
d62a17ae 14921{
96c81f66 14922 uint16_t show_flags = 0;
96f3485c
MK
14923
14924 if (use_json)
14925 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14926
d62a17ae 14927 if (!peer || !peer->afc[afi][safi]) {
14928 if (use_json) {
14929 json_object *json_no = NULL;
14930 json_no = json_object_new_object();
14931 json_object_string_add(
14932 json_no, "warning",
14933 "No such neighbor or address family");
14934 vty_out(vty, "%s\n",
14935 json_object_to_json_string(json_no));
14936 json_object_free(json_no);
14937 } else
14938 vty_out(vty, "%% No such neighbor or address family\n");
14939 return CMD_WARNING;
14940 }
47fc97cc 14941
7daf25a3
TA
14942 /* labeled-unicast routes live in the unicast table */
14943 if (safi == SAFI_LABELED_UNICAST)
14944 safi = SAFI_UNICAST;
14945
1e2ce4f1
DS
14946 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14947 RPKI_NOT_BEING_USED);
718e3744 14948}
14949
795bef98
RR
14950/*
14951 * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
14952 * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
14953 */
14954DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed,
14955 show_ip_bgp_vrf_afi_safi_routes_detailed_cmd,
14956 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] detail [json$uj]",
14957 SHOW_STR
14958 IP_STR
14959 BGP_STR
14960 BGP_INSTANCE_HELP_STR
14961 BGP_AFI_HELP_STR
14962 BGP_SAFI_WITH_LABEL_HELP_STR
14963 "Detailed information\n"
14964 JSON_STR)
dba3c1d3 14965{
458c1475 14966 afi_t afi = AFI_IP6;
dba3c1d3
PG
14967 safi_t safi = SAFI_UNICAST;
14968 struct bgp *bgp = NULL;
14969 int idx = 0;
81dcd881 14970 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14971
795bef98 14972 if (uj)
96f3485c 14973 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
dba3c1d3
PG
14974
14975 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14976 &bgp, uj);
dba3c1d3
PG
14977 if (!idx)
14978 return CMD_WARNING;
795bef98
RR
14979 /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
14980 if (vrf_name && strmatch(vrf_name, "all")) {
14981 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
14982 return CMD_SUCCESS;
14983 }
dba3c1d3 14984
795bef98 14985 /* All other cases except vrf all */
96f3485c 14986 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14987 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14988}
14989
718e3744 14990DEFUN (show_ip_bgp_neighbor_routes,
14991 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14992 "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 14993 SHOW_STR
14994 IP_STR
14995 BGP_STR
8386ac43 14996 BGP_INSTANCE_HELP_STR
4f280b15 14997 BGP_AFI_HELP_STR
4dd6177e 14998 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14999 "Detailed information on TCP and BGP neighbor connections\n"
15000 "Neighbor to display information about\n"
15001 "Neighbor to display information about\n"
91d37724 15002 "Neighbor on BGP configured interface\n"
2525cf39 15003 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
15004 "Display the dampened routes received from neighbor\n"
15005 "Display routes learned from neighbor\n"
9973d184 15006 JSON_STR)
718e3744 15007{
d62a17ae 15008 char *peerstr = NULL;
15009 struct bgp *bgp = NULL;
15010 afi_t afi = AFI_IP6;
15011 safi_t safi = SAFI_UNICAST;
15012 struct peer *peer;
15013 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 15014 int idx = 0;
9f049418
DS
15015 bool uj = use_json(argc, argv);
15016
15017 if (uj)
15018 argc--;
bb46e94f 15019
d62a17ae 15020 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 15021 &bgp, uj);
d62a17ae 15022 if (!idx)
15023 return CMD_WARNING;
c493f2d8 15024
d62a17ae 15025 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
15026 argv_find(argv, argc, "neighbors", &idx);
15027 peerstr = argv[++idx]->arg;
8c3deaae 15028
d62a17ae 15029 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 15030 if (!peer)
d62a17ae 15031 return CMD_WARNING;
bb46e94f 15032
d62a17ae 15033 if (argv_find(argv, argc, "flap-statistics", &idx))
15034 sh_type = bgp_show_type_flap_neighbor;
15035 else if (argv_find(argv, argc, "dampened-routes", &idx))
15036 sh_type = bgp_show_type_damp_neighbor;
15037 else if (argv_find(argv, argc, "routes", &idx))
15038 sh_type = bgp_show_type_neighbor;
2525cf39 15039
d62a17ae 15040 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 15041}
6b0655a2 15042
734b349e 15043struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 15044
d62a17ae 15045struct bgp_distance {
15046 /* Distance value for the IP source prefix. */
d7c0a89a 15047 uint8_t distance;
718e3744 15048
d62a17ae 15049 /* Name of the access-list to be matched. */
15050 char *access_list;
718e3744 15051};
15052
4f280b15
LB
15053DEFUN (show_bgp_afi_vpn_rd_route,
15054 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 15055 "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
15056 SHOW_STR
15057 BGP_STR
15058 BGP_AFI_HELP_STR
00e6edb9 15059 BGP_AF_MODIFIER_STR
4f280b15
LB
15060 "Display information for a route distinguisher\n"
15061 "Route Distinguisher\n"
a111dd97 15062 "All Route Distinguishers\n"
7395a2c9
DS
15063 "Network in the BGP routing table to display\n"
15064 "Network in the BGP routing table to display\n"
15065 JSON_STR)
4f280b15 15066{
d62a17ae 15067 int ret;
15068 struct prefix_rd prd;
15069 afi_t afi = AFI_MAX;
15070 int idx = 0;
4f280b15 15071
ff6566f3
DS
15072 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
15073 vty_out(vty, "%% Malformed Address Family\n");
15074 return CMD_WARNING;
15075 }
15076
a111dd97
TA
15077 if (!strcmp(argv[5]->arg, "all"))
15078 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
15079 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
15080 RPKI_NOT_BEING_USED,
15081 use_json(argc, argv));
15082
d62a17ae 15083 ret = str2prefix_rd(argv[5]->arg, &prd);
15084 if (!ret) {
15085 vty_out(vty, "%% Malformed Route Distinguisher\n");
15086 return CMD_WARNING;
15087 }
ff6566f3 15088
d62a17ae 15089 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
15090 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
15091 use_json(argc, argv));
4f280b15
LB
15092}
15093
d62a17ae 15094static struct bgp_distance *bgp_distance_new(void)
718e3744 15095{
d62a17ae 15096 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 15097}
15098
d62a17ae 15099static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 15100{
d62a17ae 15101 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 15102}
15103
585f1adc
IR
15104static int bgp_distance_set(struct vty *vty, const char *distance_str,
15105 const char *ip_str, const char *access_list_str)
718e3744 15106{
d62a17ae 15107 int ret;
585f1adc
IR
15108 afi_t afi;
15109 safi_t safi;
d62a17ae 15110 struct prefix p;
585f1adc 15111 uint8_t distance;
9bcb3eef 15112 struct bgp_dest *dest;
d62a17ae 15113 struct bgp_distance *bdistance;
718e3744 15114
585f1adc
IR
15115 afi = bgp_node_afi(vty);
15116 safi = bgp_node_safi(vty);
15117
d62a17ae 15118 ret = str2prefix(ip_str, &p);
15119 if (ret == 0) {
585f1adc 15120 vty_out(vty, "Malformed prefix\n");
d62a17ae 15121 return CMD_WARNING_CONFIG_FAILED;
15122 }
718e3744 15123
585f1adc
IR
15124 distance = atoi(distance_str);
15125
d62a17ae 15126 /* Get BGP distance node. */
9bcb3eef
DS
15127 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
15128 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 15129 if (bdistance)
9bcb3eef 15130 bgp_dest_unlock_node(dest);
ca2e160d 15131 else {
d62a17ae 15132 bdistance = bgp_distance_new();
9bcb3eef 15133 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15134 }
718e3744 15135
d62a17ae 15136 /* Set distance value. */
15137 bdistance->distance = distance;
718e3744 15138
d62a17ae 15139 /* Reset access-list configuration. */
e1b36e13 15140 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15141 if (access_list_str)
15142 bdistance->access_list =
15143 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15144
d62a17ae 15145 return CMD_SUCCESS;
718e3744 15146}
15147
585f1adc
IR
15148static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15149 const char *ip_str, const char *access_list_str)
718e3744 15150{
d62a17ae 15151 int ret;
585f1adc
IR
15152 afi_t afi;
15153 safi_t safi;
d62a17ae 15154 struct prefix p;
585f1adc 15155 int distance;
9bcb3eef 15156 struct bgp_dest *dest;
d62a17ae 15157 struct bgp_distance *bdistance;
718e3744 15158
585f1adc
IR
15159 afi = bgp_node_afi(vty);
15160 safi = bgp_node_safi(vty);
15161
d62a17ae 15162 ret = str2prefix(ip_str, &p);
15163 if (ret == 0) {
585f1adc 15164 vty_out(vty, "Malformed prefix\n");
d62a17ae 15165 return CMD_WARNING_CONFIG_FAILED;
15166 }
718e3744 15167
9bcb3eef
DS
15168 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15169 if (!dest) {
585f1adc 15170 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15171 return CMD_WARNING_CONFIG_FAILED;
15172 }
718e3744 15173
9bcb3eef 15174 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15175 distance = atoi(distance_str);
1f9a9fff 15176
d62a17ae 15177 if (bdistance->distance != distance) {
585f1adc 15178 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15179 bgp_dest_unlock_node(dest);
d62a17ae 15180 return CMD_WARNING_CONFIG_FAILED;
15181 }
718e3744 15182
0a22ddfb 15183 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15184 bgp_distance_free(bdistance);
718e3744 15185
9bcb3eef
DS
15186 bgp_dest_set_bgp_path_info(dest, NULL);
15187 bgp_dest_unlock_node(dest);
15188 bgp_dest_unlock_node(dest);
718e3744 15189
d62a17ae 15190 return CMD_SUCCESS;
718e3744 15191}
15192
718e3744 15193/* Apply BGP information to distance method. */
b8685f9b 15194uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15195 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15196{
9bcb3eef 15197 struct bgp_dest *dest;
801bb996 15198 struct prefix q = {0};
d62a17ae 15199 struct peer *peer;
15200 struct bgp_distance *bdistance;
15201 struct access_list *alist;
15202 struct bgp_static *bgp_static;
a04f1c42 15203 struct bgp_path_info *bpi_ultimate;
d62a17ae 15204
15205 if (!bgp)
15206 return 0;
15207
40381db7 15208 peer = pinfo->peer;
d62a17ae 15209
7b7d48e5
DS
15210 if (pinfo->attr->distance)
15211 return pinfo->attr->distance;
15212
a04f1c42
PG
15213 /* get peer origin to calculate appropriate distance */
15214 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15215 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15216 peer = bpi_ultimate->peer;
15217 }
15218
801bb996
CS
15219 /* Check source address.
15220 * Note: for aggregate route, peer can have unspec af type.
15221 */
15222 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15223 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15224 return 0;
15225
9bcb3eef
DS
15226 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15227 if (dest) {
15228 bdistance = bgp_dest_get_bgp_distance_info(dest);
15229 bgp_dest_unlock_node(dest);
d62a17ae 15230
15231 if (bdistance->access_list) {
15232 alist = access_list_lookup(afi, bdistance->access_list);
15233 if (alist
15234 && access_list_apply(alist, p) == FILTER_PERMIT)
15235 return bdistance->distance;
15236 } else
15237 return bdistance->distance;
718e3744 15238 }
718e3744 15239
d62a17ae 15240 /* Backdoor check. */
9bcb3eef
DS
15241 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15242 if (dest) {
15243 bgp_static = bgp_dest_get_bgp_static_info(dest);
15244 bgp_dest_unlock_node(dest);
718e3744 15245
d62a17ae 15246 if (bgp_static->backdoor) {
15247 if (bgp->distance_local[afi][safi])
15248 return bgp->distance_local[afi][safi];
15249 else
15250 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15251 }
718e3744 15252 }
718e3744 15253
d62a17ae 15254 if (peer->sort == BGP_PEER_EBGP) {
15255 if (bgp->distance_ebgp[afi][safi])
15256 return bgp->distance_ebgp[afi][safi];
15257 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15258 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15259 if (bgp->distance_ibgp[afi][safi])
15260 return bgp->distance_ibgp[afi][safi];
15261 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15262 } else {
15263 if (bgp->distance_local[afi][safi])
15264 return bgp->distance_local[afi][safi];
15265 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15266 }
718e3744 15267}
15268
a612fb77
DA
15269/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15270 * we should tell ZEBRA update the routes for a specific
15271 * AFI/SAFI to reflect changes in RIB.
15272 */
585f1adc
IR
15273static void bgp_announce_routes_distance_update(struct bgp *bgp,
15274 afi_t update_afi,
15275 safi_t update_safi)
a612fb77
DA
15276{
15277 afi_t afi;
15278 safi_t safi;
15279
15280 FOREACH_AFI_SAFI (afi, safi) {
15281 if (!bgp_fibupd_safi(safi))
15282 continue;
15283
8b54bc30
DA
15284 if (afi != update_afi && safi != update_safi)
15285 continue;
15286
15287 if (BGP_DEBUG(zebra, ZEBRA))
15288 zlog_debug(
15289 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15290 __func__, afi, safi);
15291 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15292 }
15293}
15294
585f1adc
IR
15295DEFUN (bgp_distance,
15296 bgp_distance_cmd,
15297 "distance bgp (1-255) (1-255) (1-255)",
15298 "Define an administrative distance\n"
15299 "BGP distance\n"
15300 "Distance for routes external to the AS\n"
15301 "Distance for routes internal to the AS\n"
15302 "Distance for local routes\n")
718e3744 15303{
585f1adc 15304 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15305 int idx_number = 2;
15306 int idx_number_2 = 3;
15307 int idx_number_3 = 4;
585f1adc
IR
15308 int distance_ebgp = atoi(argv[idx_number]->arg);
15309 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15310 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15311 afi_t afi;
15312 safi_t safi;
718e3744 15313
d62a17ae 15314 afi = bgp_node_afi(vty);
15315 safi = bgp_node_safi(vty);
718e3744 15316
585f1adc
IR
15317 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15318 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15319 || bgp->distance_local[afi][safi] != distance_local) {
15320 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15321 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15322 bgp->distance_local[afi][safi] = distance_local;
15323 bgp_announce_routes_distance_update(bgp, afi, safi);
15324 }
15325 return CMD_SUCCESS;
15326}
37a87b8f 15327
585f1adc
IR
15328DEFUN (no_bgp_distance,
15329 no_bgp_distance_cmd,
15330 "no distance bgp [(1-255) (1-255) (1-255)]",
15331 NO_STR
15332 "Define an administrative distance\n"
15333 "BGP distance\n"
15334 "Distance for routes external to the AS\n"
15335 "Distance for routes internal to the AS\n"
15336 "Distance for local routes\n")
718e3744 15337{
585f1adc 15338 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15339 afi_t afi;
15340 safi_t safi;
37a87b8f
CS
15341
15342 afi = bgp_node_afi(vty);
15343 safi = bgp_node_safi(vty);
15344
585f1adc
IR
15345 if (bgp->distance_ebgp[afi][safi] != 0
15346 || bgp->distance_ibgp[afi][safi] != 0
15347 || bgp->distance_local[afi][safi] != 0) {
15348 bgp->distance_ebgp[afi][safi] = 0;
15349 bgp->distance_ibgp[afi][safi] = 0;
15350 bgp->distance_local[afi][safi] = 0;
15351 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15352 }
585f1adc
IR
15353 return CMD_SUCCESS;
15354}
37a87b8f 15355
37a87b8f 15356
585f1adc
IR
15357DEFUN (bgp_distance_source,
15358 bgp_distance_source_cmd,
15359 "distance (1-255) A.B.C.D/M",
15360 "Define an administrative distance\n"
15361 "Administrative distance\n"
15362 "IP source prefix\n")
15363{
15364 int idx_number = 1;
15365 int idx_ipv4_prefixlen = 2;
15366 bgp_distance_set(vty, argv[idx_number]->arg,
15367 argv[idx_ipv4_prefixlen]->arg, NULL);
15368 return CMD_SUCCESS;
734b349e
MZ
15369}
15370
585f1adc
IR
15371DEFUN (no_bgp_distance_source,
15372 no_bgp_distance_source_cmd,
15373 "no distance (1-255) A.B.C.D/M",
15374 NO_STR
15375 "Define an administrative distance\n"
15376 "Administrative distance\n"
15377 "IP source prefix\n")
37a87b8f 15378{
585f1adc
IR
15379 int idx_number = 2;
15380 int idx_ipv4_prefixlen = 3;
15381 bgp_distance_unset(vty, argv[idx_number]->arg,
15382 argv[idx_ipv4_prefixlen]->arg, NULL);
15383 return CMD_SUCCESS;
37a87b8f
CS
15384}
15385
585f1adc
IR
15386DEFUN (bgp_distance_source_access_list,
15387 bgp_distance_source_access_list_cmd,
15388 "distance (1-255) A.B.C.D/M WORD",
15389 "Define an administrative distance\n"
15390 "Administrative distance\n"
15391 "IP source prefix\n"
15392 "Access list name\n")
37a87b8f 15393{
585f1adc
IR
15394 int idx_number = 1;
15395 int idx_ipv4_prefixlen = 2;
15396 int idx_word = 3;
15397 bgp_distance_set(vty, argv[idx_number]->arg,
15398 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15399 return CMD_SUCCESS;
15400}
718e3744 15401
585f1adc
IR
15402DEFUN (no_bgp_distance_source_access_list,
15403 no_bgp_distance_source_access_list_cmd,
15404 "no distance (1-255) A.B.C.D/M WORD",
15405 NO_STR
15406 "Define an administrative distance\n"
15407 "Administrative distance\n"
15408 "IP source prefix\n"
15409 "Access list name\n")
15410{
15411 int idx_number = 2;
15412 int idx_ipv4_prefixlen = 3;
15413 int idx_word = 4;
15414 bgp_distance_unset(vty, argv[idx_number]->arg,
15415 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15416 return CMD_SUCCESS;
15417}
37a87b8f 15418
585f1adc
IR
15419DEFUN (ipv6_bgp_distance_source,
15420 ipv6_bgp_distance_source_cmd,
15421 "distance (1-255) X:X::X:X/M",
15422 "Define an administrative distance\n"
15423 "Administrative distance\n"
15424 "IP source prefix\n")
15425{
15426 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15427 return CMD_SUCCESS;
15428}
7ebe9748 15429
585f1adc
IR
15430DEFUN (no_ipv6_bgp_distance_source,
15431 no_ipv6_bgp_distance_source_cmd,
15432 "no distance (1-255) X:X::X:X/M",
15433 NO_STR
15434 "Define an administrative distance\n"
15435 "Administrative distance\n"
15436 "IP source prefix\n")
15437{
15438 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15439 return CMD_SUCCESS;
15440}
37a87b8f 15441
585f1adc
IR
15442DEFUN (ipv6_bgp_distance_source_access_list,
15443 ipv6_bgp_distance_source_access_list_cmd,
15444 "distance (1-255) X:X::X:X/M WORD",
15445 "Define an administrative distance\n"
15446 "Administrative distance\n"
15447 "IP source prefix\n"
15448 "Access list name\n")
15449{
15450 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15451 return CMD_SUCCESS;
718e3744 15452}
15453
585f1adc
IR
15454DEFUN (no_ipv6_bgp_distance_source_access_list,
15455 no_ipv6_bgp_distance_source_access_list_cmd,
15456 "no distance (1-255) X:X::X:X/M WORD",
15457 NO_STR
15458 "Define an administrative distance\n"
15459 "Administrative distance\n"
15460 "IP source prefix\n"
15461 "Access list name\n")
718e3744 15462{
585f1adc
IR
15463 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15464 return CMD_SUCCESS;
15465}
37a87b8f 15466
585f1adc
IR
15467DEFUN (bgp_damp_set,
15468 bgp_damp_set_cmd,
a30fec23 15469 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15470 "BGP Specific commands\n"
15471 "Enable route-flap dampening\n"
15472 "Half-life time for the penalty\n"
15473 "Value to start reusing a route\n"
15474 "Value to start suppressing a route\n"
15475 "Maximum duration to suppress a stable route\n")
15476{
15477 VTY_DECLVAR_CONTEXT(bgp, bgp);
15478 int idx_half_life = 2;
15479 int idx_reuse = 3;
15480 int idx_suppress = 4;
15481 int idx_max_suppress = 5;
37a87b8f
CS
15482 int half = DEFAULT_HALF_LIFE * 60;
15483 int reuse = DEFAULT_REUSE;
15484 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15485 int max = 4 * half;
15486
15487 if (argc == 6) {
15488 half = atoi(argv[idx_half_life]->arg) * 60;
15489 reuse = atoi(argv[idx_reuse]->arg);
15490 suppress = atoi(argv[idx_suppress]->arg);
15491 max = atoi(argv[idx_max_suppress]->arg) * 60;
15492 } else if (argc == 3) {
15493 half = atoi(argv[idx_half_life]->arg) * 60;
15494 max = 4 * half;
15495 }
15496
15497 /*
15498 * These can't be 0 but our SA doesn't understand the
15499 * way our cli is constructed
15500 */
15501 assert(reuse);
15502 assert(half);
15503 if (suppress < reuse) {
15504 vty_out(vty,
15505 "Suppress value cannot be less than reuse value \n");
15506 return 0;
15507 }
15508
15509 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15510 reuse, suppress, max);
15511}
15512
15513DEFUN (bgp_damp_unset,
15514 bgp_damp_unset_cmd,
a30fec23 15515 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15516 NO_STR
15517 "BGP Specific commands\n"
15518 "Enable route-flap dampening\n"
15519 "Half-life time for the penalty\n"
15520 "Value to start reusing a route\n"
15521 "Value to start suppressing a route\n"
15522 "Maximum duration to suppress a stable route\n")
15523{
15524 VTY_DECLVAR_CONTEXT(bgp, bgp);
15525 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15526}
15527
718e3744 15528/* Display specified route of BGP table. */
d62a17ae 15529static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15530 const char *ip_str, afi_t afi, safi_t safi,
15531 struct prefix_rd *prd, int prefix_check)
15532{
15533 int ret;
15534 struct prefix match;
9bcb3eef
DS
15535 struct bgp_dest *dest;
15536 struct bgp_dest *rm;
40381db7
DS
15537 struct bgp_path_info *pi;
15538 struct bgp_path_info *pi_temp;
d62a17ae 15539 struct bgp *bgp;
15540 struct bgp_table *table;
15541
15542 /* BGP structure lookup. */
15543 if (view_name) {
15544 bgp = bgp_lookup_by_name(view_name);
15545 if (bgp == NULL) {
15546 vty_out(vty, "%% Can't find BGP instance %s\n",
15547 view_name);
15548 return CMD_WARNING;
15549 }
15550 } else {
15551 bgp = bgp_get_default();
15552 if (bgp == NULL) {
15553 vty_out(vty, "%% No BGP process is configured\n");
15554 return CMD_WARNING;
15555 }
718e3744 15556 }
718e3744 15557
d62a17ae 15558 /* Check IP address argument. */
15559 ret = str2prefix(ip_str, &match);
15560 if (!ret) {
15561 vty_out(vty, "%% address is malformed\n");
15562 return CMD_WARNING;
15563 }
718e3744 15564
d62a17ae 15565 match.family = afi2family(afi);
15566
15567 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15568 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15569 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15570 dest = bgp_route_next(dest)) {
15571 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15572
9bcb3eef 15573 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15574 continue;
9bcb3eef 15575 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15576 if (!table)
ea47320b 15577 continue;
4953391b
DA
15578 rm = bgp_node_match(table, &match);
15579 if (rm == NULL)
ea47320b 15580 continue;
d62a17ae 15581
9bcb3eef 15582 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15583
ea47320b 15584 if (!prefix_check
b54892e0 15585 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15586 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15587 while (pi) {
15588 if (pi->extra && pi->extra->damp_info) {
15589 pi_temp = pi->next;
ea47320b 15590 bgp_damp_info_free(
19971c9a 15591 pi->extra->damp_info,
5c8846f6 15592 1, afi, safi);
40381db7 15593 pi = pi_temp;
ea47320b 15594 } else
40381db7 15595 pi = pi->next;
d62a17ae 15596 }
ea47320b
DL
15597 }
15598
9bcb3eef 15599 bgp_dest_unlock_node(rm);
d62a17ae 15600 }
15601 } else {
4953391b
DA
15602 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15603 if (dest != NULL) {
9bcb3eef 15604 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15605
d62a17ae 15606 if (!prefix_check
9bcb3eef
DS
15607 || dest_p->prefixlen == match.prefixlen) {
15608 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15609 while (pi) {
15610 if (pi->extra && pi->extra->damp_info) {
15611 pi_temp = pi->next;
d62a17ae 15612 bgp_damp_info_free(
19971c9a 15613 pi->extra->damp_info,
5c8846f6 15614 1, afi, safi);
40381db7 15615 pi = pi_temp;
d62a17ae 15616 } else
40381db7 15617 pi = pi->next;
d62a17ae 15618 }
15619 }
15620
9bcb3eef 15621 bgp_dest_unlock_node(dest);
d62a17ae 15622 }
15623 }
718e3744 15624
d62a17ae 15625 return CMD_SUCCESS;
718e3744 15626}
15627
15628DEFUN (clear_ip_bgp_dampening,
15629 clear_ip_bgp_dampening_cmd,
15630 "clear ip bgp dampening",
15631 CLEAR_STR
15632 IP_STR
15633 BGP_STR
15634 "Clear route flap dampening information\n")
15635{
b4f7f45b 15636 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15637 return CMD_SUCCESS;
718e3744 15638}
15639
15640DEFUN (clear_ip_bgp_dampening_prefix,
15641 clear_ip_bgp_dampening_prefix_cmd,
15642 "clear ip bgp dampening A.B.C.D/M",
15643 CLEAR_STR
15644 IP_STR
15645 BGP_STR
15646 "Clear route flap dampening information\n"
0c7b1b01 15647 "IPv4 prefix\n")
718e3744 15648{
d62a17ae 15649 int idx_ipv4_prefixlen = 4;
15650 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15651 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15652}
15653
15654DEFUN (clear_ip_bgp_dampening_address,
15655 clear_ip_bgp_dampening_address_cmd,
15656 "clear ip bgp dampening A.B.C.D",
15657 CLEAR_STR
15658 IP_STR
15659 BGP_STR
15660 "Clear route flap dampening information\n"
15661 "Network to clear damping information\n")
15662{
d62a17ae 15663 int idx_ipv4 = 4;
15664 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15665 SAFI_UNICAST, NULL, 0);
718e3744 15666}
15667
15668DEFUN (clear_ip_bgp_dampening_address_mask,
15669 clear_ip_bgp_dampening_address_mask_cmd,
15670 "clear ip bgp dampening A.B.C.D A.B.C.D",
15671 CLEAR_STR
15672 IP_STR
15673 BGP_STR
15674 "Clear route flap dampening information\n"
15675 "Network to clear damping information\n"
15676 "Network mask\n")
15677{
d62a17ae 15678 int idx_ipv4 = 4;
15679 int idx_ipv4_2 = 5;
15680 int ret;
15681 char prefix_str[BUFSIZ];
718e3744 15682
d62a17ae 15683 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15684 prefix_str, sizeof(prefix_str));
d62a17ae 15685 if (!ret) {
15686 vty_out(vty, "%% Inconsistent address and mask\n");
15687 return CMD_WARNING;
15688 }
718e3744 15689
d62a17ae 15690 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15691 NULL, 0);
718e3744 15692}
6b0655a2 15693
e3b78da8 15694static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15695{
15696 struct vty *vty = arg;
e3b78da8 15697 struct peer *peer = bucket->data;
825d9834 15698
47e12884 15699 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15700}
15701
2a0e69ae
DS
15702DEFUN (show_bgp_listeners,
15703 show_bgp_listeners_cmd,
15704 "show bgp listeners",
15705 SHOW_STR
15706 BGP_STR
15707 "Display Listen Sockets and who created them\n")
15708{
15709 bgp_dump_listener_info(vty);
15710
15711 return CMD_SUCCESS;
15712}
15713
825d9834
DS
15714DEFUN (show_bgp_peerhash,
15715 show_bgp_peerhash_cmd,
15716 "show bgp peerhash",
15717 SHOW_STR
15718 BGP_STR
15719 "Display information about the BGP peerhash\n")
15720{
15721 struct list *instances = bm->bgp;
15722 struct listnode *node;
15723 struct bgp *bgp;
15724
15725 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15726 vty_out(vty, "BGP: %s\n", bgp->name);
15727 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15728 vty);
15729 }
15730
15731 return CMD_SUCCESS;
15732}
15733
587ff0fd 15734/* also used for encap safi */
2b791107
DL
15735static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15736 afi_t afi, safi_t safi)
d62a17ae 15737{
9bcb3eef
DS
15738 struct bgp_dest *pdest;
15739 struct bgp_dest *dest;
d62a17ae 15740 struct bgp_table *table;
b54892e0 15741 const struct prefix *p;
d62a17ae 15742 struct bgp_static *bgp_static;
15743 mpls_label_t label;
d62a17ae 15744
15745 /* Network configuration. */
9bcb3eef
DS
15746 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15747 pdest = bgp_route_next(pdest)) {
15748 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15749 if (!table)
ea47320b 15750 continue;
d62a17ae 15751
9bcb3eef
DS
15752 for (dest = bgp_table_top(table); dest;
15753 dest = bgp_route_next(dest)) {
15754 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15755 if (bgp_static == NULL)
ea47320b 15756 continue;
d62a17ae 15757
9bcb3eef 15758 p = bgp_dest_get_prefix(dest);
d62a17ae 15759
ea47320b 15760 /* "network" configuration display. */
ea47320b
DL
15761 label = decode_label(&bgp_static->label);
15762
c1aa9e7f
PG
15763 vty_out(vty, " network %pFX rd %s", p,
15764 bgp_static->prd_pretty);
ea47320b
DL
15765 if (safi == SAFI_MPLS_VPN)
15766 vty_out(vty, " label %u", label);
15767
15768 if (bgp_static->rmap.name)
15769 vty_out(vty, " route-map %s",
15770 bgp_static->rmap.name);
e2a86ad9
DS
15771
15772 if (bgp_static->backdoor)
15773 vty_out(vty, " backdoor");
15774
ea47320b
DL
15775 vty_out(vty, "\n");
15776 }
15777 }
d62a17ae 15778}
15779
2b791107
DL
15780static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15781 afi_t afi, safi_t safi)
d62a17ae 15782{
9bcb3eef
DS
15783 struct bgp_dest *pdest;
15784 struct bgp_dest *dest;
d62a17ae 15785 struct bgp_table *table;
b54892e0 15786 const struct prefix *p;
d62a17ae 15787 struct bgp_static *bgp_static;
ff44f570 15788 char buf[PREFIX_STRLEN * 2];
d62a17ae 15789 char buf2[SU_ADDRSTRLEN];
5f933e1e 15790 char esi_buf[ESI_STR_LEN];
d62a17ae 15791
15792 /* Network configuration. */
9bcb3eef
DS
15793 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15794 pdest = bgp_route_next(pdest)) {
15795 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15796 if (!table)
ea47320b 15797 continue;
d62a17ae 15798
9bcb3eef
DS
15799 for (dest = bgp_table_top(table); dest;
15800 dest = bgp_route_next(dest)) {
15801 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15802 if (bgp_static == NULL)
ea47320b 15803 continue;
d62a17ae 15804
ea47320b 15805 char *macrouter = NULL;
d62a17ae 15806
ea47320b
DL
15807 if (bgp_static->router_mac)
15808 macrouter = prefix_mac2str(
15809 bgp_static->router_mac, NULL, 0);
15810 if (bgp_static->eth_s_id)
0a50c248
AK
15811 esi_to_str(bgp_static->eth_s_id,
15812 esi_buf, sizeof(esi_buf));
9bcb3eef 15813 p = bgp_dest_get_prefix(dest);
d62a17ae 15814
ea47320b 15815 /* "network" configuration display. */
197cb530
PG
15816 if (p->u.prefix_evpn.route_type == 5) {
15817 char local_buf[PREFIX_STRLEN];
07380148 15818
3714a385 15819 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15820 struct prefix_evpn *)p)
15821 ? AF_INET
15822 : AF_INET6;
3714a385 15823 inet_ntop(family,
07380148
DA
15824 &p->u.prefix_evpn.prefix_addr.ip.ip
15825 .addr,
15826 local_buf, sizeof(local_buf));
772270f3
QY
15827 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15828 p->u.prefix_evpn.prefix_addr
15829 .ip_prefix_length);
197cb530
PG
15830 } else {
15831 prefix2str(p, buf, sizeof(buf));
15832 }
ea47320b 15833
a4d82a8a
PZ
15834 if (bgp_static->gatewayIp.family == AF_INET
15835 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15836 inet_ntop(bgp_static->gatewayIp.family,
15837 &bgp_static->gatewayIp.u.prefix, buf2,
15838 sizeof(buf2));
ea47320b 15839 vty_out(vty,
c1aa9e7f
PG
15840 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
15841 buf, bgp_static->prd_pretty,
15842 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15843 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15844 macrouter);
15845
0a22ddfb 15846 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15847 }
15848 }
3da6fcd5
PG
15849}
15850
718e3744 15851/* Configuration of static route announcement and aggregate
15852 information. */
2b791107
DL
15853void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15854 safi_t safi)
d62a17ae 15855{
9bcb3eef 15856 struct bgp_dest *dest;
b54892e0 15857 const struct prefix *p;
d62a17ae 15858 struct bgp_static *bgp_static;
15859 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15860
2b791107
DL
15861 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15862 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15863 return;
15864 }
d62a17ae 15865
2b791107
DL
15866 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15867 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15868 return;
15869 }
d62a17ae 15870
15871 /* Network configuration. */
9bcb3eef
DS
15872 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15873 dest = bgp_route_next(dest)) {
15874 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15875 if (bgp_static == NULL)
ea47320b 15876 continue;
d62a17ae 15877
9bcb3eef 15878 p = bgp_dest_get_prefix(dest);
d62a17ae 15879
8228a9a7 15880 vty_out(vty, " network %pFX", p);
d62a17ae 15881
ea47320b
DL
15882 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15883 vty_out(vty, " label-index %u",
15884 bgp_static->label_index);
d62a17ae 15885
ea47320b
DL
15886 if (bgp_static->rmap.name)
15887 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15888
15889 if (bgp_static->backdoor)
15890 vty_out(vty, " backdoor");
718e3744 15891
ea47320b
DL
15892 vty_out(vty, "\n");
15893 }
15894
d62a17ae 15895 /* Aggregate-address configuration. */
9bcb3eef
DS
15896 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15897 dest = bgp_route_next(dest)) {
15898 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15899 if (bgp_aggregate == NULL)
ea47320b 15900 continue;
d62a17ae 15901
9bcb3eef 15902 p = bgp_dest_get_prefix(dest);
d62a17ae 15903
8228a9a7 15904 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15905
ea47320b
DL
15906 if (bgp_aggregate->as_set)
15907 vty_out(vty, " as-set");
d62a17ae 15908
ea47320b
DL
15909 if (bgp_aggregate->summary_only)
15910 vty_out(vty, " summary-only");
718e3744 15911
20894f50
DA
15912 if (bgp_aggregate->rmap.name)
15913 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15914
229757f1
DA
15915 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15916 vty_out(vty, " origin %s",
15917 bgp_origin2str(bgp_aggregate->origin));
15918
6aabb15d
RZ
15919 if (bgp_aggregate->match_med)
15920 vty_out(vty, " matching-MED-only");
15921
365ab2e7
RZ
15922 if (bgp_aggregate->suppress_map_name)
15923 vty_out(vty, " suppress-map %s",
15924 bgp_aggregate->suppress_map_name);
15925
ea47320b
DL
15926 vty_out(vty, "\n");
15927 }
d62a17ae 15928}
734b349e 15929
2b791107 15930void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15931 safi_t safi)
d62a17ae 15932{
9bcb3eef 15933 struct bgp_dest *dest;
d62a17ae 15934 struct bgp_distance *bdistance;
15935
15936 /* Distance configuration. */
15937 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15938 && bgp->distance_local[afi][safi]
15939 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15940 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15941 || bgp->distance_local[afi][safi]
15942 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15943 vty_out(vty, " distance bgp %d %d %d\n",
15944 bgp->distance_ebgp[afi][safi],
15945 bgp->distance_ibgp[afi][safi],
15946 bgp->distance_local[afi][safi]);
15947 }
734b349e 15948
9bcb3eef
DS
15949 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15950 dest = bgp_route_next(dest)) {
15951 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15952 if (bdistance != NULL)
56ca3b5b 15953 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15954 bdistance->distance, dest,
d62a17ae 15955 bdistance->access_list ? bdistance->access_list
15956 : "");
ca2e160d 15957 }
718e3744 15958}
15959
15960/* Allocate routing table structure and install commands. */
d62a17ae 15961void bgp_route_init(void)
15962{
15963 afi_t afi;
15964 safi_t safi;
15965
15966 /* Init BGP distance table. */
05c7a1cc 15967 FOREACH_AFI_SAFI (afi, safi)
960035b2 15968 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15969
15970 /* IPv4 BGP commands. */
15971 install_element(BGP_NODE, &bgp_table_map_cmd);
15972 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15973 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15974
554b3b10 15975 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15976
15977 /* IPv4 unicast configuration. */
15978 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15979 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15980 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15981
554b3b10 15982 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15983
15984 /* IPv4 multicast configuration. */
15985 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15986 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15987 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15988 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15989
15990 /* IPv4 labeled-unicast configuration. */
fb985e0c 15991 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15992 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15993
d62a17ae 15994 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15995 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15996 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15997 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15998 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15999 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
16000 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 16001 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 16002
16003 install_element(VIEW_NODE,
16004 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
16005 install_element(VIEW_NODE,
16006 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 16007 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
16008 install_element(VIEW_NODE,
16009 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 16010#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 16011 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 16012#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 16013 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
16014 install_element(VIEW_NODE,
44c69747 16015 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 16016
d62a17ae 16017 /* BGP dampening clear commands */
16018 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
16019 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 16020
d62a17ae 16021 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
16022 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
16023
16024 /* prefix count */
16025 install_element(ENABLE_NODE,
16026 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 16027#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 16028 install_element(ENABLE_NODE,
16029 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 16030#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 16031
d62a17ae 16032 /* New config IPv6 BGP commands. */
16033 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
16034 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 16035 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 16036
554b3b10 16037 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 16038
16039 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 16040
fb985e0c
DA
16041 /* IPv6 labeled unicast address family. */
16042 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 16043 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 16044
d62a17ae 16045 install_element(BGP_NODE, &bgp_distance_cmd);
16046 install_element(BGP_NODE, &no_bgp_distance_cmd);
16047 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16048 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
16049 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
16050 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 16051 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
16052 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
16053 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16054 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
16055 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
16056 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 16057 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
16058 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
16059 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
16060 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
16061 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
16062 install_element(BGP_IPV4M_NODE,
16063 &no_bgp_distance_source_access_list_cmd);
d62a17ae 16064 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
16065 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16066 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
16067 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
16068 install_element(BGP_IPV6_NODE,
16069 &ipv6_bgp_distance_source_access_list_cmd);
16070 install_element(BGP_IPV6_NODE,
16071 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16072 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
16073 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
16074 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
16075 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
16076 install_element(BGP_IPV6M_NODE,
16077 &ipv6_bgp_distance_source_access_list_cmd);
16078 install_element(BGP_IPV6M_NODE,
16079 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 16080
ef5f4b23 16081 /* BGP dampening */
585f1adc
IR
16082 install_element(BGP_NODE, &bgp_damp_set_cmd);
16083 install_element(BGP_NODE, &bgp_damp_unset_cmd);
16084 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
16085 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
16086 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
16087 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
16088 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
16089 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
16090 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
16091 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
16092 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
16093 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
16094 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
16095 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 16096
16097 /* Large Communities */
16098 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
16099 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3 16100
795bef98
RR
16101 /* show bgp vrf <afi> <safi> detailed */
16102 install_element(VIEW_NODE,
16103 &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd);
dba3c1d3 16104
2a0e69ae 16105 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 16106 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 16107}
16108
16109void bgp_route_finish(void)
16110{
16111 afi_t afi;
16112 safi_t safi;
16113
05c7a1cc
QY
16114 FOREACH_AFI_SAFI (afi, safi) {
16115 bgp_table_unlock(bgp_distance_table[afi][safi]);
16116 bgp_distance_table[afi][safi] = NULL;
16117 }
228da428 16118}