]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
tests: add unit tests to bgp aspath to check as dot format
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9 92#include "bgpd/bgp_route_clippy.c"
aee875b5 93
7fd28dd2
PR
94DEFINE_HOOK(bgp_snmp_update_stats,
95 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 96 (rn, pi, added));
7fd28dd2 97
b5b99af8
DS
98DEFINE_HOOK(bgp_rpki_prefix_status,
99 (struct peer *peer, struct attr *attr,
100 const struct prefix *prefix),
8451921b 101 (peer, attr, prefix));
b5b99af8 102
718e3744 103/* Extern from bgp_dump.c */
dde72586
SH
104extern const char *bgp_origin_str[];
105extern const char *bgp_origin_long_str[];
3742de8d 106
b7d08f5a 107/* PMSI strings. */
108#define PMSI_TNLTYPE_STR_NO_INFO "No info"
109#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
110static const struct message bgp_pmsi_tnltype_str[] = {
111 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
112 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
113 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
114 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
115 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
116 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
117 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
118 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 119 {0}
120};
b7d08f5a 121
9df8b37c 122#define VRFID_NONE_STR "-"
46aeabed 123#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 124
4a11bf2c 125DEFINE_HOOK(bgp_process,
9bcb3eef
DS
126 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
127 struct peer *peer, bool withdraw),
8451921b 128 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 129
4056a5f6
RZ
130/** Test if path is suppressed. */
131static bool bgp_path_suppressed(struct bgp_path_info *pi)
132{
133 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
134 return false;
135
136 return listcount(pi->extra->aggr_suppressors) > 0;
137}
4a11bf2c 138
9bcb3eef 139struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 140 safi_t safi, const struct prefix *p,
d62a17ae 141 struct prefix_rd *prd)
142{
9bcb3eef
DS
143 struct bgp_dest *dest;
144 struct bgp_dest *pdest = NULL;
d62a17ae 145
146 assert(table);
d62a17ae 147
148 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
149 || (safi == SAFI_EVPN)) {
9bcb3eef 150 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 151
9bcb3eef
DS
152 if (!bgp_dest_has_bgp_path_info_data(pdest))
153 bgp_dest_set_bgp_table_info(
154 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 155 else
9bcb3eef
DS
156 bgp_dest_unlock_node(pdest);
157 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 158 }
718e3744 159
9bcb3eef 160 dest = bgp_node_get(table, p);
718e3744 161
d62a17ae 162 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
163 || (safi == SAFI_EVPN))
9bcb3eef 164 dest->pdest = pdest;
718e3744 165
9bcb3eef 166 return dest;
718e3744 167}
6b0655a2 168
9bcb3eef 169struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 170 safi_t safi, const struct prefix *p,
d62a17ae 171 struct prefix_rd *prd)
128ea8ab 172{
9bcb3eef
DS
173 struct bgp_dest *dest;
174 struct bgp_dest *pdest = NULL;
128ea8ab 175
d62a17ae 176 if (!table)
177 return NULL;
128ea8ab 178
d62a17ae 179 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
180 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
181 pdest = bgp_node_lookup(table, (struct prefix *)prd);
182 if (!pdest)
d62a17ae 183 return NULL;
128ea8ab 184
9bcb3eef
DS
185 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
186 bgp_dest_unlock_node(pdest);
d62a17ae 187 return NULL;
188 }
128ea8ab 189
9bcb3eef 190 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 191 }
128ea8ab 192
9bcb3eef 193 dest = bgp_node_lookup(table, p);
128ea8ab 194
9bcb3eef 195 return dest;
128ea8ab 196}
197
18ee8310
DS
198/* Allocate bgp_path_info_extra */
199static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 200{
4b7e6066
DS
201 struct bgp_path_info_extra *new;
202 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
203 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
204 new->label[0] = MPLS_INVALID_LABEL;
205 new->num_labels = 0;
3e3708cb
PG
206 new->bgp_fs_pbr = NULL;
207 new->bgp_fs_iprule = NULL;
d62a17ae 208 return new;
fb982c25
PJ
209}
210
a2e219fe 211void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 212{
4b7e6066 213 struct bgp_path_info_extra *e;
d62a17ae 214
c93a3b77
DS
215 if (!extra || !*extra)
216 return;
d62a17ae 217
c93a3b77 218 e = *extra;
4538f895 219 if (e->damp_info)
b4f7f45b
IR
220 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
221 e->damp_info->safi);
4538f895 222
c93a3b77
DS
223 e->damp_info = NULL;
224 if (e->parent) {
40381db7 225 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 226
40381db7 227 if (bpi->net) {
0e70e6c8
DL
228 /* FIXME: since multiple e may have the same e->parent
229 * and e->parent->net is holding a refcount for each
230 * of them, we need to do some fudging here.
231 *
40381db7
DS
232 * WARNING: if bpi->net->lock drops to 0, bpi may be
233 * freed as well (because bpi->net was holding the
234 * last reference to bpi) => write after free!
0e70e6c8
DL
235 */
236 unsigned refcount;
237
40381db7 238 bpi = bgp_path_info_lock(bpi);
c10e14e9 239 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 240 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 241 if (!refcount)
40381db7
DS
242 bpi->net = NULL;
243 bgp_path_info_unlock(bpi);
0e70e6c8 244 }
18ee8310 245 bgp_path_info_unlock(e->parent);
c93a3b77 246 e->parent = NULL;
d62a17ae 247 }
c93a3b77
DS
248
249 if (e->bgp_orig)
250 bgp_unlock(e->bgp_orig);
c26edcda 251
4cd690ae
PG
252 if (e->peer_orig)
253 peer_unlock(e->peer_orig);
254
ff3bf9a4
DS
255 if (e->aggr_suppressors)
256 list_delete(&e->aggr_suppressors);
257
60605cbc
AK
258 if (e->mh_info)
259 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 260
ce3c0614
PG
261 if ((*extra)->bgp_fs_iprule)
262 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 263 if ((*extra)->bgp_fs_pbr)
6a154c88 264 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 265 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
266}
267
18ee8310
DS
268/* Get bgp_path_info extra information for the given bgp_path_info, lazy
269 * allocated if required.
fb982c25 270 */
40381db7 271struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 272{
40381db7
DS
273 if (!pi->extra)
274 pi->extra = bgp_path_info_extra_new();
275 return pi->extra;
fb982c25
PJ
276}
277
718e3744 278/* Free bgp route information. */
eb473185
DA
279void bgp_path_info_free_with_caller(const char *name,
280 struct bgp_path_info *path)
718e3744 281{
eb473185 282 frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
05864da7 283 bgp_attr_unintern(&path->attr);
fb018d25 284
9b6d8fcf
DS
285 bgp_unlink_nexthop(path);
286 bgp_path_info_extra_free(&path->extra);
287 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
288 if (path->net)
289 bgp_addpath_free_info_data(&path->tx_addpath,
290 &path->net->tx_addpath);
718e3744 291
9b6d8fcf 292 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 293
9b6d8fcf 294 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 295}
296
9b6d8fcf 297struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 298{
9b6d8fcf
DS
299 path->lock++;
300 return path;
200df115 301}
302
9b6d8fcf 303struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 304{
9b6d8fcf
DS
305 assert(path && path->lock > 0);
306 path->lock--;
d62a17ae 307
9b6d8fcf 308 if (path->lock == 0) {
9b6d8fcf 309 bgp_path_info_free(path);
d62a17ae 310 return NULL;
311 }
200df115 312
9b6d8fcf 313 return path;
200df115 314}
315
f009ff26 316/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 317static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 318{
319 struct peer *peer;
320 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 321 bool set_flag = false;
f009ff26 322 struct bgp *bgp = NULL;
323 struct bgp_table *table = NULL;
324 afi_t afi = 0;
325 safi_t safi = 0;
f009ff26 326
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
329 */
9bcb3eef 330 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 331 return 0;
332
9bcb3eef 333 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 334 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 335 zlog_debug(
56ca3b5b
DL
336 "Route %pBD is in workqueue and being processed, not deferred.",
337 dest);
b54892e0 338
5f9c1aa2 339 return 0;
340 }
341
9bcb3eef 342 table = bgp_dest_table(dest);
f009ff26 343 if (table) {
344 bgp = table->bgp;
345 afi = table->afi;
346 safi = table->safi;
347 }
348
9bcb3eef 349 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 350 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
351 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
352 continue;
353
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
356 */
36235319
QY
357 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
358 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 359 set_flag = true;
f009ff26 360 } else {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
363 */
364 peer = old_pi->peer;
36235319
QY
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
366 && BGP_PEER_RESTARTING_MODE(peer)
367 && (old_pi
368 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 369 set_flag = true;
f009ff26 370 }
371 }
372 if (set_flag)
373 break;
374 }
375
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
377 * is active
378 */
2ba1fe69 379 if (set_flag && table) {
f009ff26 380 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
381 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
382 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 383 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 384 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
385 zlog_debug("DEFER route %pBD, dest %p", dest,
386 dest);
f009ff26 387 return 0;
388 }
389 }
390 return -1;
391}
392
eb473185
DA
393void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
394 struct bgp_path_info *pi)
718e3744 395{
c6b077a5 396 frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
4b7e6066 397 struct bgp_path_info *top;
718e3744 398
9bcb3eef 399 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 400
6f94b685 401 pi->next = top;
40381db7 402 pi->prev = NULL;
d62a17ae 403 if (top)
40381db7 404 top->prev = pi;
9bcb3eef 405 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 406
40381db7 407 bgp_path_info_lock(pi);
9bcb3eef 408 bgp_dest_lock_node(dest);
40381db7 409 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 410 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 411 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 412}
413
d62a17ae 414/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 415 completion callback *only* */
9bcb3eef 416void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 417{
40381db7
DS
418 if (pi->next)
419 pi->next->prev = pi->prev;
420 if (pi->prev)
421 pi->prev->next = pi->next;
d62a17ae 422 else
9bcb3eef 423 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 424
40381db7
DS
425 bgp_path_info_mpath_dequeue(pi);
426 bgp_path_info_unlock(pi);
7fd28dd2 427 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 428 bgp_dest_unlock_node(dest);
718e3744 429}
430
9bcb3eef 431void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 432{
9bcb3eef 433 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 434 /* set of previous already took care of pcount */
40381db7 435 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 436}
437
18ee8310 438/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
439 called when a route is deleted and then quickly re-added before the
440 deletion has been processed */
9bcb3eef 441void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 442{
9bcb3eef 443 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 444 /* unset of previous already took care of pcount */
40381db7 445 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
446}
447
d62a17ae 448/* Adjust pcount as required */
9bcb3eef 449static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 450{
d62a17ae 451 struct bgp_table *table;
67174041 452
9bcb3eef 453 assert(dest && bgp_dest_table(dest));
40381db7 454 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 455
9bcb3eef 456 table = bgp_dest_table(dest);
67174041 457
40381db7 458 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 459 return;
460
40381db7
DS
461 if (!BGP_PATH_COUNTABLE(pi)
462 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 463
40381db7 464 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 465
466 /* slight hack, but more robust against errors. */
40381db7
DS
467 if (pi->peer->pcount[table->afi][table->safi])
468 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 469 else
450971aa 470 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 471 "Asked to decrement 0 prefix count for peer");
40381db7
DS
472 } else if (BGP_PATH_COUNTABLE(pi)
473 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
474 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
475 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 476 }
1a392d46
PJ
477}
478
40381db7
DS
479static int bgp_label_index_differs(struct bgp_path_info *pi1,
480 struct bgp_path_info *pi2)
28d58fd7 481{
40381db7 482 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 483}
1a392d46 484
18ee8310 485/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
486 * This is here primarily to keep prefix-count in check.
487 */
9bcb3eef 488void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 489 uint32_t flag)
1a392d46 490{
40381db7 491 SET_FLAG(pi->flags, flag);
d62a17ae 492
493 /* early bath if we know it's not a flag that changes countability state
494 */
495 if (!CHECK_FLAG(flag,
1defdda8 496 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 497 return;
498
9bcb3eef 499 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
500}
501
9bcb3eef 502void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 503 uint32_t flag)
1a392d46 504{
40381db7 505 UNSET_FLAG(pi->flags, flag);
d62a17ae 506
507 /* early bath if we know it's not a flag that changes countability state
508 */
509 if (!CHECK_FLAG(flag,
1defdda8 510 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 511 return;
512
9bcb3eef 513 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
514}
515
718e3744 516/* Get MED value. If MED value is missing and "bgp bestpath
517 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 518static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 519{
520 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
521 return attr->med;
522 else {
892fedb6 523 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 524 return BGP_MED_MAX;
525 else
526 return 0;
527 }
718e3744 528}
529
7533cad7
QY
530void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
531 size_t buf_len)
2ec1e66f 532{
40381db7 533 if (pi->addpath_rx_id)
7533cad7
QY
534 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
535 pi->peer->host, pi->addpath_rx_id);
d62a17ae 536 else
7533cad7 537 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 538}
9fbdd100 539
da0c0ef7
KM
540
541/*
542 * Get the ultimate path info.
543 */
544struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
545{
546 struct bgp_path_info *bpi_ultimate;
547
548 if (info->sub_type != BGP_ROUTE_IMPORTED)
549 return info;
550
551 for (bpi_ultimate = info;
552 bpi_ultimate->extra && bpi_ultimate->extra->parent;
553 bpi_ultimate = bpi_ultimate->extra->parent)
554 ;
555
556 return bpi_ultimate;
557}
558
d62a17ae 559/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
560 */
18ee8310
DS
561static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
562 struct bgp_path_info *exist, int *paths_eq,
563 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
564 char *pfx_buf, afi_t afi, safi_t safi,
565 enum bgp_path_selection_reason *reason)
d62a17ae 566{
5df26422 567 const struct prefix *new_p;
d62a17ae 568 struct attr *newattr, *existattr;
3061acc2
DA
569 enum bgp_peer_sort new_sort;
570 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
571 uint32_t new_pref;
572 uint32_t exist_pref;
573 uint32_t new_med;
574 uint32_t exist_med;
575 uint32_t new_weight;
576 uint32_t exist_weight;
d62a17ae 577 uint32_t newm, existm;
578 struct in_addr new_id;
579 struct in_addr exist_id;
580 int new_cluster;
581 int exist_cluster;
582 int internal_as_route;
583 int confed_as_route;
04d14c8b 584 int ret = 0;
ee88563a
JM
585 int igp_metric_ret = 0;
586 int peer_sort_ret = -1;
d62a17ae 587 char new_buf[PATH_ADDPATH_STR_BUFFER];
588 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
589 uint32_t new_mm_seq;
590 uint32_t exist_mm_seq;
6d8c603a 591 int nh_cmp;
d071f237
AK
592 esi_t *exist_esi;
593 esi_t *new_esi;
594 bool same_esi;
595 bool old_proxy;
596 bool new_proxy;
33c6e933 597 bool new_origin, exist_origin;
da0c0ef7 598 struct bgp_path_info *bpi_ultimate;
d62a17ae 599
600 *paths_eq = 0;
601
602 /* 0. Null check. */
603 if (new == NULL) {
fdf81fa0 604 *reason = bgp_path_selection_none;
d62a17ae 605 if (debug)
606 zlog_debug("%s: new is NULL", pfx_buf);
607 return 0;
608 }
2ec1e66f 609
da0c0ef7
KM
610 if (debug) {
611 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
612 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 613 sizeof(new_buf));
da0c0ef7 614 }
718e3744 615
d62a17ae 616 if (exist == NULL) {
fdf81fa0 617 *reason = bgp_path_selection_first;
d62a17ae 618 if (debug)
4378495a
DS
619 zlog_debug("%s(%s): %s is the initial bestpath",
620 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 621 return 1;
622 }
2ec1e66f 623
d62a17ae 624 if (debug) {
da0c0ef7
KM
625 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
626 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 627 sizeof(exist_buf));
4378495a
DS
628 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
629 pfx_buf, bgp->name_pretty, new_buf, new->flags,
630 exist_buf, exist->flags);
d62a17ae 631 }
8ff56318 632
d62a17ae 633 newattr = new->attr;
634 existattr = exist->attr;
635
1479ed2f
DA
636 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
637 * Capability" to a neighbor MUST perform the following upon receiving
638 * a route from that neighbor with the "LLGR_STALE" community, or upon
639 * attaching the "LLGR_STALE" community itself per Section 4.2:
640 *
641 * Treat the route as the least-preferred in route selection (see
642 * below). See the Risks of Depreferencing Routes section (Section 5.2)
643 * for a discussion of potential risks inherent in doing this.
644 */
9a706b42
DA
645 if (bgp_attr_get_community(newattr) &&
646 community_include(bgp_attr_get_community(newattr),
647 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
648 if (debug)
649 zlog_debug(
650 "%s: %s wins over %s due to LLGR_STALE community",
651 pfx_buf, new_buf, exist_buf);
652 return 0;
653 }
654
9a706b42
DA
655 if (bgp_attr_get_community(existattr) &&
656 community_include(bgp_attr_get_community(existattr),
657 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
658 if (debug)
659 zlog_debug(
660 "%s: %s loses to %s due to LLGR_STALE community",
661 pfx_buf, new_buf, exist_buf);
662 return 1;
663 }
664
5df26422
NS
665 new_p = bgp_dest_get_prefix(new->net);
666
d62a17ae 667 /* For EVPN routes, we cannot just go by local vs remote, we have to
668 * look at the MAC mobility sequence number, if present.
669 */
5df26422
NS
670 if ((safi == SAFI_EVPN)
671 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 672 /* This is an error condition described in RFC 7432 Section
673 * 15.2. The RFC
674 * states that in this scenario "the PE MUST alert the operator"
675 * but it
676 * does not state what other action to take. In order to provide
677 * some
678 * consistency in this scenario we are going to prefer the path
679 * with the
680 * sticky flag.
681 */
682 if (newattr->sticky != existattr->sticky) {
683 if (!debug) {
5df26422
NS
684 prefix2str(new_p, pfx_buf,
685 sizeof(*pfx_buf)
686 * PREFIX2STR_BUFFER);
18ee8310 687 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
688 new, new_buf, sizeof(new_buf));
689 bgp_path_info_path_with_addpath_rx_str(
690 exist, exist_buf, sizeof(exist_buf));
d62a17ae 691 }
692
693 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 694 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
695 if (debug)
696 zlog_debug(
697 "%s: %s wins over %s due to sticky MAC flag",
698 pfx_buf, new_buf, exist_buf);
d62a17ae 699 return 1;
700 }
701
702 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 703 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
704 if (debug)
705 zlog_debug(
706 "%s: %s loses to %s due to sticky MAC flag",
707 pfx_buf, new_buf, exist_buf);
d62a17ae 708 return 0;
709 }
710 }
128ea8ab 711
d071f237
AK
712 new_esi = bgp_evpn_attr_get_esi(newattr);
713 exist_esi = bgp_evpn_attr_get_esi(existattr);
714 if (bgp_evpn_is_esi_valid(new_esi) &&
715 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
716 same_esi = true;
717 } else {
718 same_esi = false;
719 }
720
721 /* If both paths have the same non-zero ES and
722 * one path is local it wins.
723 * PS: Note the local path wins even if the remote
724 * has the higher MM seq. The local path's
725 * MM seq will be fixed up to match the highest
726 * rem seq, subsequently.
727 */
728 if (same_esi) {
729 char esi_buf[ESI_STR_LEN];
730
731 if (bgp_evpn_is_path_local(bgp, new)) {
732 *reason = bgp_path_selection_evpn_local_path;
733 if (debug)
734 zlog_debug(
735 "%s: %s wins over %s as ES %s is same and local",
736 pfx_buf, new_buf, exist_buf,
737 esi_to_str(new_esi, esi_buf,
738 sizeof(esi_buf)));
739 return 1;
740 }
741 if (bgp_evpn_is_path_local(bgp, exist)) {
742 *reason = bgp_path_selection_evpn_local_path;
743 if (debug)
744 zlog_debug(
745 "%s: %s loses to %s as ES %s is same and local",
746 pfx_buf, new_buf, exist_buf,
747 esi_to_str(new_esi, esi_buf,
748 sizeof(esi_buf)));
749 return 0;
750 }
751 }
752
d62a17ae 753 new_mm_seq = mac_mobility_seqnum(newattr);
754 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 755
d62a17ae 756 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 757 *reason = bgp_path_selection_evpn_seq;
d62a17ae 758 if (debug)
759 zlog_debug(
760 "%s: %s wins over %s due to MM seq %u > %u",
761 pfx_buf, new_buf, exist_buf, new_mm_seq,
762 exist_mm_seq);
763 return 1;
764 }
8ff56318 765
d62a17ae 766 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 767 *reason = bgp_path_selection_evpn_seq;
d62a17ae 768 if (debug)
769 zlog_debug(
770 "%s: %s loses to %s due to MM seq %u < %u",
771 pfx_buf, new_buf, exist_buf, new_mm_seq,
772 exist_mm_seq);
773 return 0;
774 }
6d8c603a 775
d071f237
AK
776 /* if the sequence numbers and ESI are the same and one path
777 * is non-proxy it wins (over proxy)
778 */
779 new_proxy = bgp_evpn_attr_is_proxy(newattr);
780 old_proxy = bgp_evpn_attr_is_proxy(existattr);
781 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
782 old_proxy != new_proxy) {
783 if (!new_proxy) {
784 *reason = bgp_path_selection_evpn_non_proxy;
785 if (debug)
786 zlog_debug(
787 "%s: %s wins over %s, same seq/es and non-proxy",
788 pfx_buf, new_buf, exist_buf);
789 return 1;
790 }
791
792 *reason = bgp_path_selection_evpn_non_proxy;
793 if (debug)
794 zlog_debug(
795 "%s: %s loses to %s, same seq/es and non-proxy",
796 pfx_buf, new_buf, exist_buf);
797 return 0;
798 }
799
6d8c603a
AK
800 /*
801 * if sequence numbers are the same path with the lowest IP
802 * wins
803 */
804 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
805 if (nh_cmp < 0) {
fdf81fa0 806 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
807 if (debug)
808 zlog_debug(
23d0a753 809 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 810 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 811 &new->attr->nexthop);
6d8c603a
AK
812 return 1;
813 }
814 if (nh_cmp > 0) {
fdf81fa0 815 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
816 if (debug)
817 zlog_debug(
23d0a753 818 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 819 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 820 &new->attr->nexthop);
6d8c603a
AK
821 return 0;
822 }
d62a17ae 823 }
9fbdd100 824
d62a17ae 825 /* 1. Weight check. */
d62a17ae 826 new_weight = newattr->weight;
827 exist_weight = existattr->weight;
8ff56318 828
d62a17ae 829 if (new_weight > exist_weight) {
fdf81fa0 830 *reason = bgp_path_selection_weight;
d62a17ae 831 if (debug)
832 zlog_debug("%s: %s wins over %s due to weight %d > %d",
833 pfx_buf, new_buf, exist_buf, new_weight,
834 exist_weight);
835 return 1;
836 }
718e3744 837
d62a17ae 838 if (new_weight < exist_weight) {
fdf81fa0 839 *reason = bgp_path_selection_weight;
d62a17ae 840 if (debug)
841 zlog_debug("%s: %s loses to %s due to weight %d < %d",
842 pfx_buf, new_buf, exist_buf, new_weight,
843 exist_weight);
844 return 0;
845 }
9fbdd100 846
d62a17ae 847 /* 2. Local preference check. */
848 new_pref = exist_pref = bgp->default_local_pref;
849
850 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
851 new_pref = newattr->local_pref;
852 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
853 exist_pref = existattr->local_pref;
854
855 if (new_pref > exist_pref) {
fdf81fa0 856 *reason = bgp_path_selection_local_pref;
d62a17ae 857 if (debug)
858 zlog_debug(
859 "%s: %s wins over %s due to localpref %d > %d",
860 pfx_buf, new_buf, exist_buf, new_pref,
861 exist_pref);
862 return 1;
863 }
718e3744 864
d62a17ae 865 if (new_pref < exist_pref) {
fdf81fa0 866 *reason = bgp_path_selection_local_pref;
d62a17ae 867 if (debug)
868 zlog_debug(
869 "%s: %s loses to %s due to localpref %d < %d",
870 pfx_buf, new_buf, exist_buf, new_pref,
871 exist_pref);
872 return 0;
873 }
9fbdd100 874
46dbf9d0
DA
875 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
876 * extensions defined in this document, the following step is inserted
877 * after the LOCAL_PREF comparison step in the BGP decision process:
878 * When comparing a pair of routes for a BGP destination, the
879 * route with the ACCEPT_OWN community attached is preferred over
880 * the route that does not have the community.
881 * This extra step MUST only be invoked during the best path selection
882 * process of VPN-IP routes.
883 */
884 if (safi == SAFI_MPLS_VPN &&
885 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
886 CHECK_FLAG(exist->peer->af_flags[afi][safi],
887 PEER_FLAG_ACCEPT_OWN))) {
888 bool new_accept_own = false;
889 bool exist_accept_own = false;
890 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
891
892 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
893 new_accept_own = community_include(
894 bgp_attr_get_community(newattr), accept_own);
895 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
896 exist_accept_own = community_include(
897 bgp_attr_get_community(existattr), accept_own);
898
899 if (new_accept_own && !exist_accept_own) {
900 *reason = bgp_path_selection_accept_own;
901 if (debug)
902 zlog_debug(
903 "%s: %s wins over %s due to accept-own",
904 pfx_buf, new_buf, exist_buf);
905 return 1;
906 }
907
908 if (!new_accept_own && exist_accept_own) {
909 *reason = bgp_path_selection_accept_own;
910 if (debug)
911 zlog_debug(
912 "%s: %s loses to %s due to accept-own",
913 pfx_buf, new_buf, exist_buf);
914 return 0;
915 }
916 }
917
97a52c82
DA
918 /* Tie-breaker - AIGP (Metric TLV) attribute */
919 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
920 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
921 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
922 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
923 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
924
925 if (new_aigp < exist_aigp) {
926 *reason = bgp_path_selection_aigp;
927 if (debug)
928 zlog_debug(
929 "%s: %s wins over %s due to AIGP %" PRIu64
930 " < %" PRIu64,
931 pfx_buf, new_buf, exist_buf, new_aigp,
932 exist_aigp);
933 return 1;
934 }
935
936 if (new_aigp > exist_aigp) {
937 *reason = bgp_path_selection_aigp;
938 if (debug)
939 zlog_debug(
940 "%s: %s loses to %s due to AIGP %" PRIu64
941 " > %" PRIu64,
942 pfx_buf, new_buf, exist_buf, new_aigp,
943 exist_aigp);
944 return 0;
945 }
946 }
947
d62a17ae 948 /* 3. Local route check. We prefer:
949 * - BGP_ROUTE_STATIC
950 * - BGP_ROUTE_AGGREGATE
951 * - BGP_ROUTE_REDISTRIBUTE
952 */
33c6e933
DS
953 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
954 new->sub_type == BGP_ROUTE_IMPORTED);
955 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
956 exist->sub_type == BGP_ROUTE_IMPORTED);
957
958 if (new_origin && !exist_origin) {
fdf81fa0 959 *reason = bgp_path_selection_local_route;
d62a17ae 960 if (debug)
961 zlog_debug(
962 "%s: %s wins over %s due to preferred BGP_ROUTE type",
963 pfx_buf, new_buf, exist_buf);
964 return 1;
965 }
718e3744 966
33c6e933 967 if (!new_origin && exist_origin) {
fdf81fa0 968 *reason = bgp_path_selection_local_route;
d62a17ae 969 if (debug)
970 zlog_debug(
971 "%s: %s loses to %s due to preferred BGP_ROUTE type",
972 pfx_buf, new_buf, exist_buf);
973 return 0;
6811845b 974 }
718e3744 975
da0c0ef7
KM
976 /* Here if these are imported routes then get ultimate pi for
977 * path compare.
978 */
979 new = bgp_get_imported_bpi_ultimate(new);
980 exist = bgp_get_imported_bpi_ultimate(exist);
981 newattr = new->attr;
982 existattr = exist->attr;
983
d62a17ae 984 /* 4. AS path length check. */
892fedb6 985 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 986 int exist_hops = aspath_count_hops(existattr->aspath);
987 int exist_confeds = aspath_count_confeds(existattr->aspath);
988
892fedb6 989 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 990 int aspath_hops;
991
992 aspath_hops = aspath_count_hops(newattr->aspath);
993 aspath_hops += aspath_count_confeds(newattr->aspath);
994
995 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 996 *reason = bgp_path_selection_confed_as_path;
d62a17ae 997 if (debug)
998 zlog_debug(
999 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1000 pfx_buf, new_buf, exist_buf,
1001 aspath_hops,
1002 (exist_hops + exist_confeds));
1003 return 1;
1004 }
1005
1006 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1007 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1008 if (debug)
1009 zlog_debug(
1010 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1011 pfx_buf, new_buf, exist_buf,
1012 aspath_hops,
1013 (exist_hops + exist_confeds));
1014 return 0;
1015 }
1016 } else {
1017 int newhops = aspath_count_hops(newattr->aspath);
1018
1019 if (newhops < exist_hops) {
fdf81fa0 1020 *reason = bgp_path_selection_as_path;
d62a17ae 1021 if (debug)
1022 zlog_debug(
1023 "%s: %s wins over %s due to aspath hopcount %d < %d",
1024 pfx_buf, new_buf, exist_buf,
1025 newhops, exist_hops);
1026 return 1;
1027 }
1028
1029 if (newhops > exist_hops) {
fdf81fa0 1030 *reason = bgp_path_selection_as_path;
d62a17ae 1031 if (debug)
1032 zlog_debug(
1033 "%s: %s loses to %s due to aspath hopcount %d > %d",
1034 pfx_buf, new_buf, exist_buf,
1035 newhops, exist_hops);
1036 return 0;
1037 }
1038 }
1039 }
9fbdd100 1040
d62a17ae 1041 /* 5. Origin check. */
1042 if (newattr->origin < existattr->origin) {
fdf81fa0 1043 *reason = bgp_path_selection_origin;
d62a17ae 1044 if (debug)
1045 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1046 pfx_buf, new_buf, exist_buf,
1047 bgp_origin_long_str[newattr->origin],
1048 bgp_origin_long_str[existattr->origin]);
1049 return 1;
1050 }
718e3744 1051
d62a17ae 1052 if (newattr->origin > existattr->origin) {
fdf81fa0 1053 *reason = bgp_path_selection_origin;
d62a17ae 1054 if (debug)
1055 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1056 pfx_buf, new_buf, exist_buf,
1057 bgp_origin_long_str[newattr->origin],
1058 bgp_origin_long_str[existattr->origin]);
1059 return 0;
1060 }
718e3744 1061
d62a17ae 1062 /* 6. MED check. */
1063 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1064 && aspath_count_hops(existattr->aspath) == 0);
1065 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1066 && aspath_count_confeds(existattr->aspath) > 0
1067 && aspath_count_hops(newattr->aspath) == 0
1068 && aspath_count_hops(existattr->aspath) == 0);
1069
892fedb6
DA
1070 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1071 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1072 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1073 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1074 || internal_as_route) {
1075 new_med = bgp_med_value(new->attr, bgp);
1076 exist_med = bgp_med_value(exist->attr, bgp);
1077
1078 if (new_med < exist_med) {
fdf81fa0 1079 *reason = bgp_path_selection_med;
d62a17ae 1080 if (debug)
1081 zlog_debug(
1082 "%s: %s wins over %s due to MED %d < %d",
1083 pfx_buf, new_buf, exist_buf, new_med,
1084 exist_med);
1085 return 1;
1086 }
8ff56318 1087
d62a17ae 1088 if (new_med > exist_med) {
fdf81fa0 1089 *reason = bgp_path_selection_med;
d62a17ae 1090 if (debug)
1091 zlog_debug(
1092 "%s: %s loses to %s due to MED %d > %d",
1093 pfx_buf, new_buf, exist_buf, new_med,
1094 exist_med);
1095 return 0;
1096 }
1097 }
9fbdd100 1098
d62a17ae 1099 /* 7. Peer type check. */
1100 new_sort = new->peer->sort;
1101 exist_sort = exist->peer->sort;
1102
1103 if (new_sort == BGP_PEER_EBGP
1104 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1105 *reason = bgp_path_selection_peer;
d62a17ae 1106 if (debug)
1107 zlog_debug(
1108 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1109 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1110 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1111 return 1;
1112 peer_sort_ret = 1;
d62a17ae 1113 }
718e3744 1114
d62a17ae 1115 if (exist_sort == BGP_PEER_EBGP
1116 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1117 *reason = bgp_path_selection_peer;
d62a17ae 1118 if (debug)
1119 zlog_debug(
1120 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1121 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1122 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1123 return 0;
1124 peer_sort_ret = 0;
d62a17ae 1125 }
8ff56318 1126
d62a17ae 1127 /* 8. IGP metric check. */
1128 newm = existm = 0;
8ff56318 1129
d62a17ae 1130 if (new->extra)
1131 newm = new->extra->igpmetric;
1132 if (exist->extra)
1133 existm = exist->extra->igpmetric;
9fbdd100 1134
d62a17ae 1135 if (newm < existm) {
ee88563a 1136 if (debug && peer_sort_ret < 0)
d62a17ae 1137 zlog_debug(
d588b995 1138 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1139 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1140 igp_metric_ret = 1;
d62a17ae 1141 }
718e3744 1142
d62a17ae 1143 if (newm > existm) {
ee88563a 1144 if (debug && peer_sort_ret < 0)
d62a17ae 1145 zlog_debug(
d588b995 1146 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1147 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1148 igp_metric_ret = 0;
5e242b0d 1149 }
5e242b0d 1150
d62a17ae 1151 /* 9. Same IGP metric. Compare the cluster list length as
1152 representative of IGP hops metric. Rewrite the metric value
1153 pair (newm, existm) with the cluster list length. Prefer the
1154 path with smaller cluster list length. */
1155 if (newm == existm) {
aa53c036
DS
1156 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1157 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1158 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1159 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1160 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1161
1162 if (newm < existm) {
ee88563a 1163 if (debug && peer_sort_ret < 0)
d62a17ae 1164 zlog_debug(
d588b995 1165 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1166 pfx_buf, new_buf, exist_buf,
1167 newm, existm);
ee88563a 1168 igp_metric_ret = 1;
d62a17ae 1169 }
1170
1171 if (newm > existm) {
ee88563a 1172 if (debug && peer_sort_ret < 0)
d62a17ae 1173 zlog_debug(
d588b995 1174 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1175 pfx_buf, new_buf, exist_buf,
1176 newm, existm);
ee88563a 1177 igp_metric_ret = 0;
d62a17ae 1178 }
1179 }
1180 }
31a4638f 1181
d62a17ae 1182 /* 10. confed-external vs. confed-internal */
1183 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1184 if (new_sort == BGP_PEER_CONFED
1185 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1186 *reason = bgp_path_selection_confed;
d62a17ae 1187 if (debug)
1188 zlog_debug(
1189 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1190 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1191 if (!CHECK_FLAG(bgp->flags,
1192 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1193 return 1;
1194 peer_sort_ret = 1;
d62a17ae 1195 }
718e3744 1196
d62a17ae 1197 if (exist_sort == BGP_PEER_CONFED
1198 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1199 *reason = bgp_path_selection_confed;
d62a17ae 1200 if (debug)
1201 zlog_debug(
1202 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1203 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1204 if (!CHECK_FLAG(bgp->flags,
1205 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1206 return 0;
1207 peer_sort_ret = 0;
d62a17ae 1208 }
1209 }
718e3744 1210
d62a17ae 1211 /* 11. Maximum path check. */
1212 if (newm == existm) {
1213 /* If one path has a label but the other does not, do not treat
1214 * them as equals for multipath
1215 */
a4d82a8a 1216 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1217 != (exist->extra
b57ba6d2 1218 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1219 if (debug)
1220 zlog_debug(
1221 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1222 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1223 } else if (CHECK_FLAG(bgp->flags,
1224 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1225
1226 /*
1227 * For the two paths, all comparison steps till IGP
1228 * metric
1229 * have succeeded - including AS_PATH hop count. Since
1230 * 'bgp
1231 * bestpath as-path multipath-relax' knob is on, we
1232 * don't need
1233 * an exact match of AS_PATH. Thus, mark the paths are
1234 * equal.
1235 * That will trigger both these paths to get into the
1236 * multipath
1237 * array.
1238 */
1239 *paths_eq = 1;
1240
1241 if (debug)
1242 zlog_debug(
1243 "%s: %s and %s are equal via multipath-relax",
1244 pfx_buf, new_buf, exist_buf);
1245 } else if (new->peer->sort == BGP_PEER_IBGP) {
1246 if (aspath_cmp(new->attr->aspath,
1247 exist->attr->aspath)) {
1248 *paths_eq = 1;
1249
1250 if (debug)
1251 zlog_debug(
1252 "%s: %s and %s are equal via matching aspaths",
1253 pfx_buf, new_buf, exist_buf);
1254 }
1255 } else if (new->peer->as == exist->peer->as) {
1256 *paths_eq = 1;
1257
1258 if (debug)
1259 zlog_debug(
1260 "%s: %s and %s are equal via same remote-as",
1261 pfx_buf, new_buf, exist_buf);
1262 }
1263 } else {
1264 /*
1265 * TODO: If unequal cost ibgp multipath is enabled we can
1266 * mark the paths as equal here instead of returning
1267 */
ee88563a
JM
1268
1269 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1270 * if either step 7 or 10 (peer type checks) yielded a winner,
1271 * that result was returned immediately. Returning from step 10
1272 * ignored the return value computed in steps 8 and 9 (IGP
1273 * metric checks). In order to preserve that behavior, if
1274 * peer_sort_ret is set, return that rather than igp_metric_ret.
1275 */
1276 ret = peer_sort_ret;
1277 if (peer_sort_ret < 0) {
1278 ret = igp_metric_ret;
1279 if (debug) {
1280 if (ret == 1)
1281 zlog_debug(
1282 "%s: %s wins over %s after IGP metric comparison",
1283 pfx_buf, new_buf, exist_buf);
1284 else
1285 zlog_debug(
1286 "%s: %s loses to %s after IGP metric comparison",
1287 pfx_buf, new_buf, exist_buf);
1288 }
1289 *reason = bgp_path_selection_igp_metric;
d62a17ae 1290 }
1291 return ret;
1292 }
718e3744 1293
ee88563a
JM
1294 /*
1295 * At this point, the decision whether to set *paths_eq = 1 has been
1296 * completed. If we deferred returning because of bestpath peer-type
1297 * relax configuration, return now.
1298 */
1299 if (peer_sort_ret >= 0)
1300 return peer_sort_ret;
1301
d62a17ae 1302 /* 12. If both paths are external, prefer the path that was received
1303 first (the oldest one). This step minimizes route-flap, since a
1304 newer path won't displace an older one, even if it was the
1305 preferred route based on the additional decision criteria below. */
892fedb6 1306 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1307 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1308 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1309 *reason = bgp_path_selection_older;
d62a17ae 1310 if (debug)
1311 zlog_debug(
1312 "%s: %s wins over %s due to oldest external",
1313 pfx_buf, new_buf, exist_buf);
1314 return 1;
1315 }
9fbdd100 1316
1defdda8 1317 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1318 *reason = bgp_path_selection_older;
d62a17ae 1319 if (debug)
1320 zlog_debug(
1321 "%s: %s loses to %s due to oldest external",
1322 pfx_buf, new_buf, exist_buf);
1323 return 0;
1324 }
1325 }
718e3744 1326
ce5002c6 1327 /* 13. Router-ID comparison. */
d62a17ae 1328 /* If one of the paths is "stale", the corresponding peer router-id will
1329 * be 0 and would always win over the other path. If originator id is
ce5002c6 1330 * used for the comparison, it will decide which path is better.
d62a17ae 1331 */
1332 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1333 new_id.s_addr = newattr->originator_id.s_addr;
1334 else
1335 new_id.s_addr = new->peer->remote_id.s_addr;
1336 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1337 exist_id.s_addr = existattr->originator_id.s_addr;
1338 else
1339 exist_id.s_addr = exist->peer->remote_id.s_addr;
1340
1341 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1342 *reason = bgp_path_selection_router_id;
d62a17ae 1343 if (debug)
1344 zlog_debug(
1345 "%s: %s wins over %s due to Router-ID comparison",
1346 pfx_buf, new_buf, exist_buf);
1347 return 1;
1348 }
718e3744 1349
d62a17ae 1350 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1351 *reason = bgp_path_selection_router_id;
d62a17ae 1352 if (debug)
1353 zlog_debug(
1354 "%s: %s loses to %s due to Router-ID comparison",
1355 pfx_buf, new_buf, exist_buf);
1356 return 0;
1357 }
9fbdd100 1358
ce5002c6 1359 /* 14. Cluster length comparison. */
d62a17ae 1360 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1361 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1362
1363 if (new_cluster < exist_cluster) {
fdf81fa0 1364 *reason = bgp_path_selection_cluster_length;
d62a17ae 1365 if (debug)
1366 zlog_debug(
1367 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1368 pfx_buf, new_buf, exist_buf, new_cluster,
1369 exist_cluster);
1370 return 1;
1371 }
718e3744 1372
d62a17ae 1373 if (new_cluster > exist_cluster) {
fdf81fa0 1374 *reason = bgp_path_selection_cluster_length;
d62a17ae 1375 if (debug)
1376 zlog_debug(
1377 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1378 pfx_buf, new_buf, exist_buf, new_cluster,
1379 exist_cluster);
1380 return 0;
1381 }
9fbdd100 1382
ce5002c6 1383 /* 15. Neighbor address comparison. */
d62a17ae 1384 /* Do this only if neither path is "stale" as stale paths do not have
1385 * valid peer information (as the connection may or may not be up).
1386 */
1defdda8 1387 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1388 *reason = bgp_path_selection_stale;
d62a17ae 1389 if (debug)
1390 zlog_debug(
1391 "%s: %s wins over %s due to latter path being STALE",
1392 pfx_buf, new_buf, exist_buf);
1393 return 1;
1394 }
0de5153c 1395
1defdda8 1396 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1397 *reason = bgp_path_selection_stale;
d62a17ae 1398 if (debug)
1399 zlog_debug(
1400 "%s: %s loses to %s due to former path being STALE",
1401 pfx_buf, new_buf, exist_buf);
1402 return 0;
1403 }
718e3744 1404
d62a17ae 1405 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1406 if (new->peer->su_remote == NULL) {
1407 *reason = bgp_path_selection_local_configured;
d62a17ae 1408 return 0;
fdf81fa0
DS
1409 }
1410 if (exist->peer->su_remote == NULL) {
1411 *reason = bgp_path_selection_local_configured;
d62a17ae 1412 return 1;
fdf81fa0 1413 }
9fbdd100 1414
d62a17ae 1415 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1416
1417 if (ret == 1) {
fdf81fa0 1418 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1419 if (debug)
1420 zlog_debug(
1421 "%s: %s loses to %s due to Neighor IP comparison",
1422 pfx_buf, new_buf, exist_buf);
1423 return 0;
1424 }
1425
1426 if (ret == -1) {
fdf81fa0 1427 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1428 if (debug)
1429 zlog_debug(
1430 "%s: %s wins over %s due to Neighor IP comparison",
1431 pfx_buf, new_buf, exist_buf);
1432 return 1;
1433 }
9fbdd100 1434
fdf81fa0 1435 *reason = bgp_path_selection_default;
d62a17ae 1436 if (debug)
1437 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1438 pfx_buf, new_buf, exist_buf);
718e3744 1439
d62a17ae 1440 return 1;
718e3744 1441}
1442
d071f237
AK
1443
1444int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1445 struct bgp_path_info *exist, int *paths_eq)
1446{
1447 enum bgp_path_selection_reason reason;
1448 char pfx_buf[PREFIX2STR_BUFFER];
1449
1450 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1451 AFI_L2VPN, SAFI_EVPN, &reason);
1452}
1453
65efcfce
LB
1454/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1455 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1456 * multipath is enabled
65efcfce 1457 * This version is compatible with */
18ee8310
DS
1458int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1459 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1460 afi_t afi, safi_t safi,
1461 enum bgp_path_selection_reason *reason)
d62a17ae 1462{
1463 int paths_eq;
1464 int ret;
18ee8310 1465 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1466 afi, safi, reason);
d62a17ae 1467
1468 if (paths_eq)
1469 ret = 0;
1470 else {
1471 if (ret == 1)
1472 ret = -1;
1473 else
1474 ret = 1;
1475 }
1476 return ret;
65efcfce
LB
1477}
1478
5a1ae2c2
DS
1479static enum filter_type bgp_input_filter(struct peer *peer,
1480 const struct prefix *p,
d62a17ae 1481 struct attr *attr, afi_t afi,
1482 safi_t safi)
718e3744 1483{
d62a17ae 1484 struct bgp_filter *filter;
6401252f 1485 enum filter_type ret = FILTER_PERMIT;
718e3744 1486
d62a17ae 1487 filter = &peer->filter[afi][safi];
718e3744 1488
d62a17ae 1489#define FILTER_EXIST_WARN(F, f, filter) \
1490 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1491 zlog_debug("%s: Could not find configured input %s-list %s!", \
1492 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1493
1494 if (DISTRIBUTE_IN_NAME(filter)) {
1495 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1496
6401252f
QY
1497 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1498 == FILTER_DENY) {
1499 ret = FILTER_DENY;
1500 goto done;
1501 }
d62a17ae 1502 }
1503
1504 if (PREFIX_LIST_IN_NAME(filter)) {
1505 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1506
6401252f
QY
1507 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1508 == PREFIX_DENY) {
1509 ret = FILTER_DENY;
1510 goto done;
1511 }
d62a17ae 1512 }
1513
1514 if (FILTER_LIST_IN_NAME(filter)) {
1515 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1516
1517 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1518 == AS_FILTER_DENY) {
1519 ret = FILTER_DENY;
1520 goto done;
1521 }
d62a17ae 1522 }
1523
6401252f 1524done:
c7bb4f00 1525 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1526 char pfxprint[PREFIX2STR_BUFFER];
1527
1528 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1529 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1530 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1531 }
1532
1533 return ret;
650f76c2 1534#undef FILTER_EXIST_WARN
718e3744 1535}
1536
b8685f9b
DS
1537static enum filter_type bgp_output_filter(struct peer *peer,
1538 const struct prefix *p,
d62a17ae 1539 struct attr *attr, afi_t afi,
1540 safi_t safi)
718e3744 1541{
d62a17ae 1542 struct bgp_filter *filter;
6401252f 1543 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1544
1545 filter = &peer->filter[afi][safi];
1546
1547#define FILTER_EXIST_WARN(F, f, filter) \
1548 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1549 zlog_debug("%s: Could not find configured output %s-list %s!", \
1550 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1551
d62a17ae 1552 if (DISTRIBUTE_OUT_NAME(filter)) {
1553 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1554
6401252f
QY
1555 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1556 == FILTER_DENY) {
1557 ret = FILTER_DENY;
1558 goto done;
1559 }
d62a17ae 1560 }
1561
1562 if (PREFIX_LIST_OUT_NAME(filter)) {
1563 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1564
d62a17ae 1565 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1566 == PREFIX_DENY) {
1567 ret = FILTER_DENY;
1568 goto done;
1569 }
d62a17ae 1570 }
718e3744 1571
d62a17ae 1572 if (FILTER_LIST_OUT_NAME(filter)) {
1573 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1574
d62a17ae 1575 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1576 == AS_FILTER_DENY) {
1577 ret = FILTER_DENY;
1578 goto done;
1579 }
1580 }
1581
c7bb4f00 1582 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1583 char pfxprint[PREFIX2STR_BUFFER];
1584
1585 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1586 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1587 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1588 }
718e3744 1589
6401252f
QY
1590done:
1591 return ret;
650f76c2 1592#undef FILTER_EXIST_WARN
718e3744 1593}
1594
1595/* If community attribute includes no_export then return 1. */
3dc339cd 1596static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1597{
9a706b42 1598 if (bgp_attr_get_community(attr)) {
d62a17ae 1599 /* NO_ADVERTISE check. */
9a706b42
DA
1600 if (community_include(bgp_attr_get_community(attr),
1601 COMMUNITY_NO_ADVERTISE))
3dc339cd 1602 return true;
d62a17ae 1603
1604 /* NO_EXPORT check. */
9a706b42
DA
1605 if (peer->sort == BGP_PEER_EBGP &&
1606 community_include(bgp_attr_get_community(attr),
1607 COMMUNITY_NO_EXPORT))
3dc339cd 1608 return true;
d62a17ae 1609
1610 /* NO_EXPORT_SUBCONFED check. */
1611 if (peer->sort == BGP_PEER_EBGP
1612 || peer->sort == BGP_PEER_CONFED)
9a706b42 1613 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1614 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1615 return true;
d62a17ae 1616 }
3dc339cd 1617 return false;
718e3744 1618}
1619
1620/* Route reflection loop check. */
3dc339cd 1621static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1622{
d62a17ae 1623 struct in_addr cluster_id;
779fee93 1624 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1625
779fee93 1626 if (cluster) {
d62a17ae 1627 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1628 cluster_id = peer->bgp->cluster_id;
1629 else
1630 cluster_id = peer->bgp->router_id;
1631
779fee93 1632 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1633 return true;
d62a17ae 1634 }
3dc339cd 1635 return false;
718e3744 1636}
6b0655a2 1637
d864dd9e
EB
1638static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1639{
1640 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1641 if (peer->local_role == ROLE_PROVIDER ||
1642 peer->local_role == ROLE_RS_SERVER)
1643 return true;
1644 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1645 return true;
1646 return false;
1647 }
1648 if (peer->local_role == ROLE_CUSTOMER ||
1649 peer->local_role == ROLE_PEER ||
1650 peer->local_role == ROLE_RS_CLIENT) {
1651 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1652 attr->otc = peer->as;
1653 }
1654 return false;
1655}
1656
1657static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1658{
1659 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1660 if (peer->local_role == ROLE_CUSTOMER ||
1661 peer->local_role == ROLE_RS_CLIENT ||
1662 peer->local_role == ROLE_PEER)
1663 return true;
1664 return false;
1665 }
1666 if (peer->local_role == ROLE_PROVIDER ||
1667 peer->local_role == ROLE_PEER ||
1668 peer->local_role == ROLE_RS_SERVER) {
1669 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1670 attr->otc = peer->bgp->as;
1671 }
1672 return false;
1673}
1674
5a78f2bc
EB
1675static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1676{
1677 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1678}
1679
5a1ae2c2 1680static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1681 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1682 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1683 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1684{
d62a17ae 1685 struct bgp_filter *filter;
82b692c0
LK
1686 struct bgp_path_info rmap_path = { 0 };
1687 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1688 route_map_result_t ret;
1689 struct route_map *rmap = NULL;
718e3744 1690
d62a17ae 1691 filter = &peer->filter[afi][safi];
718e3744 1692
d62a17ae 1693 /* Apply default weight value. */
1694 if (peer->weight[afi][safi])
1695 attr->weight = peer->weight[afi][safi];
718e3744 1696
d62a17ae 1697 if (rmap_name) {
1698 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1699
d62a17ae 1700 if (rmap == NULL)
1701 return RMAP_DENY;
1702 } else {
1703 if (ROUTE_MAP_IN_NAME(filter)) {
1704 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1705
d62a17ae 1706 if (rmap == NULL)
1707 return RMAP_DENY;
1708 }
1709 }
0b16f239 1710
d62a17ae 1711 /* Route map apply. */
1712 if (rmap) {
6006b807 1713 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1714 /* Duplicate current value to new structure for modification. */
40381db7
DS
1715 rmap_path.peer = peer;
1716 rmap_path.attr = attr;
82b692c0 1717 rmap_path.extra = &extra;
9bcb3eef 1718 rmap_path.net = dest;
196c6b09 1719
82b692c0
LK
1720 extra.num_labels = num_labels;
1721 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1722 memcpy(extra.label, label,
1723 num_labels * sizeof(mpls_label_t));
718e3744 1724
d62a17ae 1725 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1726
d62a17ae 1727 /* Apply BGP route map to the attribute. */
1782514f 1728 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1729
d62a17ae 1730 peer->rmap_type = 0;
0b16f239 1731
1f2263be 1732 if (ret == RMAP_DENYMATCH)
d62a17ae 1733 return RMAP_DENY;
0b16f239 1734 }
d62a17ae 1735 return RMAP_PERMIT;
0b16f239
DS
1736}
1737
5f040085 1738static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1739 struct attr *attr, afi_t afi, safi_t safi,
1740 const char *rmap_name)
0b16f239 1741{
40381db7 1742 struct bgp_path_info rmap_path;
d62a17ae 1743 route_map_result_t ret;
1744 struct route_map *rmap = NULL;
d7c0a89a 1745 uint8_t rmap_type;
0b16f239 1746
b787157a
DS
1747 /*
1748 * So if we get to this point and have no rmap_name
1749 * we want to just show the output as it currently
1750 * exists.
1751 */
1752 if (!rmap_name)
1753 return RMAP_PERMIT;
0b16f239 1754
d62a17ae 1755 /* Apply default weight value. */
1756 if (peer->weight[afi][safi])
1757 attr->weight = peer->weight[afi][safi];
0b16f239 1758
b787157a 1759 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1760
b787157a
DS
1761 /*
1762 * If we have a route map name and we do not find
1763 * the routemap that means we have an implicit
1764 * deny.
1765 */
1766 if (rmap == NULL)
1767 return RMAP_DENY;
0b16f239 1768
6006b807 1769 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1770 /* Route map apply. */
544be979 1771 /* Duplicate current value to new structure for modification. */
40381db7
DS
1772 rmap_path.peer = peer;
1773 rmap_path.attr = attr;
0b16f239 1774
0f672529 1775 rmap_type = peer->rmap_type;
b787157a 1776 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1777
b787157a 1778 /* Apply BGP route map to the attribute. */
1782514f 1779 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1780
0f672529 1781 peer->rmap_type = rmap_type;
b787157a
DS
1782
1783 if (ret == RMAP_DENYMATCH)
1784 /*
1785 * caller has multiple error paths with bgp_attr_flush()
1786 */
1787 return RMAP_DENY;
ac41b2a2 1788
d62a17ae 1789 return RMAP_PERMIT;
718e3744 1790}
6b0655a2 1791
5000f21c 1792/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1793static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1794 struct peer *peer, struct attr *attr)
1795{
1796 if (peer->sort == BGP_PEER_EBGP
1797 && (peer_af_flag_check(peer, afi, safi,
1798 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1799 || peer_af_flag_check(peer, afi, safi,
1800 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1801 || peer_af_flag_check(peer, afi, safi,
1802 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1803 || peer_af_flag_check(peer, afi, safi,
1804 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1805 // Take action on the entire aspath
1806 if (peer_af_flag_check(peer, afi, safi,
1807 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1808 || peer_af_flag_check(peer, afi, safi,
1809 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1810 if (peer_af_flag_check(
1811 peer, afi, safi,
1812 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1813 attr->aspath = aspath_replace_private_asns(
bf26b80e 1814 attr->aspath, bgp->as, peer->as);
d62a17ae 1815
179d5a0e
TA
1816 /*
1817 * Even if the aspath consists of just private ASNs we
1818 * need to walk the AS-Path to maintain all instances
1819 * of the peer's ASN to break possible loops.
1820 */
d62a17ae 1821 else
1822 attr->aspath = aspath_remove_private_asns(
bf26b80e 1823 attr->aspath, peer->as);
d62a17ae 1824 }
1825
1826 // 'all' was not specified so the entire aspath must be private
1827 // ASNs
1828 // for us to do anything
1829 else if (aspath_private_as_check(attr->aspath)) {
1830 if (peer_af_flag_check(
1831 peer, afi, safi,
1832 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1833 attr->aspath = aspath_replace_private_asns(
bf26b80e 1834 attr->aspath, bgp->as, peer->as);
d62a17ae 1835 else
179d5a0e
TA
1836 /*
1837 * Walk the aspath to retain any instances of
1838 * the peer_asn
1839 */
1840 attr->aspath = aspath_remove_private_asns(
1841 attr->aspath, peer->as);
d62a17ae 1842 }
1843 }
5000f21c
DS
1844}
1845
c7122e14 1846/* If this is an EBGP peer with as-override */
d62a17ae 1847static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1848 struct peer *peer, struct attr *attr)
1849{
bbe7bc46
DA
1850 struct aspath *aspath;
1851
9bbdb457 1852 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1853 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1854 if (attr->aspath->refcnt)
1855 aspath = aspath_dup(attr->aspath);
1856 else
1857 aspath = attr->aspath;
1858
1859 attr->aspath = aspath_intern(
1860 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1861
1862 aspath_free(aspath);
1863 }
d62a17ae 1864}
1865
1479ed2f
DA
1866void bgp_attr_add_llgr_community(struct attr *attr)
1867{
1868 struct community *old;
1869 struct community *new;
1870 struct community *merge;
1871 struct community *llgr;
1872
9a706b42 1873 old = bgp_attr_get_community(attr);
1479ed2f
DA
1874 llgr = community_str2com("llgr-stale");
1875
1876 assert(llgr);
1877
1878 if (old) {
1879 merge = community_merge(community_dup(old), llgr);
1880
1881 if (old->refcnt == 0)
1882 community_free(&old);
1883
1884 new = community_uniq_sort(merge);
1885 community_free(&merge);
1886 } else {
1887 new = community_dup(llgr);
1888 }
1889
1890 community_free(&llgr);
1891
9a706b42 1892 bgp_attr_set_community(attr, new);
1479ed2f
DA
1893}
1894
7f323236
DW
1895void bgp_attr_add_gshut_community(struct attr *attr)
1896{
1897 struct community *old;
1898 struct community *new;
1899 struct community *merge;
1900 struct community *gshut;
1901
9a706b42 1902 old = bgp_attr_get_community(attr);
7f323236
DW
1903 gshut = community_str2com("graceful-shutdown");
1904
990f4f91 1905 assert(gshut);
1906
7f323236
DW
1907 if (old) {
1908 merge = community_merge(community_dup(old), gshut);
1909
a4d82a8a 1910 if (old->refcnt == 0)
3c1f53de 1911 community_free(&old);
7f323236
DW
1912
1913 new = community_uniq_sort(merge);
3c1f53de 1914 community_free(&merge);
7f323236
DW
1915 } else {
1916 new = community_dup(gshut);
1917 }
1918
3c1f53de 1919 community_free(&gshut);
9a706b42 1920 bgp_attr_set_community(attr, new);
7f323236
DW
1921
1922 /* When we add the graceful-shutdown community we must also
1923 * lower the local-preference */
1924 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1925 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1926}
1927
1928
e73c112e
MK
1929/* Notify BGP Conditional advertisement scanner process. */
1930void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1931{
e73c112e 1932 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1933 afi_t afi = SUBGRP_AFI(subgrp);
1934 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1935 struct bgp_filter *filter = &peer->filter[afi][safi];
1936
1937 if (!ADVERTISE_MAP_NAME(filter))
1938 return;
1939
52979c3b
DS
1940 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1941 return;
e73c112e 1942
52979c3b 1943 peer->advmap_table_change = true;
e73c112e
MK
1944}
1945
1946
f2ee6d5c 1947void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1948{
960035b2 1949 if (family == AF_INET) {
975a328e
DA
1950 attr->nexthop.s_addr = INADDR_ANY;
1951 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1952 }
d62a17ae 1953 if (family == AF_INET6)
1954 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1955 if (family == AF_EVPN)
1956 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1957}
1958
9bcb3eef 1959bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1960 struct update_subgroup *subgrp,
7f7940e6 1961 const struct prefix *p, struct attr *attr,
51c3a7de 1962 struct attr *post_attr)
d62a17ae 1963{
1964 struct bgp_filter *filter;
1965 struct peer *from;
1966 struct peer *peer;
1967 struct peer *onlypeer;
1968 struct bgp *bgp;
40381db7 1969 struct attr *piattr;
b68885f9 1970 route_map_result_t ret;
d62a17ae 1971 int transparent;
1972 int reflect;
1973 afi_t afi;
1974 safi_t safi;
1975 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1976 bool nh_reset = false;
1977 uint64_t cum_bw;
d62a17ae 1978
1979 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1980 return false;
d62a17ae 1981
1982 afi = SUBGRP_AFI(subgrp);
1983 safi = SUBGRP_SAFI(subgrp);
1984 peer = SUBGRP_PEER(subgrp);
1985 onlypeer = NULL;
1986 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1987 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1988
40381db7 1989 from = pi->peer;
d62a17ae 1990 filter = &peer->filter[afi][safi];
1991 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1992 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1993 : pi->attr;
3f9c7369 1994
d0bf49ec
LS
1995 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1996 peer->pmax_out[afi][safi] != 0 &&
1997 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1998 if (BGP_DEBUG(update, UPDATE_OUT) ||
1999 BGP_DEBUG(update, UPDATE_PREFIX)) {
2000 zlog_debug("%s reached maximum prefix to be send (%u)",
2001 peer->host, peer->pmax_out[afi][safi]);
2002 }
2003 return false;
2004 }
2005
49e5a4a0 2006#ifdef ENABLE_BGP_VNC
d62a17ae 2007 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2008 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2009 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2010
2011 /*
2012 * direct and direct_ext type routes originate internally even
2013 * though they can have peer pointers that reference other
2014 * systems
2015 */
8228a9a7
DS
2016 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2017 __func__, p);
d62a17ae 2018 samepeer_safe = 1;
2019 }
65efcfce
LB
2020#endif
2021
ddb5b488
PZ
2022 if (((afi == AFI_IP) || (afi == AFI_IP6))
2023 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2024 && (pi->type == ZEBRA_ROUTE_BGP)
2025 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2026
2027 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2028
2029 samepeer_safe = 1;
2030 }
2031
d62a17ae 2032 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2033 * pi is valid */
2034 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2035 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2036 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2037 return false;
d62a17ae 2038 }
adbac85e 2039
d62a17ae 2040 /* If this is not the bestpath then check to see if there is an enabled
2041 * addpath
2042 * feature that requires us to advertise it */
8ccee4b8
DA
2043 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2044 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2045 return false;
06370dac 2046
d62a17ae 2047 /* Aggregate-address suppress check. */
4056a5f6
RZ
2048 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2049 return false;
3f9c7369 2050
13b7e7f0
DS
2051 /*
2052 * If we are doing VRF 2 VRF leaking via the import
2053 * statement, we want to prevent the route going
2054 * off box as that the RT and RD created are localy
2055 * significant and globaly useless.
2056 */
40381db7
DS
2057 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2058 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2059 return false;
13b7e7f0 2060
d62a17ae 2061 /* If it's labeled safi, make sure the route has a valid label. */
2062 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2063 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2064 if (!bgp_is_valid_label(&label)) {
2065 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2066 zlog_debug("u%" PRIu64 ":s%" PRIu64
2067 " %pFX is filtered - no label (%p)",
d62a17ae 2068 subgrp->update_group->id, subgrp->id,
8228a9a7 2069 p, &label);
3dc339cd 2070 return false;
d62a17ae 2071 }
2072 }
cd1964ff 2073
d62a17ae 2074 /* Do not send back route to sender. */
2075 if (onlypeer && from == onlypeer) {
3dc339cd 2076 return false;
d62a17ae 2077 }
3f9c7369 2078
d62a17ae 2079 /* Do not send the default route in the BGP table if the neighbor is
2080 * configured for default-originate */
2081 if (CHECK_FLAG(peer->af_flags[afi][safi],
2082 PEER_FLAG_DEFAULT_ORIGINATE)) {
2083 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2084 return false;
d62a17ae 2085 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2086 return false;
d62a17ae 2087 }
4125bb67 2088
d62a17ae 2089 /* Transparency check. */
2090 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2091 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2092 transparent = 1;
2093 else
2094 transparent = 0;
2095
2096 /* If community is not disabled check the no-export and local. */
40381db7 2097 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2098 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2099 zlog_debug("%s: community filter check fail for %pFX",
2100 __func__, p);
3dc339cd 2101 return false;
d62a17ae 2102 }
3f9c7369 2103
d62a17ae 2104 /* If the attribute has originator-id and it is same as remote
2105 peer's id. */
40381db7
DS
2106 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2107 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2108 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2109 zlog_debug(
a9f3f4f5
DA
2110 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2111 onlypeer, p);
3dc339cd 2112 return false;
d62a17ae 2113 }
3f9c7369 2114
d62a17ae 2115 /* ORF prefix-list filter check */
2116 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2117 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2118 || CHECK_FLAG(peer->af_cap[afi][safi],
2119 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2120 if (peer->orf_plist[afi][safi]) {
2121 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2122 == PREFIX_DENY) {
2123 if (bgp_debug_update(NULL, p,
2124 subgrp->update_group, 0))
2125 zlog_debug(
a9f3f4f5
DA
2126 "%pBP [Update:SEND] %pFX is filtered via ORF",
2127 peer, p);
3dc339cd 2128 return false;
d62a17ae 2129 }
2130 }
2131
2132 /* Output filter check. */
40381db7 2133 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2134 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2135 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2136 p);
3dc339cd 2137 return false;
d62a17ae 2138 }
3f9c7369 2139
d62a17ae 2140 /* AS path loop check. */
25851bf0
DA
2141 if (peer->as_path_loop_detection &&
2142 aspath_loop_check(piattr->aspath, peer->as)) {
d62a17ae 2143 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2144 zlog_debug(
a9f3f4f5 2145 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
25851bf0 2146 peer, peer->as);
3dc339cd 2147 return false;
d62a17ae 2148 }
3f9c7369 2149
d62a17ae 2150 /* If we're a CONFED we need to loop check the CONFED ID too */
2151 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2152 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2153 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2154 zlog_debug(
a9f3f4f5
DA
2155 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2156 peer, bgp->confed_id);
3dc339cd 2157 return false;
d62a17ae 2158 }
3f9c7369 2159 }
3f9c7369 2160
d62a17ae 2161 /* Route-Reflect check. */
2162 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2163 reflect = 1;
2164 else
2165 reflect = 0;
2166
2167 /* IBGP reflection check. */
2168 if (reflect && !samepeer_safe) {
2169 /* A route from a Client peer. */
2170 if (CHECK_FLAG(from->af_flags[afi][safi],
2171 PEER_FLAG_REFLECTOR_CLIENT)) {
2172 /* Reflect to all the Non-Client peers and also to the
2173 Client peers other than the originator. Originator
2174 check
2175 is already done. So there is noting to do. */
2176 /* no bgp client-to-client reflection check. */
892fedb6
DA
2177 if (CHECK_FLAG(bgp->flags,
2178 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2179 if (CHECK_FLAG(peer->af_flags[afi][safi],
2180 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2181 return false;
d62a17ae 2182 } else {
2183 /* A route from a Non-client peer. Reflect to all other
2184 clients. */
2185 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2186 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2187 return false;
d62a17ae 2188 }
2189 }
3f9c7369 2190
51c3a7de
DA
2191 /* For modify attribute, copy it to temporary structure.
2192 * post_attr comes from BGP conditional advertisements, where
2193 * attributes are already processed by advertise-map route-map,
2194 * and this needs to be saved instead of overwriting from the
2195 * path attributes.
2196 */
2197 if (post_attr)
2198 *attr = *post_attr;
2199 else
2200 *attr = *piattr;
d62a17ae 2201
2202 /* If local-preference is not set. */
2203 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2204 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2205 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2206 attr->local_pref = bgp->default_local_pref;
3f9c7369 2207 }
3f9c7369 2208
d62a17ae 2209 /* If originator-id is not set and the route is to be reflected,
2210 set the originator id */
2211 if (reflect
2212 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2213 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2214 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2215 }
3f9c7369 2216
d62a17ae 2217 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2218 */
2219 if (peer->sort == BGP_PEER_EBGP
2220 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2221 if (from != bgp->peer_self && !transparent
2222 && !CHECK_FLAG(peer->af_flags[afi][safi],
2223 PEER_FLAG_MED_UNCHANGED))
2224 attr->flag &=
2225 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2226 }
3f9c7369 2227
d62a17ae 2228 /* Since the nexthop attribute can vary per peer, it is not explicitly
2229 * set
2230 * in announce check, only certain flags and length (or number of
2231 * nexthops
2232 * -- for IPv6/MP_REACH) are set here in order to guide the update
2233 * formation
2234 * code in setting the nexthop(s) on a per peer basis in
2235 * reformat_peer().
2236 * Typically, the source nexthop in the attribute is preserved but in
2237 * the
2238 * scenarios where we know it will always be overwritten, we reset the
2239 * nexthop to "0" in an attempt to achieve better Update packing. An
2240 * example of this is when a prefix from each of 2 IBGP peers needs to
2241 * be
2242 * announced to an EBGP peer (and they have the same attributes barring
2243 * their nexthop).
2244 */
2245 if (reflect)
2246 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2247
2248#define NEXTHOP_IS_V6 \
2249 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2250 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2251 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2252 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2253
2254 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2255 * if
2256 * the peer (group) is configured to receive link-local nexthop
2257 * unchanged
c728d027
DA
2258 * and it is available in the prefix OR we're not reflecting the route,
2259 * link-local nexthop address is valid and
d62a17ae 2260 * the peer (group) to whom we're going to announce is on a shared
2261 * network
2262 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2263 * By checking if nexthop LL address is valid we are sure that
2264 * we do not announce LL address as `::`.
d62a17ae 2265 */
2266 if (NEXTHOP_IS_V6) {
2267 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2268 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2269 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2270 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2271 || (!reflect && !transparent
c728d027
DA
2272 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2273 && peer->shared_network
d62a17ae 2274 && (from == bgp->peer_self
2275 || peer->sort == BGP_PEER_EBGP))) {
f7a0eb6a
PG
2276 if (safi == SAFI_MPLS_VPN)
2277 attr->mp_nexthop_len =
2278 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2279 else
2280 attr->mp_nexthop_len =
2281 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 2282 }
3f9c7369 2283
d62a17ae 2284 /* Clear off link-local nexthop in source, whenever it is not
2285 * needed to
2286 * ensure more prefixes share the same attribute for
2287 * announcement.
2288 */
2289 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2290 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2291 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2292 }
3f9c7369 2293
5a78f2bc
EB
2294 if (bgp_check_role_applicability(afi, safi) &&
2295 bgp_otc_egress(peer, attr))
d864dd9e
EB
2296 return false;
2297
d62a17ae 2298 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2299 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2300
0655090c
QY
2301 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2302 filter->advmap.aname &&
2303 route_map_lookup_by_name(filter->advmap.aname)) {
2304 struct bgp_path_info rmap_path = {0};
2305 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2306 struct attr dummy_attr = *attr;
2307
2308 /* Fill temp path_info */
2309 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2310 pi, peer, &dummy_attr);
2311
2312 struct route_map *amap =
2313 route_map_lookup_by_name(filter->advmap.aname);
2314
2315 ret = route_map_apply(amap, p, &rmap_path);
2316
2317 bgp_attr_flush(&dummy_attr);
2318
2319 /*
2320 * The conditional advertisement mode is Withdraw and this
2321 * prefix is a conditional prefix. Don't advertise it
2322 */
2323 if (ret == RMAP_PERMITMATCH)
2324 return false;
2325 }
2326
d62a17ae 2327 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2328 if (!post_attr &&
2329 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2330 struct bgp_path_info rmap_path = {0};
2331 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2332 struct attr dummy_attr = {0};
d62a17ae 2333
e34291b8 2334 /* Fill temp path_info */
9bcb3eef
DS
2335 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2336 pi, peer, attr);
16f7ce2b 2337
d62a17ae 2338 /* don't confuse inbound and outbound setting */
2339 RESET_FLAG(attr->rmap_change_flags);
2340
2341 /*
2342 * The route reflector is not allowed to modify the attributes
2343 * of the reflected IBGP routes unless explicitly allowed.
2344 */
2345 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2346 && !CHECK_FLAG(bgp->flags,
2347 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2348 dummy_attr = *attr;
40381db7 2349 rmap_path.attr = &dummy_attr;
d62a17ae 2350 }
3f9c7369 2351
d62a17ae 2352 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2353
4056a5f6 2354 if (bgp_path_suppressed(pi))
d62a17ae 2355 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2356 &rmap_path);
d62a17ae 2357 else
2358 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2359 &rmap_path);
d62a17ae 2360
7e7639f5 2361 bgp_attr_flush(&dummy_attr);
d62a17ae 2362 peer->rmap_type = 0;
2363
2364 if (ret == RMAP_DENYMATCH) {
778048bf 2365 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2366 zlog_debug(
a9f3f4f5
DA
2367 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2368 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2369 bgp_attr_flush(rmap_path.attr);
3dc339cd 2370 return false;
d62a17ae 2371 }
3f9c7369 2372 }
3f9c7369 2373
9dac9fc8
DA
2374 /* RFC 8212 to prevent route leaks.
2375 * This specification intends to improve this situation by requiring the
2376 * explicit configuration of both BGP Import and Export Policies for any
2377 * External BGP (EBGP) session such as customers, peers, or
2378 * confederation boundaries for all enabled address families. Through
2379 * codification of the aforementioned requirement, operators will
2380 * benefit from consistent behavior across different BGP
2381 * implementations.
2382 */
1d3fdccf 2383 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2384 if (!bgp_outbound_policy_exists(peer, filter)) {
2385 if (monotime_since(&bgp->ebgprequirespolicywarning,
2386 NULL) > FIFTEENMINUTE2USEC ||
2387 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2388 zlog_warn(
2389 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2390 monotime(&bgp->ebgprequirespolicywarning);
2391 }
3dc339cd 2392 return false;
b17826b7 2393 }
9dac9fc8 2394
fb29348a
DA
2395 /* draft-ietf-idr-deprecate-as-set-confed-set
2396 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2397 * Eventually, This document (if approved) updates RFC 4271
2398 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2399 * and obsoletes RFC 6472.
2400 */
7f972cd8 2401 if (peer->bgp->reject_as_sets)
fb29348a 2402 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2403 return false;
fb29348a 2404
8c4d4624 2405 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2406 * SoO extended community and validate against the configured
2407 * one. If they match, do not announce, to prevent routing
2408 * loops.
2409 */
2410 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2411 peer->soo[afi][safi]) {
2412 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2413 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2414
2415 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2416 ECOMMUNITY_SITE_ORIGIN) ||
2417 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2418 ECOMMUNITY_SITE_ORIGIN) ||
2419 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2420 ECOMMUNITY_SITE_ORIGIN)) &&
2421 ecommunity_include(ecomm, ecomm_soo)) {
2422 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2423 zlog_debug(
2424 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2425 peer, p, ecommunity_str(ecomm_soo));
2426 return false;
2427 }
2428 }
2429
33d022bc
DA
2430 /* Codification of AS 0 Processing */
2431 if (aspath_check_as_zero(attr->aspath))
e2369003 2432 return false;
33d022bc 2433
637e5ba4 2434 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2435 if (peer->sort == BGP_PEER_IBGP
2436 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2437 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2438 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2439 } else {
2440 bgp_attr_add_gshut_community(attr);
2441 }
2442 }
2443
1479ed2f
DA
2444 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2445 * Capability" to a neighbor MUST perform the following upon receiving
2446 * a route from that neighbor with the "LLGR_STALE" community, or upon
2447 * attaching the "LLGR_STALE" community itself per Section 4.2:
2448 *
2449 * The route SHOULD NOT be advertised to any neighbor from which the
2450 * Long-lived Graceful Restart Capability has not been received.
2451 */
9a706b42
DA
2452 if (bgp_attr_get_community(attr) &&
2453 community_include(bgp_attr_get_community(attr),
2454 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2455 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2456 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2457 return false;
2458
d62a17ae 2459 /* After route-map has been applied, we check to see if the nexthop to
2460 * be carried in the attribute (that is used for the announcement) can
2461 * be cleared off or not. We do this in all cases where we would be
2462 * setting the nexthop to "ourselves". For IPv6, we only need to
2463 * consider
2464 * the global nexthop here; the link-local nexthop would have been
2465 * cleared
2466 * already, and if not, it is required by the update formation code.
2467 * Also see earlier comments in this function.
2468 */
2469 /*
2470 * If route-map has performed some operation on the nexthop or the peer
2471 * configuration says to pass it unchanged, we cannot reset the nexthop
2472 * here, so only attempt to do it if these aren't true. Note that the
2473 * route-map handler itself might have cleared the nexthop, if for
2474 * example,
2475 * it is configured as 'peer-address'.
2476 */
2477 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2478 piattr->rmap_change_flags)
d62a17ae 2479 && !transparent
2480 && !CHECK_FLAG(peer->af_flags[afi][safi],
2481 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2482 /* We can reset the nexthop, if setting (or forcing) it to
2483 * 'self' */
2484 if (CHECK_FLAG(peer->af_flags[afi][safi],
2485 PEER_FLAG_NEXTHOP_SELF)
2486 || CHECK_FLAG(peer->af_flags[afi][safi],
2487 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2488 if (!reflect
2489 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2490 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2491 subgroup_announce_reset_nhop(
2492 (peer_cap_enhe(peer, afi, safi)
2493 ? AF_INET6
2494 : p->family),
2495 attr);
7b651a32 2496 nh_reset = true;
2497 }
d62a17ae 2498 } else if (peer->sort == BGP_PEER_EBGP) {
2499 /* Can also reset the nexthop if announcing to EBGP, but
2500 * only if
2501 * no peer in the subgroup is on a shared subnet.
2502 * Note: 3rd party nexthop currently implemented for
2503 * IPv4 only.
2504 */
737af885
BS
2505 if ((p->family == AF_INET) &&
2506 (!bgp_subgrp_multiaccess_check_v4(
2507 piattr->nexthop,
7b651a32 2508 subgrp, from))) {
d62a17ae 2509 subgroup_announce_reset_nhop(
2510 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2511 ? AF_INET6
2512 : p->family),
737af885 2513 attr);
7b651a32 2514 nh_reset = true;
2515 }
737af885
BS
2516
2517 if ((p->family == AF_INET6) &&
2518 (!bgp_subgrp_multiaccess_check_v6(
2519 piattr->mp_nexthop_global,
7b651a32 2520 subgrp, from))) {
737af885
BS
2521 subgroup_announce_reset_nhop(
2522 (peer_cap_enhe(peer, afi, safi)
2523 ? AF_INET6
2524 : p->family),
2525 attr);
7b651a32 2526 nh_reset = true;
2527 }
737af885
BS
2528
2529
2530
40381db7 2531 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2532 /*
2533 * This flag is used for leaked vpn-vrf routes
2534 */
2535 int family = p->family;
2536
2537 if (peer_cap_enhe(peer, afi, safi))
2538 family = AF_INET6;
2539
2540 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2541 zlog_debug(
6cf8a4bf
DA
2542 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2543 __func__, p, family2str(family));
960035b2 2544 subgroup_announce_reset_nhop(family, attr);
7b651a32 2545 nh_reset = true;
d62a17ae 2546 }
63696f1d 2547 }
960035b2 2548
63696f1d 2549 /* If IPv6/MP and nexthop does not have any override and happens
2550 * to
2551 * be a link-local address, reset it so that we don't pass along
2552 * the
2553 * source's link-local IPv6 address to recipients who may not be
2554 * on
2555 * the same interface.
2556 */
2557 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2558 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2559 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2560 nh_reset = true;
2561 }
d62a17ae 2562 }
3f9c7369 2563
7b27cf7b
DA
2564 /* If this is an iBGP, send Origin Validation State (OVS)
2565 * extended community (rfc8097).
2566 */
2567 if (peer->sort == BGP_PEER_IBGP) {
2568 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2569
2570 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2571
2572 if (rpki_state != RPKI_NOT_BEING_USED)
2573 bgp_attr_set_ecommunity(
2574 attr, ecommunity_add_origin_validation_state(
2575 rpki_state,
2576 bgp_attr_get_ecommunity(attr)));
2577 }
2578
7b651a32 2579 /*
2580 * When the next hop is set to ourselves, if all multipaths have
2581 * link-bandwidth announce the cumulative bandwidth as that makes
2582 * the most sense. However, don't modify if the link-bandwidth has
2583 * been explicitly set by user policy.
2584 */
2585 if (nh_reset &&
f7e1c681 2586 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2587 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2588 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2589 bgp_attr_set_ecommunity(
2590 attr,
2591 ecommunity_replace_linkbw(
2592 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2593 CHECK_FLAG(
2594 peer->flags,
2595 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2596
3dc339cd 2597 return true;
3f9c7369
DS
2598}
2599
cc9f21da 2600static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2601{
2602 struct afi_safi_info *info;
2603 afi_t afi;
2604 safi_t safi;
2605 struct bgp *bgp;
2606
2607 info = THREAD_ARG(thread);
2608 afi = info->afi;
2609 safi = info->safi;
2610 bgp = info->bgp;
2611
f009ff26 2612 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2613 XFREE(MTYPE_TMP, info);
2614
2615 /* Best path selection */
cc9f21da 2616 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2617}
2618
9bcb3eef 2619void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2620 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2621 struct bgp_path_info_pair *result, afi_t afi,
2622 safi_t safi)
2623{
2624 struct bgp_path_info *new_select;
2625 struct bgp_path_info *old_select;
40381db7
DS
2626 struct bgp_path_info *pi;
2627 struct bgp_path_info *pi1;
2628 struct bgp_path_info *pi2;
2629 struct bgp_path_info *nextpi = NULL;
d62a17ae 2630 int paths_eq, do_mpath, debug;
2631 struct list mp_list;
2632 char pfx_buf[PREFIX2STR_BUFFER];
2633 char path_buf[PATH_ADDPATH_STR_BUFFER];
2634
2635 bgp_mp_list_init(&mp_list);
2636 do_mpath =
2637 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2638
9bcb3eef 2639 debug = bgp_debug_bestpath(dest);
d62a17ae 2640
2641 if (debug)
9bcb3eef 2642 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2643
9bcb3eef 2644 dest->reason = bgp_path_selection_none;
d62a17ae 2645 /* bgp deterministic-med */
2646 new_select = NULL;
892fedb6 2647 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2648
1defdda8 2649 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2650 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2651 pi1 = pi1->next)
9bcb3eef 2652 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2653 BGP_PATH_DMED_SELECTED);
d62a17ae 2654
9bcb3eef 2655 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2656 pi1 = pi1->next) {
40381db7 2657 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2658 continue;
40381db7 2659 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2660 continue;
ea8b2282 2661 if (pi1->peer != bgp->peer_self)
feb17238 2662 if (!peer_established(pi1->peer))
d62a17ae 2663 continue;
2664
40381db7
DS
2665 new_select = pi1;
2666 if (pi1->next) {
2667 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2668 if (CHECK_FLAG(pi2->flags,
1defdda8 2669 BGP_PATH_DMED_CHECK))
d62a17ae 2670 continue;
40381db7 2671 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2672 continue;
ea8b2282 2673 if (pi2->peer != bgp->peer_self
d62a17ae 2674 && !CHECK_FLAG(
ea8b2282
DS
2675 pi2->peer->sflags,
2676 PEER_STATUS_NSF_WAIT))
40381db7 2677 if (pi2->peer->status
d62a17ae 2678 != Established)
2679 continue;
2680
121e245d
DS
2681 if (!aspath_cmp_left(pi1->attr->aspath,
2682 pi2->attr->aspath)
2683 && !aspath_cmp_left_confed(
40381db7 2684 pi1->attr->aspath,
121e245d
DS
2685 pi2->attr->aspath))
2686 continue;
d62a17ae 2687
121e245d
DS
2688 if (bgp_path_info_cmp(
2689 bgp, pi2, new_select,
2690 &paths_eq, mpath_cfg, debug,
fdf81fa0 2691 pfx_buf, afi, safi,
9bcb3eef 2692 &dest->reason)) {
121e245d 2693 bgp_path_info_unset_flag(
9bcb3eef 2694 dest, new_select,
121e245d
DS
2695 BGP_PATH_DMED_SELECTED);
2696 new_select = pi2;
d62a17ae 2697 }
121e245d
DS
2698
2699 bgp_path_info_set_flag(
9bcb3eef 2700 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2701 }
2702 }
9bcb3eef 2703 bgp_path_info_set_flag(dest, new_select,
18ee8310 2704 BGP_PATH_DMED_CHECK);
9bcb3eef 2705 bgp_path_info_set_flag(dest, new_select,
18ee8310 2706 BGP_PATH_DMED_SELECTED);
d62a17ae 2707
2708 if (debug) {
18ee8310 2709 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2710 new_select, path_buf, sizeof(path_buf));
8228a9a7 2711 zlog_debug(
4378495a
DS
2712 "%pBD(%s): %s is the bestpath from AS %u",
2713 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2714 aspath_get_first_as(
2715 new_select->attr->aspath));
d62a17ae 2716 }
2717 }
2718 }
96450faf 2719
d62a17ae 2720 /* Check old selected route and new selected route. */
2721 old_select = NULL;
2722 new_select = NULL;
9bcb3eef 2723 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2724 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2725 enum bgp_path_selection_reason reason;
2726
40381db7
DS
2727 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2728 old_select = pi;
d62a17ae 2729
40381db7 2730 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2731 /* reap REMOVED routes, if needs be
2732 * selected route must stay for a while longer though
2733 */
40381db7
DS
2734 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2735 && (pi != old_select))
9bcb3eef 2736 bgp_path_info_reap(dest, pi);
d62a17ae 2737
ddb5b488 2738 if (debug)
40381db7
DS
2739 zlog_debug("%s: pi %p in holddown", __func__,
2740 pi);
ddb5b488 2741
d62a17ae 2742 continue;
2743 }
96450faf 2744
40381db7
DS
2745 if (pi->peer && pi->peer != bgp->peer_self
2746 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2747 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2748
2749 if (debug)
2750 zlog_debug(
40381db7
DS
2751 "%s: pi %p non self peer %s not estab state",
2752 __func__, pi, pi->peer->host);
ddb5b488 2753
d62a17ae 2754 continue;
ddb5b488 2755 }
9fbdd100 2756
892fedb6 2757 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2758 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2759 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2760 if (debug)
40381db7 2761 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2762 continue;
2763 }
9fbdd100 2764
9bcb3eef 2765 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2766
9bcb3eef 2767 reason = dest->reason;
40381db7 2768 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2769 debug, pfx_buf, afi, safi,
2770 &dest->reason)) {
19ea4cec
DS
2771 if (new_select == NULL &&
2772 reason != bgp_path_selection_none)
9bcb3eef 2773 dest->reason = reason;
40381db7 2774 new_select = pi;
d62a17ae 2775 }
2776 }
718e3744 2777
d62a17ae 2778 /* Now that we know which path is the bestpath see if any of the other
2779 * paths
2780 * qualify as multipaths
2781 */
2782 if (debug) {
2783 if (new_select)
7533cad7
QY
2784 bgp_path_info_path_with_addpath_rx_str(
2785 new_select, path_buf, sizeof(path_buf));
d62a17ae 2786 else
772270f3 2787 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2788 zlog_debug(
4378495a
DS
2789 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2790 dest, bgp->name_pretty, path_buf,
d62a17ae 2791 old_select ? old_select->peer->host : "NONE");
96450faf 2792 }
9fbdd100 2793
d62a17ae 2794 if (do_mpath && new_select) {
9bcb3eef 2795 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2796 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2797
2798 if (debug)
18ee8310 2799 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2800 pi, path_buf, sizeof(path_buf));
d62a17ae 2801
40381db7 2802 if (pi == new_select) {
d62a17ae 2803 if (debug)
2804 zlog_debug(
4378495a
DS
2805 "%pBD(%s): %s is the bestpath, add to the multipath list",
2806 dest, bgp->name_pretty,
2807 path_buf);
40381db7 2808 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2809 continue;
2810 }
2811
40381db7 2812 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2813 continue;
2814
40381db7
DS
2815 if (pi->peer && pi->peer != bgp->peer_self
2816 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2817 PEER_STATUS_NSF_WAIT))
feb17238 2818 if (!peer_established(pi->peer))
d62a17ae 2819 continue;
2820
40381db7 2821 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2822 if (debug)
2823 zlog_debug(
8228a9a7
DS
2824 "%pBD: %s has the same nexthop as the bestpath, skip it",
2825 dest, path_buf);
d62a17ae 2826 continue;
2827 }
2828
40381db7 2829 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2830 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2831 &dest->reason);
d62a17ae 2832
2833 if (paths_eq) {
2834 if (debug)
2835 zlog_debug(
8228a9a7
DS
2836 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2837 dest, path_buf);
40381db7 2838 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2839 }
2840 }
2841 }
fee0f4c6 2842
4378495a 2843 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2844 mpath_cfg);
2845 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2846 bgp_mp_list_clear(&mp_list);
96450faf 2847
9bcb3eef 2848 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2849
d62a17ae 2850 result->old = old_select;
2851 result->new = new_select;
96450faf 2852
d62a17ae 2853 return;
fee0f4c6 2854}
2855
3f9c7369
DS
2856/*
2857 * A new route/change in bestpath of an existing route. Evaluate the path
2858 * for advertisement to the subgroup.
2859 */
3dc339cd
DA
2860void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2861 struct bgp_path_info *selected,
9bcb3eef 2862 struct bgp_dest *dest,
3dc339cd 2863 uint32_t addpath_tx_id)
d62a17ae 2864{
b54892e0 2865 const struct prefix *p;
d62a17ae 2866 struct peer *onlypeer;
2867 struct attr attr;
2868 afi_t afi;
2869 safi_t safi;
a77e2f4b
S
2870 struct bgp *bgp;
2871 bool advertise;
adbac85e 2872
9bcb3eef 2873 p = bgp_dest_get_prefix(dest);
d62a17ae 2874 afi = SUBGRP_AFI(subgrp);
2875 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2876 bgp = SUBGRP_INST(subgrp);
d62a17ae 2877 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2878 : NULL);
2879
2dbe669b
DA
2880 if (BGP_DEBUG(update, UPDATE_OUT))
2881 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2882
d62a17ae 2883 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2884 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2885 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2886 return;
d62a17ae 2887
6006b807 2888 memset(&attr, 0, sizeof(attr));
d62a17ae 2889 /* It's initialized in bgp_announce_check() */
2890
a77e2f4b
S
2891 /* Announcement to the subgroup. If the route is filtered withdraw it.
2892 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2893 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2894 * route
d62a17ae 2895 */
a77e2f4b
S
2896 advertise = bgp_check_advertise(bgp, dest);
2897
d62a17ae 2898 if (selected) {
7f7940e6 2899 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2900 NULL)) {
a77e2f4b
S
2901 /* Route is selected, if the route is already installed
2902 * in FIB, then it is advertised
2903 */
be785e35
DS
2904 if (advertise) {
2905 if (!bgp_check_withdrawal(bgp, dest))
2906 bgp_adj_out_set_subgroup(
2907 dest, subgrp, &attr, selected);
2908 else
2909 bgp_adj_out_unset_subgroup(
2910 dest, subgrp, 1, addpath_tx_id);
2911 }
a77e2f4b 2912 } else
9bcb3eef 2913 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2914 addpath_tx_id);
d62a17ae 2915 }
2916
2917 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2918 else {
9bcb3eef 2919 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2920 }
200df115 2921}
fee0f4c6 2922
3064bf43 2923/*
e1072051 2924 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2925 * This is called at the end of route processing.
3064bf43 2926 */
9bcb3eef 2927void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2928{
40381db7 2929 struct bgp_path_info *pi;
3064bf43 2930
9bcb3eef 2931 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2932 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2933 continue;
40381db7
DS
2934 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2935 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2936 }
3064bf43 2937}
2938
2939/*
2940 * Has the route changed from the RIB's perspective? This is invoked only
2941 * if the route selection returns the same best route as earlier - to
2942 * determine if we need to update zebra or not.
2943 */
9bcb3eef 2944bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2945{
4b7e6066 2946 struct bgp_path_info *mpinfo;
d62a17ae 2947
2bb9eff4
DS
2948 /* If this is multipath, check all selected paths for any nexthop
2949 * change or attribute change. Some attribute changes (e.g., community)
2950 * aren't of relevance to the RIB, but we'll update zebra to ensure
2951 * we handle the case of BGP nexthop change. This is the behavior
2952 * when the best path has an attribute change anyway.
d62a17ae 2953 */
1defdda8 2954 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2955 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2956 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2957 return true;
d62a17ae 2958
2bb9eff4
DS
2959 /*
2960 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2961 */
18ee8310
DS
2962 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2963 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2964 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2965 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2966 return true;
d62a17ae 2967 }
3064bf43 2968
d62a17ae 2969 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2970 return false;
3064bf43 2971}
2972
d62a17ae 2973struct bgp_process_queue {
2974 struct bgp *bgp;
9bcb3eef 2975 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2976#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2977 unsigned int flags;
2978 unsigned int queued;
200df115 2979};
2980
3b0c17e1 2981static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2982 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2983 struct bgp_path_info *new_select,
2984 struct bgp_path_info *old_select)
2985{
9bcb3eef 2986 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2987
2988 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2989 return;
2990
2991 if (advertise_type5_routes(bgp, afi) && new_select
2992 && is_route_injectable_into_evpn(new_select)) {
2993
2994 /* apply the route-map */
2995 if (bgp->adv_cmd_rmap[afi][safi].map) {
2996 route_map_result_t ret;
2997 struct bgp_path_info rmap_path;
2998 struct bgp_path_info_extra rmap_path_extra;
2999 struct attr dummy_attr;
3000
3001 dummy_attr = *new_select->attr;
3002
3003 /* Fill temp path_info */
9bcb3eef 3004 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3005 new_select, new_select->peer,
3006 &dummy_attr);
3007
3008 RESET_FLAG(dummy_attr.rmap_change_flags);
3009
3010 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3011 p, &rmap_path);
3b0c17e1 3012
3013 if (ret == RMAP_DENYMATCH) {
3014 bgp_attr_flush(&dummy_attr);
3015 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3016 safi);
3017 } else
3018 bgp_evpn_advertise_type5_route(
3019 bgp, p, &dummy_attr, afi, safi);
3020 } else {
3021 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3022 afi, safi);
3023 }
3024 } else if (advertise_type5_routes(bgp, afi) && old_select
3025 && is_route_injectable_into_evpn(old_select))
3026 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3027}
3028
bb2ca692
MS
3029/*
3030 * Utility to determine whether a particular path_info should use
3031 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3032 * in a path where we basically _know_ this is a BGP-LU route.
3033 */
3034static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3035{
3036 /* Certain types get imp null; so do paths where the nexthop is
3037 * not labeled.
3038 */
3039 if (new_select->sub_type == BGP_ROUTE_STATIC
3040 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3041 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3042 return true;
3043 else if (new_select->extra == NULL ||
3044 !bgp_is_valid_label(&new_select->extra->label[0]))
3045 /* TODO -- should be configurable? */
3046 return true;
3047 else
3048 return false;
3049}
3050
3103e8d2
DS
3051/*
3052 * old_select = The old best path
3053 * new_select = the new best path
3054 *
3055 * if (!old_select && new_select)
3056 * We are sending new information on.
3057 *
3058 * if (old_select && new_select) {
3059 * if (new_select != old_select)
3060 * We have a new best path send a change
3061 * else
3062 * We've received a update with new attributes that needs
3063 * to be passed on.
3064 * }
3065 *
3066 * if (old_select && !new_select)
3067 * We have no eligible route that we can announce or the rn
3068 * is being removed.
3069 */
9bcb3eef 3070static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3071 afi_t afi, safi_t safi)
d62a17ae 3072{
4b7e6066
DS
3073 struct bgp_path_info *new_select;
3074 struct bgp_path_info *old_select;
3075 struct bgp_path_info_pair old_and_new;
ddb5b488 3076 int debug = 0;
d62a17ae 3077
892fedb6 3078 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3079 if (dest)
3080 debug = bgp_debug_bestpath(dest);
b54892e0 3081 if (debug)
f4c713ae 3082 zlog_debug(
56ca3b5b 3083 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3084 __func__, dest);
f4c713ae
LB
3085 return;
3086 }
d62a17ae 3087 /* Is it end of initial update? (after startup) */
9bcb3eef 3088 if (!dest) {
e36f61b5
DS
3089 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3090 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3091
3092 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3093 FOREACH_AFI_SAFI (afi, safi) {
3094 if (bgp_fibupd_safi(safi))
3095 bgp_zebra_announce_table(bgp, afi, safi);
3096 }
d62a17ae 3097 bgp->main_peers_update_hold = 0;
3098
3099 bgp_start_routeadv(bgp);
aac24838 3100 return;
d62a17ae 3101 }
cb1faec9 3102
9bcb3eef 3103 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3104
9bcb3eef 3105 debug = bgp_debug_bestpath(dest);
b54892e0 3106 if (debug)
4378495a
DS
3107 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3108 dest, bgp->name_pretty, afi2str(afi),
3109 safi2str(safi));
ddb5b488 3110
f009ff26 3111 /* The best path calculation for the route is deferred if
3112 * BGP_NODE_SELECT_DEFER is set
3113 */
9bcb3eef 3114 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3115 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3116 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3117 return;
3118 }
3119
d62a17ae 3120 /* Best path selection. */
9bcb3eef 3121 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3122 afi, safi);
3123 old_select = old_and_new.old;
3124 new_select = old_and_new.new;
3125
3126 /* Do we need to allocate or free labels?
3127 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3128 * necessary to do this upon changes to best path. Exceptions:
3129 * - label index has changed -> recalculate resulting label
3130 * - path_info sub_type changed -> switch to/from implicit-null
3131 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3132 */
318cac96 3133 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3134 if (new_select) {
3135 if (!old_select
3136 || bgp_label_index_differs(new_select, old_select)
57592a53 3137 || new_select->sub_type != old_select->sub_type
9bcb3eef 3138 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3139 /* Enforced penultimate hop popping:
3140 * implicit-null for local routes, aggregate
3141 * and redistributed routes
3142 */
bb2ca692 3143 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3144 if (CHECK_FLAG(
9bcb3eef 3145 dest->flags,
992dd67e
PR
3146 BGP_NODE_REGISTERED_FOR_LABEL)
3147 || CHECK_FLAG(
3148 dest->flags,
3149 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3150 bgp_unregister_for_label(dest);
67f67ba4
DA
3151 dest->local_label = mpls_lse_encode(
3152 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3153 1);
9bcb3eef 3154 bgp_set_valid_label(&dest->local_label);
d62a17ae 3155 } else
9bcb3eef
DS
3156 bgp_register_for_label(dest,
3157 new_select);
d62a17ae 3158 }
9bcb3eef 3159 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3160 BGP_NODE_REGISTERED_FOR_LABEL)
3161 || CHECK_FLAG(dest->flags,
3162 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3163 bgp_unregister_for_label(dest);
318cac96 3164 }
992dd67e
PR
3165 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3166 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3167 bgp_unregister_for_label(dest);
d62a17ae 3168 }
cd1964ff 3169
b54892e0 3170 if (debug)
ddb5b488 3171 zlog_debug(
4378495a
DS
3172 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3173 __func__, dest, bgp->name_pretty, afi2str(afi),
3174 safi2str(safi), old_select, new_select);
ddb5b488 3175
d62a17ae 3176 /* If best route remains the same and this is not due to user-initiated
3177 * clear, see exactly what needs to be done.
3178 */
d62a17ae 3179 if (old_select && old_select == new_select
9bcb3eef 3180 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3181 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3182 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3183 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3184#ifdef ENABLE_BGP_VNC
d62a17ae 3185 vnc_import_bgp_add_route(bgp, p, old_select);
3186 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3187#endif
bb744275 3188 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3189 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3190
be785e35
DS
3191 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3192 && new_select->sub_type == BGP_ROUTE_NORMAL)
3193 SET_FLAG(dest->flags,
3194 BGP_NODE_FIB_INSTALL_PENDING);
3195
ddb5b488
PZ
3196 if (new_select->type == ZEBRA_ROUTE_BGP
3197 && (new_select->sub_type == BGP_ROUTE_NORMAL
3198 || new_select->sub_type
3199 == BGP_ROUTE_IMPORTED))
3200
9bcb3eef 3201 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3202 bgp, afi, safi);
3203 }
d62a17ae 3204 }
d62a17ae 3205
3206 /* If there is a change of interest to peers, reannounce the
3207 * route. */
1defdda8 3208 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3209 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3210 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3211 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3212
3213 /* unicast routes must also be annouced to
3214 * labeled-unicast update-groups */
3215 if (safi == SAFI_UNICAST)
3216 group_announce_route(bgp, afi,
9bcb3eef 3217 SAFI_LABELED_UNICAST, dest,
d62a17ae 3218 new_select);
3219
1defdda8 3220 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3221 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3222 }
fee0f4c6 3223
3b0c17e1 3224 /* advertise/withdraw type-5 routes */
3225 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3226 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3227 bgp_process_evpn_route_injection(
9bcb3eef 3228 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3229
b1875e65 3230 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3231 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3232 bgp_zebra_clear_route_change_flags(dest);
3233 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3234 return;
d62a17ae 3235 }
8ad7271d 3236
d62a17ae 3237 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3238 */
9bcb3eef 3239 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3240
3241 /* bestpath has changed; bump version */
3242 if (old_select || new_select) {
9bcb3eef 3243 bgp_bump_version(dest);
d62a17ae 3244
3245 if (!bgp->t_rmap_def_originate_eval) {
3246 bgp_lock(bgp);
3247 thread_add_timer(
3248 bm->master,
3249 update_group_refresh_default_originate_route_map,
3250 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3251 &bgp->t_rmap_def_originate_eval);
3252 }
3253 }
3f9c7369 3254
d62a17ae 3255 if (old_select)
9bcb3eef 3256 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3257 if (new_select) {
ddb5b488
PZ
3258 if (debug)
3259 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3260 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3261 bgp_path_info_unset_flag(dest, new_select,
3262 BGP_PATH_ATTR_CHANGED);
1defdda8 3263 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3264 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3265 }
338b3424 3266
49e5a4a0 3267#ifdef ENABLE_BGP_VNC
d62a17ae 3268 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3269 if (old_select != new_select) {
3270 if (old_select) {
3271 vnc_import_bgp_exterior_del_route(bgp, p,
3272 old_select);
3273 vnc_import_bgp_del_route(bgp, p, old_select);
3274 }
3275 if (new_select) {
3276 vnc_import_bgp_exterior_add_route(bgp, p,
3277 new_select);
3278 vnc_import_bgp_add_route(bgp, p, new_select);
3279 }
3280 }
3281 }
65efcfce
LB
3282#endif
3283
9bcb3eef 3284 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3285
3286 /* unicast routes must also be annouced to labeled-unicast update-groups
3287 */
3288 if (safi == SAFI_UNICAST)
9bcb3eef 3289 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3290 new_select);
3291
3292 /* FIB update. */
3293 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3294 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3295
d62a17ae 3296 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3297 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3298 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3299 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3300
be785e35
DS
3301 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3302 SET_FLAG(dest->flags,
3303 BGP_NODE_FIB_INSTALL_PENDING);
3304
2b659f33
MK
3305 /* if this is an evpn imported type-5 prefix,
3306 * we need to withdraw the route first to clear
3307 * the nh neigh and the RMAC entry.
3308 */
3309 if (old_select &&
3310 is_route_parent_evpn(old_select))
3311 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3312
9bcb3eef 3313 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3314 } else {
d62a17ae 3315 /* Withdraw the route from the kernel. */
3316 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3317 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3318 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3319 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3320
568e10ca 3321 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3322 }
718e3744 3323 }
3064bf43 3324
9bcb3eef 3325 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3326 old_select);
5424b7ba 3327
d62a17ae 3328 /* Clear any route change flags. */
9bcb3eef 3329 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3330
18ee8310 3331 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3332 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3333 bgp_path_info_reap(dest, old_select);
d62a17ae 3334
9bcb3eef 3335 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3336 return;
718e3744 3337}
3338
f009ff26 3339/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3340void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3341{
9bcb3eef 3342 struct bgp_dest *dest;
f009ff26 3343 int cnt = 0;
3344 struct afi_safi_info *thread_info;
f009ff26 3345
56c226e7
DS
3346 if (bgp->gr_info[afi][safi].t_route_select) {
3347 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3348
3349 thread_info = THREAD_ARG(t);
3350 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3351 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3352 }
f009ff26 3353
3354 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3355 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3356 get_afi_safi_str(afi, safi, false),
26742171 3357 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3358 }
3359
3360 /* Process the route list */
6338d242 3361 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3362 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3363 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3364 dest = bgp_route_next(dest)) {
3365 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3366 continue;
3367
3368 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3369 bgp->gr_info[afi][safi].gr_deferred--;
3370 bgp_process_main_one(bgp, dest, afi, safi);
3371 cnt++;
067ea165
CB
3372 }
3373 /* If iteration stopped before the entire table was traversed then the
3374 * node needs to be unlocked.
3375 */
3376 if (dest) {
3377 bgp_dest_unlock_node(dest);
3378 dest = NULL;
f009ff26 3379 }
3380
9e3b51a7 3381 /* Send EOR message when all routes are processed */
6338d242 3382 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3383 bgp_send_delayed_eor(bgp);
8c48b3b6 3384 /* Send route processing complete message to RIB */
3385 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3386 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3387 return;
9e3b51a7 3388 }
f009ff26 3389
3390 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3391
3392 thread_info->afi = afi;
3393 thread_info->safi = safi;
3394 thread_info->bgp = bgp;
3395
3396 /* If there are more routes to be processed, start the
3397 * selection timer
3398 */
3399 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3400 BGP_ROUTE_SELECT_DELAY,
3401 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3402}
3403
aac24838 3404static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3405{
aac24838
JB
3406 struct bgp_process_queue *pqnode = data;
3407 struct bgp *bgp = pqnode->bgp;
d62a17ae 3408 struct bgp_table *table;
9bcb3eef 3409 struct bgp_dest *dest;
aac24838
JB
3410
3411 /* eoiu marker */
3412 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3413 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3414 /* should always have dedicated wq call */
3415 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3416 return WQ_SUCCESS;
3417 }
3418
ac021f40 3419 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3420 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3421 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3422 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3423 table = bgp_dest_table(dest);
3424 /* note, new DESTs may be added as part of processing */
3425 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3426
9bcb3eef 3427 bgp_dest_unlock_node(dest);
d62a17ae 3428 bgp_table_unlock(table);
3429 }
aac24838
JB
3430
3431 return WQ_SUCCESS;
3432}
3433
3434static void bgp_processq_del(struct work_queue *wq, void *data)
3435{
3436 struct bgp_process_queue *pqnode = data;
3437
3438 bgp_unlock(pqnode->bgp);
3439
3440 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3441}
3442
b6c386bb 3443void bgp_process_queue_init(struct bgp *bgp)
200df115 3444{
b6c386bb
DS
3445 if (!bgp->process_queue) {
3446 char name[BUFSIZ];
3447
3448 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3449 bgp->process_queue = work_queue_new(bm->master, name);
3450 }
3451
3452 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3453 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3454 bgp->process_queue->spec.max_retries = 0;
3455 bgp->process_queue->spec.hold = 50;
d62a17ae 3456 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3457 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3458}
3459
cfe8d15a 3460static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3461{
3462 struct bgp_process_queue *pqnode;
3463
a4d82a8a
PZ
3464 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3465 sizeof(struct bgp_process_queue));
aac24838
JB
3466
3467 /* unlocked in bgp_processq_del */
3468 pqnode->bgp = bgp_lock(bgp);
3469 STAILQ_INIT(&pqnode->pqueue);
3470
aac24838
JB
3471 return pqnode;
3472}
3473
9bcb3eef 3474void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3475{
aac24838 3476#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3477 struct work_queue *wq = bgp->process_queue;
d62a17ae 3478 struct bgp_process_queue *pqnode;
cfe8d15a 3479 int pqnode_reuse = 0;
495f0b13 3480
d62a17ae 3481 /* already scheduled for processing? */
9bcb3eef 3482 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3483 return;
2e02b9b2 3484
f009ff26 3485 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3486 * the workqueue
3487 */
9bcb3eef 3488 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3489 if (BGP_DEBUG(update, UPDATE_OUT))
3490 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3491 dest);
f009ff26 3492 return;
3493 }
3494
46aeabed
LS
3495 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3496 if (BGP_DEBUG(update, UPDATE_OUT))
3497 zlog_debug(
3498 "Soft reconfigure table in progress for route %p",
3499 dest);
3500 return;
3501 }
3502
aac24838 3503 if (wq == NULL)
d62a17ae 3504 return;
3505
aac24838 3506 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3507 limit only if is from the same BGP view and it's not an EOIU marker
3508 */
aac24838
JB
3509 if (work_queue_item_count(wq)) {
3510 struct work_queue_item *item = work_queue_last_item(wq);
3511 pqnode = item->data;
228da428 3512
a4d82a8a
PZ
3513 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3514 || pqnode->bgp != bgp
3515 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3516 pqnode = bgp_processq_alloc(bgp);
3517 else
3518 pqnode_reuse = 1;
aac24838 3519 } else
cfe8d15a 3520 pqnode = bgp_processq_alloc(bgp);
aac24838 3521 /* all unlocked in bgp_process_wq */
9bcb3eef 3522 bgp_table_lock(bgp_dest_table(dest));
aac24838 3523
9bcb3eef
DS
3524 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3525 bgp_dest_lock_node(dest);
aac24838 3526
60466a63 3527 /* can't be enqueued twice */
9bcb3eef
DS
3528 assert(STAILQ_NEXT(dest, pq) == NULL);
3529 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3530 pqnode->queued++;
3531
cfe8d15a
LB
3532 if (!pqnode_reuse)
3533 work_queue_add(wq, pqnode);
3534
d62a17ae 3535 return;
fee0f4c6 3536}
0a486e5f 3537
d62a17ae 3538void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3539{
d62a17ae 3540 struct bgp_process_queue *pqnode;
cb1faec9 3541
b6c386bb 3542 if (bgp->process_queue == NULL)
d62a17ae 3543 return;
2e02b9b2 3544
cfe8d15a 3545 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3546
aac24838 3547 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3548 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3549}
3550
cc9f21da 3551static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3552{
d62a17ae 3553 struct peer *peer;
0a486e5f 3554
d62a17ae 3555 peer = THREAD_ARG(thread);
3556 peer->t_pmax_restart = NULL;
0a486e5f 3557
d62a17ae 3558 if (bgp_debug_neighbor_events(peer))
3559 zlog_debug(
3560 "%s Maximum-prefix restart timer expired, restore peering",
3561 peer->host);
0a486e5f 3562
a9bafa95 3563 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3564 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3565}
3566
9cbd06e0
DA
3567static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3568 safi_t safi)
3569{
3570 uint32_t count = 0;
f41b0459 3571 bool filtered = false;
9cbd06e0
DA
3572 struct bgp_dest *dest;
3573 struct bgp_adj_in *ain;
40bb2ccf 3574 struct attr attr = {};
9cbd06e0
DA
3575 struct bgp_table *table = peer->bgp->rib[afi][safi];
3576
3577 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3578 for (ain = dest->adj_in; ain; ain = ain->next) {
3579 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3580
3581 attr = *ain->attr;
9cbd06e0
DA
3582
3583 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3584 == FILTER_DENY)
f41b0459
DA
3585 filtered = true;
3586
3587 if (bgp_input_modifier(
3588 peer, rn_p, &attr, afi, safi,
3589 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3590 NULL, 0, NULL)
3591 == RMAP_DENY)
3592 filtered = true;
3593
3594 if (filtered)
9cbd06e0 3595 count++;
f41b0459 3596
d498917e 3597 bgp_attr_flush(&attr);
9cbd06e0
DA
3598 }
3599 }
3600
3601 return count;
3602}
3603
3dc339cd
DA
3604bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3605 int always)
718e3744 3606{
d62a17ae 3607 iana_afi_t pkt_afi;
5c525538 3608 iana_safi_t pkt_safi;
9cbd06e0
DA
3609 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3610 PEER_FLAG_MAX_PREFIX_FORCE))
3611 ? bgp_filtered_routes_count(peer, afi, safi)
3612 + peer->pcount[afi][safi]
3613 : peer->pcount[afi][safi];
9cabb64b 3614
d62a17ae 3615 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3616 return false;
e0701b79 3617
9cbd06e0 3618 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3619 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3620 PEER_STATUS_PREFIX_LIMIT)
3621 && !always)
3dc339cd 3622 return false;
e0701b79 3623
d62a17ae 3624 zlog_info(
f70c91dc
DA
3625 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3626 get_afi_safi_str(afi, safi, false), peer, pcount,
3627 peer->pmax[afi][safi]);
d62a17ae 3628 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3629
3630 if (CHECK_FLAG(peer->af_flags[afi][safi],
3631 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3632 return false;
d62a17ae 3633
3634 /* Convert AFI, SAFI to values for packet. */
3635 pkt_afi = afi_int2iana(afi);
3636 pkt_safi = safi_int2iana(safi);
3637 {
d7c0a89a 3638 uint8_t ndata[7];
d62a17ae 3639
3640 ndata[0] = (pkt_afi >> 8);
3641 ndata[1] = pkt_afi;
3642 ndata[2] = pkt_safi;
3643 ndata[3] = (peer->pmax[afi][safi] >> 24);
3644 ndata[4] = (peer->pmax[afi][safi] >> 16);
3645 ndata[5] = (peer->pmax[afi][safi] >> 8);
3646 ndata[6] = (peer->pmax[afi][safi]);
3647
3648 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3649 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3650 BGP_NOTIFY_CEASE_MAX_PREFIX,
3651 ndata, 7);
3652 }
3653
3654 /* Dynamic peers will just close their connection. */
3655 if (peer_dynamic_neighbor(peer))
3dc339cd 3656 return true;
d62a17ae 3657
3658 /* restart timer start */
3659 if (peer->pmax_restart[afi][safi]) {
3660 peer->v_pmax_restart =
3661 peer->pmax_restart[afi][safi] * 60;
3662
3663 if (bgp_debug_neighbor_events(peer))
3664 zlog_debug(
f70c91dc
DA
3665 "%pBP Maximum-prefix restart timer started for %d secs",
3666 peer, peer->v_pmax_restart);
d62a17ae 3667
3668 BGP_TIMER_ON(peer->t_pmax_restart,
3669 bgp_maximum_prefix_restart_timer,
3670 peer->v_pmax_restart);
3671 }
3672
3dc339cd 3673 return true;
d62a17ae 3674 } else
3675 UNSET_FLAG(peer->af_sflags[afi][safi],
3676 PEER_STATUS_PREFIX_LIMIT);
3677
b1823b69
DS
3678 if (pcount
3679 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3680 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3681 PEER_STATUS_PREFIX_THRESHOLD)
3682 && !always)
3dc339cd 3683 return false;
d62a17ae 3684
3685 zlog_info(
f70c91dc
DA
3686 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3687 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3688 peer->pmax[afi][safi]);
d62a17ae 3689 SET_FLAG(peer->af_sflags[afi][safi],
3690 PEER_STATUS_PREFIX_THRESHOLD);
3691 } else
3692 UNSET_FLAG(peer->af_sflags[afi][safi],
3693 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3694 return false;
718e3744 3695}
3696
b40d939b 3697/* Unconditionally remove the route from the RIB, without taking
3698 * damping into consideration (eg, because the session went down)
3699 */
9bcb3eef 3700void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3701 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3702{
f009ff26 3703
3704 struct bgp *bgp = NULL;
3705 bool delete_route = false;
3706
9bcb3eef
DS
3707 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3708 safi);
d62a17ae 3709
f009ff26 3710 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3711 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3712
f009ff26 3713 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3714 * flag
3715 */
3716 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3717 delete_route = true;
9bcb3eef 3718 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3719 delete_route = true;
f009ff26 3720 if (delete_route) {
9bcb3eef
DS
3721 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3722 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3723 bgp = pi->peer->bgp;
26742171 3724 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3725 }
3726 }
3727 }
4a11bf2c 3728
9bcb3eef
DS
3729 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3730 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3731}
3732
9bcb3eef 3733static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3734 struct peer *peer, afi_t afi, safi_t safi,
3735 struct prefix_rd *prd)
3736{
9bcb3eef 3737 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3738
d62a17ae 3739 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3740 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3741 */
b4f7f45b
IR
3742 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3743 && peer->sort == BGP_PEER_EBGP)
3744 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3745 == BGP_DAMP_SUPPRESSED) {
3746 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3747 safi);
3748 return;
d62a17ae 3749 }
3750
49e5a4a0 3751#ifdef ENABLE_BGP_VNC
d62a17ae 3752 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3753 struct bgp_dest *pdest = NULL;
d62a17ae 3754 struct bgp_table *table = NULL;
3755
9bcb3eef
DS
3756 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3757 (struct prefix *)prd);
3758 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3759 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3760
3761 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3762 peer->bgp, prd, table, p, pi);
d62a17ae 3763 }
9bcb3eef 3764 bgp_dest_unlock_node(pdest);
d62a17ae 3765 }
3766 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3767 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3768
b54892e0
DS
3769 vnc_import_bgp_del_route(peer->bgp, p, pi);
3770 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3771 }
65efcfce 3772 }
d62a17ae 3773#endif
128ea8ab 3774
d62a17ae 3775 /* If this is an EVPN route, process for un-import. */
3776 if (safi == SAFI_EVPN)
b54892e0 3777 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3778
9bcb3eef 3779 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3780}
3781
4b7e6066
DS
3782struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3783 struct peer *peer, struct attr *attr,
9bcb3eef 3784 struct bgp_dest *dest)
fb018d25 3785{
4b7e6066 3786 struct bgp_path_info *new;
fb018d25 3787
d62a17ae 3788 /* Make new BGP info. */
4b7e6066 3789 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3790 new->type = type;
3791 new->instance = instance;
3792 new->sub_type = sub_type;
3793 new->peer = peer;
3794 new->attr = attr;
083ec940 3795 new->uptime = monotime(NULL);
9bcb3eef 3796 new->net = dest;
d62a17ae 3797 return new;
fb018d25
DS
3798}
3799
c265ee22 3800/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3801bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3802 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3803 struct bgp_dest *dest)
d62a17ae 3804{
2dbe3fa9 3805 bool ret = false;
b099a5c8
DA
3806 bool is_bgp_static_route =
3807 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3808 : false;
d62a17ae 3809
e8442016
DS
3810 /*
3811 * Only validated for unicast and multicast currently.
3812 * Also valid for EVPN where the nexthop is an IP address.
3813 * If we are a bgp static route being checked then there is
3814 * no need to check to see if the nexthop is martian as
3815 * that it should be ok.
3816 */
3817 if (is_bgp_static_route ||
3818 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3819 return false;
d62a17ae 3820
3821 /* If NEXT_HOP is present, validate it. */
3822 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3823 if (attr->nexthop.s_addr == INADDR_ANY ||
3824 !ipv4_unicast_valid(&attr->nexthop) ||
3825 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3826 return true;
d62a17ae 3827 }
c265ee22 3828
d62a17ae 3829 /* If MP_NEXTHOP is present, validate it. */
3830 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3831 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3832 * it is not an IPv6 link-local address.
0355b41d
DA
3833 *
3834 * If we receive an UPDATE with nexthop length set to 32 bytes
3835 * we shouldn't discard an UPDATE if it's set to (::).
3836 * The link-local (2st) is validated along the code path later.
d62a17ae 3837 */
3838 if (attr->mp_nexthop_len) {
3839 switch (attr->mp_nexthop_len) {
3840 case BGP_ATTR_NHLEN_IPV4:
3841 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3842 ret = (attr->mp_nexthop_global_in.s_addr ==
3843 INADDR_ANY ||
3844 !ipv4_unicast_valid(
3845 &attr->mp_nexthop_global_in) ||
3846 bgp_nexthop_self(bgp, afi, type, stype, attr,
3847 dest));
d62a17ae 3848 break;
3849
3850 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3851 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3852 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3853 &attr->mp_nexthop_global)
d62a17ae 3854 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3855 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3856 &attr->mp_nexthop_global)
3857 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3858 dest));
d62a17ae 3859 break;
0355b41d
DA
3860 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3861 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3862 || IN6_IS_ADDR_MULTICAST(
3863 &attr->mp_nexthop_global)
3864 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3865 dest));
0355b41d 3866 break;
d62a17ae 3867
3868 default:
3dc339cd 3869 ret = true;
d62a17ae 3870 break;
3871 }
3872 }
c265ee22 3873
d62a17ae 3874 return ret;
3875}
3876
aade37d7 3877static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3878{
3879 struct community *old;
3880 struct community *new;
3881 struct community *merge;
aade37d7 3882 struct community *no_export;
2721dd61 3883
9a706b42 3884 old = bgp_attr_get_community(attr);
aade37d7 3885 no_export = community_str2com("no-export");
2721dd61 3886
b4efa101
DA
3887 assert(no_export);
3888
2721dd61 3889 if (old) {
aade37d7 3890 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3891
3892 if (!old->refcnt)
3893 community_free(&old);
3894
3895 new = community_uniq_sort(merge);
3896 community_free(&merge);
3897 } else {
aade37d7 3898 new = community_dup(no_export);
2721dd61
DA
3899 }
3900
aade37d7 3901 community_free(&no_export);
2721dd61 3902
9a706b42 3903 bgp_attr_set_community(attr, new);
2721dd61
DA
3904}
3905
46dbf9d0
DA
3906static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3907 struct attr *attr, const struct prefix *prefix,
3908 int *sub_type)
3909{
3910 struct listnode *node, *nnode;
3911 struct bgp *bgp;
3912 bool accept_own_found = false;
3913
3914 if (safi != SAFI_MPLS_VPN)
3915 return false;
3916
3917 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3918 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3919 return false;
3920
3921 /* The route in question carries the ACCEPT_OWN community */
3922 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3923 struct community *comm = bgp_attr_get_community(attr);
3924
3925 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3926 accept_own_found = true;
3927 }
3928
3929 /* The route in question is targeted to one or more destination VRFs
3930 * on the router (as determined by inspecting the Route Target(s)).
3931 */
3932 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3933 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3934 continue;
3935
3936 if (accept_own_found &&
3937 ecommunity_include(
3938 bgp->vpn_policy[afi]
3939 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3940 bgp_attr_get_ecommunity(attr))) {
3941 if (bgp_debug_update(peer, prefix, NULL, 1))
3942 zlog_debug(
3943 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3944 peer, prefix);
3945
3946 /* Treat this route as imported, because it's leaked
3947 * already from another VRF, and we got an updated
3948 * version from route-reflector with ACCEPT_OWN
3949 * community.
3950 */
3951 *sub_type = BGP_ROUTE_IMPORTED;
3952
3953 return true;
3954 }
3955 }
3956
3957 return false;
3958}
3959
367b458c
DS
3960void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3961 struct attr *attr, afi_t afi, safi_t safi, int type,
3962 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3963 uint32_t num_labels, int soft_reconfig,
3964 struct bgp_route_evpn *evpn)
d62a17ae 3965{
3966 int ret;
3967 int aspath_loop_count = 0;
9bcb3eef 3968 struct bgp_dest *dest;
d62a17ae 3969 struct bgp *bgp;
3970 struct attr new_attr;
3971 struct attr *attr_new;
40381db7 3972 struct bgp_path_info *pi;
819e6767 3973 struct bgp_path_info *new = NULL;
4b7e6066 3974 struct bgp_path_info_extra *extra;
d62a17ae 3975 const char *reason;
3976 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3977 int connected = 0;
3978 int do_loop_check = 1;
3979 int has_valid_label = 0;
7c312383 3980 afi_t nh_afi;
9146341f 3981 bool force_evpn_import = false;
907707db 3982 safi_t orig_safi = safi;
a486300b 3983 bool leak_success = true;
b2ac1d0d 3984 int allowas_in = 0;
949b0f24 3985
c7bb4f00 3986 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3987 char pfxprint[PREFIX2STR_BUFFER];
3988
3989 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3990 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3991 afi, safi, attr);
6401252f
QY
3992 }
3993
49e5a4a0 3994#ifdef ENABLE_BGP_VNC
d62a17ae 3995 int vnc_implicit_withdraw = 0;
65efcfce 3996#endif
d62a17ae 3997 int same_attr = 0;
f8745525 3998 const struct prefix *bgp_nht_param_prefix;
718e3744 3999
907707db
MS
4000 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4001 if (orig_safi == SAFI_LABELED_UNICAST)
4002 safi = SAFI_UNICAST;
4003
6006b807 4004 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4005 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4006 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4007
d62a17ae 4008 bgp = peer->bgp;
9bcb3eef 4009 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4010 /* TODO: Check to see if we can get rid of "is_valid_label" */
4011 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4012 has_valid_label = (num_labels > 0) ? 1 : 0;
4013 else
4014 has_valid_label = bgp_is_valid_label(label);
718e3744 4015
28f66de2
MS
4016 if (has_valid_label)
4017 assert(label != NULL);
4018
66ff6089
AD
4019 /* Update overlay index of the attribute */
4020 if (afi == AFI_L2VPN && evpn)
4021 memcpy(&attr->evpn_overlay, evpn,
4022 sizeof(struct bgp_route_evpn));
4023
d62a17ae 4024 /* When peer's soft reconfiguration enabled. Record input packet in
4025 Adj-RIBs-In. */
4026 if (!soft_reconfig
4027 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4028 && peer != bgp->peer_self)
9bcb3eef 4029 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4030
b2ac1d0d
MS
4031 /* Update permitted loop count */
4032 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4033 allowas_in = peer->allowas_in[afi][safi];
4034
d62a17ae 4035 /* Check previously received route. */
9bcb3eef 4036 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4037 if (pi->peer == peer && pi->type == type
4038 && pi->sub_type == sub_type
4039 && pi->addpath_rx_id == addpath_id)
d62a17ae 4040 break;
4041
4042 /* AS path local-as loop check. */
4043 if (peer->change_local_as) {
b2ac1d0d
MS
4044 if (allowas_in)
4045 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4046 else if (!CHECK_FLAG(peer->flags,
4047 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4048 aspath_loop_count = 1;
4049
4050 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4051 > aspath_loop_count) {
b4d46cc9 4052 peer->stat_pfx_aspath_loop++;
692174a1 4053 reason = "as-path contains our own AS;";
d62a17ae 4054 goto filtered;
4055 }
718e3744 4056 }
718e3744 4057
d62a17ae 4058 /* If the peer is configured for "allowas-in origin" and the last ASN in
4059 * the
4060 * as-path is our ASN then we do not need to call aspath_loop_check
4061 */
4062 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4063 if (aspath_get_last_as(attr->aspath) == bgp->as)
4064 do_loop_check = 0;
4065
f8745525
PG
4066 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4067 bgp_nht_param_prefix = NULL;
4068 else
4069 bgp_nht_param_prefix = p;
4070
d62a17ae 4071 /* AS path loop check. */
4072 if (do_loop_check) {
b0a8f709
FD
4073 if (aspath_loop_check(attr->aspath, bgp->as) >
4074 peer->allowas_in[afi][safi]) {
b4d46cc9 4075 peer->stat_pfx_aspath_loop++;
d62a17ae 4076 reason = "as-path contains our own AS;";
4077 goto filtered;
4078 }
4079 }
aac9ef6c 4080
b0a8f709
FD
4081 /* If we're a CONFED we need to loop check the CONFED ID too */
4082 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4083 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4084 peer->allowas_in[afi][safi]) {
4085 peer->stat_pfx_aspath_loop++;
4086 reason = "as-path contains our own confed AS;";
4087 goto filtered;
4088 }
4089
46dbf9d0
DA
4090 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4091 * enabled, then take care of that too.
4092 */
4093 bool accept_own = false;
4094
d62a17ae 4095 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4096 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4097 accept_own =
4098 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4099 if (!accept_own) {
4100 peer->stat_pfx_originator_loop++;
4101 reason = "originator is us;";
4102 goto filtered;
4103 }
d62a17ae 4104 }
718e3744 4105
d62a17ae 4106 /* Route reflector cluster ID check. */
4107 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4108 peer->stat_pfx_cluster_loop++;
d62a17ae 4109 reason = "reflected from the same cluster;";
4110 goto filtered;
4111 }
718e3744 4112
d62a17ae 4113 /* Apply incoming filter. */
907707db 4114 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4115 peer->stat_pfx_filter++;
d62a17ae 4116 reason = "filter;";
4117 goto filtered;
4118 }
718e3744 4119
a8b72dc6
DA
4120 /* RFC 8212 to prevent route leaks.
4121 * This specification intends to improve this situation by requiring the
4122 * explicit configuration of both BGP Import and Export Policies for any
4123 * External BGP (EBGP) session such as customers, peers, or
4124 * confederation boundaries for all enabled address families. Through
4125 * codification of the aforementioned requirement, operators will
4126 * benefit from consistent behavior across different BGP
4127 * implementations.
4128 */
1d3fdccf 4129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4130 if (!bgp_inbound_policy_exists(peer,
4131 &peer->filter[afi][safi])) {
4132 reason = "inbound policy missing";
b17826b7
DS
4133 if (monotime_since(&bgp->ebgprequirespolicywarning,
4134 NULL) > FIFTEENMINUTE2USEC ||
4135 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4136 zlog_warn(
4137 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4138 monotime(&bgp->ebgprequirespolicywarning);
4139 }
a8b72dc6
DA
4140 goto filtered;
4141 }
4142
fb29348a
DA
4143 /* draft-ietf-idr-deprecate-as-set-confed-set
4144 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4145 * Eventually, This document (if approved) updates RFC 4271
4146 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4147 * and obsoletes RFC 6472.
4148 */
7f972cd8 4149 if (peer->bgp->reject_as_sets)
fb29348a
DA
4150 if (aspath_check_as_sets(attr->aspath)) {
4151 reason =
4152 "as-path contains AS_SET or AS_CONFED_SET type;";
4153 goto filtered;
4154 }
4155
6f4f49b2 4156 new_attr = *attr;
d62a17ae 4157
4158 /* Apply incoming route-map.
4159 * NB: new_attr may now contain newly allocated values from route-map
4160 * "set"
4161 * commands, so we need bgp_attr_flush in the error paths, until we
4162 * intern
4163 * the attr (which takes over the memory references) */
907707db 4164 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4165 num_labels, dest)
4166 == RMAP_DENY) {
b4d46cc9 4167 peer->stat_pfx_filter++;
d62a17ae 4168 reason = "route-map;";
4169 bgp_attr_flush(&new_attr);
4170 goto filtered;
4171 }
718e3744 4172
05864da7 4173 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4174 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4175 /* remove from RIB previous entry */
4176 bgp_zebra_withdraw(p, pi, bgp, safi);
4177 }
4178
7f323236
DW
4179 if (peer->sort == BGP_PEER_EBGP) {
4180
2721dd61
DA
4181 /* rfc7999:
4182 * A BGP speaker receiving an announcement tagged with the
4183 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4184 * NO_EXPORT community as defined in RFC1997, or a
4185 * similar community, to prevent propagation of the
4186 * prefix outside the local AS. The community to prevent
4187 * propagation SHOULD be chosen according to the operator's
4188 * routing policy.
4189 */
9a706b42
DA
4190 if (bgp_attr_get_community(&new_attr) &&
4191 community_include(bgp_attr_get_community(&new_attr),
4192 COMMUNITY_BLACKHOLE))
aade37d7 4193 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4194
a4d82a8a
PZ
4195 /* If we receive the graceful-shutdown community from an eBGP
4196 * peer we must lower local-preference */
9a706b42
DA
4197 if (bgp_attr_get_community(&new_attr) &&
4198 community_include(bgp_attr_get_community(&new_attr),
4199 COMMUNITY_GSHUT)) {
7f323236
DW
4200 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4201 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4202
4f770cf1
DA
4203 /* If graceful-shutdown is configured globally or
4204 * per neighbor, then add the GSHUT community to
4205 * all paths received from eBGP peers. */
4206 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4207 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4208 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4209 }
4210
d62a17ae 4211 /* next hop check. */
860ad3f9
DS
4212 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4213 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4214 &new_attr, dest)) {
b4d46cc9 4215 peer->stat_pfx_nh_invalid++;
d62a17ae 4216 reason = "martian or self next-hop;";
4217 bgp_attr_flush(&new_attr);
4218 goto filtered;
4219 }
718e3744 4220
5c14a191 4221 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4222 peer->stat_pfx_nh_invalid++;
4e802e66 4223 reason = "self mac;";
4dbf2038 4224 bgp_attr_flush(&new_attr);
4e802e66
DS
4225 goto filtered;
4226 }
4227
5a78f2bc
EB
4228 if (bgp_check_role_applicability(afi, safi) &&
4229 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4230 reason = "failing otc validation";
4231 bgp_attr_flush(&new_attr);
4232 goto filtered;
4233 }
a1b773e2
DS
4234 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4235 * condition :
4236 * Suppress fib is enabled
4237 * BGP_OPT_NO_FIB is not enabled
4238 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4239 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4240 */
4241 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4242 && (sub_type == BGP_ROUTE_NORMAL)
4243 && (!bgp_option_check(BGP_OPT_NO_FIB))
4244 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4245 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4246
01da2d26
DA
4247 /* If neighbor soo is configured, tag all incoming routes with
4248 * this SoO tag and then filter out advertisements in
4249 * subgroup_announce_check() if it matches the configured SoO
4250 * on the other peer.
4251 */
4252 if (peer->soo[afi][safi]) {
4253 struct ecommunity *old_ecomm =
4254 bgp_attr_get_ecommunity(&new_attr);
4255 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4256 struct ecommunity *new_ecomm;
4257
4258 if (old_ecomm) {
4259 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4260 ecomm_soo);
4261
4262 if (!old_ecomm->refcnt)
4263 ecommunity_free(&old_ecomm);
4264 } else {
4265 new_ecomm = ecommunity_dup(ecomm_soo);
4266 }
4267
4268 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4269 }
4270
4dbf2038 4271 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4272
d62a17ae 4273 /* If the update is implicit withdraw. */
40381db7 4274 if (pi) {
083ec940 4275 pi->uptime = monotime(NULL);
40381db7 4276 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4277
9bcb3eef 4278 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4279
d62a17ae 4280 /* Same attribute comes in. */
40381db7 4281 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4282 && same_attr
d62a17ae 4283 && (!has_valid_label
40381db7 4284 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4285 num_labels * sizeof(mpls_label_t))
66ff6089 4286 == 0)) {
b4f7f45b
IR
4287 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4288 BGP_CONFIG_DAMPENING)
d62a17ae 4289 && peer->sort == BGP_PEER_EBGP
40381db7 4290 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4291 if (bgp_debug_update(peer, p, NULL, 1)) {
4292 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4293 afi, safi, prd, p, label,
4294 num_labels, addpath_id ? 1 : 0,
66ff6089 4295 addpath_id, evpn, pfx_buf,
a4d82a8a 4296 sizeof(pfx_buf));
f70c91dc 4297 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4298 pfx_buf);
4299 }
4300
9bcb3eef 4301 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4302 != BGP_DAMP_SUPPRESSED) {
40381db7 4303 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4304 safi);
9bcb3eef 4305 bgp_process(bgp, dest, afi, safi);
d62a17ae 4306 }
4307 } else /* Duplicate - odd */
4308 {
4309 if (bgp_debug_update(peer, p, NULL, 1)) {
4310 if (!peer->rcvd_attr_printed) {
4311 zlog_debug(
f70c91dc
DA
4312 "%pBP rcvd UPDATE w/ attr: %s",
4313 peer,
d62a17ae 4314 peer->rcvd_attr_str);
4315 peer->rcvd_attr_printed = 1;
4316 }
4317
4318 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4319 afi, safi, prd, p, label,
4320 num_labels, addpath_id ? 1 : 0,
66ff6089 4321 addpath_id, evpn, pfx_buf,
a4d82a8a 4322 sizeof(pfx_buf));
d62a17ae 4323 zlog_debug(
f70c91dc
DA
4324 "%pBP rcvd %s...duplicate ignored",
4325 peer, pfx_buf);
d62a17ae 4326 }
4327
4328 /* graceful restart STALE flag unset. */
40381db7 4329 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4330 bgp_path_info_unset_flag(
9bcb3eef
DS
4331 dest, pi, BGP_PATH_STALE);
4332 bgp_dest_set_defer_flag(dest, false);
4333 bgp_process(bgp, dest, afi, safi);
d62a17ae 4334 }
4335 }
4336
9bcb3eef 4337 bgp_dest_unlock_node(dest);
d62a17ae 4338 bgp_attr_unintern(&attr_new);
4339
367b458c 4340 return;
d62a17ae 4341 }
718e3744 4342
d62a17ae 4343 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4344 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4345 if (bgp_debug_update(peer, p, NULL, 1)) {
4346 bgp_debug_rdpfxpath2str(
a4d82a8a 4347 afi, safi, prd, p, label, num_labels,
66ff6089 4348 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4349 pfx_buf, sizeof(pfx_buf));
d62a17ae 4350 zlog_debug(
f70c91dc
DA
4351 "%pBP rcvd %s, flapped quicker than processing",
4352 peer, pfx_buf);
d62a17ae 4353 }
4354
9bcb3eef 4355 bgp_path_info_restore(dest, pi);
9146341f 4356
4357 /*
4358 * If the BGP_PATH_REMOVED flag is set, then EVPN
4359 * routes would have been unimported already when a
4360 * prior BGP withdraw processing happened. Such routes
4361 * need to be imported again, so flag accordingly.
4362 */
4363 force_evpn_import = true;
704e189e 4364 } else {
4365 /* implicit withdraw, decrement aggregate and pcount
4366 * here. only if update is accepted, they'll increment
4367 * below.
4368 */
4369 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4370 }
718e3744 4371
d62a17ae 4372 /* Received Logging. */
4373 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4374 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4375 num_labels, addpath_id ? 1 : 0,
66ff6089 4376 addpath_id, evpn, pfx_buf,
a4d82a8a 4377 sizeof(pfx_buf));
f70c91dc 4378 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4379 }
718e3744 4380
d62a17ae 4381 /* graceful restart STALE flag unset. */
f009ff26 4382 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4383 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4384 bgp_dest_set_defer_flag(dest, false);
f009ff26 4385 }
d62a17ae 4386
4387 /* The attribute is changed. */
9bcb3eef 4388 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4389
d62a17ae 4390 /* Update bgp route dampening information. */
b4f7f45b 4391 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4392 && peer->sort == BGP_PEER_EBGP) {
4393 /* This is implicit withdraw so we should update
b4f7f45b
IR
4394 dampening
4395 information. */
40381db7 4396 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4397 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4398 }
49e5a4a0 4399#ifdef ENABLE_BGP_VNC
d62a17ae 4400 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4401 struct bgp_dest *pdest = NULL;
d62a17ae 4402 struct bgp_table *table = NULL;
4403
9bcb3eef
DS
4404 pdest = bgp_node_get(bgp->rib[afi][safi],
4405 (struct prefix *)prd);
4406 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4407 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4408
4409 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4410 bgp, prd, table, p, pi);
d62a17ae 4411 }
9bcb3eef 4412 bgp_dest_unlock_node(pdest);
d62a17ae 4413 }
4414 if ((afi == AFI_IP || afi == AFI_IP6)
4415 && (safi == SAFI_UNICAST)) {
40381db7 4416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4417 /*
4418 * Implicit withdraw case.
4419 */
4420 ++vnc_implicit_withdraw;
40381db7
DS
4421 vnc_import_bgp_del_route(bgp, p, pi);
4422 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4423 }
4424 }
65efcfce 4425#endif
128ea8ab 4426
d62a17ae 4427 /* Special handling for EVPN update of an existing route. If the
4428 * extended community attribute has changed, we need to
4429 * un-import
4430 * the route using its existing extended community. It will be
4431 * subsequently processed for import with the new extended
4432 * community.
4433 */
6f8c9c11
PR
4434 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4435 && !same_attr) {
40381db7 4436 if ((pi->attr->flag
d62a17ae 4437 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4438 && (attr_new->flag
4439 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4440 int cmp;
4441
b53e67a3
DA
4442 cmp = ecommunity_cmp(
4443 bgp_attr_get_ecommunity(pi->attr),
4444 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4445 if (!cmp) {
4446 if (bgp_debug_update(peer, p, NULL, 1))
4447 zlog_debug(
4448 "Change in EXT-COMM, existing %s new %s",
4449 ecommunity_str(
b53e67a3
DA
4450 bgp_attr_get_ecommunity(
4451 pi->attr)),
d62a17ae 4452 ecommunity_str(
b53e67a3
DA
4453 bgp_attr_get_ecommunity(
4454 attr_new)));
6f8c9c11
PR
4455 if (safi == SAFI_EVPN)
4456 bgp_evpn_unimport_route(
4457 bgp, afi, safi, p, pi);
4458 else /* SAFI_MPLS_VPN */
1aa2c93e 4459 vpn_leak_to_vrf_withdraw(pi);
d62a17ae 4460 }
4461 }
4462 }
718e3744 4463
d62a17ae 4464 /* Update to new attribute. */
40381db7
DS
4465 bgp_attr_unintern(&pi->attr);
4466 pi->attr = attr_new;
d62a17ae 4467
4468 /* Update MPLS label */
4469 if (has_valid_label) {
40381db7 4470 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4471 if (extra->label != label) {
4472 memcpy(&extra->label, label,
dbd587da 4473 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4474 extra->num_labels = num_labels;
4475 }
b57ba6d2
MK
4476 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4477 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4478 }
718e3744 4479
e496b420
HS
4480 /* Update SRv6 SID */
4481 if (attr->srv6_l3vpn) {
4482 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4483 if (sid_diff(&extra->sid[0].sid,
4484 &attr->srv6_l3vpn->sid)) {
4485 sid_copy(&extra->sid[0].sid,
e496b420
HS
4486 &attr->srv6_l3vpn->sid);
4487 extra->num_sids = 1;
cc8f05df 4488
16f3db2d
RS
4489 extra->sid[0].loc_block_len = 0;
4490 extra->sid[0].loc_node_len = 0;
4491 extra->sid[0].func_len = 0;
4492 extra->sid[0].arg_len = 0;
ea7cd161
RS
4493 extra->sid[0].transposition_len = 0;
4494 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4495
4496 if (attr->srv6_l3vpn->loc_block_len != 0) {
4497 extra->sid[0].loc_block_len =
4498 attr->srv6_l3vpn->loc_block_len;
4499 extra->sid[0].loc_node_len =
4500 attr->srv6_l3vpn->loc_node_len;
4501 extra->sid[0].func_len =
4502 attr->srv6_l3vpn->func_len;
4503 extra->sid[0].arg_len =
4504 attr->srv6_l3vpn->arg_len;
ea7cd161 4505 extra->sid[0].transposition_len =
cc8f05df 4506 attr->srv6_l3vpn
ea7cd161
RS
4507 ->transposition_len;
4508 extra->sid[0].transposition_offset =
cc8f05df 4509 attr->srv6_l3vpn
ea7cd161
RS
4510 ->transposition_offset;
4511 }
e496b420
HS
4512 }
4513 } else if (attr->srv6_vpn) {
4514 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4515 if (sid_diff(&extra->sid[0].sid,
4516 &attr->srv6_vpn->sid)) {
4517 sid_copy(&extra->sid[0].sid,
4518 &attr->srv6_vpn->sid);
e496b420
HS
4519 extra->num_sids = 1;
4520 }
4521 }
4522
49e5a4a0 4523#ifdef ENABLE_BGP_VNC
d62a17ae 4524 if ((afi == AFI_IP || afi == AFI_IP6)
4525 && (safi == SAFI_UNICAST)) {
4526 if (vnc_implicit_withdraw) {
4527 /*
4528 * Add back the route with its new attributes
4529 * (e.g., nexthop).
4530 * The route is still selected, until the route
4531 * selection
4532 * queued by bgp_process actually runs. We have
4533 * to make this
4534 * update to the VNC side immediately to avoid
4535 * racing against
4536 * configuration changes (e.g., route-map
4537 * changes) which
4538 * trigger re-importation of the entire RIB.
4539 */
40381db7
DS
4540 vnc_import_bgp_add_route(bgp, p, pi);
4541 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4542 }
4543 }
65efcfce
LB
4544#endif
4545
d62a17ae 4546 /* Update bgp route dampening information. */
b4f7f45b 4547 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4548 && peer->sort == BGP_PEER_EBGP) {
4549 /* Now we do normal update dampening. */
9bcb3eef 4550 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4551 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4552 bgp_dest_unlock_node(dest);
367b458c 4553 return;
d62a17ae 4554 }
4555 }
128ea8ab 4556
d62a17ae 4557 /* Nexthop reachability check - for unicast and
4558 * labeled-unicast.. */
7c312383
AD
4559 if (((afi == AFI_IP || afi == AFI_IP6)
4560 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4561 || (safi == SAFI_EVPN &&
4562 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4563 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4564 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4565 && !CHECK_FLAG(peer->flags,
4566 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4567 && !CHECK_FLAG(bgp->flags,
4568 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4569 connected = 1;
4570 else
4571 connected = 0;
4572
960035b2
PZ
4573 struct bgp *bgp_nexthop = bgp;
4574
40381db7
DS
4575 if (pi->extra && pi->extra->bgp_orig)
4576 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4577
7c312383
AD
4578 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4579
4580 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4581 safi, pi, NULL, connected,
f8745525
PG
4582 bgp_nht_param_prefix) ||
4583 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4584 bgp_path_info_set_flag(dest, pi,
4585 BGP_PATH_VALID);
d62a17ae 4586 else {
4587 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4588 zlog_debug("%s(%pI4): NH unresolved",
4589 __func__,
4590 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4591 }
9bcb3eef 4592 bgp_path_info_unset_flag(dest, pi,
18ee8310 4593 BGP_PATH_VALID);
d62a17ae 4594 }
46dbf9d0
DA
4595 } else {
4596 if (accept_own)
4597 bgp_path_info_set_flag(dest, pi,
4598 BGP_PATH_ACCEPT_OWN);
4599
9bcb3eef 4600 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4601 }
d62a17ae 4602
49e5a4a0 4603#ifdef ENABLE_BGP_VNC
d62a17ae 4604 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4605 struct bgp_dest *pdest = NULL;
d62a17ae 4606 struct bgp_table *table = NULL;
4607
9bcb3eef
DS
4608 pdest = bgp_node_get(bgp->rib[afi][safi],
4609 (struct prefix *)prd);
4610 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4611 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4612
4613 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4614 bgp, prd, table, p, pi);
d62a17ae 4615 }
9bcb3eef 4616 bgp_dest_unlock_node(pdest);
d62a17ae 4617 }
4618#endif
718e3744 4619
d62a17ae 4620 /* If this is an EVPN route and some attribute has changed,
9146341f 4621 * or we are explicitly told to perform a route import, process
d62a17ae 4622 * route for import. If the extended community has changed, we
4623 * would
4624 * have done the un-import earlier and the import would result
4625 * in the
4626 * route getting injected into appropriate L2 VNIs. If it is
4627 * just
4628 * some other attribute change, the import will result in
4629 * updating
4630 * the attributes for the route in the VNI(s).
4631 */
9146341f 4632 if (safi == SAFI_EVPN &&
4633 (!same_attr || force_evpn_import) &&
7c312383 4634 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4635 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4636
4637 /* Process change. */
40381db7 4638 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4639
9bcb3eef
DS
4640 bgp_process(bgp, dest, afi, safi);
4641 bgp_dest_unlock_node(dest);
558d1fec 4642
ddb5b488
PZ
4643 if (SAFI_UNICAST == safi
4644 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4645 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4646
40381db7 4647 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4648 }
4649 if ((SAFI_MPLS_VPN == safi)
4650 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4651 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4652 }
4653
49e5a4a0 4654#ifdef ENABLE_BGP_VNC
d62a17ae 4655 if (SAFI_MPLS_VPN == safi) {
4656 mpls_label_t label_decoded = decode_label(label);
28070ee3 4657
d62a17ae 4658 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4659 type, sub_type, &label_decoded);
4660 }
4661 if (SAFI_ENCAP == safi) {
4662 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4663 type, sub_type, NULL);
4664 }
28070ee3 4665#endif
a486300b
PG
4666 if ((safi == SAFI_MPLS_VPN) &&
4667 !CHECK_FLAG(bgp->af_flags[afi][safi],
4668 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4669 !leak_success) {
4670 bgp_unlink_nexthop(pi);
4671 bgp_path_info_delete(dest, pi);
4672 }
367b458c 4673 return;
d62a17ae 4674 } // End of implicit withdraw
718e3744 4675
d62a17ae 4676 /* Received Logging. */
4677 if (bgp_debug_update(peer, p, NULL, 1)) {
4678 if (!peer->rcvd_attr_printed) {
f70c91dc 4679 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4680 peer->rcvd_attr_str);
4681 peer->rcvd_attr_printed = 1;
4682 }
718e3744 4683
a4d82a8a 4684 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4685 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4686 pfx_buf, sizeof(pfx_buf));
f70c91dc 4687 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4688 }
718e3744 4689
d62a17ae 4690 /* Make new BGP info. */
9bcb3eef 4691 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4692
d62a17ae 4693 /* Update MPLS label */
4694 if (has_valid_label) {
18ee8310 4695 extra = bgp_path_info_extra_get(new);
8ba71050 4696 if (extra->label != label) {
dbd587da
QY
4697 memcpy(&extra->label, label,
4698 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4699 extra->num_labels = num_labels;
4700 }
b57ba6d2
MK
4701 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4702 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4703 }
718e3744 4704
e496b420
HS
4705 /* Update SRv6 SID */
4706 if (safi == SAFI_MPLS_VPN) {
4707 extra = bgp_path_info_extra_get(new);
4708 if (attr->srv6_l3vpn) {
16f3db2d 4709 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4710 extra->num_sids = 1;
cc8f05df 4711
16f3db2d
RS
4712 extra->sid[0].loc_block_len =
4713 attr->srv6_l3vpn->loc_block_len;
4714 extra->sid[0].loc_node_len =
4715 attr->srv6_l3vpn->loc_node_len;
4716 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4717 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4718 extra->sid[0].transposition_len =
4719 attr->srv6_l3vpn->transposition_len;
4720 extra->sid[0].transposition_offset =
4721 attr->srv6_l3vpn->transposition_offset;
e496b420 4722 } else if (attr->srv6_vpn) {
16f3db2d 4723 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4724 extra->num_sids = 1;
4725 }
4726 }
4727
d62a17ae 4728 /* Nexthop reachability check. */
7c312383
AD
4729 if (((afi == AFI_IP || afi == AFI_IP6)
4730 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4731 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4732 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4733 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4734 && !CHECK_FLAG(peer->flags,
4735 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4736 && !CHECK_FLAG(bgp->flags,
4737 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4738 connected = 1;
4739 else
4740 connected = 0;
4741
7c312383
AD
4742 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4743
4053e952 4744 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4745 connected, bgp_nht_param_prefix) ||
4746 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4747 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4748 else {
07380148
DA
4749 if (BGP_DEBUG(nht, NHT))
4750 zlog_debug("%s(%pI4): NH unresolved", __func__,
4751 &attr_new->nexthop);
9bcb3eef 4752 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4753 }
46dbf9d0
DA
4754 } else {
4755 if (accept_own)
4756 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4757
9bcb3eef 4758 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4759 }
a82478b9 4760
b381ed97
DA
4761 /* If maximum prefix count is configured and current prefix
4762 * count exeed it.
4763 */
4764 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4765 reason = "maximum-prefix overflow";
4766 bgp_attr_flush(&new_attr);
b381ed97
DA
4767 goto filtered;
4768 }
4769
d62a17ae 4770 /* Addpath ID */
4771 new->addpath_rx_id = addpath_id;
4772
4773 /* Increment prefix */
4774 bgp_aggregate_increment(bgp, p, new, afi, safi);
4775
4776 /* Register new BGP information. */
9bcb3eef 4777 bgp_path_info_add(dest, new);
d62a17ae 4778
4779 /* route_node_get lock */
9bcb3eef 4780 bgp_dest_unlock_node(dest);
558d1fec 4781
49e5a4a0 4782#ifdef ENABLE_BGP_VNC
d62a17ae 4783 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4784 struct bgp_dest *pdest = NULL;
d62a17ae 4785 struct bgp_table *table = NULL;
4786
9bcb3eef
DS
4787 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4788 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4789 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4790
4791 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4792 bgp, prd, table, p, new);
4793 }
9bcb3eef 4794 bgp_dest_unlock_node(pdest);
d62a17ae 4795 }
65efcfce
LB
4796#endif
4797
d62a17ae 4798 /* If this is an EVPN route, process for import. */
7c312383 4799 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4800 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4801
9bcb3eef 4802 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4803
d62a17ae 4804 /* Process change. */
9bcb3eef 4805 bgp_process(bgp, dest, afi, safi);
718e3744 4806
ddb5b488
PZ
4807 if (SAFI_UNICAST == safi
4808 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4809 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4810 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4811 }
4812 if ((SAFI_MPLS_VPN == safi)
4813 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4814 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4815 }
49e5a4a0 4816#ifdef ENABLE_BGP_VNC
d62a17ae 4817 if (SAFI_MPLS_VPN == safi) {
4818 mpls_label_t label_decoded = decode_label(label);
28070ee3 4819
d62a17ae 4820 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4821 sub_type, &label_decoded);
4822 }
4823 if (SAFI_ENCAP == safi) {
4824 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4825 sub_type, NULL);
4826 }
28070ee3 4827#endif
a486300b
PG
4828 if ((safi == SAFI_MPLS_VPN) &&
4829 !CHECK_FLAG(bgp->af_flags[afi][safi],
4830 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4831 !leak_success) {
4832 bgp_unlink_nexthop(new);
4833 bgp_path_info_delete(dest, new);
4834 }
28070ee3 4835
367b458c 4836 return;
718e3744 4837
d62a17ae 4838/* This BGP update is filtered. Log the reason then update BGP
4839 entry. */
4840filtered:
819e6767
DA
4841 if (new) {
4842 bgp_unlink_nexthop(new);
4843 bgp_path_info_delete(dest, new);
4844 bgp_path_info_extra_free(&new->extra);
4845 XFREE(MTYPE_BGP_ROUTE, new);
4846 }
4847
9bcb3eef 4848 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4849
d62a17ae 4850 if (bgp_debug_update(peer, p, NULL, 1)) {
4851 if (!peer->rcvd_attr_printed) {
f70c91dc 4852 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4853 peer->rcvd_attr_str);
4854 peer->rcvd_attr_printed = 1;
4855 }
718e3744 4856
a4d82a8a 4857 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4858 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4859 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4860 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4861 peer, pfx_buf, reason);
d62a17ae 4862 }
128ea8ab 4863
40381db7 4864 if (pi) {
d62a17ae 4865 /* If this is an EVPN route, un-import it as it is now filtered.
4866 */
4867 if (safi == SAFI_EVPN)
40381db7 4868 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4869
ddb5b488
PZ
4870 if (SAFI_UNICAST == safi
4871 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4872 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4873
40381db7 4874 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4875 }
4876 if ((SAFI_MPLS_VPN == safi)
4877 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4878
1aa2c93e 4879 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4880 }
4881
9bcb3eef 4882 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4883 }
4884
9bcb3eef 4885 bgp_dest_unlock_node(dest);
558d1fec 4886
49e5a4a0 4887#ifdef ENABLE_BGP_VNC
d62a17ae 4888 /*
4889 * Filtered update is treated as an implicit withdrawal (see
4890 * bgp_rib_remove()
4891 * a few lines above)
4892 */
4893 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4894 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4895 0);
4896 }
97736e32
PZ
4897#endif
4898
367b458c 4899 return;
718e3744 4900}
4901
367b458c
DS
4902void bgp_withdraw(struct peer *peer, const struct prefix *p,
4903 uint32_t addpath_id, struct attr *attr, afi_t afi,
4904 safi_t safi, int type, int sub_type, struct prefix_rd *prd,
4905 mpls_label_t *label, uint32_t num_labels,
4906 struct bgp_route_evpn *evpn)
718e3744 4907{
d62a17ae 4908 struct bgp *bgp;
4909 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4910 struct bgp_dest *dest;
40381db7 4911 struct bgp_path_info *pi;
718e3744 4912
49e5a4a0 4913#ifdef ENABLE_BGP_VNC
d62a17ae 4914 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4915 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4916 0);
4917 }
28070ee3
PZ
4918#endif
4919
d62a17ae 4920 bgp = peer->bgp;
4921
4922 /* Lookup node. */
9bcb3eef 4923 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4924
4925 /* If peer is soft reconfiguration enabled. Record input packet for
4926 * further calculation.
4927 *
4928 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4929 * routes that are filtered. This tanks out Quagga RS pretty badly due
4930 * to
4931 * the iteration over all RS clients.
4932 * Since we need to remove the entry from adj_in anyway, do that first
4933 * and
4934 * if there was no entry, we don't need to do anything more.
4935 */
4936 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4937 && peer != bgp->peer_self)
9bcb3eef 4938 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4939 peer->stat_pfx_dup_withdraw++;
4940
d62a17ae 4941 if (bgp_debug_update(peer, p, NULL, 1)) {
4942 bgp_debug_rdpfxpath2str(
a4d82a8a 4943 afi, safi, prd, p, label, num_labels,
6c995628
AD
4944 addpath_id ? 1 : 0, addpath_id, NULL,
4945 pfx_buf, sizeof(pfx_buf));
d62a17ae 4946 zlog_debug(
4947 "%s withdrawing route %s not in adj-in",
4948 peer->host, pfx_buf);
4949 }
9bcb3eef 4950 bgp_dest_unlock_node(dest);
367b458c 4951 return;
d62a17ae 4952 }
cd808e74 4953
d62a17ae 4954 /* Lookup withdrawn route. */
9bcb3eef 4955 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4956 if (pi->peer == peer && pi->type == type
4957 && pi->sub_type == sub_type
4958 && pi->addpath_rx_id == addpath_id)
d62a17ae 4959 break;
4960
4961 /* Logging. */
4962 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4963 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4964 addpath_id ? 1 : 0, addpath_id, NULL,
4965 pfx_buf, sizeof(pfx_buf));
f70c91dc 4966 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4967 pfx_buf);
4968 }
718e3744 4969
d62a17ae 4970 /* Withdraw specified route from routing table. */
40381db7 4971 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4972 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4973 if (SAFI_UNICAST == safi
4974 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4975 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4976 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4977 }
4978 if ((SAFI_MPLS_VPN == safi)
4979 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4980
1aa2c93e 4981 vpn_leak_to_vrf_withdraw(pi);
ddb5b488
PZ
4982 }
4983 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4984 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4985 addpath_id ? 1 : 0, addpath_id, NULL,
4986 pfx_buf, sizeof(pfx_buf));
d62a17ae 4987 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4988 }
718e3744 4989
d62a17ae 4990 /* Unlock bgp_node_get() lock. */
9bcb3eef 4991 bgp_dest_unlock_node(dest);
d62a17ae 4992
367b458c 4993 return;
718e3744 4994}
6b0655a2 4995
d62a17ae 4996void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4997 int withdraw)
718e3744 4998{
d62a17ae 4999 struct update_subgroup *subgrp;
5000 subgrp = peer_subgroup(peer, afi, safi);
5001 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5002}
6182d65b 5003
718e3744 5004
3f9c7369
DS
5005/*
5006 * bgp_stop_announce_route_timer
5007 */
d62a17ae 5008void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5009{
d62a17ae 5010 if (!paf->t_announce_route)
5011 return;
5012
c3aaa89a 5013 THREAD_OFF(paf->t_announce_route);
718e3744 5014}
6b0655a2 5015
3f9c7369
DS
5016/*
5017 * bgp_announce_route_timer_expired
5018 *
5019 * Callback that is invoked when the route announcement timer for a
5020 * peer_af expires.
5021 */
cc9f21da 5022static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5023{
d62a17ae 5024 struct peer_af *paf;
5025 struct peer *peer;
558d1fec 5026
d62a17ae 5027 paf = THREAD_ARG(t);
5028 peer = paf->peer;
718e3744 5029
feb17238 5030 if (!peer_established(peer))
cc9f21da 5031 return;
3f9c7369 5032
d62a17ae 5033 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5034 return;
3f9c7369 5035
d62a17ae 5036 peer_af_announce_route(paf, 1);
c5aec50b
MK
5037
5038 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5039 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5040}
5041
3f9c7369
DS
5042/*
5043 * bgp_announce_route
5044 *
5045 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5046 *
5047 * if force is true we will force an update even if the update
5048 * limiting code is attempted to kick in.
3f9c7369 5049 */
e1a32ec1 5050void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5051{
5052 struct peer_af *paf;
5053 struct update_subgroup *subgrp;
5054
5055 paf = peer_af_find(peer, afi, safi);
5056 if (!paf)
5057 return;
5058 subgrp = PAF_SUBGRP(paf);
5059
5060 /*
5061 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5062 * or a refresh has already been triggered.
5063 */
5064 if (!subgrp || paf->t_announce_route)
5065 return;
5066
e1a32ec1
DS
5067 if (force)
5068 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5069
d62a17ae 5070 /*
5071 * Start a timer to stagger/delay the announce. This serves
5072 * two purposes - announcement can potentially be combined for
5073 * multiple peers and the announcement doesn't happen in the
5074 * vty context.
5075 */
5076 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5077 (subgrp->peer_count == 1)
5078 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5079 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5080 &paf->t_announce_route);
3f9c7369
DS
5081}
5082
5083/*
5084 * Announce routes from all AF tables to a peer.
5085 *
5086 * This should ONLY be called when there is a need to refresh the
5087 * routes to the peer based on a policy change for this peer alone
5088 * or a route refresh request received from the peer.
5089 * The operation will result in splitting the peer from its existing
5090 * subgroups and putting it in new subgroups.
5091 */
d62a17ae 5092void bgp_announce_route_all(struct peer *peer)
718e3744 5093{
d62a17ae 5094 afi_t afi;
5095 safi_t safi;
5096
05c7a1cc 5097 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5098 bgp_announce_route(peer, afi, safi, false);
718e3744 5099}
6b0655a2 5100
46aeabed
LS
5101/* Flag or unflag bgp_dest to determine whether it should be treated by
5102 * bgp_soft_reconfig_table_task.
5103 * Flag if flag is true. Unflag if flag is false.
5104 */
5105static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5106{
5107 struct bgp_dest *dest;
5108 struct bgp_adj_in *ain;
5109
5110 if (!table)
5111 return;
5112
5113 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5114 for (ain = dest->adj_in; ain; ain = ain->next) {
5115 if (ain->peer != NULL)
5116 break;
5117 }
5118 if (flag && ain != NULL && ain->peer != NULL)
5119 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5120 else
5121 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5122 }
5123}
5124
367b458c
DS
5125static void bgp_soft_reconfig_table_update(struct peer *peer,
5126 struct bgp_dest *dest,
5127 struct bgp_adj_in *ain, afi_t afi,
5128 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5129{
5130 struct bgp_path_info *pi;
5131 uint32_t num_labels = 0;
5132 mpls_label_t *label_pnt = NULL;
5133 struct bgp_route_evpn evpn;
5134
5135 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5136 if (pi->peer == peer)
5137 break;
5138
5139 if (pi && pi->extra)
5140 num_labels = pi->extra->num_labels;
5141 if (num_labels)
5142 label_pnt = &pi->extra->label[0];
5143 if (pi)
5144 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5145 sizeof(evpn));
5146 else
5147 memset(&evpn, 0, sizeof(evpn));
5148
367b458c
DS
5149 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5150 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5151 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5152}
5153
d62a17ae 5154static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5155 struct bgp_table *table,
5156 struct prefix_rd *prd)
718e3744 5157{
9bcb3eef 5158 struct bgp_dest *dest;
d62a17ae 5159 struct bgp_adj_in *ain;
718e3744 5160
d62a17ae 5161 if (!table)
5162 table = peer->bgp->rib[afi][safi];
718e3744 5163
9bcb3eef
DS
5164 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5165 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5166 if (ain->peer != peer)
5167 continue;
8692c506 5168
367b458c
DS
5169 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5170 safi, prd);
d62a17ae 5171 }
718e3744 5172}
5173
46aeabed
LS
5174/* Do soft reconfig table per bgp table.
5175 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5176 * when BGP_NODE_SOFT_RECONFIG is set,
5177 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5178 * Schedule a new thread to continue the job.
5179 * Without splitting the full job into several part,
5180 * vtysh waits for the job to finish before responding to a BGP command
5181 */
cc9f21da 5182static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5183{
5184 uint32_t iter, max_iter;
46aeabed
LS
5185 struct bgp_dest *dest;
5186 struct bgp_adj_in *ain;
5187 struct peer *peer;
5188 struct bgp_table *table;
5189 struct prefix_rd *prd;
5190 struct listnode *node, *nnode;
5191
5192 table = THREAD_ARG(thread);
5193 prd = NULL;
5194
5195 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5196 if (table->soft_reconfig_init) {
5197 /* first call of the function with a new srta structure.
5198 * Don't do any treatment this time on nodes
5199 * in order vtysh to respond quickly
5200 */
5201 max_iter = 0;
5202 }
5203
5204 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5205 dest = bgp_route_next(dest)) {
5206 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5207 continue;
5208
5209 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5210
5211 for (ain = dest->adj_in; ain; ain = ain->next) {
5212 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5213 nnode, peer)) {
5214 if (ain->peer != peer)
5215 continue;
5216
367b458c 5217 bgp_soft_reconfig_table_update(
46aeabed
LS
5218 peer, dest, ain, table->afi,
5219 table->safi, prd);
5220 iter++;
46aeabed
LS
5221 }
5222 }
5223 }
5224
5225 /* we're either starting the initial iteration,
5226 * or we're going to continue an ongoing iteration
5227 */
5228 if (dest || table->soft_reconfig_init) {
5229 table->soft_reconfig_init = false;
5230 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5231 table, 0, &table->soft_reconfig_thread);
cc9f21da 5232 return;
46aeabed
LS
5233 }
5234 /* we're done, clean up the background iteration context info and
5235 schedule route annoucement
5236 */
5237 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5238 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5239 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5240 }
5241
5242 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5243}
5244
5245
5246/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5247 * and peer.
5248 * - bgp cannot be NULL
5249 * - if table and peer are NULL, cancel all threads within the bgp instance
5250 * - if table is NULL and peer is not,
5251 * remove peer in all threads within the bgp instance
5252 * - if peer is NULL, cancel all threads matching table within the bgp instance
5253 */
5254void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5255 const struct bgp_table *table,
5256 const struct peer *peer)
5257{
5258 struct peer *npeer;
5259 struct listnode *node, *nnode;
5260 int afi, safi;
5261 struct bgp_table *ntable;
5262
5263 if (!bgp)
5264 return;
5265
5266 FOREACH_AFI_SAFI (afi, safi) {
5267 ntable = bgp->rib[afi][safi];
5268 if (!ntable)
5269 continue;
5270 if (table && table != ntable)
5271 continue;
5272
5273 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5274 npeer)) {
5275 if (peer && peer != npeer)
5276 continue;
5277 listnode_delete(ntable->soft_reconfig_peers, npeer);
5278 }
5279
5280 if (!ntable->soft_reconfig_peers
5281 || !list_isempty(ntable->soft_reconfig_peers))
5282 continue;
5283
5284 list_delete(&ntable->soft_reconfig_peers);
5285 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5286 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5287 }
5288}
5289
89c73443
DS
5290/*
5291 * Returns false if the peer is not configured for soft reconfig in
5292 */
5293bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5294{
9bcb3eef 5295 struct bgp_dest *dest;
d62a17ae 5296 struct bgp_table *table;
46aeabed
LS
5297 struct listnode *node, *nnode;
5298 struct peer *npeer;
5299 struct peer_af *paf;
718e3744 5300
89c73443
DS
5301 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5302 return false;
718e3744 5303
d62a17ae 5304 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5305 && (safi != SAFI_EVPN)) {
5306 table = peer->bgp->rib[afi][safi];
5307 if (!table)
89c73443 5308 return true;
46aeabed
LS
5309
5310 table->soft_reconfig_init = true;
5311
5312 if (!table->soft_reconfig_peers)
5313 table->soft_reconfig_peers = list_new();
5314 npeer = NULL;
5315 /* add peer to the table soft_reconfig_peers if not already
5316 * there
5317 */
5318 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5319 npeer)) {
5320 if (peer == npeer)
5321 break;
5322 }
5323 if (peer != npeer)
5324 listnode_add(table->soft_reconfig_peers, peer);
5325
5326 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5327 * on table would start back at the beginning.
5328 */
5329 bgp_soft_reconfig_table_flag(table, true);
5330
5331 if (!table->soft_reconfig_thread)
5332 thread_add_event(bm->master,
5333 bgp_soft_reconfig_table_task, table, 0,
5334 &table->soft_reconfig_thread);
5335 /* Cancel bgp_announce_route_timer_expired threads.
5336 * bgp_announce_route_timer_expired threads have been scheduled
5337 * to announce routes as soon as the soft_reconfigure process
5338 * finishes.
5339 * In this case, soft_reconfigure is also scheduled by using
5340 * a thread but is planned after the
5341 * bgp_announce_route_timer_expired threads. It means that,
5342 * without cancelling the threads, the route announcement task
5343 * would run before the soft reconfiguration one. That would
5344 * useless and would block vtysh during several seconds. Route
5345 * announcements are rescheduled as soon as the soft_reconfigure
5346 * process finishes.
5347 */
5348 paf = peer_af_find(peer, afi, safi);
5349 if (paf)
5350 bgp_stop_announce_route_timer(paf);
5351 } else
9bcb3eef
DS
5352 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5353 dest = bgp_route_next(dest)) {
5354 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5355
b54892e0
DS
5356 if (table == NULL)
5357 continue;
8692c506 5358
9bcb3eef 5359 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5360 struct prefix_rd prd;
5361
5362 prd.family = AF_UNSPEC;
5363 prd.prefixlen = 64;
5364 memcpy(&prd.val, p->u.val, 8);
5365
5366 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5367 }
89c73443
DS
5368
5369 return true;
718e3744 5370}
6b0655a2 5371
228da428 5372
d62a17ae 5373struct bgp_clear_node_queue {
9bcb3eef 5374 struct bgp_dest *dest;
228da428
CC
5375};
5376
d62a17ae 5377static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5378{
d62a17ae 5379 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5380 struct bgp_dest *dest = cnq->dest;
d62a17ae 5381 struct peer *peer = wq->spec.data;
40381db7 5382 struct bgp_path_info *pi;
3103e8d2 5383 struct bgp *bgp;
9bcb3eef
DS
5384 afi_t afi = bgp_dest_table(dest)->afi;
5385 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5386
9bcb3eef 5387 assert(dest && peer);
3103e8d2 5388 bgp = peer->bgp;
d62a17ae 5389
5390 /* It is possible that we have multiple paths for a prefix from a peer
5391 * if that peer is using AddPath.
5392 */
9bcb3eef 5393 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5394 if (pi->peer != peer)
ea47320b
DL
5395 continue;
5396
5397 /* graceful restart STALE flag set. */
9af52ccf
DA
5398 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5399 && peer->nsf[afi][safi])
5400 || CHECK_FLAG(peer->af_sflags[afi][safi],
5401 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5402 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5403 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5404 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5405 else {
5406 /* If this is an EVPN route, process for
5407 * un-import. */
5408 if (safi == SAFI_EVPN)
9bcb3eef
DS
5409 bgp_evpn_unimport_route(
5410 bgp, afi, safi,
5411 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5412 /* Handle withdraw for VRF route-leaking and L3VPN */
5413 if (SAFI_UNICAST == safi
5414 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5415 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5416 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5417 bgp, pi);
960035b2 5418 }
3103e8d2 5419 if (SAFI_MPLS_VPN == safi &&
960035b2 5420 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 5421 vpn_leak_to_vrf_withdraw(pi);
960035b2 5422 }
3103e8d2 5423
9bcb3eef 5424 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5425 }
ea47320b 5426 }
d62a17ae 5427 return WQ_SUCCESS;
200df115 5428}
5429
d62a17ae 5430static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5431{
d62a17ae 5432 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5433 struct bgp_dest *dest = cnq->dest;
5434 struct bgp_table *table = bgp_dest_table(dest);
228da428 5435
9bcb3eef 5436 bgp_dest_unlock_node(dest);
d62a17ae 5437 bgp_table_unlock(table);
5438 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5439}
5440
d62a17ae 5441static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5442{
d62a17ae 5443 struct peer *peer = wq->spec.data;
64e580a7 5444
d62a17ae 5445 /* Tickle FSM to start moving again */
5446 BGP_EVENT_ADD(peer, Clearing_Completed);
5447
5448 peer_unlock(peer); /* bgp_clear_route */
200df115 5449}
718e3744 5450
d62a17ae 5451static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5452{
d62a17ae 5453 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5454
5455 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5456#undef CLEAR_QUEUE_NAME_LEN
5457
0ce1ca80 5458 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5459 peer->clear_node_queue->spec.hold = 10;
5460 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5461 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5462 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5463 peer->clear_node_queue->spec.max_retries = 0;
5464
5465 /* we only 'lock' this peer reference when the queue is actually active
5466 */
5467 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5468}
5469
d62a17ae 5470static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5471 struct bgp_table *table)
65ca75e0 5472{
9bcb3eef 5473 struct bgp_dest *dest;
b6c386bb 5474 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5475
d62a17ae 5476 if (!table)
5477 table = peer->bgp->rib[afi][safi];
dc83d712 5478
d62a17ae 5479 /* If still no table => afi/safi isn't configured at all or smth. */
5480 if (!table)
5481 return;
dc83d712 5482
9bcb3eef 5483 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5484 struct bgp_path_info *pi, *next;
d62a17ae 5485 struct bgp_adj_in *ain;
5486 struct bgp_adj_in *ain_next;
5487
5488 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5489 * queued for every clearing peer, regardless of whether it is
5490 * relevant to the peer at hand.
5491 *
5492 * Overview: There are 3 different indices which need to be
5493 * scrubbed, potentially, when a peer is removed:
5494 *
5495 * 1 peer's routes visible via the RIB (ie accepted routes)
5496 * 2 peer's routes visible by the (optional) peer's adj-in index
5497 * 3 other routes visible by the peer's adj-out index
5498 *
5499 * 3 there is no hurry in scrubbing, once the struct peer is
5500 * removed from bgp->peer, we could just GC such deleted peer's
5501 * adj-outs at our leisure.
5502 *
5503 * 1 and 2 must be 'scrubbed' in some way, at least made
5504 * invisible via RIB index before peer session is allowed to be
5505 * brought back up. So one needs to know when such a 'search' is
5506 * complete.
5507 *
5508 * Ideally:
5509 *
5510 * - there'd be a single global queue or a single RIB walker
5511 * - rather than tracking which route_nodes still need to be
5512 * examined on a peer basis, we'd track which peers still
5513 * aren't cleared
5514 *
5515 * Given that our per-peer prefix-counts now should be reliable,
5516 * this may actually be achievable. It doesn't seem to be a huge
5517 * problem at this time,
5518 *
5519 * It is possible that we have multiple paths for a prefix from
5520 * a peer
5521 * if that peer is using AddPath.
5522 */
9bcb3eef 5523 ain = dest->adj_in;
d62a17ae 5524 while (ain) {
5525 ain_next = ain->next;
5526
6a840fd9 5527 if (ain->peer == peer)
9bcb3eef 5528 bgp_adj_in_remove(dest, ain);
d62a17ae 5529
5530 ain = ain_next;
5531 }
5532
9bcb3eef 5533 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5534 next = pi->next;
5535 if (pi->peer != peer)
d62a17ae 5536 continue;
5537
5538 if (force)
9bcb3eef 5539 bgp_path_info_reap(dest, pi);
d62a17ae 5540 else {
5541 struct bgp_clear_node_queue *cnq;
5542
5543 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5544 bgp_table_lock(bgp_dest_table(dest));
5545 bgp_dest_lock_node(dest);
d62a17ae 5546 cnq = XCALLOC(
5547 MTYPE_BGP_CLEAR_NODE_QUEUE,
5548 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5549 cnq->dest = dest;
d62a17ae 5550 work_queue_add(peer->clear_node_queue, cnq);
5551 break;
5552 }
5553 }
5554 }
5555 return;
5556}
5557
5558void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5559{
9bcb3eef 5560 struct bgp_dest *dest;
d62a17ae 5561 struct bgp_table *table;
5562
5563 if (peer->clear_node_queue == NULL)
5564 bgp_clear_node_queue_init(peer);
5565
5566 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5567 * Idle until it receives a Clearing_Completed event. This protects
5568 * against peers which flap faster than we can we clear, which could
5569 * lead to:
5570 *
5571 * a) race with routes from the new session being installed before
5572 * clear_route_node visits the node (to delete the route of that
5573 * peer)
5574 * b) resource exhaustion, clear_route_node likely leads to an entry
5575 * on the process_main queue. Fast-flapping could cause that queue
5576 * to grow and grow.
5577 */
5578
5579 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5580 * the unlock will happen upon work-queue completion; other wise, the
5581 * unlock happens at the end of this function.
5582 */
5583 if (!peer->clear_node_queue->thread)
5584 peer_lock(peer);
5585
5586 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5587 bgp_clear_route_table(peer, afi, safi, NULL);
5588 else
9bcb3eef
DS
5589 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5590 dest = bgp_route_next(dest)) {
5591 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5592 if (!table)
5593 continue;
5594
5595 bgp_clear_route_table(peer, afi, safi, table);
5596 }
d62a17ae 5597
5598 /* unlock if no nodes got added to the clear-node-queue. */
5599 if (!peer->clear_node_queue->thread)
5600 peer_unlock(peer);
718e3744 5601}
d62a17ae 5602
5603void bgp_clear_route_all(struct peer *peer)
718e3744 5604{
d62a17ae 5605 afi_t afi;
5606 safi_t safi;
718e3744 5607
05c7a1cc
QY
5608 FOREACH_AFI_SAFI (afi, safi)
5609 bgp_clear_route(peer, afi, safi);
65efcfce 5610
49e5a4a0 5611#ifdef ENABLE_BGP_VNC
d62a17ae 5612 rfapiProcessPeerDown(peer);
65efcfce 5613#endif
718e3744 5614}
5615
d62a17ae 5616void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5617{
d62a17ae 5618 struct bgp_table *table;
9bcb3eef 5619 struct bgp_dest *dest;
d62a17ae 5620 struct bgp_adj_in *ain;
5621 struct bgp_adj_in *ain_next;
718e3744 5622
d62a17ae 5623 table = peer->bgp->rib[afi][safi];
718e3744 5624
d62a17ae 5625 /* It is possible that we have multiple paths for a prefix from a peer
5626 * if that peer is using AddPath.
5627 */
9bcb3eef
DS
5628 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5629 ain = dest->adj_in;
43143c8f 5630
d62a17ae 5631 while (ain) {
5632 ain_next = ain->next;
43143c8f 5633
6a840fd9 5634 if (ain->peer == peer)
9bcb3eef 5635 bgp_adj_in_remove(dest, ain);
43143c8f 5636
d62a17ae 5637 ain = ain_next;
5638 }
5639 }
718e3744 5640}
93406d87 5641
1479ed2f
DA
5642/* If any of the routes from the peer have been marked with the NO_LLGR
5643 * community, either as sent by the peer, or as the result of a configured
5644 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5645 * operation of [RFC4271].
5646 */
d62a17ae 5647void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5648{
9bcb3eef 5649 struct bgp_dest *dest;
40381db7 5650 struct bgp_path_info *pi;
d62a17ae 5651 struct bgp_table *table;
5652
9af52ccf 5653 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5654 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5655 dest = bgp_route_next(dest)) {
5656 struct bgp_dest *rm;
d62a17ae 5657
5658 /* look for neighbor in tables */
9bcb3eef 5659 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5660 if (!table)
ea47320b
DL
5661 continue;
5662
5663 for (rm = bgp_table_top(table); rm;
5664 rm = bgp_route_next(rm))
9bcb3eef 5665 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5666 pi = pi->next) {
40381db7 5667 if (pi->peer != peer)
ea47320b 5668 continue;
1479ed2f
DA
5669 if (CHECK_FLAG(
5670 peer->af_sflags[afi][safi],
5671 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5672 bgp_attr_get_community(pi->attr) &&
1479ed2f 5673 !community_include(
9a706b42
DA
5674 bgp_attr_get_community(
5675 pi->attr),
1479ed2f 5676 COMMUNITY_NO_LLGR))
e3015d91 5677 continue;
40381db7 5678 if (!CHECK_FLAG(pi->flags,
1defdda8 5679 BGP_PATH_STALE))
e3015d91 5680 continue;
ea47320b 5681
641065d4
KM
5682 /*
5683 * If this is VRF leaked route
5684 * process for withdraw.
5685 */
5686 if (pi->sub_type ==
5687 BGP_ROUTE_IMPORTED &&
5688 peer->bgp->inst_type ==
5689 BGP_INSTANCE_TYPE_DEFAULT)
1aa2c93e 5690 vpn_leak_to_vrf_withdraw(pi);
641065d4 5691
40381db7 5692 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5693 break;
5694 }
d62a17ae 5695 }
5696 } else {
9bcb3eef
DS
5697 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5698 dest = bgp_route_next(dest))
5699 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5700 pi = pi->next) {
40381db7 5701 if (pi->peer != peer)
ea47320b 5702 continue;
1479ed2f
DA
5703 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5704 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5705 bgp_attr_get_community(pi->attr) &&
5706 !community_include(
5707 bgp_attr_get_community(pi->attr),
5708 COMMUNITY_NO_LLGR))
e3015d91 5709 continue;
40381db7 5710 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5711 continue;
641065d4
KM
5712 if (safi == SAFI_UNICAST &&
5713 (peer->bgp->inst_type ==
5714 BGP_INSTANCE_TYPE_VRF ||
5715 peer->bgp->inst_type ==
5716 BGP_INSTANCE_TYPE_DEFAULT))
5717 vpn_leak_from_vrf_withdraw(
5718 bgp_get_default(), peer->bgp,
5719 pi);
5720
9bcb3eef 5721 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5722 break;
5723 }
d62a17ae 5724 }
93406d87 5725}
6b0655a2 5726
9af52ccf
DA
5727void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5728{
5729 struct bgp_dest *dest, *ndest;
5730 struct bgp_path_info *pi;
5731 struct bgp_table *table;
5732
5733 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5734 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5735 dest = bgp_route_next(dest)) {
5736 table = bgp_dest_get_bgp_table_info(dest);
5737 if (!table)
5738 continue;
5739
5740 for (ndest = bgp_table_top(table); ndest;
5741 ndest = bgp_route_next(ndest)) {
5742 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5743 pi = pi->next) {
5744 if (pi->peer != peer)
5745 continue;
5746
5747 if ((CHECK_FLAG(
5748 peer->af_sflags[afi][safi],
5749 PEER_STATUS_ENHANCED_REFRESH))
5750 && !CHECK_FLAG(pi->flags,
5751 BGP_PATH_STALE)
5752 && !CHECK_FLAG(
5753 pi->flags,
5754 BGP_PATH_UNUSEABLE)) {
5755 if (bgp_debug_neighbor_events(
5756 peer))
5757 zlog_debug(
58e111f6
DA
5758 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5759 peer,
9af52ccf
DA
5760 afi2str(afi),
5761 safi2str(safi),
5762 bgp_dest_get_prefix(
5763 ndest));
5764
5765 bgp_path_info_set_flag(
5766 ndest, pi,
5767 BGP_PATH_STALE);
5768 }
5769 }
5770 }
5771 }
5772 } else {
5773 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5774 dest = bgp_route_next(dest)) {
5775 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5776 pi = pi->next) {
5777 if (pi->peer != peer)
5778 continue;
5779
5780 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5781 PEER_STATUS_ENHANCED_REFRESH))
5782 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5783 && !CHECK_FLAG(pi->flags,
5784 BGP_PATH_UNUSEABLE)) {
5785 if (bgp_debug_neighbor_events(peer))
5786 zlog_debug(
58e111f6
DA
5787 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5788 peer, afi2str(afi),
9af52ccf
DA
5789 safi2str(safi),
5790 bgp_dest_get_prefix(
5791 dest));
5792
5793 bgp_path_info_set_flag(dest, pi,
5794 BGP_PATH_STALE);
5795 }
5796 }
5797 }
5798 }
5799}
5800
3dc339cd 5801bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5802{
e0df4c04 5803 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5804 return true;
e0df4c04 5805
9dac9fc8
DA
5806 if (peer->sort == BGP_PEER_EBGP
5807 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5808 || FILTER_LIST_OUT_NAME(filter)
5809 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5810 return true;
5811 return false;
9dac9fc8
DA
5812}
5813
3dc339cd 5814bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5815{
e0df4c04 5816 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5817 return true;
e0df4c04 5818
9dac9fc8
DA
5819 if (peer->sort == BGP_PEER_EBGP
5820 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5821 || FILTER_LIST_IN_NAME(filter)
5822 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5823 return true;
5824 return false;
9dac9fc8
DA
5825}
5826
568e10ca 5827static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5828 safi_t safi)
bb86c601 5829{
9bcb3eef 5830 struct bgp_dest *dest;
40381db7 5831 struct bgp_path_info *pi;
4b7e6066 5832 struct bgp_path_info *next;
bb86c601 5833
9bcb3eef
DS
5834 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5835 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5836 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5837
40381db7 5838 next = pi->next;
1b7bb747
CS
5839
5840 /* Unimport EVPN routes from VRFs */
5841 if (safi == SAFI_EVPN)
5842 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5843 SAFI_EVPN, p, pi);
1b7bb747 5844
40381db7
DS
5845 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5846 && pi->type == ZEBRA_ROUTE_BGP
5847 && (pi->sub_type == BGP_ROUTE_NORMAL
5848 || pi->sub_type == BGP_ROUTE_AGGREGATE
5849 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5850
d62a17ae 5851 if (bgp_fibupd_safi(safi))
b54892e0 5852 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5853 }
9514b37d 5854
9bcb3eef 5855 bgp_path_info_reap(dest, pi);
d62a17ae 5856 }
bb86c601
LB
5857}
5858
718e3744 5859/* Delete all kernel routes. */
d62a17ae 5860void bgp_cleanup_routes(struct bgp *bgp)
5861{
5862 afi_t afi;
9bcb3eef 5863 struct bgp_dest *dest;
67009e22 5864 struct bgp_table *table;
d62a17ae 5865
5866 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5867 if (afi == AFI_L2VPN)
5868 continue;
568e10ca 5869 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5870 SAFI_UNICAST);
d62a17ae 5871 /*
5872 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5873 */
5874 if (afi != AFI_L2VPN) {
5875 safi_t safi;
5876 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5877 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5878 dest = bgp_route_next(dest)) {
5879 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5880 if (table != NULL) {
5881 bgp_cleanup_table(bgp, table, safi);
5882 bgp_table_finish(&table);
9bcb3eef
DS
5883 bgp_dest_set_bgp_table_info(dest, NULL);
5884 bgp_dest_unlock_node(dest);
d62a17ae 5885 }
5886 }
5887 safi = SAFI_ENCAP;
9bcb3eef
DS
5888 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5889 dest = bgp_route_next(dest)) {
5890 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5891 if (table != NULL) {
5892 bgp_cleanup_table(bgp, table, safi);
5893 bgp_table_finish(&table);
9bcb3eef
DS
5894 bgp_dest_set_bgp_table_info(dest, NULL);
5895 bgp_dest_unlock_node(dest);
d62a17ae 5896 }
5897 }
5898 }
5899 }
9bcb3eef
DS
5900 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5901 dest = bgp_route_next(dest)) {
5902 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5903 if (table != NULL) {
5904 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5905 bgp_table_finish(&table);
9bcb3eef
DS
5906 bgp_dest_set_bgp_table_info(dest, NULL);
5907 bgp_dest_unlock_node(dest);
d62a17ae 5908 }
bb86c601 5909 }
718e3744 5910}
5911
d62a17ae 5912void bgp_reset(void)
718e3744 5913{
d62a17ae 5914 vty_reset();
5915 bgp_zclient_reset();
5916 access_list_reset();
5917 prefix_list_reset();
718e3744 5918}
6b0655a2 5919
be92fc9f 5920bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5921{
d62a17ae 5922 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5923 && CHECK_FLAG(peer->af_cap[afi][safi],
5924 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5925}
5926
718e3744 5927/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5928 value. */
d62a17ae 5929int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5930 struct bgp_nlri *packet)
5931{
d7c0a89a
QY
5932 uint8_t *pnt;
5933 uint8_t *lim;
d62a17ae 5934 struct prefix p;
5935 int psize;
d62a17ae 5936 afi_t afi;
5937 safi_t safi;
be92fc9f 5938 bool addpath_capable;
d7c0a89a 5939 uint32_t addpath_id;
d62a17ae 5940
d62a17ae 5941 pnt = packet->nlri;
5942 lim = pnt + packet->length;
5943 afi = packet->afi;
5944 safi = packet->safi;
5945 addpath_id = 0;
be92fc9f 5946 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5947
5948 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5949 syntactic validity. If the field is syntactically incorrect,
5950 then the Error Subcode is set to Invalid Network Field. */
5951 for (; pnt < lim; pnt += psize) {
5952 /* Clear prefix structure. */
6006b807 5953 memset(&p, 0, sizeof(p));
d62a17ae 5954
be92fc9f 5955 if (addpath_capable) {
d62a17ae 5956
5957 /* When packet overflow occurs return immediately. */
761ed665 5958 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5959 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5960
a3a850a1 5961 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5962 addpath_id = ntohl(addpath_id);
d62a17ae 5963 pnt += BGP_ADDPATH_ID_LEN;
5964 }
718e3744 5965
d62a17ae 5966 /* Fetch prefix length. */
5967 p.prefixlen = *pnt++;
5968 /* afi/safi validity already verified by caller,
5969 * bgp_update_receive */
5970 p.family = afi2family(afi);
5971
5972 /* Prefix length check. */
5973 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5974 flog_err(
e50f7cfd 5975 EC_BGP_UPDATE_RCV,
14454c9f 5976 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5977 peer->host, p.prefixlen, packet->afi);
513386b5 5978 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5979 }
6b0655a2 5980
d62a17ae 5981 /* Packet size overflow check. */
5982 psize = PSIZE(p.prefixlen);
5983
5984 /* When packet overflow occur return immediately. */
5985 if (pnt + psize > lim) {
af4c2728 5986 flog_err(
e50f7cfd 5987 EC_BGP_UPDATE_RCV,
d62a17ae 5988 "%s [Error] Update packet error (prefix length %d overflows packet)",
5989 peer->host, p.prefixlen);
513386b5 5990 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5991 }
5992
5993 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5994 * prefix for the v4 and v6 afi's and unicast/multicast */
5995 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5996 flog_err(
e50f7cfd 5997 EC_BGP_UPDATE_RCV,
d62a17ae 5998 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5999 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6000 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6001 }
6002
6003 /* Fetch prefix from NLRI packet. */
a85297a7 6004 memcpy(p.u.val, pnt, psize);
d62a17ae 6005
6006 /* Check address. */
6007 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6008 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6009 /* From RFC4271 Section 6.3:
6010 *
6011 * If a prefix in the NLRI field is semantically
6012 * incorrect
6013 * (e.g., an unexpected multicast IP address),
6014 * an error SHOULD
6015 * be logged locally, and the prefix SHOULD be
6016 * ignored.
a4d82a8a 6017 */
af4c2728 6018 flog_err(
e50f7cfd 6019 EC_BGP_UPDATE_RCV,
23d0a753
DA
6020 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6021 peer->host, &p.u.prefix4);
d62a17ae 6022 continue;
6023 }
6024 }
6025
6026 /* Check address. */
6027 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6028 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6029 flog_err(
e50f7cfd 6030 EC_BGP_UPDATE_RCV,
c0d72166
DS
6031 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6032 peer->host, &p.u.prefix6);
d62a17ae 6033
6034 continue;
6035 }
6036 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6037 flog_err(
e50f7cfd 6038 EC_BGP_UPDATE_RCV,
c0d72166
DS
6039 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6040 peer->host, &p.u.prefix6);
d62a17ae 6041
6042 continue;
6043 }
6044 }
6045
6046 /* Normal process. */
6047 if (attr)
367b458c
DS
6048 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6049 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6050 NULL, 0, 0, NULL);
d62a17ae 6051 else
367b458c
DS
6052 bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
6053 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6054 NULL, 0, NULL);
d62a17ae 6055
513386b5
DA
6056 /* Do not send BGP notification twice when maximum-prefix count
6057 * overflow. */
6058 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6059 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6060 }
6061
6062 /* Packet length consistency check. */
6063 if (pnt != lim) {
af4c2728 6064 flog_err(
e50f7cfd 6065 EC_BGP_UPDATE_RCV,
d62a17ae 6066 "%s [Error] Update packet error (prefix length mismatch with total length)",
6067 peer->host);
513386b5 6068 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6069 }
6b0655a2 6070
513386b5 6071 return BGP_NLRI_PARSE_OK;
718e3744 6072}
6073
d62a17ae 6074static struct bgp_static *bgp_static_new(void)
718e3744 6075{
d62a17ae 6076 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6077}
6078
d62a17ae 6079static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6080{
0a22ddfb 6081 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6082 route_map_counter_decrement(bgp_static->rmap.map);
6083
0a22ddfb 6084 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6085 XFREE(MTYPE_BGP_STATIC, bgp_static);
6086}
6087
5f040085 6088void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6089 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6090{
9bcb3eef 6091 struct bgp_dest *dest;
40381db7 6092 struct bgp_path_info *pi;
4b7e6066 6093 struct bgp_path_info *new;
40381db7 6094 struct bgp_path_info rmap_path;
d62a17ae 6095 struct attr attr;
6096 struct attr *attr_new;
b68885f9 6097 route_map_result_t ret;
49e5a4a0 6098#ifdef ENABLE_BGP_VNC
d62a17ae 6099 int vnc_implicit_withdraw = 0;
65efcfce 6100#endif
fee0f4c6 6101
d62a17ae 6102 assert(bgp_static);
dd8103a9 6103
9bcb3eef 6104 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6105
0f05ea43 6106 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6107
d62a17ae 6108 attr.nexthop = bgp_static->igpnexthop;
6109 attr.med = bgp_static->igpmetric;
6110 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6111
7226bc40
TA
6112 if (afi == AFI_IP)
6113 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6114
97a52c82
DA
6115 if (bgp_static->igpmetric)
6116 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6117
d62a17ae 6118 if (bgp_static->atomic)
6119 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6120
d62a17ae 6121 /* Store label index, if required. */
6122 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6123 attr.label_index = bgp_static->label_index;
6124 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6125 }
718e3744 6126
d62a17ae 6127 /* Apply route-map. */
6128 if (bgp_static->rmap.name) {
6129 struct attr attr_tmp = attr;
80ced710 6130
6006b807 6131 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6132 rmap_path.peer = bgp->peer_self;
6133 rmap_path.attr = &attr_tmp;
fee0f4c6 6134
d62a17ae 6135 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6136
1782514f 6137 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6138
d62a17ae 6139 bgp->peer_self->rmap_type = 0;
718e3744 6140
d62a17ae 6141 if (ret == RMAP_DENYMATCH) {
6142 /* Free uninterned attribute. */
6143 bgp_attr_flush(&attr_tmp);
718e3744 6144
d62a17ae 6145 /* Unintern original. */
6146 aspath_unintern(&attr.aspath);
6147 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6148 bgp_dest_unlock_node(dest);
d62a17ae 6149 return;
6150 }
7f323236 6151
637e5ba4 6152 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6153 bgp_attr_add_gshut_community(&attr_tmp);
6154
d62a17ae 6155 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6156 } else {
6157
637e5ba4 6158 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6159 bgp_attr_add_gshut_community(&attr);
6160
d62a17ae 6161 attr_new = bgp_attr_intern(&attr);
7f323236 6162 }
718e3744 6163
9bcb3eef 6164 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6165 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6166 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6167 break;
6168
40381db7
DS
6169 if (pi) {
6170 if (attrhash_cmp(pi->attr, attr_new)
6171 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6172 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6173 bgp_dest_unlock_node(dest);
d62a17ae 6174 bgp_attr_unintern(&attr_new);
6175 aspath_unintern(&attr.aspath);
6176 return;
6177 } else {
6178 /* The attribute is changed. */
9bcb3eef 6179 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6180
6181 /* Rewrite BGP route information. */
40381db7 6182 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6183 bgp_path_info_restore(dest, pi);
d62a17ae 6184 else
40381db7 6185 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6186#ifdef ENABLE_BGP_VNC
d62a17ae 6187 if ((afi == AFI_IP || afi == AFI_IP6)
6188 && (safi == SAFI_UNICAST)) {
40381db7 6189 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6190 /*
6191 * Implicit withdraw case.
40381db7 6192 * We have to do this before pi is
d62a17ae 6193 * changed
6194 */
6195 ++vnc_implicit_withdraw;
40381db7 6196 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6197 vnc_import_bgp_exterior_del_route(
40381db7 6198 bgp, p, pi);
d62a17ae 6199 }
6200 }
65efcfce 6201#endif
40381db7
DS
6202 bgp_attr_unintern(&pi->attr);
6203 pi->attr = attr_new;
083ec940 6204 pi->uptime = monotime(NULL);
49e5a4a0 6205#ifdef ENABLE_BGP_VNC
d62a17ae 6206 if ((afi == AFI_IP || afi == AFI_IP6)
6207 && (safi == SAFI_UNICAST)) {
6208 if (vnc_implicit_withdraw) {
40381db7 6209 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6210 vnc_import_bgp_exterior_add_route(
40381db7 6211 bgp, p, pi);
d62a17ae 6212 }
6213 }
65efcfce 6214#endif
718e3744 6215
d62a17ae 6216 /* Nexthop reachability check. */
892fedb6 6217 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6218 && (safi == SAFI_UNICAST
6219 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6220
6221 struct bgp *bgp_nexthop = bgp;
6222
40381db7
DS
6223 if (pi->extra && pi->extra->bgp_orig)
6224 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6225
6226 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6227 afi, safi, pi, NULL,
654a5978 6228 0, p))
9bcb3eef 6229 bgp_path_info_set_flag(dest, pi,
18ee8310 6230 BGP_PATH_VALID);
d62a17ae 6231 else {
6232 if (BGP_DEBUG(nht, NHT)) {
6233 char buf1[INET6_ADDRSTRLEN];
6234 inet_ntop(p->family,
6235 &p->u.prefix, buf1,
07380148 6236 sizeof(buf1));
d62a17ae 6237 zlog_debug(
6238 "%s(%s): Route not in table, not advertising",
15569c58 6239 __func__, buf1);
d62a17ae 6240 }
18ee8310 6241 bgp_path_info_unset_flag(
9bcb3eef 6242 dest, pi, BGP_PATH_VALID);
d62a17ae 6243 }
6244 } else {
6245 /* Delete the NHT structure if any, if we're
6246 * toggling between
6247 * enabling/disabling import check. We
6248 * deregister the route
6249 * from NHT to avoid overloading NHT and the
6250 * process interaction
6251 */
40381db7 6252 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6253 bgp_path_info_set_flag(dest, pi,
6254 BGP_PATH_VALID);
d62a17ae 6255 }
6256 /* Process change. */
40381db7 6257 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6258 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6259
6260 if (SAFI_UNICAST == safi
6261 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6262 || bgp->inst_type
6263 == BGP_INSTANCE_TYPE_DEFAULT)) {
6264 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6265 pi);
ddb5b488
PZ
6266 }
6267
9bcb3eef 6268 bgp_dest_unlock_node(dest);
d62a17ae 6269 aspath_unintern(&attr.aspath);
6270 return;
6271 }
718e3744 6272 }
718e3744 6273
d62a17ae 6274 /* Make new BGP info. */
6275 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6276 attr_new, dest);
d62a17ae 6277 /* Nexthop reachability check. */
892fedb6 6278 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6279 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6280 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6281 p))
9bcb3eef 6282 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6283 else {
6284 if (BGP_DEBUG(nht, NHT)) {
6285 char buf1[INET6_ADDRSTRLEN];
07380148 6286
d62a17ae 6287 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6288 sizeof(buf1));
d62a17ae 6289 zlog_debug(
6290 "%s(%s): Route not in table, not advertising",
15569c58 6291 __func__, buf1);
d62a17ae 6292 }
9bcb3eef 6293 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6294 }
6295 } else {
6296 /* Delete the NHT structure if any, if we're toggling between
6297 * enabling/disabling import check. We deregister the route
6298 * from NHT to avoid overloading NHT and the process interaction
6299 */
6300 bgp_unlink_nexthop(new);
6301
9bcb3eef 6302 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6303 }
078430f6 6304
d62a17ae 6305 /* Aggregate address increment. */
6306 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6307
d62a17ae 6308 /* Register new BGP information. */
9bcb3eef 6309 bgp_path_info_add(dest, new);
718e3744 6310
d62a17ae 6311 /* route_node_get lock */
9bcb3eef 6312 bgp_dest_unlock_node(dest);
d62a17ae 6313
6314 /* Process change. */
9bcb3eef 6315 bgp_process(bgp, dest, afi, safi);
d62a17ae 6316
ddb5b488
PZ
6317 if (SAFI_UNICAST == safi
6318 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6319 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6320 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6321 }
6322
d62a17ae 6323 /* Unintern original. */
6324 aspath_unintern(&attr.aspath);
718e3744 6325}
6326
5f040085 6327void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6328 safi_t safi)
718e3744 6329{
9bcb3eef 6330 struct bgp_dest *dest;
40381db7 6331 struct bgp_path_info *pi;
718e3744 6332
9bcb3eef 6333 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6334
d62a17ae 6335 /* Check selected route and self inserted route. */
9bcb3eef 6336 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6337 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6338 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6339 break;
6340
6341 /* Withdraw static BGP route from routing table. */
40381db7 6342 if (pi) {
ddb5b488
PZ
6343 if (SAFI_UNICAST == safi
6344 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6345 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6346 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6347 }
40381db7
DS
6348 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6349 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6350 bgp_path_info_delete(dest, pi);
6351 bgp_process(bgp, dest, afi, safi);
d62a17ae 6352 }
718e3744 6353
d62a17ae 6354 /* Unlock bgp_node_lookup. */
9bcb3eef 6355 bgp_dest_unlock_node(dest);
718e3744 6356}
6357
137446f9
LB
6358/*
6359 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6360 */
5f040085 6361static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6362 afi_t afi, safi_t safi,
6363 struct prefix_rd *prd)
718e3744 6364{
9bcb3eef 6365 struct bgp_dest *dest;
40381db7 6366 struct bgp_path_info *pi;
718e3744 6367
9bcb3eef 6368 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6369
d62a17ae 6370 /* Check selected route and self inserted route. */
9bcb3eef 6371 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6372 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6373 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6374 break;
718e3744 6375
d62a17ae 6376 /* Withdraw static BGP route from routing table. */
40381db7 6377 if (pi) {
49e5a4a0 6378#ifdef ENABLE_BGP_VNC
d62a17ae 6379 rfapiProcessWithdraw(
40381db7 6380 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6381 1); /* Kill, since it is an administrative change */
65efcfce 6382#endif
ddb5b488
PZ
6383 if (SAFI_MPLS_VPN == safi
6384 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
1aa2c93e 6385 vpn_leak_to_vrf_withdraw(pi);
ddb5b488 6386 }
40381db7 6387 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6388 bgp_path_info_delete(dest, pi);
6389 bgp_process(bgp, dest, afi, safi);
d62a17ae 6390 }
718e3744 6391
d62a17ae 6392 /* Unlock bgp_node_lookup. */
9bcb3eef 6393 bgp_dest_unlock_node(dest);
718e3744 6394}
6395
5f040085 6396static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6397 struct bgp_static *bgp_static, afi_t afi,
6398 safi_t safi)
137446f9 6399{
9bcb3eef 6400 struct bgp_dest *dest;
4b7e6066 6401 struct bgp_path_info *new;
d62a17ae 6402 struct attr *attr_new;
6403 struct attr attr = {0};
40381db7 6404 struct bgp_path_info *pi;
49e5a4a0 6405#ifdef ENABLE_BGP_VNC
d62a17ae 6406 mpls_label_t label = 0;
65efcfce 6407#endif
d7c0a89a 6408 uint32_t num_labels = 0;
137446f9 6409
d62a17ae 6410 assert(bgp_static);
137446f9 6411
b57ba6d2
MK
6412 if (bgp_static->label != MPLS_INVALID_LABEL)
6413 num_labels = 1;
9bcb3eef
DS
6414 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6415 &bgp_static->prd);
137446f9 6416
0f05ea43 6417 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6418
d62a17ae 6419 attr.nexthop = bgp_static->igpnexthop;
6420 attr.med = bgp_static->igpmetric;
6421 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6422
d62a17ae 6423 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6424 || (safi == SAFI_ENCAP)) {
6425 if (afi == AFI_IP) {
6426 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6427 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6428 }
6429 }
6430 if (afi == AFI_L2VPN) {
b04c1e99
IR
6431 if (bgp_static->gatewayIp.family == AF_INET) {
6432 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6433 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6434 &bgp_static->gatewayIp.u.prefix4,
6435 IPV4_MAX_BYTELEN);
b04c1e99
IR
6436 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6437 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6438 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6439 &bgp_static->gatewayIp.u.prefix6,
6440 IPV6_MAX_BYTELEN);
b04c1e99 6441 }
0a50c248 6442 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6443 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6444 struct bgp_encap_type_vxlan bet;
6006b807 6445 memset(&bet, 0, sizeof(bet));
3714a385 6446 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6447 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6448 }
6449 if (bgp_static->router_mac) {
6450 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6451 }
6452 }
6453 /* Apply route-map. */
6454 if (bgp_static->rmap.name) {
6455 struct attr attr_tmp = attr;
40381db7 6456 struct bgp_path_info rmap_path;
b68885f9 6457 route_map_result_t ret;
137446f9 6458
40381db7
DS
6459 rmap_path.peer = bgp->peer_self;
6460 rmap_path.attr = &attr_tmp;
137446f9 6461
d62a17ae 6462 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6463
1782514f 6464 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6465
d62a17ae 6466 bgp->peer_self->rmap_type = 0;
137446f9 6467
d62a17ae 6468 if (ret == RMAP_DENYMATCH) {
6469 /* Free uninterned attribute. */
6470 bgp_attr_flush(&attr_tmp);
137446f9 6471
d62a17ae 6472 /* Unintern original. */
6473 aspath_unintern(&attr.aspath);
6474 bgp_static_withdraw_safi(bgp, p, afi, safi,
6475 &bgp_static->prd);
bbc52106 6476 bgp_dest_unlock_node(dest);
d62a17ae 6477 return;
6478 }
137446f9 6479
d62a17ae 6480 attr_new = bgp_attr_intern(&attr_tmp);
6481 } else {
6482 attr_new = bgp_attr_intern(&attr);
6483 }
137446f9 6484
9bcb3eef 6485 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6486 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6487 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6488 break;
6489
40381db7 6490 if (pi) {
40381db7 6491 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6492 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6493 bgp_dest_unlock_node(dest);
d62a17ae 6494 bgp_attr_unintern(&attr_new);
6495 aspath_unintern(&attr.aspath);
6496 return;
6497 } else {
6498 /* The attribute is changed. */
9bcb3eef 6499 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6500
6501 /* Rewrite BGP route information. */
40381db7 6502 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6503 bgp_path_info_restore(dest, pi);
d62a17ae 6504 else
40381db7
DS
6505 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6506 bgp_attr_unintern(&pi->attr);
6507 pi->attr = attr_new;
083ec940 6508 pi->uptime = monotime(NULL);
49e5a4a0 6509#ifdef ENABLE_BGP_VNC
40381db7
DS
6510 if (pi->extra)
6511 label = decode_label(&pi->extra->label[0]);
65efcfce 6512#endif
137446f9 6513
d62a17ae 6514 /* Process change. */
40381db7 6515 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6516 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6517
6518 if (SAFI_MPLS_VPN == safi
6519 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6520 vpn_leak_to_vrf_update(bgp, pi,
6521 &bgp_static->prd);
ddb5b488 6522 }
49e5a4a0 6523#ifdef ENABLE_BGP_VNC
40381db7
DS
6524 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6525 pi->attr, afi, safi, pi->type,
6526 pi->sub_type, &label);
65efcfce 6527#endif
9bcb3eef 6528 bgp_dest_unlock_node(dest);
d62a17ae 6529 aspath_unintern(&attr.aspath);
6530 return;
6531 }
6532 }
137446f9
LB
6533
6534
d62a17ae 6535 /* Make new BGP info. */
6536 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6537 attr_new, dest);
1defdda8 6538 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6539 bgp_path_info_extra_get(new);
b57ba6d2
MK
6540 if (num_labels) {
6541 new->extra->label[0] = bgp_static->label;
6542 new->extra->num_labels = num_labels;
6543 }
49e5a4a0 6544#ifdef ENABLE_BGP_VNC
d62a17ae 6545 label = decode_label(&bgp_static->label);
65efcfce 6546#endif
137446f9 6547
d62a17ae 6548 /* Aggregate address increment. */
6549 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6550
d62a17ae 6551 /* Register new BGP information. */
9bcb3eef 6552 bgp_path_info_add(dest, new);
d62a17ae 6553 /* route_node_get lock */
9bcb3eef 6554 bgp_dest_unlock_node(dest);
137446f9 6555
d62a17ae 6556 /* Process change. */
9bcb3eef 6557 bgp_process(bgp, dest, afi, safi);
137446f9 6558
ddb5b488
PZ
6559 if (SAFI_MPLS_VPN == safi
6560 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6561 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6562 }
49e5a4a0 6563#ifdef ENABLE_BGP_VNC
d62a17ae 6564 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6565 safi, new->type, new->sub_type, &label);
65efcfce
LB
6566#endif
6567
d62a17ae 6568 /* Unintern original. */
6569 aspath_unintern(&attr.aspath);
137446f9
LB
6570}
6571
718e3744 6572/* Configure static BGP network. When user don't run zebra, static
6573 route should be installed as valid. */
585f1adc
IR
6574static int bgp_static_set(struct vty *vty, const char *negate,
6575 const char *ip_str, afi_t afi, safi_t safi,
6576 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6577{
585f1adc
IR
6578 VTY_DECLVAR_CONTEXT(bgp, bgp);
6579 int ret;
d62a17ae 6580 struct prefix p;
6581 struct bgp_static *bgp_static;
9bcb3eef 6582 struct bgp_dest *dest;
d7c0a89a 6583 uint8_t need_update = 0;
d62a17ae 6584
585f1adc
IR
6585 /* Convert IP prefix string to struct prefix. */
6586 ret = str2prefix(ip_str, &p);
6587 if (!ret) {
6588 vty_out(vty, "%% Malformed prefix\n");
6589 return CMD_WARNING_CONFIG_FAILED;
6590 }
6591 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6592 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6593 return CMD_WARNING_CONFIG_FAILED;
6594 }
6595
d62a17ae 6596 apply_mask(&p);
718e3744 6597
e2a86ad9 6598 if (negate) {
718e3744 6599
e2a86ad9 6600 /* Set BGP static route configuration. */
9bcb3eef 6601 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6602
9bcb3eef 6603 if (!dest) {
585f1adc
IR
6604 vty_out(vty, "%% Can't find static route specified\n");
6605 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6606 }
6607
9bcb3eef 6608 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6609
e2a86ad9
DS
6610 if ((label_index != BGP_INVALID_LABEL_INDEX)
6611 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6612 vty_out(vty,
6613 "%% label-index doesn't match static route\n");
70d9b134 6614 bgp_dest_unlock_node(dest);
585f1adc 6615 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6616 }
d62a17ae 6617
e2a86ad9
DS
6618 if ((rmap && bgp_static->rmap.name)
6619 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6620 vty_out(vty,
6621 "%% route-map name doesn't match static route\n");
70d9b134 6622 bgp_dest_unlock_node(dest);
585f1adc 6623 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6624 }
718e3744 6625
e2a86ad9
DS
6626 /* Update BGP RIB. */
6627 if (!bgp_static->backdoor)
6628 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6629
e2a86ad9
DS
6630 /* Clear configuration. */
6631 bgp_static_free(bgp_static);
9bcb3eef
DS
6632 bgp_dest_set_bgp_static_info(dest, NULL);
6633 bgp_dest_unlock_node(dest);
6634 bgp_dest_unlock_node(dest);
e2a86ad9 6635 } else {
718e3744 6636
e2a86ad9 6637 /* Set BGP static route configuration. */
9bcb3eef
DS
6638 dest = bgp_node_get(bgp->route[afi][safi], &p);
6639 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6640 if (bgp_static) {
e2a86ad9 6641 /* Configuration change. */
e2a86ad9
DS
6642 /* Label index cannot be changed. */
6643 if (bgp_static->label_index != label_index) {
585f1adc 6644 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6645 bgp_dest_unlock_node(dest);
585f1adc 6646 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6647 }
d62a17ae 6648
e2a86ad9 6649 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6650 if (bgp_static->valid
6651 && bgp_static->backdoor != backdoor)
e2a86ad9 6652 need_update = 1;
718e3744 6653
e2a86ad9 6654 bgp_static->backdoor = backdoor;
718e3744 6655
e2a86ad9 6656 if (rmap) {
0a22ddfb
QY
6657 XFREE(MTYPE_ROUTE_MAP_NAME,
6658 bgp_static->rmap.name);
b4897fa5 6659 route_map_counter_decrement(
6660 bgp_static->rmap.map);
e2a86ad9
DS
6661 bgp_static->rmap.name =
6662 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6663 bgp_static->rmap.map =
6664 route_map_lookup_by_name(rmap);
b4897fa5 6665 route_map_counter_increment(
6666 bgp_static->rmap.map);
e2a86ad9 6667 } else {
0a22ddfb
QY
6668 XFREE(MTYPE_ROUTE_MAP_NAME,
6669 bgp_static->rmap.name);
b4897fa5 6670 route_map_counter_decrement(
6671 bgp_static->rmap.map);
e2a86ad9
DS
6672 bgp_static->rmap.map = NULL;
6673 bgp_static->valid = 0;
6674 }
9bcb3eef 6675 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6676 } else {
6677 /* New configuration. */
6678 bgp_static = bgp_static_new();
6679 bgp_static->backdoor = backdoor;
6680 bgp_static->valid = 0;
6681 bgp_static->igpmetric = 0;
975a328e 6682 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6683 bgp_static->label_index = label_index;
718e3744 6684
e2a86ad9 6685 if (rmap) {
0a22ddfb
QY
6686 XFREE(MTYPE_ROUTE_MAP_NAME,
6687 bgp_static->rmap.name);
b4897fa5 6688 route_map_counter_decrement(
6689 bgp_static->rmap.map);
e2a86ad9
DS
6690 bgp_static->rmap.name =
6691 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6692 bgp_static->rmap.map =
6693 route_map_lookup_by_name(rmap);
b4897fa5 6694 route_map_counter_increment(
6695 bgp_static->rmap.map);
e2a86ad9 6696 }
9bcb3eef 6697 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6698 }
d62a17ae 6699
e2a86ad9
DS
6700 bgp_static->valid = 1;
6701 if (need_update)
6702 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6703
e2a86ad9
DS
6704 if (!bgp_static->backdoor)
6705 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6706 }
d62a17ae 6707
585f1adc 6708 return CMD_SUCCESS;
d62a17ae 6709}
6710
6711void bgp_static_add(struct bgp *bgp)
6712{
6713 afi_t afi;
6714 safi_t safi;
9bcb3eef
DS
6715 struct bgp_dest *dest;
6716 struct bgp_dest *rm;
d62a17ae 6717 struct bgp_table *table;
6718 struct bgp_static *bgp_static;
6719
47fc6261 6720 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6721 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6722 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6723 dest = bgp_route_next(dest)) {
6724 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6725 continue;
ea47320b 6726
05c7a1cc
QY
6727 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6728 || (safi == SAFI_EVPN)) {
9bcb3eef 6729 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6730
6731 for (rm = bgp_table_top(table); rm;
6732 rm = bgp_route_next(rm)) {
a78beeb5 6733 bgp_static =
9bcb3eef 6734 bgp_dest_get_bgp_static_info(
5a8ba9fc 6735 rm);
9bcb3eef
DS
6736 bgp_static_update_safi(
6737 bgp, bgp_dest_get_prefix(rm),
6738 bgp_static, afi, safi);
d62a17ae 6739 }
05c7a1cc 6740 } else {
5a8ba9fc 6741 bgp_static_update(
9bcb3eef
DS
6742 bgp, bgp_dest_get_prefix(dest),
6743 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6744 safi);
ea47320b 6745 }
05c7a1cc 6746 }
47fc6261 6747 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6748}
6749
718e3744 6750/* Called from bgp_delete(). Delete all static routes from the BGP
6751 instance. */
d62a17ae 6752void bgp_static_delete(struct bgp *bgp)
6753{
6754 afi_t afi;
6755 safi_t safi;
9bcb3eef
DS
6756 struct bgp_dest *dest;
6757 struct bgp_dest *rm;
d62a17ae 6758 struct bgp_table *table;
6759 struct bgp_static *bgp_static;
6760
05c7a1cc 6761 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6762 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6763 dest = bgp_route_next(dest)) {
6764 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6765 continue;
ea47320b 6766
05c7a1cc
QY
6767 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6768 || (safi == SAFI_EVPN)) {
9bcb3eef 6769 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6770
6771 for (rm = bgp_table_top(table); rm;
6772 rm = bgp_route_next(rm)) {
a78beeb5 6773 bgp_static =
9bcb3eef 6774 bgp_dest_get_bgp_static_info(
5a8ba9fc 6775 rm);
c7d14ba6
PG
6776 if (!bgp_static)
6777 continue;
6778
05c7a1cc 6779 bgp_static_withdraw_safi(
9bcb3eef 6780 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6781 AFI_IP, safi,
6782 (struct prefix_rd *)
9bcb3eef
DS
6783 bgp_dest_get_prefix(
6784 dest));
ea47320b 6785 bgp_static_free(bgp_static);
811c6797 6786 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6787 NULL);
811c6797 6788 bgp_dest_unlock_node(rm);
d62a17ae 6789 }
05c7a1cc 6790 } else {
9bcb3eef 6791 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6792 bgp_static_withdraw(bgp,
9bcb3eef 6793 bgp_dest_get_prefix(dest),
b54892e0 6794 afi, safi);
05c7a1cc 6795 bgp_static_free(bgp_static);
9bcb3eef
DS
6796 bgp_dest_set_bgp_static_info(dest, NULL);
6797 bgp_dest_unlock_node(dest);
ea47320b 6798 }
05c7a1cc 6799 }
d62a17ae 6800}
6801
6802void bgp_static_redo_import_check(struct bgp *bgp)
6803{
6804 afi_t afi;
6805 safi_t safi;
9bcb3eef
DS
6806 struct bgp_dest *dest;
6807 struct bgp_dest *rm;
d62a17ae 6808 struct bgp_table *table;
6809 struct bgp_static *bgp_static;
6810
6811 /* Use this flag to force reprocessing of the route */
892fedb6 6812 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6813 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6814 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6815 dest = bgp_route_next(dest)) {
6816 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6817 continue;
ea47320b 6818
05c7a1cc
QY
6819 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6820 || (safi == SAFI_EVPN)) {
9bcb3eef 6821 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6822
6823 for (rm = bgp_table_top(table); rm;
6824 rm = bgp_route_next(rm)) {
a78beeb5 6825 bgp_static =
9bcb3eef 6826 bgp_dest_get_bgp_static_info(
5a8ba9fc 6827 rm);
9bcb3eef
DS
6828 bgp_static_update_safi(
6829 bgp, bgp_dest_get_prefix(rm),
6830 bgp_static, afi, safi);
d62a17ae 6831 }
05c7a1cc 6832 } else {
9bcb3eef
DS
6833 bgp_static = bgp_dest_get_bgp_static_info(dest);
6834 bgp_static_update(bgp,
6835 bgp_dest_get_prefix(dest),
6836 bgp_static, afi, safi);
ea47320b 6837 }
05c7a1cc
QY
6838 }
6839 }
892fedb6 6840 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6841}
6842
6843static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6844 safi_t safi)
6845{
6846 struct bgp_table *table;
9bcb3eef 6847 struct bgp_dest *dest;
40381db7 6848 struct bgp_path_info *pi;
d62a17ae 6849
dfb6fd1d
NT
6850 /* Do not install the aggregate route if BGP is in the
6851 * process of termination.
6852 */
892fedb6
DA
6853 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6854 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6855 return;
6856
d62a17ae 6857 table = bgp->rib[afi][safi];
9bcb3eef
DS
6858 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6859 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6860 if (pi->peer == bgp->peer_self
6861 && ((pi->type == ZEBRA_ROUTE_BGP
6862 && pi->sub_type == BGP_ROUTE_STATIC)
6863 || (pi->type != ZEBRA_ROUTE_BGP
6864 && pi->sub_type
d62a17ae 6865 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6866 bgp_aggregate_decrement(
6867 bgp, bgp_dest_get_prefix(dest), pi, afi,
6868 safi);
40381db7 6869 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6870 bgp_path_info_delete(dest, pi);
6871 bgp_process(bgp, dest, afi, safi);
d62a17ae 6872 }
6873 }
6874 }
ad4cbda1 6875}
6876
6877/*
6878 * Purge all networks and redistributed routes from routing table.
6879 * Invoked upon the instance going down.
6880 */
d62a17ae 6881void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6882{
d62a17ae 6883 afi_t afi;
6884 safi_t safi;
ad4cbda1 6885
05c7a1cc
QY
6886 FOREACH_AFI_SAFI (afi, safi)
6887 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6888}
6889
137446f9
LB
6890/*
6891 * gpz 110624
6892 * Currently this is used to set static routes for VPN and ENCAP.
6893 * I think it can probably be factored with bgp_static_set.
6894 */
d62a17ae 6895int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6896 const char *ip_str, const char *rd_str,
6897 const char *label_str, const char *rmap_str,
6898 int evpn_type, const char *esi, const char *gwip,
6899 const char *ethtag, const char *routermac)
6900{
6901 VTY_DECLVAR_CONTEXT(bgp, bgp);
6902 int ret;
6903 struct prefix p;
6904 struct prefix_rd prd;
9bcb3eef
DS
6905 struct bgp_dest *pdest;
6906 struct bgp_dest *dest;
d62a17ae 6907 struct bgp_table *table;
6908 struct bgp_static *bgp_static;
6909 mpls_label_t label = MPLS_INVALID_LABEL;
6910 struct prefix gw_ip;
6911
6912 /* validate ip prefix */
6913 ret = str2prefix(ip_str, &p);
6914 if (!ret) {
6915 vty_out(vty, "%% Malformed prefix\n");
6916 return CMD_WARNING_CONFIG_FAILED;
6917 }
6918 apply_mask(&p);
6919 if ((afi == AFI_L2VPN)
6920 && (bgp_build_evpn_prefix(evpn_type,
6921 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6922 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6923 return CMD_WARNING_CONFIG_FAILED;
6924 }
718e3744 6925
d62a17ae 6926 ret = str2prefix_rd(rd_str, &prd);
6927 if (!ret) {
6928 vty_out(vty, "%% Malformed rd\n");
6929 return CMD_WARNING_CONFIG_FAILED;
6930 }
718e3744 6931
d62a17ae 6932 if (label_str) {
6933 unsigned long label_val;
6934 label_val = strtoul(label_str, NULL, 10);
6935 encode_label(label_val, &label);
6936 }
9bedbb1e 6937
d62a17ae 6938 if (safi == SAFI_EVPN) {
6939 if (esi && str2esi(esi, NULL) == 0) {
6940 vty_out(vty, "%% Malformed ESI\n");
6941 return CMD_WARNING_CONFIG_FAILED;
6942 }
6943 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6944 vty_out(vty, "%% Malformed Router MAC\n");
6945 return CMD_WARNING_CONFIG_FAILED;
6946 }
6947 if (gwip) {
6006b807 6948 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6949 ret = str2prefix(gwip, &gw_ip);
6950 if (!ret) {
6951 vty_out(vty, "%% Malformed GatewayIp\n");
6952 return CMD_WARNING_CONFIG_FAILED;
6953 }
6954 if ((gw_ip.family == AF_INET
3714a385 6955 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6956 (struct prefix_evpn *)&p))
6957 || (gw_ip.family == AF_INET6
3714a385 6958 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6959 (struct prefix_evpn *)&p))) {
6960 vty_out(vty,
6961 "%% GatewayIp family differs with IP prefix\n");
6962 return CMD_WARNING_CONFIG_FAILED;
6963 }
6964 }
6965 }
9bcb3eef
DS
6966 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6967 if (!bgp_dest_has_bgp_path_info_data(pdest))
6968 bgp_dest_set_bgp_table_info(pdest,
67009e22 6969 bgp_table_init(bgp, afi, safi));
9bcb3eef 6970 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6971
9bcb3eef 6972 dest = bgp_node_get(table, &p);
d62a17ae 6973
9bcb3eef 6974 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6975 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6976 bgp_dest_unlock_node(dest);
d62a17ae 6977 } else {
6978 /* New configuration. */
6979 bgp_static = bgp_static_new();
6980 bgp_static->backdoor = 0;
6981 bgp_static->valid = 0;
6982 bgp_static->igpmetric = 0;
975a328e 6983 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6984 bgp_static->label = label;
6985 bgp_static->prd = prd;
6986
6987 if (rmap_str) {
0a22ddfb 6988 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6989 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6990 bgp_static->rmap.name =
6991 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6992 bgp_static->rmap.map =
6993 route_map_lookup_by_name(rmap_str);
b4897fa5 6994 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6995 }
718e3744 6996
d62a17ae 6997 if (safi == SAFI_EVPN) {
6998 if (esi) {
6999 bgp_static->eth_s_id =
7000 XCALLOC(MTYPE_ATTR,
0a50c248 7001 sizeof(esi_t));
d62a17ae 7002 str2esi(esi, bgp_static->eth_s_id);
7003 }
7004 if (routermac) {
7005 bgp_static->router_mac =
28328ea9 7006 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7007 (void)prefix_str2mac(routermac,
7008 bgp_static->router_mac);
d62a17ae 7009 }
7010 if (gwip)
7011 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7012 }
9bcb3eef 7013 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7014
d62a17ae 7015 bgp_static->valid = 1;
7016 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7017 }
718e3744 7018
d62a17ae 7019 return CMD_SUCCESS;
718e3744 7020}
7021
7022/* Configure static BGP network. */
d62a17ae 7023int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7024 const char *ip_str, const char *rd_str,
7025 const char *label_str, int evpn_type, const char *esi,
7026 const char *gwip, const char *ethtag)
7027{
7028 VTY_DECLVAR_CONTEXT(bgp, bgp);
7029 int ret;
7030 struct prefix p;
7031 struct prefix_rd prd;
9bcb3eef
DS
7032 struct bgp_dest *pdest;
7033 struct bgp_dest *dest;
d62a17ae 7034 struct bgp_table *table;
7035 struct bgp_static *bgp_static;
7036 mpls_label_t label = MPLS_INVALID_LABEL;
7037
7038 /* Convert IP prefix string to struct prefix. */
7039 ret = str2prefix(ip_str, &p);
7040 if (!ret) {
7041 vty_out(vty, "%% Malformed prefix\n");
7042 return CMD_WARNING_CONFIG_FAILED;
7043 }
7044 apply_mask(&p);
7045 if ((afi == AFI_L2VPN)
7046 && (bgp_build_evpn_prefix(evpn_type,
7047 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7048 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7049 return CMD_WARNING_CONFIG_FAILED;
7050 }
7051 ret = str2prefix_rd(rd_str, &prd);
7052 if (!ret) {
7053 vty_out(vty, "%% Malformed rd\n");
7054 return CMD_WARNING_CONFIG_FAILED;
7055 }
718e3744 7056
d62a17ae 7057 if (label_str) {
7058 unsigned long label_val;
7059 label_val = strtoul(label_str, NULL, 10);
7060 encode_label(label_val, &label);
7061 }
718e3744 7062
9bcb3eef
DS
7063 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7064 if (!bgp_dest_has_bgp_path_info_data(pdest))
7065 bgp_dest_set_bgp_table_info(pdest,
67009e22 7066 bgp_table_init(bgp, afi, safi));
d62a17ae 7067 else
9bcb3eef
DS
7068 bgp_dest_unlock_node(pdest);
7069 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7070
9bcb3eef 7071 dest = bgp_node_lookup(table, &p);
6b0655a2 7072
9bcb3eef 7073 if (dest) {
d62a17ae 7074 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7075
9bcb3eef 7076 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7077 bgp_static_free(bgp_static);
9bcb3eef
DS
7078 bgp_dest_set_bgp_static_info(dest, NULL);
7079 bgp_dest_unlock_node(dest);
7080 bgp_dest_unlock_node(dest);
d62a17ae 7081 } else
7082 vty_out(vty, "%% Can't find the route\n");
7083
7084 return CMD_SUCCESS;
7085}
7086
7087static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7088 const char *rmap_name)
7089{
7090 VTY_DECLVAR_CONTEXT(bgp, bgp);
7091 struct bgp_rmap *rmap;
7092
7093 rmap = &bgp->table_map[afi][safi];
7094 if (rmap_name) {
0a22ddfb 7095 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7096 route_map_counter_decrement(rmap->map);
d62a17ae 7097 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7098 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7099 route_map_counter_increment(rmap->map);
d62a17ae 7100 } else {
0a22ddfb 7101 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7102 route_map_counter_decrement(rmap->map);
d62a17ae 7103 rmap->map = NULL;
7104 }
73ac8160 7105
d62a17ae 7106 if (bgp_fibupd_safi(safi))
7107 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7108
d62a17ae 7109 return CMD_SUCCESS;
73ac8160
DS
7110}
7111
d62a17ae 7112static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7113 const char *rmap_name)
73ac8160 7114{
d62a17ae 7115 VTY_DECLVAR_CONTEXT(bgp, bgp);
7116 struct bgp_rmap *rmap;
73ac8160 7117
d62a17ae 7118 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7119 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7120 route_map_counter_decrement(rmap->map);
d62a17ae 7121 rmap->map = NULL;
73ac8160 7122
d62a17ae 7123 if (bgp_fibupd_safi(safi))
7124 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7125
d62a17ae 7126 return CMD_SUCCESS;
73ac8160
DS
7127}
7128
2b791107 7129void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7130 safi_t safi)
73ac8160 7131{
d62a17ae 7132 if (bgp->table_map[afi][safi].name) {
d62a17ae 7133 vty_out(vty, " table-map %s\n",
7134 bgp->table_map[afi][safi].name);
7135 }
73ac8160
DS
7136}
7137
73ac8160
DS
7138DEFUN (bgp_table_map,
7139 bgp_table_map_cmd,
7140 "table-map WORD",
7141 "BGP table to RIB route download filter\n"
7142 "Name of the route map\n")
7143{
d62a17ae 7144 int idx_word = 1;
7145 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7146 argv[idx_word]->arg);
73ac8160
DS
7147}
7148DEFUN (no_bgp_table_map,
7149 no_bgp_table_map_cmd,
7150 "no table-map WORD",
3a2d747c 7151 NO_STR
73ac8160
DS
7152 "BGP table to RIB route download filter\n"
7153 "Name of the route map\n")
7154{
d62a17ae 7155 int idx_word = 2;
7156 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7157 argv[idx_word]->arg);
73ac8160
DS
7158}
7159
585f1adc
IR
7160DEFPY(bgp_network,
7161 bgp_network_cmd,
7162 "[no] network \
7163 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7164 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7165 backdoor$backdoor}]",
7166 NO_STR
7167 "Specify a network to announce via BGP\n"
7168 "IPv4 prefix\n"
7169 "Network number\n"
7170 "Network mask\n"
7171 "Network mask\n"
7172 "Route-map to modify the attributes\n"
7173 "Name of the route map\n"
7174 "Label index to associate with the prefix\n"
7175 "Label index value\n"
7176 "Specify a BGP backdoor route\n")
7177{
7178 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7179
7180 if (address_str) {
7181 int ret;
718e3744 7182
e2a86ad9 7183 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7184 addr_prefix_str,
7185 sizeof(addr_prefix_str));
e2a86ad9
DS
7186 if (!ret) {
7187 vty_out(vty, "%% Inconsistent address and mask\n");
7188 return CMD_WARNING_CONFIG_FAILED;
7189 }
d62a17ae 7190 }
718e3744 7191
585f1adc
IR
7192 return bgp_static_set(
7193 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7194 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7195 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7196}
7197
585f1adc
IR
7198DEFPY(ipv6_bgp_network,
7199 ipv6_bgp_network_cmd,
7200 "[no] network X:X::X:X/M$prefix \
70dd370f 7201 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7202 NO_STR
7203 "Specify a network to announce via BGP\n"
7204 "IPv6 prefix\n"
7205 "Route-map to modify the attributes\n"
7206 "Name of the route map\n"
7207 "Label index to associate with the prefix\n"
7208 "Label index value\n")
37a87b8f 7209{
585f1adc
IR
7210 return bgp_static_set(
7211 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7212 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7213}
7214
d62a17ae 7215static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7216{
d62a17ae 7217 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7218}
7219
d62a17ae 7220static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7221{
365ab2e7
RZ
7222 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7223 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7224 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7225 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7226 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7227}
718e3744 7228
365ab2e7
RZ
7229/**
7230 * Helper function to avoid repeated code: prepare variables for a
7231 * `route_map_apply` call.
7232 *
7233 * \returns `true` on route map match, otherwise `false`.
7234 */
7235static bool aggr_suppress_map_test(struct bgp *bgp,
7236 struct bgp_aggregate *aggregate,
7237 struct bgp_path_info *pi)
7238{
7239 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7240 route_map_result_t rmr = RMAP_DENYMATCH;
7241 struct bgp_path_info rmap_path = {};
7242 struct attr attr = {};
7243
7244 /* No route map entries created, just don't match. */
7245 if (aggregate->suppress_map == NULL)
7246 return false;
7247
7248 /* Call route map matching and return result. */
17571c4a 7249 attr.aspath = aspath_empty(bgp->asnotation);
365ab2e7
RZ
7250 rmap_path.peer = bgp->peer_self;
7251 rmap_path.attr = &attr;
7252
7253 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7254 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7255 bgp->peer_self->rmap_type = 0;
7256
7257 bgp_attr_flush(&attr);
afb254d7 7258 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7259
7260 return rmr == RMAP_PERMITMATCH;
7261}
7262
4056a5f6
RZ
7263/** Test whether the aggregation has suppressed this path or not. */
7264static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7265 struct bgp_path_info *pi)
7266{
7267 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7268 return false;
7269
7270 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7271}
7272
7273/**
7274 * Suppress this path and keep the reference.
7275 *
7276 * \returns `true` if needs processing otherwise `false`.
7277 */
7278static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7279 struct bgp_path_info *pi)
7280{
7281 struct bgp_path_info_extra *pie;
7282
7283 /* Path is already suppressed by this aggregation. */
7284 if (aggr_suppress_exists(aggregate, pi))
7285 return false;
7286
7287 pie = bgp_path_info_extra_get(pi);
7288
7289 /* This is the first suppression, allocate memory and list it. */
7290 if (pie->aggr_suppressors == NULL)
7291 pie->aggr_suppressors = list_new();
7292
7293 listnode_add(pie->aggr_suppressors, aggregate);
7294
7295 /* Only mark for processing if suppressed. */
7296 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7297 if (BGP_DEBUG(update, UPDATE_OUT))
7298 zlog_debug("aggregate-address suppressing: %pFX",
7299 bgp_dest_get_prefix(pi->net));
7300
4056a5f6
RZ
7301 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7302 return true;
7303 }
7304
7305 return false;
7306}
7307
7308/**
7309 * Unsuppress this path and remove the reference.
7310 *
7311 * \returns `true` if needs processing otherwise `false`.
7312 */
7313static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7314 struct bgp_path_info *pi)
7315{
7316 /* Path wasn't suppressed. */
7317 if (!aggr_suppress_exists(aggregate, pi))
7318 return false;
7319
7320 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7321
7322 /* Unsuppress and free extra memory if last item. */
7323 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7324 if (BGP_DEBUG(update, UPDATE_OUT))
7325 zlog_debug("aggregate-address unsuppressing: %pFX",
7326 bgp_dest_get_prefix(pi->net));
7327
4056a5f6
RZ
7328 list_delete(&pi->extra->aggr_suppressors);
7329 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7330 return true;
7331 }
7332
7333 return false;
7334}
7335
3dc339cd
DA
7336static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7337 struct aspath *aspath,
7338 struct community *comm,
7339 struct ecommunity *ecomm,
7340 struct lcommunity *lcomm)
eaaf8adb
DS
7341{
7342 static struct aspath *ae = NULL;
17571c4a
PG
7343 enum asnotation_mode asnotation;
7344
7345 asnotation = bgp_get_asnotation(NULL);
eaaf8adb
DS
7346
7347 if (!ae)
17571c4a 7348 ae = aspath_empty(asnotation);
eaaf8adb 7349
40381db7 7350 if (!pi)
3dc339cd 7351 return false;
eaaf8adb 7352
40381db7 7353 if (origin != pi->attr->origin)
3dc339cd 7354 return false;
eaaf8adb 7355
40381db7 7356 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7357 return false;
29f7d023 7358
9a706b42 7359 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7360 return false;
eaaf8adb 7361
b53e67a3 7362 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7363 return false;
eaaf8adb 7364
1bcf3a96 7365 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7366 return false;
dd18c5a9 7367
40381db7 7368 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7369 return false;
7ce8a8e0 7370
3dc339cd 7371 return true;
eaaf8adb
DS
7372}
7373
5f040085
DS
7374static void bgp_aggregate_install(
7375 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7376 uint8_t origin, struct aspath *aspath, struct community *community,
7377 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7378 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7379{
9bcb3eef 7380 struct bgp_dest *dest;
c701010e 7381 struct bgp_table *table;
6f94b685 7382 struct bgp_path_info *pi, *orig, *new;
20894f50 7383 struct attr *attr;
c701010e
DS
7384
7385 table = bgp->rib[afi][safi];
7386
9bcb3eef 7387 dest = bgp_node_get(table, p);
eaaf8adb 7388
9bcb3eef 7389 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7390 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7391 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7392 break;
7393
6aabb15d
RZ
7394 /*
7395 * If we have paths with different MEDs, then don't install
7396 * (or uninstall) the aggregate route.
7397 */
7398 if (aggregate->match_med && aggregate->med_mismatched)
7399 goto uninstall_aggregate_route;
7400
c701010e 7401 if (aggregate->count > 0) {
eaaf8adb
DS
7402 /*
7403 * If the aggregate information has not changed
7404 * no need to re-install it again.
7405 */
6f94b685 7406 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7407 ecommunity, lcommunity)) {
9bcb3eef 7408 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7409
7410 if (aspath)
7411 aspath_free(aspath);
7412 if (community)
3c1f53de 7413 community_free(&community);
3da2cc32
DS
7414 if (ecommunity)
7415 ecommunity_free(&ecommunity);
dd18c5a9
DS
7416 if (lcommunity)
7417 lcommunity_free(&lcommunity);
eaaf8adb
DS
7418
7419 return;
7420 }
7421
7422 /*
7423 * Mark the old as unusable
7424 */
40381db7 7425 if (pi)
9bcb3eef 7426 bgp_path_info_delete(dest, pi);
eaaf8adb 7427
20894f50
DA
7428 attr = bgp_attr_aggregate_intern(
7429 bgp, origin, aspath, community, ecommunity, lcommunity,
7430 aggregate, atomic_aggregate, p);
7431
7432 if (!attr) {
8c0044f3 7433 bgp_dest_unlock_node(dest);
20894f50 7434 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7435 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7436 zlog_debug("%s: %pFX null attribute", __func__,
7437 p);
20894f50
DA
7438 return;
7439 }
7440
3da2cc32 7441 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7442 bgp->peer_self, attr, dest);
20894f50 7443
1defdda8 7444 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7445
9bcb3eef
DS
7446 bgp_path_info_add(dest, new);
7447 bgp_process(bgp, dest, afi, safi);
c701010e 7448 } else {
6aabb15d 7449 uninstall_aggregate_route:
6f94b685 7450 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7451 if (pi->peer == bgp->peer_self
7452 && pi->type == ZEBRA_ROUTE_BGP
7453 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7454 break;
7455
7456 /* Withdraw static BGP route from routing table. */
40381db7 7457 if (pi) {
9bcb3eef
DS
7458 bgp_path_info_delete(dest, pi);
7459 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7460 }
7461 }
7462
9bcb3eef 7463 bgp_dest_unlock_node(dest);
c701010e
DS
7464}
7465
6aabb15d
RZ
7466/**
7467 * Check if the current path has different MED than other known paths.
7468 *
7469 * \returns `true` if the MED matched the others else `false`.
7470 */
7471static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7472 struct bgp *bgp, struct bgp_path_info *pi)
7473{
7474 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7475
7476 /* This is the first route being analyzed. */
7477 if (!aggregate->med_initialized) {
7478 aggregate->med_initialized = true;
7479 aggregate->med_mismatched = false;
7480 aggregate->med_matched_value = cur_med;
7481 } else {
7482 /* Check if routes with different MED showed up. */
7483 if (cur_med != aggregate->med_matched_value)
7484 aggregate->med_mismatched = true;
7485 }
7486
7487 return !aggregate->med_mismatched;
7488}
7489
7490/**
7491 * Initializes and tests all routes in the aggregate address path for MED
7492 * values.
7493 *
7494 * \returns `true` if all MEDs are the same otherwise `false`.
7495 */
7496static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7497 struct bgp *bgp, const struct prefix *p,
7498 afi_t afi, safi_t safi)
7499{
7500 struct bgp_table *table = bgp->rib[afi][safi];
7501 const struct prefix *dest_p;
7502 struct bgp_dest *dest, *top;
7503 struct bgp_path_info *pi;
7504 bool med_matched = true;
7505
7506 aggregate->med_initialized = false;
7507
7508 top = bgp_node_get(table, p);
7509 for (dest = bgp_node_get(table, p); dest;
7510 dest = bgp_route_next_until(dest, top)) {
7511 dest_p = bgp_dest_get_prefix(dest);
7512 if (dest_p->prefixlen <= p->prefixlen)
7513 continue;
7514
7515 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7516 if (BGP_PATH_HOLDDOWN(pi))
7517 continue;
7518 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7519 continue;
7520 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7521 med_matched = false;
7522 break;
7523 }
7524 }
7525 if (!med_matched)
7526 break;
7527 }
7528 bgp_dest_unlock_node(top);
7529
7530 return med_matched;
7531}
7532
7533/**
7534 * Toggles the route suppression status for this aggregate address
7535 * configuration.
7536 */
4056a5f6
RZ
7537void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7538 struct bgp *bgp, const struct prefix *p,
7539 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7540{
7541 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7542 const struct prefix *dest_p;
7543 struct bgp_dest *dest, *top;
7544 struct bgp_path_info *pi;
7545 bool toggle_suppression;
7546
7547 /* We've found a different MED we must revert any suppressed routes. */
7548 top = bgp_node_get(table, p);
7549 for (dest = bgp_node_get(table, p); dest;
7550 dest = bgp_route_next_until(dest, top)) {
7551 dest_p = bgp_dest_get_prefix(dest);
7552 if (dest_p->prefixlen <= p->prefixlen)
7553 continue;
7554
7555 toggle_suppression = false;
7556 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7557 if (BGP_PATH_HOLDDOWN(pi))
7558 continue;
7559 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7560 continue;
7561
6aabb15d
RZ
7562 /* We are toggling suppression back. */
7563 if (suppress) {
6aabb15d 7564 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7565 if (aggr_suppress_path(aggregate, pi))
7566 toggle_suppression = true;
6aabb15d
RZ
7567 continue;
7568 }
7569
6aabb15d 7570 /* Install route if there is no more suppression. */
4056a5f6 7571 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7572 toggle_suppression = true;
6aabb15d
RZ
7573 }
7574
7575 if (toggle_suppression)
7576 bgp_process(bgp, dest, afi, safi);
7577 }
7578 bgp_dest_unlock_node(top);
7579}
7580
7581/**
7582 * Aggregate address MED matching incremental test: this function is called
7583 * when the initial aggregation occurred and we are only testing a single
7584 * new path.
7585 *
7586 * In addition to testing and setting the MED validity it also installs back
7587 * suppressed routes (if summary is configured).
7588 *
7589 * Must not be called in `bgp_aggregate_route`.
7590 */
7591static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7592 struct bgp *bgp, const struct prefix *p,
7593 afi_t afi, safi_t safi,
f66624f5 7594 struct bgp_path_info *pi)
6aabb15d
RZ
7595{
7596 /* MED matching disabled. */
7597 if (!aggregate->match_med)
7598 return;
7599
f66624f5
DA
7600 /* Aggregation with different MED, recheck if we have got equal MEDs
7601 * now.
6aabb15d 7602 */
f66624f5
DA
7603 if (aggregate->med_mismatched &&
7604 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7605 aggregate->summary_only)
7606 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7607 true);
7608 else
6aabb15d
RZ
7609 bgp_aggregate_med_match(aggregate, bgp, pi);
7610
7611 /* No mismatches, just quit. */
7612 if (!aggregate->med_mismatched)
7613 return;
7614
7615 /* Route summarization is disabled. */
7616 if (!aggregate->summary_only)
7617 return;
7618
7619 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7620}
7621
b5d58c32 7622/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7623void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7624 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7625{
7626 struct bgp_table *table;
9bcb3eef
DS
7627 struct bgp_dest *top;
7628 struct bgp_dest *dest;
d7c0a89a 7629 uint8_t origin;
d62a17ae 7630 struct aspath *aspath = NULL;
d62a17ae 7631 struct community *community = NULL;
3da2cc32 7632 struct ecommunity *ecommunity = NULL;
dd18c5a9 7633 struct lcommunity *lcommunity = NULL;
40381db7 7634 struct bgp_path_info *pi;
d62a17ae 7635 unsigned long match = 0;
d7c0a89a 7636 uint8_t atomic_aggregate = 0;
d62a17ae 7637
9f822fa2
S
7638 /* If the bgp instance is being deleted or self peer is deleted
7639 * then do not create aggregate route
7640 */
892fedb6
DA
7641 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7642 || (bgp->peer_self == NULL))
9f822fa2
S
7643 return;
7644
6aabb15d
RZ
7645 /* Initialize and test routes for MED difference. */
7646 if (aggregate->match_med)
7647 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7648
4056a5f6
RZ
7649 /*
7650 * Reset aggregate count: we might've been called from route map
7651 * update so in that case we must retest all more specific routes.
7652 *
7653 * \see `bgp_route_map_process_update`.
7654 */
7655 aggregate->count = 0;
7656 aggregate->incomplete_origin_count = 0;
7657 aggregate->incomplete_origin_count = 0;
7658 aggregate->egp_origin_count = 0;
7659
d62a17ae 7660 /* ORIGIN attribute: If at least one route among routes that are
7661 aggregated has ORIGIN with the value INCOMPLETE, then the
7662 aggregated route must have the ORIGIN attribute with the value
7663 INCOMPLETE. Otherwise, if at least one route among routes that
7664 are aggregated has ORIGIN with the value EGP, then the aggregated
7665 route must have the origin attribute with the value EGP. In all
7666 other case the value of the ORIGIN attribute of the aggregated
7667 route is INTERNAL. */
7668 origin = BGP_ORIGIN_IGP;
718e3744 7669
d62a17ae 7670 table = bgp->rib[afi][safi];
718e3744 7671
d62a17ae 7672 top = bgp_node_get(table, p);
9bcb3eef
DS
7673 for (dest = bgp_node_get(table, p); dest;
7674 dest = bgp_route_next_until(dest, top)) {
7675 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7676
9bcb3eef 7677 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7678 continue;
d62a17ae 7679
a77e2f4b
S
7680 /* If suppress fib is enabled and route not installed
7681 * in FIB, skip the route
7682 */
7683 if (!bgp_check_advertise(bgp, dest))
7684 continue;
7685
c2ff8b3e 7686 match = 0;
d62a17ae 7687
9bcb3eef 7688 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7689 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7690 continue;
718e3744 7691
40381db7 7692 if (pi->attr->flag
c2ff8b3e
DS
7693 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7694 atomic_aggregate = 1;
d62a17ae 7695
40381db7 7696 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7697 continue;
d62a17ae 7698
f273fef1
DS
7699 /*
7700 * summary-only aggregate route suppress
7701 * aggregated route announcements.
6aabb15d
RZ
7702 *
7703 * MED matching:
7704 * Don't create summaries if MED didn't match
7705 * otherwise neither the specific routes and the
7706 * aggregation will be announced.
f273fef1 7707 */
6aabb15d
RZ
7708 if (aggregate->summary_only
7709 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7710 if (aggr_suppress_path(aggregate, pi))
7711 match++;
d62a17ae 7712 }
c2ff8b3e 7713
365ab2e7
RZ
7714 /*
7715 * Suppress more specific routes that match the route
7716 * map results.
7717 *
7718 * MED matching:
7719 * Don't suppress routes if MED matching is enabled and
7720 * it mismatched otherwise we might end up with no
7721 * routes for this path.
7722 */
7723 if (aggregate->suppress_map_name
7724 && AGGREGATE_MED_VALID(aggregate)
7725 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7726 if (aggr_suppress_path(aggregate, pi))
7727 match++;
d62a17ae 7728 }
c2ff8b3e
DS
7729
7730 aggregate->count++;
7731
f273fef1
DS
7732 /*
7733 * If at least one route among routes that are
7734 * aggregated has ORIGIN with the value INCOMPLETE,
7735 * then the aggregated route MUST have the ORIGIN
7736 * attribute with the value INCOMPLETE. Otherwise, if
7737 * at least one route among routes that are aggregated
7738 * has ORIGIN with the value EGP, then the aggregated
7739 * route MUST have the ORIGIN attribute with the value
7740 * EGP.
7741 */
fc968841
NT
7742 switch (pi->attr->origin) {
7743 case BGP_ORIGIN_INCOMPLETE:
7744 aggregate->incomplete_origin_count++;
7745 break;
7746 case BGP_ORIGIN_EGP:
7747 aggregate->egp_origin_count++;
7748 break;
7749 default:
7750 /*Do nothing.
7751 */
7752 break;
7753 }
c2ff8b3e
DS
7754
7755 if (!aggregate->as_set)
7756 continue;
7757
f273fef1
DS
7758 /*
7759 * as-set aggregate route generate origin, as path,
7760 * and community aggregation.
7761 */
fc968841
NT
7762 /* Compute aggregate route's as-path.
7763 */
ef51a7d8 7764 bgp_compute_aggregate_aspath_hash(aggregate,
7765 pi->attr->aspath);
c2ff8b3e 7766
fc968841
NT
7767 /* Compute aggregate route's community.
7768 */
9a706b42 7769 if (bgp_attr_get_community(pi->attr))
21fec674 7770 bgp_compute_aggregate_community_hash(
9a706b42
DA
7771 aggregate,
7772 bgp_attr_get_community(pi->attr));
dd18c5a9 7773
fc968841
NT
7774 /* Compute aggregate route's extended community.
7775 */
b53e67a3 7776 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7777 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7778 aggregate,
7779 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7780
7781 /* Compute aggregate route's large community.
7782 */
1bcf3a96 7783 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7784 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7785 aggregate,
7786 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7787 }
c2ff8b3e 7788 if (match)
9bcb3eef 7789 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7790 }
21fec674 7791 if (aggregate->as_set) {
ef51a7d8 7792 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7793 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7794 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7795 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7796 }
7797
f1eb1f05 7798
9bcb3eef 7799 bgp_dest_unlock_node(top);
718e3744 7800
718e3744 7801
fc968841
NT
7802 if (aggregate->incomplete_origin_count > 0)
7803 origin = BGP_ORIGIN_INCOMPLETE;
7804 else if (aggregate->egp_origin_count > 0)
7805 origin = BGP_ORIGIN_EGP;
d62a17ae 7806
229757f1
DA
7807 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7808 origin = aggregate->origin;
7809
fc968841
NT
7810 if (aggregate->as_set) {
7811 if (aggregate->aspath)
7812 /* Retrieve aggregate route's as-path.
7813 */
7814 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7815
fc968841
NT
7816 if (aggregate->community)
7817 /* Retrieve aggregate route's community.
7818 */
7819 community = community_dup(aggregate->community);
3da2cc32 7820
fc968841
NT
7821 if (aggregate->ecommunity)
7822 /* Retrieve aggregate route's ecommunity.
7823 */
7824 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7825
fc968841
NT
7826 if (aggregate->lcommunity)
7827 /* Retrieve aggregate route's lcommunity.
7828 */
7829 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7830 }
718e3744 7831
c701010e 7832 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7833 ecommunity, lcommunity, atomic_aggregate,
7834 aggregate);
718e3744 7835}
7836
5f040085
DS
7837void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7838 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7839{
7840 struct bgp_table *table;
9bcb3eef
DS
7841 struct bgp_dest *top;
7842 struct bgp_dest *dest;
40381db7 7843 struct bgp_path_info *pi;
3b7db173
DS
7844 unsigned long match;
7845
7846 table = bgp->rib[afi][safi];
7847
7848 /* If routes exists below this node, generate aggregate routes. */
7849 top = bgp_node_get(table, p);
9bcb3eef
DS
7850 for (dest = bgp_node_get(table, p); dest;
7851 dest = bgp_route_next_until(dest, top)) {
7852 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7853
9bcb3eef 7854 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7855 continue;
7856 match = 0;
7857
9bcb3eef 7858 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7859 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7860 continue;
7861
40381db7 7862 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7863 continue;
7864
92b175bd
RZ
7865 /*
7866 * This route is suppressed: attempt to unsuppress it.
7867 *
7868 * `aggr_unsuppress_path` will fail if this particular
7869 * aggregate route was not the suppressor.
7870 */
7871 if (pi->extra && pi->extra->aggr_suppressors &&
7872 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7873 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7874 match++;
3b7db173 7875 }
365ab2e7 7876
3b7db173 7877 aggregate->count--;
fc968841
NT
7878
7879 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7880 aggregate->incomplete_origin_count--;
7881 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7882 aggregate->egp_origin_count--;
7883
7884 if (aggregate->as_set) {
7885 /* Remove as-path from aggregate.
7886 */
ef51a7d8 7887 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7888 aggregate,
7889 pi->attr->aspath);
7890
9a706b42 7891 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7892 /* Remove community from aggregate.
7893 */
21fec674 7894 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7895 aggregate,
7896 bgp_attr_get_community(
7897 pi->attr));
fc968841 7898
b53e67a3 7899 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7900 /* Remove ecommunity from aggregate.
7901 */
4edd83f9 7902 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7903 aggregate,
7904 bgp_attr_get_ecommunity(
7905 pi->attr));
fc968841 7906
1bcf3a96 7907 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7908 /* Remove lcommunity from aggregate.
7909 */
f1eb1f05 7910 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7911 aggregate,
7912 bgp_attr_get_lcommunity(
7913 pi->attr));
fc968841 7914 }
3b7db173
DS
7915 }
7916
7917 /* If this node was suppressed, process the change. */
7918 if (match)
9bcb3eef 7919 bgp_process(bgp, dest, afi, safi);
3b7db173 7920 }
f1eb1f05 7921 if (aggregate->as_set) {
ef51a7d8 7922 aspath_free(aggregate->aspath);
7923 aggregate->aspath = NULL;
21fec674 7924 if (aggregate->community)
7925 community_free(&aggregate->community);
4edd83f9 7926 if (aggregate->ecommunity)
7927 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7928 if (aggregate->lcommunity)
7929 lcommunity_free(&aggregate->lcommunity);
7930 }
7931
9bcb3eef 7932 bgp_dest_unlock_node(top);
3b7db173 7933}
718e3744 7934
5f040085
DS
7935static void bgp_add_route_to_aggregate(struct bgp *bgp,
7936 const struct prefix *aggr_p,
fc968841
NT
7937 struct bgp_path_info *pinew, afi_t afi,
7938 safi_t safi,
7939 struct bgp_aggregate *aggregate)
7940{
7941 uint8_t origin;
7942 struct aspath *aspath = NULL;
7943 uint8_t atomic_aggregate = 0;
7944 struct community *community = NULL;
7945 struct ecommunity *ecommunity = NULL;
7946 struct lcommunity *lcommunity = NULL;
7947
a4559740 7948 /* If the bgp instance is being deleted or self peer is deleted
7949 * then do not create aggregate route
7950 */
7951 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7952 || (bgp->peer_self == NULL))
7953 return;
7954
fc968841
NT
7955 /* ORIGIN attribute: If at least one route among routes that are
7956 * aggregated has ORIGIN with the value INCOMPLETE, then the
7957 * aggregated route must have the ORIGIN attribute with the value
7958 * INCOMPLETE. Otherwise, if at least one route among routes that
7959 * are aggregated has ORIGIN with the value EGP, then the aggregated
7960 * route must have the origin attribute with the value EGP. In all
7961 * other case the value of the ORIGIN attribute of the aggregated
7962 * route is INTERNAL.
7963 */
7964 origin = BGP_ORIGIN_IGP;
7965
7966 aggregate->count++;
7967
6aabb15d
RZ
7968 /*
7969 * This must be called before `summary` check to avoid
7970 * "suppressing" twice.
7971 */
7972 if (aggregate->match_med)
7973 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 7974 pinew);
6aabb15d
RZ
7975
7976 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7977 aggr_suppress_path(aggregate, pinew);
fc968841 7978
365ab2e7
RZ
7979 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7980 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7981 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7982
7983 switch (pinew->attr->origin) {
7984 case BGP_ORIGIN_INCOMPLETE:
7985 aggregate->incomplete_origin_count++;
7986 break;
7987 case BGP_ORIGIN_EGP:
7988 aggregate->egp_origin_count++;
7989 break;
7990 default:
7991 /* Do nothing.
7992 */
7993 break;
7994 }
7995
7996 if (aggregate->incomplete_origin_count > 0)
7997 origin = BGP_ORIGIN_INCOMPLETE;
7998 else if (aggregate->egp_origin_count > 0)
7999 origin = BGP_ORIGIN_EGP;
8000
229757f1
DA
8001 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8002 origin = aggregate->origin;
8003
fc968841
NT
8004 if (aggregate->as_set) {
8005 /* Compute aggregate route's as-path.
8006 */
8007 bgp_compute_aggregate_aspath(aggregate,
8008 pinew->attr->aspath);
8009
8010 /* Compute aggregate route's community.
8011 */
9a706b42 8012 if (bgp_attr_get_community(pinew->attr))
fc968841 8013 bgp_compute_aggregate_community(
9a706b42 8014 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8015
8016 /* Compute aggregate route's extended community.
8017 */
b53e67a3 8018 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8019 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8020 aggregate,
8021 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8022
8023 /* Compute aggregate route's large community.
8024 */
1bcf3a96 8025 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8026 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8027 aggregate,
8028 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8029
8030 /* Retrieve aggregate route's as-path.
8031 */
8032 if (aggregate->aspath)
8033 aspath = aspath_dup(aggregate->aspath);
8034
8035 /* Retrieve aggregate route's community.
8036 */
8037 if (aggregate->community)
8038 community = community_dup(aggregate->community);
8039
8040 /* Retrieve aggregate route's ecommunity.
8041 */
8042 if (aggregate->ecommunity)
8043 ecommunity = ecommunity_dup(aggregate->ecommunity);
8044
8045 /* Retrieve aggregate route's lcommunity.
8046 */
8047 if (aggregate->lcommunity)
8048 lcommunity = lcommunity_dup(aggregate->lcommunity);
8049 }
8050
8051 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8052 aspath, community, ecommunity,
8053 lcommunity, atomic_aggregate, aggregate);
8054}
8055
8056static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8057 safi_t safi,
8058 struct bgp_path_info *pi,
8059 struct bgp_aggregate *aggregate,
5f040085 8060 const struct prefix *aggr_p)
fc968841
NT
8061{
8062 uint8_t origin;
8063 struct aspath *aspath = NULL;
8064 uint8_t atomic_aggregate = 0;
8065 struct community *community = NULL;
8066 struct ecommunity *ecommunity = NULL;
8067 struct lcommunity *lcommunity = NULL;
8068 unsigned long match = 0;
8069
a4559740 8070 /* If the bgp instance is being deleted or self peer is deleted
8071 * then do not create aggregate route
8072 */
8073 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8074 || (bgp->peer_self == NULL))
8075 return;
8076
fc968841
NT
8077 if (BGP_PATH_HOLDDOWN(pi))
8078 return;
8079
8080 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8081 return;
8082
4056a5f6
RZ
8083 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8084 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8085 match++;
fc968841 8086
365ab2e7 8087 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8088 && aggr_suppress_map_test(bgp, aggregate, pi))
8089 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8090 match++;
fc968841 8091
6aabb15d 8092 /*
365ab2e7 8093 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8094 * "unsuppressing" twice.
8095 */
8096 if (aggregate->match_med)
f66624f5 8097 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8098
fc968841
NT
8099 if (aggregate->count > 0)
8100 aggregate->count--;
8101
8102 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8103 aggregate->incomplete_origin_count--;
8104 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8105 aggregate->egp_origin_count--;
8106
8107 if (aggregate->as_set) {
8108 /* Remove as-path from aggregate.
8109 */
8110 bgp_remove_aspath_from_aggregate(aggregate,
8111 pi->attr->aspath);
8112
9a706b42 8113 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8114 /* Remove community from aggregate.
8115 */
8116 bgp_remove_community_from_aggregate(
9a706b42 8117 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8118
b53e67a3 8119 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8120 /* Remove ecommunity from aggregate.
8121 */
8122 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8123 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8124
1bcf3a96 8125 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8126 /* Remove lcommunity from aggregate.
8127 */
8128 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8129 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8130 }
8131
8132 /* If this node was suppressed, process the change. */
8133 if (match)
8134 bgp_process(bgp, pi->net, afi, safi);
8135
8136 origin = BGP_ORIGIN_IGP;
8137 if (aggregate->incomplete_origin_count > 0)
8138 origin = BGP_ORIGIN_INCOMPLETE;
8139 else if (aggregate->egp_origin_count > 0)
8140 origin = BGP_ORIGIN_EGP;
8141
229757f1
DA
8142 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8143 origin = aggregate->origin;
8144
fc968841
NT
8145 if (aggregate->as_set) {
8146 /* Retrieve aggregate route's as-path.
8147 */
8148 if (aggregate->aspath)
8149 aspath = aspath_dup(aggregate->aspath);
8150
8151 /* Retrieve aggregate route's community.
8152 */
8153 if (aggregate->community)
8154 community = community_dup(aggregate->community);
8155
8156 /* Retrieve aggregate route's ecommunity.
8157 */
8158 if (aggregate->ecommunity)
8159 ecommunity = ecommunity_dup(aggregate->ecommunity);
8160
8161 /* Retrieve aggregate route's lcommunity.
8162 */
8163 if (aggregate->lcommunity)
8164 lcommunity = lcommunity_dup(aggregate->lcommunity);
8165 }
8166
8167 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8168 aspath, community, ecommunity,
8169 lcommunity, atomic_aggregate, aggregate);
8170}
8171
5a1ae2c2 8172void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8173 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8174{
9bcb3eef
DS
8175 struct bgp_dest *child;
8176 struct bgp_dest *dest;
d62a17ae 8177 struct bgp_aggregate *aggregate;
8178 struct bgp_table *table;
718e3744 8179
d62a17ae 8180 table = bgp->aggregate[afi][safi];
f018db83 8181
d62a17ae 8182 /* No aggregates configured. */
8183 if (bgp_table_top_nolock(table) == NULL)
8184 return;
f018db83 8185
d62a17ae 8186 if (p->prefixlen == 0)
8187 return;
718e3744 8188
40381db7 8189 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8190 return;
718e3744 8191
a77e2f4b
S
8192 /* If suppress fib is enabled and route not installed
8193 * in FIB, do not update the aggregate route
8194 */
8195 if (!bgp_check_advertise(bgp, pi->net))
8196 return;
8197
d62a17ae 8198 child = bgp_node_get(table, p);
718e3744 8199
d62a17ae 8200 /* Aggregate address configuration check. */
9bcb3eef
DS
8201 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8202 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8203
9bcb3eef
DS
8204 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8205 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8206 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8207 aggregate);
d62a17ae 8208 }
b1e62edd 8209 }
9bcb3eef 8210 bgp_dest_unlock_node(child);
718e3744 8211}
8212
5a1ae2c2 8213void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8214 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8215{
9bcb3eef
DS
8216 struct bgp_dest *child;
8217 struct bgp_dest *dest;
d62a17ae 8218 struct bgp_aggregate *aggregate;
8219 struct bgp_table *table;
718e3744 8220
d62a17ae 8221 table = bgp->aggregate[afi][safi];
718e3744 8222
d62a17ae 8223 /* No aggregates configured. */
8224 if (bgp_table_top_nolock(table) == NULL)
8225 return;
718e3744 8226
d62a17ae 8227 if (p->prefixlen == 0)
8228 return;
718e3744 8229
d62a17ae 8230 child = bgp_node_get(table, p);
718e3744 8231
d62a17ae 8232 /* Aggregate address configuration check. */
9bcb3eef
DS
8233 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8234 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8235
9bcb3eef
DS
8236 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8237 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8238 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8239 aggregate, dest_p);
d62a17ae 8240 }
b1e62edd 8241 }
9bcb3eef 8242 bgp_dest_unlock_node(child);
d62a17ae 8243}
718e3744 8244
718e3744 8245/* Aggregate route attribute. */
8246#define AGGREGATE_SUMMARY_ONLY 1
8247#define AGGREGATE_AS_SET 1
fb29348a 8248#define AGGREGATE_AS_UNSET 0
718e3744 8249
229757f1
DA
8250static const char *bgp_origin2str(uint8_t origin)
8251{
8252 switch (origin) {
8253 case BGP_ORIGIN_IGP:
8254 return "igp";
8255 case BGP_ORIGIN_EGP:
8256 return "egp";
8257 case BGP_ORIGIN_INCOMPLETE:
8258 return "incomplete";
8259 }
8260 return "n/a";
8261}
8262
fdeb5a81 8263static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8264{
8265 switch (v_state) {
fdeb5a81
DS
8266 case RPKI_NOT_BEING_USED:
8267 return "not used";
8268 case RPKI_VALID:
b5b99af8 8269 return "valid";
fdeb5a81 8270 case RPKI_NOTFOUND:
b5b99af8 8271 return "not found";
fdeb5a81 8272 case RPKI_INVALID:
b5b99af8 8273 return "invalid";
b5b99af8 8274 }
fdeb5a81
DS
8275
8276 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8277 return "ERROR";
8278}
8279
585f1adc
IR
8280static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8281 afi_t afi, safi_t safi)
718e3744 8282{
585f1adc
IR
8283 VTY_DECLVAR_CONTEXT(bgp, bgp);
8284 int ret;
8285 struct prefix p;
9bcb3eef 8286 struct bgp_dest *dest;
d62a17ae 8287 struct bgp_aggregate *aggregate;
718e3744 8288
585f1adc
IR
8289 /* Convert string to prefix structure. */
8290 ret = str2prefix(prefix_str, &p);
8291 if (!ret) {
8292 vty_out(vty, "Malformed prefix\n");
8293 return CMD_WARNING_CONFIG_FAILED;
8294 }
8295 apply_mask(&p);
a4559740 8296
d62a17ae 8297 /* Old configuration check. */
585f1adc 8298 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8299 if (!dest) {
585f1adc
IR
8300 vty_out(vty,
8301 "%% There is no aggregate-address configuration.\n");
8302 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8303 }
f6269b4f 8304
9bcb3eef 8305 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8306 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8307 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8308 NULL, NULL, 0, aggregate);
d62a17ae 8309
8310 /* Unlock aggregate address configuration. */
9bcb3eef 8311 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8312
8313 if (aggregate->community)
8314 community_free(&aggregate->community);
8315
8316 if (aggregate->community_hash) {
8317 /* Delete all communities in the hash.
8318 */
8319 hash_clean(aggregate->community_hash,
8320 bgp_aggr_community_remove);
8321 /* Free up the community_hash.
8322 */
8323 hash_free(aggregate->community_hash);
8324 }
8325
8326 if (aggregate->ecommunity)
8327 ecommunity_free(&aggregate->ecommunity);
8328
8329 if (aggregate->ecommunity_hash) {
8330 /* Delete all ecommunities in the hash.
8331 */
8332 hash_clean(aggregate->ecommunity_hash,
8333 bgp_aggr_ecommunity_remove);
8334 /* Free up the ecommunity_hash.
8335 */
8336 hash_free(aggregate->ecommunity_hash);
8337 }
8338
8339 if (aggregate->lcommunity)
8340 lcommunity_free(&aggregate->lcommunity);
8341
8342 if (aggregate->lcommunity_hash) {
8343 /* Delete all lcommunities in the hash.
8344 */
8345 hash_clean(aggregate->lcommunity_hash,
8346 bgp_aggr_lcommunity_remove);
8347 /* Free up the lcommunity_hash.
8348 */
8349 hash_free(aggregate->lcommunity_hash);
8350 }
8351
8352 if (aggregate->aspath)
8353 aspath_free(aggregate->aspath);
8354
8355 if (aggregate->aspath_hash) {
8356 /* Delete all as-paths in the hash.
8357 */
8358 hash_clean(aggregate->aspath_hash,
8359 bgp_aggr_aspath_remove);
8360 /* Free up the aspath_hash.
8361 */
8362 hash_free(aggregate->aspath_hash);
8363 }
8364
d62a17ae 8365 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8366 bgp_dest_unlock_node(dest);
8367 bgp_dest_unlock_node(dest);
d62a17ae 8368
585f1adc 8369 return CMD_SUCCESS;
d62a17ae 8370}
8371
585f1adc
IR
8372static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8373 safi_t safi, const char *rmap,
8374 uint8_t summary_only, uint8_t as_set,
8375 uint8_t origin, bool match_med,
8376 const char *suppress_map)
d62a17ae 8377{
585f1adc 8378 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8379 int ret;
585f1adc 8380 struct prefix p;
9bcb3eef 8381 struct bgp_dest *dest;
d62a17ae 8382 struct bgp_aggregate *aggregate;
fb29348a 8383 uint8_t as_set_new = as_set;
d62a17ae 8384
365ab2e7 8385 if (suppress_map && summary_only) {
585f1adc 8386 vty_out(vty,
365ab2e7 8387 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8388 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8389 }
8390
585f1adc
IR
8391 /* Convert string to prefix structure. */
8392 ret = str2prefix(prefix_str, &p);
8393 if (!ret) {
8394 vty_out(vty, "Malformed prefix\n");
8395 return CMD_WARNING_CONFIG_FAILED;
8396 }
8397 apply_mask(&p);
d62a17ae 8398
585f1adc
IR
8399 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8400 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8401 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8402 prefix_str);
8403 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8404 }
8405
d62a17ae 8406 /* Old configuration check. */
585f1adc 8407 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8408 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8409
20894f50 8410 if (aggregate) {
585f1adc 8411 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8412 /* try to remove the old entry */
585f1adc 8413 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8414 if (ret) {
585f1adc 8415 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8416 bgp_dest_unlock_node(dest);
585f1adc 8417 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8418 }
8419 }
718e3744 8420
d62a17ae 8421 /* Make aggregate address structure. */
8422 aggregate = bgp_aggregate_new();
8423 aggregate->summary_only = summary_only;
6aabb15d 8424 aggregate->match_med = match_med;
fb29348a
DA
8425
8426 /* Network operators MUST NOT locally generate any new
8427 * announcements containing AS_SET or AS_CONFED_SET. If they have
8428 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8429 * SHOULD withdraw those routes and re-announce routes for the
8430 * aggregate or component prefixes (i.e., the more-specific routes
8431 * subsumed by the previously aggregated route) without AS_SET
8432 * or AS_CONFED_SET in the updates.
8433 */
7f972cd8 8434 if (bgp->reject_as_sets) {
fb29348a
DA
8435 if (as_set == AGGREGATE_AS_SET) {
8436 as_set_new = AGGREGATE_AS_UNSET;
8437 zlog_warn(
63efca0e 8438 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8439 __func__);
585f1adc 8440 vty_out(vty,
fb29348a
DA
8441 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8442 }
8443 }
8444
8445 aggregate->as_set = as_set_new;
d62a17ae 8446 aggregate->safi = safi;
229757f1
DA
8447 /* Override ORIGIN attribute if defined.
8448 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8449 * to IGP which is not what rfc4271 says.
8450 * This enables the same behavior, optionally.
8451 */
8452 aggregate->origin = origin;
20894f50
DA
8453
8454 if (rmap) {
8455 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8456 route_map_counter_decrement(aggregate->rmap.map);
8457 aggregate->rmap.name =
8458 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8459 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8460 route_map_counter_increment(aggregate->rmap.map);
8461 }
365ab2e7
RZ
8462
8463 if (suppress_map) {
8464 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8465 route_map_counter_decrement(aggregate->suppress_map);
8466
8467 aggregate->suppress_map_name =
8468 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8469 aggregate->suppress_map =
8470 route_map_lookup_by_name(aggregate->suppress_map_name);
8471 route_map_counter_increment(aggregate->suppress_map);
8472 }
8473
9bcb3eef 8474 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8475
d62a17ae 8476 /* Aggregate address insert into BGP routing table. */
585f1adc 8477 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8478
585f1adc 8479 return CMD_SUCCESS;
718e3744 8480}
8481
585f1adc
IR
8482DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8483 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8484 "as-set$as_set_s"
8485 "|summary-only$summary_only"
cacba915 8486 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8487 "|origin <egp|igp|incomplete>$origin_s"
8488 "|matching-MED-only$match_med"
cacba915 8489 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8490 "}]",
8491 NO_STR
8492 "Configure BGP aggregate entries\n"
764402fe
DA
8493 "Aggregate prefix\n"
8494 "Aggregate address\n"
8495 "Aggregate mask\n"
585f1adc
IR
8496 "Generate AS set path information\n"
8497 "Filter more specific routes from updates\n"
8498 "Apply route map to aggregate network\n"
8499 "Route map name\n"
8500 "BGP origin code\n"
8501 "Remote EGP\n"
8502 "Local IGP\n"
8503 "Unknown heritage\n"
8504 "Only aggregate routes with matching MED\n"
8505 "Suppress the selected more specific routes\n"
8506 "Route map with the route selectors\n")
8507{
8508 const char *prefix_s = NULL;
554b3b10 8509 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8510 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8511 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8512 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8513
554b3b10 8514 if (addr_str) {
7533cad7
QY
8515 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8516 sizeof(prefix_buf))
554b3b10
RZ
8517 == 0) {
8518 vty_out(vty, "%% Inconsistent address and mask\n");
8519 return CMD_WARNING_CONFIG_FAILED;
8520 }
585f1adc
IR
8521 prefix_s = prefix_buf;
8522 } else
8523 prefix_s = prefix_str;
37a87b8f 8524
585f1adc
IR
8525 if (origin_s) {
8526 if (strcmp(origin_s, "egp") == 0)
8527 origin = BGP_ORIGIN_EGP;
8528 else if (strcmp(origin_s, "igp") == 0)
8529 origin = BGP_ORIGIN_IGP;
8530 else if (strcmp(origin_s, "incomplete") == 0)
8531 origin = BGP_ORIGIN_INCOMPLETE;
8532 }
90e21f35 8533
585f1adc
IR
8534 if (as_set_s)
8535 as_set = AGGREGATE_AS_SET;
554b3b10 8536
585f1adc 8537 /* Handle configuration removal, otherwise installation. */
554b3b10 8538 if (no)
585f1adc
IR
8539 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8540
8541 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8542 summary_only != NULL, as_set, origin,
8543 match_med != NULL, suppress_map);
8544}
8545
8546DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8547 "[no] aggregate-address X:X::X:X/M$prefix [{"
8548 "as-set$as_set_s"
8549 "|summary-only$summary_only"
cacba915 8550 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8551 "|origin <egp|igp|incomplete>$origin_s"
8552 "|matching-MED-only$match_med"
cacba915 8553 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8554 "}]",
8555 NO_STR
8556 "Configure BGP aggregate entries\n"
8557 "Aggregate prefix\n"
8558 "Generate AS set path information\n"
8559 "Filter more specific routes from updates\n"
8560 "Apply route map to aggregate network\n"
8561 "Route map name\n"
8562 "BGP origin code\n"
8563 "Remote EGP\n"
8564 "Local IGP\n"
8565 "Unknown heritage\n"
8566 "Only aggregate routes with matching MED\n"
8567 "Suppress the selected more specific routes\n"
8568 "Route map with the route selectors\n")
8569{
8570 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8571 int as_set = AGGREGATE_AS_UNSET;
8572
8573 if (origin_s) {
8574 if (strcmp(origin_s, "egp") == 0)
8575 origin = BGP_ORIGIN_EGP;
8576 else if (strcmp(origin_s, "igp") == 0)
8577 origin = BGP_ORIGIN_IGP;
8578 else if (strcmp(origin_s, "incomplete") == 0)
8579 origin = BGP_ORIGIN_INCOMPLETE;
8580 }
8581
8582 if (as_set_s)
8583 as_set = AGGREGATE_AS_SET;
8584
8585 /* Handle configuration removal, otherwise installation. */
554b3b10 8586 if (no)
585f1adc
IR
8587 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8588 SAFI_UNICAST);
554b3b10 8589
585f1adc
IR
8590 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8591 rmap_name, summary_only != NULL, as_set,
8592 origin, match_med != NULL, suppress_map);
718e3744 8593}
8594
718e3744 8595/* Redistribute route treatment. */
d62a17ae 8596void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8597 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8598 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8599 enum blackhole_type bhtype, uint32_t metric,
8600 uint8_t type, unsigned short instance,
8601 route_tag_t tag)
d62a17ae 8602{
4b7e6066 8603 struct bgp_path_info *new;
40381db7
DS
8604 struct bgp_path_info *bpi;
8605 struct bgp_path_info rmap_path;
9bcb3eef 8606 struct bgp_dest *bn;
d62a17ae 8607 struct attr attr;
8608 struct attr *new_attr;
8609 afi_t afi;
b68885f9 8610 route_map_result_t ret;
d62a17ae 8611 struct bgp_redist *red;
8612
8613 /* Make default attribute. */
0f05ea43 8614 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8615 /*
8616 * This must not be NULL to satisfy Coverity SA
8617 */
8618 assert(attr.aspath);
9de1f7ff 8619
a4d82a8a 8620 switch (nhtype) {
9de1f7ff 8621 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8622 switch (p->family) {
8623 case AF_INET:
8624 attr.nexthop.s_addr = INADDR_ANY;
8625 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8626 break;
8627 case AF_INET6:
8628 memset(&attr.mp_nexthop_global, 0,
8629 sizeof(attr.mp_nexthop_global));
8630 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8631 break;
8632 }
9de1f7ff
DS
8633 break;
8634 case NEXTHOP_TYPE_IPV4:
8635 case NEXTHOP_TYPE_IPV4_IFINDEX:
8636 attr.nexthop = nexthop->ipv4;
7226bc40 8637 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8638 break;
8639 case NEXTHOP_TYPE_IPV6:
8640 case NEXTHOP_TYPE_IPV6_IFINDEX:
8641 attr.mp_nexthop_global = nexthop->ipv6;
8642 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8643 break;
8644 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8645 switch (p->family) {
8646 case AF_INET:
9de1f7ff 8647 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8648 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8649 break;
8650 case AF_INET6:
9de1f7ff
DS
8651 memset(&attr.mp_nexthop_global, 0,
8652 sizeof(attr.mp_nexthop_global));
74489921 8653 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8654 break;
74489921 8655 }
0789eb69 8656 attr.bh_type = bhtype;
9de1f7ff 8657 break;
d62a17ae 8658 }
0789eb69 8659 attr.nh_type = nhtype;
74489921 8660 attr.nh_ifindex = ifindex;
f04a80a5 8661
d62a17ae 8662 attr.med = metric;
957f74c3 8663 attr.distance = distance;
d62a17ae 8664 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8665 attr.tag = tag;
718e3744 8666
97a52c82
DA
8667 if (metric)
8668 bgp_attr_set_aigp_metric(&attr, metric);
8669
d62a17ae 8670 afi = family2afi(p->family);
6aeb9e78 8671
d62a17ae 8672 red = bgp_redist_lookup(bgp, afi, type, instance);
8673 if (red) {
8674 struct attr attr_new;
718e3744 8675
d62a17ae 8676 /* Copy attribute for modification. */
6f4f49b2 8677 attr_new = attr;
718e3744 8678
97a52c82 8679 if (red->redist_metric_flag) {
d62a17ae 8680 attr_new.med = red->redist_metric;
97a52c82
DA
8681 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8682 }
718e3744 8683
d62a17ae 8684 /* Apply route-map. */
8685 if (red->rmap.name) {
6006b807 8686 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8687 rmap_path.peer = bgp->peer_self;
8688 rmap_path.attr = &attr_new;
718e3744 8689
d62a17ae 8690 SET_FLAG(bgp->peer_self->rmap_type,
8691 PEER_RMAP_TYPE_REDISTRIBUTE);
8692
1782514f 8693 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8694
8695 bgp->peer_self->rmap_type = 0;
8696
8697 if (ret == RMAP_DENYMATCH) {
8698 /* Free uninterned attribute. */
8699 bgp_attr_flush(&attr_new);
8700
8701 /* Unintern original. */
8702 aspath_unintern(&attr.aspath);
8703 bgp_redistribute_delete(bgp, p, type, instance);
8704 return;
8705 }
8706 }
8707
637e5ba4 8708 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8709 bgp_attr_add_gshut_community(&attr_new);
8710
d62a17ae 8711 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8712 SAFI_UNICAST, p, NULL);
8713
8714 new_attr = bgp_attr_intern(&attr_new);
8715
9bcb3eef 8716 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8717 if (bpi->peer == bgp->peer_self
8718 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8719 break;
8720
40381db7 8721 if (bpi) {
d62a17ae 8722 /* Ensure the (source route) type is updated. */
40381db7
DS
8723 bpi->type = type;
8724 if (attrhash_cmp(bpi->attr, new_attr)
8725 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8726 bgp_attr_unintern(&new_attr);
8727 aspath_unintern(&attr.aspath);
9bcb3eef 8728 bgp_dest_unlock_node(bn);
d62a17ae 8729 return;
8730 } else {
8731 /* The attribute is changed. */
40381db7 8732 bgp_path_info_set_flag(bn, bpi,
18ee8310 8733 BGP_PATH_ATTR_CHANGED);
d62a17ae 8734
8735 /* Rewrite BGP route information. */
40381db7
DS
8736 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8737 bgp_path_info_restore(bn, bpi);
d62a17ae 8738 else
40381db7
DS
8739 bgp_aggregate_decrement(
8740 bgp, p, bpi, afi, SAFI_UNICAST);
8741 bgp_attr_unintern(&bpi->attr);
8742 bpi->attr = new_attr;
083ec940 8743 bpi->uptime = monotime(NULL);
d62a17ae 8744
8745 /* Process change. */
40381db7 8746 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8747 SAFI_UNICAST);
8748 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8749 bgp_dest_unlock_node(bn);
d62a17ae 8750 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8751
8752 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8753 || (bgp->inst_type
8754 == BGP_INSTANCE_TYPE_DEFAULT)) {
8755
8756 vpn_leak_from_vrf_update(
40381db7 8757 bgp_get_default(), bgp, bpi);
ddb5b488 8758 }
d62a17ae 8759 return;
8760 }
8761 }
8762
8763 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8764 bgp->peer_self, new_attr, bn);
1defdda8 8765 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8766
8767 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8768 bgp_path_info_add(bn, new);
9bcb3eef 8769 bgp_dest_unlock_node(bn);
be785e35 8770 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8771 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8772
8773 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8774 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8775
8776 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8777 }
d62a17ae 8778 }
8779
8780 /* Unintern original. */
8781 aspath_unintern(&attr.aspath);
718e3744 8782}
8783
d7c0a89a
QY
8784void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8785 unsigned short instance)
718e3744 8786{
d62a17ae 8787 afi_t afi;
9bcb3eef 8788 struct bgp_dest *dest;
40381db7 8789 struct bgp_path_info *pi;
d62a17ae 8790 struct bgp_redist *red;
718e3744 8791
d62a17ae 8792 afi = family2afi(p->family);
718e3744 8793
d62a17ae 8794 red = bgp_redist_lookup(bgp, afi, type, instance);
8795 if (red) {
9bcb3eef
DS
8796 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8797 SAFI_UNICAST, p, NULL);
d62a17ae 8798
9bcb3eef 8799 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8800 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8801 break;
8802
40381db7 8803 if (pi) {
ddb5b488
PZ
8804 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8805 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8806
8807 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8808 bgp, pi);
ddb5b488 8809 }
40381db7 8810 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8811 bgp_path_info_delete(dest, pi);
8812 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8813 }
9bcb3eef 8814 bgp_dest_unlock_node(dest);
d62a17ae 8815 }
8816}
8817
8818/* Withdraw specified route type's route. */
8819void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8820 unsigned short instance)
d62a17ae 8821{
9bcb3eef 8822 struct bgp_dest *dest;
40381db7 8823 struct bgp_path_info *pi;
d62a17ae 8824 struct bgp_table *table;
8825
8826 table = bgp->rib[afi][SAFI_UNICAST];
8827
9bcb3eef
DS
8828 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8829 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8830 if (pi->peer == bgp->peer_self && pi->type == type
8831 && pi->instance == instance)
d62a17ae 8832 break;
8833
40381db7 8834 if (pi) {
ddb5b488
PZ
8835 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8836 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8837
8838 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8839 bgp, pi);
ddb5b488 8840 }
9bcb3eef 8841 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8842 pi, afi, SAFI_UNICAST);
9bcb3eef 8843 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8844 if (!CHECK_FLAG(bgp->flags,
8845 BGP_FLAG_DELETE_IN_PROGRESS))
8846 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8847 else
8848 bgp_path_info_reap(dest, pi);
d62a17ae 8849 }
718e3744 8850 }
718e3744 8851}
6b0655a2 8852
718e3744 8853/* Static function to display route. */
7d3cae70
DA
8854static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8855 struct vty *vty, json_object *json, bool wide)
718e3744 8856{
be054588 8857 int len = 0;
07380148 8858 char buf[INET6_ADDRSTRLEN];
718e3744 8859
d62a17ae 8860 if (p->family == AF_INET) {
c6462ff4 8861 if (!json) {
8228a9a7 8862 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8863 } else {
8864 json_object_string_add(json, "prefix",
8865 inet_ntop(p->family,
8866 &p->u.prefix, buf,
07380148 8867 sizeof(buf)));
c6462ff4 8868 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8869 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8870 json_object_int_add(json, "version", dest->version);
c6462ff4 8871 }
d62a17ae 8872 } else if (p->family == AF_ETHERNET) {
8228a9a7 8873 len = vty_out(vty, "%pFX", p);
b03b8898 8874 } else if (p->family == AF_EVPN) {
57f7feb6 8875 if (!json)
2dbe669b 8876 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8877 else
60466a63 8878 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8879 } else if (p->family == AF_FLOWSPEC) {
8880 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8881 json ?
8882 NLRI_STRING_FORMAT_JSON_SIMPLE :
8883 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8884 } else {
c6462ff4 8885 if (!json)
8228a9a7 8886 len = vty_out(vty, "%pFX", p);
50e05855
AD
8887 else {
8888 json_object_string_add(json, "prefix",
07380148
DA
8889 inet_ntop(p->family,
8890 &p->u.prefix, buf,
8891 sizeof(buf)));
50e05855 8892 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8893 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8894 json_object_int_add(json, "version", dest->version);
37d4e0df 8895 }
9c92b5f7 8896 }
d62a17ae 8897
9c92b5f7 8898 if (!json) {
ae248832 8899 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8900 if (len < 1)
8901 vty_out(vty, "\n%*s", 20, " ");
8902 else
8903 vty_out(vty, "%*s", len, " ");
8904 }
718e3744 8905}
8906
d62a17ae 8907enum bgp_display_type {
8908 normal_list,
718e3744 8909};
8910
1d7260a1 8911const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8912{
8913 switch (reason) {
8914 case bgp_path_selection_none:
8915 return "Nothing to Select";
8916 case bgp_path_selection_first:
8917 return "First path received";
8918 case bgp_path_selection_evpn_sticky_mac:
8919 return "EVPN Sticky Mac";
8920 case bgp_path_selection_evpn_seq:
8921 return "EVPN sequence number";
8922 case bgp_path_selection_evpn_lower_ip:
8923 return "EVPN lower IP";
8924 case bgp_path_selection_evpn_local_path:
8925 return "EVPN local ES path";
8926 case bgp_path_selection_evpn_non_proxy:
8927 return "EVPN non proxy";
8928 case bgp_path_selection_weight:
8929 return "Weight";
8930 case bgp_path_selection_local_pref:
8931 return "Local Pref";
46dbf9d0
DA
8932 case bgp_path_selection_accept_own:
8933 return "Accept Own";
bbb46eb5
DA
8934 case bgp_path_selection_local_route:
8935 return "Local Route";
97a52c82
DA
8936 case bgp_path_selection_aigp:
8937 return "AIGP";
bbb46eb5
DA
8938 case bgp_path_selection_confed_as_path:
8939 return "Confederation based AS Path";
8940 case bgp_path_selection_as_path:
8941 return "AS Path";
8942 case bgp_path_selection_origin:
8943 return "Origin";
8944 case bgp_path_selection_med:
8945 return "MED";
8946 case bgp_path_selection_peer:
8947 return "Peer Type";
8948 case bgp_path_selection_confed:
8949 return "Confed Peer Type";
8950 case bgp_path_selection_igp_metric:
8951 return "IGP Metric";
8952 case bgp_path_selection_older:
8953 return "Older Path";
8954 case bgp_path_selection_router_id:
8955 return "Router ID";
8956 case bgp_path_selection_cluster_length:
bcab253c 8957 return "Cluster length";
bbb46eb5
DA
8958 case bgp_path_selection_stale:
8959 return "Path Staleness";
8960 case bgp_path_selection_local_configured:
8961 return "Locally configured route";
8962 case bgp_path_selection_neighbor_ip:
8963 return "Neighbor IP";
8964 case bgp_path_selection_default:
8965 return "Nothing left to compare";
8966 }
8967 return "Invalid (internal error)";
8968}
8969
18ee8310 8970/* Print the short form route status for a bgp_path_info */
4b7e6066 8971static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8972 struct bgp_path_info *path,
82c298be 8973 const struct prefix *p,
d62a17ae 8974 json_object *json_path)
718e3744 8975{
82c298be
DA
8976 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8977
d62a17ae 8978 if (json_path) {
b05a1c8b 8979
d62a17ae 8980 /* Route status display. */
9b6d8fcf 8981 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8982 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8983
9b6d8fcf 8984 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8985 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8986
4056a5f6 8987 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8988 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8989
9b6d8fcf
DS
8990 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8991 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8992 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8993
d62a17ae 8994 /* Selected */
9b6d8fcf 8995 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8996 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8997
9b6d8fcf 8998 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8999 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9000
bbb46eb5 9001 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9002 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9003 json_object_string_add(json_path, "selectionReason",
9004 bgp_path_selection_reason2str(
9005 path->net->reason));
9006 }
b05a1c8b 9007
9b6d8fcf 9008 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9009 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9010
d62a17ae 9011 /* Internal route. */
9b6d8fcf
DS
9012 if ((path->peer->as)
9013 && (path->peer->as == path->peer->local_as))
d62a17ae 9014 json_object_string_add(json_path, "pathFrom",
9015 "internal");
9016 else
9017 json_object_string_add(json_path, "pathFrom",
9018 "external");
b05a1c8b 9019
d62a17ae 9020 return;
9021 }
b05a1c8b 9022
82c298be
DA
9023 /* RPKI validation state */
9024 rpki_state =
9025 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9026
9027 if (rpki_state == RPKI_VALID)
9028 vty_out(vty, "V");
9029 else if (rpki_state == RPKI_INVALID)
9030 vty_out(vty, "I");
9031 else if (rpki_state == RPKI_NOTFOUND)
9032 vty_out(vty, "N");
eaeba5e8
WM
9033 else
9034 vty_out(vty, " ");
82c298be 9035
d62a17ae 9036 /* Route status display. */
9b6d8fcf 9037 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9038 vty_out(vty, "R");
9b6d8fcf 9039 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9040 vty_out(vty, "S");
4056a5f6 9041 else if (bgp_path_suppressed(path))
d62a17ae 9042 vty_out(vty, "s");
9b6d8fcf
DS
9043 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9044 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9045 vty_out(vty, "*");
9046 else
9047 vty_out(vty, " ");
9048
9049 /* Selected */
9b6d8fcf 9050 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9051 vty_out(vty, "h");
9b6d8fcf 9052 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9053 vty_out(vty, "d");
9b6d8fcf 9054 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9055 vty_out(vty, ">");
9b6d8fcf 9056 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9057 vty_out(vty, "=");
9058 else
9059 vty_out(vty, " ");
718e3744 9060
d62a17ae 9061 /* Internal route. */
9b6d8fcf
DS
9062 if (path->peer && (path->peer->as)
9063 && (path->peer->as == path->peer->local_as))
d62a17ae 9064 vty_out(vty, "i");
9065 else
9066 vty_out(vty, " ");
b40d939b 9067}
9068
2ba93fd6
DA
9069static char *bgp_nexthop_hostname(struct peer *peer,
9070 struct bgp_nexthop_cache *bnc)
25b5da8d 9071{
892fedb6 9072 if (peer->hostname
aef999a2 9073 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9074 return peer->hostname;
9075 return NULL;
9076}
9077
b40d939b 9078/* called from terminal list command */
bd494ec5 9079void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9080 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9081 json_object *json_paths, bool wide)
d62a17ae 9082{
aef999a2 9083 int len;
515c2602 9084 struct attr *attr = path->attr;
d62a17ae 9085 json_object *json_path = NULL;
9086 json_object *json_nexthops = NULL;
9087 json_object *json_nexthop_global = NULL;
9088 json_object *json_nexthop_ll = NULL;
6f214dd3 9089 json_object *json_ext_community = NULL;
9df8b37c 9090 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9091 bool nexthop_self =
9b6d8fcf 9092 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9093 bool nexthop_othervrf = false;
43089216 9094 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9095 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9096 char *nexthop_hostname =
9097 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9098 char esi_buf[ESI_STR_LEN];
d62a17ae 9099
9100 if (json_paths)
9101 json_path = json_object_new_object();
9102
9103 /* short status lead text */
82c298be 9104 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9105
9106 if (!json_paths) {
9107 /* print prefix and mask */
9108 if (!display)
7d3cae70 9109 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9110 else
ae248832 9111 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9112 } else {
7d3cae70 9113 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9114 }
47fc97cc 9115
9df8b37c
PZ
9116 /*
9117 * If vrf id of nexthop is different from that of prefix,
9118 * set up printable string to append
9119 */
9b6d8fcf 9120 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9121 const char *self = "";
9122
9123 if (nexthop_self)
9124 self = "<";
9125
9126 nexthop_othervrf = true;
9b6d8fcf 9127 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9128
9b6d8fcf 9129 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9130 snprintf(vrf_id_str, sizeof(vrf_id_str),
9131 "@%s%s", VRFID_NONE_STR, self);
9132 else
9133 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9134 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9135
9b6d8fcf
DS
9136 if (path->extra->bgp_orig->inst_type
9137 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9138
9b6d8fcf 9139 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9140 } else {
9141 const char *self = "";
9142
9143 if (nexthop_self)
9144 self = "<";
9145
9146 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9147 }
9148
445c2480
DS
9149 /*
9150 * For ENCAP and EVPN routes, nexthop address family is not
9151 * neccessarily the same as the prefix address family.
9152 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9153 * EVPN routes are also exchanged with a MP nexthop. Currently,
9154 * this
9155 * is only IPv4, the value will be present in either
9156 * attr->nexthop or
9157 * attr->mp_nexthop_global_in
9158 */
9159 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9160 char nexthop[128];
9161 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9162
9163 switch (af) {
9164 case AF_INET:
07380148
DA
9165 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9166 &attr->mp_nexthop_global_in);
445c2480
DS
9167 break;
9168 case AF_INET6:
07380148
DA
9169 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9170 &attr->mp_nexthop_global);
445c2480
DS
9171 break;
9172 default:
772270f3 9173 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9174 break;
d62a17ae 9175 }
d62a17ae 9176
445c2480
DS
9177 if (json_paths) {
9178 json_nexthop_global = json_object_new_object();
9179
515c2602
DA
9180 json_object_string_add(json_nexthop_global, "ip",
9181 nexthop);
9182
939a97f4 9183 if (path->peer->hostname)
515c2602
DA
9184 json_object_string_add(json_nexthop_global,
9185 "hostname",
939a97f4 9186 path->peer->hostname);
515c2602
DA
9187
9188 json_object_string_add(json_nexthop_global, "afi",
9189 (af == AF_INET) ? "ipv4"
9190 : "ipv6");
445c2480
DS
9191 json_object_boolean_true_add(json_nexthop_global,
9192 "used");
aef999a2
DA
9193 } else {
9194 if (nexthop_hostname)
9195 len = vty_out(vty, "%s(%s)%s", nexthop,
9196 nexthop_hostname, vrf_id_str);
9197 else
9198 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9199
ae248832 9200 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9201 if (len < 1)
9202 vty_out(vty, "\n%*s", 36, " ");
9203 else
9204 vty_out(vty, "%*s", len, " ");
9205 }
445c2480
DS
9206 } else if (safi == SAFI_EVPN) {
9207 if (json_paths) {
9208 json_nexthop_global = json_object_new_object();
9209
c949c771 9210 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9211 "%pI4",
9212 &attr->mp_nexthop_global_in);
515c2602 9213
939a97f4 9214 if (path->peer->hostname)
515c2602
DA
9215 json_object_string_add(json_nexthop_global,
9216 "hostname",
939a97f4 9217 path->peer->hostname);
515c2602 9218
a4d82a8a
PZ
9219 json_object_string_add(json_nexthop_global, "afi",
9220 "ipv4");
445c2480
DS
9221 json_object_boolean_true_add(json_nexthop_global,
9222 "used");
aef999a2
DA
9223 } else {
9224 if (nexthop_hostname)
7226bc40
TA
9225 len = vty_out(vty, "%pI4(%s)%s",
9226 &attr->mp_nexthop_global_in,
aef999a2
DA
9227 nexthop_hostname, vrf_id_str);
9228 else
7226bc40
TA
9229 len = vty_out(vty, "%pI4%s",
9230 &attr->mp_nexthop_global_in,
aef999a2
DA
9231 vrf_id_str);
9232
ae248832 9233 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9234 if (len < 1)
9235 vty_out(vty, "\n%*s", 36, " ");
9236 else
9237 vty_out(vty, "%*s", len, " ");
9238 }
d33fc23b 9239 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9240 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9241 if (json_paths) {
9242 json_nexthop_global = json_object_new_object();
515c2602 9243
026b914a
PG
9244 json_object_string_add(json_nexthop_global,
9245 "afi", "ipv4");
c949c771
DA
9246 json_object_string_addf(json_nexthop_global,
9247 "ip", "%pI4",
9248 &attr->nexthop);
515c2602 9249
939a97f4 9250 if (path->peer->hostname)
515c2602
DA
9251 json_object_string_add(
9252 json_nexthop_global, "hostname",
939a97f4 9253 path->peer->hostname);
515c2602 9254
50e05855
AD
9255 json_object_boolean_true_add(
9256 json_nexthop_global,
026b914a
PG
9257 "used");
9258 } else {
aef999a2
DA
9259 if (nexthop_hostname)
9260 len = vty_out(vty, "%pI4(%s)%s",
9261 &attr->nexthop,
9262 nexthop_hostname,
9263 vrf_id_str);
9264 else
9265 len = vty_out(vty, "%pI4%s",
9266 &attr->nexthop,
9267 vrf_id_str);
9268
ae248832 9269 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9270 if (len < 1)
9271 vty_out(vty, "\n%*s", 36, " ");
9272 else
9273 vty_out(vty, "%*s", len, " ");
026b914a
PG
9274 }
9275 }
7226bc40 9276 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9277 if (json_paths) {
9278 json_nexthop_global = json_object_new_object();
d62a17ae 9279
c949c771
DA
9280 json_object_string_addf(json_nexthop_global, "ip",
9281 "%pI4", &attr->nexthop);
515c2602 9282
939a97f4 9283 if (path->peer->hostname)
515c2602
DA
9284 json_object_string_add(json_nexthop_global,
9285 "hostname",
939a97f4 9286 path->peer->hostname);
445c2480 9287
a4d82a8a
PZ
9288 json_object_string_add(json_nexthop_global, "afi",
9289 "ipv4");
445c2480
DS
9290 json_object_boolean_true_add(json_nexthop_global,
9291 "used");
9292 } else {
aef999a2
DA
9293 if (nexthop_hostname)
9294 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9295 nexthop_hostname, vrf_id_str);
9296 else
9297 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9298 vrf_id_str);
9df8b37c 9299
ae248832 9300 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9301 if (len < 1)
9302 vty_out(vty, "\n%*s", 36, " ");
9303 else
9304 vty_out(vty, "%*s", len, " ");
d62a17ae 9305 }
445c2480 9306 }
b05a1c8b 9307
445c2480 9308 /* IPv6 Next Hop */
7226bc40 9309 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9310 if (json_paths) {
9311 json_nexthop_global = json_object_new_object();
c949c771
DA
9312 json_object_string_addf(json_nexthop_global, "ip",
9313 "%pI6",
9314 &attr->mp_nexthop_global);
515c2602 9315
939a97f4 9316 if (path->peer->hostname)
515c2602
DA
9317 json_object_string_add(json_nexthop_global,
9318 "hostname",
939a97f4 9319 path->peer->hostname);
515c2602 9320
a4d82a8a
PZ
9321 json_object_string_add(json_nexthop_global, "afi",
9322 "ipv6");
9323 json_object_string_add(json_nexthop_global, "scope",
9324 "global");
445c2480
DS
9325
9326 /* We display both LL & GL if both have been
9327 * received */
0606039c
DA
9328 if ((attr->mp_nexthop_len
9329 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9330 || (path->peer->conf_if)) {
a4d82a8a 9331 json_nexthop_ll = json_object_new_object();
c949c771
DA
9332 json_object_string_addf(
9333 json_nexthop_ll, "ip", "%pI6",
9334 &attr->mp_nexthop_local);
515c2602 9335
939a97f4 9336 if (path->peer->hostname)
515c2602
DA
9337 json_object_string_add(
9338 json_nexthop_ll, "hostname",
939a97f4 9339 path->peer->hostname);
515c2602 9340
a4d82a8a
PZ
9341 json_object_string_add(json_nexthop_ll, "afi",
9342 "ipv6");
9343 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9344 "link-local");
d62a17ae 9345
a4d82a8a 9346 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9347 &attr->mp_nexthop_local)
9348 != 0)
9349 && !attr->mp_nexthop_prefer_global)
d62a17ae 9350 json_object_boolean_true_add(
a4d82a8a 9351 json_nexthop_ll, "used");
445c2480
DS
9352 else
9353 json_object_boolean_true_add(
a4d82a8a 9354 json_nexthop_global, "used");
445c2480
DS
9355 } else
9356 json_object_boolean_true_add(
9357 json_nexthop_global, "used");
9358 } else {
9359 /* Display LL if LL/Global both in table unless
9360 * prefer-global is set */
2bb8b49c
DS
9361 if (((attr->mp_nexthop_len
9362 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9363 && !attr->mp_nexthop_prefer_global)
9364 || (path->peer->conf_if)) {
9b6d8fcf 9365 if (path->peer->conf_if) {
a4d82a8a 9366 len = vty_out(vty, "%s",
9b6d8fcf 9367 path->peer->conf_if);
ae248832
MK
9368 /* len of IPv6 addr + max len of def
9369 * ifname */
9370 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9371
9372 if (len < 1)
a4d82a8a 9373 vty_out(vty, "\n%*s", 36, " ");
445c2480 9374 else
a4d82a8a 9375 vty_out(vty, "%*s", len, " ");
d62a17ae 9376 } else {
aef999a2
DA
9377 if (nexthop_hostname)
9378 len = vty_out(
9379 vty, "%pI6(%s)%s",
9380 &attr->mp_nexthop_local,
9381 nexthop_hostname,
9382 vrf_id_str);
9383 else
9384 len = vty_out(
9385 vty, "%pI6%s",
9386 &attr->mp_nexthop_local,
9387 vrf_id_str);
9388
ae248832 9389 len = wide ? (41 - len) : (16 - len);
d62a17ae 9390
9391 if (len < 1)
a4d82a8a 9392 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9393 else
a4d82a8a 9394 vty_out(vty, "%*s", len, " ");
d62a17ae 9395 }
445c2480 9396 } else {
aef999a2
DA
9397 if (nexthop_hostname)
9398 len = vty_out(vty, "%pI6(%s)%s",
9399 &attr->mp_nexthop_global,
9400 nexthop_hostname,
9401 vrf_id_str);
9402 else
9403 len = vty_out(vty, "%pI6%s",
9404 &attr->mp_nexthop_global,
9405 vrf_id_str);
9406
ae248832 9407 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9408
9409 if (len < 1)
9410 vty_out(vty, "\n%*s", 36, " ");
9411 else
9412 vty_out(vty, "%*s", len, " ");
d62a17ae 9413 }
9414 }
445c2480 9415 }
718e3744 9416
445c2480
DS
9417 /* MED/Metric */
9418 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9419 if (json_paths)
50e05855 9420 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9421 else if (wide)
9422 vty_out(vty, "%7u", attr->med);
0fbac0b4 9423 else
445c2480 9424 vty_out(vty, "%10u", attr->med);
ae248832
MK
9425 else if (!json_paths) {
9426 if (wide)
9427 vty_out(vty, "%*s", 7, " ");
9428 else
9429 vty_out(vty, "%*s", 10, " ");
9430 }
d62a17ae 9431
445c2480
DS
9432 /* Local Pref */
9433 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9434 if (json_paths)
50e05855 9435 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9436 attr->local_pref);
9437 else
445c2480
DS
9438 vty_out(vty, "%7u", attr->local_pref);
9439 else if (!json_paths)
9440 vty_out(vty, " ");
d62a17ae 9441
445c2480
DS
9442 if (json_paths)
9443 json_object_int_add(json_path, "weight", attr->weight);
9444 else
9445 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9446
47e12884
DA
9447 if (json_paths)
9448 json_object_string_addf(json_path, "peerId", "%pSU",
9449 &path->peer->su);
b05a1c8b 9450
445c2480
DS
9451 /* Print aspath */
9452 if (attr->aspath) {
0fbac0b4 9453 if (json_paths)
50e05855 9454 json_object_string_add(json_path, "path",
0fbac0b4
DA
9455 attr->aspath->str);
9456 else
e678b143 9457 aspath_print_vty(vty, attr->aspath);
d62a17ae 9458 }
f1aa5d8a 9459
445c2480
DS
9460 /* Print origin */
9461 if (json_paths)
a4d82a8a
PZ
9462 json_object_string_add(json_path, "origin",
9463 bgp_origin_long_str[attr->origin]);
445c2480
DS
9464 else
9465 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9466
9df8b37c 9467 if (json_paths) {
d071f237 9468 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9469 json_object_string_add(json_path, "esi",
9470 esi_to_str(&attr->esi,
9471 esi_buf, sizeof(esi_buf)));
9472 }
6f214dd3
CS
9473 if (safi == SAFI_EVPN &&
9474 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9475 json_ext_community = json_object_new_object();
b53e67a3
DA
9476 json_object_string_add(
9477 json_ext_community, "string",
9478 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9479 json_object_object_add(json_path,
9480 "extendedCommunity",
9481 json_ext_community);
9482 }
9483
9df8b37c
PZ
9484 if (nexthop_self)
9485 json_object_boolean_true_add(json_path,
9486 "announceNexthopSelf");
9487 if (nexthop_othervrf) {
9488 json_object_string_add(json_path, "nhVrfName",
9489 nexthop_vrfname);
9490
9491 json_object_int_add(json_path, "nhVrfId",
9492 ((nexthop_vrfid == VRF_UNKNOWN)
9493 ? -1
9494 : (int)nexthop_vrfid));
9495 }
9496 }
9497
d62a17ae 9498 if (json_paths) {
9499 if (json_nexthop_global || json_nexthop_ll) {
9500 json_nexthops = json_object_new_array();
f1aa5d8a 9501
d62a17ae 9502 if (json_nexthop_global)
9503 json_object_array_add(json_nexthops,
9504 json_nexthop_global);
f1aa5d8a 9505
d62a17ae 9506 if (json_nexthop_ll)
9507 json_object_array_add(json_nexthops,
9508 json_nexthop_ll);
f1aa5d8a 9509
d62a17ae 9510 json_object_object_add(json_path, "nexthops",
9511 json_nexthops);
9512 }
9513
9514 json_object_array_add(json_paths, json_path);
9515 } else {
9516 vty_out(vty, "\n");
6f214dd3 9517
b5e140c8 9518 if (safi == SAFI_EVPN) {
d071f237 9519 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9520 /* XXX - add these params to the json out */
b5e140c8 9521 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9522 vty_out(vty, "ESI:%s",
9523 esi_to_str(&attr->esi, esi_buf,
9524 sizeof(esi_buf)));
60605cbc 9525
229587fb 9526 vty_out(vty, "\n");
b5e140c8
AK
9527 }
9528 if (attr->flag &
9529 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9530 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9531 vty_out(vty, "%s\n",
9532 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9533 }
6f214dd3
CS
9534 }
9535
49e5a4a0 9536#ifdef ENABLE_BGP_VNC
d62a17ae 9537 /* prints an additional line, indented, with VNC info, if
9538 * present */
9539 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9540 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9541#endif
d62a17ae 9542 }
9543}
718e3744 9544
9545/* called from terminal list command */
7d3cae70
DA
9546void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9547 const struct prefix *p, struct attr *attr, safi_t safi,
9548 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9549{
9550 json_object *json_status = NULL;
9551 json_object *json_net = NULL;
aef999a2 9552 int len;
d62a17ae 9553 char buff[BUFSIZ];
dc387b0f 9554
d62a17ae 9555 /* Route status display. */
9556 if (use_json) {
9557 json_status = json_object_new_object();
9558 json_net = json_object_new_object();
9559 } else {
146c574b 9560 vty_out(vty, " *");
d62a17ae 9561 vty_out(vty, ">");
9562 vty_out(vty, " ");
9563 }
718e3744 9564
d62a17ae 9565 /* print prefix and mask */
50e05855 9566 if (use_json) {
dc387b0f
LK
9567 if (safi == SAFI_EVPN)
9568 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9569 else if (p->family == AF_INET || p->family == AF_INET6) {
9570 json_object_string_add(
9571 json_net, "addrPrefix",
9572 inet_ntop(p->family, &p->u.prefix, buff,
9573 BUFSIZ));
9574 json_object_int_add(json_net, "prefixLen",
9575 p->prefixlen);
67d7e256 9576 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9577 }
50e05855 9578 } else
7d3cae70 9579 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9580
9581 /* Print attribute */
9582 if (attr) {
9583 if (use_json) {
7226bc40
TA
9584 if (p->family == AF_INET &&
9585 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9586 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9587 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9588 json_object_string_addf(
9589 json_net, "nextHop", "%pI4",
9590 &attr->mp_nexthop_global_in);
d62a17ae 9591 else
c949c771
DA
9592 json_object_string_addf(
9593 json_net, "nextHop", "%pI4",
9594 &attr->nexthop);
7226bc40
TA
9595 } else if (p->family == AF_INET6 ||
9596 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9597 json_object_string_addf(
9598 json_net, "nextHopGlobal", "%pI6",
9599 &attr->mp_nexthop_global);
7226bc40
TA
9600 } else if (p->family == AF_EVPN &&
9601 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9602 json_object_string_addf(
9603 json_net, "nextHop", "%pI4",
9604 &attr->mp_nexthop_global_in);
23d0a753 9605 }
d62a17ae 9606
9607 if (attr->flag
9608 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9609 json_object_int_add(json_net, "metric",
9610 attr->med);
9611
0fbac0b4 9612 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9613 json_object_int_add(json_net, "locPrf",
0fbac0b4 9614 attr->local_pref);
d62a17ae 9615
9616 json_object_int_add(json_net, "weight", attr->weight);
9617
9618 /* Print aspath */
0fbac0b4 9619 if (attr->aspath)
50e05855 9620 json_object_string_add(json_net, "path",
0fbac0b4 9621 attr->aspath->str);
d62a17ae 9622
9623 /* Print origin */
dd426a51
DA
9624#if CONFDATE > 20231208
9625CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9626#endif
d62a17ae 9627 json_object_string_add(json_net, "bgpOriginCode",
9628 bgp_origin_str[attr->origin]);
dd426a51
DA
9629 json_object_string_add(
9630 json_net, "origin",
9631 bgp_origin_long_str[attr->origin]);
d62a17ae 9632 } else {
7226bc40
TA
9633 if (p->family == AF_INET &&
9634 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9635 safi == SAFI_EVPN ||
9636 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9637 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9638 || safi == SAFI_EVPN)
23d0a753
DA
9639 vty_out(vty, "%-16pI4",
9640 &attr->mp_nexthop_global_in);
ae248832 9641 else if (wide)
23d0a753 9642 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9643 else
23d0a753 9644 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9645 } else if (p->family == AF_INET6 ||
9646 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9647 len = vty_out(vty, "%pI6",
9648 &attr->mp_nexthop_global);
ae248832 9649 len = wide ? (41 - len) : (16 - len);
d62a17ae 9650 if (len < 1)
9651 vty_out(vty, "\n%*s", 36, " ");
9652 else
9653 vty_out(vty, "%*s", len, " ");
9654 }
9655 if (attr->flag
9656 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9657 if (wide)
9658 vty_out(vty, "%7u", attr->med);
9659 else
9660 vty_out(vty, "%10u", attr->med);
9661 else if (wide)
9662 vty_out(vty, " ");
d62a17ae 9663 else
9664 vty_out(vty, " ");
718e3744 9665
d62a17ae 9666 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9667 vty_out(vty, "%7u", attr->local_pref);
9668 else
9669 vty_out(vty, " ");
9670
9671 vty_out(vty, "%7u ", attr->weight);
9672
9673 /* Print aspath */
9674 if (attr->aspath)
e678b143 9675 aspath_print_vty(vty, attr->aspath);
d62a17ae 9676
9677 /* Print origin */
9678 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9679 }
9680 }
9681 if (use_json) {
4d65410c
DA
9682 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9683
dd426a51
DA
9684#if CONFDATE > 20231208
9685CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9686#endif
d62a17ae 9687 json_object_boolean_true_add(json_status, "*");
9688 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9689 json_object_boolean_true_add(json_net, "valid");
9690 json_object_boolean_true_add(json_net, "best");
4d65410c 9691
dd426a51 9692 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9693 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9694 json_object_boolean_true_add(json_net, "multipath");
9695 }
d62a17ae 9696 json_object_object_add(json_net, "appliedStatusSymbols",
9697 json_status);
511211bf 9698 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9699 } else
9700 vty_out(vty, "\n");
9701}
9702
bd494ec5 9703void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9704 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9705 json_object *json)
9706{
9707 json_object *json_out = NULL;
9708 struct attr *attr;
9709 mpls_label_t label = MPLS_INVALID_LABEL;
9710
9b6d8fcf 9711 if (!path->extra)
d62a17ae 9712 return;
9713
9714 if (json)
9715 json_out = json_object_new_object();
9716
9717 /* short status lead text */
82c298be 9718 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9719
9720 /* print prefix and mask */
9721 if (json == NULL) {
9722 if (!display)
7d3cae70 9723 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9724 else
9725 vty_out(vty, "%*s", 17, " ");
9726 }
9727
9728 /* Print attribute */
9b6d8fcf 9729 attr = path->attr;
7226bc40
TA
9730 if (((p->family == AF_INET) &&
9731 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9732 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9733 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9734 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9735 || safi == SAFI_EVPN) {
9736 if (json)
c949c771
DA
9737 json_object_string_addf(
9738 json_out, "mpNexthopGlobalIn", "%pI4",
9739 &attr->mp_nexthop_global_in);
05864da7 9740 else
23d0a753
DA
9741 vty_out(vty, "%-16pI4",
9742 &attr->mp_nexthop_global_in);
05864da7
DS
9743 } else {
9744 if (json)
c949c771
DA
9745 json_object_string_addf(json_out, "nexthop",
9746 "%pI4", &attr->nexthop);
05864da7 9747 else
23d0a753 9748 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9749 }
7226bc40
TA
9750 } else if (((p->family == AF_INET6) &&
9751 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9752 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9753 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9754 char buf_a[512];
9755
9756 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9757 if (json)
c949c771
DA
9758 json_object_string_addf(
9759 json_out, "mpNexthopGlobalIn", "%pI6",
9760 &attr->mp_nexthop_global);
05864da7
DS
9761 else
9762 vty_out(vty, "%s",
9763 inet_ntop(AF_INET6,
9764 &attr->mp_nexthop_global,
9765 buf_a, sizeof(buf_a)));
9766 } else if (attr->mp_nexthop_len
9767 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9768 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9769 &attr->mp_nexthop_global,
9770 &attr->mp_nexthop_local);
9771 if (json)
9772 json_object_string_add(json_out,
9773 "mpNexthopGlobalLocal",
9774 buf_a);
9775 else
9776 vty_out(vty, "%s", buf_a);
d62a17ae 9777 }
9778 }
9779
9b6d8fcf 9780 label = decode_label(&path->extra->label[0]);
d62a17ae 9781
9782 if (bgp_is_valid_label(&label)) {
9783 if (json) {
9784 json_object_int_add(json_out, "notag", label);
9785 json_object_array_add(json, json_out);
9786 } else {
9787 vty_out(vty, "notag/%d", label);
9788 vty_out(vty, "\n");
9789 }
700ddfed
PG
9790 } else if (!json)
9791 vty_out(vty, "\n");
d62a17ae 9792}
718e3744 9793
bd494ec5 9794void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9795 struct bgp_path_info *path, int display,
d62a17ae 9796 json_object *json_paths)
718e3744 9797{
d62a17ae 9798 struct attr *attr;
d62a17ae 9799 json_object *json_path = NULL;
14f51eba
LK
9800 json_object *json_nexthop = NULL;
9801 json_object *json_overlay = NULL;
856ca177 9802
9b6d8fcf 9803 if (!path->extra)
d62a17ae 9804 return;
718e3744 9805
14f51eba
LK
9806 if (json_paths) {
9807 json_path = json_object_new_object();
9808 json_overlay = json_object_new_object();
9809 json_nexthop = json_object_new_object();
9810 }
9811
d62a17ae 9812 /* short status lead text */
82c298be 9813 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9814
d62a17ae 9815 /* print prefix and mask */
9816 if (!display)
7d3cae70 9817 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9818 else
9819 vty_out(vty, "%*s", 17, " ");
9820
9821 /* Print attribute */
9b6d8fcf 9822 attr = path->attr;
05864da7 9823 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9824
05864da7
DS
9825 switch (af) {
9826 case AF_INET:
05864da7 9827 if (!json_path) {
db66cf7c 9828 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9829 } else {
db66cf7c
DA
9830 json_object_string_addf(json_nexthop, "ip", "%pI4",
9831 &attr->mp_nexthop_global_in);
14f51eba 9832
05864da7 9833 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9834
05864da7
DS
9835 json_object_object_add(json_path, "nexthop",
9836 json_nexthop);
9837 }
9838 break;
9839 case AF_INET6:
05864da7 9840 if (!json_path) {
db66cf7c
DA
9841 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9842 &attr->mp_nexthop_local);
05864da7 9843 } else {
db66cf7c
DA
9844 json_object_string_addf(json_nexthop, "ipv6Global",
9845 "%pI6",
9846 &attr->mp_nexthop_global);
14f51eba 9847
db66cf7c
DA
9848 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9849 "%pI6",
9850 &attr->mp_nexthop_local);
14f51eba 9851
05864da7 9852 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9853
05864da7
DS
9854 json_object_object_add(json_path, "nexthop",
9855 json_nexthop);
9856 }
9857 break;
9858 default:
9859 if (!json_path) {
9860 vty_out(vty, "?");
9861 } else {
77a2f8e5
DA
9862 json_object_string_add(json_nexthop, "error",
9863 "Unsupported address-family");
d62a17ae 9864 }
05864da7 9865 }
988258b4 9866
6c924775
DS
9867 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9868
05864da7 9869 if (!json_path)
db66cf7c 9870 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9871 else
db66cf7c 9872 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9873
b53e67a3 9874 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9875 char *mac = NULL;
9876 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9877 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9878 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9879
9880 if (routermac)
9881 mac = ecom_mac2str((char *)routermac->val);
9882 if (mac) {
9883 if (!json_path) {
c4efd0f4 9884 vty_out(vty, "/%s", mac);
05864da7
DS
9885 } else {
9886 json_object_string_add(json_overlay, "rmac",
9887 mac);
988258b4 9888 }
05864da7 9889 XFREE(MTYPE_TMP, mac);
988258b4 9890 }
05864da7 9891 }
718e3744 9892
05864da7
DS
9893 if (!json_path) {
9894 vty_out(vty, "\n");
9895 } else {
9896 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9897
05864da7 9898 json_object_array_add(json_paths, json_path);
14f51eba 9899 }
d62a17ae 9900}
718e3744 9901
d62a17ae 9902/* dampening route */
5f040085
DS
9903static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9904 struct bgp_path_info *path, int display,
9905 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9906 json_object *json_paths)
d62a17ae 9907{
e5be8c1d 9908 struct attr *attr = path->attr;
d62a17ae 9909 int len;
9910 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9911 json_object *json_path = NULL;
9912
9913 if (use_json)
9914 json_path = json_object_new_object();
d62a17ae 9915
9916 /* short status lead text */
e5be8c1d 9917 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9918
9919 /* print prefix and mask */
9920 if (!use_json) {
9921 if (!display)
7d3cae70 9922 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9923 else
9924 vty_out(vty, "%*s", 17, " ");
d62a17ae 9925
e5be8c1d
DA
9926 len = vty_out(vty, "%s", path->peer->host);
9927 len = 17 - len;
9928
9929 if (len < 1)
d62a17ae 9930 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9931 else
9932 vty_out(vty, "%*s", len, " ");
d62a17ae 9933
9b6d8fcf
DS
9934 vty_out(vty, "%s ",
9935 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9936 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9937 use_json, NULL));
d62a17ae 9938
e5be8c1d 9939 if (attr->aspath)
e678b143 9940 aspath_print_vty(vty, attr->aspath);
05864da7 9941
05864da7
DS
9942 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9943
d62a17ae 9944 vty_out(vty, "\n");
e5be8c1d
DA
9945 } else {
9946 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9947 safi, use_json, json_path);
9948
9949 if (attr->aspath)
9950 json_object_string_add(json_path, "asPath",
9951 attr->aspath->str);
9952
9953 json_object_string_add(json_path, "origin",
9954 bgp_origin_str[attr->origin]);
9955 json_object_string_add(json_path, "peerHost", path->peer->host);
9956
9957 json_object_array_add(json_paths, json_path);
9958 }
d62a17ae 9959}
718e3744 9960
d62a17ae 9961/* flap route */
5f040085
DS
9962static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9963 struct bgp_path_info *path, int display,
9964 afi_t afi, safi_t safi, bool use_json,
31258046 9965 json_object *json_paths)
784d3a42 9966{
31258046 9967 struct attr *attr = path->attr;
d62a17ae 9968 struct bgp_damp_info *bdi;
9969 char timebuf[BGP_UPTIME_LEN];
9970 int len;
31258046 9971 json_object *json_path = NULL;
784d3a42 9972
9b6d8fcf 9973 if (!path->extra)
d62a17ae 9974 return;
784d3a42 9975
31258046
DA
9976 if (use_json)
9977 json_path = json_object_new_object();
9978
9b6d8fcf 9979 bdi = path->extra->damp_info;
784d3a42 9980
d62a17ae 9981 /* short status lead text */
31258046 9982 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9983
d62a17ae 9984 if (!use_json) {
9985 if (!display)
7d3cae70 9986 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9987 else
9988 vty_out(vty, "%*s", 17, " ");
784d3a42 9989
31258046
DA
9990 len = vty_out(vty, "%s", path->peer->host);
9991 len = 16 - len;
9992 if (len < 1)
d62a17ae 9993 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9994 else
9995 vty_out(vty, "%*s", len, " ");
784d3a42 9996
31258046
DA
9997 len = vty_out(vty, "%d", bdi->flap);
9998 len = 5 - len;
9999 if (len < 1)
d62a17ae 10000 vty_out(vty, " ");
d62a17ae 10001 else
10002 vty_out(vty, "%*s", len, " ");
d62a17ae 10003
996c9314
LB
10004 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10005 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10006
31258046
DA
10007 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10008 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10009 vty_out(vty, "%s ",
9b6d8fcf 10010 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10011 BGP_UPTIME_LEN, afi,
31258046
DA
10012 safi, use_json, NULL));
10013 else
d62a17ae 10014 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10015
31258046 10016 if (attr->aspath)
e678b143 10017 aspath_print_vty(vty, attr->aspath);
05864da7 10018
05864da7
DS
10019 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10020
d62a17ae 10021 vty_out(vty, "\n");
31258046
DA
10022 } else {
10023 json_object_string_add(json_path, "peerHost", path->peer->host);
10024 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10025
10026 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10027 json_path);
10028
10029 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10030 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10031 bgp_damp_reuse_time_vty(vty, path, timebuf,
10032 BGP_UPTIME_LEN, afi, safi,
10033 use_json, json_path);
10034
10035 if (attr->aspath)
10036 json_object_string_add(json_path, "asPath",
10037 attr->aspath->str);
10038
10039 json_object_string_add(json_path, "origin",
10040 bgp_origin_str[attr->origin]);
10041
10042 json_object_array_add(json_paths, json_path);
10043 }
d62a17ae 10044}
10045
10046static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10047 int *first, const char *header,
10048 json_object *json_adv_to)
10049{
d62a17ae 10050 json_object *json_peer = NULL;
10051
10052 if (json_adv_to) {
10053 /* 'advertised-to' is a dictionary of peers we have advertised
10054 * this
10055 * prefix too. The key is the peer's IP or swpX, the value is
10056 * the
10057 * hostname if we know it and "" if not.
10058 */
10059 json_peer = json_object_new_object();
10060
10061 if (peer->hostname)
10062 json_object_string_add(json_peer, "hostname",
10063 peer->hostname);
10064
10065 if (peer->conf_if)
10066 json_object_object_add(json_adv_to, peer->conf_if,
10067 json_peer);
10068 else
47e12884
DA
10069 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10070 &peer->su);
d62a17ae 10071 } else {
10072 if (*first) {
10073 vty_out(vty, "%s", header);
10074 *first = 0;
10075 }
10076
10077 if (peer->hostname
892fedb6 10078 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10079 if (peer->conf_if)
10080 vty_out(vty, " %s(%s)", peer->hostname,
10081 peer->conf_if);
10082 else
47e12884
DA
10083 vty_out(vty, " %s(%pSU)", peer->hostname,
10084 &peer->su);
d62a17ae 10085 } else {
10086 if (peer->conf_if)
10087 vty_out(vty, " %s", peer->conf_if);
10088 else
47e12884 10089 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10090 }
10091 }
784d3a42
PG
10092}
10093
dcc68b5e
MS
10094static void route_vty_out_tx_ids(struct vty *vty,
10095 struct bgp_addpath_info_data *d)
10096{
10097 int i;
10098
10099 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10100 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10101 d->addpath_tx_id[i],
10102 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10103 }
10104}
10105
5e4d4c8a 10106static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10107 struct bgp_path_info *pi,
10108 struct attr *attr,
10109 json_object *json_path)
5e4d4c8a
AK
10110{
10111 char esi_buf[ESI_STR_LEN];
10112 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10113 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10114 ATTR_ES_PEER_ROUTER);
10115 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10116 ATTR_ES_PEER_ACTIVE);
10117 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10118 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10119 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10120 if (json_path) {
10121 json_object *json_es_info = NULL;
10122
10123 json_object_string_add(
10124 json_path, "esi",
10125 esi_buf);
10126 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10127 json_es_info = json_object_new_object();
10128 if (es_local)
10129 json_object_boolean_true_add(
10130 json_es_info, "localEs");
10131 if (peer_active)
10132 json_object_boolean_true_add(
10133 json_es_info, "peerActive");
10134 if (peer_proxy)
10135 json_object_boolean_true_add(
10136 json_es_info, "peerProxy");
10137 if (peer_router)
10138 json_object_boolean_true_add(
10139 json_es_info, "peerRouter");
10140 if (attr->mm_sync_seqnum)
10141 json_object_int_add(
10142 json_es_info, "peerSeq",
10143 attr->mm_sync_seqnum);
10144 json_object_object_add(
10145 json_path, "es_info",
10146 json_es_info);
10147 }
10148 } else {
10149 if (bgp_evpn_attr_is_sync(attr))
10150 vty_out(vty,
10151 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10152 esi_buf,
10153 es_local ? "local-es":"",
10154 peer_proxy ? "proxy " : "",
10155 peer_active ? "active ":"",
10156 peer_router ? "router ":"",
10157 attr->mm_sync_seqnum);
10158 else
10159 vty_out(vty, " ESI %s %s\n",
10160 esi_buf,
10161 es_local ? "local-es":"");
10162 }
10163}
10164
4933eaaf 10165void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10166 const struct prefix *p, struct bgp_path_info *path,
10167 afi_t afi, safi_t safi,
4027d19b
DS
10168 enum rpki_states rpki_curr_state,
10169 json_object *json_paths)
d62a17ae 10170{
10171 char buf[INET6_ADDRSTRLEN];
100290e4 10172 char tag_buf[30];
515c2602 10173 struct attr *attr = path->attr;
d62a17ae 10174 time_t tbuf;
10175 json_object *json_bestpath = NULL;
10176 json_object *json_cluster_list = NULL;
10177 json_object *json_cluster_list_list = NULL;
10178 json_object *json_ext_community = NULL;
10179 json_object *json_last_update = NULL;
7fd077aa 10180 json_object *json_pmsi = NULL;
d62a17ae 10181 json_object *json_nexthop_global = NULL;
10182 json_object *json_nexthop_ll = NULL;
10183 json_object *json_nexthops = NULL;
10184 json_object *json_path = NULL;
10185 json_object *json_peer = NULL;
10186 json_object *json_string = NULL;
10187 json_object *json_adv_to = NULL;
10188 int first = 0;
10189 struct listnode *node, *nnode;
10190 struct peer *peer;
be92fc9f 10191 bool addpath_capable;
d62a17ae 10192 int has_adj;
10193 unsigned int first_as;
1defdda8 10194 bool nexthop_self =
9b6d8fcf 10195 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10196 int i;
2ba93fd6
DA
10197 char *nexthop_hostname =
10198 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10199 uint32_t ttl = 0;
10200 uint32_t bos = 0;
10201 uint32_t exp = 0;
10202 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10203 tag_buf[0] = '\0';
f0cde006
LS
10204 struct bgp_path_info *bpi_ultimate =
10205 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10206
10207 if (json_paths) {
10208 json_path = json_object_new_object();
10209 json_peer = json_object_new_object();
10210 json_nexthop_global = json_object_new_object();
10211 }
10212
8304dabf
AD
10213 if (safi == SAFI_EVPN) {
10214 if (!json_paths)
34c7f35f 10215 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10216 }
10217
44c69747 10218 if (path->extra) {
9b6d8fcf
DS
10219 if (path->extra && path->extra->num_labels) {
10220 bgp_evpn_label2str(path->extra->label,
10221 path->extra->num_labels, tag_buf,
a4d82a8a 10222 sizeof(tag_buf));
d62a17ae 10223 }
d7325ee7 10224 if (safi == SAFI_EVPN) {
44c69747 10225 if (!json_paths) {
44c69747
LK
10226 if (tag_buf[0] != '\0')
10227 vty_out(vty, " VNI %s", tag_buf);
44c69747 10228 } else {
1ce23106 10229 if (tag_buf[0])
77a2f8e5
DA
10230 json_object_string_add(json_path, "vni",
10231 tag_buf);
44c69747 10232 }
d7325ee7 10233 }
d62a17ae 10234 }
d62a17ae 10235
8304dabf
AD
10236 if (safi == SAFI_EVPN
10237 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10238 char gwip_buf[INET6_ADDRSTRLEN];
10239
860e740b
IR
10240 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10241 sizeof(gwip_buf));
8304dabf
AD
10242
10243 if (json_paths)
10244 json_object_string_add(json_path, "gatewayIP",
10245 gwip_buf);
10246 else
10247 vty_out(vty, " Gateway IP %s", gwip_buf);
10248 }
10249
2bf9780b 10250 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10251 vty_out(vty, "\n");
10252
100290e4
SW
10253
10254 if (path->extra && path->extra->parent && !json_paths) {
10255 struct bgp_path_info *parent_ri;
10256 struct bgp_dest *dest, *pdest;
10257
10258 parent_ri = (struct bgp_path_info *)path->extra->parent;
10259 dest = parent_ri->net;
10260 if (dest && dest->pdest) {
10261 pdest = dest->pdest;
10262 if (is_pi_family_evpn(parent_ri)) {
4a8cd6ad
PG
10263 vty_out(vty, " Imported from ");
10264 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10265 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10266 pdest));
10267 vty_out(vty, ":%pFX, VNI %s",
100290e4
SW
10268 (struct prefix_evpn *)
10269 bgp_dest_get_prefix(dest),
10270 tag_buf);
6012963e 10271 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10272 vty_out(vty, ", L3NHG %s",
6012963e
SW
10273 CHECK_FLAG(
10274 attr->es_flags,
10275 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10276 ? "active"
10277 : "inactive");
10278 vty_out(vty, "\n");
10279
4a8cd6ad
PG
10280 } else {
10281 vty_out(vty, " Imported from ");
10282 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
100290e4 10283 (struct prefix_rd *)bgp_dest_get_prefix(
4a8cd6ad
PG
10284 pdest));
10285 vty_out(vty, ":%pFX\n",
100290e4
SW
10286 (struct prefix_evpn *)
10287 bgp_dest_get_prefix(dest));
4a8cd6ad 10288 }
100290e4
SW
10289 }
10290 }
10291
05864da7
DS
10292 /* Line1 display AS-path, Aggregator */
10293 if (attr->aspath) {
10294 if (json_paths) {
10295 if (!attr->aspath->json)
10296 aspath_str_update(attr->aspath, true);
10297 json_object_lock(attr->aspath->json);
10298 json_object_object_add(json_path, "aspath",
10299 attr->aspath->json);
10300 } else {
10301 if (attr->aspath->segments)
e678b143 10302 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10303 else
05864da7 10304 vty_out(vty, " Local");
d62a17ae 10305 }
05864da7 10306 }
d62a17ae 10307
05864da7
DS
10308 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10309 if (json_paths)
10310 json_object_boolean_true_add(json_path, "removed");
10311 else
10312 vty_out(vty, ", (removed)");
10313 }
d62a17ae 10314
05864da7
DS
10315 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10316 if (json_paths)
10317 json_object_boolean_true_add(json_path, "stale");
10318 else
10319 vty_out(vty, ", (stale)");
10320 }
d62a17ae 10321
05864da7
DS
10322 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10323 if (json_paths) {
10324 json_object_int_add(json_path, "aggregatorAs",
10325 attr->aggregator_as);
c949c771
DA
10326 json_object_string_addf(json_path, "aggregatorId",
10327 "%pI4", &attr->aggregator_addr);
05864da7 10328 } else {
88d495a9
DA
10329 vty_out(vty, ", (aggregated by %u %pI4)",
10330 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10331 }
05864da7 10332 }
d62a17ae 10333
05864da7
DS
10334 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10335 PEER_FLAG_REFLECTOR_CLIENT)) {
10336 if (json_paths)
10337 json_object_boolean_true_add(json_path,
10338 "rxedFromRrClient");
10339 else
10340 vty_out(vty, ", (Received from a RR-client)");
10341 }
d62a17ae 10342
05864da7
DS
10343 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10344 PEER_FLAG_RSERVER_CLIENT)) {
10345 if (json_paths)
10346 json_object_boolean_true_add(json_path,
10347 "rxedFromRsClient");
10348 else
10349 vty_out(vty, ", (Received from a RS-client)");
10350 }
d62a17ae 10351
05864da7
DS
10352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10353 if (json_paths)
10354 json_object_boolean_true_add(json_path,
10355 "dampeningHistoryEntry");
10356 else
10357 vty_out(vty, ", (history entry)");
10358 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path,
10361 "dampeningSuppressed");
10362 else
10363 vty_out(vty, ", (suppressed due to dampening)");
10364 }
d62a17ae 10365
05864da7
DS
10366 if (!json_paths)
10367 vty_out(vty, "\n");
d62a17ae 10368
05864da7
DS
10369 /* Line2 display Next-hop, Neighbor, Router-id */
10370 /* Display the nexthop */
b54892e0 10371
34c7f35f
SW
10372 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10373 p->family == AF_EVPN) &&
7226bc40
TA
10374 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10375 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10376 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10377 || safi == SAFI_EVPN) {
515c2602 10378 if (json_paths) {
c949c771
DA
10379 json_object_string_addf(
10380 json_nexthop_global, "ip", "%pI4",
10381 &attr->mp_nexthop_global_in);
515c2602 10382
939a97f4 10383 if (path->peer->hostname)
515c2602
DA
10384 json_object_string_add(
10385 json_nexthop_global, "hostname",
939a97f4 10386 path->peer->hostname);
aef999a2
DA
10387 } else {
10388 if (nexthop_hostname)
10389 vty_out(vty, " %pI4(%s)",
10390 &attr->mp_nexthop_global_in,
10391 nexthop_hostname);
10392 else
10393 vty_out(vty, " %pI4",
10394 &attr->mp_nexthop_global_in);
10395 }
d62a17ae 10396 } else {
515c2602 10397 if (json_paths) {
c949c771
DA
10398 json_object_string_addf(json_nexthop_global,
10399 "ip", "%pI4",
10400 &attr->nexthop);
515c2602 10401
939a97f4 10402 if (path->peer->hostname)
515c2602
DA
10403 json_object_string_add(
10404 json_nexthop_global, "hostname",
939a97f4 10405 path->peer->hostname);
aef999a2
DA
10406 } else {
10407 if (nexthop_hostname)
10408 vty_out(vty, " %pI4(%s)",
10409 &attr->nexthop,
10410 nexthop_hostname);
10411 else
10412 vty_out(vty, " %pI4",
10413 &attr->nexthop);
10414 }
d62a17ae 10415 }
10416
05864da7
DS
10417 if (json_paths)
10418 json_object_string_add(json_nexthop_global, "afi",
10419 "ipv4");
10420 } else {
10421 if (json_paths) {
c949c771
DA
10422 json_object_string_addf(json_nexthop_global, "ip",
10423 "%pI6",
10424 &attr->mp_nexthop_global);
515c2602 10425
939a97f4 10426 if (path->peer->hostname)
515c2602
DA
10427 json_object_string_add(json_nexthop_global,
10428 "hostname",
939a97f4 10429 path->peer->hostname);
515c2602 10430
05864da7
DS
10431 json_object_string_add(json_nexthop_global, "afi",
10432 "ipv6");
10433 json_object_string_add(json_nexthop_global, "scope",
10434 "global");
10435 } else {
aef999a2
DA
10436 if (nexthop_hostname)
10437 vty_out(vty, " %pI6(%s)",
10438 &attr->mp_nexthop_global,
10439 nexthop_hostname);
10440 else
10441 vty_out(vty, " %pI6",
10442 &attr->mp_nexthop_global);
d62a17ae 10443 }
05864da7 10444 }
d62a17ae 10445
05864da7 10446 /* Display the IGP cost or 'inaccessible' */
f0cde006 10447 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10448 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10449
10450 if (json_paths) {
05864da7
DS
10451 json_object_boolean_false_add(json_nexthop_global,
10452 "accessible");
95ba22d5
DA
10453 json_object_boolean_add(json_nexthop_global,
10454 "importCheckEnabled", import);
10455 } else {
10456 vty_out(vty, " (inaccessible%s)",
10457 import ? ", import-check enabled" : "");
10458 }
05864da7 10459 } else {
f0cde006 10460 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10461 if (json_paths)
f0cde006
LS
10462 json_object_int_add(
10463 json_nexthop_global, "metric",
10464 bpi_ultimate->extra->igpmetric);
d62a17ae 10465 else
05864da7 10466 vty_out(vty, " (metric %u)",
f0cde006 10467 bpi_ultimate->extra->igpmetric);
d62a17ae 10468 }
10469
05864da7 10470 /* IGP cost is 0, display this only for json */
d62a17ae 10471 else {
d62a17ae 10472 if (json_paths)
05864da7
DS
10473 json_object_int_add(json_nexthop_global,
10474 "metric", 0);
d62a17ae 10475 }
d62a17ae 10476
05864da7
DS
10477 if (json_paths)
10478 json_object_boolean_true_add(json_nexthop_global,
10479 "accessible");
10480 }
d62a17ae 10481
05864da7
DS
10482 /* Display peer "from" output */
10483 /* This path was originated locally */
10484 if (path->peer == bgp->peer_self) {
d62a17ae 10485
34c7f35f 10486 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10487 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10488 if (json_paths)
05864da7
DS
10489 json_object_string_add(json_peer, "peerId",
10490 "0.0.0.0");
d62a17ae 10491 else
05864da7
DS
10492 vty_out(vty, " from 0.0.0.0 ");
10493 } else {
d62a17ae 10494 if (json_paths)
05864da7
DS
10495 json_object_string_add(json_peer, "peerId",
10496 "::");
d62a17ae 10497 else
05864da7 10498 vty_out(vty, " from :: ");
d62a17ae 10499 }
d62a17ae 10500
4e9a9863 10501 if (json_paths)
c949c771
DA
10502 json_object_string_addf(json_peer, "routerId", "%pI4",
10503 &bgp->router_id);
4e9a9863 10504 else
23d0a753 10505 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10506 }
d62a17ae 10507
05864da7
DS
10508 /* We RXed this path from one of our peers */
10509 else {
10510
10511 if (json_paths) {
47e12884
DA
10512 json_object_string_addf(json_peer, "peerId", "%pSU",
10513 &path->peer->su);
c949c771
DA
10514 json_object_string_addf(json_peer, "routerId", "%pI4",
10515 &path->peer->remote_id);
05864da7
DS
10516
10517 if (path->peer->hostname)
10518 json_object_string_add(json_peer, "hostname",
10519 path->peer->hostname);
10520
10521 if (path->peer->domainname)
10522 json_object_string_add(json_peer, "domainname",
10523 path->peer->domainname);
10524
10525 if (path->peer->conf_if)
10526 json_object_string_add(json_peer, "interface",
10527 path->peer->conf_if);
10528 } else {
10529 if (path->peer->conf_if) {
10530 if (path->peer->hostname
892fedb6
DA
10531 && CHECK_FLAG(path->peer->bgp->flags,
10532 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10533 vty_out(vty, " from %s(%s)",
10534 path->peer->hostname,
10535 path->peer->conf_if);
d62a17ae 10536 else
05864da7 10537 vty_out(vty, " from %s",
9b6d8fcf 10538 path->peer->conf_if);
d62a17ae 10539 } else {
05864da7 10540 if (path->peer->hostname
892fedb6
DA
10541 && CHECK_FLAG(path->peer->bgp->flags,
10542 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10543 vty_out(vty, " from %s(%s)",
10544 path->peer->hostname,
10545 path->peer->host);
d62a17ae 10546 else
47e12884
DA
10547 vty_out(vty, " from %pSU",
10548 &path->peer->su);
d62a17ae 10549 }
d62a17ae 10550
05864da7 10551 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10552 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10553 else
07380148 10554 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10555 }
05864da7 10556 }
9df8b37c 10557
05864da7
DS
10558 /*
10559 * Note when vrfid of nexthop is different from that of prefix
10560 */
10561 if (path->extra && path->extra->bgp_orig) {
10562 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10563
05864da7
DS
10564 if (json_paths) {
10565 const char *vn;
9df8b37c 10566
05864da7
DS
10567 if (path->extra->bgp_orig->inst_type
10568 == BGP_INSTANCE_TYPE_DEFAULT)
10569 vn = VRF_DEFAULT_NAME;
10570 else
10571 vn = path->extra->bgp_orig->name;
9df8b37c 10572
05864da7 10573 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10574
05864da7
DS
10575 if (nexthop_vrfid == VRF_UNKNOWN) {
10576 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10577 } else {
05864da7
DS
10578 json_object_int_add(json_path, "nhVrfId",
10579 (int)nexthop_vrfid);
9df8b37c 10580 }
05864da7
DS
10581 } else {
10582 if (nexthop_vrfid == VRF_UNKNOWN)
10583 vty_out(vty, " vrf ?");
137147c6
DS
10584 else {
10585 struct vrf *vrf;
10586
10587 vrf = vrf_lookup_by_id(nexthop_vrfid);
10588 vty_out(vty, " vrf %s(%u)",
10589 VRF_LOGNAME(vrf), nexthop_vrfid);
10590 }
9df8b37c 10591 }
05864da7 10592 }
9df8b37c 10593
05864da7
DS
10594 if (nexthop_self) {
10595 if (json_paths) {
10596 json_object_boolean_true_add(json_path,
10597 "announceNexthopSelf");
10598 } else {
10599 vty_out(vty, " announce-nh-self");
9df8b37c 10600 }
05864da7 10601 }
9df8b37c 10602
05864da7
DS
10603 if (!json_paths)
10604 vty_out(vty, "\n");
d62a17ae 10605
05864da7
DS
10606 /* display the link-local nexthop */
10607 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10608 if (json_paths) {
10609 json_nexthop_ll = json_object_new_object();
c949c771
DA
10610 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10611 &attr->mp_nexthop_local);
515c2602 10612
939a97f4 10613 if (path->peer->hostname)
515c2602
DA
10614 json_object_string_add(json_nexthop_ll,
10615 "hostname",
939a97f4 10616 path->peer->hostname);
515c2602 10617
05864da7
DS
10618 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10619 json_object_string_add(json_nexthop_ll, "scope",
10620 "link-local");
d62a17ae 10621
05864da7
DS
10622 json_object_boolean_true_add(json_nexthop_ll,
10623 "accessible");
d62a17ae 10624
2bb8b49c 10625 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10626 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10627 "used");
10628 else
10629 json_object_boolean_true_add(
10630 json_nexthop_global, "used");
10631 } else {
10632 vty_out(vty, " (%s) %s\n",
10633 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10634 buf, INET6_ADDRSTRLEN),
2bb8b49c 10635 attr->mp_nexthop_prefer_global
05864da7
DS
10636 ? "(prefer-global)"
10637 : "(used)");
d62a17ae 10638 }
05864da7
DS
10639 }
10640 /* If we do not have a link-local nexthop then we must flag the
10641 global as "used" */
10642 else {
10643 if (json_paths)
10644 json_object_boolean_true_add(json_nexthop_global,
10645 "used");
10646 }
d62a17ae 10647
b5e140c8 10648 if (safi == SAFI_EVPN &&
5e4d4c8a 10649 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10650 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10651 }
10652
05864da7
DS
10653 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10654 * Int/Ext/Local, Atomic, best */
10655 if (json_paths)
10656 json_object_string_add(json_path, "origin",
10657 bgp_origin_long_str[attr->origin]);
10658 else
10659 vty_out(vty, " Origin %s",
10660 bgp_origin_long_str[attr->origin]);
9df8b37c 10661
05864da7 10662 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10663 if (json_paths)
05864da7 10664 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10665 else
05864da7
DS
10666 vty_out(vty, ", metric %u", attr->med);
10667 }
9df8b37c 10668
05864da7
DS
10669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10670 if (json_paths)
0fbac0b4 10671 json_object_int_add(json_path, "locPrf",
05864da7
DS
10672 attr->local_pref);
10673 else
10674 vty_out(vty, ", localpref %u", attr->local_pref);
10675 }
9df8b37c 10676
97a52c82
DA
10677 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10678 if (json_paths)
10679 json_object_int_add(json_path, "aigpMetric",
10680 bgp_attr_get_aigp_metric(attr));
10681 else
10682 vty_out(vty, ", aigp-metric %" PRIu64,
10683 bgp_attr_get_aigp_metric(attr));
10684 }
10685
05864da7
DS
10686 if (attr->weight != 0) {
10687 if (json_paths)
10688 json_object_int_add(json_path, "weight", attr->weight);
10689 else
10690 vty_out(vty, ", weight %u", attr->weight);
10691 }
9df8b37c 10692
05864da7
DS
10693 if (attr->tag != 0) {
10694 if (json_paths)
10695 json_object_int_add(json_path, "tag", attr->tag);
10696 else
10697 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10698 }
9df8b37c 10699
05864da7
DS
10700 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10701 if (json_paths)
10702 json_object_boolean_false_add(json_path, "valid");
10703 else
10704 vty_out(vty, ", invalid");
10705 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10706 if (json_paths)
10707 json_object_boolean_true_add(json_path, "valid");
10708 else
10709 vty_out(vty, ", valid");
10710 }
9df8b37c 10711
7d3cae70
DA
10712 if (json_paths)
10713 json_object_int_add(json_path, "version", bn->version);
10714
05864da7
DS
10715 if (path->peer != bgp->peer_self) {
10716 if (path->peer->as == path->peer->local_as) {
10717 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10718 if (json_paths)
10719 json_object_string_add(
10720 json_peer, "type",
10721 "confed-internal");
d62a17ae 10722 else
05864da7 10723 vty_out(vty, ", confed-internal");
d62a17ae 10724 } else {
05864da7
DS
10725 if (json_paths)
10726 json_object_string_add(
10727 json_peer, "type", "internal");
10728 else
10729 vty_out(vty, ", internal");
9df8b37c 10730 }
05864da7
DS
10731 } else {
10732 if (bgp_confederation_peers_check(bgp,
10733 path->peer->as)) {
10734 if (json_paths)
10735 json_object_string_add(
10736 json_peer, "type",
10737 "confed-external");
d62a17ae 10738 else
05864da7 10739 vty_out(vty, ", confed-external");
d62a17ae 10740 } else {
05864da7
DS
10741 if (json_paths)
10742 json_object_string_add(
10743 json_peer, "type", "external");
10744 else
10745 vty_out(vty, ", external");
d62a17ae 10746 }
10747 }
05864da7
DS
10748 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10749 if (json_paths) {
10750 json_object_boolean_true_add(json_path, "aggregated");
10751 json_object_boolean_true_add(json_path, "local");
10752 } else {
10753 vty_out(vty, ", aggregated, local");
10754 }
10755 } else if (path->type != ZEBRA_ROUTE_BGP) {
10756 if (json_paths)
10757 json_object_boolean_true_add(json_path, "sourced");
10758 else
10759 vty_out(vty, ", sourced");
10760 } else {
10761 if (json_paths) {
10762 json_object_boolean_true_add(json_path, "sourced");
10763 json_object_boolean_true_add(json_path, "local");
10764 } else {
10765 vty_out(vty, ", sourced, local");
d62a17ae 10766 }
05864da7 10767 }
718e3744 10768
05864da7 10769 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10770 if (json_paths)
05864da7
DS
10771 json_object_boolean_true_add(json_path,
10772 "atomicAggregate");
d62a17ae 10773 else
05864da7
DS
10774 vty_out(vty, ", atomic-aggregate");
10775 }
d62a17ae 10776
d864dd9e
EB
10777 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10778 if (json_paths)
10779 json_object_int_add(json_path, "otc", attr->otc);
10780 else
10781 vty_out(vty, ", otc %u", attr->otc);
10782 }
10783
05864da7
DS
10784 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10785 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10786 && bgp_path_info_mpath_count(path))) {
10787 if (json_paths)
10788 json_object_boolean_true_add(json_path, "multipath");
10789 else
10790 vty_out(vty, ", multipath");
10791 }
50e05855 10792
05864da7
DS
10793 // Mark the bestpath(s)
10794 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10795 first_as = aspath_get_first_as(attr->aspath);
718e3744 10796
05864da7
DS
10797 if (json_paths) {
10798 if (!json_bestpath)
10799 json_bestpath = json_object_new_object();
10800 json_object_int_add(json_bestpath, "bestpathFromAs",
10801 first_as);
10802 } else {
10803 if (first_as)
10804 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10805 else
05864da7 10806 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10807 }
05864da7 10808 }
718e3744 10809
05864da7
DS
10810 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10811 if (json_paths) {
10812 if (!json_bestpath)
10813 json_bestpath = json_object_new_object();
10814 json_object_boolean_true_add(json_bestpath, "overall");
10815 json_object_string_add(
10816 json_bestpath, "selectionReason",
10817 bgp_path_selection_reason2str(bn->reason));
10818 } else {
10819 vty_out(vty, ", best");
10820 vty_out(vty, " (%s)",
10821 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10822 }
05864da7 10823 }
718e3744 10824
4027d19b 10825 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10826 if (json_paths)
10827 json_object_string_add(
10828 json_path, "rpkiValidationState",
4027d19b 10829 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10830 else
1d327209 10831 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10832 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10833 }
10834
05864da7
DS
10835 if (json_bestpath)
10836 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10837
05864da7
DS
10838 if (!json_paths)
10839 vty_out(vty, "\n");
10840
10841 /* Line 4 display Community */
29e72930 10842 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10843 if (json_paths) {
9a706b42
DA
10844 if (!bgp_attr_get_community(attr)->json)
10845 community_str(bgp_attr_get_community(attr),
c0945b78 10846 true, true);
9a706b42
DA
10847 json_object_lock(bgp_attr_get_community(attr)->json);
10848 json_object_object_add(
10849 json_path, "community",
10850 bgp_attr_get_community(attr)->json);
05864da7
DS
10851 } else {
10852 vty_out(vty, " Community: %s\n",
9a706b42 10853 bgp_attr_get_community(attr)->str);
d62a17ae 10854 }
05864da7 10855 }
718e3744 10856
05864da7
DS
10857 /* Line 5 display Extended-community */
10858 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10859 if (json_paths) {
10860 json_ext_community = json_object_new_object();
b53e67a3
DA
10861 json_object_string_add(
10862 json_ext_community, "string",
10863 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10864 json_object_object_add(json_path, "extendedCommunity",
10865 json_ext_community);
d62a17ae 10866 } else {
05864da7 10867 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10868 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10869 }
05864da7 10870 }
718e3744 10871
05864da7
DS
10872 /* Line 6 display Large community */
10873 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10874 if (json_paths) {
1bcf3a96
DA
10875 if (!bgp_attr_get_lcommunity(attr)->json)
10876 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10877 true, true);
1bcf3a96
DA
10878 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10879 json_object_object_add(
10880 json_path, "largeCommunity",
10881 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10882 } else {
10883 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10884 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10885 }
05864da7 10886 }
718e3744 10887
05864da7
DS
10888 /* Line 7 display Originator, Cluster-id */
10889 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10890 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10891 char buf[BUFSIZ] = {0};
10892
05864da7 10893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10894 if (json_paths)
c949c771
DA
10895 json_object_string_addf(json_path,
10896 "originatorId", "%pI4",
10897 &attr->originator_id);
d62a17ae 10898 else
23d0a753
DA
10899 vty_out(vty, " Originator: %pI4",
10900 &attr->originator_id);
d62a17ae 10901 }
856ca177 10902
05864da7 10903 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10904 struct cluster_list *cluster =
10905 bgp_attr_get_cluster(attr);
05864da7 10906 int i;
d62a17ae 10907
10908 if (json_paths) {
05864da7
DS
10909 json_cluster_list = json_object_new_object();
10910 json_cluster_list_list =
10911 json_object_new_array();
10912
779fee93 10913 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10914 json_string = json_object_new_string(
779fee93
DS
10915 inet_ntop(AF_INET,
10916 &cluster->list[i],
10917 buf, sizeof(buf)));
05864da7
DS
10918 json_object_array_add(
10919 json_cluster_list_list,
10920 json_string);
10921 }
718e3744 10922
05864da7
DS
10923 /*
10924 * struct cluster_list does not have
10925 * "str" variable like aspath and community
10926 * do. Add this someday if someone asks
10927 * for it.
10928 * json_object_string_add(json_cluster_list,
779fee93 10929 * "string", cluster->str);
05864da7
DS
10930 */
10931 json_object_object_add(json_cluster_list,
10932 "list",
10933 json_cluster_list_list);
10934 json_object_object_add(json_path, "clusterList",
10935 json_cluster_list);
0dc8ee70 10936 } else {
05864da7
DS
10937 vty_out(vty, ", Cluster list: ");
10938
779fee93 10939 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10940 vty_out(vty, "%pI4 ",
779fee93 10941 &cluster->list[i]);
05864da7 10942 }
0dc8ee70 10943 }
d62a17ae 10944 }
718e3744 10945
d62a17ae 10946 if (!json_paths)
10947 vty_out(vty, "\n");
05864da7 10948 }
d62a17ae 10949
05864da7 10950 if (path->extra && path->extra->damp_info)
b4f7f45b 10951 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10952
05864da7
DS
10953 /* Remote Label */
10954 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10955 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10956 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10957 &bos);
d62a17ae 10958
05864da7
DS
10959 if (json_paths)
10960 json_object_int_add(json_path, "remoteLabel", label);
10961 else
10962 vty_out(vty, " Remote label: %d\n", label);
10963 }
d62a17ae 10964
e496b420
HS
10965 /* Remote SID */
10966 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10967 if (json_paths)
07380148
DA
10968 json_object_string_addf(json_path, "remoteSid", "%pI6",
10969 &path->extra->sid[0].sid);
e496b420 10970 else
07380148
DA
10971 vty_out(vty, " Remote SID: %pI6\n",
10972 &path->extra->sid[0].sid);
e496b420
HS
10973 }
10974
05864da7
DS
10975 /* Label Index */
10976 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10977 if (json_paths)
10978 json_object_int_add(json_path, "labelIndex",
10979 attr->label_index);
10980 else
10981 vty_out(vty, " Label Index: %d\n",
10982 attr->label_index);
10983 }
d62a17ae 10984
05864da7
DS
10985 /* Line 8 display Addpath IDs */
10986 if (path->addpath_rx_id
10987 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10988 if (json_paths) {
10989 json_object_int_add(json_path, "addpathRxId",
10990 path->addpath_rx_id);
d62a17ae 10991
05864da7
DS
10992 /* Keep backwards compatibility with the old API
10993 * by putting TX All's ID in the old field
10994 */
10995 json_object_int_add(
10996 json_path, "addpathTxId",
10997 path->tx_addpath
10998 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10999
05864da7
DS
11000 /* ... but create a specific field for each
11001 * strategy
11002 */
11003 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11004 json_object_int_add(
11005 json_path,
11006 bgp_addpath_names(i)->id_json_name,
11007 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11008 }
05864da7
DS
11009 } else {
11010 vty_out(vty, " AddPath ID: RX %u, ",
11011 path->addpath_rx_id);
d62a17ae 11012
05864da7 11013 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11014 }
05864da7 11015 }
520d5d76 11016
05864da7
DS
11017 /* If we used addpath to TX a non-bestpath we need to display
11018 * "Advertised to" on a path-by-path basis
11019 */
11020 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11021 first = 1;
dcc68b5e 11022
05864da7
DS
11023 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11024 addpath_capable =
11025 bgp_addpath_encode_tx(peer, afi, safi);
11026 has_adj = bgp_adj_out_lookup(
11027 peer, path->net,
11028 bgp_addpath_id_for_peer(peer, afi, safi,
11029 &path->tx_addpath));
11030
11031 if ((addpath_capable && has_adj)
11032 || (!addpath_capable && has_adj
11033 && CHECK_FLAG(path->flags,
11034 BGP_PATH_SELECTED))) {
11035 if (json_path && !json_adv_to)
11036 json_adv_to = json_object_new_object();
dcc68b5e 11037
05864da7
DS
11038 route_vty_out_advertised_to(
11039 vty, peer, &first,
11040 " Advertised to:", json_adv_to);
d62a17ae 11041 }
11042 }
718e3744 11043
05864da7
DS
11044 if (json_path) {
11045 if (json_adv_to) {
11046 json_object_object_add(
11047 json_path, "advertisedTo", json_adv_to);
d62a17ae 11048 }
05864da7
DS
11049 } else {
11050 if (!first) {
11051 vty_out(vty, "\n");
d62a17ae 11052 }
11053 }
05864da7 11054 }
b05a1c8b 11055
05864da7 11056 /* Line 9 display Uptime */
083ec940 11057 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11058 if (json_paths) {
11059 json_last_update = json_object_new_object();
11060 json_object_int_add(json_last_update, "epoch", tbuf);
11061 json_object_string_add(json_last_update, "string",
11062 ctime(&tbuf));
11063 json_object_object_add(json_path, "lastUpdate",
11064 json_last_update);
11065 } else
11066 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11067
05864da7
DS
11068 /* Line 10 display PMSI tunnel attribute, if present */
11069 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11070 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11071 bgp_attr_get_pmsi_tnl_type(attr),
11072 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11073
05864da7
DS
11074 if (json_paths) {
11075 json_pmsi = json_object_new_object();
11076 json_object_string_add(json_pmsi, "tunnelType", str);
11077 json_object_int_add(json_pmsi, "label",
11078 label2vni(&attr->label));
11079 json_object_object_add(json_path, "pmsi", json_pmsi);
11080 } else
11081 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11082 str, label2vni(&attr->label));
d62a17ae 11083 }
f1aa5d8a 11084
848e8cf6
DA
11085 if (path->peer->t_gr_restart &&
11086 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11087 unsigned long gr_remaining =
11088 thread_timer_remain_second(path->peer->t_gr_restart);
11089
11090 if (json_paths) {
11091 json_object_int_add(json_path,
11092 "gracefulRestartSecondsRemaining",
11093 gr_remaining);
11094 } else
11095 vty_out(vty,
11096 " Time until Graceful Restart stale route deleted: %lu\n",
11097 gr_remaining);
11098 }
11099
9a706b42
DA
11100 if (path->peer->t_llgr_stale[afi][safi] &&
11101 bgp_attr_get_community(attr) &&
11102 community_include(bgp_attr_get_community(attr),
11103 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11104 unsigned long llgr_remaining = thread_timer_remain_second(
11105 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11106
48ebba04
DA
11107 if (json_paths) {
11108 json_object_int_add(json_path, "llgrSecondsRemaining",
11109 llgr_remaining);
11110 } else
11111 vty_out(vty,
11112 " Time until Long-lived stale route deleted: %lu\n",
11113 llgr_remaining);
11114 }
11115
92269aa2
DS
11116 /* Output some debug about internal state of the dest flags */
11117 if (json_paths) {
11118 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11119 json_object_boolean_true_add(json_path, "processScheduled");
11120 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11121 json_object_boolean_true_add(json_path, "userCleared");
11122 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11123 json_object_boolean_true_add(json_path, "labelChanged");
11124 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11125 json_object_boolean_true_add(json_path, "registeredForLabel");
11126 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11127 json_object_boolean_true_add(json_path, "selectDefered");
11128 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11129 json_object_boolean_true_add(json_path, "fibInstalled");
11130 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11131 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11132
d62a17ae 11133 if (json_nexthop_global || json_nexthop_ll) {
11134 json_nexthops = json_object_new_array();
f1aa5d8a 11135
d62a17ae 11136 if (json_nexthop_global)
11137 json_object_array_add(json_nexthops,
11138 json_nexthop_global);
f1aa5d8a 11139
d62a17ae 11140 if (json_nexthop_ll)
11141 json_object_array_add(json_nexthops,
11142 json_nexthop_ll);
f1aa5d8a 11143
d62a17ae 11144 json_object_object_add(json_path, "nexthops",
11145 json_nexthops);
11146 }
11147
11148 json_object_object_add(json_path, "peer", json_peer);
11149 json_object_array_add(json_paths, json_path);
05864da7 11150 }
b366b518
BB
11151}
11152
96ade3ed 11153#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11154#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11155#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11156
a4d82a8a 11157static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11158 afi_t afi, safi_t safi, enum bgp_show_type type,
11159 bool use_json);
7f323236
DW
11160static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11161 const char *comstr, int exact, afi_t afi,
96c81f66 11162 safi_t safi, uint16_t show_flags);
d62a17ae 11163
1ae44dfc 11164static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11165 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11166 void *output_arg, const char *rd, int is_last,
96f3485c 11167 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11168 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11169 enum rpki_states rpki_target_state)
d62a17ae 11170{
40381db7 11171 struct bgp_path_info *pi;
9bcb3eef 11172 struct bgp_dest *dest;
2aad8c42
MS
11173 bool header = true;
11174 bool json_detail_header = false;
d62a17ae 11175 int display;
1ae44dfc
LB
11176 unsigned long output_count = 0;
11177 unsigned long total_count = 0;
d62a17ae 11178 struct prefix *p;
d62a17ae 11179 json_object *json_paths = NULL;
11180 int first = 1;
96f3485c
MK
11181 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11182 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11183 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11184 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11185 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11186
1ae44dfc 11187 if (output_cum && *output_cum != 0)
2aad8c42 11188 header = false;
1ae44dfc 11189
9386b588 11190 if (use_json && !*json_header_depth) {
96f3485c
MK
11191 if (all)
11192 *json_header_depth = 1;
11193 else {
11194 vty_out(vty, "{\n");
11195 *json_header_depth = 2;
11196 }
d62a17ae 11197 vty_out(vty,
23d0a753
DA
11198 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11199 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11200 " \"localAS\": ",
a8bf7d9c 11201 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11202 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11203 ? VRF_DEFAULT_NAME
11204 : bgp->name,
11205 table->version, &bgp->router_id,
e84c7c12
PG
11206 bgp->default_local_pref);
11207 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11208 ((bgp->asnotation == ASNOTATION_DOT) &&
11209 (bgp->as < UINT16_MAX)))
11210 vty_out(vty, "%u", bgp->as);
11211 else {
11212 vty_out(vty, "\"");
11213 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11214 vty_out(vty, "\"");
11215 }
11216 vty_out(vty, ",\n \"routes\": { ");
9386b588 11217 if (rd) {
445c2480 11218 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11219 ++*json_header_depth;
11220 }
d62a17ae 11221 }
718e3744 11222
445c2480
DS
11223 if (use_json && rd) {
11224 vty_out(vty, " \"%s\" : { ", rd);
11225 }
11226
2aad8c42 11227 /* Check for 'json detail', where we need header output once per dest */
67799a48 11228 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11229 type != bgp_show_type_damp_neighbor &&
11230 type != bgp_show_type_flap_statistics &&
11231 type != bgp_show_type_flap_neighbor)
11232 json_detail_header = true;
11233
d62a17ae 11234 /* Start processing of routes. */
9bcb3eef
DS
11235 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11236 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11237 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11238 bool json_detail = json_detail_header;
b54892e0 11239
9bcb3eef 11240 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11241 if (pi == NULL)
98ce9a06 11242 continue;
d62a17ae 11243
98ce9a06 11244 display = 0;
98ce9a06
DS
11245 if (use_json)
11246 json_paths = json_object_new_array();
11247 else
11248 json_paths = NULL;
d62a17ae 11249
6f94b685 11250 for (; pi; pi = pi->next) {
9a706b42
DA
11251 struct community *picomm = NULL;
11252
11253 picomm = bgp_attr_get_community(pi->attr);
11254
98ce9a06 11255 total_count++;
1e2ce4f1 11256
7d3cae70
DA
11257 if (type == bgp_show_type_prefix_version) {
11258 uint32_t version =
11259 strtoul(output_arg, NULL, 10);
11260 if (dest->version < version)
11261 continue;
11262 }
11263
a70a28a5
DA
11264 if (type == bgp_show_type_community_alias) {
11265 char *alias = output_arg;
11266 char **communities;
11267 int num;
11268 bool found = false;
11269
9a706b42
DA
11270 if (picomm) {
11271 frrstr_split(picomm->str, " ",
11272 &communities, &num);
a70a28a5
DA
11273 for (int i = 0; i < num; i++) {
11274 const char *com2alias =
11275 bgp_community2alias(
11276 communities[i]);
cd9cc0e6
IR
11277 if (!found
11278 && strcmp(alias, com2alias)
11279 == 0)
a70a28a5 11280 found = true;
cd9cc0e6
IR
11281 XFREE(MTYPE_TMP,
11282 communities[i]);
a70a28a5 11283 }
cd9cc0e6 11284 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11285 }
11286
1bcf3a96
DA
11287 if (!found &&
11288 bgp_attr_get_lcommunity(pi->attr)) {
11289 frrstr_split(bgp_attr_get_lcommunity(
11290 pi->attr)
11291 ->str,
a70a28a5
DA
11292 " ", &communities, &num);
11293 for (int i = 0; i < num; i++) {
11294 const char *com2alias =
11295 bgp_community2alias(
11296 communities[i]);
cd9cc0e6
IR
11297 if (!found
11298 && strcmp(alias, com2alias)
11299 == 0)
a70a28a5 11300 found = true;
cd9cc0e6
IR
11301 XFREE(MTYPE_TMP,
11302 communities[i]);
a70a28a5 11303 }
cd9cc0e6 11304 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11305 }
11306
11307 if (!found)
11308 continue;
11309 }
11310
1e2ce4f1
DS
11311 if (type == bgp_show_type_rpki) {
11312 if (dest_p->family == AF_INET
11313 || dest_p->family == AF_INET6)
4027d19b 11314 rpki_curr_state = hook_call(
1e2ce4f1
DS
11315 bgp_rpki_prefix_status,
11316 pi->peer, pi->attr, dest_p);
4027d19b
DS
11317 if (rpki_target_state != RPKI_NOT_BEING_USED
11318 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11319 continue;
11320 }
11321
98ce9a06
DS
11322 if (type == bgp_show_type_flap_statistics
11323 || type == bgp_show_type_flap_neighbor
11324 || type == bgp_show_type_dampend_paths
11325 || type == bgp_show_type_damp_neighbor) {
40381db7 11326 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11327 continue;
11328 }
11329 if (type == bgp_show_type_regexp) {
11330 regex_t *regex = output_arg;
d62a17ae 11331
40381db7 11332 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11333 == REG_NOMATCH)
11334 continue;
11335 }
11336 if (type == bgp_show_type_prefix_list) {
11337 struct prefix_list *plist = output_arg;
d62a17ae 11338
9bcb3eef 11339 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11340 != PREFIX_PERMIT)
11341 continue;
11342 }
ed126382
DA
11343 if (type == bgp_show_type_access_list) {
11344 struct access_list *alist = output_arg;
11345
11346 if (access_list_apply(alist, dest_p) !=
11347 FILTER_PERMIT)
11348 continue;
11349 }
98ce9a06
DS
11350 if (type == bgp_show_type_filter_list) {
11351 struct as_list *as_list = output_arg;
d62a17ae 11352
40381db7 11353 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11354 != AS_FILTER_PERMIT)
11355 continue;
11356 }
11357 if (type == bgp_show_type_route_map) {
11358 struct route_map *rmap = output_arg;
9b6d8fcf 11359 struct bgp_path_info path;
636632c3
DA
11360 struct bgp_path_info_extra extra;
11361 struct attr dummy_attr = {};
b68885f9 11362 route_map_result_t ret;
d62a17ae 11363
6f4f49b2 11364 dummy_attr = *pi->attr;
d62a17ae 11365
636632c3
DA
11366 prep_for_rmap_apply(&path, &extra, dest, pi,
11367 pi->peer, &dummy_attr);
d62a17ae 11368
1782514f 11369 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11370 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11371 if (ret == RMAP_DENYMATCH)
11372 continue;
11373 }
11374 if (type == bgp_show_type_neighbor
11375 || type == bgp_show_type_flap_neighbor
11376 || type == bgp_show_type_damp_neighbor) {
11377 union sockunion *su = output_arg;
11378
40381db7
DS
11379 if (pi->peer == NULL
11380 || pi->peer->su_remote == NULL
11381 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11382 continue;
11383 }
11384 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11385 uint32_t destination;
d62a17ae 11386
9bcb3eef 11387 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11388 if (IN_CLASSC(destination)
9bcb3eef 11389 && dest_p->prefixlen == 24)
98ce9a06
DS
11390 continue;
11391 if (IN_CLASSB(destination)
9bcb3eef 11392 && dest_p->prefixlen == 16)
98ce9a06
DS
11393 continue;
11394 if (IN_CLASSA(destination)
9bcb3eef 11395 && dest_p->prefixlen == 8)
98ce9a06
DS
11396 continue;
11397 }
11398 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11399 p = output_arg;
9bcb3eef 11400 if (!prefix_match(p, dest_p))
98ce9a06
DS
11401 continue;
11402 }
11403 if (type == bgp_show_type_community_all) {
9a706b42 11404 if (!picomm)
98ce9a06
DS
11405 continue;
11406 }
11407 if (type == bgp_show_type_community) {
11408 struct community *com = output_arg;
d62a17ae 11409
9a706b42 11410 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11411 continue;
11412 }
11413 if (type == bgp_show_type_community_exact) {
11414 struct community *com = output_arg;
d62a17ae 11415
9a706b42 11416 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11417 continue;
11418 }
11419 if (type == bgp_show_type_community_list) {
11420 struct community_list *list = output_arg;
d62a17ae 11421
9a706b42 11422 if (!community_list_match(picomm, list))
98ce9a06
DS
11423 continue;
11424 }
a4d82a8a 11425 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11426 struct community_list *list = output_arg;
d62a17ae 11427
9a706b42 11428 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11429 continue;
11430 }
11431 if (type == bgp_show_type_lcommunity) {
11432 struct lcommunity *lcom = output_arg;
d62a17ae 11433
1bcf3a96
DA
11434 if (!bgp_attr_get_lcommunity(pi->attr) ||
11435 !lcommunity_match(
11436 bgp_attr_get_lcommunity(pi->attr),
11437 lcom))
98ce9a06
DS
11438 continue;
11439 }
36a206db 11440
11441 if (type == bgp_show_type_lcommunity_exact) {
11442 struct lcommunity *lcom = output_arg;
11443
1bcf3a96
DA
11444 if (!bgp_attr_get_lcommunity(pi->attr) ||
11445 !lcommunity_cmp(
11446 bgp_attr_get_lcommunity(pi->attr),
11447 lcom))
36a206db 11448 continue;
11449 }
98ce9a06
DS
11450 if (type == bgp_show_type_lcommunity_list) {
11451 struct community_list *list = output_arg;
d62a17ae 11452
1bcf3a96
DA
11453 if (!lcommunity_list_match(
11454 bgp_attr_get_lcommunity(pi->attr),
11455 list))
98ce9a06
DS
11456 continue;
11457 }
36a206db 11458 if (type
11459 == bgp_show_type_lcommunity_list_exact) {
11460 struct community_list *list = output_arg;
11461
11462 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11463 bgp_attr_get_lcommunity(pi->attr),
11464 list))
36a206db 11465 continue;
11466 }
98ce9a06 11467 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11468 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11469 continue;
11470 }
11471 if (type == bgp_show_type_dampend_paths
11472 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11473 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11474 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11475 continue;
11476 }
11477
11478 if (!use_json && header) {
23d0a753
DA
11479 vty_out(vty,
11480 "BGP table version is %" PRIu64
11481 ", local router ID is %pI4, vrf id ",
11482 table->version, &bgp->router_id);
9df8b37c
PZ
11483 if (bgp->vrf_id == VRF_UNKNOWN)
11484 vty_out(vty, "%s", VRFID_NONE_STR);
11485 else
11486 vty_out(vty, "%u", bgp->vrf_id);
11487 vty_out(vty, "\n");
01eced22
AD
11488 vty_out(vty, "Default local pref %u, ",
11489 bgp->default_local_pref);
e84c7c12
PG
11490 vty_out(vty, "local AS ");
11491 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11492 &bgp->as);
11493 vty_out(vty, "\n");
509d82bd 11494 if (!detail_routes) {
9a1aae2d
DA
11495 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11496 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11497 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11498 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11499 }
d62a17ae 11500 if (type == bgp_show_type_dampend_paths
11501 || type == bgp_show_type_damp_neighbor)
98ce9a06 11502 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11503 else if (type == bgp_show_type_flap_statistics
11504 || type == bgp_show_type_flap_neighbor)
98ce9a06 11505 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11506 else if (!detail_routes)
ae248832
MK
11507 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11508 : BGP_SHOW_HEADER));
2aad8c42
MS
11509 header = false;
11510
11511 } else if (json_detail && json_paths != NULL) {
11512 const struct prefix_rd *prd;
11513 json_object *jtemp;
11514
11515 /* Use common detail header, for most types;
11516 * need a json 'object'.
11517 */
11518
11519 jtemp = json_object_new_object();
11520 prd = bgp_rd_from_dest(dest, safi);
11521
11522 route_vty_out_detail_header(
34c7f35f
SW
11523 vty, bgp, dest,
11524 bgp_dest_get_prefix(dest), prd,
11525 table->afi, safi, jtemp);
2aad8c42
MS
11526
11527 json_object_array_add(json_paths, jtemp);
11528
11529 json_detail = false;
d62a17ae 11530 }
2aad8c42 11531
98ce9a06
DS
11532 if (rd != NULL && !display && !output_count) {
11533 if (!use_json)
11534 vty_out(vty,
11535 "Route Distinguisher: %s\n",
11536 rd);
d62a17ae 11537 }
98ce9a06
DS
11538 if (type == bgp_show_type_dampend_paths
11539 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11540 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11541 AFI_IP, safi, use_json,
11542 json_paths);
98ce9a06
DS
11543 else if (type == bgp_show_type_flap_statistics
11544 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11545 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11546 AFI_IP, safi, use_json,
11547 json_paths);
f280c93b 11548 else {
27bb782a
DA
11549 if (detail_routes || detail_json) {
11550 const struct prefix_rd *prd = NULL;
9a1aae2d 11551
27bb782a
DA
11552 if (dest->pdest)
11553 prd = bgp_rd_from_dest(
11554 dest->pdest, safi);
9a1aae2d
DA
11555
11556 if (!use_json)
11557 route_vty_out_detail_header(
11558 vty, bgp, dest,
11559 bgp_dest_get_prefix(
11560 dest),
11561 prd, table->afi, safi,
11562 NULL);
11563
f280c93b 11564 route_vty_out_detail(
27bb782a 11565 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11566 family2afi(dest_p->family),
11567 safi, RPKI_NOT_BEING_USED,
11568 json_paths);
9a1aae2d 11569 } else {
f280c93b
DA
11570 route_vty_out(vty, dest_p, pi, display,
11571 safi, json_paths, wide);
9a1aae2d 11572 }
f280c93b 11573 }
98ce9a06 11574 display++;
d62a17ae 11575 }
11576
98ce9a06
DS
11577 if (display) {
11578 output_count++;
11579 if (!use_json)
11580 continue;
11581
625d2931 11582 /* encode prefix */
9bcb3eef 11583 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11584 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11585
1840384b 11586
b54892e0
DS
11587 bgp_fs_nlri_get_string(
11588 (unsigned char *)
9bcb3eef
DS
11589 dest_p->u.prefix_flowspec.ptr,
11590 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11591 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11592 family2afi(dest_p->u
11593 .prefix_flowspec.family));
625d2931 11594 if (first)
b54892e0 11595 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11596 dest_p->u.prefix_flowspec
b54892e0 11597 .prefixlen);
625d2931 11598 else
b54892e0 11599 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11600 dest_p->u.prefix_flowspec
b54892e0 11601 .prefixlen);
625d2931 11602 } else {
625d2931 11603 if (first)
1b78780b 11604 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11605 else
1b78780b 11606 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11607 }
d7c6467b
DS
11608 /*
11609 * We are using no_pretty here because under
11610 * extremely high settings( say lots and lots of
11611 * routes with lots and lots of ways to reach
11612 * that route via different paths ) this can
11613 * save several minutes of output when FRR
11614 * is run on older cpu's or more underperforming
11615 * routers out there
11616 */
11617 vty_json_no_pretty(vty, json_paths);
449feb8e 11618 json_paths = NULL;
98ce9a06 11619 first = 0;
1f83ed02
DS
11620 } else
11621 json_object_free(json_paths);
98ce9a06
DS
11622 }
11623
1ae44dfc
LB
11624 if (output_cum) {
11625 output_count += *output_cum;
11626 *output_cum = output_count;
11627 }
11628 if (total_cum) {
11629 total_count += *total_cum;
11630 *total_cum = total_count;
11631 }
d62a17ae 11632 if (use_json) {
9386b588 11633 if (rd) {
a4d82a8a 11634 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11635 }
11636 if (is_last) {
a4d82a8a
PZ
11637 unsigned long i;
11638 for (i = 0; i < *json_header_depth; ++i)
11639 vty_out(vty, " } ");
96f3485c
MK
11640 if (!all)
11641 vty_out(vty, "\n");
9386b588 11642 }
d62a17ae 11643 } else {
1ae44dfc
LB
11644 if (is_last) {
11645 /* No route is displayed */
11646 if (output_count == 0) {
11647 if (type == bgp_show_type_normal)
11648 vty_out(vty,
11649 "No BGP prefixes displayed, %ld exist\n",
11650 total_count);
11651 } else
d62a17ae 11652 vty_out(vty,
1ae44dfc
LB
11653 "\nDisplayed %ld routes and %ld total paths\n",
11654 output_count, total_count);
11655 }
d62a17ae 11656 }
718e3744 11657
d62a17ae 11658 return CMD_SUCCESS;
718e3744 11659}
11660
1ae44dfc
LB
11661int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11662 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11663 enum bgp_show_type type, void *output_arg,
11664 uint16_t show_flags)
1ae44dfc 11665{
9bcb3eef 11666 struct bgp_dest *dest, *next;
1ae44dfc
LB
11667 unsigned long output_cum = 0;
11668 unsigned long total_cum = 0;
9386b588 11669 unsigned long json_header_depth = 0;
67009e22 11670 struct bgp_table *itable;
0136788c 11671 bool show_msg;
27bb782a 11672 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11673
11674 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11675
9bcb3eef
DS
11676 for (dest = bgp_table_top(table); dest; dest = next) {
11677 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11678
9bcb3eef
DS
11679 next = bgp_route_next(dest);
11680 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11681 continue;
67009e22 11682
9bcb3eef 11683 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11684 if (itable != NULL) {
1ae44dfc 11685 struct prefix_rd prd;
06b9f471 11686 char rd[RD_ADDRSTRLEN];
1ae44dfc 11687
9bcb3eef 11688 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
4a8cd6ad 11689 prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
67009e22 11690 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11691 rd, next == NULL, &output_cum,
11692 &total_cum, &json_header_depth,
1e2ce4f1 11693 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11694 if (next == NULL)
11695 show_msg = false;
1ae44dfc
LB
11696 }
11697 }
0136788c
LB
11698 if (show_msg) {
11699 if (output_cum == 0)
11700 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11701 total_cum);
11702 else
11703 vty_out(vty,
11704 "\nDisplayed %ld routes and %ld total paths\n",
11705 output_cum, total_cum);
0224b329
DA
11706 } else {
11707 if (use_json && output_cum == 0)
11708 vty_out(vty, "{}\n");
0136788c 11709 }
1ae44dfc
LB
11710 return CMD_SUCCESS;
11711}
2aad8c42 11712
d62a17ae 11713static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11714 enum bgp_show_type type, void *output_arg,
96c81f66 11715 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11716{
d62a17ae 11717 struct bgp_table *table;
9386b588 11718 unsigned long json_header_depth = 0;
96f3485c 11719 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11720
d62a17ae 11721 if (bgp == NULL) {
11722 bgp = bgp_get_default();
11723 }
fee0f4c6 11724
d62a17ae 11725 if (bgp == NULL) {
11726 if (!use_json)
11727 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11728 else
11729 vty_out(vty, "{}\n");
d62a17ae 11730 return CMD_WARNING;
11731 }
4dd6177e 11732
cd8c2a27
MS
11733 /* Labeled-unicast routes live in the unicast table. */
11734 if (safi == SAFI_LABELED_UNICAST)
11735 safi = SAFI_UNICAST;
11736
1ae44dfc 11737 table = bgp->rib[afi][safi];
d62a17ae 11738 /* use MPLS and ENCAP specific shows until they are merged */
11739 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11740 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11741 output_arg, show_flags);
d62a17ae 11742 }
dba3c1d3
PG
11743
11744 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11745 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11746 output_arg, use_json,
11747 1, NULL, NULL);
11748 }
fee0f4c6 11749
0adc5bbb
LS
11750 if (safi == SAFI_EVPN)
11751 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11752
96f3485c 11753 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11754 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11755 rpki_target_state);
fee0f4c6 11756}
11757
d62a17ae 11758static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11759 safi_t safi, uint16_t show_flags)
f186de26 11760{
d62a17ae 11761 struct listnode *node, *nnode;
11762 struct bgp *bgp;
11763 int is_first = 1;
9f049418 11764 bool route_output = false;
96f3485c 11765 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11766
d62a17ae 11767 if (use_json)
11768 vty_out(vty, "{\n");
9f689658 11769
d62a17ae 11770 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11771 route_output = true;
d62a17ae 11772 if (use_json) {
11773 if (!is_first)
11774 vty_out(vty, ",\n");
11775 else
11776 is_first = 0;
11777
11778 vty_out(vty, "\"%s\":",
11779 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11780 ? VRF_DEFAULT_NAME
d62a17ae 11781 : bgp->name);
11782 } else {
11783 vty_out(vty, "\nInstance %s:\n",
11784 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11785 ? VRF_DEFAULT_NAME
d62a17ae 11786 : bgp->name);
11787 }
11788 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11789 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11790 }
9f689658 11791
d62a17ae 11792 if (use_json)
11793 vty_out(vty, "}\n");
9f049418
DS
11794 else if (!route_output)
11795 vty_out(vty, "%% BGP instance not found\n");
f186de26 11796}
11797
718e3744 11798/* Header of detailed BGP route information */
d62a17ae 11799void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11800 struct bgp_dest *dest, const struct prefix *p,
11801 const struct prefix_rd *prd, afi_t afi,
11802 safi_t safi, json_object *json)
d62a17ae 11803{
40381db7 11804 struct bgp_path_info *pi;
d62a17ae 11805 struct peer *peer;
11806 struct listnode *node, *nnode;
06b9f471 11807 char buf1[RD_ADDRSTRLEN];
d62a17ae 11808 int count = 0;
11809 int best = 0;
11810 int suppress = 0;
c5f1e1b2
C
11811 int accept_own = 0;
11812 int route_filter_translated_v4 = 0;
11813 int route_filter_v4 = 0;
11814 int route_filter_translated_v6 = 0;
11815 int route_filter_v6 = 0;
11816 int llgr_stale = 0;
11817 int no_llgr = 0;
11818 int accept_own_nexthop = 0;
11819 int blackhole = 0;
d62a17ae 11820 int no_export = 0;
11821 int no_advertise = 0;
11822 int local_as = 0;
c5f1e1b2 11823 int no_peer = 0;
d62a17ae 11824 int first = 1;
11825 int has_valid_label = 0;
11826 mpls_label_t label = 0;
11827 json_object *json_adv_to = NULL;
67f67ba4
DA
11828 uint32_t ttl = 0;
11829 uint32_t bos = 0;
11830 uint32_t exp = 0;
9bedbb1e 11831
67f67ba4 11832 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11833
67f67ba4 11834 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11835
44c69747 11836 if (safi == SAFI_EVPN) {
44c69747 11837 if (!json) {
2dbe669b 11838 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
4a8cd6ad
PG
11839 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11840 bgp->asnotation)
f137734b 11841 : "",
2dbe669b 11842 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747 11843 } else {
4a8cd6ad
PG
11844 json_object_string_add(
11845 json, "rd",
11846 prd ? prefix_rd2str(prd, buf1, sizeof(buf1),
11847 bgp->asnotation)
11848 : "");
44c69747
LK
11849 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11850 }
11851 } else {
11852 if (!json) {
9119ef3a
DA
11853 vty_out(vty,
11854 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11855 "\n",
d62a17ae 11856 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7 11857 ? prefix_rd2str(prd, buf1,
4a8cd6ad
PG
11858 sizeof(buf1),
11859 bgp->asnotation)
8228a9a7 11860 : ""),
9119ef3a
DA
11861 safi == SAFI_MPLS_VPN ? ":" : "", p,
11862 dest->version);
cd1964ff 11863
9119ef3a 11864 } else {
67d7e256 11865 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11866 json_object_int_add(json, "version", dest->version);
11867
11868 }
44c69747
LK
11869 }
11870
11871 if (has_valid_label) {
11872 if (json)
11873 json_object_int_add(json, "localLabel", label);
11874 else
d62a17ae 11875 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11876 }
11877
11878 if (!json)
d62a17ae 11879 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11880 vty_out(vty, "not allocated\n");
718e3744 11881
9bcb3eef 11882 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11883 struct community *picomm = NULL;
11884
11885 picomm = bgp_attr_get_community(pi->attr);
11886
d62a17ae 11887 count++;
40381db7 11888 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11889 best = count;
4056a5f6 11890 if (bgp_path_suppressed(pi))
d62a17ae 11891 suppress = 1;
cee9c031 11892
9a706b42 11893 if (!picomm)
cee9c031
QY
11894 continue;
11895
11896 no_advertise += community_include(
9a706b42
DA
11897 picomm, COMMUNITY_NO_ADVERTISE);
11898 no_export +=
11899 community_include(picomm, COMMUNITY_NO_EXPORT);
11900 local_as +=
11901 community_include(picomm, COMMUNITY_LOCAL_AS);
11902 accept_own +=
11903 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11904 route_filter_translated_v4 += community_include(
9a706b42 11905 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11906 route_filter_translated_v6 += community_include(
9a706b42 11907 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11908 route_filter_v4 += community_include(
9a706b42 11909 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11910 route_filter_v6 += community_include(
9a706b42
DA
11911 picomm, COMMUNITY_ROUTE_FILTER_v6);
11912 llgr_stale +=
11913 community_include(picomm, COMMUNITY_LLGR_STALE);
11914 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11915 accept_own_nexthop += community_include(
11916 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11917 blackhole +=
11918 community_include(picomm, COMMUNITY_BLACKHOLE);
11919 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11920 }
718e3744 11921 }
718e3744 11922
d62a17ae 11923 if (!json) {
11924 vty_out(vty, "Paths: (%d available", count);
11925 if (best) {
11926 vty_out(vty, ", best #%d", best);
b84060bb
PG
11927 if (safi == SAFI_UNICAST) {
11928 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11929 vty_out(vty, ", table %s",
11930 VRF_DEFAULT_NAME);
11931 else
11932 vty_out(vty, ", vrf %s",
11933 bgp->name);
11934 }
d62a17ae 11935 } else
11936 vty_out(vty, ", no best path");
11937
c5f1e1b2
C
11938 if (accept_own)
11939 vty_out(vty,
11940 ", accept own local route exported and imported in different VRF");
11941 else if (route_filter_translated_v4)
11942 vty_out(vty,
11943 ", mark translated RTs for VPNv4 route filtering");
11944 else if (route_filter_v4)
11945 vty_out(vty,
11946 ", attach RT as-is for VPNv4 route filtering");
11947 else if (route_filter_translated_v6)
11948 vty_out(vty,
11949 ", mark translated RTs for VPNv6 route filtering");
11950 else if (route_filter_v6)
11951 vty_out(vty,
11952 ", attach RT as-is for VPNv6 route filtering");
11953 else if (llgr_stale)
11954 vty_out(vty,
1479ed2f 11955 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11956 else if (no_llgr)
11957 vty_out(vty,
11958 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11959 else if (accept_own_nexthop)
11960 vty_out(vty,
11961 ", accept local nexthop");
11962 else if (blackhole)
11963 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11964 else if (no_export)
11965 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11966 else if (no_advertise)
11967 vty_out(vty, ", not advertised to any peer");
d62a17ae 11968 else if (local_as)
11969 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11970 else if (no_peer)
11971 vty_out(vty,
11972 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11973
11974 if (suppress)
11975 vty_out(vty,
11976 ", Advertisements suppressed by an aggregate.");
11977 vty_out(vty, ")\n");
11978 }
718e3744 11979
d62a17ae 11980 /* If we are not using addpath then we can display Advertised to and
11981 * that will
11982 * show what peers we advertised the bestpath to. If we are using
11983 * addpath
11984 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11985 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11986 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11987 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11988 if (json && !json_adv_to)
11989 json_adv_to = json_object_new_object();
11990
11991 route_vty_out_advertised_to(
11992 vty, peer, &first,
11993 " Advertised to non peer-group peers:\n ",
11994 json_adv_to);
11995 }
11996 }
11997
11998 if (json) {
11999 if (json_adv_to) {
12000 json_object_object_add(json, "advertisedTo",
12001 json_adv_to);
12002 }
12003 } else {
12004 if (first)
12005 vty_out(vty, " Not advertised to any peer");
12006 vty_out(vty, "\n");
12007 }
12008 }
718e3744 12009}
12010
edfee30d 12011static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12012 struct bgp_dest *bgp_node, struct vty *vty,
12013 struct bgp *bgp, afi_t afi, safi_t safi,
12014 json_object *json, enum bgp_path_type pathtype,
4027d19b 12015 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12016{
12017 struct bgp_path_info *pi;
12018 int header = 1;
44c69747
LK
12019 json_object *json_header = NULL;
12020 json_object *json_paths = NULL;
4933eaaf 12021 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12022
9bcb3eef 12023 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12024 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12025
12026 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12027 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12028 pi->peer, pi->attr, p);
4933eaaf 12029
4027d19b
DS
12030 if (rpki_target_state != RPKI_NOT_BEING_USED
12031 && rpki_curr_state != rpki_target_state)
4933eaaf 12032 continue;
44c69747
LK
12033
12034 if (json && !json_paths) {
12035 /* Instantiate json_paths only if path is valid */
12036 json_paths = json_object_new_array();
c4f64ea9 12037 if (pfx_rd)
44c69747 12038 json_header = json_object_new_object();
c4f64ea9 12039 else
44c69747
LK
12040 json_header = json;
12041 }
12042
12043 if (header) {
12044 route_vty_out_detail_header(
34c7f35f
SW
12045 vty, bgp, bgp_node,
12046 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12047 safi, json_header);
44c69747
LK
12048 header = 0;
12049 }
12050 (*display)++;
12051
12052 if (pathtype == BGP_PATH_SHOW_ALL
12053 || (pathtype == BGP_PATH_SHOW_BESTPATH
12054 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12055 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12056 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12057 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12058 route_vty_out_detail(vty, bgp, bgp_node,
12059 bgp_dest_get_prefix(bgp_node), pi,
12060 AFI_IP, safi, rpki_curr_state,
12061 json_paths);
44c69747
LK
12062 }
12063
12064 if (json && json_paths) {
12065 json_object_object_add(json_header, "paths", json_paths);
12066
12067 if (pfx_rd)
4a8cd6ad
PG
12068 json_object_object_addf(
12069 json, json_header,
12070 BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);
44c69747
LK
12071 }
12072}
12073
2aad8c42
MS
12074/*
12075 * Return rd based on safi
12076 */
46dbf9d0
DA
12077const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12078 safi_t safi)
2aad8c42
MS
12079{
12080 switch (safi) {
12081 case SAFI_MPLS_VPN:
12082 case SAFI_ENCAP:
12083 case SAFI_EVPN:
12084 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12085 case SAFI_UNSPEC:
12086 case SAFI_UNICAST:
12087 case SAFI_MULTICAST:
12088 case SAFI_LABELED_UNICAST:
12089 case SAFI_FLOWSPEC:
12090 case SAFI_MAX:
2aad8c42 12091 return NULL;
2aad8c42 12092 }
58cf0823
DS
12093
12094 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12095}
12096
718e3744 12097/* Display specified route of BGP table. */
d62a17ae 12098static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12099 struct bgp_table *rib, const char *ip_str,
12100 afi_t afi, safi_t safi,
4027d19b 12101 enum rpki_states rpki_target_state,
d62a17ae 12102 struct prefix_rd *prd, int prefix_check,
9f049418 12103 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12104{
12105 int ret;
d62a17ae 12106 int display = 0;
12107 struct prefix match;
9bcb3eef
DS
12108 struct bgp_dest *dest;
12109 struct bgp_dest *rm;
d62a17ae 12110 struct bgp_table *table;
12111 json_object *json = NULL;
12112 json_object *json_paths = NULL;
12113
12114 /* Check IP address argument. */
12115 ret = str2prefix(ip_str, &match);
12116 if (!ret) {
12117 vty_out(vty, "address is malformed\n");
12118 return CMD_WARNING;
12119 }
718e3744 12120
d62a17ae 12121 match.family = afi2family(afi);
b05a1c8b 12122
44c69747 12123 if (use_json)
d62a17ae 12124 json = json_object_new_object();
718e3744 12125
44c69747 12126 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12127 for (dest = bgp_table_top(rib); dest;
12128 dest = bgp_route_next(dest)) {
12129 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12130
9bcb3eef 12131 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12132 continue;
9bcb3eef 12133 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12134 if (!table)
ea47320b 12135 continue;
d62a17ae 12136
4953391b
DA
12137 rm = bgp_node_match(table, &match);
12138 if (rm == NULL)
ea47320b 12139 continue;
d62a17ae 12140
9bcb3eef 12141 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12142 if (prefix_check
b54892e0 12143 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12144 bgp_dest_unlock_node(rm);
ea47320b
DL
12145 continue;
12146 }
d62a17ae 12147
9bcb3eef 12148 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12149 bgp, afi, safi, json, pathtype,
4027d19b 12150 &display, rpki_target_state);
44c69747 12151
9bcb3eef 12152 bgp_dest_unlock_node(rm);
44c69747
LK
12153 }
12154 } else if (safi == SAFI_EVPN) {
9bcb3eef 12155 struct bgp_dest *longest_pfx;
cded3b72 12156 bool is_exact_pfxlen_match = false;
44c69747 12157
9bcb3eef
DS
12158 for (dest = bgp_table_top(rib); dest;
12159 dest = bgp_route_next(dest)) {
12160 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12161
9bcb3eef 12162 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12163 continue;
9bcb3eef 12164 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12165 if (!table)
12166 continue;
12167
12168 longest_pfx = NULL;
cded3b72 12169 is_exact_pfxlen_match = false;
44c69747
LK
12170 /*
12171 * Search through all the prefixes for a match. The
12172 * pfx's are enumerated in ascending order of pfxlens.
12173 * So, the last pfx match is the longest match. Set
12174 * is_exact_pfxlen_match when we get exact pfxlen match
12175 */
12176 for (rm = bgp_table_top(table); rm;
12177 rm = bgp_route_next(rm)) {
b54892e0 12178 const struct prefix *rm_p =
9bcb3eef 12179 bgp_dest_get_prefix(rm);
44c69747
LK
12180 /*
12181 * Get prefixlen of the ip-prefix within type5
12182 * evpn route
12183 */
b54892e0
DS
12184 if (evpn_type5_prefix_match(rm_p, &match)
12185 && rm->info) {
44c69747
LK
12186 longest_pfx = rm;
12187 int type5_pfxlen =
b54892e0
DS
12188 bgp_evpn_get_type5_prefixlen(
12189 rm_p);
44c69747 12190 if (type5_pfxlen == match.prefixlen) {
cded3b72 12191 is_exact_pfxlen_match = true;
9bcb3eef 12192 bgp_dest_unlock_node(rm);
44c69747
LK
12193 break;
12194 }
d62a17ae 12195 }
12196 }
ea47320b 12197
44c69747
LK
12198 if (!longest_pfx)
12199 continue;
12200
12201 if (prefix_check && !is_exact_pfxlen_match)
12202 continue;
12203
12204 rm = longest_pfx;
9bcb3eef 12205 bgp_dest_lock_node(rm);
44c69747 12206
9bcb3eef 12207 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12208 bgp, afi, safi, json, pathtype,
4027d19b 12209 &display, rpki_target_state);
44c69747 12210
9bcb3eef 12211 bgp_dest_unlock_node(rm);
d62a17ae 12212 }
98a9dbc7 12213 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12214 if (use_json)
12215 json_paths = json_object_new_array();
12216
63a0b7a9
PG
12217 display = bgp_flowspec_display_match_per_ip(afi, rib,
12218 &match, prefix_check,
12219 vty,
12220 use_json,
12221 json_paths);
d5f20468
SP
12222 if (use_json) {
12223 if (display)
12224 json_object_object_add(json, "paths",
12225 json_paths);
12226 else
12227 json_object_free(json_paths);
12228 }
d62a17ae 12229 } else {
4953391b
DA
12230 dest = bgp_node_match(rib, &match);
12231 if (dest != NULL) {
9bcb3eef 12232 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12233 if (!prefix_check
9bcb3eef
DS
12234 || dest_p->prefixlen == match.prefixlen) {
12235 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12236 safi, json, pathtype,
4027d19b 12237 &display, rpki_target_state);
d62a17ae 12238 }
12239
9bcb3eef 12240 bgp_dest_unlock_node(dest);
d62a17ae 12241 }
12242 }
e5eee9af 12243
d62a17ae 12244 if (use_json) {
75eeda93 12245 vty_json(vty, json);
d62a17ae 12246 } else {
12247 if (!display) {
12248 vty_out(vty, "%% Network not in table\n");
12249 return CMD_WARNING;
12250 }
12251 }
b05a1c8b 12252
d62a17ae 12253 return CMD_SUCCESS;
718e3744 12254}
12255
fee0f4c6 12256/* Display specified route of Main RIB */
d62a17ae 12257static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12258 afi_t afi, safi_t safi, struct prefix_rd *prd,
12259 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12260 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12261{
9b86009a 12262 if (!bgp) {
d62a17ae 12263 bgp = bgp_get_default();
9b86009a
RW
12264 if (!bgp) {
12265 if (!use_json)
12266 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12267 else
12268 vty_out(vty, "{}\n");
9b86009a
RW
12269 return CMD_WARNING;
12270 }
12271 }
d62a17ae 12272
12273 /* labeled-unicast routes live in the unicast table */
12274 if (safi == SAFI_LABELED_UNICAST)
12275 safi = SAFI_UNICAST;
12276
12277 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12278 afi, safi, rpki_target_state, prd,
8aa22bbb 12279 prefix_check, pathtype, use_json);
d62a17ae 12280}
12281
12282static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12283 struct cmd_token **argv, bool exact, afi_t afi,
12284 safi_t safi, bool uj)
d62a17ae 12285{
12286 struct lcommunity *lcom;
12287 struct buffer *b;
12288 int i;
12289 char *str;
12290 int first = 0;
96c81f66 12291 uint16_t show_flags = 0;
4f28b2b5 12292 int ret;
96f3485c
MK
12293
12294 if (uj)
12295 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12296
12297 b = buffer_new(1024);
12298 for (i = 0; i < argc; i++) {
12299 if (first)
12300 buffer_putc(b, ' ');
12301 else {
12302 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12303 first = 1;
12304 buffer_putstr(b, argv[i]->arg);
12305 }
12306 }
12307 }
12308 buffer_putc(b, '\0');
57d187bc 12309
d62a17ae 12310 str = buffer_getstr(b);
12311 buffer_free(b);
57d187bc 12312
d62a17ae 12313 lcom = lcommunity_str2com(str);
12314 XFREE(MTYPE_TMP, str);
12315 if (!lcom) {
12316 vty_out(vty, "%% Large-community malformed\n");
12317 return CMD_WARNING;
12318 }
57d187bc 12319
4f28b2b5 12320 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12321 (exact ? bgp_show_type_lcommunity_exact
12322 : bgp_show_type_lcommunity),
12323 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12324
12325 lcommunity_free(&lcom);
12326 return ret;
57d187bc
JS
12327}
12328
d62a17ae 12329static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12330 const char *lcom, bool exact, afi_t afi,
12331 safi_t safi, bool uj)
57d187bc 12332{
d62a17ae 12333 struct community_list *list;
96c81f66 12334 uint16_t show_flags = 0;
96f3485c
MK
12335
12336 if (uj)
12337 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12338
57d187bc 12339
e237b0d2 12340 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12341 LARGE_COMMUNITY_LIST_MASTER);
12342 if (list == NULL) {
12343 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12344 lcom);
12345 return CMD_WARNING;
12346 }
57d187bc 12347
36a206db 12348 return bgp_show(vty, bgp, afi, safi,
12349 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12350 : bgp_show_type_lcommunity_list),
1e2ce4f1 12351 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12352}
12353
52951b63
DS
12354DEFUN (show_ip_bgp_large_community_list,
12355 show_ip_bgp_large_community_list_cmd,
77a3a95e 12356 "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
12357 SHOW_STR
12358 IP_STR
12359 BGP_STR
12360 BGP_INSTANCE_HELP_STR
9bedbb1e 12361 BGP_AFI_HELP_STR
4dd6177e 12362 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12363 "Display routes matching the large-community-list\n"
12364 "large-community-list number\n"
12365 "large-community-list name\n"
36a206db 12366 "Exact match of the large-communities\n"
52951b63
DS
12367 JSON_STR)
12368{
d62a17ae 12369 afi_t afi = AFI_IP6;
12370 safi_t safi = SAFI_UNICAST;
12371 int idx = 0;
36a206db 12372 bool exact_match = 0;
4d678463 12373 struct bgp *bgp = NULL;
9f049418 12374 bool uj = use_json(argc, argv);
d62a17ae 12375
ef3364f0
DA
12376 if (uj)
12377 argc--;
4d678463 12378
ef3364f0
DA
12379 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12380 &bgp, uj);
12381 if (!idx)
12382 return CMD_WARNING;
d62a17ae 12383
12384 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12385
12386 const char *clist_number_or_name = argv[++idx]->arg;
12387
12388 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12389 exact_match = 1;
12390
12391 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12392 exact_match, afi, safi, uj);
52951b63
DS
12393}
12394DEFUN (show_ip_bgp_large_community,
12395 show_ip_bgp_large_community_cmd,
36a206db 12396 "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
12397 SHOW_STR
12398 IP_STR
12399 BGP_STR
12400 BGP_INSTANCE_HELP_STR
9bedbb1e 12401 BGP_AFI_HELP_STR
4dd6177e 12402 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12403 "Display routes matching the large-communities\n"
12404 "List of large-community numbers\n"
36a206db 12405 "Exact match of the large-communities\n"
52951b63
DS
12406 JSON_STR)
12407{
d62a17ae 12408 afi_t afi = AFI_IP6;
12409 safi_t safi = SAFI_UNICAST;
12410 int idx = 0;
36a206db 12411 bool exact_match = 0;
4d678463 12412 struct bgp *bgp = NULL;
9f049418 12413 bool uj = use_json(argc, argv);
96c81f66 12414 uint16_t show_flags = 0;
d62a17ae 12415
96f3485c
MK
12416 if (uj) {
12417 argc--;
12418 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12419 }
4d678463 12420
96f3485c
MK
12421 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12422 &bgp, uj);
12423 if (!idx)
12424 return CMD_WARNING;
d62a17ae 12425
36a206db 12426 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12427 if (argv_find(argv, argc, "exact-match", &idx)) {
12428 argc--;
36a206db 12429 exact_match = 1;
1857760c 12430 }
36a206db 12431 return bgp_show_lcommunity(vty, bgp, argc, argv,
12432 exact_match, afi, safi, uj);
12433 } else
d62a17ae 12434 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12435 bgp_show_type_lcommunity_all, NULL, show_flags,
12436 RPKI_NOT_BEING_USED);
52951b63
DS
12437}
12438
71f1613a
DA
12439static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12440 safi_t safi, struct json_object *json_array);
d62a17ae 12441static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12442 safi_t safi, struct json_object *json);
e01ca200 12443
7b2ff250 12444
9ab0cf58
PG
12445DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12446 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12447 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12448 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12449{
12450 bool uj = use_json(argc, argv);
12451 struct bgp *bgp = NULL;
ec76a1d1
DA
12452 safi_t safi = SAFI_UNICAST;
12453 afi_t afi = AFI_IP6;
4265b261 12454 int idx = 0;
6c9d22e2
PG
12455 struct json_object *json_all = NULL;
12456 struct json_object *json_afi_safi = NULL;
4265b261
PG
12457
12458 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12459 &bgp, false);
71f1613a 12460 if (!idx)
4265b261 12461 return CMD_WARNING;
6c9d22e2 12462
4265b261 12463 if (uj)
6c9d22e2 12464 json_all = json_object_new_object();
4265b261 12465
9ab0cf58
PG
12466 FOREACH_AFI_SAFI (afi, safi) {
12467 /*
12468 * So limit output to those afi/safi pairs that
12469 * actually have something interesting in them
12470 */
12471 if (strmatch(get_afi_safi_str(afi, safi, true),
12472 "Unknown")) {
12473 continue;
12474 }
12475 if (uj) {
12476 json_afi_safi = json_object_new_array();
12477 json_object_object_add(
12478 json_all,
12479 get_afi_safi_str(afi, safi, true),
12480 json_afi_safi);
12481 } else {
12482 json_afi_safi = NULL;
6c9d22e2 12483 }
9ab0cf58
PG
12484
12485 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12486 }
6c9d22e2 12487
3757f964
DA
12488 if (uj)
12489 vty_json(vty, json_all);
6c9d22e2 12490
4265b261
PG
12491 return CMD_SUCCESS;
12492}
12493
7b2ff250 12494/* BGP route print out function without JSON */
14718643
PG
12495DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12496 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12497 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12498 SHOW_STR
12499 IP_STR
12500 BGP_STR
12501 BGP_INSTANCE_HELP_STR
12502 L2VPN_HELP_STR
12503 EVPN_HELP_STR
12504 "BGP RIB advertisement statistics\n"
12505 JSON_STR)
12506{
ec76a1d1
DA
12507 afi_t afi = AFI_IP6;
12508 safi_t safi = SAFI_UNICAST;
14718643
PG
12509 struct bgp *bgp = NULL;
12510 int idx = 0, ret;
12511 bool uj = use_json(argc, argv);
12512 struct json_object *json_afi_safi = NULL, *json = NULL;
12513
12514 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12515 &bgp, false);
12516 if (!idx)
12517 return CMD_WARNING;
12518
12519 if (uj)
12520 json_afi_safi = json_object_new_array();
12521 else
12522 json_afi_safi = NULL;
12523
12524 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12525
12526 if (uj) {
12527 json = json_object_new_object();
12528 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12529 json_afi_safi);
3757f964 12530 vty_json(vty, json);
14718643
PG
12531 }
12532 return ret;
12533}
12534
893cccd0 12535/* BGP route print out function without JSON */
9ab0cf58
PG
12536DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12537 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12538 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12539 "]]\
893cccd0 12540 statistics [json]",
9ab0cf58
PG
12541 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12542 BGP_SAFI_WITH_LABEL_HELP_STR
12543 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12544{
ec76a1d1
DA
12545 afi_t afi = AFI_IP6;
12546 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12547 struct bgp *bgp = NULL;
12548 int idx = 0, ret;
12549 bool uj = use_json(argc, argv);
6c9d22e2 12550 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12551
12552 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12553 &bgp, false);
12554 if (!idx)
12555 return CMD_WARNING;
6c9d22e2 12556
893cccd0 12557 if (uj)
6c9d22e2
PG
12558 json_afi_safi = json_object_new_array();
12559 else
12560 json_afi_safi = NULL;
12561
12562 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12563
12564 if (uj) {
12565 json = json_object_new_object();
12566 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12567 json_afi_safi);
3757f964 12568 vty_json(vty, json);
893cccd0
PG
12569 }
12570 return ret;
893cccd0 12571}
7b2ff250 12572
fe0f234d 12573DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12574 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12575 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12576 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12577 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12578 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12579 "Display the entries for all address families\n"
9ab0cf58
PG
12580 "Display detailed information about dampening\n"
12581 "Display detail of configured dampening parameters\n"
fe0f234d 12582 JSON_STR)
718e3744 12583{
d62a17ae 12584 afi_t afi = AFI_IP6;
12585 safi_t safi = SAFI_UNICAST;
d62a17ae 12586 struct bgp *bgp = NULL;
12587 int idx = 0;
96c81f66 12588 uint16_t show_flags = 0;
fe0f234d
RW
12589 bool uj = use_json(argc, argv);
12590
12591 if (uj) {
12592 argc--;
12593 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12594 }
96f3485c
MK
12595
12596 /* [<ipv4|ipv6> [all]] */
12597 if (all) {
12598 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12599 if (argv_find(argv, argc, "ipv4", &idx))
12600 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12601
12602 if (argv_find(argv, argc, "ipv6", &idx))
12603 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12604 }
d62a17ae 12605
12606 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12607 &bgp, false);
d62a17ae 12608 if (!idx)
12609 return CMD_WARNING;
12610
fe0f234d 12611 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12612}
12613
fe0f234d
RW
12614/* BGP route print out function */
12615DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12616 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12617 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12618 "]]\
96f3485c 12619 [all$all]\
cf4898bc
QY
12620 [cidr-only\
12621 |dampening <flap-statistics|dampened-paths>\
12622 |community [AA:NN|local-AS|no-advertise|no-export\
12623 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12624 |accept-own|accept-own-nexthop|route-filter-v6\
12625 |route-filter-v4|route-filter-translated-v6\
12626 |route-filter-translated-v4] [exact-match]\
70799983 12627 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12628 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12629 |prefix-list WORD\
ed126382 12630 |access-list ACCESSLIST_NAME\
70dd370f 12631 |route-map RMAP_NAME\
1e2ce4f1 12632 |rpki <invalid|valid|notfound>\
7d3cae70 12633 |version (1-4294967295)\
b4ad2fae 12634 |alias ALIAS_NAME\
39c3c736
RW
12635 |A.B.C.D/M longer-prefixes\
12636 |X:X::X:X/M longer-prefixes\
509d82bd 12637 |detail-routes$detail_routes\
67799a48 12638 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12639 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12640 BGP_SAFI_WITH_LABEL_HELP_STR
12641 "Display the entries for all address families\n"
12642 "Display only routes with non-natural netmasks\n"
12643 "Display detailed information about dampening\n"
12644 "Display flap statistics of routes\n"
12645 "Display paths suppressed due to dampening\n"
12646 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12647 "Do not send outside local AS (well-known community)\n"
12648 "Do not advertise to any peer (well-known community)\n"
12649 "Do not export to next AS (well-known community)\n"
12650 "Graceful shutdown (well-known community)\n"
12651 "Do not export to any peer (well-known community)\n"
12652 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12653 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12654 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12655 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12656 "Should accept VPN route with local nexthop (well-known community)\n"
12657 "RT VPNv6 route filtering (well-known community)\n"
12658 "RT VPNv4 route filtering (well-known community)\n"
12659 "RT translated VPNv6 route filtering (well-known community)\n"
12660 "RT translated VPNv4 route filtering (well-known community)\n"
12661 "Exact match of the communities\n"
70799983
RW
12662 "Community-list number\n"
12663 "Community-list name\n"
12664 "Display routes matching the community-list\n"
12665 "Exact match of the communities\n"
a7129347
RW
12666 "Display routes conforming to the filter-list\n"
12667 "Regular expression access list name\n"
6deaf579
RW
12668 "Display routes conforming to the prefix-list\n"
12669 "Prefix-list name\n"
ed126382
DA
12670 "Display routes conforming to the access-list\n"
12671 "Access-list name\n"
bf1a944a
RW
12672 "Display routes matching the route-map\n"
12673 "A route-map to match on\n"
a70a28a5
DA
12674 "RPKI route types\n"
12675 "A valid path as determined by rpki\n"
12676 "A invalid path as determined by rpki\n"
12677 "A path that has no rpki data\n"
12678 "Display prefixes with matching version numbers\n"
12679 "Version number and above\n"
12680 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12681 "BGP community alias\n"
12682 "IPv4 prefix\n"
12683 "Display route and more specific routes\n"
12684 "IPv6 prefix\n"
12685 "Display route and more specific routes\n"
509d82bd 12686 "Display detailed version of all routes\n"
39c3c736 12687 JSON_STR
a70a28a5
DA
12688 "Display detailed version of JSON output\n"
12689 "Increase table width for longer prefixes\n")
7b2ff250
DW
12690{
12691 afi_t afi = AFI_IP6;
12692 safi_t safi = SAFI_UNICAST;
12693 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12694 void *output_arg = NULL;
7b2ff250
DW
12695 struct bgp *bgp = NULL;
12696 int idx = 0;
d0086e8e 12697 int exact_match = 0;
96f3485c
MK
12698 char *community = NULL;
12699 bool first = true;
96c81f66 12700 uint16_t show_flags = 0;
4027d19b 12701 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12702 struct prefix p;
96f3485c
MK
12703
12704 if (uj) {
9f049418 12705 argc--;
96f3485c
MK
12706 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12707 }
12708
67799a48
DA
12709 if (detail_json)
12710 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12711
509d82bd
DA
12712 if (detail_routes)
12713 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12714
96f3485c
MK
12715 /* [<ipv4|ipv6> [all]] */
12716 if (all) {
12717 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12718
12719 if (argv_find(argv, argc, "ipv4", &idx))
12720 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12721
12722 if (argv_find(argv, argc, "ipv6", &idx))
12723 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12724 }
12725
12726 if (wide)
12727 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12728
12729 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12730 &bgp, uj);
7b2ff250
DW
12731 if (!idx)
12732 return CMD_WARNING;
12733
7b2ff250 12734 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12735 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12736
12737 if (argv_find(argv, argc, "dampening", &idx)) {
12738 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12739 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12740 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12741 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12742 }
12743
12744 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12745 char *maybecomm = NULL;
d0086e8e 12746
79bc257a
RW
12747 if (idx + 1 < argc) {
12748 if (argv[idx + 1]->type == VARIABLE_TKN)
12749 maybecomm = argv[idx + 1]->arg;
12750 else
12751 maybecomm = argv[idx + 1]->text;
12752 }
12753
cf4898bc
QY
12754 if (maybecomm && !strmatch(maybecomm, "json")
12755 && !strmatch(maybecomm, "exact-match"))
12756 community = maybecomm;
d0086e8e 12757
cf4898bc
QY
12758 if (argv_find(argv, argc, "exact-match", &idx))
12759 exact_match = 1;
d0086e8e 12760
96f3485c
MK
12761 if (!community)
12762 sh_type = bgp_show_type_community_all;
12763 }
12764
70799983
RW
12765 if (argv_find(argv, argc, "community-list", &idx)) {
12766 const char *clist_number_or_name = argv[++idx]->arg;
12767 struct community_list *list;
12768
12769 if (argv_find(argv, argc, "exact-match", &idx))
12770 exact_match = 1;
12771
12772 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12773 COMMUNITY_LIST_MASTER);
12774 if (list == NULL) {
606d49a4 12775 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12776 clist_number_or_name);
12777 return CMD_WARNING;
12778 }
12779
12780 if (exact_match)
12781 sh_type = bgp_show_type_community_list_exact;
12782 else
12783 sh_type = bgp_show_type_community_list;
12784 output_arg = list;
12785 }
12786
a7129347
RW
12787 if (argv_find(argv, argc, "filter-list", &idx)) {
12788 const char *filter = argv[++idx]->arg;
12789 struct as_list *as_list;
12790
12791 as_list = as_list_lookup(filter);
12792 if (as_list == NULL) {
606d49a4 12793 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12794 filter);
12795 return CMD_WARNING;
12796 }
12797
12798 sh_type = bgp_show_type_filter_list;
12799 output_arg = as_list;
12800 }
12801
6deaf579
RW
12802 if (argv_find(argv, argc, "prefix-list", &idx)) {
12803 const char *prefix_list_str = argv[++idx]->arg;
12804 struct prefix_list *plist;
12805
12806 plist = prefix_list_lookup(afi, prefix_list_str);
12807 if (plist == NULL) {
606d49a4 12808 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12809 prefix_list_str);
12810 return CMD_WARNING;
12811 }
12812
12813 sh_type = bgp_show_type_prefix_list;
12814 output_arg = plist;
12815 }
12816
ed126382
DA
12817 if (argv_find(argv, argc, "access-list", &idx)) {
12818 const char *access_list_str = argv[++idx]->arg;
12819 struct access_list *alist;
12820
12821 alist = access_list_lookup(afi, access_list_str);
12822 if (!alist) {
606d49a4 12823 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12824 access_list_str);
12825 return CMD_WARNING;
12826 }
12827
12828 sh_type = bgp_show_type_access_list;
12829 output_arg = alist;
12830 }
12831
bf1a944a
RW
12832 if (argv_find(argv, argc, "route-map", &idx)) {
12833 const char *rmap_str = argv[++idx]->arg;
12834 struct route_map *rmap;
12835
12836 rmap = route_map_lookup_by_name(rmap_str);
12837 if (!rmap) {
606d49a4 12838 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12839 return CMD_WARNING;
12840 }
12841
12842 sh_type = bgp_show_type_route_map;
12843 output_arg = rmap;
12844 }
12845
1e2ce4f1
DS
12846 if (argv_find(argv, argc, "rpki", &idx)) {
12847 sh_type = bgp_show_type_rpki;
12848 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12849 rpki_target_state = RPKI_VALID;
1e2ce4f1 12850 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12851 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12852 }
12853
7d3cae70
DA
12854 /* Display prefixes with matching version numbers */
12855 if (argv_find(argv, argc, "version", &idx)) {
12856 sh_type = bgp_show_type_prefix_version;
2391833e 12857 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12858 }
12859
a70a28a5
DA
12860 /* Display prefixes with matching BGP community alias */
12861 if (argv_find(argv, argc, "alias", &idx)) {
12862 sh_type = bgp_show_type_community_alias;
2391833e 12863 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12864 }
12865
39c3c736
RW
12866 /* prefix-longer */
12867 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12868 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12869 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12870
12871 if (!str2prefix(prefix_str, &p)) {
12872 vty_out(vty, "%% Malformed Prefix\n");
12873 return CMD_WARNING;
12874 }
12875
12876 sh_type = bgp_show_type_prefix_longer;
12877 output_arg = &p;
a70a28a5
DA
12878 }
12879
96f3485c
MK
12880 if (!all) {
12881 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12882 if (community)
12883 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12884 exact_match, afi, safi,
12885 show_flags);
2391833e 12886 else
a70a28a5 12887 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12888 output_arg, show_flags,
a70a28a5 12889 rpki_target_state);
96f3485c 12890 } else {
fa5ac378
DA
12891 struct listnode *node;
12892 struct bgp *abgp;
96f3485c
MK
12893 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12894 * AFI_IP6 */
12895
12896 if (uj)
12897 vty_out(vty, "{\n");
12898
12899 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12900 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12901 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12902 ? AFI_IP
12903 : AFI_IP6;
fa5ac378
DA
12904 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12905 FOREACH_SAFI (safi) {
12906 if (!bgp_afi_safi_peer_exists(abgp, afi,
12907 safi))
12908 continue;
96f3485c 12909
fa5ac378
DA
12910 if (uj) {
12911 if (first)
12912 first = false;
12913 else
12914 vty_out(vty, ",\n");
12915 vty_out(vty, "\"%s\":{\n",
12916 get_afi_safi_str(afi,
12917 safi,
12918 true));
12919 } else
12920 vty_out(vty,
12921 "\nFor address family: %s\n",
12922 get_afi_safi_str(
12923 afi, safi,
12924 false));
12925
12926 if (community)
12927 bgp_show_community(
12928 vty, abgp, community,
12929 exact_match, afi, safi,
12930 show_flags);
96f3485c 12931 else
fa5ac378
DA
12932 bgp_show(vty, abgp, afi, safi,
12933 sh_type, output_arg,
12934 show_flags,
12935 rpki_target_state);
12936 if (uj)
12937 vty_out(vty, "}\n");
12938 }
96f3485c
MK
12939 }
12940 } else {
12941 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12942 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12943 FOREACH_AFI_SAFI (afi, safi) {
12944 if (!bgp_afi_safi_peer_exists(abgp, afi,
12945 safi))
12946 continue;
96f3485c 12947
fa5ac378
DA
12948 if (uj) {
12949 if (first)
12950 first = false;
12951 else
12952 vty_out(vty, ",\n");
12953
12954 vty_out(vty, "\"%s\":{\n",
12955 get_afi_safi_str(afi,
12956 safi,
12957 true));
12958 } else
12959 vty_out(vty,
12960 "\nFor address family: %s\n",
12961 get_afi_safi_str(
12962 afi, safi,
12963 false));
12964
12965 if (community)
12966 bgp_show_community(
12967 vty, abgp, community,
12968 exact_match, afi, safi,
12969 show_flags);
96f3485c 12970 else
fa5ac378
DA
12971 bgp_show(vty, abgp, afi, safi,
12972 sh_type, output_arg,
12973 show_flags,
12974 rpki_target_state);
12975 if (uj)
12976 vty_out(vty, "}\n");
12977 }
96f3485c
MK
12978 }
12979 }
12980 if (uj)
12981 vty_out(vty, "}\n");
12982 }
12983 return CMD_SUCCESS;
a636c635 12984}
47fc97cc 12985
718e3744 12986DEFUN (show_ip_bgp_route,
12987 show_ip_bgp_route_cmd,
8aa22bbb 12988 "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 12989 SHOW_STR
12990 IP_STR
12991 BGP_STR
a636c635 12992 BGP_INSTANCE_HELP_STR
4f280b15 12993 BGP_AFI_HELP_STR
4dd6177e 12994 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12995 "Network in the BGP routing table to display\n"
0c7b1b01 12996 "IPv4 prefix\n"
8c3deaae 12997 "Network in the BGP routing table to display\n"
0c7b1b01 12998 "IPv6 prefix\n"
4092b06c 12999 "Display only the bestpath\n"
b05a1c8b 13000 "Display only multipaths\n"
8aa22bbb
DS
13001 "Display only paths that match the specified rpki state\n"
13002 "A valid path as determined by rpki\n"
13003 "A invalid path as determined by rpki\n"
13004 "A path that has no rpki data\n"
9973d184 13005 JSON_STR)
4092b06c 13006{
d62a17ae 13007 int prefix_check = 0;
ae19d7dd 13008
d62a17ae 13009 afi_t afi = AFI_IP6;
13010 safi_t safi = SAFI_UNICAST;
13011 char *prefix = NULL;
13012 struct bgp *bgp = NULL;
13013 enum bgp_path_type path_type;
9f049418 13014 bool uj = use_json(argc, argv);
b05a1c8b 13015
d62a17ae 13016 int idx = 0;
ae19d7dd 13017
d62a17ae 13018 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13019 &bgp, uj);
d62a17ae 13020 if (!idx)
13021 return CMD_WARNING;
c41247f5 13022
d62a17ae 13023 if (!bgp) {
13024 vty_out(vty,
13025 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13026 return CMD_WARNING;
13027 }
a636c635 13028
d62a17ae 13029 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13030 if (argv_find(argv, argc, "A.B.C.D", &idx)
13031 || argv_find(argv, argc, "X:X::X:X", &idx))
13032 prefix_check = 0;
13033 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13034 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13035 prefix_check = 1;
13036
13037 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13038 && afi != AFI_IP6) {
13039 vty_out(vty,
13040 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13041 return CMD_WARNING;
13042 }
13043 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13044 && afi != AFI_IP) {
13045 vty_out(vty,
13046 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13047 return CMD_WARNING;
13048 }
13049
13050 prefix = argv[idx]->arg;
13051
13052 /* [<bestpath|multipath>] */
13053 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13054 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13055 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13056 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13057 else
360660c6 13058 path_type = BGP_PATH_SHOW_ALL;
a636c635 13059
d62a17ae 13060 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13061 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13062}
13063
8c3deaae
QY
13064DEFUN (show_ip_bgp_regexp,
13065 show_ip_bgp_regexp_cmd,
3e5b31b3 13066 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13067 SHOW_STR
13068 IP_STR
13069 BGP_STR
b00b230a 13070 BGP_INSTANCE_HELP_STR
4f280b15 13071 BGP_AFI_HELP_STR
4dd6177e 13072 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13073 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13074 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13075 JSON_STR)
8c3deaae 13076{
d62a17ae 13077 afi_t afi = AFI_IP6;
13078 safi_t safi = SAFI_UNICAST;
13079 struct bgp *bgp = NULL;
3e5b31b3
DA
13080 bool uj = use_json(argc, argv);
13081 char *regstr = NULL;
8c3deaae 13082
d62a17ae 13083 int idx = 0;
13084 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13085 &bgp, false);
d62a17ae 13086 if (!idx)
13087 return CMD_WARNING;
8c3deaae 13088
d62a17ae 13089 // get index of regex
3e5b31b3
DA
13090 if (argv_find(argv, argc, "REGEX", &idx))
13091 regstr = argv[idx]->arg;
8c3deaae 13092
5f71d11c 13093 assert(regstr);
3e5b31b3
DA
13094 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13095 bgp_show_type_regexp, uj);
8c3deaae
QY
13096}
13097
ae248832 13098DEFPY (show_ip_bgp_instance_all,
a636c635 13099 show_ip_bgp_instance_all_cmd,
ae248832 13100 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13101 SHOW_STR
a636c635 13102 IP_STR
4092b06c 13103 BGP_STR
a636c635 13104 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13105 BGP_AFI_HELP_STR
4dd6177e 13106 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13107 JSON_STR
13108 "Increase table width for longer prefixes\n")
4092b06c 13109{
54d05dea 13110 afi_t afi = AFI_IP6;
d62a17ae 13111 safi_t safi = SAFI_UNICAST;
13112 struct bgp *bgp = NULL;
d62a17ae 13113 int idx = 0;
96c81f66 13114 uint16_t show_flags = 0;
ae19d7dd 13115
96f3485c 13116 if (uj) {
d62a17ae 13117 argc--;
96f3485c
MK
13118 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13119 }
13120
13121 if (wide)
13122 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13123
9f049418
DS
13124 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13125 &bgp, uj);
13126 if (!idx)
13127 return CMD_WARNING;
13128
96f3485c 13129 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13130 return CMD_SUCCESS;
e3e29b32
LB
13131}
13132
a4d82a8a 13133static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13134 afi_t afi, safi_t safi, enum bgp_show_type type,
13135 bool use_json)
718e3744 13136{
d62a17ae 13137 regex_t *regex;
13138 int rc;
96c81f66 13139 uint16_t show_flags = 0;
96f3485c
MK
13140
13141 if (use_json)
13142 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13143
c3900853 13144 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13145 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13146 regstr);
13147 return CMD_WARNING_CONFIG_FAILED;
13148 }
13149
d62a17ae 13150 regex = bgp_regcomp(regstr);
13151 if (!regex) {
13152 vty_out(vty, "Can't compile regexp %s\n", regstr);
13153 return CMD_WARNING;
13154 }
a636c635 13155
1e2ce4f1
DS
13156 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13157 RPKI_NOT_BEING_USED);
d62a17ae 13158 bgp_regex_free(regex);
13159 return rc;
e3e29b32
LB
13160}
13161
7f323236
DW
13162static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13163 const char *comstr, int exact, afi_t afi,
96c81f66 13164 safi_t safi, uint16_t show_flags)
d62a17ae 13165{
13166 struct community *com;
d62a17ae 13167 int ret = 0;
13168
7f323236 13169 com = community_str2com(comstr);
d62a17ae 13170 if (!com) {
7f323236 13171 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13172 return CMD_WARNING;
13173 }
13174
13175 ret = bgp_show(vty, bgp, afi, safi,
13176 (exact ? bgp_show_type_community_exact
13177 : bgp_show_type_community),
1e2ce4f1 13178 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13179 community_free(&com);
46c3ce83 13180
d62a17ae 13181 return ret;
718e3744 13182}
13183
d62a17ae 13184enum bgp_stats {
13185 BGP_STATS_MAXBITLEN = 0,
13186 BGP_STATS_RIB,
13187 BGP_STATS_PREFIXES,
13188 BGP_STATS_TOTPLEN,
13189 BGP_STATS_UNAGGREGATEABLE,
13190 BGP_STATS_MAX_AGGREGATEABLE,
13191 BGP_STATS_AGGREGATES,
13192 BGP_STATS_SPACE,
13193 BGP_STATS_ASPATH_COUNT,
13194 BGP_STATS_ASPATH_MAXHOPS,
13195 BGP_STATS_ASPATH_TOTHOPS,
13196 BGP_STATS_ASPATH_MAXSIZE,
13197 BGP_STATS_ASPATH_TOTSIZE,
13198 BGP_STATS_ASN_HIGHEST,
13199 BGP_STATS_MAX,
a636c635 13200};
2815e61f 13201
9ab0cf58 13202#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13203#define TABLE_STATS_IDX_JSON 1
13204
13205static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13206 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13207 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13208 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13209 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13210 "unaggregateablePrefixes"},
13211 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13212 "maximumAggregateablePrefixes"},
13213 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13214 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13215 [BGP_STATS_SPACE] = {"Address space advertised",
13216 "addressSpaceAdvertised"},
9ab0cf58
PG
13217 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13218 "advertisementsWithPaths"},
13219 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13220 "longestAsPath"},
13221 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13222 "largestAsPath"},
13223 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13224 "averageAsPathLengthHops"},
13225 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13226 "averageAsPathSizeBytes"},
13227 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13228 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13229};
2815e61f 13230
d62a17ae 13231struct bgp_table_stats {
13232 struct bgp_table *table;
13233 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13234
13235 unsigned long long
13236 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13237 1];
13238
8d0ab76d 13239 double total_space;
ff7924f6
PJ
13240};
13241
9bcb3eef 13242static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13243 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13244{
9bcb3eef 13245 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13246 struct bgp_path_info *pi;
b54892e0 13247 const struct prefix *rn_p;
d62a17ae 13248
9bcb3eef 13249 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13250 return;
d62a17ae 13251
9bcb3eef 13252 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13253 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13254 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13255
0747643e 13256 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13257 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13258 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13259 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13260
9bcb3eef 13261 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13262 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13263 /* announced address space */
13264 if (space)
b54892e0 13265 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13266 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13267 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13268
9c14ec72 13269
9bcb3eef 13270 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13271 ts->counts[BGP_STATS_RIB]++;
13272
05864da7
DS
13273 if (CHECK_FLAG(pi->attr->flag,
13274 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13275 ts->counts[BGP_STATS_AGGREGATES]++;
13276
13277 /* as-path stats */
05864da7 13278 if (pi->attr->aspath) {
9c14ec72
RW
13279 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13280 unsigned int size = aspath_size(pi->attr->aspath);
13281 as_t highest = aspath_highest(pi->attr->aspath);
13282
13283 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13284
13285 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13286 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13287
13288 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13289 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13290
13291 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13292 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13293 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13294 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13295 }
13296 }
13297}
13298
cc9f21da 13299static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13300{
9bcb3eef
DS
13301 struct bgp_dest *dest, *ndest;
13302 struct bgp_dest *top;
9c14ec72
RW
13303 struct bgp_table_stats *ts = THREAD_ARG(t);
13304 unsigned int space = 0;
13305
13306 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13307 return;
9c14ec72
RW
13308
13309 switch (ts->table->afi) {
13310 case AFI_IP:
13311 space = IPV4_MAX_BITLEN;
13312 break;
13313 case AFI_IP6:
13314 space = IPV6_MAX_BITLEN;
13315 break;
3ba7b4af
TA
13316 case AFI_L2VPN:
13317 space = EVPN_ROUTE_PREFIXLEN;
13318 break;
58cf0823
DS
13319 case AFI_UNSPEC:
13320 case AFI_MAX:
cc9f21da 13321 return;
9c14ec72
RW
13322 }
13323
13324 ts->counts[BGP_STATS_MAXBITLEN] = space;
13325
9bcb3eef 13326 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13327 if (ts->table->safi == SAFI_MPLS_VPN
13328 || ts->table->safi == SAFI_ENCAP
13329 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13330 struct bgp_table *table;
13331
9bcb3eef 13332 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13333 if (!table)
13334 continue;
13335
13336 top = bgp_table_top(table);
9bcb3eef
DS
13337 for (ndest = bgp_table_top(table); ndest;
13338 ndest = bgp_route_next(ndest))
13339 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13340 } else {
9bcb3eef 13341 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13342 }
13343 }
2815e61f 13344}
ff7924f6 13345
71f1613a
DA
13346static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13347 struct json_object *json_array)
13348{
13349 struct listnode *node, *nnode;
13350 struct bgp *bgp;
13351
13352 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13353 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13354}
13355
13356static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13357 safi_t safi, struct json_object *json_array)
2815e61f 13358{
d62a17ae 13359 struct bgp_table_stats ts;
13360 unsigned int i;
893cccd0
PG
13361 int ret = CMD_SUCCESS;
13362 char temp_buf[20];
6c9d22e2 13363 struct json_object *json = NULL;
0747643e
AQ
13364 uint32_t bitlen = 0;
13365 struct json_object *json_bitlen;
6c9d22e2
PG
13366
13367 if (json_array)
13368 json = json_object_new_object();
019386c2 13369
d62a17ae 13370 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13371 char warning_msg[50];
13372
13373 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13374 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13375 safi);
6c9d22e2
PG
13376
13377 if (!json)
893cccd0
PG
13378 vty_out(vty, "%s\n", warning_msg);
13379 else
9ab0cf58 13380 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13381
893cccd0
PG
13382 ret = CMD_WARNING;
13383 goto end_table_stats;
d62a17ae 13384 }
019386c2 13385
893cccd0 13386 if (!json)
5290ceab
DA
13387 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13388 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13389 else
13390 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13391
d62a17ae 13392 /* labeled-unicast routes live in the unicast table */
13393 if (safi == SAFI_LABELED_UNICAST)
13394 safi = SAFI_UNICAST;
019386c2 13395
d62a17ae 13396 memset(&ts, 0, sizeof(ts));
13397 ts.table = bgp->rib[afi][safi];
13398 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13399
d62a17ae 13400 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13401 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13402 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13403 continue;
13404
13405 switch (i) {
d62a17ae 13406 case BGP_STATS_ASPATH_TOTHOPS:
13407 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13408 if (!json) {
9ab0cf58
PG
13409 snprintf(
13410 temp_buf, sizeof(temp_buf), "%12.2f",
13411 ts.counts[i]
13412 ? (float)ts.counts[i]
13413 / (float)ts.counts
13414 [BGP_STATS_ASPATH_COUNT]
13415 : 0);
893cccd0 13416 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13417 table_stats_strs[i]
13418 [TABLE_STATS_IDX_VTY],
893cccd0 13419 temp_buf);
9ab0cf58
PG
13420 } else {
13421 json_object_double_add(
13422 json,
13423 table_stats_strs[i]
13424 [TABLE_STATS_IDX_JSON],
13425 ts.counts[i]
13426 ? (double)ts.counts[i]
13427 / (double)ts.counts
d62a17ae 13428 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13429 : 0);
13430 }
d62a17ae 13431 break;
13432 case BGP_STATS_TOTPLEN:
6c9d22e2 13433 if (!json) {
9ab0cf58
PG
13434 snprintf(
13435 temp_buf, sizeof(temp_buf), "%12.2f",
13436 ts.counts[i]
13437 ? (float)ts.counts[i]
13438 / (float)ts.counts
13439 [BGP_STATS_PREFIXES]
13440 : 0);
893cccd0 13441 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13442 table_stats_strs[i]
13443 [TABLE_STATS_IDX_VTY],
893cccd0 13444 temp_buf);
9ab0cf58
PG
13445 } else {
13446 json_object_double_add(
13447 json,
13448 table_stats_strs[i]
13449 [TABLE_STATS_IDX_JSON],
13450 ts.counts[i]
13451 ? (double)ts.counts[i]
13452 / (double)ts.counts
d62a17ae 13453 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13454 : 0);
13455 }
d62a17ae 13456 break;
13457 case BGP_STATS_SPACE:
6c9d22e2
PG
13458 if (!json) {
13459 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13460 ts.total_space);
893cccd0 13461 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13462 table_stats_strs[i]
13463 [TABLE_STATS_IDX_VTY],
893cccd0 13464 temp_buf);
9ab0cf58
PG
13465 } else {
13466 json_object_double_add(
13467 json,
13468 table_stats_strs[i]
13469 [TABLE_STATS_IDX_JSON],
13470 (double)ts.total_space);
13471 }
8d0ab76d 13472 if (afi == AFI_IP6) {
6c9d22e2
PG
13473 if (!json) {
13474 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13475 "%12g",
13476 ts.total_space
13477 * pow(2.0, -128 + 32));
6c9d22e2
PG
13478 vty_out(vty, "%30s: %s\n",
13479 "/32 equivalent %s\n",
13480 temp_buf);
9ab0cf58
PG
13481 } else {
13482 json_object_double_add(
13483 json, "/32equivalent",
13484 (double)(ts.total_space
13485 * pow(2.0,
13486 -128 + 32)));
13487 }
6c9d22e2
PG
13488 if (!json) {
13489 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13490 "%12g",
13491 ts.total_space
13492 * pow(2.0, -128 + 48));
6c9d22e2
PG
13493 vty_out(vty, "%30s: %s\n",
13494 "/48 equivalent %s\n",
13495 temp_buf);
9ab0cf58
PG
13496 } else {
13497 json_object_double_add(
13498 json, "/48equivalent",
13499 (double)(ts.total_space
13500 * pow(2.0,
13501 -128 + 48)));
13502 }
8d0ab76d 13503 } else {
6c9d22e2
PG
13504 if (!json) {
13505 snprintf(temp_buf, sizeof(temp_buf),
13506 "%12.2f",
9ab0cf58
PG
13507 ts.total_space * 100.
13508 * pow(2.0, -32));
6c9d22e2 13509 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13510 "% announced ", temp_buf);
13511 } else {
13512 json_object_double_add(
13513 json, "%announced",
13514 (double)(ts.total_space * 100.
13515 * pow(2.0, -32)));
13516 }
6c9d22e2
PG
13517 if (!json) {
13518 snprintf(temp_buf, sizeof(temp_buf),
13519 "%12.2f",
9ab0cf58
PG
13520 ts.total_space
13521 * pow(2.0, -32 + 8));
6c9d22e2
PG
13522 vty_out(vty, "%30s: %s\n",
13523 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13524 } else {
13525 json_object_double_add(
13526 json, "/8equivalent",
13527 (double)(ts.total_space
13528 * pow(2.0, -32 + 8)));
13529 }
6c9d22e2
PG
13530 if (!json) {
13531 snprintf(temp_buf, sizeof(temp_buf),
13532 "%12.2f",
9ab0cf58
PG
13533 ts.total_space
13534 * pow(2.0, -32 + 24));
6c9d22e2 13535 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13536 "/24 equivalent ", temp_buf);
13537 } else {
13538 json_object_double_add(
13539 json, "/24equivalent",
13540 (double)(ts.total_space
13541 * pow(2.0, -32 + 24)));
13542 }
8d0ab76d 13543 }
d62a17ae 13544 break;
13545 default:
6c9d22e2
PG
13546 if (!json) {
13547 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13548 ts.counts[i]);
893cccd0 13549 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13550 table_stats_strs[i]
13551 [TABLE_STATS_IDX_VTY],
13552 temp_buf);
13553 } else {
13554 json_object_int_add(
13555 json,
13556 table_stats_strs[i]
13557 [TABLE_STATS_IDX_JSON],
13558 ts.counts[i]);
13559 }
d62a17ae 13560 }
893cccd0
PG
13561 if (!json)
13562 vty_out(vty, "\n");
d62a17ae 13563 }
0747643e
AQ
13564
13565 switch (afi) {
13566 case AFI_IP:
13567 bitlen = IPV4_MAX_BITLEN;
13568 break;
13569 case AFI_IP6:
13570 bitlen = IPV6_MAX_BITLEN;
13571 break;
13572 case AFI_L2VPN:
13573 bitlen = EVPN_ROUTE_PREFIXLEN;
13574 break;
58cf0823
DS
13575 case AFI_UNSPEC:
13576 case AFI_MAX:
0747643e
AQ
13577 break;
13578 }
13579
13580 if (json) {
13581 json_bitlen = json_object_new_array();
13582
13583 for (i = 0; i <= bitlen; i++) {
13584 struct json_object *ind_bit = json_object_new_object();
13585
13586 if (!ts.prefix_len_count[i])
13587 continue;
13588
13589 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13590 json_object_int_add(ind_bit, temp_buf,
13591 ts.prefix_len_count[i]);
13592 json_object_array_add(json_bitlen, ind_bit);
13593 }
13594 json_object_object_add(json, "prefixLength", json_bitlen);
13595 }
13596
9ab0cf58 13597end_table_stats:
6c9d22e2
PG
13598 if (json)
13599 json_object_array_add(json_array, json);
893cccd0 13600 return ret;
d62a17ae 13601}
13602
71f1613a
DA
13603static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13604 safi_t safi, struct json_object *json_array)
13605{
13606 if (!bgp) {
13607 bgp_table_stats_all(vty, afi, safi, json_array);
13608 return CMD_SUCCESS;
13609 }
13610
13611 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13612}
13613
d62a17ae 13614enum bgp_pcounts {
13615 PCOUNT_ADJ_IN = 0,
13616 PCOUNT_DAMPED,
13617 PCOUNT_REMOVED,
13618 PCOUNT_HISTORY,
13619 PCOUNT_STALE,
13620 PCOUNT_VALID,
13621 PCOUNT_ALL,
13622 PCOUNT_COUNTED,
7e3d9632 13623 PCOUNT_BPATH_SELECTED,
d62a17ae 13624 PCOUNT_PFCNT, /* the figure we display to users */
13625 PCOUNT_MAX,
a636c635 13626};
718e3744 13627
2b64873d 13628static const char *const pcount_strs[] = {
9d303b37
DL
13629 [PCOUNT_ADJ_IN] = "Adj-in",
13630 [PCOUNT_DAMPED] = "Damped",
13631 [PCOUNT_REMOVED] = "Removed",
13632 [PCOUNT_HISTORY] = "History",
13633 [PCOUNT_STALE] = "Stale",
13634 [PCOUNT_VALID] = "Valid",
13635 [PCOUNT_ALL] = "All RIB",
13636 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13637 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13638 [PCOUNT_PFCNT] = "Useable",
13639 [PCOUNT_MAX] = NULL,
a636c635 13640};
718e3744 13641
d62a17ae 13642struct peer_pcounts {
13643 unsigned int count[PCOUNT_MAX];
13644 const struct peer *peer;
13645 const struct bgp_table *table;
54317cba 13646 safi_t safi;
a636c635 13647};
47fc97cc 13648
9bcb3eef 13649static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13650{
54317cba
JW
13651 const struct bgp_adj_in *ain;
13652 const struct bgp_path_info *pi;
d62a17ae 13653 const struct peer *peer = pc->peer;
13654
54317cba
JW
13655 for (ain = rn->adj_in; ain; ain = ain->next)
13656 if (ain->peer == peer)
13657 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13658
9bcb3eef 13659 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13660
54317cba
JW
13661 if (pi->peer != peer)
13662 continue;
d62a17ae 13663
54317cba 13664 pc->count[PCOUNT_ALL]++;
d62a17ae 13665
54317cba
JW
13666 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13667 pc->count[PCOUNT_DAMPED]++;
13668 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13669 pc->count[PCOUNT_HISTORY]++;
13670 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13671 pc->count[PCOUNT_REMOVED]++;
13672 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13673 pc->count[PCOUNT_STALE]++;
13674 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13675 pc->count[PCOUNT_VALID]++;
13676 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13677 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13678 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13679 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13680
13681 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13682 pc->count[PCOUNT_COUNTED]++;
13683 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13684 flog_err(
13685 EC_LIB_DEVELOPMENT,
13686 "Attempting to count but flags say it is unusable");
13687 } else {
40381db7 13688 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13689 flog_err(
13690 EC_LIB_DEVELOPMENT,
13691 "Not counted but flags say we should");
d62a17ae 13692 }
13693 }
54317cba
JW
13694}
13695
cc9f21da 13696static void bgp_peer_count_walker(struct thread *t)
54317cba 13697{
9bcb3eef 13698 struct bgp_dest *rn, *rm;
54317cba
JW
13699 const struct bgp_table *table;
13700 struct peer_pcounts *pc = THREAD_ARG(t);
13701
13702 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13703 || pc->safi == SAFI_EVPN) {
13704 /* Special handling for 2-level routing tables. */
13705 for (rn = bgp_table_top(pc->table); rn;
13706 rn = bgp_route_next(rn)) {
9bcb3eef 13707 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13708 if (table != NULL)
13709 for (rm = bgp_table_top(table); rm;
13710 rm = bgp_route_next(rm))
13711 bgp_peer_count_proc(rm, pc);
13712 }
13713 } else
13714 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13715 bgp_peer_count_proc(rn, pc);
718e3744 13716}
13717
d62a17ae 13718static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13719 safi_t safi, bool use_json)
856ca177 13720{
d62a17ae 13721 struct peer_pcounts pcounts = {.peer = peer};
13722 unsigned int i;
13723 json_object *json = NULL;
13724 json_object *json_loop = NULL;
856ca177 13725
d62a17ae 13726 if (use_json) {
13727 json = json_object_new_object();
13728 json_loop = json_object_new_object();
13729 }
718e3744 13730
d62a17ae 13731 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13732 || !peer->bgp->rib[afi][safi]) {
13733 if (use_json) {
13734 json_object_string_add(
13735 json, "warning",
13736 "No such neighbor or address family");
13737 vty_out(vty, "%s\n", json_object_to_json_string(json));
13738 json_object_free(json);
d5f20468 13739 json_object_free(json_loop);
d62a17ae 13740 } else
13741 vty_out(vty, "%% No such neighbor or address family\n");
13742
13743 return CMD_WARNING;
13744 }
2a71e9ce 13745
d62a17ae 13746 memset(&pcounts, 0, sizeof(pcounts));
13747 pcounts.peer = peer;
13748 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13749 pcounts.safi = safi;
d62a17ae 13750
13751 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13752 * stats for the thread-walk (i.e. ensure this can't be blamed on
13753 * on just vty_read()).
13754 */
d62a17ae 13755 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13756
13757 if (use_json) {
13758 json_object_string_add(json, "prefixCountsFor", peer->host);
13759 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13760 get_afi_safi_str(afi, safi, true));
d62a17ae 13761 json_object_int_add(json, "pfxCounter",
13762 peer->pcount[afi][safi]);
13763
13764 for (i = 0; i < PCOUNT_MAX; i++)
13765 json_object_int_add(json_loop, pcount_strs[i],
13766 pcounts.count[i]);
13767
13768 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13769
13770 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13771 json_object_string_add(json, "pfxctDriftFor",
13772 peer->host);
13773 json_object_string_add(
13774 json, "recommended",
13775 "Please report this bug, with the above command output");
13776 }
75eeda93 13777 vty_json(vty, json);
d62a17ae 13778 } else {
13779
13780 if (peer->hostname
892fedb6 13781 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13782 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13783 peer->hostname, peer->host,
5cb5f4d0 13784 get_afi_safi_str(afi, safi, false));
d62a17ae 13785 } else {
13786 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13787 get_afi_safi_str(afi, safi, false));
d62a17ae 13788 }
13789
6cde4b45 13790 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13791 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13792
13793 for (i = 0; i < PCOUNT_MAX; i++)
13794 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13795 pcounts.count[i]);
13796
13797 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13798 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13799 vty_out(vty,
13800 "Please report this bug, with the above command output\n");
13801 }
13802 }
13803
13804 return CMD_SUCCESS;
718e3744 13805}
13806
a636c635
DW
13807DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13808 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13809 "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 13810 SHOW_STR
13811 IP_STR
13812 BGP_STR
8386ac43 13813 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13814 BGP_AFI_HELP_STR
13815 BGP_SAFI_HELP_STR
0b16f239
DS
13816 "Detailed information on TCP and BGP neighbor connections\n"
13817 "Neighbor to display information about\n"
13818 "Neighbor to display information about\n"
91d37724 13819 "Neighbor on BGP configured interface\n"
a636c635 13820 "Display detailed prefix count information\n"
9973d184 13821 JSON_STR)
0b16f239 13822{
d62a17ae 13823 afi_t afi = AFI_IP6;
13824 safi_t safi = SAFI_UNICAST;
13825 struct peer *peer;
13826 int idx = 0;
13827 struct bgp *bgp = NULL;
9f049418
DS
13828 bool uj = use_json(argc, argv);
13829
13830 if (uj)
13831 argc--;
856ca177 13832
d62a17ae 13833 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13834 &bgp, uj);
d62a17ae 13835 if (!idx)
13836 return CMD_WARNING;
0b16f239 13837
d62a17ae 13838 argv_find(argv, argc, "neighbors", &idx);
13839 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13840 if (!peer)
13841 return CMD_WARNING;
bb46e94f 13842
29c8d9da 13843 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13844}
0b16f239 13845
d6902373
PG
13846#ifdef KEEP_OLD_VPN_COMMANDS
13847DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13848 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13849 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13850 SHOW_STR
13851 IP_STR
13852 BGP_STR
d6902373 13853 BGP_VPNVX_HELP_STR
91d37724 13854 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13855 "Detailed information on TCP and BGP neighbor connections\n"
13856 "Neighbor to display information about\n"
13857 "Neighbor to display information about\n"
91d37724 13858 "Neighbor on BGP configured interface\n"
a636c635 13859 "Display detailed prefix count information\n"
9973d184 13860 JSON_STR)
a636c635 13861{
d62a17ae 13862 int idx_peer = 6;
13863 struct peer *peer;
9f049418 13864 bool uj = use_json(argc, argv);
a636c635 13865
d62a17ae 13866 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13867 if (!peer)
13868 return CMD_WARNING;
13869
13870 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13871}
13872
d6902373
PG
13873DEFUN (show_ip_bgp_vpn_all_route_prefix,
13874 show_ip_bgp_vpn_all_route_prefix_cmd,
13875 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13876 SHOW_STR
13877 IP_STR
13878 BGP_STR
d6902373 13879 BGP_VPNVX_HELP_STR
91d37724
QY
13880 "Display information about all VPNv4 NLRIs\n"
13881 "Network in the BGP routing table to display\n"
3a2d747c 13882 "Network in the BGP routing table to display\n"
9973d184 13883 JSON_STR)
91d37724 13884{
d62a17ae 13885 int idx = 0;
13886 char *network = NULL;
13887 struct bgp *bgp = bgp_get_default();
13888 if (!bgp) {
13889 vty_out(vty, "Can't find default instance\n");
13890 return CMD_WARNING;
13891 }
87e34b58 13892
d62a17ae 13893 if (argv_find(argv, argc, "A.B.C.D", &idx))
13894 network = argv[idx]->arg;
13895 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13896 network = argv[idx]->arg;
13897 else {
13898 vty_out(vty, "Unable to figure out Network\n");
13899 return CMD_WARNING;
13900 }
87e34b58 13901
d62a17ae 13902 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13903 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13904 use_json(argc, argv));
91d37724 13905}
d6902373 13906#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13907
44c69747
LK
13908DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13909 show_bgp_l2vpn_evpn_route_prefix_cmd,
13910 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13911 SHOW_STR
4c63a661
PG
13912 BGP_STR
13913 L2VPN_HELP_STR
13914 EVPN_HELP_STR
44c69747
LK
13915 "Network in the BGP routing table to display\n"
13916 "Network in the BGP routing table to display\n"
4c63a661
PG
13917 "Network in the BGP routing table to display\n"
13918 "Network in the BGP routing table to display\n"
13919 JSON_STR)
13920{
d62a17ae 13921 int idx = 0;
13922 char *network = NULL;
44c69747 13923 int prefix_check = 0;
a636c635 13924
44c69747
LK
13925 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13926 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13927 network = argv[idx]->arg;
44c69747 13928 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13929 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13930 network = argv[idx]->arg;
44c69747
LK
13931 prefix_check = 1;
13932 } else {
d62a17ae 13933 vty_out(vty, "Unable to figure out Network\n");
13934 return CMD_WARNING;
13935 }
44c69747
LK
13936 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13937 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13938 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13939}
13940
114fc229 13941static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13942 struct bgp_table *table, int *header1,
13943 int *header2, json_object *json,
13944 json_object *json_scode,
e960b4ca
TA
13945 json_object *json_ocode, bool wide,
13946 bool detail)
2f9bc755
DS
13947{
13948 uint64_t version = table ? table->version : 0;
13949
13950 if (*header1) {
13951 if (json) {
13952 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13953 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13954 "%pI4", &peer->bgp->router_id);
2f9bc755 13955 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13956 peer->bgp->default_local_pref);
13957 json_object_int_add(json, "localAS",
13958 peer->change_local_as
13959 ? peer->change_local_as
13960 : peer->local_as);
2f9bc755
DS
13961 json_object_object_add(json, "bgpStatusCodes",
13962 json_scode);
13963 json_object_object_add(json, "bgpOriginCodes",
13964 json_ocode);
13965 } else {
13966 vty_out(vty,
23d0a753
DA
13967 "BGP table version is %" PRIu64
13968 ", local router ID is %pI4, vrf id ",
114fc229
DA
13969 version, &peer->bgp->router_id);
13970 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13971 vty_out(vty, "%s", VRFID_NONE_STR);
13972 else
114fc229 13973 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13974 vty_out(vty, "\n");
13975 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13976 peer->bgp->default_local_pref);
13977 vty_out(vty, "local AS %u\n",
13978 peer->change_local_as ? peer->change_local_as
13979 : peer->local_as);
e960b4ca
TA
13980 if (!detail) {
13981 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13982 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13983 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13984 vty_out(vty, BGP_SHOW_RPKI_HEADER);
13985 }
2f9bc755
DS
13986 }
13987 *header1 = 0;
13988 }
13989 if (*header2) {
e960b4ca 13990 if (!json && !detail)
2f9bc755
DS
13991 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13992 : BGP_SHOW_HEADER));
13993 *header2 = 0;
13994 }
13995}
13996
d9478df0
TA
13997static void
13998show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13999 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14000 const char *rmap_name, json_object *json, json_object *json_ar,
14001 json_object *json_scode, json_object *json_ocode,
96c81f66 14002 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
14003 const struct prefix *match, unsigned long *output_count,
14004 unsigned long *filtered_count)
d62a17ae 14005{
3880b4ec
TA
14006 struct bgp_adj_in *ain = NULL;
14007 struct bgp_adj_out *adj = NULL;
9bcb3eef 14008 struct bgp_dest *dest;
d62a17ae 14009 struct bgp *bgp;
d62a17ae 14010 struct attr attr;
14011 int ret;
14012 struct update_subgroup *subgrp;
3880b4ec 14013 struct peer_af *paf = NULL;
f99def61 14014 bool route_filtered;
e960b4ca 14015 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14016 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14017 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14018 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14019 || (safi == SAFI_EVPN))
14020 ? true
14021 : false;
e960b4ca
TA
14022 int display = 0;
14023 json_object *json_net = NULL;
a636c635 14024
d62a17ae 14025 bgp = peer->bgp;
a636c635 14026
3880b4ec
TA
14027 /* If the user supplied a prefix, look for a matching route instead
14028 * of walking the whole table.
14029 */
14030 if (match) {
14031 dest = bgp_node_match(table, match);
14032 if (!dest) {
14033 if (!use_json)
14034 vty_out(vty, "Network not in table\n");
14035 return;
14036 }
14037
14038 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14039
14040 if (rn_p->prefixlen != match->prefixlen) {
14041 if (!use_json)
14042 vty_out(vty, "Network not in table\n");
14043 bgp_dest_unlock_node(dest);
14044 return;
14045 }
14046
14047 if (type == bgp_show_adj_route_received ||
14048 type == bgp_show_adj_route_filtered) {
14049 for (ain = dest->adj_in; ain; ain = ain->next) {
14050 if (ain->peer == peer) {
14051 attr = *ain->attr;
14052 break;
14053 }
14054 }
14055 /* bail out if if adj_out is empty, or
14056 * if the prefix isn't in this peer's
14057 * adj_in
14058 */
14059 if (!ain || ain->peer != peer) {
14060 if (!use_json)
14061 vty_out(vty, "Network not in table\n");
14062 bgp_dest_unlock_node(dest);
14063 return;
14064 }
14065 } else if (type == bgp_show_adj_route_advertised) {
14066 bool peer_found = false;
14067
14068 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14069 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14070 if (paf->peer == peer && adj->attr) {
14071 attr = *adj->attr;
14072 peer_found = true;
14073 break;
14074 }
14075 }
14076 if (peer_found)
14077 break;
14078 }
14079 /* bail out if if adj_out is empty, or
14080 * if the prefix isn't in this peer's
14081 * adj_out
14082 */
14083 if (!paf || !peer_found) {
14084 if (!use_json)
14085 vty_out(vty, "Network not in table\n");
14086 bgp_dest_unlock_node(dest);
14087 return;
14088 }
14089 }
14090
14091 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14092 rmap_name);
14093
14094 if (ret != RMAP_DENY) {
14095 show_adj_route_header(vty, peer, table, header1,
14096 header2, json, json_scode,
14097 json_ocode, wide, detail);
14098
14099 if (use_json)
14100 json_net = json_object_new_object();
14101
14102 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14103 afi, safi, json_net,
14104 BGP_PATH_SHOW_ALL, &display,
14105 RPKI_NOT_BEING_USED);
14106 if (use_json)
14107 json_object_object_addf(json_ar, json_net,
14108 "%pFX", rn_p);
14109 (*output_count)++;
14110 } else
14111 (*filtered_count)++;
14112
14113 bgp_attr_flush(&attr);
14114 bgp_dest_unlock_node(dest);
14115 return;
14116 }
14117
14118
d62a17ae 14119 subgrp = peer_subgroup(peer, afi, safi);
14120
6392aaa6 14121 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14122 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14123 if (use_json) {
14124 json_object_int_add(json, "bgpTableVersion",
14125 table->version);
c949c771
DA
14126 json_object_string_addf(json, "bgpLocalRouterId",
14127 "%pI4", &bgp->router_id);
01eced22
AD
14128 json_object_int_add(json, "defaultLocPrf",
14129 bgp->default_local_pref);
114fc229
DA
14130 json_object_int_add(json, "localAS",
14131 peer->change_local_as
14132 ? peer->change_local_as
14133 : peer->local_as);
d62a17ae 14134 json_object_object_add(json, "bgpStatusCodes",
14135 json_scode);
14136 json_object_object_add(json, "bgpOriginCodes",
14137 json_ocode);
07d0c4ed
DA
14138 json_object_string_add(
14139 json, "bgpOriginatingDefaultNetwork",
14140 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14141 } else {
23d0a753
DA
14142 vty_out(vty,
14143 "BGP table version is %" PRIu64
14144 ", local router ID is %pI4, vrf id ",
14145 table->version, &bgp->router_id);
9df8b37c
PZ
14146 if (bgp->vrf_id == VRF_UNKNOWN)
14147 vty_out(vty, "%s", VRFID_NONE_STR);
14148 else
14149 vty_out(vty, "%u", bgp->vrf_id);
14150 vty_out(vty, "\n");
01eced22
AD
14151 vty_out(vty, "Default local pref %u, ",
14152 bgp->default_local_pref);
114fc229
DA
14153 vty_out(vty, "local AS %u\n",
14154 peer->change_local_as ? peer->change_local_as
14155 : peer->local_as);
e960b4ca
TA
14156 if (!detail) {
14157 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14158 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14159 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14160 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14161 }
d62a17ae 14162
07d0c4ed
DA
14163 vty_out(vty, "Originating default network %s\n\n",
14164 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14165 }
65565c9a 14166 (*output_count)++;
d9478df0 14167 *header1 = 0;
d62a17ae 14168 }
a636c635 14169
9bcb3eef 14170 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14171 if (type == bgp_show_adj_route_received
14172 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14173 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14174 if (ain->peer != peer)
ea47320b 14175 continue;
6392aaa6 14176
114fc229 14177 show_adj_route_header(vty, peer, table, header1,
d9478df0 14178 header2, json, json_scode,
e960b4ca 14179 json_ocode, wide, detail);
d9478df0
TA
14180
14181 if ((safi == SAFI_MPLS_VPN)
14182 || (safi == SAFI_ENCAP)
14183 || (safi == SAFI_EVPN)) {
14184 if (use_json)
14185 json_object_string_add(
14186 json_ar, "rd", rd_str);
14187 else if (show_rd && rd_str) {
14188 vty_out(vty,
14189 "Route Distinguisher: %s\n",
14190 rd_str);
14191 show_rd = false;
14192 }
14193 }
6392aaa6 14194
6f4f49b2 14195 attr = *ain->attr;
f99def61
AD
14196 route_filtered = false;
14197
14198 /* Filter prefix using distribute list,
14199 * filter list or prefix list
14200 */
b54892e0 14201 const struct prefix *rn_p =
9bcb3eef 14202 bgp_dest_get_prefix(dest);
b54892e0
DS
14203 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14204 safi))
14205 == FILTER_DENY)
f99def61
AD
14206 route_filtered = true;
14207
14208 /* Filter prefix using route-map */
b54892e0
DS
14209 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14210 safi, rmap_name, NULL,
14211 0, NULL);
6392aaa6 14212
13c8e163
AD
14213 if (type == bgp_show_adj_route_filtered &&
14214 !route_filtered && ret != RMAP_DENY) {
d498917e 14215 bgp_attr_flush(&attr);
6392aaa6 14216 continue;
d62a17ae 14217 }
6392aaa6 14218
d9478df0
TA
14219 if (type == bgp_show_adj_route_received
14220 && (route_filtered || ret == RMAP_DENY))
14221 (*filtered_count)++;
6392aaa6 14222
e960b4ca
TA
14223 if (detail) {
14224 if (use_json)
14225 json_net =
14226 json_object_new_object();
14227 bgp_show_path_info(
14228 NULL /* prefix_rd */, dest, vty,
14229 bgp, afi, safi, json_net,
14230 BGP_PATH_SHOW_ALL, &display,
14231 RPKI_NOT_BEING_USED);
14232 if (use_json)
14233 json_object_object_addf(
14234 json_ar, json_net,
14235 "%pFX", rn_p);
14236 } else
14237 route_vty_out_tmp(vty, dest, rn_p,
14238 &attr, safi, use_json,
14239 json_ar, wide);
d498917e 14240 bgp_attr_flush(&attr);
d9478df0 14241 (*output_count)++;
d62a17ae 14242 }
6392aaa6 14243 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14244 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14245 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14246 if (paf->peer != peer || !adj->attr)
924c3f6a 14247 continue;
d62a17ae 14248
e960b4ca
TA
14249 show_adj_route_header(
14250 vty, peer, table, header1,
14251 header2, json, json_scode,
14252 json_ocode, wide, detail);
d62a17ae 14253
b54892e0 14254 const struct prefix *rn_p =
9bcb3eef 14255 bgp_dest_get_prefix(dest);
b54892e0 14256
6f4f49b2 14257 attr = *adj->attr;
b755861b 14258 ret = bgp_output_modifier(
b54892e0 14259 peer, rn_p, &attr, afi, safi,
b755861b 14260 rmap_name);
f46d8e1e 14261
b755861b 14262 if (ret != RMAP_DENY) {
d9478df0
TA
14263 if ((safi == SAFI_MPLS_VPN)
14264 || (safi == SAFI_ENCAP)
14265 || (safi == SAFI_EVPN)) {
14266 if (use_json)
14267 json_object_string_add(
14268 json_ar,
14269 "rd",
14270 rd_str);
14271 else if (show_rd
14272 && rd_str) {
14273 vty_out(vty,
14274 "Route Distinguisher: %s\n",
14275 rd_str);
14276 show_rd = false;
14277 }
14278 }
e960b4ca
TA
14279 if (detail) {
14280 if (use_json)
14281 json_net =
14282 json_object_new_object();
14283 bgp_show_path_info(
14284 NULL /* prefix_rd
14285 */
14286 ,
14287 dest, vty, bgp,
14288 afi, safi,
14289 json_net,
14290 BGP_PATH_SHOW_ALL,
14291 &display,
14292 RPKI_NOT_BEING_USED);
14293 if (use_json)
14294 json_object_object_addf(
14295 json_ar,
14296 json_net,
14297 "%pFX",
14298 rn_p);
14299 } else
14300 route_vty_out_tmp(
14301 vty, dest, rn_p,
14302 &attr, safi,
14303 use_json,
14304 json_ar, wide);
d9478df0 14305 (*output_count)++;
b755861b 14306 } else {
d9478df0 14307 (*filtered_count)++;
a2addae8 14308 }
b755861b 14309
d498917e 14310 bgp_attr_flush(&attr);
924c3f6a 14311 }
f20ce998
DS
14312 } else if (type == bgp_show_adj_route_bestpath) {
14313 struct bgp_path_info *pi;
14314
114fc229
DA
14315 show_adj_route_header(vty, peer, table, header1,
14316 header2, json, json_scode,
e960b4ca 14317 json_ocode, wide, detail);
f20ce998 14318
aa9bf57e
TA
14319 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14320
f20ce998
DS
14321 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14322 pi = pi->next) {
14323 if (pi->peer != peer)
14324 continue;
14325
14326 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14327 continue;
14328
aa9bf57e
TA
14329 if (detail) {
14330 if (use_json)
14331 json_net =
14332 json_object_new_object();
14333 bgp_show_path_info(
14334 NULL /* prefix_rd */, dest, vty,
14335 bgp, afi, safi, json_net,
14336 BGP_PATH_SHOW_BESTPATH,
14337 &display, RPKI_NOT_BEING_USED);
14338 if (use_json)
14339 json_object_object_addf(
14340 json_ar, json_net,
14341 "%pFX", rn_p);
14342 } else
14343 route_vty_out_tmp(
14344 vty, dest, rn_p, pi->attr, safi,
14345 use_json, json_ar, wide);
d9478df0 14346 (*output_count)++;
f20ce998 14347 }
d62a17ae 14348 }
14349 }
a636c635 14350}
2a71e9ce 14351
d62a17ae 14352static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14353 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14354 const char *rmap_name, const struct prefix *match,
14355 uint16_t show_flags)
0b16f239 14356{
d9478df0
TA
14357 struct bgp *bgp;
14358 struct bgp_table *table;
d62a17ae 14359 json_object *json = NULL;
d9478df0
TA
14360 json_object *json_scode = NULL;
14361 json_object *json_ocode = NULL;
14362 json_object *json_ar = NULL;
96f3485c 14363 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14364
d9478df0
TA
14365 /* Init BGP headers here so they're only displayed once
14366 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14367 */
14368 int header1 = 1;
14369 int header2 = 1;
14370
14371 /*
14372 * Initialize variables for each RD
14373 * All prefixes under an RD is aggregated within "json_routes"
14374 */
14375 char rd_str[BUFSIZ] = {0};
14376 json_object *json_routes = NULL;
14377
14378
14379 /* For 2-tier tables, prefix counts need to be
14380 * maintained across multiple runs of show_adj_route()
14381 */
14382 unsigned long output_count_per_rd;
14383 unsigned long filtered_count_per_rd;
14384 unsigned long output_count = 0;
14385 unsigned long filtered_count = 0;
14386
14387 if (use_json) {
d62a17ae 14388 json = json_object_new_object();
d9478df0
TA
14389 json_ar = json_object_new_object();
14390 json_scode = json_object_new_object();
14391 json_ocode = json_object_new_object();
dd426a51
DA
14392#if CONFDATE > 20231208
14393CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14394#endif
d9478df0
TA
14395 json_object_string_add(json_scode, "suppressed", "s");
14396 json_object_string_add(json_scode, "damped", "d");
14397 json_object_string_add(json_scode, "history", "h");
14398 json_object_string_add(json_scode, "valid", "*");
14399 json_object_string_add(json_scode, "best", ">");
14400 json_object_string_add(json_scode, "multipath", "=");
14401 json_object_string_add(json_scode, "internal", "i");
14402 json_object_string_add(json_scode, "ribFailure", "r");
14403 json_object_string_add(json_scode, "stale", "S");
14404 json_object_string_add(json_scode, "removed", "R");
14405
dd426a51
DA
14406#if CONFDATE > 20231208
14407CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14408#endif
d9478df0
TA
14409 json_object_string_add(json_ocode, "igp", "i");
14410 json_object_string_add(json_ocode, "egp", "e");
14411 json_object_string_add(json_ocode, "incomplete", "?");
14412 }
0b16f239 14413
d62a17ae 14414 if (!peer || !peer->afc[afi][safi]) {
14415 if (use_json) {
14416 json_object_string_add(
14417 json, "warning",
14418 "No such neighbor or address family");
14419 vty_out(vty, "%s\n", json_object_to_json_string(json));
14420 json_object_free(json);
690c3134
MW
14421 json_object_free(json_ar);
14422 json_object_free(json_scode);
14423 json_object_free(json_ocode);
d62a17ae 14424 } else
14425 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14426
d62a17ae 14427 return CMD_WARNING;
14428 }
14429
6392aaa6
PM
14430 if ((type == bgp_show_adj_route_received
14431 || type == bgp_show_adj_route_filtered)
d62a17ae 14432 && !CHECK_FLAG(peer->af_flags[afi][safi],
14433 PEER_FLAG_SOFT_RECONFIG)) {
14434 if (use_json) {
14435 json_object_string_add(
14436 json, "warning",
14437 "Inbound soft reconfiguration not enabled");
14438 vty_out(vty, "%s\n", json_object_to_json_string(json));
14439 json_object_free(json);
690c3134
MW
14440 json_object_free(json_ar);
14441 json_object_free(json_scode);
14442 json_object_free(json_ocode);
d62a17ae 14443 } else
14444 vty_out(vty,
14445 "%% Inbound soft reconfiguration not enabled\n");
14446
14447 return CMD_WARNING;
14448 }
0b16f239 14449
d9478df0
TA
14450 bgp = peer->bgp;
14451
14452 /* labeled-unicast routes live in the unicast table */
14453 if (safi == SAFI_LABELED_UNICAST)
14454 table = bgp->rib[afi][SAFI_UNICAST];
14455 else
14456 table = bgp->rib[afi][safi];
14457
14458 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14459 || (safi == SAFI_EVPN)) {
14460
14461 struct bgp_dest *dest;
14462
14463 for (dest = bgp_table_top(table); dest;
14464 dest = bgp_route_next(dest)) {
14465 table = bgp_dest_get_bgp_table_info(dest);
14466 if (!table)
14467 continue;
14468
14469 output_count_per_rd = 0;
14470 filtered_count_per_rd = 0;
14471
14472 if (use_json)
14473 json_routes = json_object_new_object();
14474
14475 const struct prefix_rd *prd;
14476 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14477 dest);
14478
4a8cd6ad
PG
14479 prefix_rd2str(prd, rd_str, sizeof(rd_str),
14480 bgp->asnotation);
d9478df0 14481
3880b4ec
TA
14482 show_adj_route(
14483 vty, peer, table, afi, safi, type, rmap_name,
14484 json, json_routes, json_scode, json_ocode,
14485 show_flags, &header1, &header2, rd_str, match,
14486 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14487
14488 /* Don't include an empty RD in the output! */
14489 if (json_routes && (output_count_per_rd > 0))
14490 json_object_object_add(json_ar, rd_str,
14491 json_routes);
14492
14493 output_count += output_count_per_rd;
14494 filtered_count += filtered_count_per_rd;
14495 }
14496 } else
14497 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14498 json, json_ar, json_scode, json_ocode,
3880b4ec 14499 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14500 &output_count, &filtered_count);
14501
14502 if (use_json) {
c1984955
TA
14503 if (type == bgp_show_adj_route_advertised)
14504 json_object_object_add(json, "advertisedRoutes",
14505 json_ar);
14506 else
14507 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14508 json_object_int_add(json, "totalPrefixCounter", output_count);
14509 json_object_int_add(json, "filteredPrefixCounter",
14510 filtered_count);
14511
690c3134
MW
14512 /*
14513 * These fields only give up ownership to `json` when `header1`
14514 * is used (set to zero). See code in `show_adj_route` and
14515 * `show_adj_route_header`.
14516 */
14517 if (header1 == 1) {
d9478df0
TA
14518 json_object_free(json_scode);
14519 json_object_free(json_ocode);
14520 }
14521
75eeda93 14522 vty_json(vty, json);
d9478df0 14523 } else if (output_count > 0) {
3880b4ec 14524 if (!match && filtered_count > 0)
d9478df0
TA
14525 vty_out(vty,
14526 "\nTotal number of prefixes %ld (%ld filtered)\n",
14527 output_count, filtered_count);
14528 else
14529 vty_out(vty, "\nTotal number of prefixes %ld\n",
14530 output_count);
14531 }
0b16f239 14532
d62a17ae 14533 return CMD_SUCCESS;
a636c635 14534}
50ef26d4 14535
f20ce998
DS
14536DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14537 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14538 "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
14539 SHOW_STR
14540 IP_STR
14541 BGP_STR
14542 BGP_INSTANCE_HELP_STR
14543 BGP_AFI_HELP_STR
14544 BGP_SAFI_WITH_LABEL_HELP_STR
14545 "Detailed information on TCP and BGP neighbor connections\n"
14546 "Neighbor to display information about\n"
14547 "Neighbor to display information about\n"
14548 "Neighbor on BGP configured interface\n"
14549 "Display the routes selected by best path\n"
aa9bf57e 14550 "Display detailed version of routes\n"
f20ce998
DS
14551 JSON_STR
14552 "Increase table width for longer prefixes\n")
14553{
14554 afi_t afi = AFI_IP6;
14555 safi_t safi = SAFI_UNICAST;
14556 char *rmap_name = NULL;
14557 char *peerstr = NULL;
14558 struct bgp *bgp = NULL;
14559 struct peer *peer;
14560 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14561 int idx = 0;
96c81f66 14562 uint16_t show_flags = 0;
96f3485c 14563
aa9bf57e
TA
14564 if (detail)
14565 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14566
96f3485c
MK
14567 if (uj)
14568 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14569
14570 if (wide)
14571 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14572
14573 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14574 &bgp, uj);
14575
14576 if (!idx)
14577 return CMD_WARNING;
14578
14579 argv_find(argv, argc, "neighbors", &idx);
14580 peerstr = argv[++idx]->arg;
14581
14582 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14583 if (!peer)
14584 return CMD_WARNING;
14585
3880b4ec 14586 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14587 show_flags);
f20ce998
DS
14588}
14589
e960b4ca
TA
14590DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14591 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14592 "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
14593 SHOW_STR
14594 IP_STR
14595 BGP_STR
14596 BGP_INSTANCE_HELP_STR
14597 BGP_AFI_HELP_STR
14598 BGP_SAFI_WITH_LABEL_HELP_STR
14599 "Display the entries for all address families\n"
14600 "Detailed information on TCP and BGP neighbor connections\n"
14601 "Neighbor to display information about\n"
14602 "Neighbor to display information about\n"
14603 "Neighbor on BGP configured interface\n"
14604 "Display the routes advertised to a BGP neighbor\n"
14605 "Display the received routes from neighbor\n"
14606 "Display the filtered routes received from neighbor\n"
14607 "Route-map to modify the attributes\n"
14608 "Name of the route map\n"
3880b4ec
TA
14609 "IPv4 prefix\n"
14610 "IPv6 prefix\n"
e960b4ca
TA
14611 "Display detailed version of routes\n"
14612 JSON_STR
14613 "Increase table width for longer prefixes\n")
718e3744 14614{
d62a17ae 14615 afi_t afi = AFI_IP6;
14616 safi_t safi = SAFI_UNICAST;
d62a17ae 14617 char *peerstr = NULL;
d62a17ae 14618 struct bgp *bgp = NULL;
14619 struct peer *peer;
6392aaa6 14620 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14621 int idx = 0;
96f3485c 14622 bool first = true;
96c81f66 14623 uint16_t show_flags = 0;
75ce3b14
DA
14624 struct listnode *node;
14625 struct bgp *abgp;
6392aaa6 14626
3880b4ec 14627 if (detail || prefix_str)
e960b4ca
TA
14628 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14629
96f3485c 14630 if (uj) {
d62a17ae 14631 argc--;
96f3485c
MK
14632 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14633 }
14634
14635 if (all) {
14636 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14637 if (argv_find(argv, argc, "ipv4", &idx))
14638 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14639
14640 if (argv_find(argv, argc, "ipv6", &idx))
14641 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14642 }
14643
14644 if (wide)
14645 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14646
9f049418
DS
14647 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14648 &bgp, uj);
14649 if (!idx)
14650 return CMD_WARNING;
14651
d62a17ae 14652 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14653 argv_find(argv, argc, "neighbors", &idx);
14654 peerstr = argv[++idx]->arg;
8c3deaae 14655
d62a17ae 14656 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14657 if (!peer)
14658 return CMD_WARNING;
856ca177 14659
d62a17ae 14660 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14661 type = bgp_show_adj_route_advertised;
14662 else if (argv_find(argv, argc, "received-routes", &idx))
14663 type = bgp_show_adj_route_received;
14664 else if (argv_find(argv, argc, "filtered-routes", &idx))
14665 type = bgp_show_adj_route_filtered;
14666
96f3485c 14667 if (!all)
70dd370f 14668 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14669 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14670 if (uj)
14671 vty_out(vty, "{\n");
14672
14673 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14674 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14675 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14676 : AFI_IP6;
75ce3b14
DA
14677 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14678 FOREACH_SAFI (safi) {
14679 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14680 continue;
96f3485c 14681
75ce3b14
DA
14682 if (uj) {
14683 if (first)
14684 first = false;
14685 else
14686 vty_out(vty, ",\n");
14687 vty_out(vty, "\"%s\":",
14688 get_afi_safi_str(afi, safi,
14689 true));
14690 } else
14691 vty_out(vty,
14692 "\nFor address family: %s\n",
14693 get_afi_safi_str(afi, safi,
14694 false));
96f3485c 14695
75ce3b14 14696 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14697 route_map, prefix, show_flags);
75ce3b14 14698 }
96f3485c
MK
14699 }
14700 } else {
75ce3b14
DA
14701 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14702 FOREACH_AFI_SAFI (afi, safi) {
14703 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14704 continue;
96f3485c 14705
75ce3b14
DA
14706 if (uj) {
14707 if (first)
14708 first = false;
14709 else
14710 vty_out(vty, ",\n");
14711 vty_out(vty, "\"%s\":",
14712 get_afi_safi_str(afi, safi,
14713 true));
14714 } else
14715 vty_out(vty,
14716 "\nFor address family: %s\n",
14717 get_afi_safi_str(afi, safi,
14718 false));
96f3485c 14719
75ce3b14 14720 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14721 route_map, prefix, show_flags);
75ce3b14 14722 }
96f3485c
MK
14723 }
14724 }
14725 if (uj)
14726 vty_out(vty, "}\n");
14727
14728 return CMD_SUCCESS;
95cbbd2a
ML
14729}
14730
718e3744 14731DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14732 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14733 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14734 SHOW_STR
14735 IP_STR
14736 BGP_STR
d3120452 14737 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14738 BGP_AF_STR
14739 BGP_AF_STR
14740 BGP_AF_MODIFIER_STR
718e3744 14741 "Detailed information on TCP and BGP neighbor connections\n"
14742 "Neighbor to display information about\n"
14743 "Neighbor to display information about\n"
91d37724 14744 "Neighbor on BGP configured interface\n"
718e3744 14745 "Display information received from a BGP neighbor\n"
856ca177 14746 "Display the prefixlist filter\n"
9973d184 14747 JSON_STR)
718e3744 14748{
d62a17ae 14749 afi_t afi = AFI_IP6;
14750 safi_t safi = SAFI_UNICAST;
14751 char *peerstr = NULL;
d62a17ae 14752 char name[BUFSIZ];
d62a17ae 14753 struct peer *peer;
d3120452 14754 int count;
d62a17ae 14755 int idx = 0;
d3120452
IR
14756 struct bgp *bgp = NULL;
14757 bool uj = use_json(argc, argv);
14758
14759 if (uj)
14760 argc--;
14761
14762 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14763 &bgp, uj);
14764 if (!idx)
14765 return CMD_WARNING;
d62a17ae 14766
d62a17ae 14767 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14768 argv_find(argv, argc, "neighbors", &idx);
14769 peerstr = argv[++idx]->arg;
14770
d3120452
IR
14771 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14772 if (!peer)
14773 return CMD_WARNING;
718e3744 14774
4ced1a2c 14775 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14776 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14777 if (count) {
14778 if (!uj)
14779 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14780 get_afi_safi_str(afi, safi, false));
d62a17ae 14781 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14782 } else {
14783 if (uj)
14784 vty_out(vty, "{}\n");
14785 else
14786 vty_out(vty, "No functional output\n");
14787 }
718e3744 14788
d62a17ae 14789 return CMD_SUCCESS;
14790}
14791
14792static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14793 afi_t afi, safi_t safi,
9f049418 14794 enum bgp_show_type type, bool use_json)
d62a17ae 14795{
96c81f66 14796 uint16_t show_flags = 0;
96f3485c
MK
14797
14798 if (use_json)
14799 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14800
d62a17ae 14801 if (!peer || !peer->afc[afi][safi]) {
14802 if (use_json) {
14803 json_object *json_no = NULL;
14804 json_no = json_object_new_object();
14805 json_object_string_add(
14806 json_no, "warning",
14807 "No such neighbor or address family");
14808 vty_out(vty, "%s\n",
14809 json_object_to_json_string(json_no));
14810 json_object_free(json_no);
14811 } else
14812 vty_out(vty, "%% No such neighbor or address family\n");
14813 return CMD_WARNING;
14814 }
47fc97cc 14815
7daf25a3
TA
14816 /* labeled-unicast routes live in the unicast table */
14817 if (safi == SAFI_LABELED_UNICAST)
14818 safi = SAFI_UNICAST;
14819
1e2ce4f1
DS
14820 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14821 RPKI_NOT_BEING_USED);
718e3744 14822}
14823
dba3c1d3
PG
14824DEFUN (show_ip_bgp_flowspec_routes_detailed,
14825 show_ip_bgp_flowspec_routes_detailed_cmd,
14826 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14827 SHOW_STR
14828 IP_STR
14829 BGP_STR
14830 BGP_INSTANCE_HELP_STR
14831 BGP_AFI_HELP_STR
14832 "SAFI Flowspec\n"
14833 "Detailed information on flowspec entries\n"
14834 JSON_STR)
14835{
458c1475 14836 afi_t afi = AFI_IP6;
dba3c1d3
PG
14837 safi_t safi = SAFI_UNICAST;
14838 struct bgp *bgp = NULL;
14839 int idx = 0;
9f049418 14840 bool uj = use_json(argc, argv);
81dcd881 14841 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14842
96f3485c 14843 if (uj) {
9f049418 14844 argc--;
96f3485c
MK
14845 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14846 }
dba3c1d3
PG
14847
14848 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14849 &bgp, uj);
dba3c1d3
PG
14850 if (!idx)
14851 return CMD_WARNING;
14852
96f3485c 14853 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14854 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14855}
14856
718e3744 14857DEFUN (show_ip_bgp_neighbor_routes,
14858 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14859 "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 14860 SHOW_STR
14861 IP_STR
14862 BGP_STR
8386ac43 14863 BGP_INSTANCE_HELP_STR
4f280b15 14864 BGP_AFI_HELP_STR
4dd6177e 14865 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14866 "Detailed information on TCP and BGP neighbor connections\n"
14867 "Neighbor to display information about\n"
14868 "Neighbor to display information about\n"
91d37724 14869 "Neighbor on BGP configured interface\n"
2525cf39 14870 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14871 "Display the dampened routes received from neighbor\n"
14872 "Display routes learned from neighbor\n"
9973d184 14873 JSON_STR)
718e3744 14874{
d62a17ae 14875 char *peerstr = NULL;
14876 struct bgp *bgp = NULL;
14877 afi_t afi = AFI_IP6;
14878 safi_t safi = SAFI_UNICAST;
14879 struct peer *peer;
14880 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14881 int idx = 0;
9f049418
DS
14882 bool uj = use_json(argc, argv);
14883
14884 if (uj)
14885 argc--;
bb46e94f 14886
d62a17ae 14887 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14888 &bgp, uj);
d62a17ae 14889 if (!idx)
14890 return CMD_WARNING;
c493f2d8 14891
d62a17ae 14892 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14893 argv_find(argv, argc, "neighbors", &idx);
14894 peerstr = argv[++idx]->arg;
8c3deaae 14895
d62a17ae 14896 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14897 if (!peer)
d62a17ae 14898 return CMD_WARNING;
bb46e94f 14899
d62a17ae 14900 if (argv_find(argv, argc, "flap-statistics", &idx))
14901 sh_type = bgp_show_type_flap_neighbor;
14902 else if (argv_find(argv, argc, "dampened-routes", &idx))
14903 sh_type = bgp_show_type_damp_neighbor;
14904 else if (argv_find(argv, argc, "routes", &idx))
14905 sh_type = bgp_show_type_neighbor;
2525cf39 14906
d62a17ae 14907 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14908}
6b0655a2 14909
734b349e 14910struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14911
d62a17ae 14912struct bgp_distance {
14913 /* Distance value for the IP source prefix. */
d7c0a89a 14914 uint8_t distance;
718e3744 14915
d62a17ae 14916 /* Name of the access-list to be matched. */
14917 char *access_list;
718e3744 14918};
14919
4f280b15
LB
14920DEFUN (show_bgp_afi_vpn_rd_route,
14921 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14922 "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
14923 SHOW_STR
14924 BGP_STR
14925 BGP_AFI_HELP_STR
00e6edb9 14926 BGP_AF_MODIFIER_STR
4f280b15
LB
14927 "Display information for a route distinguisher\n"
14928 "Route Distinguisher\n"
a111dd97 14929 "All Route Distinguishers\n"
7395a2c9
DS
14930 "Network in the BGP routing table to display\n"
14931 "Network in the BGP routing table to display\n"
14932 JSON_STR)
4f280b15 14933{
d62a17ae 14934 int ret;
14935 struct prefix_rd prd;
14936 afi_t afi = AFI_MAX;
14937 int idx = 0;
4f280b15 14938
ff6566f3
DS
14939 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14940 vty_out(vty, "%% Malformed Address Family\n");
14941 return CMD_WARNING;
14942 }
14943
a111dd97
TA
14944 if (!strcmp(argv[5]->arg, "all"))
14945 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14946 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14947 RPKI_NOT_BEING_USED,
14948 use_json(argc, argv));
14949
d62a17ae 14950 ret = str2prefix_rd(argv[5]->arg, &prd);
14951 if (!ret) {
14952 vty_out(vty, "%% Malformed Route Distinguisher\n");
14953 return CMD_WARNING;
14954 }
ff6566f3 14955
d62a17ae 14956 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14957 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14958 use_json(argc, argv));
4f280b15
LB
14959}
14960
d62a17ae 14961static struct bgp_distance *bgp_distance_new(void)
718e3744 14962{
d62a17ae 14963 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14964}
14965
d62a17ae 14966static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14967{
d62a17ae 14968 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14969}
14970
585f1adc
IR
14971static int bgp_distance_set(struct vty *vty, const char *distance_str,
14972 const char *ip_str, const char *access_list_str)
718e3744 14973{
d62a17ae 14974 int ret;
585f1adc
IR
14975 afi_t afi;
14976 safi_t safi;
d62a17ae 14977 struct prefix p;
585f1adc 14978 uint8_t distance;
9bcb3eef 14979 struct bgp_dest *dest;
d62a17ae 14980 struct bgp_distance *bdistance;
718e3744 14981
585f1adc
IR
14982 afi = bgp_node_afi(vty);
14983 safi = bgp_node_safi(vty);
14984
d62a17ae 14985 ret = str2prefix(ip_str, &p);
14986 if (ret == 0) {
585f1adc 14987 vty_out(vty, "Malformed prefix\n");
d62a17ae 14988 return CMD_WARNING_CONFIG_FAILED;
14989 }
718e3744 14990
585f1adc
IR
14991 distance = atoi(distance_str);
14992
d62a17ae 14993 /* Get BGP distance node. */
9bcb3eef
DS
14994 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14995 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14996 if (bdistance)
9bcb3eef 14997 bgp_dest_unlock_node(dest);
ca2e160d 14998 else {
d62a17ae 14999 bdistance = bgp_distance_new();
9bcb3eef 15000 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 15001 }
718e3744 15002
d62a17ae 15003 /* Set distance value. */
15004 bdistance->distance = distance;
718e3744 15005
d62a17ae 15006 /* Reset access-list configuration. */
e1b36e13 15007 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15008 if (access_list_str)
15009 bdistance->access_list =
15010 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15011
d62a17ae 15012 return CMD_SUCCESS;
718e3744 15013}
15014
585f1adc
IR
15015static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15016 const char *ip_str, const char *access_list_str)
718e3744 15017{
d62a17ae 15018 int ret;
585f1adc
IR
15019 afi_t afi;
15020 safi_t safi;
d62a17ae 15021 struct prefix p;
585f1adc 15022 int distance;
9bcb3eef 15023 struct bgp_dest *dest;
d62a17ae 15024 struct bgp_distance *bdistance;
718e3744 15025
585f1adc
IR
15026 afi = bgp_node_afi(vty);
15027 safi = bgp_node_safi(vty);
15028
d62a17ae 15029 ret = str2prefix(ip_str, &p);
15030 if (ret == 0) {
585f1adc 15031 vty_out(vty, "Malformed prefix\n");
d62a17ae 15032 return CMD_WARNING_CONFIG_FAILED;
15033 }
718e3744 15034
9bcb3eef
DS
15035 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15036 if (!dest) {
585f1adc 15037 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15038 return CMD_WARNING_CONFIG_FAILED;
15039 }
718e3744 15040
9bcb3eef 15041 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15042 distance = atoi(distance_str);
1f9a9fff 15043
d62a17ae 15044 if (bdistance->distance != distance) {
585f1adc 15045 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15046 bgp_dest_unlock_node(dest);
d62a17ae 15047 return CMD_WARNING_CONFIG_FAILED;
15048 }
718e3744 15049
0a22ddfb 15050 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15051 bgp_distance_free(bdistance);
718e3744 15052
9bcb3eef
DS
15053 bgp_dest_set_bgp_path_info(dest, NULL);
15054 bgp_dest_unlock_node(dest);
15055 bgp_dest_unlock_node(dest);
718e3744 15056
d62a17ae 15057 return CMD_SUCCESS;
718e3744 15058}
15059
718e3744 15060/* Apply BGP information to distance method. */
b8685f9b 15061uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15062 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15063{
9bcb3eef 15064 struct bgp_dest *dest;
801bb996 15065 struct prefix q = {0};
d62a17ae 15066 struct peer *peer;
15067 struct bgp_distance *bdistance;
15068 struct access_list *alist;
15069 struct bgp_static *bgp_static;
a04f1c42 15070 struct bgp_path_info *bpi_ultimate;
d62a17ae 15071
15072 if (!bgp)
15073 return 0;
15074
40381db7 15075 peer = pinfo->peer;
d62a17ae 15076
7b7d48e5
DS
15077 if (pinfo->attr->distance)
15078 return pinfo->attr->distance;
15079
a04f1c42
PG
15080 /* get peer origin to calculate appropriate distance */
15081 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15082 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15083 peer = bpi_ultimate->peer;
15084 }
15085
801bb996
CS
15086 /* Check source address.
15087 * Note: for aggregate route, peer can have unspec af type.
15088 */
15089 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15090 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15091 return 0;
15092
9bcb3eef
DS
15093 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15094 if (dest) {
15095 bdistance = bgp_dest_get_bgp_distance_info(dest);
15096 bgp_dest_unlock_node(dest);
d62a17ae 15097
15098 if (bdistance->access_list) {
15099 alist = access_list_lookup(afi, bdistance->access_list);
15100 if (alist
15101 && access_list_apply(alist, p) == FILTER_PERMIT)
15102 return bdistance->distance;
15103 } else
15104 return bdistance->distance;
718e3744 15105 }
718e3744 15106
d62a17ae 15107 /* Backdoor check. */
9bcb3eef
DS
15108 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15109 if (dest) {
15110 bgp_static = bgp_dest_get_bgp_static_info(dest);
15111 bgp_dest_unlock_node(dest);
718e3744 15112
d62a17ae 15113 if (bgp_static->backdoor) {
15114 if (bgp->distance_local[afi][safi])
15115 return bgp->distance_local[afi][safi];
15116 else
15117 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15118 }
718e3744 15119 }
718e3744 15120
d62a17ae 15121 if (peer->sort == BGP_PEER_EBGP) {
15122 if (bgp->distance_ebgp[afi][safi])
15123 return bgp->distance_ebgp[afi][safi];
15124 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15125 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15126 if (bgp->distance_ibgp[afi][safi])
15127 return bgp->distance_ibgp[afi][safi];
15128 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15129 } else {
15130 if (bgp->distance_local[afi][safi])
15131 return bgp->distance_local[afi][safi];
15132 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15133 }
718e3744 15134}
15135
a612fb77
DA
15136/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15137 * we should tell ZEBRA update the routes for a specific
15138 * AFI/SAFI to reflect changes in RIB.
15139 */
585f1adc
IR
15140static void bgp_announce_routes_distance_update(struct bgp *bgp,
15141 afi_t update_afi,
15142 safi_t update_safi)
a612fb77
DA
15143{
15144 afi_t afi;
15145 safi_t safi;
15146
15147 FOREACH_AFI_SAFI (afi, safi) {
15148 if (!bgp_fibupd_safi(safi))
15149 continue;
15150
8b54bc30
DA
15151 if (afi != update_afi && safi != update_safi)
15152 continue;
15153
15154 if (BGP_DEBUG(zebra, ZEBRA))
15155 zlog_debug(
15156 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15157 __func__, afi, safi);
15158 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15159 }
15160}
15161
585f1adc
IR
15162DEFUN (bgp_distance,
15163 bgp_distance_cmd,
15164 "distance bgp (1-255) (1-255) (1-255)",
15165 "Define an administrative distance\n"
15166 "BGP distance\n"
15167 "Distance for routes external to the AS\n"
15168 "Distance for routes internal to the AS\n"
15169 "Distance for local routes\n")
718e3744 15170{
585f1adc 15171 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15172 int idx_number = 2;
15173 int idx_number_2 = 3;
15174 int idx_number_3 = 4;
585f1adc
IR
15175 int distance_ebgp = atoi(argv[idx_number]->arg);
15176 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15177 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15178 afi_t afi;
15179 safi_t safi;
718e3744 15180
d62a17ae 15181 afi = bgp_node_afi(vty);
15182 safi = bgp_node_safi(vty);
718e3744 15183
585f1adc
IR
15184 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15185 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15186 || bgp->distance_local[afi][safi] != distance_local) {
15187 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15188 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15189 bgp->distance_local[afi][safi] = distance_local;
15190 bgp_announce_routes_distance_update(bgp, afi, safi);
15191 }
15192 return CMD_SUCCESS;
15193}
37a87b8f 15194
585f1adc
IR
15195DEFUN (no_bgp_distance,
15196 no_bgp_distance_cmd,
15197 "no distance bgp [(1-255) (1-255) (1-255)]",
15198 NO_STR
15199 "Define an administrative distance\n"
15200 "BGP distance\n"
15201 "Distance for routes external to the AS\n"
15202 "Distance for routes internal to the AS\n"
15203 "Distance for local routes\n")
718e3744 15204{
585f1adc 15205 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15206 afi_t afi;
15207 safi_t safi;
37a87b8f
CS
15208
15209 afi = bgp_node_afi(vty);
15210 safi = bgp_node_safi(vty);
15211
585f1adc
IR
15212 if (bgp->distance_ebgp[afi][safi] != 0
15213 || bgp->distance_ibgp[afi][safi] != 0
15214 || bgp->distance_local[afi][safi] != 0) {
15215 bgp->distance_ebgp[afi][safi] = 0;
15216 bgp->distance_ibgp[afi][safi] = 0;
15217 bgp->distance_local[afi][safi] = 0;
15218 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15219 }
585f1adc
IR
15220 return CMD_SUCCESS;
15221}
37a87b8f 15222
37a87b8f 15223
585f1adc
IR
15224DEFUN (bgp_distance_source,
15225 bgp_distance_source_cmd,
15226 "distance (1-255) A.B.C.D/M",
15227 "Define an administrative distance\n"
15228 "Administrative distance\n"
15229 "IP source prefix\n")
15230{
15231 int idx_number = 1;
15232 int idx_ipv4_prefixlen = 2;
15233 bgp_distance_set(vty, argv[idx_number]->arg,
15234 argv[idx_ipv4_prefixlen]->arg, NULL);
15235 return CMD_SUCCESS;
734b349e
MZ
15236}
15237
585f1adc
IR
15238DEFUN (no_bgp_distance_source,
15239 no_bgp_distance_source_cmd,
15240 "no distance (1-255) A.B.C.D/M",
15241 NO_STR
15242 "Define an administrative distance\n"
15243 "Administrative distance\n"
15244 "IP source prefix\n")
37a87b8f 15245{
585f1adc
IR
15246 int idx_number = 2;
15247 int idx_ipv4_prefixlen = 3;
15248 bgp_distance_unset(vty, argv[idx_number]->arg,
15249 argv[idx_ipv4_prefixlen]->arg, NULL);
15250 return CMD_SUCCESS;
37a87b8f
CS
15251}
15252
585f1adc
IR
15253DEFUN (bgp_distance_source_access_list,
15254 bgp_distance_source_access_list_cmd,
15255 "distance (1-255) A.B.C.D/M WORD",
15256 "Define an administrative distance\n"
15257 "Administrative distance\n"
15258 "IP source prefix\n"
15259 "Access list name\n")
37a87b8f 15260{
585f1adc
IR
15261 int idx_number = 1;
15262 int idx_ipv4_prefixlen = 2;
15263 int idx_word = 3;
15264 bgp_distance_set(vty, argv[idx_number]->arg,
15265 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15266 return CMD_SUCCESS;
15267}
718e3744 15268
585f1adc
IR
15269DEFUN (no_bgp_distance_source_access_list,
15270 no_bgp_distance_source_access_list_cmd,
15271 "no distance (1-255) A.B.C.D/M WORD",
15272 NO_STR
15273 "Define an administrative distance\n"
15274 "Administrative distance\n"
15275 "IP source prefix\n"
15276 "Access list name\n")
15277{
15278 int idx_number = 2;
15279 int idx_ipv4_prefixlen = 3;
15280 int idx_word = 4;
15281 bgp_distance_unset(vty, argv[idx_number]->arg,
15282 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15283 return CMD_SUCCESS;
15284}
37a87b8f 15285
585f1adc
IR
15286DEFUN (ipv6_bgp_distance_source,
15287 ipv6_bgp_distance_source_cmd,
15288 "distance (1-255) X:X::X:X/M",
15289 "Define an administrative distance\n"
15290 "Administrative distance\n"
15291 "IP source prefix\n")
15292{
15293 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15294 return CMD_SUCCESS;
15295}
7ebe9748 15296
585f1adc
IR
15297DEFUN (no_ipv6_bgp_distance_source,
15298 no_ipv6_bgp_distance_source_cmd,
15299 "no distance (1-255) X:X::X:X/M",
15300 NO_STR
15301 "Define an administrative distance\n"
15302 "Administrative distance\n"
15303 "IP source prefix\n")
15304{
15305 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15306 return CMD_SUCCESS;
15307}
37a87b8f 15308
585f1adc
IR
15309DEFUN (ipv6_bgp_distance_source_access_list,
15310 ipv6_bgp_distance_source_access_list_cmd,
15311 "distance (1-255) X:X::X:X/M WORD",
15312 "Define an administrative distance\n"
15313 "Administrative distance\n"
15314 "IP source prefix\n"
15315 "Access list name\n")
15316{
15317 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15318 return CMD_SUCCESS;
718e3744 15319}
15320
585f1adc
IR
15321DEFUN (no_ipv6_bgp_distance_source_access_list,
15322 no_ipv6_bgp_distance_source_access_list_cmd,
15323 "no distance (1-255) X:X::X:X/M WORD",
15324 NO_STR
15325 "Define an administrative distance\n"
15326 "Administrative distance\n"
15327 "IP source prefix\n"
15328 "Access list name\n")
718e3744 15329{
585f1adc
IR
15330 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15331 return CMD_SUCCESS;
15332}
37a87b8f 15333
585f1adc
IR
15334DEFUN (bgp_damp_set,
15335 bgp_damp_set_cmd,
a30fec23 15336 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15337 "BGP Specific commands\n"
15338 "Enable route-flap dampening\n"
15339 "Half-life time for the penalty\n"
15340 "Value to start reusing a route\n"
15341 "Value to start suppressing a route\n"
15342 "Maximum duration to suppress a stable route\n")
15343{
15344 VTY_DECLVAR_CONTEXT(bgp, bgp);
15345 int idx_half_life = 2;
15346 int idx_reuse = 3;
15347 int idx_suppress = 4;
15348 int idx_max_suppress = 5;
37a87b8f
CS
15349 int half = DEFAULT_HALF_LIFE * 60;
15350 int reuse = DEFAULT_REUSE;
15351 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15352 int max = 4 * half;
15353
15354 if (argc == 6) {
15355 half = atoi(argv[idx_half_life]->arg) * 60;
15356 reuse = atoi(argv[idx_reuse]->arg);
15357 suppress = atoi(argv[idx_suppress]->arg);
15358 max = atoi(argv[idx_max_suppress]->arg) * 60;
15359 } else if (argc == 3) {
15360 half = atoi(argv[idx_half_life]->arg) * 60;
15361 max = 4 * half;
15362 }
15363
15364 /*
15365 * These can't be 0 but our SA doesn't understand the
15366 * way our cli is constructed
15367 */
15368 assert(reuse);
15369 assert(half);
15370 if (suppress < reuse) {
15371 vty_out(vty,
15372 "Suppress value cannot be less than reuse value \n");
15373 return 0;
15374 }
15375
15376 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15377 reuse, suppress, max);
15378}
15379
15380DEFUN (bgp_damp_unset,
15381 bgp_damp_unset_cmd,
a30fec23 15382 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15383 NO_STR
15384 "BGP Specific commands\n"
15385 "Enable route-flap dampening\n"
15386 "Half-life time for the penalty\n"
15387 "Value to start reusing a route\n"
15388 "Value to start suppressing a route\n"
15389 "Maximum duration to suppress a stable route\n")
15390{
15391 VTY_DECLVAR_CONTEXT(bgp, bgp);
15392 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15393}
15394
718e3744 15395/* Display specified route of BGP table. */
d62a17ae 15396static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15397 const char *ip_str, afi_t afi, safi_t safi,
15398 struct prefix_rd *prd, int prefix_check)
15399{
15400 int ret;
15401 struct prefix match;
9bcb3eef
DS
15402 struct bgp_dest *dest;
15403 struct bgp_dest *rm;
40381db7
DS
15404 struct bgp_path_info *pi;
15405 struct bgp_path_info *pi_temp;
d62a17ae 15406 struct bgp *bgp;
15407 struct bgp_table *table;
15408
15409 /* BGP structure lookup. */
15410 if (view_name) {
15411 bgp = bgp_lookup_by_name(view_name);
15412 if (bgp == NULL) {
15413 vty_out(vty, "%% Can't find BGP instance %s\n",
15414 view_name);
15415 return CMD_WARNING;
15416 }
15417 } else {
15418 bgp = bgp_get_default();
15419 if (bgp == NULL) {
15420 vty_out(vty, "%% No BGP process is configured\n");
15421 return CMD_WARNING;
15422 }
718e3744 15423 }
718e3744 15424
d62a17ae 15425 /* Check IP address argument. */
15426 ret = str2prefix(ip_str, &match);
15427 if (!ret) {
15428 vty_out(vty, "%% address is malformed\n");
15429 return CMD_WARNING;
15430 }
718e3744 15431
d62a17ae 15432 match.family = afi2family(afi);
15433
15434 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15435 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15436 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15437 dest = bgp_route_next(dest)) {
15438 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15439
9bcb3eef 15440 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15441 continue;
9bcb3eef 15442 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15443 if (!table)
ea47320b 15444 continue;
4953391b
DA
15445 rm = bgp_node_match(table, &match);
15446 if (rm == NULL)
ea47320b 15447 continue;
d62a17ae 15448
9bcb3eef 15449 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15450
ea47320b 15451 if (!prefix_check
b54892e0 15452 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15453 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15454 while (pi) {
15455 if (pi->extra && pi->extra->damp_info) {
15456 pi_temp = pi->next;
ea47320b 15457 bgp_damp_info_free(
19971c9a 15458 pi->extra->damp_info,
5c8846f6 15459 1, afi, safi);
40381db7 15460 pi = pi_temp;
ea47320b 15461 } else
40381db7 15462 pi = pi->next;
d62a17ae 15463 }
ea47320b
DL
15464 }
15465
9bcb3eef 15466 bgp_dest_unlock_node(rm);
d62a17ae 15467 }
15468 } else {
4953391b
DA
15469 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15470 if (dest != NULL) {
9bcb3eef 15471 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15472
d62a17ae 15473 if (!prefix_check
9bcb3eef
DS
15474 || dest_p->prefixlen == match.prefixlen) {
15475 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15476 while (pi) {
15477 if (pi->extra && pi->extra->damp_info) {
15478 pi_temp = pi->next;
d62a17ae 15479 bgp_damp_info_free(
19971c9a 15480 pi->extra->damp_info,
5c8846f6 15481 1, afi, safi);
40381db7 15482 pi = pi_temp;
d62a17ae 15483 } else
40381db7 15484 pi = pi->next;
d62a17ae 15485 }
15486 }
15487
9bcb3eef 15488 bgp_dest_unlock_node(dest);
d62a17ae 15489 }
15490 }
718e3744 15491
d62a17ae 15492 return CMD_SUCCESS;
718e3744 15493}
15494
15495DEFUN (clear_ip_bgp_dampening,
15496 clear_ip_bgp_dampening_cmd,
15497 "clear ip bgp dampening",
15498 CLEAR_STR
15499 IP_STR
15500 BGP_STR
15501 "Clear route flap dampening information\n")
15502{
b4f7f45b 15503 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15504 return CMD_SUCCESS;
718e3744 15505}
15506
15507DEFUN (clear_ip_bgp_dampening_prefix,
15508 clear_ip_bgp_dampening_prefix_cmd,
15509 "clear ip bgp dampening A.B.C.D/M",
15510 CLEAR_STR
15511 IP_STR
15512 BGP_STR
15513 "Clear route flap dampening information\n"
0c7b1b01 15514 "IPv4 prefix\n")
718e3744 15515{
d62a17ae 15516 int idx_ipv4_prefixlen = 4;
15517 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15518 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15519}
15520
15521DEFUN (clear_ip_bgp_dampening_address,
15522 clear_ip_bgp_dampening_address_cmd,
15523 "clear ip bgp dampening A.B.C.D",
15524 CLEAR_STR
15525 IP_STR
15526 BGP_STR
15527 "Clear route flap dampening information\n"
15528 "Network to clear damping information\n")
15529{
d62a17ae 15530 int idx_ipv4 = 4;
15531 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15532 SAFI_UNICAST, NULL, 0);
718e3744 15533}
15534
15535DEFUN (clear_ip_bgp_dampening_address_mask,
15536 clear_ip_bgp_dampening_address_mask_cmd,
15537 "clear ip bgp dampening A.B.C.D A.B.C.D",
15538 CLEAR_STR
15539 IP_STR
15540 BGP_STR
15541 "Clear route flap dampening information\n"
15542 "Network to clear damping information\n"
15543 "Network mask\n")
15544{
d62a17ae 15545 int idx_ipv4 = 4;
15546 int idx_ipv4_2 = 5;
15547 int ret;
15548 char prefix_str[BUFSIZ];
718e3744 15549
d62a17ae 15550 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15551 prefix_str, sizeof(prefix_str));
d62a17ae 15552 if (!ret) {
15553 vty_out(vty, "%% Inconsistent address and mask\n");
15554 return CMD_WARNING;
15555 }
718e3744 15556
d62a17ae 15557 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15558 NULL, 0);
718e3744 15559}
6b0655a2 15560
e3b78da8 15561static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15562{
15563 struct vty *vty = arg;
e3b78da8 15564 struct peer *peer = bucket->data;
825d9834 15565
47e12884 15566 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15567}
15568
2a0e69ae
DS
15569DEFUN (show_bgp_listeners,
15570 show_bgp_listeners_cmd,
15571 "show bgp listeners",
15572 SHOW_STR
15573 BGP_STR
15574 "Display Listen Sockets and who created them\n")
15575{
15576 bgp_dump_listener_info(vty);
15577
15578 return CMD_SUCCESS;
15579}
15580
825d9834
DS
15581DEFUN (show_bgp_peerhash,
15582 show_bgp_peerhash_cmd,
15583 "show bgp peerhash",
15584 SHOW_STR
15585 BGP_STR
15586 "Display information about the BGP peerhash\n")
15587{
15588 struct list *instances = bm->bgp;
15589 struct listnode *node;
15590 struct bgp *bgp;
15591
15592 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15593 vty_out(vty, "BGP: %s\n", bgp->name);
15594 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15595 vty);
15596 }
15597
15598 return CMD_SUCCESS;
15599}
15600
587ff0fd 15601/* also used for encap safi */
2b791107
DL
15602static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15603 afi_t afi, safi_t safi)
d62a17ae 15604{
9bcb3eef
DS
15605 struct bgp_dest *pdest;
15606 struct bgp_dest *dest;
d62a17ae 15607 struct bgp_table *table;
b54892e0
DS
15608 const struct prefix *p;
15609 const struct prefix_rd *prd;
d62a17ae 15610 struct bgp_static *bgp_static;
15611 mpls_label_t label;
d62a17ae 15612
15613 /* Network configuration. */
9bcb3eef
DS
15614 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15615 pdest = bgp_route_next(pdest)) {
15616 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15617 if (!table)
ea47320b 15618 continue;
d62a17ae 15619
9bcb3eef
DS
15620 for (dest = bgp_table_top(table); dest;
15621 dest = bgp_route_next(dest)) {
15622 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15623 if (bgp_static == NULL)
ea47320b 15624 continue;
d62a17ae 15625
9bcb3eef
DS
15626 p = bgp_dest_get_prefix(dest);
15627 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15628 pdest);
d62a17ae 15629
ea47320b 15630 /* "network" configuration display. */
ea47320b
DL
15631 label = decode_label(&bgp_static->label);
15632
fa566a94 15633 /* TODO: save RD format */
4a8cd6ad 15634 vty_out(vty, " network %pFX rd %pRDP", p, prd);
ea47320b
DL
15635 if (safi == SAFI_MPLS_VPN)
15636 vty_out(vty, " label %u", label);
15637
15638 if (bgp_static->rmap.name)
15639 vty_out(vty, " route-map %s",
15640 bgp_static->rmap.name);
e2a86ad9
DS
15641
15642 if (bgp_static->backdoor)
15643 vty_out(vty, " backdoor");
15644
ea47320b
DL
15645 vty_out(vty, "\n");
15646 }
15647 }
d62a17ae 15648}
15649
2b791107
DL
15650static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15651 afi_t afi, safi_t safi)
d62a17ae 15652{
9bcb3eef
DS
15653 struct bgp_dest *pdest;
15654 struct bgp_dest *dest;
d62a17ae 15655 struct bgp_table *table;
b54892e0
DS
15656 const struct prefix *p;
15657 const struct prefix_rd *prd;
d62a17ae 15658 struct bgp_static *bgp_static;
ff44f570 15659 char buf[PREFIX_STRLEN * 2];
d62a17ae 15660 char buf2[SU_ADDRSTRLEN];
5f933e1e 15661 char esi_buf[ESI_STR_LEN];
d62a17ae 15662
15663 /* Network configuration. */
9bcb3eef
DS
15664 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15665 pdest = bgp_route_next(pdest)) {
15666 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15667 if (!table)
ea47320b 15668 continue;
d62a17ae 15669
9bcb3eef
DS
15670 for (dest = bgp_table_top(table); dest;
15671 dest = bgp_route_next(dest)) {
15672 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15673 if (bgp_static == NULL)
ea47320b 15674 continue;
d62a17ae 15675
ea47320b 15676 char *macrouter = NULL;
d62a17ae 15677
ea47320b
DL
15678 if (bgp_static->router_mac)
15679 macrouter = prefix_mac2str(
15680 bgp_static->router_mac, NULL, 0);
15681 if (bgp_static->eth_s_id)
0a50c248
AK
15682 esi_to_str(bgp_static->eth_s_id,
15683 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15684 p = bgp_dest_get_prefix(dest);
15685 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15686
ea47320b 15687 /* "network" configuration display. */
197cb530
PG
15688 if (p->u.prefix_evpn.route_type == 5) {
15689 char local_buf[PREFIX_STRLEN];
07380148 15690
3714a385 15691 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15692 struct prefix_evpn *)p)
15693 ? AF_INET
15694 : AF_INET6;
3714a385 15695 inet_ntop(family,
07380148
DA
15696 &p->u.prefix_evpn.prefix_addr.ip.ip
15697 .addr,
15698 local_buf, sizeof(local_buf));
772270f3
QY
15699 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15700 p->u.prefix_evpn.prefix_addr
15701 .ip_prefix_length);
197cb530
PG
15702 } else {
15703 prefix2str(p, buf, sizeof(buf));
15704 }
ea47320b 15705
a4d82a8a
PZ
15706 if (bgp_static->gatewayIp.family == AF_INET
15707 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15708 inet_ntop(bgp_static->gatewayIp.family,
15709 &bgp_static->gatewayIp.u.prefix, buf2,
15710 sizeof(buf2));
fa566a94 15711 /* TODO: save RD format */
ea47320b 15712 vty_out(vty,
4a8cd6ad 15713 " network %s rd %pRDP ethtag %u label %u esi %s gwip %s routermac %s\n",
c4f64ea9 15714 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15715 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15716 macrouter);
15717
0a22ddfb 15718 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15719 }
15720 }
3da6fcd5
PG
15721}
15722
718e3744 15723/* Configuration of static route announcement and aggregate
15724 information. */
2b791107
DL
15725void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15726 safi_t safi)
d62a17ae 15727{
9bcb3eef 15728 struct bgp_dest *dest;
b54892e0 15729 const struct prefix *p;
d62a17ae 15730 struct bgp_static *bgp_static;
15731 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15732
2b791107
DL
15733 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15734 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15735 return;
15736 }
d62a17ae 15737
2b791107
DL
15738 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15739 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15740 return;
15741 }
d62a17ae 15742
15743 /* Network configuration. */
9bcb3eef
DS
15744 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15745 dest = bgp_route_next(dest)) {
15746 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15747 if (bgp_static == NULL)
ea47320b 15748 continue;
d62a17ae 15749
9bcb3eef 15750 p = bgp_dest_get_prefix(dest);
d62a17ae 15751
8228a9a7 15752 vty_out(vty, " network %pFX", p);
d62a17ae 15753
ea47320b
DL
15754 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15755 vty_out(vty, " label-index %u",
15756 bgp_static->label_index);
d62a17ae 15757
ea47320b
DL
15758 if (bgp_static->rmap.name)
15759 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15760
15761 if (bgp_static->backdoor)
15762 vty_out(vty, " backdoor");
718e3744 15763
ea47320b
DL
15764 vty_out(vty, "\n");
15765 }
15766
d62a17ae 15767 /* Aggregate-address configuration. */
9bcb3eef
DS
15768 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15769 dest = bgp_route_next(dest)) {
15770 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15771 if (bgp_aggregate == NULL)
ea47320b 15772 continue;
d62a17ae 15773
9bcb3eef 15774 p = bgp_dest_get_prefix(dest);
d62a17ae 15775
8228a9a7 15776 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15777
ea47320b
DL
15778 if (bgp_aggregate->as_set)
15779 vty_out(vty, " as-set");
d62a17ae 15780
ea47320b
DL
15781 if (bgp_aggregate->summary_only)
15782 vty_out(vty, " summary-only");
718e3744 15783
20894f50
DA
15784 if (bgp_aggregate->rmap.name)
15785 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15786
229757f1
DA
15787 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15788 vty_out(vty, " origin %s",
15789 bgp_origin2str(bgp_aggregate->origin));
15790
6aabb15d
RZ
15791 if (bgp_aggregate->match_med)
15792 vty_out(vty, " matching-MED-only");
15793
365ab2e7
RZ
15794 if (bgp_aggregate->suppress_map_name)
15795 vty_out(vty, " suppress-map %s",
15796 bgp_aggregate->suppress_map_name);
15797
ea47320b
DL
15798 vty_out(vty, "\n");
15799 }
d62a17ae 15800}
734b349e 15801
2b791107 15802void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15803 safi_t safi)
d62a17ae 15804{
9bcb3eef 15805 struct bgp_dest *dest;
d62a17ae 15806 struct bgp_distance *bdistance;
15807
15808 /* Distance configuration. */
15809 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15810 && bgp->distance_local[afi][safi]
15811 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15812 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15813 || bgp->distance_local[afi][safi]
15814 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15815 vty_out(vty, " distance bgp %d %d %d\n",
15816 bgp->distance_ebgp[afi][safi],
15817 bgp->distance_ibgp[afi][safi],
15818 bgp->distance_local[afi][safi]);
15819 }
734b349e 15820
9bcb3eef
DS
15821 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15822 dest = bgp_route_next(dest)) {
15823 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15824 if (bdistance != NULL)
56ca3b5b 15825 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15826 bdistance->distance, dest,
d62a17ae 15827 bdistance->access_list ? bdistance->access_list
15828 : "");
ca2e160d 15829 }
718e3744 15830}
15831
15832/* Allocate routing table structure and install commands. */
d62a17ae 15833void bgp_route_init(void)
15834{
15835 afi_t afi;
15836 safi_t safi;
15837
15838 /* Init BGP distance table. */
05c7a1cc 15839 FOREACH_AFI_SAFI (afi, safi)
960035b2 15840 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15841
15842 /* IPv4 BGP commands. */
15843 install_element(BGP_NODE, &bgp_table_map_cmd);
15844 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15845 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15846
554b3b10 15847 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15848
15849 /* IPv4 unicast configuration. */
15850 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15851 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15852 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15853
554b3b10 15854 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15855
15856 /* IPv4 multicast configuration. */
15857 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15858 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15859 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15860 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15861
15862 /* IPv4 labeled-unicast configuration. */
fb985e0c 15863 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15864 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15865
d62a17ae 15866 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15867 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15868 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15869 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15870 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15871 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15872 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15873 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15874
15875 install_element(VIEW_NODE,
15876 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15877 install_element(VIEW_NODE,
15878 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15879 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15880 install_element(VIEW_NODE,
15881 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15882#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15883 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15884#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15885 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15886 install_element(VIEW_NODE,
44c69747 15887 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15888
d62a17ae 15889 /* BGP dampening clear commands */
15890 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15891 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15892
d62a17ae 15893 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15894 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15895
15896 /* prefix count */
15897 install_element(ENABLE_NODE,
15898 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15899#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15900 install_element(ENABLE_NODE,
15901 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15902#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15903
d62a17ae 15904 /* New config IPv6 BGP commands. */
15905 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15906 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15907 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15908
554b3b10 15909 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15910
15911 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15912
fb985e0c
DA
15913 /* IPv6 labeled unicast address family. */
15914 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15915 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15916
d62a17ae 15917 install_element(BGP_NODE, &bgp_distance_cmd);
15918 install_element(BGP_NODE, &no_bgp_distance_cmd);
15919 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15920 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15921 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15922 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15923 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15924 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15925 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15926 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15927 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15928 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15929 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15930 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15931 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15932 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15933 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15934 install_element(BGP_IPV4M_NODE,
15935 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15936 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15937 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15938 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15939 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15940 install_element(BGP_IPV6_NODE,
15941 &ipv6_bgp_distance_source_access_list_cmd);
15942 install_element(BGP_IPV6_NODE,
15943 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15944 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15945 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15946 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15947 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15948 install_element(BGP_IPV6M_NODE,
15949 &ipv6_bgp_distance_source_access_list_cmd);
15950 install_element(BGP_IPV6M_NODE,
15951 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15952
ef5f4b23 15953 /* BGP dampening */
585f1adc
IR
15954 install_element(BGP_NODE, &bgp_damp_set_cmd);
15955 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15956 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15957 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15958 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15959 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15960 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15961 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15962 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15963 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15964 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15965 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15966 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15967 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15968
15969 /* Large Communities */
15970 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15971 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15972
15973 /* show bgp ipv4 flowspec detailed */
15974 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15975
2a0e69ae 15976 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15977 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15978}
15979
15980void bgp_route_finish(void)
15981{
15982 afi_t afi;
15983 safi_t safi;
15984
05c7a1cc
QY
15985 FOREACH_AFI_SAFI (afi, safi) {
15986 bgp_table_unlock(bgp_distance_table[afi][safi]);
15987 bgp_distance_table[afi][safi] = NULL;
15988 }
228da428 15989}