]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: the neighbor as are displayed with as-notation mode
[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)) {
10263 vty_out(vty,
10264 " Imported from %pRD:%pFX, VNI %s",
10265 (struct prefix_rd *)bgp_dest_get_prefix(
10266 pdest),
10267 (struct prefix_evpn *)
10268 bgp_dest_get_prefix(dest),
10269 tag_buf);
6012963e 10270 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10271 vty_out(vty, ", L3NHG %s",
6012963e
SW
10272 CHECK_FLAG(
10273 attr->es_flags,
10274 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10275 ? "active"
10276 : "inactive");
10277 vty_out(vty, "\n");
10278
10279 } else
10280 vty_out(vty, " Imported from %pRD:%pFX\n",
10281 (struct prefix_rd *)bgp_dest_get_prefix(
10282 pdest),
10283 (struct prefix_evpn *)
10284 bgp_dest_get_prefix(dest));
10285 }
10286 }
10287
05864da7
DS
10288 /* Line1 display AS-path, Aggregator */
10289 if (attr->aspath) {
10290 if (json_paths) {
10291 if (!attr->aspath->json)
10292 aspath_str_update(attr->aspath, true);
10293 json_object_lock(attr->aspath->json);
10294 json_object_object_add(json_path, "aspath",
10295 attr->aspath->json);
10296 } else {
10297 if (attr->aspath->segments)
e678b143 10298 vty_out(vty, " %s", attr->aspath->str);
d62a17ae 10299 else
05864da7 10300 vty_out(vty, " Local");
d62a17ae 10301 }
05864da7 10302 }
d62a17ae 10303
05864da7
DS
10304 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10305 if (json_paths)
10306 json_object_boolean_true_add(json_path, "removed");
10307 else
10308 vty_out(vty, ", (removed)");
10309 }
d62a17ae 10310
05864da7
DS
10311 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10312 if (json_paths)
10313 json_object_boolean_true_add(json_path, "stale");
10314 else
10315 vty_out(vty, ", (stale)");
10316 }
d62a17ae 10317
05864da7
DS
10318 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10319 if (json_paths) {
10320 json_object_int_add(json_path, "aggregatorAs",
10321 attr->aggregator_as);
c949c771
DA
10322 json_object_string_addf(json_path, "aggregatorId",
10323 "%pI4", &attr->aggregator_addr);
05864da7 10324 } else {
88d495a9
DA
10325 vty_out(vty, ", (aggregated by %u %pI4)",
10326 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10327 }
05864da7 10328 }
d62a17ae 10329
05864da7
DS
10330 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10331 PEER_FLAG_REFLECTOR_CLIENT)) {
10332 if (json_paths)
10333 json_object_boolean_true_add(json_path,
10334 "rxedFromRrClient");
10335 else
10336 vty_out(vty, ", (Received from a RR-client)");
10337 }
d62a17ae 10338
05864da7
DS
10339 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10340 PEER_FLAG_RSERVER_CLIENT)) {
10341 if (json_paths)
10342 json_object_boolean_true_add(json_path,
10343 "rxedFromRsClient");
10344 else
10345 vty_out(vty, ", (Received from a RS-client)");
10346 }
d62a17ae 10347
05864da7
DS
10348 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10349 if (json_paths)
10350 json_object_boolean_true_add(json_path,
10351 "dampeningHistoryEntry");
10352 else
10353 vty_out(vty, ", (history entry)");
10354 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10355 if (json_paths)
10356 json_object_boolean_true_add(json_path,
10357 "dampeningSuppressed");
10358 else
10359 vty_out(vty, ", (suppressed due to dampening)");
10360 }
d62a17ae 10361
05864da7
DS
10362 if (!json_paths)
10363 vty_out(vty, "\n");
d62a17ae 10364
05864da7
DS
10365 /* Line2 display Next-hop, Neighbor, Router-id */
10366 /* Display the nexthop */
b54892e0 10367
34c7f35f
SW
10368 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10369 p->family == AF_EVPN) &&
7226bc40
TA
10370 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10371 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10372 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10373 || safi == SAFI_EVPN) {
515c2602 10374 if (json_paths) {
c949c771
DA
10375 json_object_string_addf(
10376 json_nexthop_global, "ip", "%pI4",
10377 &attr->mp_nexthop_global_in);
515c2602 10378
939a97f4 10379 if (path->peer->hostname)
515c2602
DA
10380 json_object_string_add(
10381 json_nexthop_global, "hostname",
939a97f4 10382 path->peer->hostname);
aef999a2
DA
10383 } else {
10384 if (nexthop_hostname)
10385 vty_out(vty, " %pI4(%s)",
10386 &attr->mp_nexthop_global_in,
10387 nexthop_hostname);
10388 else
10389 vty_out(vty, " %pI4",
10390 &attr->mp_nexthop_global_in);
10391 }
d62a17ae 10392 } else {
515c2602 10393 if (json_paths) {
c949c771
DA
10394 json_object_string_addf(json_nexthop_global,
10395 "ip", "%pI4",
10396 &attr->nexthop);
515c2602 10397
939a97f4 10398 if (path->peer->hostname)
515c2602
DA
10399 json_object_string_add(
10400 json_nexthop_global, "hostname",
939a97f4 10401 path->peer->hostname);
aef999a2
DA
10402 } else {
10403 if (nexthop_hostname)
10404 vty_out(vty, " %pI4(%s)",
10405 &attr->nexthop,
10406 nexthop_hostname);
10407 else
10408 vty_out(vty, " %pI4",
10409 &attr->nexthop);
10410 }
d62a17ae 10411 }
10412
05864da7
DS
10413 if (json_paths)
10414 json_object_string_add(json_nexthop_global, "afi",
10415 "ipv4");
10416 } else {
10417 if (json_paths) {
c949c771
DA
10418 json_object_string_addf(json_nexthop_global, "ip",
10419 "%pI6",
10420 &attr->mp_nexthop_global);
515c2602 10421
939a97f4 10422 if (path->peer->hostname)
515c2602
DA
10423 json_object_string_add(json_nexthop_global,
10424 "hostname",
939a97f4 10425 path->peer->hostname);
515c2602 10426
05864da7
DS
10427 json_object_string_add(json_nexthop_global, "afi",
10428 "ipv6");
10429 json_object_string_add(json_nexthop_global, "scope",
10430 "global");
10431 } else {
aef999a2
DA
10432 if (nexthop_hostname)
10433 vty_out(vty, " %pI6(%s)",
10434 &attr->mp_nexthop_global,
10435 nexthop_hostname);
10436 else
10437 vty_out(vty, " %pI6",
10438 &attr->mp_nexthop_global);
d62a17ae 10439 }
05864da7 10440 }
d62a17ae 10441
05864da7 10442 /* Display the IGP cost or 'inaccessible' */
f0cde006 10443 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10444 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10445
10446 if (json_paths) {
05864da7
DS
10447 json_object_boolean_false_add(json_nexthop_global,
10448 "accessible");
95ba22d5
DA
10449 json_object_boolean_add(json_nexthop_global,
10450 "importCheckEnabled", import);
10451 } else {
10452 vty_out(vty, " (inaccessible%s)",
10453 import ? ", import-check enabled" : "");
10454 }
05864da7 10455 } else {
f0cde006 10456 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10457 if (json_paths)
f0cde006
LS
10458 json_object_int_add(
10459 json_nexthop_global, "metric",
10460 bpi_ultimate->extra->igpmetric);
d62a17ae 10461 else
05864da7 10462 vty_out(vty, " (metric %u)",
f0cde006 10463 bpi_ultimate->extra->igpmetric);
d62a17ae 10464 }
10465
05864da7 10466 /* IGP cost is 0, display this only for json */
d62a17ae 10467 else {
d62a17ae 10468 if (json_paths)
05864da7
DS
10469 json_object_int_add(json_nexthop_global,
10470 "metric", 0);
d62a17ae 10471 }
d62a17ae 10472
05864da7
DS
10473 if (json_paths)
10474 json_object_boolean_true_add(json_nexthop_global,
10475 "accessible");
10476 }
d62a17ae 10477
05864da7
DS
10478 /* Display peer "from" output */
10479 /* This path was originated locally */
10480 if (path->peer == bgp->peer_self) {
d62a17ae 10481
34c7f35f 10482 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10483 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10484 if (json_paths)
05864da7
DS
10485 json_object_string_add(json_peer, "peerId",
10486 "0.0.0.0");
d62a17ae 10487 else
05864da7
DS
10488 vty_out(vty, " from 0.0.0.0 ");
10489 } else {
d62a17ae 10490 if (json_paths)
05864da7
DS
10491 json_object_string_add(json_peer, "peerId",
10492 "::");
d62a17ae 10493 else
05864da7 10494 vty_out(vty, " from :: ");
d62a17ae 10495 }
d62a17ae 10496
4e9a9863 10497 if (json_paths)
c949c771
DA
10498 json_object_string_addf(json_peer, "routerId", "%pI4",
10499 &bgp->router_id);
4e9a9863 10500 else
23d0a753 10501 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10502 }
d62a17ae 10503
05864da7
DS
10504 /* We RXed this path from one of our peers */
10505 else {
10506
10507 if (json_paths) {
47e12884
DA
10508 json_object_string_addf(json_peer, "peerId", "%pSU",
10509 &path->peer->su);
c949c771
DA
10510 json_object_string_addf(json_peer, "routerId", "%pI4",
10511 &path->peer->remote_id);
05864da7
DS
10512
10513 if (path->peer->hostname)
10514 json_object_string_add(json_peer, "hostname",
10515 path->peer->hostname);
10516
10517 if (path->peer->domainname)
10518 json_object_string_add(json_peer, "domainname",
10519 path->peer->domainname);
10520
10521 if (path->peer->conf_if)
10522 json_object_string_add(json_peer, "interface",
10523 path->peer->conf_if);
10524 } else {
10525 if (path->peer->conf_if) {
10526 if (path->peer->hostname
892fedb6
DA
10527 && CHECK_FLAG(path->peer->bgp->flags,
10528 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10529 vty_out(vty, " from %s(%s)",
10530 path->peer->hostname,
10531 path->peer->conf_if);
d62a17ae 10532 else
05864da7 10533 vty_out(vty, " from %s",
9b6d8fcf 10534 path->peer->conf_if);
d62a17ae 10535 } else {
05864da7 10536 if (path->peer->hostname
892fedb6
DA
10537 && CHECK_FLAG(path->peer->bgp->flags,
10538 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10539 vty_out(vty, " from %s(%s)",
10540 path->peer->hostname,
10541 path->peer->host);
d62a17ae 10542 else
47e12884
DA
10543 vty_out(vty, " from %pSU",
10544 &path->peer->su);
d62a17ae 10545 }
d62a17ae 10546
05864da7 10547 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10548 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10549 else
07380148 10550 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10551 }
05864da7 10552 }
9df8b37c 10553
05864da7
DS
10554 /*
10555 * Note when vrfid of nexthop is different from that of prefix
10556 */
10557 if (path->extra && path->extra->bgp_orig) {
10558 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10559
05864da7
DS
10560 if (json_paths) {
10561 const char *vn;
9df8b37c 10562
05864da7
DS
10563 if (path->extra->bgp_orig->inst_type
10564 == BGP_INSTANCE_TYPE_DEFAULT)
10565 vn = VRF_DEFAULT_NAME;
10566 else
10567 vn = path->extra->bgp_orig->name;
9df8b37c 10568
05864da7 10569 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10570
05864da7
DS
10571 if (nexthop_vrfid == VRF_UNKNOWN) {
10572 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10573 } else {
05864da7
DS
10574 json_object_int_add(json_path, "nhVrfId",
10575 (int)nexthop_vrfid);
9df8b37c 10576 }
05864da7
DS
10577 } else {
10578 if (nexthop_vrfid == VRF_UNKNOWN)
10579 vty_out(vty, " vrf ?");
137147c6
DS
10580 else {
10581 struct vrf *vrf;
10582
10583 vrf = vrf_lookup_by_id(nexthop_vrfid);
10584 vty_out(vty, " vrf %s(%u)",
10585 VRF_LOGNAME(vrf), nexthop_vrfid);
10586 }
9df8b37c 10587 }
05864da7 10588 }
9df8b37c 10589
05864da7
DS
10590 if (nexthop_self) {
10591 if (json_paths) {
10592 json_object_boolean_true_add(json_path,
10593 "announceNexthopSelf");
10594 } else {
10595 vty_out(vty, " announce-nh-self");
9df8b37c 10596 }
05864da7 10597 }
9df8b37c 10598
05864da7
DS
10599 if (!json_paths)
10600 vty_out(vty, "\n");
d62a17ae 10601
05864da7
DS
10602 /* display the link-local nexthop */
10603 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10604 if (json_paths) {
10605 json_nexthop_ll = json_object_new_object();
c949c771
DA
10606 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10607 &attr->mp_nexthop_local);
515c2602 10608
939a97f4 10609 if (path->peer->hostname)
515c2602
DA
10610 json_object_string_add(json_nexthop_ll,
10611 "hostname",
939a97f4 10612 path->peer->hostname);
515c2602 10613
05864da7
DS
10614 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10615 json_object_string_add(json_nexthop_ll, "scope",
10616 "link-local");
d62a17ae 10617
05864da7
DS
10618 json_object_boolean_true_add(json_nexthop_ll,
10619 "accessible");
d62a17ae 10620
2bb8b49c 10621 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10622 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10623 "used");
10624 else
10625 json_object_boolean_true_add(
10626 json_nexthop_global, "used");
10627 } else {
10628 vty_out(vty, " (%s) %s\n",
10629 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10630 buf, INET6_ADDRSTRLEN),
2bb8b49c 10631 attr->mp_nexthop_prefer_global
05864da7
DS
10632 ? "(prefer-global)"
10633 : "(used)");
d62a17ae 10634 }
05864da7
DS
10635 }
10636 /* If we do not have a link-local nexthop then we must flag the
10637 global as "used" */
10638 else {
10639 if (json_paths)
10640 json_object_boolean_true_add(json_nexthop_global,
10641 "used");
10642 }
d62a17ae 10643
b5e140c8 10644 if (safi == SAFI_EVPN &&
5e4d4c8a 10645 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10646 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10647 }
10648
05864da7
DS
10649 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10650 * Int/Ext/Local, Atomic, best */
10651 if (json_paths)
10652 json_object_string_add(json_path, "origin",
10653 bgp_origin_long_str[attr->origin]);
10654 else
10655 vty_out(vty, " Origin %s",
10656 bgp_origin_long_str[attr->origin]);
9df8b37c 10657
05864da7 10658 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10659 if (json_paths)
05864da7 10660 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10661 else
05864da7
DS
10662 vty_out(vty, ", metric %u", attr->med);
10663 }
9df8b37c 10664
05864da7
DS
10665 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10666 if (json_paths)
0fbac0b4 10667 json_object_int_add(json_path, "locPrf",
05864da7
DS
10668 attr->local_pref);
10669 else
10670 vty_out(vty, ", localpref %u", attr->local_pref);
10671 }
9df8b37c 10672
97a52c82
DA
10673 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10674 if (json_paths)
10675 json_object_int_add(json_path, "aigpMetric",
10676 bgp_attr_get_aigp_metric(attr));
10677 else
10678 vty_out(vty, ", aigp-metric %" PRIu64,
10679 bgp_attr_get_aigp_metric(attr));
10680 }
10681
05864da7
DS
10682 if (attr->weight != 0) {
10683 if (json_paths)
10684 json_object_int_add(json_path, "weight", attr->weight);
10685 else
10686 vty_out(vty, ", weight %u", attr->weight);
10687 }
9df8b37c 10688
05864da7
DS
10689 if (attr->tag != 0) {
10690 if (json_paths)
10691 json_object_int_add(json_path, "tag", attr->tag);
10692 else
10693 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10694 }
9df8b37c 10695
05864da7
DS
10696 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10697 if (json_paths)
10698 json_object_boolean_false_add(json_path, "valid");
10699 else
10700 vty_out(vty, ", invalid");
10701 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10702 if (json_paths)
10703 json_object_boolean_true_add(json_path, "valid");
10704 else
10705 vty_out(vty, ", valid");
10706 }
9df8b37c 10707
7d3cae70
DA
10708 if (json_paths)
10709 json_object_int_add(json_path, "version", bn->version);
10710
05864da7
DS
10711 if (path->peer != bgp->peer_self) {
10712 if (path->peer->as == path->peer->local_as) {
10713 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10714 if (json_paths)
10715 json_object_string_add(
10716 json_peer, "type",
10717 "confed-internal");
d62a17ae 10718 else
05864da7 10719 vty_out(vty, ", confed-internal");
d62a17ae 10720 } else {
05864da7
DS
10721 if (json_paths)
10722 json_object_string_add(
10723 json_peer, "type", "internal");
10724 else
10725 vty_out(vty, ", internal");
9df8b37c 10726 }
05864da7
DS
10727 } else {
10728 if (bgp_confederation_peers_check(bgp,
10729 path->peer->as)) {
10730 if (json_paths)
10731 json_object_string_add(
10732 json_peer, "type",
10733 "confed-external");
d62a17ae 10734 else
05864da7 10735 vty_out(vty, ", confed-external");
d62a17ae 10736 } else {
05864da7
DS
10737 if (json_paths)
10738 json_object_string_add(
10739 json_peer, "type", "external");
10740 else
10741 vty_out(vty, ", external");
d62a17ae 10742 }
10743 }
05864da7
DS
10744 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10745 if (json_paths) {
10746 json_object_boolean_true_add(json_path, "aggregated");
10747 json_object_boolean_true_add(json_path, "local");
10748 } else {
10749 vty_out(vty, ", aggregated, local");
10750 }
10751 } else if (path->type != ZEBRA_ROUTE_BGP) {
10752 if (json_paths)
10753 json_object_boolean_true_add(json_path, "sourced");
10754 else
10755 vty_out(vty, ", sourced");
10756 } else {
10757 if (json_paths) {
10758 json_object_boolean_true_add(json_path, "sourced");
10759 json_object_boolean_true_add(json_path, "local");
10760 } else {
10761 vty_out(vty, ", sourced, local");
d62a17ae 10762 }
05864da7 10763 }
718e3744 10764
05864da7 10765 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10766 if (json_paths)
05864da7
DS
10767 json_object_boolean_true_add(json_path,
10768 "atomicAggregate");
d62a17ae 10769 else
05864da7
DS
10770 vty_out(vty, ", atomic-aggregate");
10771 }
d62a17ae 10772
d864dd9e
EB
10773 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10774 if (json_paths)
10775 json_object_int_add(json_path, "otc", attr->otc);
10776 else
10777 vty_out(vty, ", otc %u", attr->otc);
10778 }
10779
05864da7
DS
10780 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10781 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10782 && bgp_path_info_mpath_count(path))) {
10783 if (json_paths)
10784 json_object_boolean_true_add(json_path, "multipath");
10785 else
10786 vty_out(vty, ", multipath");
10787 }
50e05855 10788
05864da7
DS
10789 // Mark the bestpath(s)
10790 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10791 first_as = aspath_get_first_as(attr->aspath);
718e3744 10792
05864da7
DS
10793 if (json_paths) {
10794 if (!json_bestpath)
10795 json_bestpath = json_object_new_object();
10796 json_object_int_add(json_bestpath, "bestpathFromAs",
10797 first_as);
10798 } else {
10799 if (first_as)
10800 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10801 else
05864da7 10802 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10803 }
05864da7 10804 }
718e3744 10805
05864da7
DS
10806 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10807 if (json_paths) {
10808 if (!json_bestpath)
10809 json_bestpath = json_object_new_object();
10810 json_object_boolean_true_add(json_bestpath, "overall");
10811 json_object_string_add(
10812 json_bestpath, "selectionReason",
10813 bgp_path_selection_reason2str(bn->reason));
10814 } else {
10815 vty_out(vty, ", best");
10816 vty_out(vty, " (%s)",
10817 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10818 }
05864da7 10819 }
718e3744 10820
4027d19b 10821 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10822 if (json_paths)
10823 json_object_string_add(
10824 json_path, "rpkiValidationState",
4027d19b 10825 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10826 else
1d327209 10827 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10828 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10829 }
10830
05864da7
DS
10831 if (json_bestpath)
10832 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10833
05864da7
DS
10834 if (!json_paths)
10835 vty_out(vty, "\n");
10836
10837 /* Line 4 display Community */
29e72930 10838 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10839 if (json_paths) {
9a706b42
DA
10840 if (!bgp_attr_get_community(attr)->json)
10841 community_str(bgp_attr_get_community(attr),
c0945b78 10842 true, true);
9a706b42
DA
10843 json_object_lock(bgp_attr_get_community(attr)->json);
10844 json_object_object_add(
10845 json_path, "community",
10846 bgp_attr_get_community(attr)->json);
05864da7
DS
10847 } else {
10848 vty_out(vty, " Community: %s\n",
9a706b42 10849 bgp_attr_get_community(attr)->str);
d62a17ae 10850 }
05864da7 10851 }
718e3744 10852
05864da7
DS
10853 /* Line 5 display Extended-community */
10854 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10855 if (json_paths) {
10856 json_ext_community = json_object_new_object();
b53e67a3
DA
10857 json_object_string_add(
10858 json_ext_community, "string",
10859 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10860 json_object_object_add(json_path, "extendedCommunity",
10861 json_ext_community);
d62a17ae 10862 } else {
05864da7 10863 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10864 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10865 }
05864da7 10866 }
718e3744 10867
05864da7
DS
10868 /* Line 6 display Large community */
10869 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10870 if (json_paths) {
1bcf3a96
DA
10871 if (!bgp_attr_get_lcommunity(attr)->json)
10872 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10873 true, true);
1bcf3a96
DA
10874 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10875 json_object_object_add(
10876 json_path, "largeCommunity",
10877 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10878 } else {
10879 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10880 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10881 }
05864da7 10882 }
718e3744 10883
05864da7
DS
10884 /* Line 7 display Originator, Cluster-id */
10885 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10886 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10887 char buf[BUFSIZ] = {0};
10888
05864da7 10889 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10890 if (json_paths)
c949c771
DA
10891 json_object_string_addf(json_path,
10892 "originatorId", "%pI4",
10893 &attr->originator_id);
d62a17ae 10894 else
23d0a753
DA
10895 vty_out(vty, " Originator: %pI4",
10896 &attr->originator_id);
d62a17ae 10897 }
856ca177 10898
05864da7 10899 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10900 struct cluster_list *cluster =
10901 bgp_attr_get_cluster(attr);
05864da7 10902 int i;
d62a17ae 10903
10904 if (json_paths) {
05864da7
DS
10905 json_cluster_list = json_object_new_object();
10906 json_cluster_list_list =
10907 json_object_new_array();
10908
779fee93 10909 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10910 json_string = json_object_new_string(
779fee93
DS
10911 inet_ntop(AF_INET,
10912 &cluster->list[i],
10913 buf, sizeof(buf)));
05864da7
DS
10914 json_object_array_add(
10915 json_cluster_list_list,
10916 json_string);
10917 }
718e3744 10918
05864da7
DS
10919 /*
10920 * struct cluster_list does not have
10921 * "str" variable like aspath and community
10922 * do. Add this someday if someone asks
10923 * for it.
10924 * json_object_string_add(json_cluster_list,
779fee93 10925 * "string", cluster->str);
05864da7
DS
10926 */
10927 json_object_object_add(json_cluster_list,
10928 "list",
10929 json_cluster_list_list);
10930 json_object_object_add(json_path, "clusterList",
10931 json_cluster_list);
0dc8ee70 10932 } else {
05864da7
DS
10933 vty_out(vty, ", Cluster list: ");
10934
779fee93 10935 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10936 vty_out(vty, "%pI4 ",
779fee93 10937 &cluster->list[i]);
05864da7 10938 }
0dc8ee70 10939 }
d62a17ae 10940 }
718e3744 10941
d62a17ae 10942 if (!json_paths)
10943 vty_out(vty, "\n");
05864da7 10944 }
d62a17ae 10945
05864da7 10946 if (path->extra && path->extra->damp_info)
b4f7f45b 10947 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10948
05864da7
DS
10949 /* Remote Label */
10950 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10951 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10952 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10953 &bos);
d62a17ae 10954
05864da7
DS
10955 if (json_paths)
10956 json_object_int_add(json_path, "remoteLabel", label);
10957 else
10958 vty_out(vty, " Remote label: %d\n", label);
10959 }
d62a17ae 10960
e496b420
HS
10961 /* Remote SID */
10962 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10963 if (json_paths)
07380148
DA
10964 json_object_string_addf(json_path, "remoteSid", "%pI6",
10965 &path->extra->sid[0].sid);
e496b420 10966 else
07380148
DA
10967 vty_out(vty, " Remote SID: %pI6\n",
10968 &path->extra->sid[0].sid);
e496b420
HS
10969 }
10970
05864da7
DS
10971 /* Label Index */
10972 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10973 if (json_paths)
10974 json_object_int_add(json_path, "labelIndex",
10975 attr->label_index);
10976 else
10977 vty_out(vty, " Label Index: %d\n",
10978 attr->label_index);
10979 }
d62a17ae 10980
05864da7
DS
10981 /* Line 8 display Addpath IDs */
10982 if (path->addpath_rx_id
10983 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10984 if (json_paths) {
10985 json_object_int_add(json_path, "addpathRxId",
10986 path->addpath_rx_id);
d62a17ae 10987
05864da7
DS
10988 /* Keep backwards compatibility with the old API
10989 * by putting TX All's ID in the old field
10990 */
10991 json_object_int_add(
10992 json_path, "addpathTxId",
10993 path->tx_addpath
10994 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10995
05864da7
DS
10996 /* ... but create a specific field for each
10997 * strategy
10998 */
10999 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11000 json_object_int_add(
11001 json_path,
11002 bgp_addpath_names(i)->id_json_name,
11003 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11004 }
05864da7
DS
11005 } else {
11006 vty_out(vty, " AddPath ID: RX %u, ",
11007 path->addpath_rx_id);
d62a17ae 11008
05864da7 11009 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11010 }
05864da7 11011 }
520d5d76 11012
05864da7
DS
11013 /* If we used addpath to TX a non-bestpath we need to display
11014 * "Advertised to" on a path-by-path basis
11015 */
11016 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11017 first = 1;
dcc68b5e 11018
05864da7
DS
11019 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11020 addpath_capable =
11021 bgp_addpath_encode_tx(peer, afi, safi);
11022 has_adj = bgp_adj_out_lookup(
11023 peer, path->net,
11024 bgp_addpath_id_for_peer(peer, afi, safi,
11025 &path->tx_addpath));
11026
11027 if ((addpath_capable && has_adj)
11028 || (!addpath_capable && has_adj
11029 && CHECK_FLAG(path->flags,
11030 BGP_PATH_SELECTED))) {
11031 if (json_path && !json_adv_to)
11032 json_adv_to = json_object_new_object();
dcc68b5e 11033
05864da7
DS
11034 route_vty_out_advertised_to(
11035 vty, peer, &first,
11036 " Advertised to:", json_adv_to);
d62a17ae 11037 }
11038 }
718e3744 11039
05864da7
DS
11040 if (json_path) {
11041 if (json_adv_to) {
11042 json_object_object_add(
11043 json_path, "advertisedTo", json_adv_to);
d62a17ae 11044 }
05864da7
DS
11045 } else {
11046 if (!first) {
11047 vty_out(vty, "\n");
d62a17ae 11048 }
11049 }
05864da7 11050 }
b05a1c8b 11051
05864da7 11052 /* Line 9 display Uptime */
083ec940 11053 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11054 if (json_paths) {
11055 json_last_update = json_object_new_object();
11056 json_object_int_add(json_last_update, "epoch", tbuf);
11057 json_object_string_add(json_last_update, "string",
11058 ctime(&tbuf));
11059 json_object_object_add(json_path, "lastUpdate",
11060 json_last_update);
11061 } else
11062 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11063
05864da7
DS
11064 /* Line 10 display PMSI tunnel attribute, if present */
11065 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11066 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11067 bgp_attr_get_pmsi_tnl_type(attr),
11068 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11069
05864da7
DS
11070 if (json_paths) {
11071 json_pmsi = json_object_new_object();
11072 json_object_string_add(json_pmsi, "tunnelType", str);
11073 json_object_int_add(json_pmsi, "label",
11074 label2vni(&attr->label));
11075 json_object_object_add(json_path, "pmsi", json_pmsi);
11076 } else
11077 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11078 str, label2vni(&attr->label));
d62a17ae 11079 }
f1aa5d8a 11080
848e8cf6
DA
11081 if (path->peer->t_gr_restart &&
11082 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11083 unsigned long gr_remaining =
11084 thread_timer_remain_second(path->peer->t_gr_restart);
11085
11086 if (json_paths) {
11087 json_object_int_add(json_path,
11088 "gracefulRestartSecondsRemaining",
11089 gr_remaining);
11090 } else
11091 vty_out(vty,
11092 " Time until Graceful Restart stale route deleted: %lu\n",
11093 gr_remaining);
11094 }
11095
9a706b42
DA
11096 if (path->peer->t_llgr_stale[afi][safi] &&
11097 bgp_attr_get_community(attr) &&
11098 community_include(bgp_attr_get_community(attr),
11099 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11100 unsigned long llgr_remaining = thread_timer_remain_second(
11101 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11102
48ebba04
DA
11103 if (json_paths) {
11104 json_object_int_add(json_path, "llgrSecondsRemaining",
11105 llgr_remaining);
11106 } else
11107 vty_out(vty,
11108 " Time until Long-lived stale route deleted: %lu\n",
11109 llgr_remaining);
11110 }
11111
92269aa2
DS
11112 /* Output some debug about internal state of the dest flags */
11113 if (json_paths) {
11114 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11115 json_object_boolean_true_add(json_path, "processScheduled");
11116 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11117 json_object_boolean_true_add(json_path, "userCleared");
11118 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11119 json_object_boolean_true_add(json_path, "labelChanged");
11120 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11121 json_object_boolean_true_add(json_path, "registeredForLabel");
11122 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11123 json_object_boolean_true_add(json_path, "selectDefered");
11124 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11125 json_object_boolean_true_add(json_path, "fibInstalled");
11126 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11127 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11128
d62a17ae 11129 if (json_nexthop_global || json_nexthop_ll) {
11130 json_nexthops = json_object_new_array();
f1aa5d8a 11131
d62a17ae 11132 if (json_nexthop_global)
11133 json_object_array_add(json_nexthops,
11134 json_nexthop_global);
f1aa5d8a 11135
d62a17ae 11136 if (json_nexthop_ll)
11137 json_object_array_add(json_nexthops,
11138 json_nexthop_ll);
f1aa5d8a 11139
d62a17ae 11140 json_object_object_add(json_path, "nexthops",
11141 json_nexthops);
11142 }
11143
11144 json_object_object_add(json_path, "peer", json_peer);
11145 json_object_array_add(json_paths, json_path);
05864da7 11146 }
b366b518
BB
11147}
11148
96ade3ed 11149#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11150#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11151#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11152
a4d82a8a 11153static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11154 afi_t afi, safi_t safi, enum bgp_show_type type,
11155 bool use_json);
7f323236
DW
11156static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11157 const char *comstr, int exact, afi_t afi,
96c81f66 11158 safi_t safi, uint16_t show_flags);
d62a17ae 11159
1ae44dfc 11160static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11161 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11162 void *output_arg, const char *rd, int is_last,
96f3485c 11163 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11164 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11165 enum rpki_states rpki_target_state)
d62a17ae 11166{
40381db7 11167 struct bgp_path_info *pi;
9bcb3eef 11168 struct bgp_dest *dest;
2aad8c42
MS
11169 bool header = true;
11170 bool json_detail_header = false;
d62a17ae 11171 int display;
1ae44dfc
LB
11172 unsigned long output_count = 0;
11173 unsigned long total_count = 0;
d62a17ae 11174 struct prefix *p;
d62a17ae 11175 json_object *json_paths = NULL;
11176 int first = 1;
96f3485c
MK
11177 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11178 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11179 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11180 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11181 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11182
1ae44dfc 11183 if (output_cum && *output_cum != 0)
2aad8c42 11184 header = false;
1ae44dfc 11185
9386b588 11186 if (use_json && !*json_header_depth) {
96f3485c
MK
11187 if (all)
11188 *json_header_depth = 1;
11189 else {
11190 vty_out(vty, "{\n");
11191 *json_header_depth = 2;
11192 }
d62a17ae 11193 vty_out(vty,
23d0a753
DA
11194 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11195 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
e84c7c12 11196 " \"localAS\": ",
a8bf7d9c 11197 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11198 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11199 ? VRF_DEFAULT_NAME
11200 : bgp->name,
11201 table->version, &bgp->router_id,
e84c7c12
PG
11202 bgp->default_local_pref);
11203 if ((bgp->asnotation == ASNOTATION_PLAIN) ||
11204 ((bgp->asnotation == ASNOTATION_DOT) &&
11205 (bgp->as < UINT16_MAX)))
11206 vty_out(vty, "%u", bgp->as);
11207 else {
11208 vty_out(vty, "\"");
11209 vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as);
11210 vty_out(vty, "\"");
11211 }
11212 vty_out(vty, ",\n \"routes\": { ");
9386b588 11213 if (rd) {
445c2480 11214 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11215 ++*json_header_depth;
11216 }
d62a17ae 11217 }
718e3744 11218
445c2480
DS
11219 if (use_json && rd) {
11220 vty_out(vty, " \"%s\" : { ", rd);
11221 }
11222
2aad8c42 11223 /* Check for 'json detail', where we need header output once per dest */
67799a48 11224 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11225 type != bgp_show_type_damp_neighbor &&
11226 type != bgp_show_type_flap_statistics &&
11227 type != bgp_show_type_flap_neighbor)
11228 json_detail_header = true;
11229
d62a17ae 11230 /* Start processing of routes. */
9bcb3eef
DS
11231 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11232 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11233 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11234 bool json_detail = json_detail_header;
b54892e0 11235
9bcb3eef 11236 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11237 if (pi == NULL)
98ce9a06 11238 continue;
d62a17ae 11239
98ce9a06 11240 display = 0;
98ce9a06
DS
11241 if (use_json)
11242 json_paths = json_object_new_array();
11243 else
11244 json_paths = NULL;
d62a17ae 11245
6f94b685 11246 for (; pi; pi = pi->next) {
9a706b42
DA
11247 struct community *picomm = NULL;
11248
11249 picomm = bgp_attr_get_community(pi->attr);
11250
98ce9a06 11251 total_count++;
1e2ce4f1 11252
7d3cae70
DA
11253 if (type == bgp_show_type_prefix_version) {
11254 uint32_t version =
11255 strtoul(output_arg, NULL, 10);
11256 if (dest->version < version)
11257 continue;
11258 }
11259
a70a28a5
DA
11260 if (type == bgp_show_type_community_alias) {
11261 char *alias = output_arg;
11262 char **communities;
11263 int num;
11264 bool found = false;
11265
9a706b42
DA
11266 if (picomm) {
11267 frrstr_split(picomm->str, " ",
11268 &communities, &num);
a70a28a5
DA
11269 for (int i = 0; i < num; i++) {
11270 const char *com2alias =
11271 bgp_community2alias(
11272 communities[i]);
cd9cc0e6
IR
11273 if (!found
11274 && strcmp(alias, com2alias)
11275 == 0)
a70a28a5 11276 found = true;
cd9cc0e6
IR
11277 XFREE(MTYPE_TMP,
11278 communities[i]);
a70a28a5 11279 }
cd9cc0e6 11280 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11281 }
11282
1bcf3a96
DA
11283 if (!found &&
11284 bgp_attr_get_lcommunity(pi->attr)) {
11285 frrstr_split(bgp_attr_get_lcommunity(
11286 pi->attr)
11287 ->str,
a70a28a5
DA
11288 " ", &communities, &num);
11289 for (int i = 0; i < num; i++) {
11290 const char *com2alias =
11291 bgp_community2alias(
11292 communities[i]);
cd9cc0e6
IR
11293 if (!found
11294 && strcmp(alias, com2alias)
11295 == 0)
a70a28a5 11296 found = true;
cd9cc0e6
IR
11297 XFREE(MTYPE_TMP,
11298 communities[i]);
a70a28a5 11299 }
cd9cc0e6 11300 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11301 }
11302
11303 if (!found)
11304 continue;
11305 }
11306
1e2ce4f1
DS
11307 if (type == bgp_show_type_rpki) {
11308 if (dest_p->family == AF_INET
11309 || dest_p->family == AF_INET6)
4027d19b 11310 rpki_curr_state = hook_call(
1e2ce4f1
DS
11311 bgp_rpki_prefix_status,
11312 pi->peer, pi->attr, dest_p);
4027d19b
DS
11313 if (rpki_target_state != RPKI_NOT_BEING_USED
11314 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11315 continue;
11316 }
11317
98ce9a06
DS
11318 if (type == bgp_show_type_flap_statistics
11319 || type == bgp_show_type_flap_neighbor
11320 || type == bgp_show_type_dampend_paths
11321 || type == bgp_show_type_damp_neighbor) {
40381db7 11322 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11323 continue;
11324 }
11325 if (type == bgp_show_type_regexp) {
11326 regex_t *regex = output_arg;
d62a17ae 11327
40381db7 11328 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11329 == REG_NOMATCH)
11330 continue;
11331 }
11332 if (type == bgp_show_type_prefix_list) {
11333 struct prefix_list *plist = output_arg;
d62a17ae 11334
9bcb3eef 11335 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11336 != PREFIX_PERMIT)
11337 continue;
11338 }
ed126382
DA
11339 if (type == bgp_show_type_access_list) {
11340 struct access_list *alist = output_arg;
11341
11342 if (access_list_apply(alist, dest_p) !=
11343 FILTER_PERMIT)
11344 continue;
11345 }
98ce9a06
DS
11346 if (type == bgp_show_type_filter_list) {
11347 struct as_list *as_list = output_arg;
d62a17ae 11348
40381db7 11349 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11350 != AS_FILTER_PERMIT)
11351 continue;
11352 }
11353 if (type == bgp_show_type_route_map) {
11354 struct route_map *rmap = output_arg;
9b6d8fcf 11355 struct bgp_path_info path;
636632c3
DA
11356 struct bgp_path_info_extra extra;
11357 struct attr dummy_attr = {};
b68885f9 11358 route_map_result_t ret;
d62a17ae 11359
6f4f49b2 11360 dummy_attr = *pi->attr;
d62a17ae 11361
636632c3
DA
11362 prep_for_rmap_apply(&path, &extra, dest, pi,
11363 pi->peer, &dummy_attr);
d62a17ae 11364
1782514f 11365 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11366 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11367 if (ret == RMAP_DENYMATCH)
11368 continue;
11369 }
11370 if (type == bgp_show_type_neighbor
11371 || type == bgp_show_type_flap_neighbor
11372 || type == bgp_show_type_damp_neighbor) {
11373 union sockunion *su = output_arg;
11374
40381db7
DS
11375 if (pi->peer == NULL
11376 || pi->peer->su_remote == NULL
11377 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11378 continue;
11379 }
11380 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11381 uint32_t destination;
d62a17ae 11382
9bcb3eef 11383 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11384 if (IN_CLASSC(destination)
9bcb3eef 11385 && dest_p->prefixlen == 24)
98ce9a06
DS
11386 continue;
11387 if (IN_CLASSB(destination)
9bcb3eef 11388 && dest_p->prefixlen == 16)
98ce9a06
DS
11389 continue;
11390 if (IN_CLASSA(destination)
9bcb3eef 11391 && dest_p->prefixlen == 8)
98ce9a06
DS
11392 continue;
11393 }
11394 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11395 p = output_arg;
9bcb3eef 11396 if (!prefix_match(p, dest_p))
98ce9a06
DS
11397 continue;
11398 }
11399 if (type == bgp_show_type_community_all) {
9a706b42 11400 if (!picomm)
98ce9a06
DS
11401 continue;
11402 }
11403 if (type == bgp_show_type_community) {
11404 struct community *com = output_arg;
d62a17ae 11405
9a706b42 11406 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11407 continue;
11408 }
11409 if (type == bgp_show_type_community_exact) {
11410 struct community *com = output_arg;
d62a17ae 11411
9a706b42 11412 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11413 continue;
11414 }
11415 if (type == bgp_show_type_community_list) {
11416 struct community_list *list = output_arg;
d62a17ae 11417
9a706b42 11418 if (!community_list_match(picomm, list))
98ce9a06
DS
11419 continue;
11420 }
a4d82a8a 11421 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11422 struct community_list *list = output_arg;
d62a17ae 11423
9a706b42 11424 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11425 continue;
11426 }
11427 if (type == bgp_show_type_lcommunity) {
11428 struct lcommunity *lcom = output_arg;
d62a17ae 11429
1bcf3a96
DA
11430 if (!bgp_attr_get_lcommunity(pi->attr) ||
11431 !lcommunity_match(
11432 bgp_attr_get_lcommunity(pi->attr),
11433 lcom))
98ce9a06
DS
11434 continue;
11435 }
36a206db 11436
11437 if (type == bgp_show_type_lcommunity_exact) {
11438 struct lcommunity *lcom = output_arg;
11439
1bcf3a96
DA
11440 if (!bgp_attr_get_lcommunity(pi->attr) ||
11441 !lcommunity_cmp(
11442 bgp_attr_get_lcommunity(pi->attr),
11443 lcom))
36a206db 11444 continue;
11445 }
98ce9a06
DS
11446 if (type == bgp_show_type_lcommunity_list) {
11447 struct community_list *list = output_arg;
d62a17ae 11448
1bcf3a96
DA
11449 if (!lcommunity_list_match(
11450 bgp_attr_get_lcommunity(pi->attr),
11451 list))
98ce9a06
DS
11452 continue;
11453 }
36a206db 11454 if (type
11455 == bgp_show_type_lcommunity_list_exact) {
11456 struct community_list *list = output_arg;
11457
11458 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11459 bgp_attr_get_lcommunity(pi->attr),
11460 list))
36a206db 11461 continue;
11462 }
98ce9a06 11463 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11464 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11465 continue;
11466 }
11467 if (type == bgp_show_type_dampend_paths
11468 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11469 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11470 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11471 continue;
11472 }
11473
11474 if (!use_json && header) {
23d0a753
DA
11475 vty_out(vty,
11476 "BGP table version is %" PRIu64
11477 ", local router ID is %pI4, vrf id ",
11478 table->version, &bgp->router_id);
9df8b37c
PZ
11479 if (bgp->vrf_id == VRF_UNKNOWN)
11480 vty_out(vty, "%s", VRFID_NONE_STR);
11481 else
11482 vty_out(vty, "%u", bgp->vrf_id);
11483 vty_out(vty, "\n");
01eced22
AD
11484 vty_out(vty, "Default local pref %u, ",
11485 bgp->default_local_pref);
e84c7c12
PG
11486 vty_out(vty, "local AS ");
11487 vty_out(vty, ASN_FORMAT(bgp->asnotation),
11488 &bgp->as);
11489 vty_out(vty, "\n");
509d82bd 11490 if (!detail_routes) {
9a1aae2d
DA
11491 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11492 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11493 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11494 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11495 }
d62a17ae 11496 if (type == bgp_show_type_dampend_paths
11497 || type == bgp_show_type_damp_neighbor)
98ce9a06 11498 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11499 else if (type == bgp_show_type_flap_statistics
11500 || type == bgp_show_type_flap_neighbor)
98ce9a06 11501 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11502 else if (!detail_routes)
ae248832
MK
11503 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11504 : BGP_SHOW_HEADER));
2aad8c42
MS
11505 header = false;
11506
11507 } else if (json_detail && json_paths != NULL) {
11508 const struct prefix_rd *prd;
11509 json_object *jtemp;
11510
11511 /* Use common detail header, for most types;
11512 * need a json 'object'.
11513 */
11514
11515 jtemp = json_object_new_object();
11516 prd = bgp_rd_from_dest(dest, safi);
11517
11518 route_vty_out_detail_header(
34c7f35f
SW
11519 vty, bgp, dest,
11520 bgp_dest_get_prefix(dest), prd,
11521 table->afi, safi, jtemp);
2aad8c42
MS
11522
11523 json_object_array_add(json_paths, jtemp);
11524
11525 json_detail = false;
d62a17ae 11526 }
2aad8c42 11527
98ce9a06
DS
11528 if (rd != NULL && !display && !output_count) {
11529 if (!use_json)
11530 vty_out(vty,
11531 "Route Distinguisher: %s\n",
11532 rd);
d62a17ae 11533 }
98ce9a06
DS
11534 if (type == bgp_show_type_dampend_paths
11535 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11536 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11537 AFI_IP, safi, use_json,
11538 json_paths);
98ce9a06
DS
11539 else if (type == bgp_show_type_flap_statistics
11540 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11541 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11542 AFI_IP, safi, use_json,
11543 json_paths);
f280c93b 11544 else {
27bb782a
DA
11545 if (detail_routes || detail_json) {
11546 const struct prefix_rd *prd = NULL;
9a1aae2d 11547
27bb782a
DA
11548 if (dest->pdest)
11549 prd = bgp_rd_from_dest(
11550 dest->pdest, safi);
9a1aae2d
DA
11551
11552 if (!use_json)
11553 route_vty_out_detail_header(
11554 vty, bgp, dest,
11555 bgp_dest_get_prefix(
11556 dest),
11557 prd, table->afi, safi,
11558 NULL);
11559
f280c93b 11560 route_vty_out_detail(
27bb782a 11561 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11562 family2afi(dest_p->family),
11563 safi, RPKI_NOT_BEING_USED,
11564 json_paths);
9a1aae2d 11565 } else {
f280c93b
DA
11566 route_vty_out(vty, dest_p, pi, display,
11567 safi, json_paths, wide);
9a1aae2d 11568 }
f280c93b 11569 }
98ce9a06 11570 display++;
d62a17ae 11571 }
11572
98ce9a06
DS
11573 if (display) {
11574 output_count++;
11575 if (!use_json)
11576 continue;
11577
625d2931 11578 /* encode prefix */
9bcb3eef 11579 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11580 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11581
1840384b 11582
b54892e0
DS
11583 bgp_fs_nlri_get_string(
11584 (unsigned char *)
9bcb3eef
DS
11585 dest_p->u.prefix_flowspec.ptr,
11586 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11587 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11588 family2afi(dest_p->u
11589 .prefix_flowspec.family));
625d2931 11590 if (first)
b54892e0 11591 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11592 dest_p->u.prefix_flowspec
b54892e0 11593 .prefixlen);
625d2931 11594 else
b54892e0 11595 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11596 dest_p->u.prefix_flowspec
b54892e0 11597 .prefixlen);
625d2931 11598 } else {
625d2931 11599 if (first)
1b78780b 11600 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11601 else
1b78780b 11602 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11603 }
d7c6467b
DS
11604 /*
11605 * We are using no_pretty here because under
11606 * extremely high settings( say lots and lots of
11607 * routes with lots and lots of ways to reach
11608 * that route via different paths ) this can
11609 * save several minutes of output when FRR
11610 * is run on older cpu's or more underperforming
11611 * routers out there
11612 */
11613 vty_json_no_pretty(vty, json_paths);
449feb8e 11614 json_paths = NULL;
98ce9a06 11615 first = 0;
1f83ed02
DS
11616 } else
11617 json_object_free(json_paths);
98ce9a06
DS
11618 }
11619
1ae44dfc
LB
11620 if (output_cum) {
11621 output_count += *output_cum;
11622 *output_cum = output_count;
11623 }
11624 if (total_cum) {
11625 total_count += *total_cum;
11626 *total_cum = total_count;
11627 }
d62a17ae 11628 if (use_json) {
9386b588 11629 if (rd) {
a4d82a8a 11630 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11631 }
11632 if (is_last) {
a4d82a8a
PZ
11633 unsigned long i;
11634 for (i = 0; i < *json_header_depth; ++i)
11635 vty_out(vty, " } ");
96f3485c
MK
11636 if (!all)
11637 vty_out(vty, "\n");
9386b588 11638 }
d62a17ae 11639 } else {
1ae44dfc
LB
11640 if (is_last) {
11641 /* No route is displayed */
11642 if (output_count == 0) {
11643 if (type == bgp_show_type_normal)
11644 vty_out(vty,
11645 "No BGP prefixes displayed, %ld exist\n",
11646 total_count);
11647 } else
d62a17ae 11648 vty_out(vty,
1ae44dfc
LB
11649 "\nDisplayed %ld routes and %ld total paths\n",
11650 output_count, total_count);
11651 }
d62a17ae 11652 }
718e3744 11653
d62a17ae 11654 return CMD_SUCCESS;
718e3744 11655}
11656
1ae44dfc
LB
11657int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11658 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11659 enum bgp_show_type type, void *output_arg,
11660 uint16_t show_flags)
1ae44dfc 11661{
9bcb3eef 11662 struct bgp_dest *dest, *next;
1ae44dfc
LB
11663 unsigned long output_cum = 0;
11664 unsigned long total_cum = 0;
9386b588 11665 unsigned long json_header_depth = 0;
67009e22 11666 struct bgp_table *itable;
0136788c 11667 bool show_msg;
27bb782a 11668 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11669
11670 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11671
9bcb3eef
DS
11672 for (dest = bgp_table_top(table); dest; dest = next) {
11673 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11674
9bcb3eef
DS
11675 next = bgp_route_next(dest);
11676 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11677 continue;
67009e22 11678
9bcb3eef 11679 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11680 if (itable != NULL) {
1ae44dfc 11681 struct prefix_rd prd;
06b9f471 11682 char rd[RD_ADDRSTRLEN];
1ae44dfc 11683
9bcb3eef 11684 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11685 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11686 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11687 rd, next == NULL, &output_cum,
11688 &total_cum, &json_header_depth,
1e2ce4f1 11689 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11690 if (next == NULL)
11691 show_msg = false;
1ae44dfc
LB
11692 }
11693 }
0136788c
LB
11694 if (show_msg) {
11695 if (output_cum == 0)
11696 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11697 total_cum);
11698 else
11699 vty_out(vty,
11700 "\nDisplayed %ld routes and %ld total paths\n",
11701 output_cum, total_cum);
0224b329
DA
11702 } else {
11703 if (use_json && output_cum == 0)
11704 vty_out(vty, "{}\n");
0136788c 11705 }
1ae44dfc
LB
11706 return CMD_SUCCESS;
11707}
2aad8c42 11708
d62a17ae 11709static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11710 enum bgp_show_type type, void *output_arg,
96c81f66 11711 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11712{
d62a17ae 11713 struct bgp_table *table;
9386b588 11714 unsigned long json_header_depth = 0;
96f3485c 11715 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11716
d62a17ae 11717 if (bgp == NULL) {
11718 bgp = bgp_get_default();
11719 }
fee0f4c6 11720
d62a17ae 11721 if (bgp == NULL) {
11722 if (!use_json)
11723 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11724 else
11725 vty_out(vty, "{}\n");
d62a17ae 11726 return CMD_WARNING;
11727 }
4dd6177e 11728
cd8c2a27
MS
11729 /* Labeled-unicast routes live in the unicast table. */
11730 if (safi == SAFI_LABELED_UNICAST)
11731 safi = SAFI_UNICAST;
11732
1ae44dfc 11733 table = bgp->rib[afi][safi];
d62a17ae 11734 /* use MPLS and ENCAP specific shows until they are merged */
11735 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11736 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11737 output_arg, show_flags);
d62a17ae 11738 }
dba3c1d3
PG
11739
11740 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11741 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11742 output_arg, use_json,
11743 1, NULL, NULL);
11744 }
fee0f4c6 11745
0adc5bbb
LS
11746 if (safi == SAFI_EVPN)
11747 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11748
96f3485c 11749 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11750 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11751 rpki_target_state);
fee0f4c6 11752}
11753
d62a17ae 11754static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11755 safi_t safi, uint16_t show_flags)
f186de26 11756{
d62a17ae 11757 struct listnode *node, *nnode;
11758 struct bgp *bgp;
11759 int is_first = 1;
9f049418 11760 bool route_output = false;
96f3485c 11761 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11762
d62a17ae 11763 if (use_json)
11764 vty_out(vty, "{\n");
9f689658 11765
d62a17ae 11766 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11767 route_output = true;
d62a17ae 11768 if (use_json) {
11769 if (!is_first)
11770 vty_out(vty, ",\n");
11771 else
11772 is_first = 0;
11773
11774 vty_out(vty, "\"%s\":",
11775 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11776 ? VRF_DEFAULT_NAME
d62a17ae 11777 : bgp->name);
11778 } else {
11779 vty_out(vty, "\nInstance %s:\n",
11780 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11781 ? VRF_DEFAULT_NAME
d62a17ae 11782 : bgp->name);
11783 }
11784 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11785 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11786 }
9f689658 11787
d62a17ae 11788 if (use_json)
11789 vty_out(vty, "}\n");
9f049418
DS
11790 else if (!route_output)
11791 vty_out(vty, "%% BGP instance not found\n");
f186de26 11792}
11793
718e3744 11794/* Header of detailed BGP route information */
d62a17ae 11795void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11796 struct bgp_dest *dest, const struct prefix *p,
11797 const struct prefix_rd *prd, afi_t afi,
11798 safi_t safi, json_object *json)
d62a17ae 11799{
40381db7 11800 struct bgp_path_info *pi;
d62a17ae 11801 struct peer *peer;
11802 struct listnode *node, *nnode;
06b9f471 11803 char buf1[RD_ADDRSTRLEN];
d62a17ae 11804 int count = 0;
11805 int best = 0;
11806 int suppress = 0;
c5f1e1b2
C
11807 int accept_own = 0;
11808 int route_filter_translated_v4 = 0;
11809 int route_filter_v4 = 0;
11810 int route_filter_translated_v6 = 0;
11811 int route_filter_v6 = 0;
11812 int llgr_stale = 0;
11813 int no_llgr = 0;
11814 int accept_own_nexthop = 0;
11815 int blackhole = 0;
d62a17ae 11816 int no_export = 0;
11817 int no_advertise = 0;
11818 int local_as = 0;
c5f1e1b2 11819 int no_peer = 0;
d62a17ae 11820 int first = 1;
11821 int has_valid_label = 0;
11822 mpls_label_t label = 0;
11823 json_object *json_adv_to = NULL;
67f67ba4
DA
11824 uint32_t ttl = 0;
11825 uint32_t bos = 0;
11826 uint32_t exp = 0;
9bedbb1e 11827
67f67ba4 11828 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11829
67f67ba4 11830 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11831
44c69747 11832 if (safi == SAFI_EVPN) {
44c69747 11833 if (!json) {
2dbe669b 11834 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11835 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11836 : "",
2dbe669b 11837 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11838 } else {
11839 json_object_string_add(json, "rd",
11840 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11841 "");
11842 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11843 }
11844 } else {
11845 if (!json) {
9119ef3a
DA
11846 vty_out(vty,
11847 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11848 "\n",
d62a17ae 11849 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11850 ? prefix_rd2str(prd, buf1,
11851 sizeof(buf1))
11852 : ""),
9119ef3a
DA
11853 safi == SAFI_MPLS_VPN ? ":" : "", p,
11854 dest->version);
cd1964ff 11855
9119ef3a 11856 } else {
67d7e256 11857 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11858 json_object_int_add(json, "version", dest->version);
11859
11860 }
44c69747
LK
11861 }
11862
11863 if (has_valid_label) {
11864 if (json)
11865 json_object_int_add(json, "localLabel", label);
11866 else
d62a17ae 11867 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11868 }
11869
11870 if (!json)
d62a17ae 11871 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11872 vty_out(vty, "not allocated\n");
718e3744 11873
9bcb3eef 11874 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11875 struct community *picomm = NULL;
11876
11877 picomm = bgp_attr_get_community(pi->attr);
11878
d62a17ae 11879 count++;
40381db7 11880 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11881 best = count;
4056a5f6 11882 if (bgp_path_suppressed(pi))
d62a17ae 11883 suppress = 1;
cee9c031 11884
9a706b42 11885 if (!picomm)
cee9c031
QY
11886 continue;
11887
11888 no_advertise += community_include(
9a706b42
DA
11889 picomm, COMMUNITY_NO_ADVERTISE);
11890 no_export +=
11891 community_include(picomm, COMMUNITY_NO_EXPORT);
11892 local_as +=
11893 community_include(picomm, COMMUNITY_LOCAL_AS);
11894 accept_own +=
11895 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11896 route_filter_translated_v4 += community_include(
9a706b42 11897 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11898 route_filter_translated_v6 += community_include(
9a706b42 11899 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11900 route_filter_v4 += community_include(
9a706b42 11901 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11902 route_filter_v6 += community_include(
9a706b42
DA
11903 picomm, COMMUNITY_ROUTE_FILTER_v6);
11904 llgr_stale +=
11905 community_include(picomm, COMMUNITY_LLGR_STALE);
11906 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11907 accept_own_nexthop += community_include(
11908 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11909 blackhole +=
11910 community_include(picomm, COMMUNITY_BLACKHOLE);
11911 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11912 }
718e3744 11913 }
718e3744 11914
d62a17ae 11915 if (!json) {
11916 vty_out(vty, "Paths: (%d available", count);
11917 if (best) {
11918 vty_out(vty, ", best #%d", best);
b84060bb
PG
11919 if (safi == SAFI_UNICAST) {
11920 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11921 vty_out(vty, ", table %s",
11922 VRF_DEFAULT_NAME);
11923 else
11924 vty_out(vty, ", vrf %s",
11925 bgp->name);
11926 }
d62a17ae 11927 } else
11928 vty_out(vty, ", no best path");
11929
c5f1e1b2
C
11930 if (accept_own)
11931 vty_out(vty,
11932 ", accept own local route exported and imported in different VRF");
11933 else if (route_filter_translated_v4)
11934 vty_out(vty,
11935 ", mark translated RTs for VPNv4 route filtering");
11936 else if (route_filter_v4)
11937 vty_out(vty,
11938 ", attach RT as-is for VPNv4 route filtering");
11939 else if (route_filter_translated_v6)
11940 vty_out(vty,
11941 ", mark translated RTs for VPNv6 route filtering");
11942 else if (route_filter_v6)
11943 vty_out(vty,
11944 ", attach RT as-is for VPNv6 route filtering");
11945 else if (llgr_stale)
11946 vty_out(vty,
1479ed2f 11947 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11948 else if (no_llgr)
11949 vty_out(vty,
11950 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11951 else if (accept_own_nexthop)
11952 vty_out(vty,
11953 ", accept local nexthop");
11954 else if (blackhole)
11955 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11956 else if (no_export)
11957 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11958 else if (no_advertise)
11959 vty_out(vty, ", not advertised to any peer");
d62a17ae 11960 else if (local_as)
11961 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11962 else if (no_peer)
11963 vty_out(vty,
11964 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11965
11966 if (suppress)
11967 vty_out(vty,
11968 ", Advertisements suppressed by an aggregate.");
11969 vty_out(vty, ")\n");
11970 }
718e3744 11971
d62a17ae 11972 /* If we are not using addpath then we can display Advertised to and
11973 * that will
11974 * show what peers we advertised the bestpath to. If we are using
11975 * addpath
11976 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11977 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11978 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11979 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11980 if (json && !json_adv_to)
11981 json_adv_to = json_object_new_object();
11982
11983 route_vty_out_advertised_to(
11984 vty, peer, &first,
11985 " Advertised to non peer-group peers:\n ",
11986 json_adv_to);
11987 }
11988 }
11989
11990 if (json) {
11991 if (json_adv_to) {
11992 json_object_object_add(json, "advertisedTo",
11993 json_adv_to);
11994 }
11995 } else {
11996 if (first)
11997 vty_out(vty, " Not advertised to any peer");
11998 vty_out(vty, "\n");
11999 }
12000 }
718e3744 12001}
12002
edfee30d 12003static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12004 struct bgp_dest *bgp_node, struct vty *vty,
12005 struct bgp *bgp, afi_t afi, safi_t safi,
12006 json_object *json, enum bgp_path_type pathtype,
4027d19b 12007 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12008{
12009 struct bgp_path_info *pi;
12010 int header = 1;
44c69747
LK
12011 json_object *json_header = NULL;
12012 json_object *json_paths = NULL;
4933eaaf 12013 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12014
9bcb3eef 12015 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12016 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12017
12018 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12019 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12020 pi->peer, pi->attr, p);
4933eaaf 12021
4027d19b
DS
12022 if (rpki_target_state != RPKI_NOT_BEING_USED
12023 && rpki_curr_state != rpki_target_state)
4933eaaf 12024 continue;
44c69747
LK
12025
12026 if (json && !json_paths) {
12027 /* Instantiate json_paths only if path is valid */
12028 json_paths = json_object_new_array();
c4f64ea9 12029 if (pfx_rd)
44c69747 12030 json_header = json_object_new_object();
c4f64ea9 12031 else
44c69747
LK
12032 json_header = json;
12033 }
12034
12035 if (header) {
12036 route_vty_out_detail_header(
34c7f35f
SW
12037 vty, bgp, bgp_node,
12038 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12039 safi, json_header);
44c69747
LK
12040 header = 0;
12041 }
12042 (*display)++;
12043
12044 if (pathtype == BGP_PATH_SHOW_ALL
12045 || (pathtype == BGP_PATH_SHOW_BESTPATH
12046 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12047 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12048 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12049 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12050 route_vty_out_detail(vty, bgp, bgp_node,
12051 bgp_dest_get_prefix(bgp_node), pi,
12052 AFI_IP, safi, rpki_curr_state,
12053 json_paths);
44c69747
LK
12054 }
12055
12056 if (json && json_paths) {
12057 json_object_object_add(json_header, "paths", json_paths);
12058
12059 if (pfx_rd)
c4f64ea9
DA
12060 json_object_object_addf(json, json_header, "%pRD",
12061 pfx_rd);
44c69747
LK
12062 }
12063}
12064
2aad8c42
MS
12065/*
12066 * Return rd based on safi
12067 */
46dbf9d0
DA
12068const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12069 safi_t safi)
2aad8c42
MS
12070{
12071 switch (safi) {
12072 case SAFI_MPLS_VPN:
12073 case SAFI_ENCAP:
12074 case SAFI_EVPN:
12075 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
58cf0823
DS
12076 case SAFI_UNSPEC:
12077 case SAFI_UNICAST:
12078 case SAFI_MULTICAST:
12079 case SAFI_LABELED_UNICAST:
12080 case SAFI_FLOWSPEC:
12081 case SAFI_MAX:
2aad8c42 12082 return NULL;
2aad8c42 12083 }
58cf0823
DS
12084
12085 assert(!"Reached end of function when we were not expecting it");
2aad8c42
MS
12086}
12087
718e3744 12088/* Display specified route of BGP table. */
d62a17ae 12089static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12090 struct bgp_table *rib, const char *ip_str,
12091 afi_t afi, safi_t safi,
4027d19b 12092 enum rpki_states rpki_target_state,
d62a17ae 12093 struct prefix_rd *prd, int prefix_check,
9f049418 12094 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12095{
12096 int ret;
d62a17ae 12097 int display = 0;
12098 struct prefix match;
9bcb3eef
DS
12099 struct bgp_dest *dest;
12100 struct bgp_dest *rm;
d62a17ae 12101 struct bgp_table *table;
12102 json_object *json = NULL;
12103 json_object *json_paths = NULL;
12104
12105 /* Check IP address argument. */
12106 ret = str2prefix(ip_str, &match);
12107 if (!ret) {
12108 vty_out(vty, "address is malformed\n");
12109 return CMD_WARNING;
12110 }
718e3744 12111
d62a17ae 12112 match.family = afi2family(afi);
b05a1c8b 12113
44c69747 12114 if (use_json)
d62a17ae 12115 json = json_object_new_object();
718e3744 12116
44c69747 12117 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12118 for (dest = bgp_table_top(rib); dest;
12119 dest = bgp_route_next(dest)) {
12120 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12121
9bcb3eef 12122 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12123 continue;
9bcb3eef 12124 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12125 if (!table)
ea47320b 12126 continue;
d62a17ae 12127
4953391b
DA
12128 rm = bgp_node_match(table, &match);
12129 if (rm == NULL)
ea47320b 12130 continue;
d62a17ae 12131
9bcb3eef 12132 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12133 if (prefix_check
b54892e0 12134 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12135 bgp_dest_unlock_node(rm);
ea47320b
DL
12136 continue;
12137 }
d62a17ae 12138
9bcb3eef 12139 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12140 bgp, afi, safi, json, pathtype,
4027d19b 12141 &display, rpki_target_state);
44c69747 12142
9bcb3eef 12143 bgp_dest_unlock_node(rm);
44c69747
LK
12144 }
12145 } else if (safi == SAFI_EVPN) {
9bcb3eef 12146 struct bgp_dest *longest_pfx;
cded3b72 12147 bool is_exact_pfxlen_match = false;
44c69747 12148
9bcb3eef
DS
12149 for (dest = bgp_table_top(rib); dest;
12150 dest = bgp_route_next(dest)) {
12151 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12152
9bcb3eef 12153 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12154 continue;
9bcb3eef 12155 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12156 if (!table)
12157 continue;
12158
12159 longest_pfx = NULL;
cded3b72 12160 is_exact_pfxlen_match = false;
44c69747
LK
12161 /*
12162 * Search through all the prefixes for a match. The
12163 * pfx's are enumerated in ascending order of pfxlens.
12164 * So, the last pfx match is the longest match. Set
12165 * is_exact_pfxlen_match when we get exact pfxlen match
12166 */
12167 for (rm = bgp_table_top(table); rm;
12168 rm = bgp_route_next(rm)) {
b54892e0 12169 const struct prefix *rm_p =
9bcb3eef 12170 bgp_dest_get_prefix(rm);
44c69747
LK
12171 /*
12172 * Get prefixlen of the ip-prefix within type5
12173 * evpn route
12174 */
b54892e0
DS
12175 if (evpn_type5_prefix_match(rm_p, &match)
12176 && rm->info) {
44c69747
LK
12177 longest_pfx = rm;
12178 int type5_pfxlen =
b54892e0
DS
12179 bgp_evpn_get_type5_prefixlen(
12180 rm_p);
44c69747 12181 if (type5_pfxlen == match.prefixlen) {
cded3b72 12182 is_exact_pfxlen_match = true;
9bcb3eef 12183 bgp_dest_unlock_node(rm);
44c69747
LK
12184 break;
12185 }
d62a17ae 12186 }
12187 }
ea47320b 12188
44c69747
LK
12189 if (!longest_pfx)
12190 continue;
12191
12192 if (prefix_check && !is_exact_pfxlen_match)
12193 continue;
12194
12195 rm = longest_pfx;
9bcb3eef 12196 bgp_dest_lock_node(rm);
44c69747 12197
9bcb3eef 12198 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12199 bgp, afi, safi, json, pathtype,
4027d19b 12200 &display, rpki_target_state);
44c69747 12201
9bcb3eef 12202 bgp_dest_unlock_node(rm);
d62a17ae 12203 }
98a9dbc7 12204 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12205 if (use_json)
12206 json_paths = json_object_new_array();
12207
63a0b7a9
PG
12208 display = bgp_flowspec_display_match_per_ip(afi, rib,
12209 &match, prefix_check,
12210 vty,
12211 use_json,
12212 json_paths);
d5f20468
SP
12213 if (use_json) {
12214 if (display)
12215 json_object_object_add(json, "paths",
12216 json_paths);
12217 else
12218 json_object_free(json_paths);
12219 }
d62a17ae 12220 } else {
4953391b
DA
12221 dest = bgp_node_match(rib, &match);
12222 if (dest != NULL) {
9bcb3eef 12223 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12224 if (!prefix_check
9bcb3eef
DS
12225 || dest_p->prefixlen == match.prefixlen) {
12226 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12227 safi, json, pathtype,
4027d19b 12228 &display, rpki_target_state);
d62a17ae 12229 }
12230
9bcb3eef 12231 bgp_dest_unlock_node(dest);
d62a17ae 12232 }
12233 }
e5eee9af 12234
d62a17ae 12235 if (use_json) {
75eeda93 12236 vty_json(vty, json);
d62a17ae 12237 } else {
12238 if (!display) {
12239 vty_out(vty, "%% Network not in table\n");
12240 return CMD_WARNING;
12241 }
12242 }
b05a1c8b 12243
d62a17ae 12244 return CMD_SUCCESS;
718e3744 12245}
12246
fee0f4c6 12247/* Display specified route of Main RIB */
d62a17ae 12248static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12249 afi_t afi, safi_t safi, struct prefix_rd *prd,
12250 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12251 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12252{
9b86009a 12253 if (!bgp) {
d62a17ae 12254 bgp = bgp_get_default();
9b86009a
RW
12255 if (!bgp) {
12256 if (!use_json)
12257 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12258 else
12259 vty_out(vty, "{}\n");
9b86009a
RW
12260 return CMD_WARNING;
12261 }
12262 }
d62a17ae 12263
12264 /* labeled-unicast routes live in the unicast table */
12265 if (safi == SAFI_LABELED_UNICAST)
12266 safi = SAFI_UNICAST;
12267
12268 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12269 afi, safi, rpki_target_state, prd,
8aa22bbb 12270 prefix_check, pathtype, use_json);
d62a17ae 12271}
12272
12273static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12274 struct cmd_token **argv, bool exact, afi_t afi,
12275 safi_t safi, bool uj)
d62a17ae 12276{
12277 struct lcommunity *lcom;
12278 struct buffer *b;
12279 int i;
12280 char *str;
12281 int first = 0;
96c81f66 12282 uint16_t show_flags = 0;
4f28b2b5 12283 int ret;
96f3485c
MK
12284
12285 if (uj)
12286 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12287
12288 b = buffer_new(1024);
12289 for (i = 0; i < argc; i++) {
12290 if (first)
12291 buffer_putc(b, ' ');
12292 else {
12293 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12294 first = 1;
12295 buffer_putstr(b, argv[i]->arg);
12296 }
12297 }
12298 }
12299 buffer_putc(b, '\0');
57d187bc 12300
d62a17ae 12301 str = buffer_getstr(b);
12302 buffer_free(b);
57d187bc 12303
d62a17ae 12304 lcom = lcommunity_str2com(str);
12305 XFREE(MTYPE_TMP, str);
12306 if (!lcom) {
12307 vty_out(vty, "%% Large-community malformed\n");
12308 return CMD_WARNING;
12309 }
57d187bc 12310
4f28b2b5 12311 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12312 (exact ? bgp_show_type_lcommunity_exact
12313 : bgp_show_type_lcommunity),
12314 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12315
12316 lcommunity_free(&lcom);
12317 return ret;
57d187bc
JS
12318}
12319
d62a17ae 12320static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12321 const char *lcom, bool exact, afi_t afi,
12322 safi_t safi, bool uj)
57d187bc 12323{
d62a17ae 12324 struct community_list *list;
96c81f66 12325 uint16_t show_flags = 0;
96f3485c
MK
12326
12327 if (uj)
12328 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12329
57d187bc 12330
e237b0d2 12331 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12332 LARGE_COMMUNITY_LIST_MASTER);
12333 if (list == NULL) {
12334 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12335 lcom);
12336 return CMD_WARNING;
12337 }
57d187bc 12338
36a206db 12339 return bgp_show(vty, bgp, afi, safi,
12340 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12341 : bgp_show_type_lcommunity_list),
1e2ce4f1 12342 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12343}
12344
52951b63
DS
12345DEFUN (show_ip_bgp_large_community_list,
12346 show_ip_bgp_large_community_list_cmd,
77a3a95e 12347 "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
12348 SHOW_STR
12349 IP_STR
12350 BGP_STR
12351 BGP_INSTANCE_HELP_STR
9bedbb1e 12352 BGP_AFI_HELP_STR
4dd6177e 12353 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12354 "Display routes matching the large-community-list\n"
12355 "large-community-list number\n"
12356 "large-community-list name\n"
36a206db 12357 "Exact match of the large-communities\n"
52951b63
DS
12358 JSON_STR)
12359{
d62a17ae 12360 afi_t afi = AFI_IP6;
12361 safi_t safi = SAFI_UNICAST;
12362 int idx = 0;
36a206db 12363 bool exact_match = 0;
4d678463 12364 struct bgp *bgp = NULL;
9f049418 12365 bool uj = use_json(argc, argv);
d62a17ae 12366
ef3364f0
DA
12367 if (uj)
12368 argc--;
4d678463 12369
ef3364f0
DA
12370 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12371 &bgp, uj);
12372 if (!idx)
12373 return CMD_WARNING;
d62a17ae 12374
12375 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12376
12377 const char *clist_number_or_name = argv[++idx]->arg;
12378
12379 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12380 exact_match = 1;
12381
12382 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12383 exact_match, afi, safi, uj);
52951b63
DS
12384}
12385DEFUN (show_ip_bgp_large_community,
12386 show_ip_bgp_large_community_cmd,
36a206db 12387 "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
12388 SHOW_STR
12389 IP_STR
12390 BGP_STR
12391 BGP_INSTANCE_HELP_STR
9bedbb1e 12392 BGP_AFI_HELP_STR
4dd6177e 12393 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12394 "Display routes matching the large-communities\n"
12395 "List of large-community numbers\n"
36a206db 12396 "Exact match of the large-communities\n"
52951b63
DS
12397 JSON_STR)
12398{
d62a17ae 12399 afi_t afi = AFI_IP6;
12400 safi_t safi = SAFI_UNICAST;
12401 int idx = 0;
36a206db 12402 bool exact_match = 0;
4d678463 12403 struct bgp *bgp = NULL;
9f049418 12404 bool uj = use_json(argc, argv);
96c81f66 12405 uint16_t show_flags = 0;
d62a17ae 12406
96f3485c
MK
12407 if (uj) {
12408 argc--;
12409 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12410 }
4d678463 12411
96f3485c
MK
12412 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12413 &bgp, uj);
12414 if (!idx)
12415 return CMD_WARNING;
d62a17ae 12416
36a206db 12417 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12418 if (argv_find(argv, argc, "exact-match", &idx)) {
12419 argc--;
36a206db 12420 exact_match = 1;
1857760c 12421 }
36a206db 12422 return bgp_show_lcommunity(vty, bgp, argc, argv,
12423 exact_match, afi, safi, uj);
12424 } else
d62a17ae 12425 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12426 bgp_show_type_lcommunity_all, NULL, show_flags,
12427 RPKI_NOT_BEING_USED);
52951b63
DS
12428}
12429
71f1613a
DA
12430static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12431 safi_t safi, struct json_object *json_array);
d62a17ae 12432static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12433 safi_t safi, struct json_object *json);
e01ca200 12434
7b2ff250 12435
9ab0cf58
PG
12436DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12437 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12438 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12439 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12440{
12441 bool uj = use_json(argc, argv);
12442 struct bgp *bgp = NULL;
ec76a1d1
DA
12443 safi_t safi = SAFI_UNICAST;
12444 afi_t afi = AFI_IP6;
4265b261 12445 int idx = 0;
6c9d22e2
PG
12446 struct json_object *json_all = NULL;
12447 struct json_object *json_afi_safi = NULL;
4265b261
PG
12448
12449 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12450 &bgp, false);
71f1613a 12451 if (!idx)
4265b261 12452 return CMD_WARNING;
6c9d22e2 12453
4265b261 12454 if (uj)
6c9d22e2 12455 json_all = json_object_new_object();
4265b261 12456
9ab0cf58
PG
12457 FOREACH_AFI_SAFI (afi, safi) {
12458 /*
12459 * So limit output to those afi/safi pairs that
12460 * actually have something interesting in them
12461 */
12462 if (strmatch(get_afi_safi_str(afi, safi, true),
12463 "Unknown")) {
12464 continue;
12465 }
12466 if (uj) {
12467 json_afi_safi = json_object_new_array();
12468 json_object_object_add(
12469 json_all,
12470 get_afi_safi_str(afi, safi, true),
12471 json_afi_safi);
12472 } else {
12473 json_afi_safi = NULL;
6c9d22e2 12474 }
9ab0cf58
PG
12475
12476 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12477 }
6c9d22e2 12478
3757f964
DA
12479 if (uj)
12480 vty_json(vty, json_all);
6c9d22e2 12481
4265b261
PG
12482 return CMD_SUCCESS;
12483}
12484
7b2ff250 12485/* BGP route print out function without JSON */
14718643
PG
12486DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12487 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12488 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12489 SHOW_STR
12490 IP_STR
12491 BGP_STR
12492 BGP_INSTANCE_HELP_STR
12493 L2VPN_HELP_STR
12494 EVPN_HELP_STR
12495 "BGP RIB advertisement statistics\n"
12496 JSON_STR)
12497{
ec76a1d1
DA
12498 afi_t afi = AFI_IP6;
12499 safi_t safi = SAFI_UNICAST;
14718643
PG
12500 struct bgp *bgp = NULL;
12501 int idx = 0, ret;
12502 bool uj = use_json(argc, argv);
12503 struct json_object *json_afi_safi = NULL, *json = NULL;
12504
12505 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12506 &bgp, false);
12507 if (!idx)
12508 return CMD_WARNING;
12509
12510 if (uj)
12511 json_afi_safi = json_object_new_array();
12512 else
12513 json_afi_safi = NULL;
12514
12515 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12516
12517 if (uj) {
12518 json = json_object_new_object();
12519 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12520 json_afi_safi);
3757f964 12521 vty_json(vty, json);
14718643
PG
12522 }
12523 return ret;
12524}
12525
893cccd0 12526/* BGP route print out function without JSON */
9ab0cf58
PG
12527DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12528 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12529 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12530 "]]\
893cccd0 12531 statistics [json]",
9ab0cf58
PG
12532 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12533 BGP_SAFI_WITH_LABEL_HELP_STR
12534 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12535{
ec76a1d1
DA
12536 afi_t afi = AFI_IP6;
12537 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12538 struct bgp *bgp = NULL;
12539 int idx = 0, ret;
12540 bool uj = use_json(argc, argv);
6c9d22e2 12541 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12542
12543 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12544 &bgp, false);
12545 if (!idx)
12546 return CMD_WARNING;
6c9d22e2 12547
893cccd0 12548 if (uj)
6c9d22e2
PG
12549 json_afi_safi = json_object_new_array();
12550 else
12551 json_afi_safi = NULL;
12552
12553 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12554
12555 if (uj) {
12556 json = json_object_new_object();
12557 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12558 json_afi_safi);
3757f964 12559 vty_json(vty, json);
893cccd0
PG
12560 }
12561 return ret;
893cccd0 12562}
7b2ff250 12563
fe0f234d 12564DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12565 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12566 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12567 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12568 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12569 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12570 "Display the entries for all address families\n"
9ab0cf58
PG
12571 "Display detailed information about dampening\n"
12572 "Display detail of configured dampening parameters\n"
fe0f234d 12573 JSON_STR)
718e3744 12574{
d62a17ae 12575 afi_t afi = AFI_IP6;
12576 safi_t safi = SAFI_UNICAST;
d62a17ae 12577 struct bgp *bgp = NULL;
12578 int idx = 0;
96c81f66 12579 uint16_t show_flags = 0;
fe0f234d
RW
12580 bool uj = use_json(argc, argv);
12581
12582 if (uj) {
12583 argc--;
12584 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12585 }
96f3485c
MK
12586
12587 /* [<ipv4|ipv6> [all]] */
12588 if (all) {
12589 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12590 if (argv_find(argv, argc, "ipv4", &idx))
12591 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12592
12593 if (argv_find(argv, argc, "ipv6", &idx))
12594 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12595 }
d62a17ae 12596
12597 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12598 &bgp, false);
d62a17ae 12599 if (!idx)
12600 return CMD_WARNING;
12601
fe0f234d 12602 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12603}
12604
fe0f234d
RW
12605/* BGP route print out function */
12606DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12607 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12608 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12609 "]]\
96f3485c 12610 [all$all]\
cf4898bc
QY
12611 [cidr-only\
12612 |dampening <flap-statistics|dampened-paths>\
12613 |community [AA:NN|local-AS|no-advertise|no-export\
12614 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12615 |accept-own|accept-own-nexthop|route-filter-v6\
12616 |route-filter-v4|route-filter-translated-v6\
12617 |route-filter-translated-v4] [exact-match]\
70799983 12618 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12619 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12620 |prefix-list WORD\
ed126382 12621 |access-list ACCESSLIST_NAME\
70dd370f 12622 |route-map RMAP_NAME\
1e2ce4f1 12623 |rpki <invalid|valid|notfound>\
7d3cae70 12624 |version (1-4294967295)\
b4ad2fae 12625 |alias ALIAS_NAME\
39c3c736
RW
12626 |A.B.C.D/M longer-prefixes\
12627 |X:X::X:X/M longer-prefixes\
509d82bd 12628 |detail-routes$detail_routes\
67799a48 12629 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12630 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12631 BGP_SAFI_WITH_LABEL_HELP_STR
12632 "Display the entries for all address families\n"
12633 "Display only routes with non-natural netmasks\n"
12634 "Display detailed information about dampening\n"
12635 "Display flap statistics of routes\n"
12636 "Display paths suppressed due to dampening\n"
12637 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12638 "Do not send outside local AS (well-known community)\n"
12639 "Do not advertise to any peer (well-known community)\n"
12640 "Do not export to next AS (well-known community)\n"
12641 "Graceful shutdown (well-known community)\n"
12642 "Do not export to any peer (well-known community)\n"
12643 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12644 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12645 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12646 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12647 "Should accept VPN route with local nexthop (well-known community)\n"
12648 "RT VPNv6 route filtering (well-known community)\n"
12649 "RT VPNv4 route filtering (well-known community)\n"
12650 "RT translated VPNv6 route filtering (well-known community)\n"
12651 "RT translated VPNv4 route filtering (well-known community)\n"
12652 "Exact match of the communities\n"
70799983
RW
12653 "Community-list number\n"
12654 "Community-list name\n"
12655 "Display routes matching the community-list\n"
12656 "Exact match of the communities\n"
a7129347
RW
12657 "Display routes conforming to the filter-list\n"
12658 "Regular expression access list name\n"
6deaf579
RW
12659 "Display routes conforming to the prefix-list\n"
12660 "Prefix-list name\n"
ed126382
DA
12661 "Display routes conforming to the access-list\n"
12662 "Access-list name\n"
bf1a944a
RW
12663 "Display routes matching the route-map\n"
12664 "A route-map to match on\n"
a70a28a5
DA
12665 "RPKI route types\n"
12666 "A valid path as determined by rpki\n"
12667 "A invalid path as determined by rpki\n"
12668 "A path that has no rpki data\n"
12669 "Display prefixes with matching version numbers\n"
12670 "Version number and above\n"
12671 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12672 "BGP community alias\n"
12673 "IPv4 prefix\n"
12674 "Display route and more specific routes\n"
12675 "IPv6 prefix\n"
12676 "Display route and more specific routes\n"
509d82bd 12677 "Display detailed version of all routes\n"
39c3c736 12678 JSON_STR
a70a28a5
DA
12679 "Display detailed version of JSON output\n"
12680 "Increase table width for longer prefixes\n")
7b2ff250
DW
12681{
12682 afi_t afi = AFI_IP6;
12683 safi_t safi = SAFI_UNICAST;
12684 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12685 void *output_arg = NULL;
7b2ff250
DW
12686 struct bgp *bgp = NULL;
12687 int idx = 0;
d0086e8e 12688 int exact_match = 0;
96f3485c
MK
12689 char *community = NULL;
12690 bool first = true;
96c81f66 12691 uint16_t show_flags = 0;
4027d19b 12692 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12693 struct prefix p;
96f3485c
MK
12694
12695 if (uj) {
9f049418 12696 argc--;
96f3485c
MK
12697 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12698 }
12699
67799a48
DA
12700 if (detail_json)
12701 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12702
509d82bd
DA
12703 if (detail_routes)
12704 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12705
96f3485c
MK
12706 /* [<ipv4|ipv6> [all]] */
12707 if (all) {
12708 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12709
12710 if (argv_find(argv, argc, "ipv4", &idx))
12711 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12712
12713 if (argv_find(argv, argc, "ipv6", &idx))
12714 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12715 }
12716
12717 if (wide)
12718 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12719
12720 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12721 &bgp, uj);
7b2ff250
DW
12722 if (!idx)
12723 return CMD_WARNING;
12724
7b2ff250 12725 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12726 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12727
12728 if (argv_find(argv, argc, "dampening", &idx)) {
12729 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12730 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12731 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12732 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12733 }
12734
12735 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12736 char *maybecomm = NULL;
d0086e8e 12737
79bc257a
RW
12738 if (idx + 1 < argc) {
12739 if (argv[idx + 1]->type == VARIABLE_TKN)
12740 maybecomm = argv[idx + 1]->arg;
12741 else
12742 maybecomm = argv[idx + 1]->text;
12743 }
12744
cf4898bc
QY
12745 if (maybecomm && !strmatch(maybecomm, "json")
12746 && !strmatch(maybecomm, "exact-match"))
12747 community = maybecomm;
d0086e8e 12748
cf4898bc
QY
12749 if (argv_find(argv, argc, "exact-match", &idx))
12750 exact_match = 1;
d0086e8e 12751
96f3485c
MK
12752 if (!community)
12753 sh_type = bgp_show_type_community_all;
12754 }
12755
70799983
RW
12756 if (argv_find(argv, argc, "community-list", &idx)) {
12757 const char *clist_number_or_name = argv[++idx]->arg;
12758 struct community_list *list;
12759
12760 if (argv_find(argv, argc, "exact-match", &idx))
12761 exact_match = 1;
12762
12763 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12764 COMMUNITY_LIST_MASTER);
12765 if (list == NULL) {
606d49a4 12766 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12767 clist_number_or_name);
12768 return CMD_WARNING;
12769 }
12770
12771 if (exact_match)
12772 sh_type = bgp_show_type_community_list_exact;
12773 else
12774 sh_type = bgp_show_type_community_list;
12775 output_arg = list;
12776 }
12777
a7129347
RW
12778 if (argv_find(argv, argc, "filter-list", &idx)) {
12779 const char *filter = argv[++idx]->arg;
12780 struct as_list *as_list;
12781
12782 as_list = as_list_lookup(filter);
12783 if (as_list == NULL) {
606d49a4 12784 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12785 filter);
12786 return CMD_WARNING;
12787 }
12788
12789 sh_type = bgp_show_type_filter_list;
12790 output_arg = as_list;
12791 }
12792
6deaf579
RW
12793 if (argv_find(argv, argc, "prefix-list", &idx)) {
12794 const char *prefix_list_str = argv[++idx]->arg;
12795 struct prefix_list *plist;
12796
12797 plist = prefix_list_lookup(afi, prefix_list_str);
12798 if (plist == NULL) {
606d49a4 12799 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12800 prefix_list_str);
12801 return CMD_WARNING;
12802 }
12803
12804 sh_type = bgp_show_type_prefix_list;
12805 output_arg = plist;
12806 }
12807
ed126382
DA
12808 if (argv_find(argv, argc, "access-list", &idx)) {
12809 const char *access_list_str = argv[++idx]->arg;
12810 struct access_list *alist;
12811
12812 alist = access_list_lookup(afi, access_list_str);
12813 if (!alist) {
606d49a4 12814 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12815 access_list_str);
12816 return CMD_WARNING;
12817 }
12818
12819 sh_type = bgp_show_type_access_list;
12820 output_arg = alist;
12821 }
12822
bf1a944a
RW
12823 if (argv_find(argv, argc, "route-map", &idx)) {
12824 const char *rmap_str = argv[++idx]->arg;
12825 struct route_map *rmap;
12826
12827 rmap = route_map_lookup_by_name(rmap_str);
12828 if (!rmap) {
606d49a4 12829 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12830 return CMD_WARNING;
12831 }
12832
12833 sh_type = bgp_show_type_route_map;
12834 output_arg = rmap;
12835 }
12836
1e2ce4f1
DS
12837 if (argv_find(argv, argc, "rpki", &idx)) {
12838 sh_type = bgp_show_type_rpki;
12839 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12840 rpki_target_state = RPKI_VALID;
1e2ce4f1 12841 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12842 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12843 }
12844
7d3cae70
DA
12845 /* Display prefixes with matching version numbers */
12846 if (argv_find(argv, argc, "version", &idx)) {
12847 sh_type = bgp_show_type_prefix_version;
2391833e 12848 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12849 }
12850
a70a28a5
DA
12851 /* Display prefixes with matching BGP community alias */
12852 if (argv_find(argv, argc, "alias", &idx)) {
12853 sh_type = bgp_show_type_community_alias;
2391833e 12854 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12855 }
12856
39c3c736
RW
12857 /* prefix-longer */
12858 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12859 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12860 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12861
12862 if (!str2prefix(prefix_str, &p)) {
12863 vty_out(vty, "%% Malformed Prefix\n");
12864 return CMD_WARNING;
12865 }
12866
12867 sh_type = bgp_show_type_prefix_longer;
12868 output_arg = &p;
a70a28a5
DA
12869 }
12870
96f3485c
MK
12871 if (!all) {
12872 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12873 if (community)
12874 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12875 exact_match, afi, safi,
12876 show_flags);
2391833e 12877 else
a70a28a5 12878 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12879 output_arg, show_flags,
a70a28a5 12880 rpki_target_state);
96f3485c 12881 } else {
fa5ac378
DA
12882 struct listnode *node;
12883 struct bgp *abgp;
96f3485c
MK
12884 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12885 * AFI_IP6 */
12886
12887 if (uj)
12888 vty_out(vty, "{\n");
12889
12890 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12891 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12892 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12893 ? AFI_IP
12894 : AFI_IP6;
fa5ac378
DA
12895 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12896 FOREACH_SAFI (safi) {
12897 if (!bgp_afi_safi_peer_exists(abgp, afi,
12898 safi))
12899 continue;
96f3485c 12900
fa5ac378
DA
12901 if (uj) {
12902 if (first)
12903 first = false;
12904 else
12905 vty_out(vty, ",\n");
12906 vty_out(vty, "\"%s\":{\n",
12907 get_afi_safi_str(afi,
12908 safi,
12909 true));
12910 } else
12911 vty_out(vty,
12912 "\nFor address family: %s\n",
12913 get_afi_safi_str(
12914 afi, safi,
12915 false));
12916
12917 if (community)
12918 bgp_show_community(
12919 vty, abgp, community,
12920 exact_match, afi, safi,
12921 show_flags);
96f3485c 12922 else
fa5ac378
DA
12923 bgp_show(vty, abgp, afi, safi,
12924 sh_type, output_arg,
12925 show_flags,
12926 rpki_target_state);
12927 if (uj)
12928 vty_out(vty, "}\n");
12929 }
96f3485c
MK
12930 }
12931 } else {
12932 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12933 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12934 FOREACH_AFI_SAFI (afi, safi) {
12935 if (!bgp_afi_safi_peer_exists(abgp, afi,
12936 safi))
12937 continue;
96f3485c 12938
fa5ac378
DA
12939 if (uj) {
12940 if (first)
12941 first = false;
12942 else
12943 vty_out(vty, ",\n");
12944
12945 vty_out(vty, "\"%s\":{\n",
12946 get_afi_safi_str(afi,
12947 safi,
12948 true));
12949 } else
12950 vty_out(vty,
12951 "\nFor address family: %s\n",
12952 get_afi_safi_str(
12953 afi, safi,
12954 false));
12955
12956 if (community)
12957 bgp_show_community(
12958 vty, abgp, community,
12959 exact_match, afi, safi,
12960 show_flags);
96f3485c 12961 else
fa5ac378
DA
12962 bgp_show(vty, abgp, afi, safi,
12963 sh_type, output_arg,
12964 show_flags,
12965 rpki_target_state);
12966 if (uj)
12967 vty_out(vty, "}\n");
12968 }
96f3485c
MK
12969 }
12970 }
12971 if (uj)
12972 vty_out(vty, "}\n");
12973 }
12974 return CMD_SUCCESS;
a636c635 12975}
47fc97cc 12976
718e3744 12977DEFUN (show_ip_bgp_route,
12978 show_ip_bgp_route_cmd,
8aa22bbb 12979 "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 12980 SHOW_STR
12981 IP_STR
12982 BGP_STR
a636c635 12983 BGP_INSTANCE_HELP_STR
4f280b15 12984 BGP_AFI_HELP_STR
4dd6177e 12985 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12986 "Network in the BGP routing table to display\n"
0c7b1b01 12987 "IPv4 prefix\n"
8c3deaae 12988 "Network in the BGP routing table to display\n"
0c7b1b01 12989 "IPv6 prefix\n"
4092b06c 12990 "Display only the bestpath\n"
b05a1c8b 12991 "Display only multipaths\n"
8aa22bbb
DS
12992 "Display only paths that match the specified rpki state\n"
12993 "A valid path as determined by rpki\n"
12994 "A invalid path as determined by rpki\n"
12995 "A path that has no rpki data\n"
9973d184 12996 JSON_STR)
4092b06c 12997{
d62a17ae 12998 int prefix_check = 0;
ae19d7dd 12999
d62a17ae 13000 afi_t afi = AFI_IP6;
13001 safi_t safi = SAFI_UNICAST;
13002 char *prefix = NULL;
13003 struct bgp *bgp = NULL;
13004 enum bgp_path_type path_type;
9f049418 13005 bool uj = use_json(argc, argv);
b05a1c8b 13006
d62a17ae 13007 int idx = 0;
ae19d7dd 13008
d62a17ae 13009 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13010 &bgp, uj);
d62a17ae 13011 if (!idx)
13012 return CMD_WARNING;
c41247f5 13013
d62a17ae 13014 if (!bgp) {
13015 vty_out(vty,
13016 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13017 return CMD_WARNING;
13018 }
a636c635 13019
d62a17ae 13020 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13021 if (argv_find(argv, argc, "A.B.C.D", &idx)
13022 || argv_find(argv, argc, "X:X::X:X", &idx))
13023 prefix_check = 0;
13024 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13025 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13026 prefix_check = 1;
13027
13028 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13029 && afi != AFI_IP6) {
13030 vty_out(vty,
13031 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13032 return CMD_WARNING;
13033 }
13034 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13035 && afi != AFI_IP) {
13036 vty_out(vty,
13037 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13038 return CMD_WARNING;
13039 }
13040
13041 prefix = argv[idx]->arg;
13042
13043 /* [<bestpath|multipath>] */
13044 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13045 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13046 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13047 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13048 else
360660c6 13049 path_type = BGP_PATH_SHOW_ALL;
a636c635 13050
d62a17ae 13051 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13052 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13053}
13054
8c3deaae
QY
13055DEFUN (show_ip_bgp_regexp,
13056 show_ip_bgp_regexp_cmd,
3e5b31b3 13057 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13058 SHOW_STR
13059 IP_STR
13060 BGP_STR
b00b230a 13061 BGP_INSTANCE_HELP_STR
4f280b15 13062 BGP_AFI_HELP_STR
4dd6177e 13063 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13064 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13065 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13066 JSON_STR)
8c3deaae 13067{
d62a17ae 13068 afi_t afi = AFI_IP6;
13069 safi_t safi = SAFI_UNICAST;
13070 struct bgp *bgp = NULL;
3e5b31b3
DA
13071 bool uj = use_json(argc, argv);
13072 char *regstr = NULL;
8c3deaae 13073
d62a17ae 13074 int idx = 0;
13075 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13076 &bgp, false);
d62a17ae 13077 if (!idx)
13078 return CMD_WARNING;
8c3deaae 13079
d62a17ae 13080 // get index of regex
3e5b31b3
DA
13081 if (argv_find(argv, argc, "REGEX", &idx))
13082 regstr = argv[idx]->arg;
8c3deaae 13083
5f71d11c 13084 assert(regstr);
3e5b31b3
DA
13085 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13086 bgp_show_type_regexp, uj);
8c3deaae
QY
13087}
13088
ae248832 13089DEFPY (show_ip_bgp_instance_all,
a636c635 13090 show_ip_bgp_instance_all_cmd,
ae248832 13091 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13092 SHOW_STR
a636c635 13093 IP_STR
4092b06c 13094 BGP_STR
a636c635 13095 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13096 BGP_AFI_HELP_STR
4dd6177e 13097 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13098 JSON_STR
13099 "Increase table width for longer prefixes\n")
4092b06c 13100{
54d05dea 13101 afi_t afi = AFI_IP6;
d62a17ae 13102 safi_t safi = SAFI_UNICAST;
13103 struct bgp *bgp = NULL;
d62a17ae 13104 int idx = 0;
96c81f66 13105 uint16_t show_flags = 0;
ae19d7dd 13106
96f3485c 13107 if (uj) {
d62a17ae 13108 argc--;
96f3485c
MK
13109 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13110 }
13111
13112 if (wide)
13113 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13114
9f049418
DS
13115 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13116 &bgp, uj);
13117 if (!idx)
13118 return CMD_WARNING;
13119
96f3485c 13120 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13121 return CMD_SUCCESS;
e3e29b32
LB
13122}
13123
a4d82a8a 13124static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13125 afi_t afi, safi_t safi, enum bgp_show_type type,
13126 bool use_json)
718e3744 13127{
d62a17ae 13128 regex_t *regex;
13129 int rc;
96c81f66 13130 uint16_t show_flags = 0;
96f3485c
MK
13131
13132 if (use_json)
13133 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13134
c3900853 13135 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13136 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13137 regstr);
13138 return CMD_WARNING_CONFIG_FAILED;
13139 }
13140
d62a17ae 13141 regex = bgp_regcomp(regstr);
13142 if (!regex) {
13143 vty_out(vty, "Can't compile regexp %s\n", regstr);
13144 return CMD_WARNING;
13145 }
a636c635 13146
1e2ce4f1
DS
13147 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13148 RPKI_NOT_BEING_USED);
d62a17ae 13149 bgp_regex_free(regex);
13150 return rc;
e3e29b32
LB
13151}
13152
7f323236
DW
13153static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13154 const char *comstr, int exact, afi_t afi,
96c81f66 13155 safi_t safi, uint16_t show_flags)
d62a17ae 13156{
13157 struct community *com;
d62a17ae 13158 int ret = 0;
13159
7f323236 13160 com = community_str2com(comstr);
d62a17ae 13161 if (!com) {
7f323236 13162 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13163 return CMD_WARNING;
13164 }
13165
13166 ret = bgp_show(vty, bgp, afi, safi,
13167 (exact ? bgp_show_type_community_exact
13168 : bgp_show_type_community),
1e2ce4f1 13169 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13170 community_free(&com);
46c3ce83 13171
d62a17ae 13172 return ret;
718e3744 13173}
13174
d62a17ae 13175enum bgp_stats {
13176 BGP_STATS_MAXBITLEN = 0,
13177 BGP_STATS_RIB,
13178 BGP_STATS_PREFIXES,
13179 BGP_STATS_TOTPLEN,
13180 BGP_STATS_UNAGGREGATEABLE,
13181 BGP_STATS_MAX_AGGREGATEABLE,
13182 BGP_STATS_AGGREGATES,
13183 BGP_STATS_SPACE,
13184 BGP_STATS_ASPATH_COUNT,
13185 BGP_STATS_ASPATH_MAXHOPS,
13186 BGP_STATS_ASPATH_TOTHOPS,
13187 BGP_STATS_ASPATH_MAXSIZE,
13188 BGP_STATS_ASPATH_TOTSIZE,
13189 BGP_STATS_ASN_HIGHEST,
13190 BGP_STATS_MAX,
a636c635 13191};
2815e61f 13192
9ab0cf58 13193#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13194#define TABLE_STATS_IDX_JSON 1
13195
13196static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13197 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13198 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13199 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13200 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13201 "unaggregateablePrefixes"},
13202 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13203 "maximumAggregateablePrefixes"},
13204 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13205 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13206 [BGP_STATS_SPACE] = {"Address space advertised",
13207 "addressSpaceAdvertised"},
9ab0cf58
PG
13208 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13209 "advertisementsWithPaths"},
13210 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13211 "longestAsPath"},
13212 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13213 "largestAsPath"},
13214 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13215 "averageAsPathLengthHops"},
13216 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13217 "averageAsPathSizeBytes"},
13218 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13219 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13220};
2815e61f 13221
d62a17ae 13222struct bgp_table_stats {
13223 struct bgp_table *table;
13224 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13225
13226 unsigned long long
13227 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13228 1];
13229
8d0ab76d 13230 double total_space;
ff7924f6
PJ
13231};
13232
9bcb3eef 13233static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13234 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13235{
9bcb3eef 13236 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13237 struct bgp_path_info *pi;
b54892e0 13238 const struct prefix *rn_p;
d62a17ae 13239
9bcb3eef 13240 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13241 return;
d62a17ae 13242
9bcb3eef 13243 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13244 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13245 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13246
0747643e 13247 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13248 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13249 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13250 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13251
9bcb3eef 13252 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13253 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13254 /* announced address space */
13255 if (space)
b54892e0 13256 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13257 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13258 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13259
9c14ec72 13260
9bcb3eef 13261 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13262 ts->counts[BGP_STATS_RIB]++;
13263
05864da7
DS
13264 if (CHECK_FLAG(pi->attr->flag,
13265 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13266 ts->counts[BGP_STATS_AGGREGATES]++;
13267
13268 /* as-path stats */
05864da7 13269 if (pi->attr->aspath) {
9c14ec72
RW
13270 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13271 unsigned int size = aspath_size(pi->attr->aspath);
13272 as_t highest = aspath_highest(pi->attr->aspath);
13273
13274 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13275
13276 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13277 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13278
13279 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13280 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13281
13282 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13283 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13284 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13285 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13286 }
13287 }
13288}
13289
cc9f21da 13290static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13291{
9bcb3eef
DS
13292 struct bgp_dest *dest, *ndest;
13293 struct bgp_dest *top;
9c14ec72
RW
13294 struct bgp_table_stats *ts = THREAD_ARG(t);
13295 unsigned int space = 0;
13296
13297 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13298 return;
9c14ec72
RW
13299
13300 switch (ts->table->afi) {
13301 case AFI_IP:
13302 space = IPV4_MAX_BITLEN;
13303 break;
13304 case AFI_IP6:
13305 space = IPV6_MAX_BITLEN;
13306 break;
3ba7b4af
TA
13307 case AFI_L2VPN:
13308 space = EVPN_ROUTE_PREFIXLEN;
13309 break;
58cf0823
DS
13310 case AFI_UNSPEC:
13311 case AFI_MAX:
cc9f21da 13312 return;
9c14ec72
RW
13313 }
13314
13315 ts->counts[BGP_STATS_MAXBITLEN] = space;
13316
9bcb3eef 13317 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13318 if (ts->table->safi == SAFI_MPLS_VPN
13319 || ts->table->safi == SAFI_ENCAP
13320 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13321 struct bgp_table *table;
13322
9bcb3eef 13323 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13324 if (!table)
13325 continue;
13326
13327 top = bgp_table_top(table);
9bcb3eef
DS
13328 for (ndest = bgp_table_top(table); ndest;
13329 ndest = bgp_route_next(ndest))
13330 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13331 } else {
9bcb3eef 13332 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13333 }
13334 }
2815e61f 13335}
ff7924f6 13336
71f1613a
DA
13337static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13338 struct json_object *json_array)
13339{
13340 struct listnode *node, *nnode;
13341 struct bgp *bgp;
13342
13343 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13344 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13345}
13346
13347static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13348 safi_t safi, struct json_object *json_array)
2815e61f 13349{
d62a17ae 13350 struct bgp_table_stats ts;
13351 unsigned int i;
893cccd0
PG
13352 int ret = CMD_SUCCESS;
13353 char temp_buf[20];
6c9d22e2 13354 struct json_object *json = NULL;
0747643e
AQ
13355 uint32_t bitlen = 0;
13356 struct json_object *json_bitlen;
6c9d22e2
PG
13357
13358 if (json_array)
13359 json = json_object_new_object();
019386c2 13360
d62a17ae 13361 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13362 char warning_msg[50];
13363
13364 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13365 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13366 safi);
6c9d22e2
PG
13367
13368 if (!json)
893cccd0
PG
13369 vty_out(vty, "%s\n", warning_msg);
13370 else
9ab0cf58 13371 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13372
893cccd0
PG
13373 ret = CMD_WARNING;
13374 goto end_table_stats;
d62a17ae 13375 }
019386c2 13376
893cccd0 13377 if (!json)
5290ceab
DA
13378 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13379 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13380 else
13381 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13382
d62a17ae 13383 /* labeled-unicast routes live in the unicast table */
13384 if (safi == SAFI_LABELED_UNICAST)
13385 safi = SAFI_UNICAST;
019386c2 13386
d62a17ae 13387 memset(&ts, 0, sizeof(ts));
13388 ts.table = bgp->rib[afi][safi];
13389 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13390
d62a17ae 13391 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13392 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13393 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13394 continue;
13395
13396 switch (i) {
d62a17ae 13397 case BGP_STATS_ASPATH_TOTHOPS:
13398 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13399 if (!json) {
9ab0cf58
PG
13400 snprintf(
13401 temp_buf, sizeof(temp_buf), "%12.2f",
13402 ts.counts[i]
13403 ? (float)ts.counts[i]
13404 / (float)ts.counts
13405 [BGP_STATS_ASPATH_COUNT]
13406 : 0);
893cccd0 13407 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13408 table_stats_strs[i]
13409 [TABLE_STATS_IDX_VTY],
893cccd0 13410 temp_buf);
9ab0cf58
PG
13411 } else {
13412 json_object_double_add(
13413 json,
13414 table_stats_strs[i]
13415 [TABLE_STATS_IDX_JSON],
13416 ts.counts[i]
13417 ? (double)ts.counts[i]
13418 / (double)ts.counts
d62a17ae 13419 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13420 : 0);
13421 }
d62a17ae 13422 break;
13423 case BGP_STATS_TOTPLEN:
6c9d22e2 13424 if (!json) {
9ab0cf58
PG
13425 snprintf(
13426 temp_buf, sizeof(temp_buf), "%12.2f",
13427 ts.counts[i]
13428 ? (float)ts.counts[i]
13429 / (float)ts.counts
13430 [BGP_STATS_PREFIXES]
13431 : 0);
893cccd0 13432 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13433 table_stats_strs[i]
13434 [TABLE_STATS_IDX_VTY],
893cccd0 13435 temp_buf);
9ab0cf58
PG
13436 } else {
13437 json_object_double_add(
13438 json,
13439 table_stats_strs[i]
13440 [TABLE_STATS_IDX_JSON],
13441 ts.counts[i]
13442 ? (double)ts.counts[i]
13443 / (double)ts.counts
d62a17ae 13444 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13445 : 0);
13446 }
d62a17ae 13447 break;
13448 case BGP_STATS_SPACE:
6c9d22e2
PG
13449 if (!json) {
13450 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13451 ts.total_space);
893cccd0 13452 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13453 table_stats_strs[i]
13454 [TABLE_STATS_IDX_VTY],
893cccd0 13455 temp_buf);
9ab0cf58
PG
13456 } else {
13457 json_object_double_add(
13458 json,
13459 table_stats_strs[i]
13460 [TABLE_STATS_IDX_JSON],
13461 (double)ts.total_space);
13462 }
8d0ab76d 13463 if (afi == AFI_IP6) {
6c9d22e2
PG
13464 if (!json) {
13465 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13466 "%12g",
13467 ts.total_space
13468 * pow(2.0, -128 + 32));
6c9d22e2
PG
13469 vty_out(vty, "%30s: %s\n",
13470 "/32 equivalent %s\n",
13471 temp_buf);
9ab0cf58
PG
13472 } else {
13473 json_object_double_add(
13474 json, "/32equivalent",
13475 (double)(ts.total_space
13476 * pow(2.0,
13477 -128 + 32)));
13478 }
6c9d22e2
PG
13479 if (!json) {
13480 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13481 "%12g",
13482 ts.total_space
13483 * pow(2.0, -128 + 48));
6c9d22e2
PG
13484 vty_out(vty, "%30s: %s\n",
13485 "/48 equivalent %s\n",
13486 temp_buf);
9ab0cf58
PG
13487 } else {
13488 json_object_double_add(
13489 json, "/48equivalent",
13490 (double)(ts.total_space
13491 * pow(2.0,
13492 -128 + 48)));
13493 }
8d0ab76d 13494 } else {
6c9d22e2
PG
13495 if (!json) {
13496 snprintf(temp_buf, sizeof(temp_buf),
13497 "%12.2f",
9ab0cf58
PG
13498 ts.total_space * 100.
13499 * pow(2.0, -32));
6c9d22e2 13500 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13501 "% announced ", temp_buf);
13502 } else {
13503 json_object_double_add(
13504 json, "%announced",
13505 (double)(ts.total_space * 100.
13506 * pow(2.0, -32)));
13507 }
6c9d22e2
PG
13508 if (!json) {
13509 snprintf(temp_buf, sizeof(temp_buf),
13510 "%12.2f",
9ab0cf58
PG
13511 ts.total_space
13512 * pow(2.0, -32 + 8));
6c9d22e2
PG
13513 vty_out(vty, "%30s: %s\n",
13514 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13515 } else {
13516 json_object_double_add(
13517 json, "/8equivalent",
13518 (double)(ts.total_space
13519 * pow(2.0, -32 + 8)));
13520 }
6c9d22e2
PG
13521 if (!json) {
13522 snprintf(temp_buf, sizeof(temp_buf),
13523 "%12.2f",
9ab0cf58
PG
13524 ts.total_space
13525 * pow(2.0, -32 + 24));
6c9d22e2 13526 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13527 "/24 equivalent ", temp_buf);
13528 } else {
13529 json_object_double_add(
13530 json, "/24equivalent",
13531 (double)(ts.total_space
13532 * pow(2.0, -32 + 24)));
13533 }
8d0ab76d 13534 }
d62a17ae 13535 break;
13536 default:
6c9d22e2
PG
13537 if (!json) {
13538 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13539 ts.counts[i]);
893cccd0 13540 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13541 table_stats_strs[i]
13542 [TABLE_STATS_IDX_VTY],
13543 temp_buf);
13544 } else {
13545 json_object_int_add(
13546 json,
13547 table_stats_strs[i]
13548 [TABLE_STATS_IDX_JSON],
13549 ts.counts[i]);
13550 }
d62a17ae 13551 }
893cccd0
PG
13552 if (!json)
13553 vty_out(vty, "\n");
d62a17ae 13554 }
0747643e
AQ
13555
13556 switch (afi) {
13557 case AFI_IP:
13558 bitlen = IPV4_MAX_BITLEN;
13559 break;
13560 case AFI_IP6:
13561 bitlen = IPV6_MAX_BITLEN;
13562 break;
13563 case AFI_L2VPN:
13564 bitlen = EVPN_ROUTE_PREFIXLEN;
13565 break;
58cf0823
DS
13566 case AFI_UNSPEC:
13567 case AFI_MAX:
0747643e
AQ
13568 break;
13569 }
13570
13571 if (json) {
13572 json_bitlen = json_object_new_array();
13573
13574 for (i = 0; i <= bitlen; i++) {
13575 struct json_object *ind_bit = json_object_new_object();
13576
13577 if (!ts.prefix_len_count[i])
13578 continue;
13579
13580 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13581 json_object_int_add(ind_bit, temp_buf,
13582 ts.prefix_len_count[i]);
13583 json_object_array_add(json_bitlen, ind_bit);
13584 }
13585 json_object_object_add(json, "prefixLength", json_bitlen);
13586 }
13587
9ab0cf58 13588end_table_stats:
6c9d22e2
PG
13589 if (json)
13590 json_object_array_add(json_array, json);
893cccd0 13591 return ret;
d62a17ae 13592}
13593
71f1613a
DA
13594static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13595 safi_t safi, struct json_object *json_array)
13596{
13597 if (!bgp) {
13598 bgp_table_stats_all(vty, afi, safi, json_array);
13599 return CMD_SUCCESS;
13600 }
13601
13602 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13603}
13604
d62a17ae 13605enum bgp_pcounts {
13606 PCOUNT_ADJ_IN = 0,
13607 PCOUNT_DAMPED,
13608 PCOUNT_REMOVED,
13609 PCOUNT_HISTORY,
13610 PCOUNT_STALE,
13611 PCOUNT_VALID,
13612 PCOUNT_ALL,
13613 PCOUNT_COUNTED,
7e3d9632 13614 PCOUNT_BPATH_SELECTED,
d62a17ae 13615 PCOUNT_PFCNT, /* the figure we display to users */
13616 PCOUNT_MAX,
a636c635 13617};
718e3744 13618
2b64873d 13619static const char *const pcount_strs[] = {
9d303b37
DL
13620 [PCOUNT_ADJ_IN] = "Adj-in",
13621 [PCOUNT_DAMPED] = "Damped",
13622 [PCOUNT_REMOVED] = "Removed",
13623 [PCOUNT_HISTORY] = "History",
13624 [PCOUNT_STALE] = "Stale",
13625 [PCOUNT_VALID] = "Valid",
13626 [PCOUNT_ALL] = "All RIB",
13627 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13628 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13629 [PCOUNT_PFCNT] = "Useable",
13630 [PCOUNT_MAX] = NULL,
a636c635 13631};
718e3744 13632
d62a17ae 13633struct peer_pcounts {
13634 unsigned int count[PCOUNT_MAX];
13635 const struct peer *peer;
13636 const struct bgp_table *table;
54317cba 13637 safi_t safi;
a636c635 13638};
47fc97cc 13639
9bcb3eef 13640static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13641{
54317cba
JW
13642 const struct bgp_adj_in *ain;
13643 const struct bgp_path_info *pi;
d62a17ae 13644 const struct peer *peer = pc->peer;
13645
54317cba
JW
13646 for (ain = rn->adj_in; ain; ain = ain->next)
13647 if (ain->peer == peer)
13648 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13649
9bcb3eef 13650 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13651
54317cba
JW
13652 if (pi->peer != peer)
13653 continue;
d62a17ae 13654
54317cba 13655 pc->count[PCOUNT_ALL]++;
d62a17ae 13656
54317cba
JW
13657 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13658 pc->count[PCOUNT_DAMPED]++;
13659 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13660 pc->count[PCOUNT_HISTORY]++;
13661 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13662 pc->count[PCOUNT_REMOVED]++;
13663 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13664 pc->count[PCOUNT_STALE]++;
13665 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13666 pc->count[PCOUNT_VALID]++;
13667 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13668 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13669 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13670 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13671
13672 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13673 pc->count[PCOUNT_COUNTED]++;
13674 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13675 flog_err(
13676 EC_LIB_DEVELOPMENT,
13677 "Attempting to count but flags say it is unusable");
13678 } else {
40381db7 13679 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13680 flog_err(
13681 EC_LIB_DEVELOPMENT,
13682 "Not counted but flags say we should");
d62a17ae 13683 }
13684 }
54317cba
JW
13685}
13686
cc9f21da 13687static void bgp_peer_count_walker(struct thread *t)
54317cba 13688{
9bcb3eef 13689 struct bgp_dest *rn, *rm;
54317cba
JW
13690 const struct bgp_table *table;
13691 struct peer_pcounts *pc = THREAD_ARG(t);
13692
13693 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13694 || pc->safi == SAFI_EVPN) {
13695 /* Special handling for 2-level routing tables. */
13696 for (rn = bgp_table_top(pc->table); rn;
13697 rn = bgp_route_next(rn)) {
9bcb3eef 13698 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13699 if (table != NULL)
13700 for (rm = bgp_table_top(table); rm;
13701 rm = bgp_route_next(rm))
13702 bgp_peer_count_proc(rm, pc);
13703 }
13704 } else
13705 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13706 bgp_peer_count_proc(rn, pc);
718e3744 13707}
13708
d62a17ae 13709static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13710 safi_t safi, bool use_json)
856ca177 13711{
d62a17ae 13712 struct peer_pcounts pcounts = {.peer = peer};
13713 unsigned int i;
13714 json_object *json = NULL;
13715 json_object *json_loop = NULL;
856ca177 13716
d62a17ae 13717 if (use_json) {
13718 json = json_object_new_object();
13719 json_loop = json_object_new_object();
13720 }
718e3744 13721
d62a17ae 13722 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13723 || !peer->bgp->rib[afi][safi]) {
13724 if (use_json) {
13725 json_object_string_add(
13726 json, "warning",
13727 "No such neighbor or address family");
13728 vty_out(vty, "%s\n", json_object_to_json_string(json));
13729 json_object_free(json);
d5f20468 13730 json_object_free(json_loop);
d62a17ae 13731 } else
13732 vty_out(vty, "%% No such neighbor or address family\n");
13733
13734 return CMD_WARNING;
13735 }
2a71e9ce 13736
d62a17ae 13737 memset(&pcounts, 0, sizeof(pcounts));
13738 pcounts.peer = peer;
13739 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13740 pcounts.safi = safi;
d62a17ae 13741
13742 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13743 * stats for the thread-walk (i.e. ensure this can't be blamed on
13744 * on just vty_read()).
13745 */
d62a17ae 13746 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13747
13748 if (use_json) {
13749 json_object_string_add(json, "prefixCountsFor", peer->host);
13750 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13751 get_afi_safi_str(afi, safi, true));
d62a17ae 13752 json_object_int_add(json, "pfxCounter",
13753 peer->pcount[afi][safi]);
13754
13755 for (i = 0; i < PCOUNT_MAX; i++)
13756 json_object_int_add(json_loop, pcount_strs[i],
13757 pcounts.count[i]);
13758
13759 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13760
13761 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13762 json_object_string_add(json, "pfxctDriftFor",
13763 peer->host);
13764 json_object_string_add(
13765 json, "recommended",
13766 "Please report this bug, with the above command output");
13767 }
75eeda93 13768 vty_json(vty, json);
d62a17ae 13769 } else {
13770
13771 if (peer->hostname
892fedb6 13772 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13773 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13774 peer->hostname, peer->host,
5cb5f4d0 13775 get_afi_safi_str(afi, safi, false));
d62a17ae 13776 } else {
13777 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13778 get_afi_safi_str(afi, safi, false));
d62a17ae 13779 }
13780
6cde4b45 13781 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13782 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13783
13784 for (i = 0; i < PCOUNT_MAX; i++)
13785 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13786 pcounts.count[i]);
13787
13788 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13789 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13790 vty_out(vty,
13791 "Please report this bug, with the above command output\n");
13792 }
13793 }
13794
13795 return CMD_SUCCESS;
718e3744 13796}
13797
a636c635
DW
13798DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13799 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13800 "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 13801 SHOW_STR
13802 IP_STR
13803 BGP_STR
8386ac43 13804 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13805 BGP_AFI_HELP_STR
13806 BGP_SAFI_HELP_STR
0b16f239
DS
13807 "Detailed information on TCP and BGP neighbor connections\n"
13808 "Neighbor to display information about\n"
13809 "Neighbor to display information about\n"
91d37724 13810 "Neighbor on BGP configured interface\n"
a636c635 13811 "Display detailed prefix count information\n"
9973d184 13812 JSON_STR)
0b16f239 13813{
d62a17ae 13814 afi_t afi = AFI_IP6;
13815 safi_t safi = SAFI_UNICAST;
13816 struct peer *peer;
13817 int idx = 0;
13818 struct bgp *bgp = NULL;
9f049418
DS
13819 bool uj = use_json(argc, argv);
13820
13821 if (uj)
13822 argc--;
856ca177 13823
d62a17ae 13824 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13825 &bgp, uj);
d62a17ae 13826 if (!idx)
13827 return CMD_WARNING;
0b16f239 13828
d62a17ae 13829 argv_find(argv, argc, "neighbors", &idx);
13830 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13831 if (!peer)
13832 return CMD_WARNING;
bb46e94f 13833
29c8d9da 13834 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13835}
0b16f239 13836
d6902373
PG
13837#ifdef KEEP_OLD_VPN_COMMANDS
13838DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13839 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13840 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13841 SHOW_STR
13842 IP_STR
13843 BGP_STR
d6902373 13844 BGP_VPNVX_HELP_STR
91d37724 13845 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13846 "Detailed information on TCP and BGP neighbor connections\n"
13847 "Neighbor to display information about\n"
13848 "Neighbor to display information about\n"
91d37724 13849 "Neighbor on BGP configured interface\n"
a636c635 13850 "Display detailed prefix count information\n"
9973d184 13851 JSON_STR)
a636c635 13852{
d62a17ae 13853 int idx_peer = 6;
13854 struct peer *peer;
9f049418 13855 bool uj = use_json(argc, argv);
a636c635 13856
d62a17ae 13857 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13858 if (!peer)
13859 return CMD_WARNING;
13860
13861 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13862}
13863
d6902373
PG
13864DEFUN (show_ip_bgp_vpn_all_route_prefix,
13865 show_ip_bgp_vpn_all_route_prefix_cmd,
13866 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13867 SHOW_STR
13868 IP_STR
13869 BGP_STR
d6902373 13870 BGP_VPNVX_HELP_STR
91d37724
QY
13871 "Display information about all VPNv4 NLRIs\n"
13872 "Network in the BGP routing table to display\n"
3a2d747c 13873 "Network in the BGP routing table to display\n"
9973d184 13874 JSON_STR)
91d37724 13875{
d62a17ae 13876 int idx = 0;
13877 char *network = NULL;
13878 struct bgp *bgp = bgp_get_default();
13879 if (!bgp) {
13880 vty_out(vty, "Can't find default instance\n");
13881 return CMD_WARNING;
13882 }
87e34b58 13883
d62a17ae 13884 if (argv_find(argv, argc, "A.B.C.D", &idx))
13885 network = argv[idx]->arg;
13886 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13887 network = argv[idx]->arg;
13888 else {
13889 vty_out(vty, "Unable to figure out Network\n");
13890 return CMD_WARNING;
13891 }
87e34b58 13892
d62a17ae 13893 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13894 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13895 use_json(argc, argv));
91d37724 13896}
d6902373 13897#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13898
44c69747
LK
13899DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13900 show_bgp_l2vpn_evpn_route_prefix_cmd,
13901 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13902 SHOW_STR
4c63a661
PG
13903 BGP_STR
13904 L2VPN_HELP_STR
13905 EVPN_HELP_STR
44c69747
LK
13906 "Network in the BGP routing table to display\n"
13907 "Network in the BGP routing table to display\n"
4c63a661
PG
13908 "Network in the BGP routing table to display\n"
13909 "Network in the BGP routing table to display\n"
13910 JSON_STR)
13911{
d62a17ae 13912 int idx = 0;
13913 char *network = NULL;
44c69747 13914 int prefix_check = 0;
a636c635 13915
44c69747
LK
13916 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13917 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13918 network = argv[idx]->arg;
44c69747 13919 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13920 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13921 network = argv[idx]->arg;
44c69747
LK
13922 prefix_check = 1;
13923 } else {
d62a17ae 13924 vty_out(vty, "Unable to figure out Network\n");
13925 return CMD_WARNING;
13926 }
44c69747
LK
13927 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13928 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13929 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13930}
13931
114fc229 13932static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13933 struct bgp_table *table, int *header1,
13934 int *header2, json_object *json,
13935 json_object *json_scode,
e960b4ca
TA
13936 json_object *json_ocode, bool wide,
13937 bool detail)
2f9bc755
DS
13938{
13939 uint64_t version = table ? table->version : 0;
13940
13941 if (*header1) {
13942 if (json) {
13943 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13944 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13945 "%pI4", &peer->bgp->router_id);
2f9bc755 13946 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13947 peer->bgp->default_local_pref);
13948 json_object_int_add(json, "localAS",
13949 peer->change_local_as
13950 ? peer->change_local_as
13951 : peer->local_as);
2f9bc755
DS
13952 json_object_object_add(json, "bgpStatusCodes",
13953 json_scode);
13954 json_object_object_add(json, "bgpOriginCodes",
13955 json_ocode);
13956 } else {
13957 vty_out(vty,
23d0a753
DA
13958 "BGP table version is %" PRIu64
13959 ", local router ID is %pI4, vrf id ",
114fc229
DA
13960 version, &peer->bgp->router_id);
13961 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13962 vty_out(vty, "%s", VRFID_NONE_STR);
13963 else
114fc229 13964 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13965 vty_out(vty, "\n");
13966 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13967 peer->bgp->default_local_pref);
13968 vty_out(vty, "local AS %u\n",
13969 peer->change_local_as ? peer->change_local_as
13970 : peer->local_as);
e960b4ca
TA
13971 if (!detail) {
13972 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13973 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13974 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13975 vty_out(vty, BGP_SHOW_RPKI_HEADER);
13976 }
2f9bc755
DS
13977 }
13978 *header1 = 0;
13979 }
13980 if (*header2) {
e960b4ca 13981 if (!json && !detail)
2f9bc755
DS
13982 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13983 : BGP_SHOW_HEADER));
13984 *header2 = 0;
13985 }
13986}
13987
d9478df0
TA
13988static void
13989show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13990 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13991 const char *rmap_name, json_object *json, json_object *json_ar,
13992 json_object *json_scode, json_object *json_ocode,
96c81f66 13993 uint16_t show_flags, int *header1, int *header2, char *rd_str,
3880b4ec
TA
13994 const struct prefix *match, unsigned long *output_count,
13995 unsigned long *filtered_count)
d62a17ae 13996{
3880b4ec
TA
13997 struct bgp_adj_in *ain = NULL;
13998 struct bgp_adj_out *adj = NULL;
9bcb3eef 13999 struct bgp_dest *dest;
d62a17ae 14000 struct bgp *bgp;
d62a17ae 14001 struct attr attr;
14002 int ret;
14003 struct update_subgroup *subgrp;
3880b4ec 14004 struct peer_af *paf = NULL;
f99def61 14005 bool route_filtered;
e960b4ca 14006 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
14007 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14008 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14009 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14010 || (safi == SAFI_EVPN))
14011 ? true
14012 : false;
e960b4ca
TA
14013 int display = 0;
14014 json_object *json_net = NULL;
a636c635 14015
d62a17ae 14016 bgp = peer->bgp;
a636c635 14017
3880b4ec
TA
14018 /* If the user supplied a prefix, look for a matching route instead
14019 * of walking the whole table.
14020 */
14021 if (match) {
14022 dest = bgp_node_match(table, match);
14023 if (!dest) {
14024 if (!use_json)
14025 vty_out(vty, "Network not in table\n");
14026 return;
14027 }
14028
14029 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14030
14031 if (rn_p->prefixlen != match->prefixlen) {
14032 if (!use_json)
14033 vty_out(vty, "Network not in table\n");
14034 bgp_dest_unlock_node(dest);
14035 return;
14036 }
14037
14038 if (type == bgp_show_adj_route_received ||
14039 type == bgp_show_adj_route_filtered) {
14040 for (ain = dest->adj_in; ain; ain = ain->next) {
14041 if (ain->peer == peer) {
14042 attr = *ain->attr;
14043 break;
14044 }
14045 }
14046 /* bail out if if adj_out is empty, or
14047 * if the prefix isn't in this peer's
14048 * adj_in
14049 */
14050 if (!ain || ain->peer != peer) {
14051 if (!use_json)
14052 vty_out(vty, "Network not in table\n");
14053 bgp_dest_unlock_node(dest);
14054 return;
14055 }
14056 } else if (type == bgp_show_adj_route_advertised) {
14057 bool peer_found = false;
14058
14059 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14060 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14061 if (paf->peer == peer && adj->attr) {
14062 attr = *adj->attr;
14063 peer_found = true;
14064 break;
14065 }
14066 }
14067 if (peer_found)
14068 break;
14069 }
14070 /* bail out if if adj_out is empty, or
14071 * if the prefix isn't in this peer's
14072 * adj_out
14073 */
14074 if (!paf || !peer_found) {
14075 if (!use_json)
14076 vty_out(vty, "Network not in table\n");
14077 bgp_dest_unlock_node(dest);
14078 return;
14079 }
14080 }
14081
14082 ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14083 rmap_name);
14084
14085 if (ret != RMAP_DENY) {
14086 show_adj_route_header(vty, peer, table, header1,
14087 header2, json, json_scode,
14088 json_ocode, wide, detail);
14089
14090 if (use_json)
14091 json_net = json_object_new_object();
14092
14093 bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14094 afi, safi, json_net,
14095 BGP_PATH_SHOW_ALL, &display,
14096 RPKI_NOT_BEING_USED);
14097 if (use_json)
14098 json_object_object_addf(json_ar, json_net,
14099 "%pFX", rn_p);
14100 (*output_count)++;
14101 } else
14102 (*filtered_count)++;
14103
14104 bgp_attr_flush(&attr);
14105 bgp_dest_unlock_node(dest);
14106 return;
14107 }
14108
14109
d62a17ae 14110 subgrp = peer_subgroup(peer, afi, safi);
14111
6392aaa6 14112 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14113 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14114 if (use_json) {
14115 json_object_int_add(json, "bgpTableVersion",
14116 table->version);
c949c771
DA
14117 json_object_string_addf(json, "bgpLocalRouterId",
14118 "%pI4", &bgp->router_id);
01eced22
AD
14119 json_object_int_add(json, "defaultLocPrf",
14120 bgp->default_local_pref);
114fc229
DA
14121 json_object_int_add(json, "localAS",
14122 peer->change_local_as
14123 ? peer->change_local_as
14124 : peer->local_as);
d62a17ae 14125 json_object_object_add(json, "bgpStatusCodes",
14126 json_scode);
14127 json_object_object_add(json, "bgpOriginCodes",
14128 json_ocode);
07d0c4ed
DA
14129 json_object_string_add(
14130 json, "bgpOriginatingDefaultNetwork",
14131 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14132 } else {
23d0a753
DA
14133 vty_out(vty,
14134 "BGP table version is %" PRIu64
14135 ", local router ID is %pI4, vrf id ",
14136 table->version, &bgp->router_id);
9df8b37c
PZ
14137 if (bgp->vrf_id == VRF_UNKNOWN)
14138 vty_out(vty, "%s", VRFID_NONE_STR);
14139 else
14140 vty_out(vty, "%u", bgp->vrf_id);
14141 vty_out(vty, "\n");
01eced22
AD
14142 vty_out(vty, "Default local pref %u, ",
14143 bgp->default_local_pref);
114fc229
DA
14144 vty_out(vty, "local AS %u\n",
14145 peer->change_local_as ? peer->change_local_as
14146 : peer->local_as);
e960b4ca
TA
14147 if (!detail) {
14148 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14149 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14150 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14151 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14152 }
d62a17ae 14153
07d0c4ed
DA
14154 vty_out(vty, "Originating default network %s\n\n",
14155 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14156 }
65565c9a 14157 (*output_count)++;
d9478df0 14158 *header1 = 0;
d62a17ae 14159 }
a636c635 14160
9bcb3eef 14161 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14162 if (type == bgp_show_adj_route_received
14163 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14164 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14165 if (ain->peer != peer)
ea47320b 14166 continue;
6392aaa6 14167
114fc229 14168 show_adj_route_header(vty, peer, table, header1,
d9478df0 14169 header2, json, json_scode,
e960b4ca 14170 json_ocode, wide, detail);
d9478df0
TA
14171
14172 if ((safi == SAFI_MPLS_VPN)
14173 || (safi == SAFI_ENCAP)
14174 || (safi == SAFI_EVPN)) {
14175 if (use_json)
14176 json_object_string_add(
14177 json_ar, "rd", rd_str);
14178 else if (show_rd && rd_str) {
14179 vty_out(vty,
14180 "Route Distinguisher: %s\n",
14181 rd_str);
14182 show_rd = false;
14183 }
14184 }
6392aaa6 14185
6f4f49b2 14186 attr = *ain->attr;
f99def61
AD
14187 route_filtered = false;
14188
14189 /* Filter prefix using distribute list,
14190 * filter list or prefix list
14191 */
b54892e0 14192 const struct prefix *rn_p =
9bcb3eef 14193 bgp_dest_get_prefix(dest);
b54892e0
DS
14194 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14195 safi))
14196 == FILTER_DENY)
f99def61
AD
14197 route_filtered = true;
14198
14199 /* Filter prefix using route-map */
b54892e0
DS
14200 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14201 safi, rmap_name, NULL,
14202 0, NULL);
6392aaa6 14203
13c8e163
AD
14204 if (type == bgp_show_adj_route_filtered &&
14205 !route_filtered && ret != RMAP_DENY) {
d498917e 14206 bgp_attr_flush(&attr);
6392aaa6 14207 continue;
d62a17ae 14208 }
6392aaa6 14209
d9478df0
TA
14210 if (type == bgp_show_adj_route_received
14211 && (route_filtered || ret == RMAP_DENY))
14212 (*filtered_count)++;
6392aaa6 14213
e960b4ca
TA
14214 if (detail) {
14215 if (use_json)
14216 json_net =
14217 json_object_new_object();
14218 bgp_show_path_info(
14219 NULL /* prefix_rd */, dest, vty,
14220 bgp, afi, safi, json_net,
14221 BGP_PATH_SHOW_ALL, &display,
14222 RPKI_NOT_BEING_USED);
14223 if (use_json)
14224 json_object_object_addf(
14225 json_ar, json_net,
14226 "%pFX", rn_p);
14227 } else
14228 route_vty_out_tmp(vty, dest, rn_p,
14229 &attr, safi, use_json,
14230 json_ar, wide);
d498917e 14231 bgp_attr_flush(&attr);
d9478df0 14232 (*output_count)++;
d62a17ae 14233 }
6392aaa6 14234 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14235 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14236 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14237 if (paf->peer != peer || !adj->attr)
924c3f6a 14238 continue;
d62a17ae 14239
e960b4ca
TA
14240 show_adj_route_header(
14241 vty, peer, table, header1,
14242 header2, json, json_scode,
14243 json_ocode, wide, detail);
d62a17ae 14244
b54892e0 14245 const struct prefix *rn_p =
9bcb3eef 14246 bgp_dest_get_prefix(dest);
b54892e0 14247
6f4f49b2 14248 attr = *adj->attr;
b755861b 14249 ret = bgp_output_modifier(
b54892e0 14250 peer, rn_p, &attr, afi, safi,
b755861b 14251 rmap_name);
f46d8e1e 14252
b755861b 14253 if (ret != RMAP_DENY) {
d9478df0
TA
14254 if ((safi == SAFI_MPLS_VPN)
14255 || (safi == SAFI_ENCAP)
14256 || (safi == SAFI_EVPN)) {
14257 if (use_json)
14258 json_object_string_add(
14259 json_ar,
14260 "rd",
14261 rd_str);
14262 else if (show_rd
14263 && rd_str) {
14264 vty_out(vty,
14265 "Route Distinguisher: %s\n",
14266 rd_str);
14267 show_rd = false;
14268 }
14269 }
e960b4ca
TA
14270 if (detail) {
14271 if (use_json)
14272 json_net =
14273 json_object_new_object();
14274 bgp_show_path_info(
14275 NULL /* prefix_rd
14276 */
14277 ,
14278 dest, vty, bgp,
14279 afi, safi,
14280 json_net,
14281 BGP_PATH_SHOW_ALL,
14282 &display,
14283 RPKI_NOT_BEING_USED);
14284 if (use_json)
14285 json_object_object_addf(
14286 json_ar,
14287 json_net,
14288 "%pFX",
14289 rn_p);
14290 } else
14291 route_vty_out_tmp(
14292 vty, dest, rn_p,
14293 &attr, safi,
14294 use_json,
14295 json_ar, wide);
d9478df0 14296 (*output_count)++;
b755861b 14297 } else {
d9478df0 14298 (*filtered_count)++;
a2addae8 14299 }
b755861b 14300
d498917e 14301 bgp_attr_flush(&attr);
924c3f6a 14302 }
f20ce998
DS
14303 } else if (type == bgp_show_adj_route_bestpath) {
14304 struct bgp_path_info *pi;
14305
114fc229
DA
14306 show_adj_route_header(vty, peer, table, header1,
14307 header2, json, json_scode,
e960b4ca 14308 json_ocode, wide, detail);
f20ce998 14309
aa9bf57e
TA
14310 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14311
f20ce998
DS
14312 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14313 pi = pi->next) {
14314 if (pi->peer != peer)
14315 continue;
14316
14317 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14318 continue;
14319
aa9bf57e
TA
14320 if (detail) {
14321 if (use_json)
14322 json_net =
14323 json_object_new_object();
14324 bgp_show_path_info(
14325 NULL /* prefix_rd */, dest, vty,
14326 bgp, afi, safi, json_net,
14327 BGP_PATH_SHOW_BESTPATH,
14328 &display, RPKI_NOT_BEING_USED);
14329 if (use_json)
14330 json_object_object_addf(
14331 json_ar, json_net,
14332 "%pFX", rn_p);
14333 } else
14334 route_vty_out_tmp(
14335 vty, dest, rn_p, pi->attr, safi,
14336 use_json, json_ar, wide);
d9478df0 14337 (*output_count)++;
f20ce998 14338 }
d62a17ae 14339 }
14340 }
a636c635 14341}
2a71e9ce 14342
d62a17ae 14343static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14344 safi_t safi, enum bgp_show_adj_route_type type,
3880b4ec
TA
14345 const char *rmap_name, const struct prefix *match,
14346 uint16_t show_flags)
0b16f239 14347{
d9478df0
TA
14348 struct bgp *bgp;
14349 struct bgp_table *table;
d62a17ae 14350 json_object *json = NULL;
d9478df0
TA
14351 json_object *json_scode = NULL;
14352 json_object *json_ocode = NULL;
14353 json_object *json_ar = NULL;
96f3485c 14354 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14355
d9478df0
TA
14356 /* Init BGP headers here so they're only displayed once
14357 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14358 */
14359 int header1 = 1;
14360 int header2 = 1;
14361
14362 /*
14363 * Initialize variables for each RD
14364 * All prefixes under an RD is aggregated within "json_routes"
14365 */
14366 char rd_str[BUFSIZ] = {0};
14367 json_object *json_routes = NULL;
14368
14369
14370 /* For 2-tier tables, prefix counts need to be
14371 * maintained across multiple runs of show_adj_route()
14372 */
14373 unsigned long output_count_per_rd;
14374 unsigned long filtered_count_per_rd;
14375 unsigned long output_count = 0;
14376 unsigned long filtered_count = 0;
14377
14378 if (use_json) {
d62a17ae 14379 json = json_object_new_object();
d9478df0
TA
14380 json_ar = json_object_new_object();
14381 json_scode = json_object_new_object();
14382 json_ocode = json_object_new_object();
dd426a51
DA
14383#if CONFDATE > 20231208
14384CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14385#endif
d9478df0
TA
14386 json_object_string_add(json_scode, "suppressed", "s");
14387 json_object_string_add(json_scode, "damped", "d");
14388 json_object_string_add(json_scode, "history", "h");
14389 json_object_string_add(json_scode, "valid", "*");
14390 json_object_string_add(json_scode, "best", ">");
14391 json_object_string_add(json_scode, "multipath", "=");
14392 json_object_string_add(json_scode, "internal", "i");
14393 json_object_string_add(json_scode, "ribFailure", "r");
14394 json_object_string_add(json_scode, "stale", "S");
14395 json_object_string_add(json_scode, "removed", "R");
14396
dd426a51
DA
14397#if CONFDATE > 20231208
14398CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14399#endif
d9478df0
TA
14400 json_object_string_add(json_ocode, "igp", "i");
14401 json_object_string_add(json_ocode, "egp", "e");
14402 json_object_string_add(json_ocode, "incomplete", "?");
14403 }
0b16f239 14404
d62a17ae 14405 if (!peer || !peer->afc[afi][safi]) {
14406 if (use_json) {
14407 json_object_string_add(
14408 json, "warning",
14409 "No such neighbor or address family");
14410 vty_out(vty, "%s\n", json_object_to_json_string(json));
14411 json_object_free(json);
690c3134
MW
14412 json_object_free(json_ar);
14413 json_object_free(json_scode);
14414 json_object_free(json_ocode);
d62a17ae 14415 } else
14416 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14417
d62a17ae 14418 return CMD_WARNING;
14419 }
14420
6392aaa6
PM
14421 if ((type == bgp_show_adj_route_received
14422 || type == bgp_show_adj_route_filtered)
d62a17ae 14423 && !CHECK_FLAG(peer->af_flags[afi][safi],
14424 PEER_FLAG_SOFT_RECONFIG)) {
14425 if (use_json) {
14426 json_object_string_add(
14427 json, "warning",
14428 "Inbound soft reconfiguration not enabled");
14429 vty_out(vty, "%s\n", json_object_to_json_string(json));
14430 json_object_free(json);
690c3134
MW
14431 json_object_free(json_ar);
14432 json_object_free(json_scode);
14433 json_object_free(json_ocode);
d62a17ae 14434 } else
14435 vty_out(vty,
14436 "%% Inbound soft reconfiguration not enabled\n");
14437
14438 return CMD_WARNING;
14439 }
0b16f239 14440
d9478df0
TA
14441 bgp = peer->bgp;
14442
14443 /* labeled-unicast routes live in the unicast table */
14444 if (safi == SAFI_LABELED_UNICAST)
14445 table = bgp->rib[afi][SAFI_UNICAST];
14446 else
14447 table = bgp->rib[afi][safi];
14448
14449 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14450 || (safi == SAFI_EVPN)) {
14451
14452 struct bgp_dest *dest;
14453
14454 for (dest = bgp_table_top(table); dest;
14455 dest = bgp_route_next(dest)) {
14456 table = bgp_dest_get_bgp_table_info(dest);
14457 if (!table)
14458 continue;
14459
14460 output_count_per_rd = 0;
14461 filtered_count_per_rd = 0;
14462
14463 if (use_json)
14464 json_routes = json_object_new_object();
14465
14466 const struct prefix_rd *prd;
14467 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14468 dest);
14469
14470 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14471
3880b4ec
TA
14472 show_adj_route(
14473 vty, peer, table, afi, safi, type, rmap_name,
14474 json, json_routes, json_scode, json_ocode,
14475 show_flags, &header1, &header2, rd_str, match,
14476 &output_count_per_rd, &filtered_count_per_rd);
d9478df0
TA
14477
14478 /* Don't include an empty RD in the output! */
14479 if (json_routes && (output_count_per_rd > 0))
14480 json_object_object_add(json_ar, rd_str,
14481 json_routes);
14482
14483 output_count += output_count_per_rd;
14484 filtered_count += filtered_count_per_rd;
14485 }
14486 } else
14487 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14488 json, json_ar, json_scode, json_ocode,
3880b4ec 14489 show_flags, &header1, &header2, rd_str, match,
d9478df0
TA
14490 &output_count, &filtered_count);
14491
14492 if (use_json) {
c1984955
TA
14493 if (type == bgp_show_adj_route_advertised)
14494 json_object_object_add(json, "advertisedRoutes",
14495 json_ar);
14496 else
14497 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14498 json_object_int_add(json, "totalPrefixCounter", output_count);
14499 json_object_int_add(json, "filteredPrefixCounter",
14500 filtered_count);
14501
690c3134
MW
14502 /*
14503 * These fields only give up ownership to `json` when `header1`
14504 * is used (set to zero). See code in `show_adj_route` and
14505 * `show_adj_route_header`.
14506 */
14507 if (header1 == 1) {
d9478df0
TA
14508 json_object_free(json_scode);
14509 json_object_free(json_ocode);
14510 }
14511
75eeda93 14512 vty_json(vty, json);
d9478df0 14513 } else if (output_count > 0) {
3880b4ec 14514 if (!match && filtered_count > 0)
d9478df0
TA
14515 vty_out(vty,
14516 "\nTotal number of prefixes %ld (%ld filtered)\n",
14517 output_count, filtered_count);
14518 else
14519 vty_out(vty, "\nTotal number of prefixes %ld\n",
14520 output_count);
14521 }
0b16f239 14522
d62a17ae 14523 return CMD_SUCCESS;
a636c635 14524}
50ef26d4 14525
f20ce998
DS
14526DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14527 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
aa9bf57e 14528 "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
14529 SHOW_STR
14530 IP_STR
14531 BGP_STR
14532 BGP_INSTANCE_HELP_STR
14533 BGP_AFI_HELP_STR
14534 BGP_SAFI_WITH_LABEL_HELP_STR
14535 "Detailed information on TCP and BGP neighbor connections\n"
14536 "Neighbor to display information about\n"
14537 "Neighbor to display information about\n"
14538 "Neighbor on BGP configured interface\n"
14539 "Display the routes selected by best path\n"
aa9bf57e 14540 "Display detailed version of routes\n"
f20ce998
DS
14541 JSON_STR
14542 "Increase table width for longer prefixes\n")
14543{
14544 afi_t afi = AFI_IP6;
14545 safi_t safi = SAFI_UNICAST;
14546 char *rmap_name = NULL;
14547 char *peerstr = NULL;
14548 struct bgp *bgp = NULL;
14549 struct peer *peer;
14550 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14551 int idx = 0;
96c81f66 14552 uint16_t show_flags = 0;
96f3485c 14553
aa9bf57e
TA
14554 if (detail)
14555 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14556
96f3485c
MK
14557 if (uj)
14558 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14559
14560 if (wide)
14561 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14562
14563 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14564 &bgp, uj);
14565
14566 if (!idx)
14567 return CMD_WARNING;
14568
14569 argv_find(argv, argc, "neighbors", &idx);
14570 peerstr = argv[++idx]->arg;
14571
14572 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14573 if (!peer)
14574 return CMD_WARNING;
14575
3880b4ec 14576 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
96f3485c 14577 show_flags);
f20ce998
DS
14578}
14579
e960b4ca
TA
14580DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14581 show_ip_bgp_instance_neighbor_advertised_route_cmd,
3880b4ec 14582 "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
14583 SHOW_STR
14584 IP_STR
14585 BGP_STR
14586 BGP_INSTANCE_HELP_STR
14587 BGP_AFI_HELP_STR
14588 BGP_SAFI_WITH_LABEL_HELP_STR
14589 "Display the entries for all address families\n"
14590 "Detailed information on TCP and BGP neighbor connections\n"
14591 "Neighbor to display information about\n"
14592 "Neighbor to display information about\n"
14593 "Neighbor on BGP configured interface\n"
14594 "Display the routes advertised to a BGP neighbor\n"
14595 "Display the received routes from neighbor\n"
14596 "Display the filtered routes received from neighbor\n"
14597 "Route-map to modify the attributes\n"
14598 "Name of the route map\n"
3880b4ec
TA
14599 "IPv4 prefix\n"
14600 "IPv6 prefix\n"
e960b4ca
TA
14601 "Display detailed version of routes\n"
14602 JSON_STR
14603 "Increase table width for longer prefixes\n")
718e3744 14604{
d62a17ae 14605 afi_t afi = AFI_IP6;
14606 safi_t safi = SAFI_UNICAST;
d62a17ae 14607 char *peerstr = NULL;
d62a17ae 14608 struct bgp *bgp = NULL;
14609 struct peer *peer;
6392aaa6 14610 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14611 int idx = 0;
96f3485c 14612 bool first = true;
96c81f66 14613 uint16_t show_flags = 0;
75ce3b14
DA
14614 struct listnode *node;
14615 struct bgp *abgp;
6392aaa6 14616
3880b4ec 14617 if (detail || prefix_str)
e960b4ca
TA
14618 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14619
96f3485c 14620 if (uj) {
d62a17ae 14621 argc--;
96f3485c
MK
14622 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14623 }
14624
14625 if (all) {
14626 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14627 if (argv_find(argv, argc, "ipv4", &idx))
14628 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14629
14630 if (argv_find(argv, argc, "ipv6", &idx))
14631 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14632 }
14633
14634 if (wide)
14635 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14636
9f049418
DS
14637 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14638 &bgp, uj);
14639 if (!idx)
14640 return CMD_WARNING;
14641
d62a17ae 14642 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14643 argv_find(argv, argc, "neighbors", &idx);
14644 peerstr = argv[++idx]->arg;
8c3deaae 14645
d62a17ae 14646 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14647 if (!peer)
14648 return CMD_WARNING;
856ca177 14649
d62a17ae 14650 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14651 type = bgp_show_adj_route_advertised;
14652 else if (argv_find(argv, argc, "received-routes", &idx))
14653 type = bgp_show_adj_route_received;
14654 else if (argv_find(argv, argc, "filtered-routes", &idx))
14655 type = bgp_show_adj_route_filtered;
14656
96f3485c 14657 if (!all)
70dd370f 14658 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
3880b4ec 14659 prefix_str ? prefix : NULL, show_flags);
96f3485c
MK
14660 if (uj)
14661 vty_out(vty, "{\n");
14662
14663 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14664 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14665 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14666 : AFI_IP6;
75ce3b14
DA
14667 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14668 FOREACH_SAFI (safi) {
14669 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14670 continue;
96f3485c 14671
75ce3b14
DA
14672 if (uj) {
14673 if (first)
14674 first = false;
14675 else
14676 vty_out(vty, ",\n");
14677 vty_out(vty, "\"%s\":",
14678 get_afi_safi_str(afi, safi,
14679 true));
14680 } else
14681 vty_out(vty,
14682 "\nFor address family: %s\n",
14683 get_afi_safi_str(afi, safi,
14684 false));
96f3485c 14685
75ce3b14 14686 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14687 route_map, prefix, show_flags);
75ce3b14 14688 }
96f3485c
MK
14689 }
14690 } else {
75ce3b14
DA
14691 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14692 FOREACH_AFI_SAFI (afi, safi) {
14693 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14694 continue;
96f3485c 14695
75ce3b14
DA
14696 if (uj) {
14697 if (first)
14698 first = false;
14699 else
14700 vty_out(vty, ",\n");
14701 vty_out(vty, "\"%s\":",
14702 get_afi_safi_str(afi, safi,
14703 true));
14704 } else
14705 vty_out(vty,
14706 "\nFor address family: %s\n",
14707 get_afi_safi_str(afi, safi,
14708 false));
96f3485c 14709
75ce3b14 14710 peer_adj_routes(vty, peer, afi, safi, type,
3880b4ec 14711 route_map, prefix, show_flags);
75ce3b14 14712 }
96f3485c
MK
14713 }
14714 }
14715 if (uj)
14716 vty_out(vty, "}\n");
14717
14718 return CMD_SUCCESS;
95cbbd2a
ML
14719}
14720
718e3744 14721DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14722 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14723 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14724 SHOW_STR
14725 IP_STR
14726 BGP_STR
d3120452 14727 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14728 BGP_AF_STR
14729 BGP_AF_STR
14730 BGP_AF_MODIFIER_STR
718e3744 14731 "Detailed information on TCP and BGP neighbor connections\n"
14732 "Neighbor to display information about\n"
14733 "Neighbor to display information about\n"
91d37724 14734 "Neighbor on BGP configured interface\n"
718e3744 14735 "Display information received from a BGP neighbor\n"
856ca177 14736 "Display the prefixlist filter\n"
9973d184 14737 JSON_STR)
718e3744 14738{
d62a17ae 14739 afi_t afi = AFI_IP6;
14740 safi_t safi = SAFI_UNICAST;
14741 char *peerstr = NULL;
d62a17ae 14742 char name[BUFSIZ];
d62a17ae 14743 struct peer *peer;
d3120452 14744 int count;
d62a17ae 14745 int idx = 0;
d3120452
IR
14746 struct bgp *bgp = NULL;
14747 bool uj = use_json(argc, argv);
14748
14749 if (uj)
14750 argc--;
14751
14752 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14753 &bgp, uj);
14754 if (!idx)
14755 return CMD_WARNING;
d62a17ae 14756
d62a17ae 14757 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14758 argv_find(argv, argc, "neighbors", &idx);
14759 peerstr = argv[++idx]->arg;
14760
d3120452
IR
14761 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14762 if (!peer)
14763 return CMD_WARNING;
718e3744 14764
4ced1a2c 14765 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14766 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14767 if (count) {
14768 if (!uj)
14769 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14770 get_afi_safi_str(afi, safi, false));
d62a17ae 14771 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14772 } else {
14773 if (uj)
14774 vty_out(vty, "{}\n");
14775 else
14776 vty_out(vty, "No functional output\n");
14777 }
718e3744 14778
d62a17ae 14779 return CMD_SUCCESS;
14780}
14781
14782static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14783 afi_t afi, safi_t safi,
9f049418 14784 enum bgp_show_type type, bool use_json)
d62a17ae 14785{
96c81f66 14786 uint16_t show_flags = 0;
96f3485c
MK
14787
14788 if (use_json)
14789 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14790
d62a17ae 14791 if (!peer || !peer->afc[afi][safi]) {
14792 if (use_json) {
14793 json_object *json_no = NULL;
14794 json_no = json_object_new_object();
14795 json_object_string_add(
14796 json_no, "warning",
14797 "No such neighbor or address family");
14798 vty_out(vty, "%s\n",
14799 json_object_to_json_string(json_no));
14800 json_object_free(json_no);
14801 } else
14802 vty_out(vty, "%% No such neighbor or address family\n");
14803 return CMD_WARNING;
14804 }
47fc97cc 14805
7daf25a3
TA
14806 /* labeled-unicast routes live in the unicast table */
14807 if (safi == SAFI_LABELED_UNICAST)
14808 safi = SAFI_UNICAST;
14809
1e2ce4f1
DS
14810 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14811 RPKI_NOT_BEING_USED);
718e3744 14812}
14813
dba3c1d3
PG
14814DEFUN (show_ip_bgp_flowspec_routes_detailed,
14815 show_ip_bgp_flowspec_routes_detailed_cmd,
14816 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14817 SHOW_STR
14818 IP_STR
14819 BGP_STR
14820 BGP_INSTANCE_HELP_STR
14821 BGP_AFI_HELP_STR
14822 "SAFI Flowspec\n"
14823 "Detailed information on flowspec entries\n"
14824 JSON_STR)
14825{
458c1475 14826 afi_t afi = AFI_IP6;
dba3c1d3
PG
14827 safi_t safi = SAFI_UNICAST;
14828 struct bgp *bgp = NULL;
14829 int idx = 0;
9f049418 14830 bool uj = use_json(argc, argv);
81dcd881 14831 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14832
96f3485c 14833 if (uj) {
9f049418 14834 argc--;
96f3485c
MK
14835 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14836 }
dba3c1d3
PG
14837
14838 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14839 &bgp, uj);
dba3c1d3
PG
14840 if (!idx)
14841 return CMD_WARNING;
14842
96f3485c 14843 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14844 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14845}
14846
718e3744 14847DEFUN (show_ip_bgp_neighbor_routes,
14848 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14849 "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 14850 SHOW_STR
14851 IP_STR
14852 BGP_STR
8386ac43 14853 BGP_INSTANCE_HELP_STR
4f280b15 14854 BGP_AFI_HELP_STR
4dd6177e 14855 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14856 "Detailed information on TCP and BGP neighbor connections\n"
14857 "Neighbor to display information about\n"
14858 "Neighbor to display information about\n"
91d37724 14859 "Neighbor on BGP configured interface\n"
2525cf39 14860 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14861 "Display the dampened routes received from neighbor\n"
14862 "Display routes learned from neighbor\n"
9973d184 14863 JSON_STR)
718e3744 14864{
d62a17ae 14865 char *peerstr = NULL;
14866 struct bgp *bgp = NULL;
14867 afi_t afi = AFI_IP6;
14868 safi_t safi = SAFI_UNICAST;
14869 struct peer *peer;
14870 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14871 int idx = 0;
9f049418
DS
14872 bool uj = use_json(argc, argv);
14873
14874 if (uj)
14875 argc--;
bb46e94f 14876
d62a17ae 14877 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14878 &bgp, uj);
d62a17ae 14879 if (!idx)
14880 return CMD_WARNING;
c493f2d8 14881
d62a17ae 14882 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14883 argv_find(argv, argc, "neighbors", &idx);
14884 peerstr = argv[++idx]->arg;
8c3deaae 14885
d62a17ae 14886 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14887 if (!peer)
d62a17ae 14888 return CMD_WARNING;
bb46e94f 14889
d62a17ae 14890 if (argv_find(argv, argc, "flap-statistics", &idx))
14891 sh_type = bgp_show_type_flap_neighbor;
14892 else if (argv_find(argv, argc, "dampened-routes", &idx))
14893 sh_type = bgp_show_type_damp_neighbor;
14894 else if (argv_find(argv, argc, "routes", &idx))
14895 sh_type = bgp_show_type_neighbor;
2525cf39 14896
d62a17ae 14897 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14898}
6b0655a2 14899
734b349e 14900struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14901
d62a17ae 14902struct bgp_distance {
14903 /* Distance value for the IP source prefix. */
d7c0a89a 14904 uint8_t distance;
718e3744 14905
d62a17ae 14906 /* Name of the access-list to be matched. */
14907 char *access_list;
718e3744 14908};
14909
4f280b15
LB
14910DEFUN (show_bgp_afi_vpn_rd_route,
14911 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14912 "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
14913 SHOW_STR
14914 BGP_STR
14915 BGP_AFI_HELP_STR
00e6edb9 14916 BGP_AF_MODIFIER_STR
4f280b15
LB
14917 "Display information for a route distinguisher\n"
14918 "Route Distinguisher\n"
a111dd97 14919 "All Route Distinguishers\n"
7395a2c9
DS
14920 "Network in the BGP routing table to display\n"
14921 "Network in the BGP routing table to display\n"
14922 JSON_STR)
4f280b15 14923{
d62a17ae 14924 int ret;
14925 struct prefix_rd prd;
14926 afi_t afi = AFI_MAX;
14927 int idx = 0;
4f280b15 14928
ff6566f3
DS
14929 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14930 vty_out(vty, "%% Malformed Address Family\n");
14931 return CMD_WARNING;
14932 }
14933
a111dd97
TA
14934 if (!strcmp(argv[5]->arg, "all"))
14935 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14936 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14937 RPKI_NOT_BEING_USED,
14938 use_json(argc, argv));
14939
d62a17ae 14940 ret = str2prefix_rd(argv[5]->arg, &prd);
14941 if (!ret) {
14942 vty_out(vty, "%% Malformed Route Distinguisher\n");
14943 return CMD_WARNING;
14944 }
ff6566f3 14945
d62a17ae 14946 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14947 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14948 use_json(argc, argv));
4f280b15
LB
14949}
14950
d62a17ae 14951static struct bgp_distance *bgp_distance_new(void)
718e3744 14952{
d62a17ae 14953 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14954}
14955
d62a17ae 14956static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14957{
d62a17ae 14958 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14959}
14960
585f1adc
IR
14961static int bgp_distance_set(struct vty *vty, const char *distance_str,
14962 const char *ip_str, const char *access_list_str)
718e3744 14963{
d62a17ae 14964 int ret;
585f1adc
IR
14965 afi_t afi;
14966 safi_t safi;
d62a17ae 14967 struct prefix p;
585f1adc 14968 uint8_t distance;
9bcb3eef 14969 struct bgp_dest *dest;
d62a17ae 14970 struct bgp_distance *bdistance;
718e3744 14971
585f1adc
IR
14972 afi = bgp_node_afi(vty);
14973 safi = bgp_node_safi(vty);
14974
d62a17ae 14975 ret = str2prefix(ip_str, &p);
14976 if (ret == 0) {
585f1adc 14977 vty_out(vty, "Malformed prefix\n");
d62a17ae 14978 return CMD_WARNING_CONFIG_FAILED;
14979 }
718e3744 14980
585f1adc
IR
14981 distance = atoi(distance_str);
14982
d62a17ae 14983 /* Get BGP distance node. */
9bcb3eef
DS
14984 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14985 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14986 if (bdistance)
9bcb3eef 14987 bgp_dest_unlock_node(dest);
ca2e160d 14988 else {
d62a17ae 14989 bdistance = bgp_distance_new();
9bcb3eef 14990 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14991 }
718e3744 14992
d62a17ae 14993 /* Set distance value. */
14994 bdistance->distance = distance;
718e3744 14995
d62a17ae 14996 /* Reset access-list configuration. */
e1b36e13 14997 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14998 if (access_list_str)
14999 bdistance->access_list =
15000 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 15001
d62a17ae 15002 return CMD_SUCCESS;
718e3744 15003}
15004
585f1adc
IR
15005static int bgp_distance_unset(struct vty *vty, const char *distance_str,
15006 const char *ip_str, const char *access_list_str)
718e3744 15007{
d62a17ae 15008 int ret;
585f1adc
IR
15009 afi_t afi;
15010 safi_t safi;
d62a17ae 15011 struct prefix p;
585f1adc 15012 int distance;
9bcb3eef 15013 struct bgp_dest *dest;
d62a17ae 15014 struct bgp_distance *bdistance;
718e3744 15015
585f1adc
IR
15016 afi = bgp_node_afi(vty);
15017 safi = bgp_node_safi(vty);
15018
d62a17ae 15019 ret = str2prefix(ip_str, &p);
15020 if (ret == 0) {
585f1adc 15021 vty_out(vty, "Malformed prefix\n");
d62a17ae 15022 return CMD_WARNING_CONFIG_FAILED;
15023 }
718e3744 15024
9bcb3eef
DS
15025 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15026 if (!dest) {
585f1adc 15027 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 15028 return CMD_WARNING_CONFIG_FAILED;
15029 }
718e3744 15030
9bcb3eef 15031 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 15032 distance = atoi(distance_str);
1f9a9fff 15033
d62a17ae 15034 if (bdistance->distance != distance) {
585f1adc 15035 vty_out(vty, "Distance does not match configured\n");
89f4bd87 15036 bgp_dest_unlock_node(dest);
d62a17ae 15037 return CMD_WARNING_CONFIG_FAILED;
15038 }
718e3744 15039
0a22ddfb 15040 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 15041 bgp_distance_free(bdistance);
718e3744 15042
9bcb3eef
DS
15043 bgp_dest_set_bgp_path_info(dest, NULL);
15044 bgp_dest_unlock_node(dest);
15045 bgp_dest_unlock_node(dest);
718e3744 15046
d62a17ae 15047 return CMD_SUCCESS;
718e3744 15048}
15049
718e3744 15050/* Apply BGP information to distance method. */
b8685f9b 15051uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 15052 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 15053{
9bcb3eef 15054 struct bgp_dest *dest;
801bb996 15055 struct prefix q = {0};
d62a17ae 15056 struct peer *peer;
15057 struct bgp_distance *bdistance;
15058 struct access_list *alist;
15059 struct bgp_static *bgp_static;
a04f1c42 15060 struct bgp_path_info *bpi_ultimate;
d62a17ae 15061
15062 if (!bgp)
15063 return 0;
15064
40381db7 15065 peer = pinfo->peer;
d62a17ae 15066
7b7d48e5
DS
15067 if (pinfo->attr->distance)
15068 return pinfo->attr->distance;
15069
a04f1c42
PG
15070 /* get peer origin to calculate appropriate distance */
15071 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15072 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15073 peer = bpi_ultimate->peer;
15074 }
15075
801bb996
CS
15076 /* Check source address.
15077 * Note: for aggregate route, peer can have unspec af type.
15078 */
15079 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15080 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
15081 return 0;
15082
9bcb3eef
DS
15083 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15084 if (dest) {
15085 bdistance = bgp_dest_get_bgp_distance_info(dest);
15086 bgp_dest_unlock_node(dest);
d62a17ae 15087
15088 if (bdistance->access_list) {
15089 alist = access_list_lookup(afi, bdistance->access_list);
15090 if (alist
15091 && access_list_apply(alist, p) == FILTER_PERMIT)
15092 return bdistance->distance;
15093 } else
15094 return bdistance->distance;
718e3744 15095 }
718e3744 15096
d62a17ae 15097 /* Backdoor check. */
9bcb3eef
DS
15098 dest = bgp_node_lookup(bgp->route[afi][safi], p);
15099 if (dest) {
15100 bgp_static = bgp_dest_get_bgp_static_info(dest);
15101 bgp_dest_unlock_node(dest);
718e3744 15102
d62a17ae 15103 if (bgp_static->backdoor) {
15104 if (bgp->distance_local[afi][safi])
15105 return bgp->distance_local[afi][safi];
15106 else
15107 return ZEBRA_IBGP_DISTANCE_DEFAULT;
15108 }
718e3744 15109 }
718e3744 15110
d62a17ae 15111 if (peer->sort == BGP_PEER_EBGP) {
15112 if (bgp->distance_ebgp[afi][safi])
15113 return bgp->distance_ebgp[afi][safi];
15114 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 15115 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 15116 if (bgp->distance_ibgp[afi][safi])
15117 return bgp->distance_ibgp[afi][safi];
15118 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
15119 } else {
15120 if (bgp->distance_local[afi][safi])
15121 return bgp->distance_local[afi][safi];
15122 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 15123 }
718e3744 15124}
15125
a612fb77
DA
15126/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15127 * we should tell ZEBRA update the routes for a specific
15128 * AFI/SAFI to reflect changes in RIB.
15129 */
585f1adc
IR
15130static void bgp_announce_routes_distance_update(struct bgp *bgp,
15131 afi_t update_afi,
15132 safi_t update_safi)
a612fb77
DA
15133{
15134 afi_t afi;
15135 safi_t safi;
15136
15137 FOREACH_AFI_SAFI (afi, safi) {
15138 if (!bgp_fibupd_safi(safi))
15139 continue;
15140
8b54bc30
DA
15141 if (afi != update_afi && safi != update_safi)
15142 continue;
15143
15144 if (BGP_DEBUG(zebra, ZEBRA))
15145 zlog_debug(
15146 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15147 __func__, afi, safi);
15148 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15149 }
15150}
15151
585f1adc
IR
15152DEFUN (bgp_distance,
15153 bgp_distance_cmd,
15154 "distance bgp (1-255) (1-255) (1-255)",
15155 "Define an administrative distance\n"
15156 "BGP distance\n"
15157 "Distance for routes external to the AS\n"
15158 "Distance for routes internal to the AS\n"
15159 "Distance for local routes\n")
718e3744 15160{
585f1adc 15161 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15162 int idx_number = 2;
15163 int idx_number_2 = 3;
15164 int idx_number_3 = 4;
585f1adc
IR
15165 int distance_ebgp = atoi(argv[idx_number]->arg);
15166 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15167 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15168 afi_t afi;
15169 safi_t safi;
718e3744 15170
d62a17ae 15171 afi = bgp_node_afi(vty);
15172 safi = bgp_node_safi(vty);
718e3744 15173
585f1adc
IR
15174 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15175 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15176 || bgp->distance_local[afi][safi] != distance_local) {
15177 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15178 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15179 bgp->distance_local[afi][safi] = distance_local;
15180 bgp_announce_routes_distance_update(bgp, afi, safi);
15181 }
15182 return CMD_SUCCESS;
15183}
37a87b8f 15184
585f1adc
IR
15185DEFUN (no_bgp_distance,
15186 no_bgp_distance_cmd,
15187 "no distance bgp [(1-255) (1-255) (1-255)]",
15188 NO_STR
15189 "Define an administrative distance\n"
15190 "BGP distance\n"
15191 "Distance for routes external to the AS\n"
15192 "Distance for routes internal to the AS\n"
15193 "Distance for local routes\n")
718e3744 15194{
585f1adc 15195 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15196 afi_t afi;
15197 safi_t safi;
37a87b8f
CS
15198
15199 afi = bgp_node_afi(vty);
15200 safi = bgp_node_safi(vty);
15201
585f1adc
IR
15202 if (bgp->distance_ebgp[afi][safi] != 0
15203 || bgp->distance_ibgp[afi][safi] != 0
15204 || bgp->distance_local[afi][safi] != 0) {
15205 bgp->distance_ebgp[afi][safi] = 0;
15206 bgp->distance_ibgp[afi][safi] = 0;
15207 bgp->distance_local[afi][safi] = 0;
15208 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15209 }
585f1adc
IR
15210 return CMD_SUCCESS;
15211}
37a87b8f 15212
37a87b8f 15213
585f1adc
IR
15214DEFUN (bgp_distance_source,
15215 bgp_distance_source_cmd,
15216 "distance (1-255) A.B.C.D/M",
15217 "Define an administrative distance\n"
15218 "Administrative distance\n"
15219 "IP source prefix\n")
15220{
15221 int idx_number = 1;
15222 int idx_ipv4_prefixlen = 2;
15223 bgp_distance_set(vty, argv[idx_number]->arg,
15224 argv[idx_ipv4_prefixlen]->arg, NULL);
15225 return CMD_SUCCESS;
734b349e
MZ
15226}
15227
585f1adc
IR
15228DEFUN (no_bgp_distance_source,
15229 no_bgp_distance_source_cmd,
15230 "no distance (1-255) A.B.C.D/M",
15231 NO_STR
15232 "Define an administrative distance\n"
15233 "Administrative distance\n"
15234 "IP source prefix\n")
37a87b8f 15235{
585f1adc
IR
15236 int idx_number = 2;
15237 int idx_ipv4_prefixlen = 3;
15238 bgp_distance_unset(vty, argv[idx_number]->arg,
15239 argv[idx_ipv4_prefixlen]->arg, NULL);
15240 return CMD_SUCCESS;
37a87b8f
CS
15241}
15242
585f1adc
IR
15243DEFUN (bgp_distance_source_access_list,
15244 bgp_distance_source_access_list_cmd,
15245 "distance (1-255) A.B.C.D/M WORD",
15246 "Define an administrative distance\n"
15247 "Administrative distance\n"
15248 "IP source prefix\n"
15249 "Access list name\n")
37a87b8f 15250{
585f1adc
IR
15251 int idx_number = 1;
15252 int idx_ipv4_prefixlen = 2;
15253 int idx_word = 3;
15254 bgp_distance_set(vty, argv[idx_number]->arg,
15255 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15256 return CMD_SUCCESS;
15257}
718e3744 15258
585f1adc
IR
15259DEFUN (no_bgp_distance_source_access_list,
15260 no_bgp_distance_source_access_list_cmd,
15261 "no distance (1-255) A.B.C.D/M WORD",
15262 NO_STR
15263 "Define an administrative distance\n"
15264 "Administrative distance\n"
15265 "IP source prefix\n"
15266 "Access list name\n")
15267{
15268 int idx_number = 2;
15269 int idx_ipv4_prefixlen = 3;
15270 int idx_word = 4;
15271 bgp_distance_unset(vty, argv[idx_number]->arg,
15272 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15273 return CMD_SUCCESS;
15274}
37a87b8f 15275
585f1adc
IR
15276DEFUN (ipv6_bgp_distance_source,
15277 ipv6_bgp_distance_source_cmd,
15278 "distance (1-255) X:X::X:X/M",
15279 "Define an administrative distance\n"
15280 "Administrative distance\n"
15281 "IP source prefix\n")
15282{
15283 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15284 return CMD_SUCCESS;
15285}
7ebe9748 15286
585f1adc
IR
15287DEFUN (no_ipv6_bgp_distance_source,
15288 no_ipv6_bgp_distance_source_cmd,
15289 "no distance (1-255) X:X::X:X/M",
15290 NO_STR
15291 "Define an administrative distance\n"
15292 "Administrative distance\n"
15293 "IP source prefix\n")
15294{
15295 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15296 return CMD_SUCCESS;
15297}
37a87b8f 15298
585f1adc
IR
15299DEFUN (ipv6_bgp_distance_source_access_list,
15300 ipv6_bgp_distance_source_access_list_cmd,
15301 "distance (1-255) X:X::X:X/M WORD",
15302 "Define an administrative distance\n"
15303 "Administrative distance\n"
15304 "IP source prefix\n"
15305 "Access list name\n")
15306{
15307 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15308 return CMD_SUCCESS;
718e3744 15309}
15310
585f1adc
IR
15311DEFUN (no_ipv6_bgp_distance_source_access_list,
15312 no_ipv6_bgp_distance_source_access_list_cmd,
15313 "no distance (1-255) X:X::X:X/M WORD",
15314 NO_STR
15315 "Define an administrative distance\n"
15316 "Administrative distance\n"
15317 "IP source prefix\n"
15318 "Access list name\n")
718e3744 15319{
585f1adc
IR
15320 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15321 return CMD_SUCCESS;
15322}
37a87b8f 15323
585f1adc
IR
15324DEFUN (bgp_damp_set,
15325 bgp_damp_set_cmd,
a30fec23 15326 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15327 "BGP Specific commands\n"
15328 "Enable route-flap dampening\n"
15329 "Half-life time for the penalty\n"
15330 "Value to start reusing a route\n"
15331 "Value to start suppressing a route\n"
15332 "Maximum duration to suppress a stable route\n")
15333{
15334 VTY_DECLVAR_CONTEXT(bgp, bgp);
15335 int idx_half_life = 2;
15336 int idx_reuse = 3;
15337 int idx_suppress = 4;
15338 int idx_max_suppress = 5;
37a87b8f
CS
15339 int half = DEFAULT_HALF_LIFE * 60;
15340 int reuse = DEFAULT_REUSE;
15341 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15342 int max = 4 * half;
15343
15344 if (argc == 6) {
15345 half = atoi(argv[idx_half_life]->arg) * 60;
15346 reuse = atoi(argv[idx_reuse]->arg);
15347 suppress = atoi(argv[idx_suppress]->arg);
15348 max = atoi(argv[idx_max_suppress]->arg) * 60;
15349 } else if (argc == 3) {
15350 half = atoi(argv[idx_half_life]->arg) * 60;
15351 max = 4 * half;
15352 }
15353
15354 /*
15355 * These can't be 0 but our SA doesn't understand the
15356 * way our cli is constructed
15357 */
15358 assert(reuse);
15359 assert(half);
15360 if (suppress < reuse) {
15361 vty_out(vty,
15362 "Suppress value cannot be less than reuse value \n");
15363 return 0;
15364 }
15365
15366 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15367 reuse, suppress, max);
15368}
15369
15370DEFUN (bgp_damp_unset,
15371 bgp_damp_unset_cmd,
a30fec23 15372 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15373 NO_STR
15374 "BGP Specific commands\n"
15375 "Enable route-flap dampening\n"
15376 "Half-life time for the penalty\n"
15377 "Value to start reusing a route\n"
15378 "Value to start suppressing a route\n"
15379 "Maximum duration to suppress a stable route\n")
15380{
15381 VTY_DECLVAR_CONTEXT(bgp, bgp);
15382 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15383}
15384
718e3744 15385/* Display specified route of BGP table. */
d62a17ae 15386static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15387 const char *ip_str, afi_t afi, safi_t safi,
15388 struct prefix_rd *prd, int prefix_check)
15389{
15390 int ret;
15391 struct prefix match;
9bcb3eef
DS
15392 struct bgp_dest *dest;
15393 struct bgp_dest *rm;
40381db7
DS
15394 struct bgp_path_info *pi;
15395 struct bgp_path_info *pi_temp;
d62a17ae 15396 struct bgp *bgp;
15397 struct bgp_table *table;
15398
15399 /* BGP structure lookup. */
15400 if (view_name) {
15401 bgp = bgp_lookup_by_name(view_name);
15402 if (bgp == NULL) {
15403 vty_out(vty, "%% Can't find BGP instance %s\n",
15404 view_name);
15405 return CMD_WARNING;
15406 }
15407 } else {
15408 bgp = bgp_get_default();
15409 if (bgp == NULL) {
15410 vty_out(vty, "%% No BGP process is configured\n");
15411 return CMD_WARNING;
15412 }
718e3744 15413 }
718e3744 15414
d62a17ae 15415 /* Check IP address argument. */
15416 ret = str2prefix(ip_str, &match);
15417 if (!ret) {
15418 vty_out(vty, "%% address is malformed\n");
15419 return CMD_WARNING;
15420 }
718e3744 15421
d62a17ae 15422 match.family = afi2family(afi);
15423
15424 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15425 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15426 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15427 dest = bgp_route_next(dest)) {
15428 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15429
9bcb3eef 15430 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15431 continue;
9bcb3eef 15432 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15433 if (!table)
ea47320b 15434 continue;
4953391b
DA
15435 rm = bgp_node_match(table, &match);
15436 if (rm == NULL)
ea47320b 15437 continue;
d62a17ae 15438
9bcb3eef 15439 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15440
ea47320b 15441 if (!prefix_check
b54892e0 15442 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15443 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15444 while (pi) {
15445 if (pi->extra && pi->extra->damp_info) {
15446 pi_temp = pi->next;
ea47320b 15447 bgp_damp_info_free(
19971c9a 15448 pi->extra->damp_info,
5c8846f6 15449 1, afi, safi);
40381db7 15450 pi = pi_temp;
ea47320b 15451 } else
40381db7 15452 pi = pi->next;
d62a17ae 15453 }
ea47320b
DL
15454 }
15455
9bcb3eef 15456 bgp_dest_unlock_node(rm);
d62a17ae 15457 }
15458 } else {
4953391b
DA
15459 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15460 if (dest != NULL) {
9bcb3eef 15461 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15462
d62a17ae 15463 if (!prefix_check
9bcb3eef
DS
15464 || dest_p->prefixlen == match.prefixlen) {
15465 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15466 while (pi) {
15467 if (pi->extra && pi->extra->damp_info) {
15468 pi_temp = pi->next;
d62a17ae 15469 bgp_damp_info_free(
19971c9a 15470 pi->extra->damp_info,
5c8846f6 15471 1, afi, safi);
40381db7 15472 pi = pi_temp;
d62a17ae 15473 } else
40381db7 15474 pi = pi->next;
d62a17ae 15475 }
15476 }
15477
9bcb3eef 15478 bgp_dest_unlock_node(dest);
d62a17ae 15479 }
15480 }
718e3744 15481
d62a17ae 15482 return CMD_SUCCESS;
718e3744 15483}
15484
15485DEFUN (clear_ip_bgp_dampening,
15486 clear_ip_bgp_dampening_cmd,
15487 "clear ip bgp dampening",
15488 CLEAR_STR
15489 IP_STR
15490 BGP_STR
15491 "Clear route flap dampening information\n")
15492{
b4f7f45b 15493 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15494 return CMD_SUCCESS;
718e3744 15495}
15496
15497DEFUN (clear_ip_bgp_dampening_prefix,
15498 clear_ip_bgp_dampening_prefix_cmd,
15499 "clear ip bgp dampening A.B.C.D/M",
15500 CLEAR_STR
15501 IP_STR
15502 BGP_STR
15503 "Clear route flap dampening information\n"
0c7b1b01 15504 "IPv4 prefix\n")
718e3744 15505{
d62a17ae 15506 int idx_ipv4_prefixlen = 4;
15507 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15508 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15509}
15510
15511DEFUN (clear_ip_bgp_dampening_address,
15512 clear_ip_bgp_dampening_address_cmd,
15513 "clear ip bgp dampening A.B.C.D",
15514 CLEAR_STR
15515 IP_STR
15516 BGP_STR
15517 "Clear route flap dampening information\n"
15518 "Network to clear damping information\n")
15519{
d62a17ae 15520 int idx_ipv4 = 4;
15521 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15522 SAFI_UNICAST, NULL, 0);
718e3744 15523}
15524
15525DEFUN (clear_ip_bgp_dampening_address_mask,
15526 clear_ip_bgp_dampening_address_mask_cmd,
15527 "clear ip bgp dampening A.B.C.D A.B.C.D",
15528 CLEAR_STR
15529 IP_STR
15530 BGP_STR
15531 "Clear route flap dampening information\n"
15532 "Network to clear damping information\n"
15533 "Network mask\n")
15534{
d62a17ae 15535 int idx_ipv4 = 4;
15536 int idx_ipv4_2 = 5;
15537 int ret;
15538 char prefix_str[BUFSIZ];
718e3744 15539
d62a17ae 15540 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15541 prefix_str, sizeof(prefix_str));
d62a17ae 15542 if (!ret) {
15543 vty_out(vty, "%% Inconsistent address and mask\n");
15544 return CMD_WARNING;
15545 }
718e3744 15546
d62a17ae 15547 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15548 NULL, 0);
718e3744 15549}
6b0655a2 15550
e3b78da8 15551static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15552{
15553 struct vty *vty = arg;
e3b78da8 15554 struct peer *peer = bucket->data;
825d9834 15555
47e12884 15556 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15557}
15558
2a0e69ae
DS
15559DEFUN (show_bgp_listeners,
15560 show_bgp_listeners_cmd,
15561 "show bgp listeners",
15562 SHOW_STR
15563 BGP_STR
15564 "Display Listen Sockets and who created them\n")
15565{
15566 bgp_dump_listener_info(vty);
15567
15568 return CMD_SUCCESS;
15569}
15570
825d9834
DS
15571DEFUN (show_bgp_peerhash,
15572 show_bgp_peerhash_cmd,
15573 "show bgp peerhash",
15574 SHOW_STR
15575 BGP_STR
15576 "Display information about the BGP peerhash\n")
15577{
15578 struct list *instances = bm->bgp;
15579 struct listnode *node;
15580 struct bgp *bgp;
15581
15582 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15583 vty_out(vty, "BGP: %s\n", bgp->name);
15584 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15585 vty);
15586 }
15587
15588 return CMD_SUCCESS;
15589}
15590
587ff0fd 15591/* also used for encap safi */
2b791107
DL
15592static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15593 afi_t afi, safi_t safi)
d62a17ae 15594{
9bcb3eef
DS
15595 struct bgp_dest *pdest;
15596 struct bgp_dest *dest;
d62a17ae 15597 struct bgp_table *table;
b54892e0
DS
15598 const struct prefix *p;
15599 const struct prefix_rd *prd;
d62a17ae 15600 struct bgp_static *bgp_static;
15601 mpls_label_t label;
d62a17ae 15602
15603 /* Network configuration. */
9bcb3eef
DS
15604 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15605 pdest = bgp_route_next(pdest)) {
15606 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15607 if (!table)
ea47320b 15608 continue;
d62a17ae 15609
9bcb3eef
DS
15610 for (dest = bgp_table_top(table); dest;
15611 dest = bgp_route_next(dest)) {
15612 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15613 if (bgp_static == NULL)
ea47320b 15614 continue;
d62a17ae 15615
9bcb3eef
DS
15616 p = bgp_dest_get_prefix(dest);
15617 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15618 pdest);
d62a17ae 15619
ea47320b 15620 /* "network" configuration display. */
ea47320b
DL
15621 label = decode_label(&bgp_static->label);
15622
c4f64ea9 15623 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15624 if (safi == SAFI_MPLS_VPN)
15625 vty_out(vty, " label %u", label);
15626
15627 if (bgp_static->rmap.name)
15628 vty_out(vty, " route-map %s",
15629 bgp_static->rmap.name);
e2a86ad9
DS
15630
15631 if (bgp_static->backdoor)
15632 vty_out(vty, " backdoor");
15633
ea47320b
DL
15634 vty_out(vty, "\n");
15635 }
15636 }
d62a17ae 15637}
15638
2b791107
DL
15639static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15640 afi_t afi, safi_t safi)
d62a17ae 15641{
9bcb3eef
DS
15642 struct bgp_dest *pdest;
15643 struct bgp_dest *dest;
d62a17ae 15644 struct bgp_table *table;
b54892e0
DS
15645 const struct prefix *p;
15646 const struct prefix_rd *prd;
d62a17ae 15647 struct bgp_static *bgp_static;
ff44f570 15648 char buf[PREFIX_STRLEN * 2];
d62a17ae 15649 char buf2[SU_ADDRSTRLEN];
5f933e1e 15650 char esi_buf[ESI_STR_LEN];
d62a17ae 15651
15652 /* Network configuration. */
9bcb3eef
DS
15653 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15654 pdest = bgp_route_next(pdest)) {
15655 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15656 if (!table)
ea47320b 15657 continue;
d62a17ae 15658
9bcb3eef
DS
15659 for (dest = bgp_table_top(table); dest;
15660 dest = bgp_route_next(dest)) {
15661 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15662 if (bgp_static == NULL)
ea47320b 15663 continue;
d62a17ae 15664
ea47320b 15665 char *macrouter = NULL;
d62a17ae 15666
ea47320b
DL
15667 if (bgp_static->router_mac)
15668 macrouter = prefix_mac2str(
15669 bgp_static->router_mac, NULL, 0);
15670 if (bgp_static->eth_s_id)
0a50c248
AK
15671 esi_to_str(bgp_static->eth_s_id,
15672 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15673 p = bgp_dest_get_prefix(dest);
15674 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15675
ea47320b 15676 /* "network" configuration display. */
197cb530
PG
15677 if (p->u.prefix_evpn.route_type == 5) {
15678 char local_buf[PREFIX_STRLEN];
07380148 15679
3714a385 15680 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15681 struct prefix_evpn *)p)
15682 ? AF_INET
15683 : AF_INET6;
3714a385 15684 inet_ntop(family,
07380148
DA
15685 &p->u.prefix_evpn.prefix_addr.ip.ip
15686 .addr,
15687 local_buf, sizeof(local_buf));
772270f3
QY
15688 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15689 p->u.prefix_evpn.prefix_addr
15690 .ip_prefix_length);
197cb530
PG
15691 } else {
15692 prefix2str(p, buf, sizeof(buf));
15693 }
ea47320b 15694
a4d82a8a
PZ
15695 if (bgp_static->gatewayIp.family == AF_INET
15696 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15697 inet_ntop(bgp_static->gatewayIp.family,
15698 &bgp_static->gatewayIp.u.prefix, buf2,
15699 sizeof(buf2));
ea47320b 15700 vty_out(vty,
c4f64ea9
DA
15701 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15702 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15703 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15704 macrouter);
15705
0a22ddfb 15706 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15707 }
15708 }
3da6fcd5
PG
15709}
15710
718e3744 15711/* Configuration of static route announcement and aggregate
15712 information. */
2b791107
DL
15713void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15714 safi_t safi)
d62a17ae 15715{
9bcb3eef 15716 struct bgp_dest *dest;
b54892e0 15717 const struct prefix *p;
d62a17ae 15718 struct bgp_static *bgp_static;
15719 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15720
2b791107
DL
15721 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15722 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15723 return;
15724 }
d62a17ae 15725
2b791107
DL
15726 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15727 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15728 return;
15729 }
d62a17ae 15730
15731 /* Network configuration. */
9bcb3eef
DS
15732 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15733 dest = bgp_route_next(dest)) {
15734 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15735 if (bgp_static == NULL)
ea47320b 15736 continue;
d62a17ae 15737
9bcb3eef 15738 p = bgp_dest_get_prefix(dest);
d62a17ae 15739
8228a9a7 15740 vty_out(vty, " network %pFX", p);
d62a17ae 15741
ea47320b
DL
15742 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15743 vty_out(vty, " label-index %u",
15744 bgp_static->label_index);
d62a17ae 15745
ea47320b
DL
15746 if (bgp_static->rmap.name)
15747 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15748
15749 if (bgp_static->backdoor)
15750 vty_out(vty, " backdoor");
718e3744 15751
ea47320b
DL
15752 vty_out(vty, "\n");
15753 }
15754
d62a17ae 15755 /* Aggregate-address configuration. */
9bcb3eef
DS
15756 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15757 dest = bgp_route_next(dest)) {
15758 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15759 if (bgp_aggregate == NULL)
ea47320b 15760 continue;
d62a17ae 15761
9bcb3eef 15762 p = bgp_dest_get_prefix(dest);
d62a17ae 15763
8228a9a7 15764 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15765
ea47320b
DL
15766 if (bgp_aggregate->as_set)
15767 vty_out(vty, " as-set");
d62a17ae 15768
ea47320b
DL
15769 if (bgp_aggregate->summary_only)
15770 vty_out(vty, " summary-only");
718e3744 15771
20894f50
DA
15772 if (bgp_aggregate->rmap.name)
15773 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15774
229757f1
DA
15775 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15776 vty_out(vty, " origin %s",
15777 bgp_origin2str(bgp_aggregate->origin));
15778
6aabb15d
RZ
15779 if (bgp_aggregate->match_med)
15780 vty_out(vty, " matching-MED-only");
15781
365ab2e7
RZ
15782 if (bgp_aggregate->suppress_map_name)
15783 vty_out(vty, " suppress-map %s",
15784 bgp_aggregate->suppress_map_name);
15785
ea47320b
DL
15786 vty_out(vty, "\n");
15787 }
d62a17ae 15788}
734b349e 15789
2b791107 15790void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15791 safi_t safi)
d62a17ae 15792{
9bcb3eef 15793 struct bgp_dest *dest;
d62a17ae 15794 struct bgp_distance *bdistance;
15795
15796 /* Distance configuration. */
15797 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15798 && bgp->distance_local[afi][safi]
15799 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15800 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15801 || bgp->distance_local[afi][safi]
15802 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15803 vty_out(vty, " distance bgp %d %d %d\n",
15804 bgp->distance_ebgp[afi][safi],
15805 bgp->distance_ibgp[afi][safi],
15806 bgp->distance_local[afi][safi]);
15807 }
734b349e 15808
9bcb3eef
DS
15809 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15810 dest = bgp_route_next(dest)) {
15811 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15812 if (bdistance != NULL)
56ca3b5b 15813 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15814 bdistance->distance, dest,
d62a17ae 15815 bdistance->access_list ? bdistance->access_list
15816 : "");
ca2e160d 15817 }
718e3744 15818}
15819
15820/* Allocate routing table structure and install commands. */
d62a17ae 15821void bgp_route_init(void)
15822{
15823 afi_t afi;
15824 safi_t safi;
15825
15826 /* Init BGP distance table. */
05c7a1cc 15827 FOREACH_AFI_SAFI (afi, safi)
960035b2 15828 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15829
15830 /* IPv4 BGP commands. */
15831 install_element(BGP_NODE, &bgp_table_map_cmd);
15832 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15833 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15834
554b3b10 15835 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15836
15837 /* IPv4 unicast configuration. */
15838 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15839 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15840 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15841
554b3b10 15842 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15843
15844 /* IPv4 multicast configuration. */
15845 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15846 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15847 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15848 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15849
15850 /* IPv4 labeled-unicast configuration. */
fb985e0c 15851 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15852 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15853
d62a17ae 15854 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15855 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15856 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15857 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15858 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15859 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15860 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15861 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15862
15863 install_element(VIEW_NODE,
15864 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15865 install_element(VIEW_NODE,
15866 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15867 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15868 install_element(VIEW_NODE,
15869 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15870#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15871 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15872#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15873 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15874 install_element(VIEW_NODE,
44c69747 15875 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15876
d62a17ae 15877 /* BGP dampening clear commands */
15878 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15879 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15880
d62a17ae 15881 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15882 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15883
15884 /* prefix count */
15885 install_element(ENABLE_NODE,
15886 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15887#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15888 install_element(ENABLE_NODE,
15889 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15890#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15891
d62a17ae 15892 /* New config IPv6 BGP commands. */
15893 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15894 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15895 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15896
554b3b10 15897 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15898
15899 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15900
fb985e0c
DA
15901 /* IPv6 labeled unicast address family. */
15902 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15903 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15904
d62a17ae 15905 install_element(BGP_NODE, &bgp_distance_cmd);
15906 install_element(BGP_NODE, &no_bgp_distance_cmd);
15907 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15908 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15909 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15910 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15911 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15912 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15913 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15914 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15915 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15916 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15917 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15918 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15919 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15920 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15921 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15922 install_element(BGP_IPV4M_NODE,
15923 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15924 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15925 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15926 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15927 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15928 install_element(BGP_IPV6_NODE,
15929 &ipv6_bgp_distance_source_access_list_cmd);
15930 install_element(BGP_IPV6_NODE,
15931 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15932 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15933 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15934 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15935 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15936 install_element(BGP_IPV6M_NODE,
15937 &ipv6_bgp_distance_source_access_list_cmd);
15938 install_element(BGP_IPV6M_NODE,
15939 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15940
ef5f4b23 15941 /* BGP dampening */
585f1adc
IR
15942 install_element(BGP_NODE, &bgp_damp_set_cmd);
15943 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15944 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15945 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15946 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15947 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15948 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15949 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15950 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15951 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15952 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15953 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15954 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15955 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15956
15957 /* Large Communities */
15958 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15959 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15960
15961 /* show bgp ipv4 flowspec detailed */
15962 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15963
2a0e69ae 15964 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15965 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15966}
15967
15968void bgp_route_finish(void)
15969{
15970 afi_t afi;
15971 safi_t safi;
15972
05c7a1cc
QY
15973 FOREACH_AFI_SAFI (afi, safi) {
15974 bgp_table_unlock(bgp_distance_table[afi][safi]);
15975 bgp_distance_table[afi][safi] = NULL;
15976 }
228da428 15977}