]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #12709 from donaldsharp/update_withdraw_always_work
[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 */
4459 vpn_leak_to_vrf_withdraw(bgp,
4460 pi);
d62a17ae 4461 }
4462 }
4463 }
718e3744 4464
d62a17ae 4465 /* Update to new attribute. */
40381db7
DS
4466 bgp_attr_unintern(&pi->attr);
4467 pi->attr = attr_new;
d62a17ae 4468
4469 /* Update MPLS label */
4470 if (has_valid_label) {
40381db7 4471 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4472 if (extra->label != label) {
4473 memcpy(&extra->label, label,
dbd587da 4474 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4475 extra->num_labels = num_labels;
4476 }
b57ba6d2
MK
4477 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4478 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4479 }
718e3744 4480
e496b420
HS
4481 /* Update SRv6 SID */
4482 if (attr->srv6_l3vpn) {
4483 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4484 if (sid_diff(&extra->sid[0].sid,
4485 &attr->srv6_l3vpn->sid)) {
4486 sid_copy(&extra->sid[0].sid,
e496b420
HS
4487 &attr->srv6_l3vpn->sid);
4488 extra->num_sids = 1;
cc8f05df 4489
16f3db2d
RS
4490 extra->sid[0].loc_block_len = 0;
4491 extra->sid[0].loc_node_len = 0;
4492 extra->sid[0].func_len = 0;
4493 extra->sid[0].arg_len = 0;
ea7cd161
RS
4494 extra->sid[0].transposition_len = 0;
4495 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4496
4497 if (attr->srv6_l3vpn->loc_block_len != 0) {
4498 extra->sid[0].loc_block_len =
4499 attr->srv6_l3vpn->loc_block_len;
4500 extra->sid[0].loc_node_len =
4501 attr->srv6_l3vpn->loc_node_len;
4502 extra->sid[0].func_len =
4503 attr->srv6_l3vpn->func_len;
4504 extra->sid[0].arg_len =
4505 attr->srv6_l3vpn->arg_len;
ea7cd161 4506 extra->sid[0].transposition_len =
cc8f05df 4507 attr->srv6_l3vpn
ea7cd161
RS
4508 ->transposition_len;
4509 extra->sid[0].transposition_offset =
cc8f05df 4510 attr->srv6_l3vpn
ea7cd161
RS
4511 ->transposition_offset;
4512 }
e496b420
HS
4513 }
4514 } else if (attr->srv6_vpn) {
4515 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4516 if (sid_diff(&extra->sid[0].sid,
4517 &attr->srv6_vpn->sid)) {
4518 sid_copy(&extra->sid[0].sid,
4519 &attr->srv6_vpn->sid);
e496b420
HS
4520 extra->num_sids = 1;
4521 }
4522 }
4523
49e5a4a0 4524#ifdef ENABLE_BGP_VNC
d62a17ae 4525 if ((afi == AFI_IP || afi == AFI_IP6)
4526 && (safi == SAFI_UNICAST)) {
4527 if (vnc_implicit_withdraw) {
4528 /*
4529 * Add back the route with its new attributes
4530 * (e.g., nexthop).
4531 * The route is still selected, until the route
4532 * selection
4533 * queued by bgp_process actually runs. We have
4534 * to make this
4535 * update to the VNC side immediately to avoid
4536 * racing against
4537 * configuration changes (e.g., route-map
4538 * changes) which
4539 * trigger re-importation of the entire RIB.
4540 */
40381db7
DS
4541 vnc_import_bgp_add_route(bgp, p, pi);
4542 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4543 }
4544 }
65efcfce
LB
4545#endif
4546
d62a17ae 4547 /* Update bgp route dampening information. */
b4f7f45b 4548 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4549 && peer->sort == BGP_PEER_EBGP) {
4550 /* Now we do normal update dampening. */
9bcb3eef 4551 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4552 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4553 bgp_dest_unlock_node(dest);
367b458c 4554 return;
d62a17ae 4555 }
4556 }
128ea8ab 4557
d62a17ae 4558 /* Nexthop reachability check - for unicast and
4559 * labeled-unicast.. */
7c312383
AD
4560 if (((afi == AFI_IP || afi == AFI_IP6)
4561 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4562 || (safi == SAFI_EVPN &&
4563 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4564 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4565 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4566 && !CHECK_FLAG(peer->flags,
4567 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4568 && !CHECK_FLAG(bgp->flags,
4569 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4570 connected = 1;
4571 else
4572 connected = 0;
4573
960035b2
PZ
4574 struct bgp *bgp_nexthop = bgp;
4575
40381db7
DS
4576 if (pi->extra && pi->extra->bgp_orig)
4577 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4578
7c312383
AD
4579 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4580
4581 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4582 safi, pi, NULL, connected,
f8745525
PG
4583 bgp_nht_param_prefix) ||
4584 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4585 bgp_path_info_set_flag(dest, pi,
4586 BGP_PATH_VALID);
d62a17ae 4587 else {
4588 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4589 zlog_debug("%s(%pI4): NH unresolved",
4590 __func__,
4591 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4592 }
9bcb3eef 4593 bgp_path_info_unset_flag(dest, pi,
18ee8310 4594 BGP_PATH_VALID);
d62a17ae 4595 }
46dbf9d0
DA
4596 } else {
4597 if (accept_own)
4598 bgp_path_info_set_flag(dest, pi,
4599 BGP_PATH_ACCEPT_OWN);
4600
9bcb3eef 4601 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4602 }
d62a17ae 4603
49e5a4a0 4604#ifdef ENABLE_BGP_VNC
d62a17ae 4605 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4606 struct bgp_dest *pdest = NULL;
d62a17ae 4607 struct bgp_table *table = NULL;
4608
9bcb3eef
DS
4609 pdest = bgp_node_get(bgp->rib[afi][safi],
4610 (struct prefix *)prd);
4611 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4612 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4613
4614 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4615 bgp, prd, table, p, pi);
d62a17ae 4616 }
9bcb3eef 4617 bgp_dest_unlock_node(pdest);
d62a17ae 4618 }
4619#endif
718e3744 4620
d62a17ae 4621 /* If this is an EVPN route and some attribute has changed,
9146341f 4622 * or we are explicitly told to perform a route import, process
d62a17ae 4623 * route for import. If the extended community has changed, we
4624 * would
4625 * have done the un-import earlier and the import would result
4626 * in the
4627 * route getting injected into appropriate L2 VNIs. If it is
4628 * just
4629 * some other attribute change, the import will result in
4630 * updating
4631 * the attributes for the route in the VNI(s).
4632 */
9146341f 4633 if (safi == SAFI_EVPN &&
4634 (!same_attr || force_evpn_import) &&
7c312383 4635 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4636 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4637
4638 /* Process change. */
40381db7 4639 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4640
9bcb3eef
DS
4641 bgp_process(bgp, dest, afi, safi);
4642 bgp_dest_unlock_node(dest);
558d1fec 4643
ddb5b488
PZ
4644 if (SAFI_UNICAST == safi
4645 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4646 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4647
40381db7 4648 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4649 }
4650 if ((SAFI_MPLS_VPN == safi)
4651 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4652 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4653 }
4654
49e5a4a0 4655#ifdef ENABLE_BGP_VNC
d62a17ae 4656 if (SAFI_MPLS_VPN == safi) {
4657 mpls_label_t label_decoded = decode_label(label);
28070ee3 4658
d62a17ae 4659 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4660 type, sub_type, &label_decoded);
4661 }
4662 if (SAFI_ENCAP == safi) {
4663 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4664 type, sub_type, NULL);
4665 }
28070ee3 4666#endif
a486300b
PG
4667 if ((safi == SAFI_MPLS_VPN) &&
4668 !CHECK_FLAG(bgp->af_flags[afi][safi],
4669 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4670 !leak_success) {
4671 bgp_unlink_nexthop(pi);
4672 bgp_path_info_delete(dest, pi);
4673 }
367b458c 4674 return;
d62a17ae 4675 } // End of implicit withdraw
718e3744 4676
d62a17ae 4677 /* Received Logging. */
4678 if (bgp_debug_update(peer, p, NULL, 1)) {
4679 if (!peer->rcvd_attr_printed) {
f70c91dc 4680 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4681 peer->rcvd_attr_str);
4682 peer->rcvd_attr_printed = 1;
4683 }
718e3744 4684
a4d82a8a 4685 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4686 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4687 pfx_buf, sizeof(pfx_buf));
f70c91dc 4688 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4689 }
718e3744 4690
d62a17ae 4691 /* Make new BGP info. */
9bcb3eef 4692 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4693
d62a17ae 4694 /* Update MPLS label */
4695 if (has_valid_label) {
18ee8310 4696 extra = bgp_path_info_extra_get(new);
8ba71050 4697 if (extra->label != label) {
dbd587da
QY
4698 memcpy(&extra->label, label,
4699 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4700 extra->num_labels = num_labels;
4701 }
b57ba6d2
MK
4702 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4703 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4704 }
718e3744 4705
e496b420
HS
4706 /* Update SRv6 SID */
4707 if (safi == SAFI_MPLS_VPN) {
4708 extra = bgp_path_info_extra_get(new);
4709 if (attr->srv6_l3vpn) {
16f3db2d 4710 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4711 extra->num_sids = 1;
cc8f05df 4712
16f3db2d
RS
4713 extra->sid[0].loc_block_len =
4714 attr->srv6_l3vpn->loc_block_len;
4715 extra->sid[0].loc_node_len =
4716 attr->srv6_l3vpn->loc_node_len;
4717 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4718 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4719 extra->sid[0].transposition_len =
4720 attr->srv6_l3vpn->transposition_len;
4721 extra->sid[0].transposition_offset =
4722 attr->srv6_l3vpn->transposition_offset;
e496b420 4723 } else if (attr->srv6_vpn) {
16f3db2d 4724 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4725 extra->num_sids = 1;
4726 }
4727 }
4728
d62a17ae 4729 /* Nexthop reachability check. */
7c312383
AD
4730 if (((afi == AFI_IP || afi == AFI_IP6)
4731 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4732 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4733 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4734 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4735 && !CHECK_FLAG(peer->flags,
4736 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4737 && !CHECK_FLAG(bgp->flags,
4738 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4739 connected = 1;
4740 else
4741 connected = 0;
4742
7c312383
AD
4743 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4744
4053e952 4745 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4746 connected, bgp_nht_param_prefix) ||
4747 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4748 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4749 else {
07380148
DA
4750 if (BGP_DEBUG(nht, NHT))
4751 zlog_debug("%s(%pI4): NH unresolved", __func__,
4752 &attr_new->nexthop);
9bcb3eef 4753 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4754 }
46dbf9d0
DA
4755 } else {
4756 if (accept_own)
4757 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4758
9bcb3eef 4759 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4760 }
a82478b9 4761
b381ed97
DA
4762 /* If maximum prefix count is configured and current prefix
4763 * count exeed it.
4764 */
4765 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4766 reason = "maximum-prefix overflow";
4767 bgp_attr_flush(&new_attr);
b381ed97
DA
4768 goto filtered;
4769 }
4770
d62a17ae 4771 /* Addpath ID */
4772 new->addpath_rx_id = addpath_id;
4773
4774 /* Increment prefix */
4775 bgp_aggregate_increment(bgp, p, new, afi, safi);
4776
4777 /* Register new BGP information. */
9bcb3eef 4778 bgp_path_info_add(dest, new);
d62a17ae 4779
4780 /* route_node_get lock */
9bcb3eef 4781 bgp_dest_unlock_node(dest);
558d1fec 4782
49e5a4a0 4783#ifdef ENABLE_BGP_VNC
d62a17ae 4784 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4785 struct bgp_dest *pdest = NULL;
d62a17ae 4786 struct bgp_table *table = NULL;
4787
9bcb3eef
DS
4788 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4789 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4790 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4791
4792 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4793 bgp, prd, table, p, new);
4794 }
9bcb3eef 4795 bgp_dest_unlock_node(pdest);
d62a17ae 4796 }
65efcfce
LB
4797#endif
4798
d62a17ae 4799 /* If this is an EVPN route, process for import. */
7c312383 4800 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4801 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4802
9bcb3eef 4803 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4804
d62a17ae 4805 /* Process change. */
9bcb3eef 4806 bgp_process(bgp, dest, afi, safi);
718e3744 4807
ddb5b488
PZ
4808 if (SAFI_UNICAST == safi
4809 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4810 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4811 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4812 }
4813 if ((SAFI_MPLS_VPN == safi)
4814 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4815 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4816 }
49e5a4a0 4817#ifdef ENABLE_BGP_VNC
d62a17ae 4818 if (SAFI_MPLS_VPN == safi) {
4819 mpls_label_t label_decoded = decode_label(label);
28070ee3 4820
d62a17ae 4821 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4822 sub_type, &label_decoded);
4823 }
4824 if (SAFI_ENCAP == safi) {
4825 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4826 sub_type, NULL);
4827 }
28070ee3 4828#endif
a486300b
PG
4829 if ((safi == SAFI_MPLS_VPN) &&
4830 !CHECK_FLAG(bgp->af_flags[afi][safi],
4831 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4832 !leak_success) {
4833 bgp_unlink_nexthop(new);
4834 bgp_path_info_delete(dest, new);
4835 }
28070ee3 4836
367b458c 4837 return;
718e3744 4838
d62a17ae 4839/* This BGP update is filtered. Log the reason then update BGP
4840 entry. */
4841filtered:
819e6767
DA
4842 if (new) {
4843 bgp_unlink_nexthop(new);
4844 bgp_path_info_delete(dest, new);
4845 bgp_path_info_extra_free(&new->extra);
4846 XFREE(MTYPE_BGP_ROUTE, new);
4847 }
4848
9bcb3eef 4849 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4850
d62a17ae 4851 if (bgp_debug_update(peer, p, NULL, 1)) {
4852 if (!peer->rcvd_attr_printed) {
f70c91dc 4853 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4854 peer->rcvd_attr_str);
4855 peer->rcvd_attr_printed = 1;
4856 }
718e3744 4857
a4d82a8a 4858 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4859 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4860 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4861 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4862 peer, pfx_buf, reason);
d62a17ae 4863 }
128ea8ab 4864
40381db7 4865 if (pi) {
d62a17ae 4866 /* If this is an EVPN route, un-import it as it is now filtered.
4867 */
4868 if (safi == SAFI_EVPN)
40381db7 4869 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4870
ddb5b488
PZ
4871 if (SAFI_UNICAST == safi
4872 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4873 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4874
40381db7 4875 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4876 }
4877 if ((SAFI_MPLS_VPN == safi)
4878 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4879
40381db7 4880 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4881 }
4882
9bcb3eef 4883 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4884 }
4885
9bcb3eef 4886 bgp_dest_unlock_node(dest);
558d1fec 4887
49e5a4a0 4888#ifdef ENABLE_BGP_VNC
d62a17ae 4889 /*
4890 * Filtered update is treated as an implicit withdrawal (see
4891 * bgp_rib_remove()
4892 * a few lines above)
4893 */
4894 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4895 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4896 0);
4897 }
97736e32
PZ
4898#endif
4899
367b458c 4900 return;
718e3744 4901}
4902
367b458c
DS
4903void bgp_withdraw(struct peer *peer, const struct prefix *p,
4904 uint32_t addpath_id, struct attr *attr, afi_t afi,
4905 safi_t safi, int type, int sub_type, struct prefix_rd *prd,
4906 mpls_label_t *label, uint32_t num_labels,
4907 struct bgp_route_evpn *evpn)
718e3744 4908{
d62a17ae 4909 struct bgp *bgp;
4910 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4911 struct bgp_dest *dest;
40381db7 4912 struct bgp_path_info *pi;
718e3744 4913
49e5a4a0 4914#ifdef ENABLE_BGP_VNC
d62a17ae 4915 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4916 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4917 0);
4918 }
28070ee3
PZ
4919#endif
4920
d62a17ae 4921 bgp = peer->bgp;
4922
4923 /* Lookup node. */
9bcb3eef 4924 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4925
4926 /* If peer is soft reconfiguration enabled. Record input packet for
4927 * further calculation.
4928 *
4929 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4930 * routes that are filtered. This tanks out Quagga RS pretty badly due
4931 * to
4932 * the iteration over all RS clients.
4933 * Since we need to remove the entry from adj_in anyway, do that first
4934 * and
4935 * if there was no entry, we don't need to do anything more.
4936 */
4937 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4938 && peer != bgp->peer_self)
9bcb3eef 4939 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4940 peer->stat_pfx_dup_withdraw++;
4941
d62a17ae 4942 if (bgp_debug_update(peer, p, NULL, 1)) {
4943 bgp_debug_rdpfxpath2str(
a4d82a8a 4944 afi, safi, prd, p, label, num_labels,
6c995628
AD
4945 addpath_id ? 1 : 0, addpath_id, NULL,
4946 pfx_buf, sizeof(pfx_buf));
d62a17ae 4947 zlog_debug(
4948 "%s withdrawing route %s not in adj-in",
4949 peer->host, pfx_buf);
4950 }
9bcb3eef 4951 bgp_dest_unlock_node(dest);
367b458c 4952 return;
d62a17ae 4953 }
cd808e74 4954
d62a17ae 4955 /* Lookup withdrawn route. */
9bcb3eef 4956 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4957 if (pi->peer == peer && pi->type == type
4958 && pi->sub_type == sub_type
4959 && pi->addpath_rx_id == addpath_id)
d62a17ae 4960 break;
4961
4962 /* Logging. */
4963 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4964 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4965 addpath_id ? 1 : 0, addpath_id, NULL,
4966 pfx_buf, sizeof(pfx_buf));
f70c91dc 4967 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4968 pfx_buf);
4969 }
718e3744 4970
d62a17ae 4971 /* Withdraw specified route from routing table. */
40381db7 4972 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4973 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4974 if (SAFI_UNICAST == safi
4975 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4976 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4977 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4978 }
4979 if ((SAFI_MPLS_VPN == safi)
4980 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4981
40381db7 4982 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4983 }
4984 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4985 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4986 addpath_id ? 1 : 0, addpath_id, NULL,
4987 pfx_buf, sizeof(pfx_buf));
d62a17ae 4988 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4989 }
718e3744 4990
d62a17ae 4991 /* Unlock bgp_node_get() lock. */
9bcb3eef 4992 bgp_dest_unlock_node(dest);
d62a17ae 4993
367b458c 4994 return;
718e3744 4995}
6b0655a2 4996
d62a17ae 4997void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4998 int withdraw)
718e3744 4999{
d62a17ae 5000 struct update_subgroup *subgrp;
5001 subgrp = peer_subgroup(peer, afi, safi);
5002 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5003}
6182d65b 5004
718e3744 5005
3f9c7369
DS
5006/*
5007 * bgp_stop_announce_route_timer
5008 */
d62a17ae 5009void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5010{
d62a17ae 5011 if (!paf->t_announce_route)
5012 return;
5013
c3aaa89a 5014 THREAD_OFF(paf->t_announce_route);
718e3744 5015}
6b0655a2 5016
3f9c7369
DS
5017/*
5018 * bgp_announce_route_timer_expired
5019 *
5020 * Callback that is invoked when the route announcement timer for a
5021 * peer_af expires.
5022 */
cc9f21da 5023static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5024{
d62a17ae 5025 struct peer_af *paf;
5026 struct peer *peer;
558d1fec 5027
d62a17ae 5028 paf = THREAD_ARG(t);
5029 peer = paf->peer;
718e3744 5030
feb17238 5031 if (!peer_established(peer))
cc9f21da 5032 return;
3f9c7369 5033
d62a17ae 5034 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5035 return;
3f9c7369 5036
d62a17ae 5037 peer_af_announce_route(paf, 1);
c5aec50b
MK
5038
5039 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5040 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5041}
5042
3f9c7369
DS
5043/*
5044 * bgp_announce_route
5045 *
5046 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5047 *
5048 * if force is true we will force an update even if the update
5049 * limiting code is attempted to kick in.
3f9c7369 5050 */
e1a32ec1 5051void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5052{
5053 struct peer_af *paf;
5054 struct update_subgroup *subgrp;
5055
5056 paf = peer_af_find(peer, afi, safi);
5057 if (!paf)
5058 return;
5059 subgrp = PAF_SUBGRP(paf);
5060
5061 /*
5062 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5063 * or a refresh has already been triggered.
5064 */
5065 if (!subgrp || paf->t_announce_route)
5066 return;
5067
e1a32ec1
DS
5068 if (force)
5069 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5070
d62a17ae 5071 /*
5072 * Start a timer to stagger/delay the announce. This serves
5073 * two purposes - announcement can potentially be combined for
5074 * multiple peers and the announcement doesn't happen in the
5075 * vty context.
5076 */
5077 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5078 (subgrp->peer_count == 1)
5079 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5080 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5081 &paf->t_announce_route);
3f9c7369
DS
5082}
5083
5084/*
5085 * Announce routes from all AF tables to a peer.
5086 *
5087 * This should ONLY be called when there is a need to refresh the
5088 * routes to the peer based on a policy change for this peer alone
5089 * or a route refresh request received from the peer.
5090 * The operation will result in splitting the peer from its existing
5091 * subgroups and putting it in new subgroups.
5092 */
d62a17ae 5093void bgp_announce_route_all(struct peer *peer)
718e3744 5094{
d62a17ae 5095 afi_t afi;
5096 safi_t safi;
5097
05c7a1cc 5098 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5099 bgp_announce_route(peer, afi, safi, false);
718e3744 5100}
6b0655a2 5101
46aeabed
LS
5102/* Flag or unflag bgp_dest to determine whether it should be treated by
5103 * bgp_soft_reconfig_table_task.
5104 * Flag if flag is true. Unflag if flag is false.
5105 */
5106static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5107{
5108 struct bgp_dest *dest;
5109 struct bgp_adj_in *ain;
5110
5111 if (!table)
5112 return;
5113
5114 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5115 for (ain = dest->adj_in; ain; ain = ain->next) {
5116 if (ain->peer != NULL)
5117 break;
5118 }
5119 if (flag && ain != NULL && ain->peer != NULL)
5120 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5121 else
5122 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5123 }
5124}
5125
367b458c
DS
5126static void bgp_soft_reconfig_table_update(struct peer *peer,
5127 struct bgp_dest *dest,
5128 struct bgp_adj_in *ain, afi_t afi,
5129 safi_t safi, struct prefix_rd *prd)
46aeabed
LS
5130{
5131 struct bgp_path_info *pi;
5132 uint32_t num_labels = 0;
5133 mpls_label_t *label_pnt = NULL;
5134 struct bgp_route_evpn evpn;
5135
5136 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5137 if (pi->peer == peer)
5138 break;
5139
5140 if (pi && pi->extra)
5141 num_labels = pi->extra->num_labels;
5142 if (num_labels)
5143 label_pnt = &pi->extra->label[0];
5144 if (pi)
5145 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5146 sizeof(evpn));
5147 else
5148 memset(&evpn, 0, sizeof(evpn));
5149
367b458c
DS
5150 bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5151 ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5152 label_pnt, num_labels, 1, &evpn);
46aeabed
LS
5153}
5154
d62a17ae 5155static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5156 struct bgp_table *table,
5157 struct prefix_rd *prd)
718e3744 5158{
9bcb3eef 5159 struct bgp_dest *dest;
d62a17ae 5160 struct bgp_adj_in *ain;
718e3744 5161
d62a17ae 5162 if (!table)
5163 table = peer->bgp->rib[afi][safi];
718e3744 5164
9bcb3eef
DS
5165 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5166 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5167 if (ain->peer != peer)
5168 continue;
8692c506 5169
367b458c
DS
5170 bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5171 safi, prd);
d62a17ae 5172 }
718e3744 5173}
5174
46aeabed
LS
5175/* Do soft reconfig table per bgp table.
5176 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5177 * when BGP_NODE_SOFT_RECONFIG is set,
5178 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5179 * Schedule a new thread to continue the job.
5180 * Without splitting the full job into several part,
5181 * vtysh waits for the job to finish before responding to a BGP command
5182 */
cc9f21da 5183static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5184{
5185 uint32_t iter, max_iter;
46aeabed
LS
5186 struct bgp_dest *dest;
5187 struct bgp_adj_in *ain;
5188 struct peer *peer;
5189 struct bgp_table *table;
5190 struct prefix_rd *prd;
5191 struct listnode *node, *nnode;
5192
5193 table = THREAD_ARG(thread);
5194 prd = NULL;
5195
5196 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5197 if (table->soft_reconfig_init) {
5198 /* first call of the function with a new srta structure.
5199 * Don't do any treatment this time on nodes
5200 * in order vtysh to respond quickly
5201 */
5202 max_iter = 0;
5203 }
5204
5205 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5206 dest = bgp_route_next(dest)) {
5207 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5208 continue;
5209
5210 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5211
5212 for (ain = dest->adj_in; ain; ain = ain->next) {
5213 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5214 nnode, peer)) {
5215 if (ain->peer != peer)
5216 continue;
5217
367b458c 5218 bgp_soft_reconfig_table_update(
46aeabed
LS
5219 peer, dest, ain, table->afi,
5220 table->safi, prd);
5221 iter++;
46aeabed
LS
5222 }
5223 }
5224 }
5225
5226 /* we're either starting the initial iteration,
5227 * or we're going to continue an ongoing iteration
5228 */
5229 if (dest || table->soft_reconfig_init) {
5230 table->soft_reconfig_init = false;
5231 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5232 table, 0, &table->soft_reconfig_thread);
cc9f21da 5233 return;
46aeabed
LS
5234 }
5235 /* we're done, clean up the background iteration context info and
5236 schedule route annoucement
5237 */
5238 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5239 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5240 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5241 }
5242
5243 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5244}
5245
5246
5247/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5248 * and peer.
5249 * - bgp cannot be NULL
5250 * - if table and peer are NULL, cancel all threads within the bgp instance
5251 * - if table is NULL and peer is not,
5252 * remove peer in all threads within the bgp instance
5253 * - if peer is NULL, cancel all threads matching table within the bgp instance
5254 */
5255void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5256 const struct bgp_table *table,
5257 const struct peer *peer)
5258{
5259 struct peer *npeer;
5260 struct listnode *node, *nnode;
5261 int afi, safi;
5262 struct bgp_table *ntable;
5263
5264 if (!bgp)
5265 return;
5266
5267 FOREACH_AFI_SAFI (afi, safi) {
5268 ntable = bgp->rib[afi][safi];
5269 if (!ntable)
5270 continue;
5271 if (table && table != ntable)
5272 continue;
5273
5274 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5275 npeer)) {
5276 if (peer && peer != npeer)
5277 continue;
5278 listnode_delete(ntable->soft_reconfig_peers, npeer);
5279 }
5280
5281 if (!ntable->soft_reconfig_peers
5282 || !list_isempty(ntable->soft_reconfig_peers))
5283 continue;
5284
5285 list_delete(&ntable->soft_reconfig_peers);
5286 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5287 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5288 }
5289}
5290
89c73443
DS
5291/*
5292 * Returns false if the peer is not configured for soft reconfig in
5293 */
5294bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5295{
9bcb3eef 5296 struct bgp_dest *dest;
d62a17ae 5297 struct bgp_table *table;
46aeabed
LS
5298 struct listnode *node, *nnode;
5299 struct peer *npeer;
5300 struct peer_af *paf;
718e3744 5301
89c73443
DS
5302 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5303 return false;
718e3744 5304
d62a17ae 5305 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5306 && (safi != SAFI_EVPN)) {
5307 table = peer->bgp->rib[afi][safi];
5308 if (!table)
89c73443 5309 return true;
46aeabed
LS
5310
5311 table->soft_reconfig_init = true;
5312
5313 if (!table->soft_reconfig_peers)
5314 table->soft_reconfig_peers = list_new();
5315 npeer = NULL;
5316 /* add peer to the table soft_reconfig_peers if not already
5317 * there
5318 */
5319 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5320 npeer)) {
5321 if (peer == npeer)
5322 break;
5323 }
5324 if (peer != npeer)
5325 listnode_add(table->soft_reconfig_peers, peer);
5326
5327 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5328 * on table would start back at the beginning.
5329 */
5330 bgp_soft_reconfig_table_flag(table, true);
5331
5332 if (!table->soft_reconfig_thread)
5333 thread_add_event(bm->master,
5334 bgp_soft_reconfig_table_task, table, 0,
5335 &table->soft_reconfig_thread);
5336 /* Cancel bgp_announce_route_timer_expired threads.
5337 * bgp_announce_route_timer_expired threads have been scheduled
5338 * to announce routes as soon as the soft_reconfigure process
5339 * finishes.
5340 * In this case, soft_reconfigure is also scheduled by using
5341 * a thread but is planned after the
5342 * bgp_announce_route_timer_expired threads. It means that,
5343 * without cancelling the threads, the route announcement task
5344 * would run before the soft reconfiguration one. That would
5345 * useless and would block vtysh during several seconds. Route
5346 * announcements are rescheduled as soon as the soft_reconfigure
5347 * process finishes.
5348 */
5349 paf = peer_af_find(peer, afi, safi);
5350 if (paf)
5351 bgp_stop_announce_route_timer(paf);
5352 } else
9bcb3eef
DS
5353 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5354 dest = bgp_route_next(dest)) {
5355 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5356
b54892e0
DS
5357 if (table == NULL)
5358 continue;
8692c506 5359
9bcb3eef 5360 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5361 struct prefix_rd prd;
5362
5363 prd.family = AF_UNSPEC;
5364 prd.prefixlen = 64;
5365 memcpy(&prd.val, p->u.val, 8);
5366
5367 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5368 }
89c73443
DS
5369
5370 return true;
718e3744 5371}
6b0655a2 5372
228da428 5373
d62a17ae 5374struct bgp_clear_node_queue {
9bcb3eef 5375 struct bgp_dest *dest;
228da428
CC
5376};
5377
d62a17ae 5378static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5379{
d62a17ae 5380 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5381 struct bgp_dest *dest = cnq->dest;
d62a17ae 5382 struct peer *peer = wq->spec.data;
40381db7 5383 struct bgp_path_info *pi;
3103e8d2 5384 struct bgp *bgp;
9bcb3eef
DS
5385 afi_t afi = bgp_dest_table(dest)->afi;
5386 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5387
9bcb3eef 5388 assert(dest && peer);
3103e8d2 5389 bgp = peer->bgp;
d62a17ae 5390
5391 /* It is possible that we have multiple paths for a prefix from a peer
5392 * if that peer is using AddPath.
5393 */
9bcb3eef 5394 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5395 if (pi->peer != peer)
ea47320b
DL
5396 continue;
5397
5398 /* graceful restart STALE flag set. */
9af52ccf
DA
5399 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5400 && peer->nsf[afi][safi])
5401 || CHECK_FLAG(peer->af_sflags[afi][safi],
5402 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5403 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5404 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5405 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5406 else {
5407 /* If this is an EVPN route, process for
5408 * un-import. */
5409 if (safi == SAFI_EVPN)
9bcb3eef
DS
5410 bgp_evpn_unimport_route(
5411 bgp, afi, safi,
5412 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5413 /* Handle withdraw for VRF route-leaking and L3VPN */
5414 if (SAFI_UNICAST == safi
5415 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5416 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5417 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5418 bgp, pi);
960035b2 5419 }
3103e8d2 5420 if (SAFI_MPLS_VPN == safi &&
960035b2 5421 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5422 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5423 }
3103e8d2 5424
9bcb3eef 5425 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5426 }
ea47320b 5427 }
d62a17ae 5428 return WQ_SUCCESS;
200df115 5429}
5430
d62a17ae 5431static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5432{
d62a17ae 5433 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5434 struct bgp_dest *dest = cnq->dest;
5435 struct bgp_table *table = bgp_dest_table(dest);
228da428 5436
9bcb3eef 5437 bgp_dest_unlock_node(dest);
d62a17ae 5438 bgp_table_unlock(table);
5439 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5440}
5441
d62a17ae 5442static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5443{
d62a17ae 5444 struct peer *peer = wq->spec.data;
64e580a7 5445
d62a17ae 5446 /* Tickle FSM to start moving again */
5447 BGP_EVENT_ADD(peer, Clearing_Completed);
5448
5449 peer_unlock(peer); /* bgp_clear_route */
200df115 5450}
718e3744 5451
d62a17ae 5452static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5453{
d62a17ae 5454 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5455
5456 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5457#undef CLEAR_QUEUE_NAME_LEN
5458
0ce1ca80 5459 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5460 peer->clear_node_queue->spec.hold = 10;
5461 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5462 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5463 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5464 peer->clear_node_queue->spec.max_retries = 0;
5465
5466 /* we only 'lock' this peer reference when the queue is actually active
5467 */
5468 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5469}
5470
d62a17ae 5471static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5472 struct bgp_table *table)
65ca75e0 5473{
9bcb3eef 5474 struct bgp_dest *dest;
b6c386bb 5475 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5476
d62a17ae 5477 if (!table)
5478 table = peer->bgp->rib[afi][safi];
dc83d712 5479
d62a17ae 5480 /* If still no table => afi/safi isn't configured at all or smth. */
5481 if (!table)
5482 return;
dc83d712 5483
9bcb3eef 5484 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5485 struct bgp_path_info *pi, *next;
d62a17ae 5486 struct bgp_adj_in *ain;
5487 struct bgp_adj_in *ain_next;
5488
5489 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5490 * queued for every clearing peer, regardless of whether it is
5491 * relevant to the peer at hand.
5492 *
5493 * Overview: There are 3 different indices which need to be
5494 * scrubbed, potentially, when a peer is removed:
5495 *
5496 * 1 peer's routes visible via the RIB (ie accepted routes)
5497 * 2 peer's routes visible by the (optional) peer's adj-in index
5498 * 3 other routes visible by the peer's adj-out index
5499 *
5500 * 3 there is no hurry in scrubbing, once the struct peer is
5501 * removed from bgp->peer, we could just GC such deleted peer's
5502 * adj-outs at our leisure.
5503 *
5504 * 1 and 2 must be 'scrubbed' in some way, at least made
5505 * invisible via RIB index before peer session is allowed to be
5506 * brought back up. So one needs to know when such a 'search' is
5507 * complete.
5508 *
5509 * Ideally:
5510 *
5511 * - there'd be a single global queue or a single RIB walker
5512 * - rather than tracking which route_nodes still need to be
5513 * examined on a peer basis, we'd track which peers still
5514 * aren't cleared
5515 *
5516 * Given that our per-peer prefix-counts now should be reliable,
5517 * this may actually be achievable. It doesn't seem to be a huge
5518 * problem at this time,
5519 *
5520 * It is possible that we have multiple paths for a prefix from
5521 * a peer
5522 * if that peer is using AddPath.
5523 */
9bcb3eef 5524 ain = dest->adj_in;
d62a17ae 5525 while (ain) {
5526 ain_next = ain->next;
5527
6a840fd9 5528 if (ain->peer == peer)
9bcb3eef 5529 bgp_adj_in_remove(dest, ain);
d62a17ae 5530
5531 ain = ain_next;
5532 }
5533
9bcb3eef 5534 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5535 next = pi->next;
5536 if (pi->peer != peer)
d62a17ae 5537 continue;
5538
5539 if (force)
9bcb3eef 5540 bgp_path_info_reap(dest, pi);
d62a17ae 5541 else {
5542 struct bgp_clear_node_queue *cnq;
5543
5544 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5545 bgp_table_lock(bgp_dest_table(dest));
5546 bgp_dest_lock_node(dest);
d62a17ae 5547 cnq = XCALLOC(
5548 MTYPE_BGP_CLEAR_NODE_QUEUE,
5549 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5550 cnq->dest = dest;
d62a17ae 5551 work_queue_add(peer->clear_node_queue, cnq);
5552 break;
5553 }
5554 }
5555 }
5556 return;
5557}
5558
5559void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5560{
9bcb3eef 5561 struct bgp_dest *dest;
d62a17ae 5562 struct bgp_table *table;
5563
5564 if (peer->clear_node_queue == NULL)
5565 bgp_clear_node_queue_init(peer);
5566
5567 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5568 * Idle until it receives a Clearing_Completed event. This protects
5569 * against peers which flap faster than we can we clear, which could
5570 * lead to:
5571 *
5572 * a) race with routes from the new session being installed before
5573 * clear_route_node visits the node (to delete the route of that
5574 * peer)
5575 * b) resource exhaustion, clear_route_node likely leads to an entry
5576 * on the process_main queue. Fast-flapping could cause that queue
5577 * to grow and grow.
5578 */
5579
5580 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5581 * the unlock will happen upon work-queue completion; other wise, the
5582 * unlock happens at the end of this function.
5583 */
5584 if (!peer->clear_node_queue->thread)
5585 peer_lock(peer);
5586
5587 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5588 bgp_clear_route_table(peer, afi, safi, NULL);
5589 else
9bcb3eef
DS
5590 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5591 dest = bgp_route_next(dest)) {
5592 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5593 if (!table)
5594 continue;
5595
5596 bgp_clear_route_table(peer, afi, safi, table);
5597 }
d62a17ae 5598
5599 /* unlock if no nodes got added to the clear-node-queue. */
5600 if (!peer->clear_node_queue->thread)
5601 peer_unlock(peer);
718e3744 5602}
d62a17ae 5603
5604void bgp_clear_route_all(struct peer *peer)
718e3744 5605{
d62a17ae 5606 afi_t afi;
5607 safi_t safi;
718e3744 5608
05c7a1cc
QY
5609 FOREACH_AFI_SAFI (afi, safi)
5610 bgp_clear_route(peer, afi, safi);
65efcfce 5611
49e5a4a0 5612#ifdef ENABLE_BGP_VNC
d62a17ae 5613 rfapiProcessPeerDown(peer);
65efcfce 5614#endif
718e3744 5615}
5616
d62a17ae 5617void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5618{
d62a17ae 5619 struct bgp_table *table;
9bcb3eef 5620 struct bgp_dest *dest;
d62a17ae 5621 struct bgp_adj_in *ain;
5622 struct bgp_adj_in *ain_next;
718e3744 5623
d62a17ae 5624 table = peer->bgp->rib[afi][safi];
718e3744 5625
d62a17ae 5626 /* It is possible that we have multiple paths for a prefix from a peer
5627 * if that peer is using AddPath.
5628 */
9bcb3eef
DS
5629 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5630 ain = dest->adj_in;
43143c8f 5631
d62a17ae 5632 while (ain) {
5633 ain_next = ain->next;
43143c8f 5634
6a840fd9 5635 if (ain->peer == peer)
9bcb3eef 5636 bgp_adj_in_remove(dest, ain);
43143c8f 5637
d62a17ae 5638 ain = ain_next;
5639 }
5640 }
718e3744 5641}
93406d87 5642
1479ed2f
DA
5643/* If any of the routes from the peer have been marked with the NO_LLGR
5644 * community, either as sent by the peer, or as the result of a configured
5645 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5646 * operation of [RFC4271].
5647 */
d62a17ae 5648void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5649{
9bcb3eef 5650 struct bgp_dest *dest;
40381db7 5651 struct bgp_path_info *pi;
d62a17ae 5652 struct bgp_table *table;
5653
9af52ccf 5654 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5655 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5656 dest = bgp_route_next(dest)) {
5657 struct bgp_dest *rm;
d62a17ae 5658
5659 /* look for neighbor in tables */
9bcb3eef 5660 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5661 if (!table)
ea47320b
DL
5662 continue;
5663
5664 for (rm = bgp_table_top(table); rm;
5665 rm = bgp_route_next(rm))
9bcb3eef 5666 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5667 pi = pi->next) {
40381db7 5668 if (pi->peer != peer)
ea47320b 5669 continue;
1479ed2f
DA
5670 if (CHECK_FLAG(
5671 peer->af_sflags[afi][safi],
5672 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5673 bgp_attr_get_community(pi->attr) &&
1479ed2f 5674 !community_include(
9a706b42
DA
5675 bgp_attr_get_community(
5676 pi->attr),
1479ed2f 5677 COMMUNITY_NO_LLGR))
e3015d91 5678 continue;
40381db7 5679 if (!CHECK_FLAG(pi->flags,
1defdda8 5680 BGP_PATH_STALE))
e3015d91 5681 continue;
ea47320b 5682
641065d4
KM
5683 /*
5684 * If this is VRF leaked route
5685 * process for withdraw.
5686 */
5687 if (pi->sub_type ==
5688 BGP_ROUTE_IMPORTED &&
5689 peer->bgp->inst_type ==
5690 BGP_INSTANCE_TYPE_DEFAULT)
5691 vpn_leak_to_vrf_withdraw(
5692 peer->bgp, pi);
5693
40381db7 5694 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5695 break;
5696 }
d62a17ae 5697 }
5698 } else {
9bcb3eef
DS
5699 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5700 dest = bgp_route_next(dest))
5701 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5702 pi = pi->next) {
40381db7 5703 if (pi->peer != peer)
ea47320b 5704 continue;
1479ed2f
DA
5705 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5706 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5707 bgp_attr_get_community(pi->attr) &&
5708 !community_include(
5709 bgp_attr_get_community(pi->attr),
5710 COMMUNITY_NO_LLGR))
e3015d91 5711 continue;
40381db7 5712 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5713 continue;
641065d4
KM
5714 if (safi == SAFI_UNICAST &&
5715 (peer->bgp->inst_type ==
5716 BGP_INSTANCE_TYPE_VRF ||
5717 peer->bgp->inst_type ==
5718 BGP_INSTANCE_TYPE_DEFAULT))
5719 vpn_leak_from_vrf_withdraw(
5720 bgp_get_default(), peer->bgp,
5721 pi);
5722
9bcb3eef 5723 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5724 break;
5725 }
d62a17ae 5726 }
93406d87 5727}
6b0655a2 5728
9af52ccf
DA
5729void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5730{
5731 struct bgp_dest *dest, *ndest;
5732 struct bgp_path_info *pi;
5733 struct bgp_table *table;
5734
5735 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5736 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5737 dest = bgp_route_next(dest)) {
5738 table = bgp_dest_get_bgp_table_info(dest);
5739 if (!table)
5740 continue;
5741
5742 for (ndest = bgp_table_top(table); ndest;
5743 ndest = bgp_route_next(ndest)) {
5744 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5745 pi = pi->next) {
5746 if (pi->peer != peer)
5747 continue;
5748
5749 if ((CHECK_FLAG(
5750 peer->af_sflags[afi][safi],
5751 PEER_STATUS_ENHANCED_REFRESH))
5752 && !CHECK_FLAG(pi->flags,
5753 BGP_PATH_STALE)
5754 && !CHECK_FLAG(
5755 pi->flags,
5756 BGP_PATH_UNUSEABLE)) {
5757 if (bgp_debug_neighbor_events(
5758 peer))
5759 zlog_debug(
58e111f6
DA
5760 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5761 peer,
9af52ccf
DA
5762 afi2str(afi),
5763 safi2str(safi),
5764 bgp_dest_get_prefix(
5765 ndest));
5766
5767 bgp_path_info_set_flag(
5768 ndest, pi,
5769 BGP_PATH_STALE);
5770 }
5771 }
5772 }
5773 }
5774 } else {
5775 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5776 dest = bgp_route_next(dest)) {
5777 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5778 pi = pi->next) {
5779 if (pi->peer != peer)
5780 continue;
5781
5782 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5783 PEER_STATUS_ENHANCED_REFRESH))
5784 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5785 && !CHECK_FLAG(pi->flags,
5786 BGP_PATH_UNUSEABLE)) {
5787 if (bgp_debug_neighbor_events(peer))
5788 zlog_debug(
58e111f6
DA
5789 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5790 peer, afi2str(afi),
9af52ccf
DA
5791 safi2str(safi),
5792 bgp_dest_get_prefix(
5793 dest));
5794
5795 bgp_path_info_set_flag(dest, pi,
5796 BGP_PATH_STALE);
5797 }
5798 }
5799 }
5800 }
5801}
5802
3dc339cd 5803bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5804{
e0df4c04 5805 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5806 return true;
e0df4c04 5807
9dac9fc8
DA
5808 if (peer->sort == BGP_PEER_EBGP
5809 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5810 || FILTER_LIST_OUT_NAME(filter)
5811 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5812 return true;
5813 return false;
9dac9fc8
DA
5814}
5815
3dc339cd 5816bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5817{
e0df4c04 5818 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5819 return true;
e0df4c04 5820
9dac9fc8
DA
5821 if (peer->sort == BGP_PEER_EBGP
5822 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5823 || FILTER_LIST_IN_NAME(filter)
5824 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5825 return true;
5826 return false;
9dac9fc8
DA
5827}
5828
568e10ca 5829static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5830 safi_t safi)
bb86c601 5831{
9bcb3eef 5832 struct bgp_dest *dest;
40381db7 5833 struct bgp_path_info *pi;
4b7e6066 5834 struct bgp_path_info *next;
bb86c601 5835
9bcb3eef
DS
5836 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5837 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5838 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5839
40381db7 5840 next = pi->next;
1b7bb747
CS
5841
5842 /* Unimport EVPN routes from VRFs */
5843 if (safi == SAFI_EVPN)
5844 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5845 SAFI_EVPN, p, pi);
1b7bb747 5846
40381db7
DS
5847 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5848 && pi->type == ZEBRA_ROUTE_BGP
5849 && (pi->sub_type == BGP_ROUTE_NORMAL
5850 || pi->sub_type == BGP_ROUTE_AGGREGATE
5851 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5852
d62a17ae 5853 if (bgp_fibupd_safi(safi))
b54892e0 5854 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5855 }
9514b37d 5856
9bcb3eef 5857 bgp_path_info_reap(dest, pi);
d62a17ae 5858 }
bb86c601
LB
5859}
5860
718e3744 5861/* Delete all kernel routes. */
d62a17ae 5862void bgp_cleanup_routes(struct bgp *bgp)
5863{
5864 afi_t afi;
9bcb3eef 5865 struct bgp_dest *dest;
67009e22 5866 struct bgp_table *table;
d62a17ae 5867
5868 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5869 if (afi == AFI_L2VPN)
5870 continue;
568e10ca 5871 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5872 SAFI_UNICAST);
d62a17ae 5873 /*
5874 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5875 */
5876 if (afi != AFI_L2VPN) {
5877 safi_t safi;
5878 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5879 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5880 dest = bgp_route_next(dest)) {
5881 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5882 if (table != NULL) {
5883 bgp_cleanup_table(bgp, table, safi);
5884 bgp_table_finish(&table);
9bcb3eef
DS
5885 bgp_dest_set_bgp_table_info(dest, NULL);
5886 bgp_dest_unlock_node(dest);
d62a17ae 5887 }
5888 }
5889 safi = SAFI_ENCAP;
9bcb3eef
DS
5890 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5891 dest = bgp_route_next(dest)) {
5892 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5893 if (table != NULL) {
5894 bgp_cleanup_table(bgp, table, safi);
5895 bgp_table_finish(&table);
9bcb3eef
DS
5896 bgp_dest_set_bgp_table_info(dest, NULL);
5897 bgp_dest_unlock_node(dest);
d62a17ae 5898 }
5899 }
5900 }
5901 }
9bcb3eef
DS
5902 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5903 dest = bgp_route_next(dest)) {
5904 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5905 if (table != NULL) {
5906 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5907 bgp_table_finish(&table);
9bcb3eef
DS
5908 bgp_dest_set_bgp_table_info(dest, NULL);
5909 bgp_dest_unlock_node(dest);
d62a17ae 5910 }
bb86c601 5911 }
718e3744 5912}
5913
d62a17ae 5914void bgp_reset(void)
718e3744 5915{
d62a17ae 5916 vty_reset();
5917 bgp_zclient_reset();
5918 access_list_reset();
5919 prefix_list_reset();
718e3744 5920}
6b0655a2 5921
be92fc9f 5922bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5923{
d62a17ae 5924 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5925 && CHECK_FLAG(peer->af_cap[afi][safi],
5926 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5927}
5928
718e3744 5929/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5930 value. */
d62a17ae 5931int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5932 struct bgp_nlri *packet)
5933{
d7c0a89a
QY
5934 uint8_t *pnt;
5935 uint8_t *lim;
d62a17ae 5936 struct prefix p;
5937 int psize;
d62a17ae 5938 afi_t afi;
5939 safi_t safi;
be92fc9f 5940 bool addpath_capable;
d7c0a89a 5941 uint32_t addpath_id;
d62a17ae 5942
d62a17ae 5943 pnt = packet->nlri;
5944 lim = pnt + packet->length;
5945 afi = packet->afi;
5946 safi = packet->safi;
5947 addpath_id = 0;
be92fc9f 5948 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5949
5950 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5951 syntactic validity. If the field is syntactically incorrect,
5952 then the Error Subcode is set to Invalid Network Field. */
5953 for (; pnt < lim; pnt += psize) {
5954 /* Clear prefix structure. */
6006b807 5955 memset(&p, 0, sizeof(p));
d62a17ae 5956
be92fc9f 5957 if (addpath_capable) {
d62a17ae 5958
5959 /* When packet overflow occurs return immediately. */
761ed665 5960 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5961 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5962
a3a850a1 5963 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5964 addpath_id = ntohl(addpath_id);
d62a17ae 5965 pnt += BGP_ADDPATH_ID_LEN;
5966 }
718e3744 5967
d62a17ae 5968 /* Fetch prefix length. */
5969 p.prefixlen = *pnt++;
5970 /* afi/safi validity already verified by caller,
5971 * bgp_update_receive */
5972 p.family = afi2family(afi);
5973
5974 /* Prefix length check. */
5975 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5976 flog_err(
e50f7cfd 5977 EC_BGP_UPDATE_RCV,
14454c9f 5978 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5979 peer->host, p.prefixlen, packet->afi);
513386b5 5980 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5981 }
6b0655a2 5982
d62a17ae 5983 /* Packet size overflow check. */
5984 psize = PSIZE(p.prefixlen);
5985
5986 /* When packet overflow occur return immediately. */
5987 if (pnt + psize > lim) {
af4c2728 5988 flog_err(
e50f7cfd 5989 EC_BGP_UPDATE_RCV,
d62a17ae 5990 "%s [Error] Update packet error (prefix length %d overflows packet)",
5991 peer->host, p.prefixlen);
513386b5 5992 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5993 }
5994
5995 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5996 * prefix for the v4 and v6 afi's and unicast/multicast */
5997 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5998 flog_err(
e50f7cfd 5999 EC_BGP_UPDATE_RCV,
d62a17ae 6000 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6001 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6002 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6003 }
6004
6005 /* Fetch prefix from NLRI packet. */
a85297a7 6006 memcpy(p.u.val, pnt, psize);
d62a17ae 6007
6008 /* Check address. */
6009 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6010 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6011 /* From RFC4271 Section 6.3:
6012 *
6013 * If a prefix in the NLRI field is semantically
6014 * incorrect
6015 * (e.g., an unexpected multicast IP address),
6016 * an error SHOULD
6017 * be logged locally, and the prefix SHOULD be
6018 * ignored.
a4d82a8a 6019 */
af4c2728 6020 flog_err(
e50f7cfd 6021 EC_BGP_UPDATE_RCV,
23d0a753
DA
6022 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6023 peer->host, &p.u.prefix4);
d62a17ae 6024 continue;
6025 }
6026 }
6027
6028 /* Check address. */
6029 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6030 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6031 flog_err(
e50f7cfd 6032 EC_BGP_UPDATE_RCV,
c0d72166
DS
6033 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6034 peer->host, &p.u.prefix6);
d62a17ae 6035
6036 continue;
6037 }
6038 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6039 flog_err(
e50f7cfd 6040 EC_BGP_UPDATE_RCV,
c0d72166
DS
6041 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6042 peer->host, &p.u.prefix6);
d62a17ae 6043
6044 continue;
6045 }
6046 }
6047
6048 /* Normal process. */
6049 if (attr)
367b458c
DS
6050 bgp_update(peer, &p, addpath_id, attr, afi, safi,
6051 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6052 NULL, 0, 0, NULL);
d62a17ae 6053 else
367b458c
DS
6054 bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
6055 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6056 NULL, 0, NULL);
d62a17ae 6057
513386b5
DA
6058 /* Do not send BGP notification twice when maximum-prefix count
6059 * overflow. */
6060 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6061 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
d62a17ae 6062 }
6063
6064 /* Packet length consistency check. */
6065 if (pnt != lim) {
af4c2728 6066 flog_err(
e50f7cfd 6067 EC_BGP_UPDATE_RCV,
d62a17ae 6068 "%s [Error] Update packet error (prefix length mismatch with total length)",
6069 peer->host);
513386b5 6070 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6071 }
6b0655a2 6072
513386b5 6073 return BGP_NLRI_PARSE_OK;
718e3744 6074}
6075
d62a17ae 6076static struct bgp_static *bgp_static_new(void)
718e3744 6077{
d62a17ae 6078 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6079}
6080
d62a17ae 6081static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6082{
0a22ddfb 6083 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6084 route_map_counter_decrement(bgp_static->rmap.map);
6085
0a22ddfb 6086 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6087 XFREE(MTYPE_BGP_STATIC, bgp_static);
6088}
6089
5f040085 6090void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6091 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6092{
9bcb3eef 6093 struct bgp_dest *dest;
40381db7 6094 struct bgp_path_info *pi;
4b7e6066 6095 struct bgp_path_info *new;
40381db7 6096 struct bgp_path_info rmap_path;
d62a17ae 6097 struct attr attr;
6098 struct attr *attr_new;
b68885f9 6099 route_map_result_t ret;
49e5a4a0 6100#ifdef ENABLE_BGP_VNC
d62a17ae 6101 int vnc_implicit_withdraw = 0;
65efcfce 6102#endif
fee0f4c6 6103
d62a17ae 6104 assert(bgp_static);
dd8103a9 6105
9bcb3eef 6106 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6107
0f05ea43 6108 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6109
d62a17ae 6110 attr.nexthop = bgp_static->igpnexthop;
6111 attr.med = bgp_static->igpmetric;
6112 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6113
7226bc40
TA
6114 if (afi == AFI_IP)
6115 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6116
97a52c82
DA
6117 if (bgp_static->igpmetric)
6118 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6119
d62a17ae 6120 if (bgp_static->atomic)
6121 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6122
d62a17ae 6123 /* Store label index, if required. */
6124 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6125 attr.label_index = bgp_static->label_index;
6126 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6127 }
718e3744 6128
d62a17ae 6129 /* Apply route-map. */
6130 if (bgp_static->rmap.name) {
6131 struct attr attr_tmp = attr;
80ced710 6132
6006b807 6133 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6134 rmap_path.peer = bgp->peer_self;
6135 rmap_path.attr = &attr_tmp;
fee0f4c6 6136
d62a17ae 6137 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6138
1782514f 6139 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6140
d62a17ae 6141 bgp->peer_self->rmap_type = 0;
718e3744 6142
d62a17ae 6143 if (ret == RMAP_DENYMATCH) {
6144 /* Free uninterned attribute. */
6145 bgp_attr_flush(&attr_tmp);
718e3744 6146
d62a17ae 6147 /* Unintern original. */
6148 aspath_unintern(&attr.aspath);
6149 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6150 bgp_dest_unlock_node(dest);
d62a17ae 6151 return;
6152 }
7f323236 6153
637e5ba4 6154 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6155 bgp_attr_add_gshut_community(&attr_tmp);
6156
d62a17ae 6157 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6158 } else {
6159
637e5ba4 6160 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6161 bgp_attr_add_gshut_community(&attr);
6162
d62a17ae 6163 attr_new = bgp_attr_intern(&attr);
7f323236 6164 }
718e3744 6165
9bcb3eef 6166 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6167 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6168 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6169 break;
6170
40381db7
DS
6171 if (pi) {
6172 if (attrhash_cmp(pi->attr, attr_new)
6173 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6174 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6175 bgp_dest_unlock_node(dest);
d62a17ae 6176 bgp_attr_unintern(&attr_new);
6177 aspath_unintern(&attr.aspath);
6178 return;
6179 } else {
6180 /* The attribute is changed. */
9bcb3eef 6181 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6182
6183 /* Rewrite BGP route information. */
40381db7 6184 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6185 bgp_path_info_restore(dest, pi);
d62a17ae 6186 else
40381db7 6187 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6188#ifdef ENABLE_BGP_VNC
d62a17ae 6189 if ((afi == AFI_IP || afi == AFI_IP6)
6190 && (safi == SAFI_UNICAST)) {
40381db7 6191 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6192 /*
6193 * Implicit withdraw case.
40381db7 6194 * We have to do this before pi is
d62a17ae 6195 * changed
6196 */
6197 ++vnc_implicit_withdraw;
40381db7 6198 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6199 vnc_import_bgp_exterior_del_route(
40381db7 6200 bgp, p, pi);
d62a17ae 6201 }
6202 }
65efcfce 6203#endif
40381db7
DS
6204 bgp_attr_unintern(&pi->attr);
6205 pi->attr = attr_new;
083ec940 6206 pi->uptime = monotime(NULL);
49e5a4a0 6207#ifdef ENABLE_BGP_VNC
d62a17ae 6208 if ((afi == AFI_IP || afi == AFI_IP6)
6209 && (safi == SAFI_UNICAST)) {
6210 if (vnc_implicit_withdraw) {
40381db7 6211 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6212 vnc_import_bgp_exterior_add_route(
40381db7 6213 bgp, p, pi);
d62a17ae 6214 }
6215 }
65efcfce 6216#endif
718e3744 6217
d62a17ae 6218 /* Nexthop reachability check. */
892fedb6 6219 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6220 && (safi == SAFI_UNICAST
6221 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6222
6223 struct bgp *bgp_nexthop = bgp;
6224
40381db7
DS
6225 if (pi->extra && pi->extra->bgp_orig)
6226 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6227
6228 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6229 afi, safi, pi, NULL,
654a5978 6230 0, p))
9bcb3eef 6231 bgp_path_info_set_flag(dest, pi,
18ee8310 6232 BGP_PATH_VALID);
d62a17ae 6233 else {
6234 if (BGP_DEBUG(nht, NHT)) {
6235 char buf1[INET6_ADDRSTRLEN];
6236 inet_ntop(p->family,
6237 &p->u.prefix, buf1,
07380148 6238 sizeof(buf1));
d62a17ae 6239 zlog_debug(
6240 "%s(%s): Route not in table, not advertising",
15569c58 6241 __func__, buf1);
d62a17ae 6242 }
18ee8310 6243 bgp_path_info_unset_flag(
9bcb3eef 6244 dest, pi, BGP_PATH_VALID);
d62a17ae 6245 }
6246 } else {
6247 /* Delete the NHT structure if any, if we're
6248 * toggling between
6249 * enabling/disabling import check. We
6250 * deregister the route
6251 * from NHT to avoid overloading NHT and the
6252 * process interaction
6253 */
40381db7 6254 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6255 bgp_path_info_set_flag(dest, pi,
6256 BGP_PATH_VALID);
d62a17ae 6257 }
6258 /* Process change. */
40381db7 6259 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6260 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6261
6262 if (SAFI_UNICAST == safi
6263 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6264 || bgp->inst_type
6265 == BGP_INSTANCE_TYPE_DEFAULT)) {
6266 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6267 pi);
ddb5b488
PZ
6268 }
6269
9bcb3eef 6270 bgp_dest_unlock_node(dest);
d62a17ae 6271 aspath_unintern(&attr.aspath);
6272 return;
6273 }
718e3744 6274 }
718e3744 6275
d62a17ae 6276 /* Make new BGP info. */
6277 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6278 attr_new, dest);
d62a17ae 6279 /* Nexthop reachability check. */
892fedb6 6280 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6281 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6282 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6283 p))
9bcb3eef 6284 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6285 else {
6286 if (BGP_DEBUG(nht, NHT)) {
6287 char buf1[INET6_ADDRSTRLEN];
07380148 6288
d62a17ae 6289 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6290 sizeof(buf1));
d62a17ae 6291 zlog_debug(
6292 "%s(%s): Route not in table, not advertising",
15569c58 6293 __func__, buf1);
d62a17ae 6294 }
9bcb3eef 6295 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6296 }
6297 } else {
6298 /* Delete the NHT structure if any, if we're toggling between
6299 * enabling/disabling import check. We deregister the route
6300 * from NHT to avoid overloading NHT and the process interaction
6301 */
6302 bgp_unlink_nexthop(new);
6303
9bcb3eef 6304 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6305 }
078430f6 6306
d62a17ae 6307 /* Aggregate address increment. */
6308 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6309
d62a17ae 6310 /* Register new BGP information. */
9bcb3eef 6311 bgp_path_info_add(dest, new);
718e3744 6312
d62a17ae 6313 /* route_node_get lock */
9bcb3eef 6314 bgp_dest_unlock_node(dest);
d62a17ae 6315
6316 /* Process change. */
9bcb3eef 6317 bgp_process(bgp, dest, afi, safi);
d62a17ae 6318
ddb5b488
PZ
6319 if (SAFI_UNICAST == safi
6320 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6321 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6322 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6323 }
6324
d62a17ae 6325 /* Unintern original. */
6326 aspath_unintern(&attr.aspath);
718e3744 6327}
6328
5f040085 6329void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6330 safi_t safi)
718e3744 6331{
9bcb3eef 6332 struct bgp_dest *dest;
40381db7 6333 struct bgp_path_info *pi;
718e3744 6334
9bcb3eef 6335 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6336
d62a17ae 6337 /* Check selected route and self inserted route. */
9bcb3eef 6338 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6339 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6340 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6341 break;
6342
6343 /* Withdraw static BGP route from routing table. */
40381db7 6344 if (pi) {
ddb5b488
PZ
6345 if (SAFI_UNICAST == safi
6346 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6347 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6348 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6349 }
40381db7
DS
6350 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6351 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6352 bgp_path_info_delete(dest, pi);
6353 bgp_process(bgp, dest, afi, safi);
d62a17ae 6354 }
718e3744 6355
d62a17ae 6356 /* Unlock bgp_node_lookup. */
9bcb3eef 6357 bgp_dest_unlock_node(dest);
718e3744 6358}
6359
137446f9
LB
6360/*
6361 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6362 */
5f040085 6363static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6364 afi_t afi, safi_t safi,
6365 struct prefix_rd *prd)
718e3744 6366{
9bcb3eef 6367 struct bgp_dest *dest;
40381db7 6368 struct bgp_path_info *pi;
718e3744 6369
9bcb3eef 6370 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6371
d62a17ae 6372 /* Check selected route and self inserted route. */
9bcb3eef 6373 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6374 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6375 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6376 break;
718e3744 6377
d62a17ae 6378 /* Withdraw static BGP route from routing table. */
40381db7 6379 if (pi) {
49e5a4a0 6380#ifdef ENABLE_BGP_VNC
d62a17ae 6381 rfapiProcessWithdraw(
40381db7 6382 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6383 1); /* Kill, since it is an administrative change */
65efcfce 6384#endif
ddb5b488
PZ
6385 if (SAFI_MPLS_VPN == safi
6386 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6387 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6388 }
40381db7 6389 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6390 bgp_path_info_delete(dest, pi);
6391 bgp_process(bgp, dest, afi, safi);
d62a17ae 6392 }
718e3744 6393
d62a17ae 6394 /* Unlock bgp_node_lookup. */
9bcb3eef 6395 bgp_dest_unlock_node(dest);
718e3744 6396}
6397
5f040085 6398static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6399 struct bgp_static *bgp_static, afi_t afi,
6400 safi_t safi)
137446f9 6401{
9bcb3eef 6402 struct bgp_dest *dest;
4b7e6066 6403 struct bgp_path_info *new;
d62a17ae 6404 struct attr *attr_new;
6405 struct attr attr = {0};
40381db7 6406 struct bgp_path_info *pi;
49e5a4a0 6407#ifdef ENABLE_BGP_VNC
d62a17ae 6408 mpls_label_t label = 0;
65efcfce 6409#endif
d7c0a89a 6410 uint32_t num_labels = 0;
137446f9 6411
d62a17ae 6412 assert(bgp_static);
137446f9 6413
b57ba6d2
MK
6414 if (bgp_static->label != MPLS_INVALID_LABEL)
6415 num_labels = 1;
9bcb3eef
DS
6416 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6417 &bgp_static->prd);
137446f9 6418
0f05ea43 6419 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6420
d62a17ae 6421 attr.nexthop = bgp_static->igpnexthop;
6422 attr.med = bgp_static->igpmetric;
6423 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6424
d62a17ae 6425 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6426 || (safi == SAFI_ENCAP)) {
6427 if (afi == AFI_IP) {
6428 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6429 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6430 }
6431 }
6432 if (afi == AFI_L2VPN) {
b04c1e99
IR
6433 if (bgp_static->gatewayIp.family == AF_INET) {
6434 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6435 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6436 &bgp_static->gatewayIp.u.prefix4,
6437 IPV4_MAX_BYTELEN);
b04c1e99
IR
6438 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6439 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6440 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6441 &bgp_static->gatewayIp.u.prefix6,
6442 IPV6_MAX_BYTELEN);
b04c1e99 6443 }
0a50c248 6444 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6445 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6446 struct bgp_encap_type_vxlan bet;
6006b807 6447 memset(&bet, 0, sizeof(bet));
3714a385 6448 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6449 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6450 }
6451 if (bgp_static->router_mac) {
6452 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6453 }
6454 }
6455 /* Apply route-map. */
6456 if (bgp_static->rmap.name) {
6457 struct attr attr_tmp = attr;
40381db7 6458 struct bgp_path_info rmap_path;
b68885f9 6459 route_map_result_t ret;
137446f9 6460
40381db7
DS
6461 rmap_path.peer = bgp->peer_self;
6462 rmap_path.attr = &attr_tmp;
137446f9 6463
d62a17ae 6464 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6465
1782514f 6466 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6467
d62a17ae 6468 bgp->peer_self->rmap_type = 0;
137446f9 6469
d62a17ae 6470 if (ret == RMAP_DENYMATCH) {
6471 /* Free uninterned attribute. */
6472 bgp_attr_flush(&attr_tmp);
137446f9 6473
d62a17ae 6474 /* Unintern original. */
6475 aspath_unintern(&attr.aspath);
6476 bgp_static_withdraw_safi(bgp, p, afi, safi,
6477 &bgp_static->prd);
bbc52106 6478 bgp_dest_unlock_node(dest);
d62a17ae 6479 return;
6480 }
137446f9 6481
d62a17ae 6482 attr_new = bgp_attr_intern(&attr_tmp);
6483 } else {
6484 attr_new = bgp_attr_intern(&attr);
6485 }
137446f9 6486
9bcb3eef 6487 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6488 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6489 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6490 break;
6491
40381db7 6492 if (pi) {
40381db7 6493 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6494 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6495 bgp_dest_unlock_node(dest);
d62a17ae 6496 bgp_attr_unintern(&attr_new);
6497 aspath_unintern(&attr.aspath);
6498 return;
6499 } else {
6500 /* The attribute is changed. */
9bcb3eef 6501 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6502
6503 /* Rewrite BGP route information. */
40381db7 6504 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6505 bgp_path_info_restore(dest, pi);
d62a17ae 6506 else
40381db7
DS
6507 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6508 bgp_attr_unintern(&pi->attr);
6509 pi->attr = attr_new;
083ec940 6510 pi->uptime = monotime(NULL);
49e5a4a0 6511#ifdef ENABLE_BGP_VNC
40381db7
DS
6512 if (pi->extra)
6513 label = decode_label(&pi->extra->label[0]);
65efcfce 6514#endif
137446f9 6515
d62a17ae 6516 /* Process change. */
40381db7 6517 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6518 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6519
6520 if (SAFI_MPLS_VPN == safi
6521 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6522 vpn_leak_to_vrf_update(bgp, pi,
6523 &bgp_static->prd);
ddb5b488 6524 }
49e5a4a0 6525#ifdef ENABLE_BGP_VNC
40381db7
DS
6526 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6527 pi->attr, afi, safi, pi->type,
6528 pi->sub_type, &label);
65efcfce 6529#endif
9bcb3eef 6530 bgp_dest_unlock_node(dest);
d62a17ae 6531 aspath_unintern(&attr.aspath);
6532 return;
6533 }
6534 }
137446f9
LB
6535
6536
d62a17ae 6537 /* Make new BGP info. */
6538 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6539 attr_new, dest);
1defdda8 6540 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6541 bgp_path_info_extra_get(new);
b57ba6d2
MK
6542 if (num_labels) {
6543 new->extra->label[0] = bgp_static->label;
6544 new->extra->num_labels = num_labels;
6545 }
49e5a4a0 6546#ifdef ENABLE_BGP_VNC
d62a17ae 6547 label = decode_label(&bgp_static->label);
65efcfce 6548#endif
137446f9 6549
d62a17ae 6550 /* Aggregate address increment. */
6551 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6552
d62a17ae 6553 /* Register new BGP information. */
9bcb3eef 6554 bgp_path_info_add(dest, new);
d62a17ae 6555 /* route_node_get lock */
9bcb3eef 6556 bgp_dest_unlock_node(dest);
137446f9 6557
d62a17ae 6558 /* Process change. */
9bcb3eef 6559 bgp_process(bgp, dest, afi, safi);
137446f9 6560
ddb5b488
PZ
6561 if (SAFI_MPLS_VPN == safi
6562 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6563 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6564 }
49e5a4a0 6565#ifdef ENABLE_BGP_VNC
d62a17ae 6566 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6567 safi, new->type, new->sub_type, &label);
65efcfce
LB
6568#endif
6569
d62a17ae 6570 /* Unintern original. */
6571 aspath_unintern(&attr.aspath);
137446f9
LB
6572}
6573
718e3744 6574/* Configure static BGP network. When user don't run zebra, static
6575 route should be installed as valid. */
585f1adc
IR
6576static int bgp_static_set(struct vty *vty, const char *negate,
6577 const char *ip_str, afi_t afi, safi_t safi,
6578 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6579{
585f1adc
IR
6580 VTY_DECLVAR_CONTEXT(bgp, bgp);
6581 int ret;
d62a17ae 6582 struct prefix p;
6583 struct bgp_static *bgp_static;
9bcb3eef 6584 struct bgp_dest *dest;
d7c0a89a 6585 uint8_t need_update = 0;
d62a17ae 6586
585f1adc
IR
6587 /* Convert IP prefix string to struct prefix. */
6588 ret = str2prefix(ip_str, &p);
6589 if (!ret) {
6590 vty_out(vty, "%% Malformed prefix\n");
6591 return CMD_WARNING_CONFIG_FAILED;
6592 }
6593 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6594 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6595 return CMD_WARNING_CONFIG_FAILED;
6596 }
6597
d62a17ae 6598 apply_mask(&p);
718e3744 6599
e2a86ad9 6600 if (negate) {
718e3744 6601
e2a86ad9 6602 /* Set BGP static route configuration. */
9bcb3eef 6603 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6604
9bcb3eef 6605 if (!dest) {
585f1adc
IR
6606 vty_out(vty, "%% Can't find static route specified\n");
6607 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6608 }
6609
9bcb3eef 6610 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6611
e2a86ad9
DS
6612 if ((label_index != BGP_INVALID_LABEL_INDEX)
6613 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6614 vty_out(vty,
6615 "%% label-index doesn't match static route\n");
70d9b134 6616 bgp_dest_unlock_node(dest);
585f1adc 6617 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6618 }
d62a17ae 6619
e2a86ad9
DS
6620 if ((rmap && bgp_static->rmap.name)
6621 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6622 vty_out(vty,
6623 "%% route-map name doesn't match static route\n");
70d9b134 6624 bgp_dest_unlock_node(dest);
585f1adc 6625 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6626 }
718e3744 6627
e2a86ad9
DS
6628 /* Update BGP RIB. */
6629 if (!bgp_static->backdoor)
6630 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6631
e2a86ad9
DS
6632 /* Clear configuration. */
6633 bgp_static_free(bgp_static);
9bcb3eef
DS
6634 bgp_dest_set_bgp_static_info(dest, NULL);
6635 bgp_dest_unlock_node(dest);
6636 bgp_dest_unlock_node(dest);
e2a86ad9 6637 } else {
718e3744 6638
e2a86ad9 6639 /* Set BGP static route configuration. */
9bcb3eef
DS
6640 dest = bgp_node_get(bgp->route[afi][safi], &p);
6641 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6642 if (bgp_static) {
e2a86ad9 6643 /* Configuration change. */
e2a86ad9
DS
6644 /* Label index cannot be changed. */
6645 if (bgp_static->label_index != label_index) {
585f1adc 6646 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6647 bgp_dest_unlock_node(dest);
585f1adc 6648 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6649 }
d62a17ae 6650
e2a86ad9 6651 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6652 if (bgp_static->valid
6653 && bgp_static->backdoor != backdoor)
e2a86ad9 6654 need_update = 1;
718e3744 6655
e2a86ad9 6656 bgp_static->backdoor = backdoor;
718e3744 6657
e2a86ad9 6658 if (rmap) {
0a22ddfb
QY
6659 XFREE(MTYPE_ROUTE_MAP_NAME,
6660 bgp_static->rmap.name);
b4897fa5 6661 route_map_counter_decrement(
6662 bgp_static->rmap.map);
e2a86ad9
DS
6663 bgp_static->rmap.name =
6664 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6665 bgp_static->rmap.map =
6666 route_map_lookup_by_name(rmap);
b4897fa5 6667 route_map_counter_increment(
6668 bgp_static->rmap.map);
e2a86ad9 6669 } else {
0a22ddfb
QY
6670 XFREE(MTYPE_ROUTE_MAP_NAME,
6671 bgp_static->rmap.name);
b4897fa5 6672 route_map_counter_decrement(
6673 bgp_static->rmap.map);
e2a86ad9
DS
6674 bgp_static->rmap.map = NULL;
6675 bgp_static->valid = 0;
6676 }
9bcb3eef 6677 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6678 } else {
6679 /* New configuration. */
6680 bgp_static = bgp_static_new();
6681 bgp_static->backdoor = backdoor;
6682 bgp_static->valid = 0;
6683 bgp_static->igpmetric = 0;
975a328e 6684 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6685 bgp_static->label_index = label_index;
718e3744 6686
e2a86ad9 6687 if (rmap) {
0a22ddfb
QY
6688 XFREE(MTYPE_ROUTE_MAP_NAME,
6689 bgp_static->rmap.name);
b4897fa5 6690 route_map_counter_decrement(
6691 bgp_static->rmap.map);
e2a86ad9
DS
6692 bgp_static->rmap.name =
6693 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6694 bgp_static->rmap.map =
6695 route_map_lookup_by_name(rmap);
b4897fa5 6696 route_map_counter_increment(
6697 bgp_static->rmap.map);
e2a86ad9 6698 }
9bcb3eef 6699 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6700 }
d62a17ae 6701
e2a86ad9
DS
6702 bgp_static->valid = 1;
6703 if (need_update)
6704 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6705
e2a86ad9
DS
6706 if (!bgp_static->backdoor)
6707 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6708 }
d62a17ae 6709
585f1adc 6710 return CMD_SUCCESS;
d62a17ae 6711}
6712
6713void bgp_static_add(struct bgp *bgp)
6714{
6715 afi_t afi;
6716 safi_t safi;
9bcb3eef
DS
6717 struct bgp_dest *dest;
6718 struct bgp_dest *rm;
d62a17ae 6719 struct bgp_table *table;
6720 struct bgp_static *bgp_static;
6721
47fc6261 6722 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6723 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6724 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6725 dest = bgp_route_next(dest)) {
6726 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6727 continue;
ea47320b 6728
05c7a1cc
QY
6729 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6730 || (safi == SAFI_EVPN)) {
9bcb3eef 6731 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6732
6733 for (rm = bgp_table_top(table); rm;
6734 rm = bgp_route_next(rm)) {
a78beeb5 6735 bgp_static =
9bcb3eef 6736 bgp_dest_get_bgp_static_info(
5a8ba9fc 6737 rm);
9bcb3eef
DS
6738 bgp_static_update_safi(
6739 bgp, bgp_dest_get_prefix(rm),
6740 bgp_static, afi, safi);
d62a17ae 6741 }
05c7a1cc 6742 } else {
5a8ba9fc 6743 bgp_static_update(
9bcb3eef
DS
6744 bgp, bgp_dest_get_prefix(dest),
6745 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6746 safi);
ea47320b 6747 }
05c7a1cc 6748 }
47fc6261 6749 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6750}
6751
718e3744 6752/* Called from bgp_delete(). Delete all static routes from the BGP
6753 instance. */
d62a17ae 6754void bgp_static_delete(struct bgp *bgp)
6755{
6756 afi_t afi;
6757 safi_t safi;
9bcb3eef
DS
6758 struct bgp_dest *dest;
6759 struct bgp_dest *rm;
d62a17ae 6760 struct bgp_table *table;
6761 struct bgp_static *bgp_static;
6762
05c7a1cc 6763 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6764 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6765 dest = bgp_route_next(dest)) {
6766 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6767 continue;
ea47320b 6768
05c7a1cc
QY
6769 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6770 || (safi == SAFI_EVPN)) {
9bcb3eef 6771 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6772
6773 for (rm = bgp_table_top(table); rm;
6774 rm = bgp_route_next(rm)) {
a78beeb5 6775 bgp_static =
9bcb3eef 6776 bgp_dest_get_bgp_static_info(
5a8ba9fc 6777 rm);
c7d14ba6
PG
6778 if (!bgp_static)
6779 continue;
6780
05c7a1cc 6781 bgp_static_withdraw_safi(
9bcb3eef 6782 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6783 AFI_IP, safi,
6784 (struct prefix_rd *)
9bcb3eef
DS
6785 bgp_dest_get_prefix(
6786 dest));
ea47320b 6787 bgp_static_free(bgp_static);
811c6797 6788 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6789 NULL);
811c6797 6790 bgp_dest_unlock_node(rm);
d62a17ae 6791 }
05c7a1cc 6792 } else {
9bcb3eef 6793 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6794 bgp_static_withdraw(bgp,
9bcb3eef 6795 bgp_dest_get_prefix(dest),
b54892e0 6796 afi, safi);
05c7a1cc 6797 bgp_static_free(bgp_static);
9bcb3eef
DS
6798 bgp_dest_set_bgp_static_info(dest, NULL);
6799 bgp_dest_unlock_node(dest);
ea47320b 6800 }
05c7a1cc 6801 }
d62a17ae 6802}
6803
6804void bgp_static_redo_import_check(struct bgp *bgp)
6805{
6806 afi_t afi;
6807 safi_t safi;
9bcb3eef
DS
6808 struct bgp_dest *dest;
6809 struct bgp_dest *rm;
d62a17ae 6810 struct bgp_table *table;
6811 struct bgp_static *bgp_static;
6812
6813 /* Use this flag to force reprocessing of the route */
892fedb6 6814 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6815 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6816 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6817 dest = bgp_route_next(dest)) {
6818 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6819 continue;
ea47320b 6820
05c7a1cc
QY
6821 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6822 || (safi == SAFI_EVPN)) {
9bcb3eef 6823 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6824
6825 for (rm = bgp_table_top(table); rm;
6826 rm = bgp_route_next(rm)) {
a78beeb5 6827 bgp_static =
9bcb3eef 6828 bgp_dest_get_bgp_static_info(
5a8ba9fc 6829 rm);
9bcb3eef
DS
6830 bgp_static_update_safi(
6831 bgp, bgp_dest_get_prefix(rm),
6832 bgp_static, afi, safi);
d62a17ae 6833 }
05c7a1cc 6834 } else {
9bcb3eef
DS
6835 bgp_static = bgp_dest_get_bgp_static_info(dest);
6836 bgp_static_update(bgp,
6837 bgp_dest_get_prefix(dest),
6838 bgp_static, afi, safi);
ea47320b 6839 }
05c7a1cc
QY
6840 }
6841 }
892fedb6 6842 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6843}
6844
6845static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6846 safi_t safi)
6847{
6848 struct bgp_table *table;
9bcb3eef 6849 struct bgp_dest *dest;
40381db7 6850 struct bgp_path_info *pi;
d62a17ae 6851
dfb6fd1d
NT
6852 /* Do not install the aggregate route if BGP is in the
6853 * process of termination.
6854 */
892fedb6
DA
6855 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6856 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6857 return;
6858
d62a17ae 6859 table = bgp->rib[afi][safi];
9bcb3eef
DS
6860 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6861 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6862 if (pi->peer == bgp->peer_self
6863 && ((pi->type == ZEBRA_ROUTE_BGP
6864 && pi->sub_type == BGP_ROUTE_STATIC)
6865 || (pi->type != ZEBRA_ROUTE_BGP
6866 && pi->sub_type
d62a17ae 6867 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6868 bgp_aggregate_decrement(
6869 bgp, bgp_dest_get_prefix(dest), pi, afi,
6870 safi);
40381db7 6871 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6872 bgp_path_info_delete(dest, pi);
6873 bgp_process(bgp, dest, afi, safi);
d62a17ae 6874 }
6875 }
6876 }
ad4cbda1 6877}
6878
6879/*
6880 * Purge all networks and redistributed routes from routing table.
6881 * Invoked upon the instance going down.
6882 */
d62a17ae 6883void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6884{
d62a17ae 6885 afi_t afi;
6886 safi_t safi;
ad4cbda1 6887
05c7a1cc
QY
6888 FOREACH_AFI_SAFI (afi, safi)
6889 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6890}
6891
137446f9
LB
6892/*
6893 * gpz 110624
6894 * Currently this is used to set static routes for VPN and ENCAP.
6895 * I think it can probably be factored with bgp_static_set.
6896 */
d62a17ae 6897int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6898 const char *ip_str, const char *rd_str,
6899 const char *label_str, const char *rmap_str,
6900 int evpn_type, const char *esi, const char *gwip,
6901 const char *ethtag, const char *routermac)
6902{
6903 VTY_DECLVAR_CONTEXT(bgp, bgp);
6904 int ret;
6905 struct prefix p;
6906 struct prefix_rd prd;
9bcb3eef
DS
6907 struct bgp_dest *pdest;
6908 struct bgp_dest *dest;
d62a17ae 6909 struct bgp_table *table;
6910 struct bgp_static *bgp_static;
6911 mpls_label_t label = MPLS_INVALID_LABEL;
6912 struct prefix gw_ip;
6913
6914 /* validate ip prefix */
6915 ret = str2prefix(ip_str, &p);
6916 if (!ret) {
6917 vty_out(vty, "%% Malformed prefix\n");
6918 return CMD_WARNING_CONFIG_FAILED;
6919 }
6920 apply_mask(&p);
6921 if ((afi == AFI_L2VPN)
6922 && (bgp_build_evpn_prefix(evpn_type,
6923 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6924 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6925 return CMD_WARNING_CONFIG_FAILED;
6926 }
718e3744 6927
d62a17ae 6928 ret = str2prefix_rd(rd_str, &prd);
6929 if (!ret) {
6930 vty_out(vty, "%% Malformed rd\n");
6931 return CMD_WARNING_CONFIG_FAILED;
6932 }
718e3744 6933
d62a17ae 6934 if (label_str) {
6935 unsigned long label_val;
6936 label_val = strtoul(label_str, NULL, 10);
6937 encode_label(label_val, &label);
6938 }
9bedbb1e 6939
d62a17ae 6940 if (safi == SAFI_EVPN) {
6941 if (esi && str2esi(esi, NULL) == 0) {
6942 vty_out(vty, "%% Malformed ESI\n");
6943 return CMD_WARNING_CONFIG_FAILED;
6944 }
6945 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6946 vty_out(vty, "%% Malformed Router MAC\n");
6947 return CMD_WARNING_CONFIG_FAILED;
6948 }
6949 if (gwip) {
6006b807 6950 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6951 ret = str2prefix(gwip, &gw_ip);
6952 if (!ret) {
6953 vty_out(vty, "%% Malformed GatewayIp\n");
6954 return CMD_WARNING_CONFIG_FAILED;
6955 }
6956 if ((gw_ip.family == AF_INET
3714a385 6957 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6958 (struct prefix_evpn *)&p))
6959 || (gw_ip.family == AF_INET6
3714a385 6960 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6961 (struct prefix_evpn *)&p))) {
6962 vty_out(vty,
6963 "%% GatewayIp family differs with IP prefix\n");
6964 return CMD_WARNING_CONFIG_FAILED;
6965 }
6966 }
6967 }
9bcb3eef
DS
6968 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6969 if (!bgp_dest_has_bgp_path_info_data(pdest))
6970 bgp_dest_set_bgp_table_info(pdest,
67009e22 6971 bgp_table_init(bgp, afi, safi));
9bcb3eef 6972 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6973
9bcb3eef 6974 dest = bgp_node_get(table, &p);
d62a17ae 6975
9bcb3eef 6976 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6977 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6978 bgp_dest_unlock_node(dest);
d62a17ae 6979 } else {
6980 /* New configuration. */
6981 bgp_static = bgp_static_new();
6982 bgp_static->backdoor = 0;
6983 bgp_static->valid = 0;
6984 bgp_static->igpmetric = 0;
975a328e 6985 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6986 bgp_static->label = label;
6987 bgp_static->prd = prd;
6988
6989 if (rmap_str) {
0a22ddfb 6990 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6991 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6992 bgp_static->rmap.name =
6993 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6994 bgp_static->rmap.map =
6995 route_map_lookup_by_name(rmap_str);
b4897fa5 6996 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6997 }
718e3744 6998
d62a17ae 6999 if (safi == SAFI_EVPN) {
7000 if (esi) {
7001 bgp_static->eth_s_id =
7002 XCALLOC(MTYPE_ATTR,
0a50c248 7003 sizeof(esi_t));
d62a17ae 7004 str2esi(esi, bgp_static->eth_s_id);
7005 }
7006 if (routermac) {
7007 bgp_static->router_mac =
28328ea9 7008 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7009 (void)prefix_str2mac(routermac,
7010 bgp_static->router_mac);
d62a17ae 7011 }
7012 if (gwip)
7013 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7014 }
9bcb3eef 7015 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7016
d62a17ae 7017 bgp_static->valid = 1;
7018 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7019 }
718e3744 7020
d62a17ae 7021 return CMD_SUCCESS;
718e3744 7022}
7023
7024/* Configure static BGP network. */
d62a17ae 7025int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7026 const char *ip_str, const char *rd_str,
7027 const char *label_str, int evpn_type, const char *esi,
7028 const char *gwip, const char *ethtag)
7029{
7030 VTY_DECLVAR_CONTEXT(bgp, bgp);
7031 int ret;
7032 struct prefix p;
7033 struct prefix_rd prd;
9bcb3eef
DS
7034 struct bgp_dest *pdest;
7035 struct bgp_dest *dest;
d62a17ae 7036 struct bgp_table *table;
7037 struct bgp_static *bgp_static;
7038 mpls_label_t label = MPLS_INVALID_LABEL;
7039
7040 /* Convert IP prefix string to struct prefix. */
7041 ret = str2prefix(ip_str, &p);
7042 if (!ret) {
7043 vty_out(vty, "%% Malformed prefix\n");
7044 return CMD_WARNING_CONFIG_FAILED;
7045 }
7046 apply_mask(&p);
7047 if ((afi == AFI_L2VPN)
7048 && (bgp_build_evpn_prefix(evpn_type,
7049 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7050 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7051 return CMD_WARNING_CONFIG_FAILED;
7052 }
7053 ret = str2prefix_rd(rd_str, &prd);
7054 if (!ret) {
7055 vty_out(vty, "%% Malformed rd\n");
7056 return CMD_WARNING_CONFIG_FAILED;
7057 }
718e3744 7058
d62a17ae 7059 if (label_str) {
7060 unsigned long label_val;
7061 label_val = strtoul(label_str, NULL, 10);
7062 encode_label(label_val, &label);
7063 }
718e3744 7064
9bcb3eef
DS
7065 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7066 if (!bgp_dest_has_bgp_path_info_data(pdest))
7067 bgp_dest_set_bgp_table_info(pdest,
67009e22 7068 bgp_table_init(bgp, afi, safi));
d62a17ae 7069 else
9bcb3eef
DS
7070 bgp_dest_unlock_node(pdest);
7071 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7072
9bcb3eef 7073 dest = bgp_node_lookup(table, &p);
6b0655a2 7074
9bcb3eef 7075 if (dest) {
d62a17ae 7076 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7077
9bcb3eef 7078 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7079 bgp_static_free(bgp_static);
9bcb3eef
DS
7080 bgp_dest_set_bgp_static_info(dest, NULL);
7081 bgp_dest_unlock_node(dest);
7082 bgp_dest_unlock_node(dest);
d62a17ae 7083 } else
7084 vty_out(vty, "%% Can't find the route\n");
7085
7086 return CMD_SUCCESS;
7087}
7088
7089static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7090 const char *rmap_name)
7091{
7092 VTY_DECLVAR_CONTEXT(bgp, bgp);
7093 struct bgp_rmap *rmap;
7094
7095 rmap = &bgp->table_map[afi][safi];
7096 if (rmap_name) {
0a22ddfb 7097 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7098 route_map_counter_decrement(rmap->map);
d62a17ae 7099 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7100 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7101 route_map_counter_increment(rmap->map);
d62a17ae 7102 } else {
0a22ddfb 7103 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7104 route_map_counter_decrement(rmap->map);
d62a17ae 7105 rmap->map = NULL;
7106 }
73ac8160 7107
d62a17ae 7108 if (bgp_fibupd_safi(safi))
7109 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7110
d62a17ae 7111 return CMD_SUCCESS;
73ac8160
DS
7112}
7113
d62a17ae 7114static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7115 const char *rmap_name)
73ac8160 7116{
d62a17ae 7117 VTY_DECLVAR_CONTEXT(bgp, bgp);
7118 struct bgp_rmap *rmap;
73ac8160 7119
d62a17ae 7120 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7121 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7122 route_map_counter_decrement(rmap->map);
d62a17ae 7123 rmap->map = NULL;
73ac8160 7124
d62a17ae 7125 if (bgp_fibupd_safi(safi))
7126 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7127
d62a17ae 7128 return CMD_SUCCESS;
73ac8160
DS
7129}
7130
2b791107 7131void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7132 safi_t safi)
73ac8160 7133{
d62a17ae 7134 if (bgp->table_map[afi][safi].name) {
d62a17ae 7135 vty_out(vty, " table-map %s\n",
7136 bgp->table_map[afi][safi].name);
7137 }
73ac8160
DS
7138}
7139
73ac8160
DS
7140DEFUN (bgp_table_map,
7141 bgp_table_map_cmd,
7142 "table-map WORD",
7143 "BGP table to RIB route download filter\n"
7144 "Name of the route map\n")
7145{
d62a17ae 7146 int idx_word = 1;
7147 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7148 argv[idx_word]->arg);
73ac8160
DS
7149}
7150DEFUN (no_bgp_table_map,
7151 no_bgp_table_map_cmd,
7152 "no table-map WORD",
3a2d747c 7153 NO_STR
73ac8160
DS
7154 "BGP table to RIB route download filter\n"
7155 "Name of the route map\n")
7156{
d62a17ae 7157 int idx_word = 2;
7158 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7159 argv[idx_word]->arg);
73ac8160
DS
7160}
7161
585f1adc
IR
7162DEFPY(bgp_network,
7163 bgp_network_cmd,
7164 "[no] network \
7165 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7166 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7167 backdoor$backdoor}]",
7168 NO_STR
7169 "Specify a network to announce via BGP\n"
7170 "IPv4 prefix\n"
7171 "Network number\n"
7172 "Network mask\n"
7173 "Network mask\n"
7174 "Route-map to modify the attributes\n"
7175 "Name of the route map\n"
7176 "Label index to associate with the prefix\n"
7177 "Label index value\n"
7178 "Specify a BGP backdoor route\n")
7179{
7180 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7181
7182 if (address_str) {
7183 int ret;
718e3744 7184
e2a86ad9 7185 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7186 addr_prefix_str,
7187 sizeof(addr_prefix_str));
e2a86ad9
DS
7188 if (!ret) {
7189 vty_out(vty, "%% Inconsistent address and mask\n");
7190 return CMD_WARNING_CONFIG_FAILED;
7191 }
d62a17ae 7192 }
718e3744 7193
585f1adc
IR
7194 return bgp_static_set(
7195 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7196 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7197 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7198}
7199
585f1adc
IR
7200DEFPY(ipv6_bgp_network,
7201 ipv6_bgp_network_cmd,
7202 "[no] network X:X::X:X/M$prefix \
70dd370f 7203 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7204 NO_STR
7205 "Specify a network to announce via BGP\n"
7206 "IPv6 prefix\n"
7207 "Route-map to modify the attributes\n"
7208 "Name of the route map\n"
7209 "Label index to associate with the prefix\n"
7210 "Label index value\n")
37a87b8f 7211{
585f1adc
IR
7212 return bgp_static_set(
7213 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7214 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7215}
7216
d62a17ae 7217static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7218{
d62a17ae 7219 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7220}
7221
d62a17ae 7222static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7223{
365ab2e7
RZ
7224 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7225 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7226 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7227 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7228 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7229}
718e3744 7230
365ab2e7
RZ
7231/**
7232 * Helper function to avoid repeated code: prepare variables for a
7233 * `route_map_apply` call.
7234 *
7235 * \returns `true` on route map match, otherwise `false`.
7236 */
7237static bool aggr_suppress_map_test(struct bgp *bgp,
7238 struct bgp_aggregate *aggregate,
7239 struct bgp_path_info *pi)
7240{
7241 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7242 route_map_result_t rmr = RMAP_DENYMATCH;
7243 struct bgp_path_info rmap_path = {};
7244 struct attr attr = {};
7245
7246 /* No route map entries created, just don't match. */
7247 if (aggregate->suppress_map == NULL)
7248 return false;
7249
7250 /* Call route map matching and return result. */
7251 attr.aspath = aspath_empty();
7252 rmap_path.peer = bgp->peer_self;
7253 rmap_path.attr = &attr;
7254
7255 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7256 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7257 bgp->peer_self->rmap_type = 0;
7258
7259 bgp_attr_flush(&attr);
afb254d7 7260 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7261
7262 return rmr == RMAP_PERMITMATCH;
7263}
7264
4056a5f6
RZ
7265/** Test whether the aggregation has suppressed this path or not. */
7266static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7267 struct bgp_path_info *pi)
7268{
7269 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7270 return false;
7271
7272 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7273}
7274
7275/**
7276 * Suppress this path and keep the reference.
7277 *
7278 * \returns `true` if needs processing otherwise `false`.
7279 */
7280static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7281 struct bgp_path_info *pi)
7282{
7283 struct bgp_path_info_extra *pie;
7284
7285 /* Path is already suppressed by this aggregation. */
7286 if (aggr_suppress_exists(aggregate, pi))
7287 return false;
7288
7289 pie = bgp_path_info_extra_get(pi);
7290
7291 /* This is the first suppression, allocate memory and list it. */
7292 if (pie->aggr_suppressors == NULL)
7293 pie->aggr_suppressors = list_new();
7294
7295 listnode_add(pie->aggr_suppressors, aggregate);
7296
7297 /* Only mark for processing if suppressed. */
7298 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7299 if (BGP_DEBUG(update, UPDATE_OUT))
7300 zlog_debug("aggregate-address suppressing: %pFX",
7301 bgp_dest_get_prefix(pi->net));
7302
4056a5f6
RZ
7303 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7304 return true;
7305 }
7306
7307 return false;
7308}
7309
7310/**
7311 * Unsuppress this path and remove the reference.
7312 *
7313 * \returns `true` if needs processing otherwise `false`.
7314 */
7315static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7316 struct bgp_path_info *pi)
7317{
7318 /* Path wasn't suppressed. */
7319 if (!aggr_suppress_exists(aggregate, pi))
7320 return false;
7321
7322 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7323
7324 /* Unsuppress and free extra memory if last item. */
7325 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7326 if (BGP_DEBUG(update, UPDATE_OUT))
7327 zlog_debug("aggregate-address unsuppressing: %pFX",
7328 bgp_dest_get_prefix(pi->net));
7329
4056a5f6
RZ
7330 list_delete(&pi->extra->aggr_suppressors);
7331 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7332 return true;
7333 }
7334
7335 return false;
7336}
7337
3dc339cd
DA
7338static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7339 struct aspath *aspath,
7340 struct community *comm,
7341 struct ecommunity *ecomm,
7342 struct lcommunity *lcomm)
eaaf8adb
DS
7343{
7344 static struct aspath *ae = NULL;
7345
7346 if (!ae)
7347 ae = aspath_empty();
7348
40381db7 7349 if (!pi)
3dc339cd 7350 return false;
eaaf8adb 7351
40381db7 7352 if (origin != pi->attr->origin)
3dc339cd 7353 return false;
eaaf8adb 7354
40381db7 7355 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7356 return false;
29f7d023 7357
9a706b42 7358 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7359 return false;
eaaf8adb 7360
b53e67a3 7361 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7362 return false;
eaaf8adb 7363
1bcf3a96 7364 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7365 return false;
dd18c5a9 7366
40381db7 7367 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7368 return false;
7ce8a8e0 7369
3dc339cd 7370 return true;
eaaf8adb
DS
7371}
7372
5f040085
DS
7373static void bgp_aggregate_install(
7374 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7375 uint8_t origin, struct aspath *aspath, struct community *community,
7376 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7377 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7378{
9bcb3eef 7379 struct bgp_dest *dest;
c701010e 7380 struct bgp_table *table;
6f94b685 7381 struct bgp_path_info *pi, *orig, *new;
20894f50 7382 struct attr *attr;
c701010e
DS
7383
7384 table = bgp->rib[afi][safi];
7385
9bcb3eef 7386 dest = bgp_node_get(table, p);
eaaf8adb 7387
9bcb3eef 7388 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7389 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7390 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7391 break;
7392
6aabb15d
RZ
7393 /*
7394 * If we have paths with different MEDs, then don't install
7395 * (or uninstall) the aggregate route.
7396 */
7397 if (aggregate->match_med && aggregate->med_mismatched)
7398 goto uninstall_aggregate_route;
7399
c701010e 7400 if (aggregate->count > 0) {
eaaf8adb
DS
7401 /*
7402 * If the aggregate information has not changed
7403 * no need to re-install it again.
7404 */
6f94b685 7405 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7406 ecommunity, lcommunity)) {
9bcb3eef 7407 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7408
7409 if (aspath)
7410 aspath_free(aspath);
7411 if (community)
3c1f53de 7412 community_free(&community);
3da2cc32
DS
7413 if (ecommunity)
7414 ecommunity_free(&ecommunity);
dd18c5a9
DS
7415 if (lcommunity)
7416 lcommunity_free(&lcommunity);
eaaf8adb
DS
7417
7418 return;
7419 }
7420
7421 /*
7422 * Mark the old as unusable
7423 */
40381db7 7424 if (pi)
9bcb3eef 7425 bgp_path_info_delete(dest, pi);
eaaf8adb 7426
20894f50
DA
7427 attr = bgp_attr_aggregate_intern(
7428 bgp, origin, aspath, community, ecommunity, lcommunity,
7429 aggregate, atomic_aggregate, p);
7430
7431 if (!attr) {
8c0044f3 7432 bgp_dest_unlock_node(dest);
20894f50 7433 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7434 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7435 zlog_debug("%s: %pFX null attribute", __func__,
7436 p);
20894f50
DA
7437 return;
7438 }
7439
3da2cc32 7440 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7441 bgp->peer_self, attr, dest);
20894f50 7442
1defdda8 7443 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7444
9bcb3eef
DS
7445 bgp_path_info_add(dest, new);
7446 bgp_process(bgp, dest, afi, safi);
c701010e 7447 } else {
6aabb15d 7448 uninstall_aggregate_route:
6f94b685 7449 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7450 if (pi->peer == bgp->peer_self
7451 && pi->type == ZEBRA_ROUTE_BGP
7452 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7453 break;
7454
7455 /* Withdraw static BGP route from routing table. */
40381db7 7456 if (pi) {
9bcb3eef
DS
7457 bgp_path_info_delete(dest, pi);
7458 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7459 }
7460 }
7461
9bcb3eef 7462 bgp_dest_unlock_node(dest);
c701010e
DS
7463}
7464
6aabb15d
RZ
7465/**
7466 * Check if the current path has different MED than other known paths.
7467 *
7468 * \returns `true` if the MED matched the others else `false`.
7469 */
7470static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7471 struct bgp *bgp, struct bgp_path_info *pi)
7472{
7473 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7474
7475 /* This is the first route being analyzed. */
7476 if (!aggregate->med_initialized) {
7477 aggregate->med_initialized = true;
7478 aggregate->med_mismatched = false;
7479 aggregate->med_matched_value = cur_med;
7480 } else {
7481 /* Check if routes with different MED showed up. */
7482 if (cur_med != aggregate->med_matched_value)
7483 aggregate->med_mismatched = true;
7484 }
7485
7486 return !aggregate->med_mismatched;
7487}
7488
7489/**
7490 * Initializes and tests all routes in the aggregate address path for MED
7491 * values.
7492 *
7493 * \returns `true` if all MEDs are the same otherwise `false`.
7494 */
7495static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7496 struct bgp *bgp, const struct prefix *p,
7497 afi_t afi, safi_t safi)
7498{
7499 struct bgp_table *table = bgp->rib[afi][safi];
7500 const struct prefix *dest_p;
7501 struct bgp_dest *dest, *top;
7502 struct bgp_path_info *pi;
7503 bool med_matched = true;
7504
7505 aggregate->med_initialized = false;
7506
7507 top = bgp_node_get(table, p);
7508 for (dest = bgp_node_get(table, p); dest;
7509 dest = bgp_route_next_until(dest, top)) {
7510 dest_p = bgp_dest_get_prefix(dest);
7511 if (dest_p->prefixlen <= p->prefixlen)
7512 continue;
7513
7514 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7515 if (BGP_PATH_HOLDDOWN(pi))
7516 continue;
7517 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7518 continue;
7519 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7520 med_matched = false;
7521 break;
7522 }
7523 }
7524 if (!med_matched)
7525 break;
7526 }
7527 bgp_dest_unlock_node(top);
7528
7529 return med_matched;
7530}
7531
7532/**
7533 * Toggles the route suppression status for this aggregate address
7534 * configuration.
7535 */
4056a5f6
RZ
7536void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7537 struct bgp *bgp, const struct prefix *p,
7538 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7539{
7540 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7541 const struct prefix *dest_p;
7542 struct bgp_dest *dest, *top;
7543 struct bgp_path_info *pi;
7544 bool toggle_suppression;
7545
7546 /* We've found a different MED we must revert any suppressed routes. */
7547 top = bgp_node_get(table, p);
7548 for (dest = bgp_node_get(table, p); dest;
7549 dest = bgp_route_next_until(dest, top)) {
7550 dest_p = bgp_dest_get_prefix(dest);
7551 if (dest_p->prefixlen <= p->prefixlen)
7552 continue;
7553
7554 toggle_suppression = false;
7555 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7556 if (BGP_PATH_HOLDDOWN(pi))
7557 continue;
7558 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7559 continue;
7560
6aabb15d
RZ
7561 /* We are toggling suppression back. */
7562 if (suppress) {
6aabb15d 7563 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7564 if (aggr_suppress_path(aggregate, pi))
7565 toggle_suppression = true;
6aabb15d
RZ
7566 continue;
7567 }
7568
6aabb15d 7569 /* Install route if there is no more suppression. */
4056a5f6 7570 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7571 toggle_suppression = true;
6aabb15d
RZ
7572 }
7573
7574 if (toggle_suppression)
7575 bgp_process(bgp, dest, afi, safi);
7576 }
7577 bgp_dest_unlock_node(top);
7578}
7579
7580/**
7581 * Aggregate address MED matching incremental test: this function is called
7582 * when the initial aggregation occurred and we are only testing a single
7583 * new path.
7584 *
7585 * In addition to testing and setting the MED validity it also installs back
7586 * suppressed routes (if summary is configured).
7587 *
7588 * Must not be called in `bgp_aggregate_route`.
7589 */
7590static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7591 struct bgp *bgp, const struct prefix *p,
7592 afi_t afi, safi_t safi,
f66624f5 7593 struct bgp_path_info *pi)
6aabb15d
RZ
7594{
7595 /* MED matching disabled. */
7596 if (!aggregate->match_med)
7597 return;
7598
f66624f5
DA
7599 /* Aggregation with different MED, recheck if we have got equal MEDs
7600 * now.
6aabb15d 7601 */
f66624f5
DA
7602 if (aggregate->med_mismatched &&
7603 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7604 aggregate->summary_only)
7605 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7606 true);
7607 else
6aabb15d
RZ
7608 bgp_aggregate_med_match(aggregate, bgp, pi);
7609
7610 /* No mismatches, just quit. */
7611 if (!aggregate->med_mismatched)
7612 return;
7613
7614 /* Route summarization is disabled. */
7615 if (!aggregate->summary_only)
7616 return;
7617
7618 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7619}
7620
b5d58c32 7621/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7622void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7623 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7624{
7625 struct bgp_table *table;
9bcb3eef
DS
7626 struct bgp_dest *top;
7627 struct bgp_dest *dest;
d7c0a89a 7628 uint8_t origin;
d62a17ae 7629 struct aspath *aspath = NULL;
d62a17ae 7630 struct community *community = NULL;
3da2cc32 7631 struct ecommunity *ecommunity = NULL;
dd18c5a9 7632 struct lcommunity *lcommunity = NULL;
40381db7 7633 struct bgp_path_info *pi;
d62a17ae 7634 unsigned long match = 0;
d7c0a89a 7635 uint8_t atomic_aggregate = 0;
d62a17ae 7636
9f822fa2
S
7637 /* If the bgp instance is being deleted or self peer is deleted
7638 * then do not create aggregate route
7639 */
892fedb6
DA
7640 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7641 || (bgp->peer_self == NULL))
9f822fa2
S
7642 return;
7643
6aabb15d
RZ
7644 /* Initialize and test routes for MED difference. */
7645 if (aggregate->match_med)
7646 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7647
4056a5f6
RZ
7648 /*
7649 * Reset aggregate count: we might've been called from route map
7650 * update so in that case we must retest all more specific routes.
7651 *
7652 * \see `bgp_route_map_process_update`.
7653 */
7654 aggregate->count = 0;
7655 aggregate->incomplete_origin_count = 0;
7656 aggregate->incomplete_origin_count = 0;
7657 aggregate->egp_origin_count = 0;
7658
d62a17ae 7659 /* ORIGIN attribute: If at least one route among routes that are
7660 aggregated has ORIGIN with the value INCOMPLETE, then the
7661 aggregated route must have the ORIGIN attribute with the value
7662 INCOMPLETE. Otherwise, if at least one route among routes that
7663 are aggregated has ORIGIN with the value EGP, then the aggregated
7664 route must have the origin attribute with the value EGP. In all
7665 other case the value of the ORIGIN attribute of the aggregated
7666 route is INTERNAL. */
7667 origin = BGP_ORIGIN_IGP;
718e3744 7668
d62a17ae 7669 table = bgp->rib[afi][safi];
718e3744 7670
d62a17ae 7671 top = bgp_node_get(table, p);
9bcb3eef
DS
7672 for (dest = bgp_node_get(table, p); dest;
7673 dest = bgp_route_next_until(dest, top)) {
7674 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7675
9bcb3eef 7676 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7677 continue;
d62a17ae 7678
a77e2f4b
S
7679 /* If suppress fib is enabled and route not installed
7680 * in FIB, skip the route
7681 */
7682 if (!bgp_check_advertise(bgp, dest))
7683 continue;
7684
c2ff8b3e 7685 match = 0;
d62a17ae 7686
9bcb3eef 7687 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7688 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7689 continue;
718e3744 7690
40381db7 7691 if (pi->attr->flag
c2ff8b3e
DS
7692 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7693 atomic_aggregate = 1;
d62a17ae 7694
40381db7 7695 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7696 continue;
d62a17ae 7697
f273fef1
DS
7698 /*
7699 * summary-only aggregate route suppress
7700 * aggregated route announcements.
6aabb15d
RZ
7701 *
7702 * MED matching:
7703 * Don't create summaries if MED didn't match
7704 * otherwise neither the specific routes and the
7705 * aggregation will be announced.
f273fef1 7706 */
6aabb15d
RZ
7707 if (aggregate->summary_only
7708 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7709 if (aggr_suppress_path(aggregate, pi))
7710 match++;
d62a17ae 7711 }
c2ff8b3e 7712
365ab2e7
RZ
7713 /*
7714 * Suppress more specific routes that match the route
7715 * map results.
7716 *
7717 * MED matching:
7718 * Don't suppress routes if MED matching is enabled and
7719 * it mismatched otherwise we might end up with no
7720 * routes for this path.
7721 */
7722 if (aggregate->suppress_map_name
7723 && AGGREGATE_MED_VALID(aggregate)
7724 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7725 if (aggr_suppress_path(aggregate, pi))
7726 match++;
d62a17ae 7727 }
c2ff8b3e
DS
7728
7729 aggregate->count++;
7730
f273fef1
DS
7731 /*
7732 * If at least one route among routes that are
7733 * aggregated has ORIGIN with the value INCOMPLETE,
7734 * then the aggregated route MUST have the ORIGIN
7735 * attribute with the value INCOMPLETE. Otherwise, if
7736 * at least one route among routes that are aggregated
7737 * has ORIGIN with the value EGP, then the aggregated
7738 * route MUST have the ORIGIN attribute with the value
7739 * EGP.
7740 */
fc968841
NT
7741 switch (pi->attr->origin) {
7742 case BGP_ORIGIN_INCOMPLETE:
7743 aggregate->incomplete_origin_count++;
7744 break;
7745 case BGP_ORIGIN_EGP:
7746 aggregate->egp_origin_count++;
7747 break;
7748 default:
7749 /*Do nothing.
7750 */
7751 break;
7752 }
c2ff8b3e
DS
7753
7754 if (!aggregate->as_set)
7755 continue;
7756
f273fef1
DS
7757 /*
7758 * as-set aggregate route generate origin, as path,
7759 * and community aggregation.
7760 */
fc968841
NT
7761 /* Compute aggregate route's as-path.
7762 */
ef51a7d8 7763 bgp_compute_aggregate_aspath_hash(aggregate,
7764 pi->attr->aspath);
c2ff8b3e 7765
fc968841
NT
7766 /* Compute aggregate route's community.
7767 */
9a706b42 7768 if (bgp_attr_get_community(pi->attr))
21fec674 7769 bgp_compute_aggregate_community_hash(
9a706b42
DA
7770 aggregate,
7771 bgp_attr_get_community(pi->attr));
dd18c5a9 7772
fc968841
NT
7773 /* Compute aggregate route's extended community.
7774 */
b53e67a3 7775 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7776 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7777 aggregate,
7778 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7779
7780 /* Compute aggregate route's large community.
7781 */
1bcf3a96 7782 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7783 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7784 aggregate,
7785 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7786 }
c2ff8b3e 7787 if (match)
9bcb3eef 7788 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7789 }
21fec674 7790 if (aggregate->as_set) {
ef51a7d8 7791 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7792 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7793 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7794 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7795 }
7796
f1eb1f05 7797
9bcb3eef 7798 bgp_dest_unlock_node(top);
718e3744 7799
718e3744 7800
fc968841
NT
7801 if (aggregate->incomplete_origin_count > 0)
7802 origin = BGP_ORIGIN_INCOMPLETE;
7803 else if (aggregate->egp_origin_count > 0)
7804 origin = BGP_ORIGIN_EGP;
d62a17ae 7805
229757f1
DA
7806 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7807 origin = aggregate->origin;
7808
fc968841
NT
7809 if (aggregate->as_set) {
7810 if (aggregate->aspath)
7811 /* Retrieve aggregate route's as-path.
7812 */
7813 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7814
fc968841
NT
7815 if (aggregate->community)
7816 /* Retrieve aggregate route's community.
7817 */
7818 community = community_dup(aggregate->community);
3da2cc32 7819
fc968841
NT
7820 if (aggregate->ecommunity)
7821 /* Retrieve aggregate route's ecommunity.
7822 */
7823 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7824
fc968841
NT
7825 if (aggregate->lcommunity)
7826 /* Retrieve aggregate route's lcommunity.
7827 */
7828 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7829 }
718e3744 7830
c701010e 7831 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7832 ecommunity, lcommunity, atomic_aggregate,
7833 aggregate);
718e3744 7834}
7835
5f040085
DS
7836void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7837 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7838{
7839 struct bgp_table *table;
9bcb3eef
DS
7840 struct bgp_dest *top;
7841 struct bgp_dest *dest;
40381db7 7842 struct bgp_path_info *pi;
3b7db173
DS
7843 unsigned long match;
7844
7845 table = bgp->rib[afi][safi];
7846
7847 /* If routes exists below this node, generate aggregate routes. */
7848 top = bgp_node_get(table, p);
9bcb3eef
DS
7849 for (dest = bgp_node_get(table, p); dest;
7850 dest = bgp_route_next_until(dest, top)) {
7851 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7852
9bcb3eef 7853 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7854 continue;
7855 match = 0;
7856
9bcb3eef 7857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7858 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7859 continue;
7860
40381db7 7861 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7862 continue;
7863
92b175bd
RZ
7864 /*
7865 * This route is suppressed: attempt to unsuppress it.
7866 *
7867 * `aggr_unsuppress_path` will fail if this particular
7868 * aggregate route was not the suppressor.
7869 */
7870 if (pi->extra && pi->extra->aggr_suppressors &&
7871 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7872 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7873 match++;
3b7db173 7874 }
365ab2e7 7875
3b7db173 7876 aggregate->count--;
fc968841
NT
7877
7878 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7879 aggregate->incomplete_origin_count--;
7880 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7881 aggregate->egp_origin_count--;
7882
7883 if (aggregate->as_set) {
7884 /* Remove as-path from aggregate.
7885 */
ef51a7d8 7886 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7887 aggregate,
7888 pi->attr->aspath);
7889
9a706b42 7890 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7891 /* Remove community from aggregate.
7892 */
21fec674 7893 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7894 aggregate,
7895 bgp_attr_get_community(
7896 pi->attr));
fc968841 7897
b53e67a3 7898 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7899 /* Remove ecommunity from aggregate.
7900 */
4edd83f9 7901 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7902 aggregate,
7903 bgp_attr_get_ecommunity(
7904 pi->attr));
fc968841 7905
1bcf3a96 7906 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7907 /* Remove lcommunity from aggregate.
7908 */
f1eb1f05 7909 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7910 aggregate,
7911 bgp_attr_get_lcommunity(
7912 pi->attr));
fc968841 7913 }
3b7db173
DS
7914 }
7915
7916 /* If this node was suppressed, process the change. */
7917 if (match)
9bcb3eef 7918 bgp_process(bgp, dest, afi, safi);
3b7db173 7919 }
f1eb1f05 7920 if (aggregate->as_set) {
ef51a7d8 7921 aspath_free(aggregate->aspath);
7922 aggregate->aspath = NULL;
21fec674 7923 if (aggregate->community)
7924 community_free(&aggregate->community);
4edd83f9 7925 if (aggregate->ecommunity)
7926 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7927 if (aggregate->lcommunity)
7928 lcommunity_free(&aggregate->lcommunity);
7929 }
7930
9bcb3eef 7931 bgp_dest_unlock_node(top);
3b7db173 7932}
718e3744 7933
5f040085
DS
7934static void bgp_add_route_to_aggregate(struct bgp *bgp,
7935 const struct prefix *aggr_p,
fc968841
NT
7936 struct bgp_path_info *pinew, afi_t afi,
7937 safi_t safi,
7938 struct bgp_aggregate *aggregate)
7939{
7940 uint8_t origin;
7941 struct aspath *aspath = NULL;
7942 uint8_t atomic_aggregate = 0;
7943 struct community *community = NULL;
7944 struct ecommunity *ecommunity = NULL;
7945 struct lcommunity *lcommunity = NULL;
7946
a4559740 7947 /* If the bgp instance is being deleted or self peer is deleted
7948 * then do not create aggregate route
7949 */
7950 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7951 || (bgp->peer_self == NULL))
7952 return;
7953
fc968841
NT
7954 /* ORIGIN attribute: If at least one route among routes that are
7955 * aggregated has ORIGIN with the value INCOMPLETE, then the
7956 * aggregated route must have the ORIGIN attribute with the value
7957 * INCOMPLETE. Otherwise, if at least one route among routes that
7958 * are aggregated has ORIGIN with the value EGP, then the aggregated
7959 * route must have the origin attribute with the value EGP. In all
7960 * other case the value of the ORIGIN attribute of the aggregated
7961 * route is INTERNAL.
7962 */
7963 origin = BGP_ORIGIN_IGP;
7964
7965 aggregate->count++;
7966
6aabb15d
RZ
7967 /*
7968 * This must be called before `summary` check to avoid
7969 * "suppressing" twice.
7970 */
7971 if (aggregate->match_med)
7972 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 7973 pinew);
6aabb15d
RZ
7974
7975 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7976 aggr_suppress_path(aggregate, pinew);
fc968841 7977
365ab2e7
RZ
7978 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7979 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7980 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7981
7982 switch (pinew->attr->origin) {
7983 case BGP_ORIGIN_INCOMPLETE:
7984 aggregate->incomplete_origin_count++;
7985 break;
7986 case BGP_ORIGIN_EGP:
7987 aggregate->egp_origin_count++;
7988 break;
7989 default:
7990 /* Do nothing.
7991 */
7992 break;
7993 }
7994
7995 if (aggregate->incomplete_origin_count > 0)
7996 origin = BGP_ORIGIN_INCOMPLETE;
7997 else if (aggregate->egp_origin_count > 0)
7998 origin = BGP_ORIGIN_EGP;
7999
229757f1
DA
8000 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8001 origin = aggregate->origin;
8002
fc968841
NT
8003 if (aggregate->as_set) {
8004 /* Compute aggregate route's as-path.
8005 */
8006 bgp_compute_aggregate_aspath(aggregate,
8007 pinew->attr->aspath);
8008
8009 /* Compute aggregate route's community.
8010 */
9a706b42 8011 if (bgp_attr_get_community(pinew->attr))
fc968841 8012 bgp_compute_aggregate_community(
9a706b42 8013 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8014
8015 /* Compute aggregate route's extended community.
8016 */
b53e67a3 8017 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8018 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8019 aggregate,
8020 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8021
8022 /* Compute aggregate route's large community.
8023 */
1bcf3a96 8024 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8025 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8026 aggregate,
8027 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8028
8029 /* Retrieve aggregate route's as-path.
8030 */
8031 if (aggregate->aspath)
8032 aspath = aspath_dup(aggregate->aspath);
8033
8034 /* Retrieve aggregate route's community.
8035 */
8036 if (aggregate->community)
8037 community = community_dup(aggregate->community);
8038
8039 /* Retrieve aggregate route's ecommunity.
8040 */
8041 if (aggregate->ecommunity)
8042 ecommunity = ecommunity_dup(aggregate->ecommunity);
8043
8044 /* Retrieve aggregate route's lcommunity.
8045 */
8046 if (aggregate->lcommunity)
8047 lcommunity = lcommunity_dup(aggregate->lcommunity);
8048 }
8049
8050 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8051 aspath, community, ecommunity,
8052 lcommunity, atomic_aggregate, aggregate);
8053}
8054
8055static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8056 safi_t safi,
8057 struct bgp_path_info *pi,
8058 struct bgp_aggregate *aggregate,
5f040085 8059 const struct prefix *aggr_p)
fc968841
NT
8060{
8061 uint8_t origin;
8062 struct aspath *aspath = NULL;
8063 uint8_t atomic_aggregate = 0;
8064 struct community *community = NULL;
8065 struct ecommunity *ecommunity = NULL;
8066 struct lcommunity *lcommunity = NULL;
8067 unsigned long match = 0;
8068
a4559740 8069 /* If the bgp instance is being deleted or self peer is deleted
8070 * then do not create aggregate route
8071 */
8072 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8073 || (bgp->peer_self == NULL))
8074 return;
8075
fc968841
NT
8076 if (BGP_PATH_HOLDDOWN(pi))
8077 return;
8078
8079 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8080 return;
8081
4056a5f6
RZ
8082 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8083 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8084 match++;
fc968841 8085
365ab2e7 8086 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8087 && aggr_suppress_map_test(bgp, aggregate, pi))
8088 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8089 match++;
fc968841 8090
6aabb15d 8091 /*
365ab2e7 8092 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8093 * "unsuppressing" twice.
8094 */
8095 if (aggregate->match_med)
f66624f5 8096 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8097
fc968841
NT
8098 if (aggregate->count > 0)
8099 aggregate->count--;
8100
8101 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8102 aggregate->incomplete_origin_count--;
8103 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8104 aggregate->egp_origin_count--;
8105
8106 if (aggregate->as_set) {
8107 /* Remove as-path from aggregate.
8108 */
8109 bgp_remove_aspath_from_aggregate(aggregate,
8110 pi->attr->aspath);
8111
9a706b42 8112 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8113 /* Remove community from aggregate.
8114 */
8115 bgp_remove_community_from_aggregate(
9a706b42 8116 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8117
b53e67a3 8118 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8119 /* Remove ecommunity from aggregate.
8120 */
8121 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8122 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8123
1bcf3a96 8124 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8125 /* Remove lcommunity from aggregate.
8126 */
8127 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8128 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8129 }
8130
8131 /* If this node was suppressed, process the change. */
8132 if (match)
8133 bgp_process(bgp, pi->net, afi, safi);
8134
8135 origin = BGP_ORIGIN_IGP;
8136 if (aggregate->incomplete_origin_count > 0)
8137 origin = BGP_ORIGIN_INCOMPLETE;
8138 else if (aggregate->egp_origin_count > 0)
8139 origin = BGP_ORIGIN_EGP;
8140
229757f1
DA
8141 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8142 origin = aggregate->origin;
8143
fc968841
NT
8144 if (aggregate->as_set) {
8145 /* Retrieve aggregate route's as-path.
8146 */
8147 if (aggregate->aspath)
8148 aspath = aspath_dup(aggregate->aspath);
8149
8150 /* Retrieve aggregate route's community.
8151 */
8152 if (aggregate->community)
8153 community = community_dup(aggregate->community);
8154
8155 /* Retrieve aggregate route's ecommunity.
8156 */
8157 if (aggregate->ecommunity)
8158 ecommunity = ecommunity_dup(aggregate->ecommunity);
8159
8160 /* Retrieve aggregate route's lcommunity.
8161 */
8162 if (aggregate->lcommunity)
8163 lcommunity = lcommunity_dup(aggregate->lcommunity);
8164 }
8165
8166 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8167 aspath, community, ecommunity,
8168 lcommunity, atomic_aggregate, aggregate);
8169}
8170
5a1ae2c2 8171void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8172 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8173{
9bcb3eef
DS
8174 struct bgp_dest *child;
8175 struct bgp_dest *dest;
d62a17ae 8176 struct bgp_aggregate *aggregate;
8177 struct bgp_table *table;
718e3744 8178
d62a17ae 8179 table = bgp->aggregate[afi][safi];
f018db83 8180
d62a17ae 8181 /* No aggregates configured. */
8182 if (bgp_table_top_nolock(table) == NULL)
8183 return;
f018db83 8184
d62a17ae 8185 if (p->prefixlen == 0)
8186 return;
718e3744 8187
40381db7 8188 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8189 return;
718e3744 8190
a77e2f4b
S
8191 /* If suppress fib is enabled and route not installed
8192 * in FIB, do not update the aggregate route
8193 */
8194 if (!bgp_check_advertise(bgp, pi->net))
8195 return;
8196
d62a17ae 8197 child = bgp_node_get(table, p);
718e3744 8198
d62a17ae 8199 /* Aggregate address configuration check. */
9bcb3eef
DS
8200 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8201 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8202
9bcb3eef
DS
8203 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8204 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8205 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8206 aggregate);
d62a17ae 8207 }
b1e62edd 8208 }
9bcb3eef 8209 bgp_dest_unlock_node(child);
718e3744 8210}
8211
5a1ae2c2 8212void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8213 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8214{
9bcb3eef
DS
8215 struct bgp_dest *child;
8216 struct bgp_dest *dest;
d62a17ae 8217 struct bgp_aggregate *aggregate;
8218 struct bgp_table *table;
718e3744 8219
d62a17ae 8220 table = bgp->aggregate[afi][safi];
718e3744 8221
d62a17ae 8222 /* No aggregates configured. */
8223 if (bgp_table_top_nolock(table) == NULL)
8224 return;
718e3744 8225
d62a17ae 8226 if (p->prefixlen == 0)
8227 return;
718e3744 8228
d62a17ae 8229 child = bgp_node_get(table, p);
718e3744 8230
d62a17ae 8231 /* Aggregate address configuration check. */
9bcb3eef
DS
8232 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8233 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8234
9bcb3eef
DS
8235 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8236 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8237 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8238 aggregate, dest_p);
d62a17ae 8239 }
b1e62edd 8240 }
9bcb3eef 8241 bgp_dest_unlock_node(child);
d62a17ae 8242}
718e3744 8243
718e3744 8244/* Aggregate route attribute. */
8245#define AGGREGATE_SUMMARY_ONLY 1
8246#define AGGREGATE_AS_SET 1
fb29348a 8247#define AGGREGATE_AS_UNSET 0
718e3744 8248
229757f1
DA
8249static const char *bgp_origin2str(uint8_t origin)
8250{
8251 switch (origin) {
8252 case BGP_ORIGIN_IGP:
8253 return "igp";
8254 case BGP_ORIGIN_EGP:
8255 return "egp";
8256 case BGP_ORIGIN_INCOMPLETE:
8257 return "incomplete";
8258 }
8259 return "n/a";
8260}
8261
fdeb5a81 8262static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8263{
8264 switch (v_state) {
fdeb5a81
DS
8265 case RPKI_NOT_BEING_USED:
8266 return "not used";
8267 case RPKI_VALID:
b5b99af8 8268 return "valid";
fdeb5a81 8269 case RPKI_NOTFOUND:
b5b99af8 8270 return "not found";
fdeb5a81 8271 case RPKI_INVALID:
b5b99af8 8272 return "invalid";
b5b99af8 8273 }
fdeb5a81
DS
8274
8275 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8276 return "ERROR";
8277}
8278
585f1adc
IR
8279static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8280 afi_t afi, safi_t safi)
718e3744 8281{
585f1adc
IR
8282 VTY_DECLVAR_CONTEXT(bgp, bgp);
8283 int ret;
8284 struct prefix p;
9bcb3eef 8285 struct bgp_dest *dest;
d62a17ae 8286 struct bgp_aggregate *aggregate;
718e3744 8287
585f1adc
IR
8288 /* Convert string to prefix structure. */
8289 ret = str2prefix(prefix_str, &p);
8290 if (!ret) {
8291 vty_out(vty, "Malformed prefix\n");
8292 return CMD_WARNING_CONFIG_FAILED;
8293 }
8294 apply_mask(&p);
a4559740 8295
d62a17ae 8296 /* Old configuration check. */
585f1adc 8297 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8298 if (!dest) {
585f1adc
IR
8299 vty_out(vty,
8300 "%% There is no aggregate-address configuration.\n");
8301 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8302 }
f6269b4f 8303
9bcb3eef 8304 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8305 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8306 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8307 NULL, NULL, 0, aggregate);
d62a17ae 8308
8309 /* Unlock aggregate address configuration. */
9bcb3eef 8310 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8311
8312 if (aggregate->community)
8313 community_free(&aggregate->community);
8314
8315 if (aggregate->community_hash) {
8316 /* Delete all communities in the hash.
8317 */
8318 hash_clean(aggregate->community_hash,
8319 bgp_aggr_community_remove);
8320 /* Free up the community_hash.
8321 */
8322 hash_free(aggregate->community_hash);
8323 }
8324
8325 if (aggregate->ecommunity)
8326 ecommunity_free(&aggregate->ecommunity);
8327
8328 if (aggregate->ecommunity_hash) {
8329 /* Delete all ecommunities in the hash.
8330 */
8331 hash_clean(aggregate->ecommunity_hash,
8332 bgp_aggr_ecommunity_remove);
8333 /* Free up the ecommunity_hash.
8334 */
8335 hash_free(aggregate->ecommunity_hash);
8336 }
8337
8338 if (aggregate->lcommunity)
8339 lcommunity_free(&aggregate->lcommunity);
8340
8341 if (aggregate->lcommunity_hash) {
8342 /* Delete all lcommunities in the hash.
8343 */
8344 hash_clean(aggregate->lcommunity_hash,
8345 bgp_aggr_lcommunity_remove);
8346 /* Free up the lcommunity_hash.
8347 */
8348 hash_free(aggregate->lcommunity_hash);
8349 }
8350
8351 if (aggregate->aspath)
8352 aspath_free(aggregate->aspath);
8353
8354 if (aggregate->aspath_hash) {
8355 /* Delete all as-paths in the hash.
8356 */
8357 hash_clean(aggregate->aspath_hash,
8358 bgp_aggr_aspath_remove);
8359 /* Free up the aspath_hash.
8360 */
8361 hash_free(aggregate->aspath_hash);
8362 }
8363
d62a17ae 8364 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8365 bgp_dest_unlock_node(dest);
8366 bgp_dest_unlock_node(dest);
d62a17ae 8367
585f1adc 8368 return CMD_SUCCESS;
d62a17ae 8369}
8370
585f1adc
IR
8371static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8372 safi_t safi, const char *rmap,
8373 uint8_t summary_only, uint8_t as_set,
8374 uint8_t origin, bool match_med,
8375 const char *suppress_map)
d62a17ae 8376{
585f1adc 8377 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8378 int ret;
585f1adc 8379 struct prefix p;
9bcb3eef 8380 struct bgp_dest *dest;
d62a17ae 8381 struct bgp_aggregate *aggregate;
fb29348a 8382 uint8_t as_set_new = as_set;
d62a17ae 8383
365ab2e7 8384 if (suppress_map && summary_only) {
585f1adc 8385 vty_out(vty,
365ab2e7 8386 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8387 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8388 }
8389
585f1adc
IR
8390 /* Convert string to prefix structure. */
8391 ret = str2prefix(prefix_str, &p);
8392 if (!ret) {
8393 vty_out(vty, "Malformed prefix\n");
8394 return CMD_WARNING_CONFIG_FAILED;
8395 }
8396 apply_mask(&p);
d62a17ae 8397
585f1adc
IR
8398 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8399 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8400 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8401 prefix_str);
8402 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8403 }
8404
d62a17ae 8405 /* Old configuration check. */
585f1adc 8406 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8407 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8408
20894f50 8409 if (aggregate) {
585f1adc 8410 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8411 /* try to remove the old entry */
585f1adc 8412 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8413 if (ret) {
585f1adc 8414 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8415 bgp_dest_unlock_node(dest);
585f1adc 8416 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8417 }
8418 }
718e3744 8419
d62a17ae 8420 /* Make aggregate address structure. */
8421 aggregate = bgp_aggregate_new();
8422 aggregate->summary_only = summary_only;
6aabb15d 8423 aggregate->match_med = match_med;
fb29348a
DA
8424
8425 /* Network operators MUST NOT locally generate any new
8426 * announcements containing AS_SET or AS_CONFED_SET. If they have
8427 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8428 * SHOULD withdraw those routes and re-announce routes for the
8429 * aggregate or component prefixes (i.e., the more-specific routes
8430 * subsumed by the previously aggregated route) without AS_SET
8431 * or AS_CONFED_SET in the updates.
8432 */
7f972cd8 8433 if (bgp->reject_as_sets) {
fb29348a
DA
8434 if (as_set == AGGREGATE_AS_SET) {
8435 as_set_new = AGGREGATE_AS_UNSET;
8436 zlog_warn(
63efca0e 8437 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8438 __func__);
585f1adc 8439 vty_out(vty,
fb29348a
DA
8440 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8441 }
8442 }
8443
8444 aggregate->as_set = as_set_new;
d62a17ae 8445 aggregate->safi = safi;
229757f1
DA
8446 /* Override ORIGIN attribute if defined.
8447 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8448 * to IGP which is not what rfc4271 says.
8449 * This enables the same behavior, optionally.
8450 */
8451 aggregate->origin = origin;
20894f50
DA
8452
8453 if (rmap) {
8454 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8455 route_map_counter_decrement(aggregate->rmap.map);
8456 aggregate->rmap.name =
8457 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8458 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8459 route_map_counter_increment(aggregate->rmap.map);
8460 }
365ab2e7
RZ
8461
8462 if (suppress_map) {
8463 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8464 route_map_counter_decrement(aggregate->suppress_map);
8465
8466 aggregate->suppress_map_name =
8467 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8468 aggregate->suppress_map =
8469 route_map_lookup_by_name(aggregate->suppress_map_name);
8470 route_map_counter_increment(aggregate->suppress_map);
8471 }
8472
9bcb3eef 8473 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8474
d62a17ae 8475 /* Aggregate address insert into BGP routing table. */
585f1adc 8476 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8477
585f1adc 8478 return CMD_SUCCESS;
718e3744 8479}
8480
585f1adc
IR
8481DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8482 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8483 "as-set$as_set_s"
8484 "|summary-only$summary_only"
cacba915 8485 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8486 "|origin <egp|igp|incomplete>$origin_s"
8487 "|matching-MED-only$match_med"
cacba915 8488 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8489 "}]",
8490 NO_STR
8491 "Configure BGP aggregate entries\n"
764402fe
DA
8492 "Aggregate prefix\n"
8493 "Aggregate address\n"
8494 "Aggregate mask\n"
585f1adc
IR
8495 "Generate AS set path information\n"
8496 "Filter more specific routes from updates\n"
8497 "Apply route map to aggregate network\n"
8498 "Route map name\n"
8499 "BGP origin code\n"
8500 "Remote EGP\n"
8501 "Local IGP\n"
8502 "Unknown heritage\n"
8503 "Only aggregate routes with matching MED\n"
8504 "Suppress the selected more specific routes\n"
8505 "Route map with the route selectors\n")
8506{
8507 const char *prefix_s = NULL;
554b3b10 8508 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8509 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8510 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8511 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8512
554b3b10 8513 if (addr_str) {
7533cad7
QY
8514 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8515 sizeof(prefix_buf))
554b3b10
RZ
8516 == 0) {
8517 vty_out(vty, "%% Inconsistent address and mask\n");
8518 return CMD_WARNING_CONFIG_FAILED;
8519 }
585f1adc
IR
8520 prefix_s = prefix_buf;
8521 } else
8522 prefix_s = prefix_str;
37a87b8f 8523
585f1adc
IR
8524 if (origin_s) {
8525 if (strcmp(origin_s, "egp") == 0)
8526 origin = BGP_ORIGIN_EGP;
8527 else if (strcmp(origin_s, "igp") == 0)
8528 origin = BGP_ORIGIN_IGP;
8529 else if (strcmp(origin_s, "incomplete") == 0)
8530 origin = BGP_ORIGIN_INCOMPLETE;
8531 }
90e21f35 8532
585f1adc
IR
8533 if (as_set_s)
8534 as_set = AGGREGATE_AS_SET;
554b3b10 8535
585f1adc 8536 /* Handle configuration removal, otherwise installation. */
554b3b10 8537 if (no)
585f1adc
IR
8538 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8539
8540 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8541 summary_only != NULL, as_set, origin,
8542 match_med != NULL, suppress_map);
8543}
8544
8545DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8546 "[no] aggregate-address X:X::X:X/M$prefix [{"
8547 "as-set$as_set_s"
8548 "|summary-only$summary_only"
cacba915 8549 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8550 "|origin <egp|igp|incomplete>$origin_s"
8551 "|matching-MED-only$match_med"
cacba915 8552 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8553 "}]",
8554 NO_STR
8555 "Configure BGP aggregate entries\n"
8556 "Aggregate prefix\n"
8557 "Generate AS set path information\n"
8558 "Filter more specific routes from updates\n"
8559 "Apply route map to aggregate network\n"
8560 "Route map name\n"
8561 "BGP origin code\n"
8562 "Remote EGP\n"
8563 "Local IGP\n"
8564 "Unknown heritage\n"
8565 "Only aggregate routes with matching MED\n"
8566 "Suppress the selected more specific routes\n"
8567 "Route map with the route selectors\n")
8568{
8569 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8570 int as_set = AGGREGATE_AS_UNSET;
8571
8572 if (origin_s) {
8573 if (strcmp(origin_s, "egp") == 0)
8574 origin = BGP_ORIGIN_EGP;
8575 else if (strcmp(origin_s, "igp") == 0)
8576 origin = BGP_ORIGIN_IGP;
8577 else if (strcmp(origin_s, "incomplete") == 0)
8578 origin = BGP_ORIGIN_INCOMPLETE;
8579 }
8580
8581 if (as_set_s)
8582 as_set = AGGREGATE_AS_SET;
8583
8584 /* Handle configuration removal, otherwise installation. */
554b3b10 8585 if (no)
585f1adc
IR
8586 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8587 SAFI_UNICAST);
554b3b10 8588
585f1adc
IR
8589 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8590 rmap_name, summary_only != NULL, as_set,
8591 origin, match_med != NULL, suppress_map);
718e3744 8592}
8593
718e3744 8594/* Redistribute route treatment. */
d62a17ae 8595void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8596 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8597 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8598 enum blackhole_type bhtype, uint32_t metric,
8599 uint8_t type, unsigned short instance,
8600 route_tag_t tag)
d62a17ae 8601{
4b7e6066 8602 struct bgp_path_info *new;
40381db7
DS
8603 struct bgp_path_info *bpi;
8604 struct bgp_path_info rmap_path;
9bcb3eef 8605 struct bgp_dest *bn;
d62a17ae 8606 struct attr attr;
8607 struct attr *new_attr;
8608 afi_t afi;
b68885f9 8609 route_map_result_t ret;
d62a17ae 8610 struct bgp_redist *red;
8611
8612 /* Make default attribute. */
0f05ea43 8613 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8614 /*
8615 * This must not be NULL to satisfy Coverity SA
8616 */
8617 assert(attr.aspath);
9de1f7ff 8618
a4d82a8a 8619 switch (nhtype) {
9de1f7ff 8620 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8621 switch (p->family) {
8622 case AF_INET:
8623 attr.nexthop.s_addr = INADDR_ANY;
8624 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8625 break;
8626 case AF_INET6:
8627 memset(&attr.mp_nexthop_global, 0,
8628 sizeof(attr.mp_nexthop_global));
8629 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8630 break;
8631 }
9de1f7ff
DS
8632 break;
8633 case NEXTHOP_TYPE_IPV4:
8634 case NEXTHOP_TYPE_IPV4_IFINDEX:
8635 attr.nexthop = nexthop->ipv4;
7226bc40 8636 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8637 break;
8638 case NEXTHOP_TYPE_IPV6:
8639 case NEXTHOP_TYPE_IPV6_IFINDEX:
8640 attr.mp_nexthop_global = nexthop->ipv6;
8641 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8642 break;
8643 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8644 switch (p->family) {
8645 case AF_INET:
9de1f7ff 8646 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8647 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8648 break;
8649 case AF_INET6:
9de1f7ff
DS
8650 memset(&attr.mp_nexthop_global, 0,
8651 sizeof(attr.mp_nexthop_global));
74489921 8652 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8653 break;
74489921 8654 }
0789eb69 8655 attr.bh_type = bhtype;
9de1f7ff 8656 break;
d62a17ae 8657 }
0789eb69 8658 attr.nh_type = nhtype;
74489921 8659 attr.nh_ifindex = ifindex;
f04a80a5 8660
d62a17ae 8661 attr.med = metric;
957f74c3 8662 attr.distance = distance;
d62a17ae 8663 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8664 attr.tag = tag;
718e3744 8665
97a52c82
DA
8666 if (metric)
8667 bgp_attr_set_aigp_metric(&attr, metric);
8668
d62a17ae 8669 afi = family2afi(p->family);
6aeb9e78 8670
d62a17ae 8671 red = bgp_redist_lookup(bgp, afi, type, instance);
8672 if (red) {
8673 struct attr attr_new;
718e3744 8674
d62a17ae 8675 /* Copy attribute for modification. */
6f4f49b2 8676 attr_new = attr;
718e3744 8677
97a52c82 8678 if (red->redist_metric_flag) {
d62a17ae 8679 attr_new.med = red->redist_metric;
97a52c82
DA
8680 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8681 }
718e3744 8682
d62a17ae 8683 /* Apply route-map. */
8684 if (red->rmap.name) {
6006b807 8685 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8686 rmap_path.peer = bgp->peer_self;
8687 rmap_path.attr = &attr_new;
718e3744 8688
d62a17ae 8689 SET_FLAG(bgp->peer_self->rmap_type,
8690 PEER_RMAP_TYPE_REDISTRIBUTE);
8691
1782514f 8692 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8693
8694 bgp->peer_self->rmap_type = 0;
8695
8696 if (ret == RMAP_DENYMATCH) {
8697 /* Free uninterned attribute. */
8698 bgp_attr_flush(&attr_new);
8699
8700 /* Unintern original. */
8701 aspath_unintern(&attr.aspath);
8702 bgp_redistribute_delete(bgp, p, type, instance);
8703 return;
8704 }
8705 }
8706
637e5ba4 8707 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8708 bgp_attr_add_gshut_community(&attr_new);
8709
d62a17ae 8710 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8711 SAFI_UNICAST, p, NULL);
8712
8713 new_attr = bgp_attr_intern(&attr_new);
8714
9bcb3eef 8715 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8716 if (bpi->peer == bgp->peer_self
8717 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8718 break;
8719
40381db7 8720 if (bpi) {
d62a17ae 8721 /* Ensure the (source route) type is updated. */
40381db7
DS
8722 bpi->type = type;
8723 if (attrhash_cmp(bpi->attr, new_attr)
8724 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8725 bgp_attr_unintern(&new_attr);
8726 aspath_unintern(&attr.aspath);
9bcb3eef 8727 bgp_dest_unlock_node(bn);
d62a17ae 8728 return;
8729 } else {
8730 /* The attribute is changed. */
40381db7 8731 bgp_path_info_set_flag(bn, bpi,
18ee8310 8732 BGP_PATH_ATTR_CHANGED);
d62a17ae 8733
8734 /* Rewrite BGP route information. */
40381db7
DS
8735 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8736 bgp_path_info_restore(bn, bpi);
d62a17ae 8737 else
40381db7
DS
8738 bgp_aggregate_decrement(
8739 bgp, p, bpi, afi, SAFI_UNICAST);
8740 bgp_attr_unintern(&bpi->attr);
8741 bpi->attr = new_attr;
083ec940 8742 bpi->uptime = monotime(NULL);
d62a17ae 8743
8744 /* Process change. */
40381db7 8745 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8746 SAFI_UNICAST);
8747 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8748 bgp_dest_unlock_node(bn);
d62a17ae 8749 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8750
8751 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8752 || (bgp->inst_type
8753 == BGP_INSTANCE_TYPE_DEFAULT)) {
8754
8755 vpn_leak_from_vrf_update(
40381db7 8756 bgp_get_default(), bgp, bpi);
ddb5b488 8757 }
d62a17ae 8758 return;
8759 }
8760 }
8761
8762 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8763 bgp->peer_self, new_attr, bn);
1defdda8 8764 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8765
8766 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8767 bgp_path_info_add(bn, new);
9bcb3eef 8768 bgp_dest_unlock_node(bn);
be785e35 8769 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8770 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8771
8772 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8773 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8774
8775 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8776 }
d62a17ae 8777 }
8778
8779 /* Unintern original. */
8780 aspath_unintern(&attr.aspath);
718e3744 8781}
8782
d7c0a89a
QY
8783void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8784 unsigned short instance)
718e3744 8785{
d62a17ae 8786 afi_t afi;
9bcb3eef 8787 struct bgp_dest *dest;
40381db7 8788 struct bgp_path_info *pi;
d62a17ae 8789 struct bgp_redist *red;
718e3744 8790
d62a17ae 8791 afi = family2afi(p->family);
718e3744 8792
d62a17ae 8793 red = bgp_redist_lookup(bgp, afi, type, instance);
8794 if (red) {
9bcb3eef
DS
8795 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8796 SAFI_UNICAST, p, NULL);
d62a17ae 8797
9bcb3eef 8798 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8799 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8800 break;
8801
40381db7 8802 if (pi) {
ddb5b488
PZ
8803 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8804 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8805
8806 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8807 bgp, pi);
ddb5b488 8808 }
40381db7 8809 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8810 bgp_path_info_delete(dest, pi);
8811 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8812 }
9bcb3eef 8813 bgp_dest_unlock_node(dest);
d62a17ae 8814 }
8815}
8816
8817/* Withdraw specified route type's route. */
8818void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8819 unsigned short instance)
d62a17ae 8820{
9bcb3eef 8821 struct bgp_dest *dest;
40381db7 8822 struct bgp_path_info *pi;
d62a17ae 8823 struct bgp_table *table;
8824
8825 table = bgp->rib[afi][SAFI_UNICAST];
8826
9bcb3eef
DS
8827 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8828 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8829 if (pi->peer == bgp->peer_self && pi->type == type
8830 && pi->instance == instance)
d62a17ae 8831 break;
8832
40381db7 8833 if (pi) {
ddb5b488
PZ
8834 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8835 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8836
8837 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8838 bgp, pi);
ddb5b488 8839 }
9bcb3eef 8840 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8841 pi, afi, SAFI_UNICAST);
9bcb3eef 8842 bgp_path_info_delete(dest, pi);
f9d6087c
DS
8843 if (!CHECK_FLAG(bgp->flags,
8844 BGP_FLAG_DELETE_IN_PROGRESS))
8845 bgp_process(bgp, dest, afi, SAFI_UNICAST);
8846 else
8847 bgp_path_info_reap(dest, pi);
d62a17ae 8848 }
718e3744 8849 }
718e3744 8850}
6b0655a2 8851
718e3744 8852/* Static function to display route. */
7d3cae70
DA
8853static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8854 struct vty *vty, json_object *json, bool wide)
718e3744 8855{
be054588 8856 int len = 0;
07380148 8857 char buf[INET6_ADDRSTRLEN];
718e3744 8858
d62a17ae 8859 if (p->family == AF_INET) {
c6462ff4 8860 if (!json) {
8228a9a7 8861 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8862 } else {
8863 json_object_string_add(json, "prefix",
8864 inet_ntop(p->family,
8865 &p->u.prefix, buf,
07380148 8866 sizeof(buf)));
c6462ff4 8867 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8868 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8869 json_object_int_add(json, "version", dest->version);
c6462ff4 8870 }
d62a17ae 8871 } else if (p->family == AF_ETHERNET) {
8228a9a7 8872 len = vty_out(vty, "%pFX", p);
b03b8898 8873 } else if (p->family == AF_EVPN) {
57f7feb6 8874 if (!json)
2dbe669b 8875 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8876 else
60466a63 8877 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8878 } else if (p->family == AF_FLOWSPEC) {
8879 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8880 json ?
8881 NLRI_STRING_FORMAT_JSON_SIMPLE :
8882 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8883 } else {
c6462ff4 8884 if (!json)
8228a9a7 8885 len = vty_out(vty, "%pFX", p);
50e05855
AD
8886 else {
8887 json_object_string_add(json, "prefix",
07380148
DA
8888 inet_ntop(p->family,
8889 &p->u.prefix, buf,
8890 sizeof(buf)));
50e05855 8891 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8892 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8893 json_object_int_add(json, "version", dest->version);
37d4e0df 8894 }
9c92b5f7 8895 }
d62a17ae 8896
9c92b5f7 8897 if (!json) {
ae248832 8898 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8899 if (len < 1)
8900 vty_out(vty, "\n%*s", 20, " ");
8901 else
8902 vty_out(vty, "%*s", len, " ");
8903 }
718e3744 8904}
8905
d62a17ae 8906enum bgp_display_type {
8907 normal_list,
718e3744 8908};
8909
1d7260a1 8910const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8911{
8912 switch (reason) {
8913 case bgp_path_selection_none:
8914 return "Nothing to Select";
8915 case bgp_path_selection_first:
8916 return "First path received";
8917 case bgp_path_selection_evpn_sticky_mac:
8918 return "EVPN Sticky Mac";
8919 case bgp_path_selection_evpn_seq:
8920 return "EVPN sequence number";
8921 case bgp_path_selection_evpn_lower_ip:
8922 return "EVPN lower IP";
8923 case bgp_path_selection_evpn_local_path:
8924 return "EVPN local ES path";
8925 case bgp_path_selection_evpn_non_proxy:
8926 return "EVPN non proxy";
8927 case bgp_path_selection_weight:
8928 return "Weight";
8929 case bgp_path_selection_local_pref:
8930 return "Local Pref";
46dbf9d0
DA
8931 case bgp_path_selection_accept_own:
8932 return "Accept Own";
bbb46eb5
DA
8933 case bgp_path_selection_local_route:
8934 return "Local Route";
97a52c82
DA
8935 case bgp_path_selection_aigp:
8936 return "AIGP";
bbb46eb5
DA
8937 case bgp_path_selection_confed_as_path:
8938 return "Confederation based AS Path";
8939 case bgp_path_selection_as_path:
8940 return "AS Path";
8941 case bgp_path_selection_origin:
8942 return "Origin";
8943 case bgp_path_selection_med:
8944 return "MED";
8945 case bgp_path_selection_peer:
8946 return "Peer Type";
8947 case bgp_path_selection_confed:
8948 return "Confed Peer Type";
8949 case bgp_path_selection_igp_metric:
8950 return "IGP Metric";
8951 case bgp_path_selection_older:
8952 return "Older Path";
8953 case bgp_path_selection_router_id:
8954 return "Router ID";
8955 case bgp_path_selection_cluster_length:
bcab253c 8956 return "Cluster length";
bbb46eb5
DA
8957 case bgp_path_selection_stale:
8958 return "Path Staleness";
8959 case bgp_path_selection_local_configured:
8960 return "Locally configured route";
8961 case bgp_path_selection_neighbor_ip:
8962 return "Neighbor IP";
8963 case bgp_path_selection_default:
8964 return "Nothing left to compare";
8965 }
8966 return "Invalid (internal error)";
8967}
8968
18ee8310 8969/* Print the short form route status for a bgp_path_info */
4b7e6066 8970static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8971 struct bgp_path_info *path,
82c298be 8972 const struct prefix *p,
d62a17ae 8973 json_object *json_path)
718e3744 8974{
82c298be
DA
8975 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8976
d62a17ae 8977 if (json_path) {
b05a1c8b 8978
d62a17ae 8979 /* Route status display. */
9b6d8fcf 8980 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8981 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8982
9b6d8fcf 8983 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8984 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8985
4056a5f6 8986 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8987 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8988
9b6d8fcf
DS
8989 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8990 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8991 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8992
d62a17ae 8993 /* Selected */
9b6d8fcf 8994 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8995 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8996
9b6d8fcf 8997 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8998 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8999
bbb46eb5 9000 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9001 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9002 json_object_string_add(json_path, "selectionReason",
9003 bgp_path_selection_reason2str(
9004 path->net->reason));
9005 }
b05a1c8b 9006
9b6d8fcf 9007 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9008 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9009
d62a17ae 9010 /* Internal route. */
9b6d8fcf
DS
9011 if ((path->peer->as)
9012 && (path->peer->as == path->peer->local_as))
d62a17ae 9013 json_object_string_add(json_path, "pathFrom",
9014 "internal");
9015 else
9016 json_object_string_add(json_path, "pathFrom",
9017 "external");
b05a1c8b 9018
d62a17ae 9019 return;
9020 }
b05a1c8b 9021
82c298be
DA
9022 /* RPKI validation state */
9023 rpki_state =
9024 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9025
9026 if (rpki_state == RPKI_VALID)
9027 vty_out(vty, "V");
9028 else if (rpki_state == RPKI_INVALID)
9029 vty_out(vty, "I");
9030 else if (rpki_state == RPKI_NOTFOUND)
9031 vty_out(vty, "N");
eaeba5e8
WM
9032 else
9033 vty_out(vty, " ");
82c298be 9034
d62a17ae 9035 /* Route status display. */
9b6d8fcf 9036 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9037 vty_out(vty, "R");
9b6d8fcf 9038 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9039 vty_out(vty, "S");
4056a5f6 9040 else if (bgp_path_suppressed(path))
d62a17ae 9041 vty_out(vty, "s");
9b6d8fcf
DS
9042 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9043 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9044 vty_out(vty, "*");
9045 else
9046 vty_out(vty, " ");
9047
9048 /* Selected */
9b6d8fcf 9049 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9050 vty_out(vty, "h");
9b6d8fcf 9051 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9052 vty_out(vty, "d");
9b6d8fcf 9053 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9054 vty_out(vty, ">");
9b6d8fcf 9055 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9056 vty_out(vty, "=");
9057 else
9058 vty_out(vty, " ");
718e3744 9059
d62a17ae 9060 /* Internal route. */
9b6d8fcf
DS
9061 if (path->peer && (path->peer->as)
9062 && (path->peer->as == path->peer->local_as))
d62a17ae 9063 vty_out(vty, "i");
9064 else
9065 vty_out(vty, " ");
b40d939b 9066}
9067
2ba93fd6
DA
9068static char *bgp_nexthop_hostname(struct peer *peer,
9069 struct bgp_nexthop_cache *bnc)
25b5da8d 9070{
892fedb6 9071 if (peer->hostname
aef999a2 9072 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9073 return peer->hostname;
9074 return NULL;
9075}
9076
b40d939b 9077/* called from terminal list command */
bd494ec5 9078void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9079 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9080 json_object *json_paths, bool wide)
d62a17ae 9081{
aef999a2 9082 int len;
515c2602 9083 struct attr *attr = path->attr;
d62a17ae 9084 json_object *json_path = NULL;
9085 json_object *json_nexthops = NULL;
9086 json_object *json_nexthop_global = NULL;
9087 json_object *json_nexthop_ll = NULL;
6f214dd3 9088 json_object *json_ext_community = NULL;
9df8b37c 9089 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9090 bool nexthop_self =
9b6d8fcf 9091 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9092 bool nexthop_othervrf = false;
43089216 9093 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9094 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9095 char *nexthop_hostname =
9096 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9097 char esi_buf[ESI_STR_LEN];
d62a17ae 9098
9099 if (json_paths)
9100 json_path = json_object_new_object();
9101
9102 /* short status lead text */
82c298be 9103 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9104
9105 if (!json_paths) {
9106 /* print prefix and mask */
9107 if (!display)
7d3cae70 9108 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9109 else
ae248832 9110 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9111 } else {
7d3cae70 9112 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9113 }
47fc97cc 9114
9df8b37c
PZ
9115 /*
9116 * If vrf id of nexthop is different from that of prefix,
9117 * set up printable string to append
9118 */
9b6d8fcf 9119 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9120 const char *self = "";
9121
9122 if (nexthop_self)
9123 self = "<";
9124
9125 nexthop_othervrf = true;
9b6d8fcf 9126 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9127
9b6d8fcf 9128 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9129 snprintf(vrf_id_str, sizeof(vrf_id_str),
9130 "@%s%s", VRFID_NONE_STR, self);
9131 else
9132 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9133 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9134
9b6d8fcf
DS
9135 if (path->extra->bgp_orig->inst_type
9136 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9137
9b6d8fcf 9138 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9139 } else {
9140 const char *self = "";
9141
9142 if (nexthop_self)
9143 self = "<";
9144
9145 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9146 }
9147
445c2480
DS
9148 /*
9149 * For ENCAP and EVPN routes, nexthop address family is not
9150 * neccessarily the same as the prefix address family.
9151 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9152 * EVPN routes are also exchanged with a MP nexthop. Currently,
9153 * this
9154 * is only IPv4, the value will be present in either
9155 * attr->nexthop or
9156 * attr->mp_nexthop_global_in
9157 */
9158 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9159 char nexthop[128];
9160 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9161
9162 switch (af) {
9163 case AF_INET:
07380148
DA
9164 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9165 &attr->mp_nexthop_global_in);
445c2480
DS
9166 break;
9167 case AF_INET6:
07380148
DA
9168 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9169 &attr->mp_nexthop_global);
445c2480
DS
9170 break;
9171 default:
772270f3 9172 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9173 break;
d62a17ae 9174 }
d62a17ae 9175
445c2480
DS
9176 if (json_paths) {
9177 json_nexthop_global = json_object_new_object();
9178
515c2602
DA
9179 json_object_string_add(json_nexthop_global, "ip",
9180 nexthop);
9181
939a97f4 9182 if (path->peer->hostname)
515c2602
DA
9183 json_object_string_add(json_nexthop_global,
9184 "hostname",
939a97f4 9185 path->peer->hostname);
515c2602
DA
9186
9187 json_object_string_add(json_nexthop_global, "afi",
9188 (af == AF_INET) ? "ipv4"
9189 : "ipv6");
445c2480
DS
9190 json_object_boolean_true_add(json_nexthop_global,
9191 "used");
aef999a2
DA
9192 } else {
9193 if (nexthop_hostname)
9194 len = vty_out(vty, "%s(%s)%s", nexthop,
9195 nexthop_hostname, vrf_id_str);
9196 else
9197 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9198
ae248832 9199 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9200 if (len < 1)
9201 vty_out(vty, "\n%*s", 36, " ");
9202 else
9203 vty_out(vty, "%*s", len, " ");
9204 }
445c2480
DS
9205 } else if (safi == SAFI_EVPN) {
9206 if (json_paths) {
9207 json_nexthop_global = json_object_new_object();
9208
c949c771 9209 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9210 "%pI4",
9211 &attr->mp_nexthop_global_in);
515c2602 9212
939a97f4 9213 if (path->peer->hostname)
515c2602
DA
9214 json_object_string_add(json_nexthop_global,
9215 "hostname",
939a97f4 9216 path->peer->hostname);
515c2602 9217
a4d82a8a
PZ
9218 json_object_string_add(json_nexthop_global, "afi",
9219 "ipv4");
445c2480
DS
9220 json_object_boolean_true_add(json_nexthop_global,
9221 "used");
aef999a2
DA
9222 } else {
9223 if (nexthop_hostname)
7226bc40
TA
9224 len = vty_out(vty, "%pI4(%s)%s",
9225 &attr->mp_nexthop_global_in,
aef999a2
DA
9226 nexthop_hostname, vrf_id_str);
9227 else
7226bc40
TA
9228 len = vty_out(vty, "%pI4%s",
9229 &attr->mp_nexthop_global_in,
aef999a2
DA
9230 vrf_id_str);
9231
ae248832 9232 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9233 if (len < 1)
9234 vty_out(vty, "\n%*s", 36, " ");
9235 else
9236 vty_out(vty, "%*s", len, " ");
9237 }
d33fc23b 9238 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9239 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9240 if (json_paths) {
9241 json_nexthop_global = json_object_new_object();
515c2602 9242
026b914a
PG
9243 json_object_string_add(json_nexthop_global,
9244 "afi", "ipv4");
c949c771
DA
9245 json_object_string_addf(json_nexthop_global,
9246 "ip", "%pI4",
9247 &attr->nexthop);
515c2602 9248
939a97f4 9249 if (path->peer->hostname)
515c2602
DA
9250 json_object_string_add(
9251 json_nexthop_global, "hostname",
939a97f4 9252 path->peer->hostname);
515c2602 9253
50e05855
AD
9254 json_object_boolean_true_add(
9255 json_nexthop_global,
026b914a
PG
9256 "used");
9257 } else {
aef999a2
DA
9258 if (nexthop_hostname)
9259 len = vty_out(vty, "%pI4(%s)%s",
9260 &attr->nexthop,
9261 nexthop_hostname,
9262 vrf_id_str);
9263 else
9264 len = vty_out(vty, "%pI4%s",
9265 &attr->nexthop,
9266 vrf_id_str);
9267
ae248832 9268 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9269 if (len < 1)
9270 vty_out(vty, "\n%*s", 36, " ");
9271 else
9272 vty_out(vty, "%*s", len, " ");
026b914a
PG
9273 }
9274 }
7226bc40 9275 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9276 if (json_paths) {
9277 json_nexthop_global = json_object_new_object();
d62a17ae 9278
c949c771
DA
9279 json_object_string_addf(json_nexthop_global, "ip",
9280 "%pI4", &attr->nexthop);
515c2602 9281
939a97f4 9282 if (path->peer->hostname)
515c2602
DA
9283 json_object_string_add(json_nexthop_global,
9284 "hostname",
939a97f4 9285 path->peer->hostname);
445c2480 9286
a4d82a8a
PZ
9287 json_object_string_add(json_nexthop_global, "afi",
9288 "ipv4");
445c2480
DS
9289 json_object_boolean_true_add(json_nexthop_global,
9290 "used");
9291 } else {
aef999a2
DA
9292 if (nexthop_hostname)
9293 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9294 nexthop_hostname, vrf_id_str);
9295 else
9296 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9297 vrf_id_str);
9df8b37c 9298
ae248832 9299 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9300 if (len < 1)
9301 vty_out(vty, "\n%*s", 36, " ");
9302 else
9303 vty_out(vty, "%*s", len, " ");
d62a17ae 9304 }
445c2480 9305 }
b05a1c8b 9306
445c2480 9307 /* IPv6 Next Hop */
7226bc40 9308 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9309 if (json_paths) {
9310 json_nexthop_global = json_object_new_object();
c949c771
DA
9311 json_object_string_addf(json_nexthop_global, "ip",
9312 "%pI6",
9313 &attr->mp_nexthop_global);
515c2602 9314
939a97f4 9315 if (path->peer->hostname)
515c2602
DA
9316 json_object_string_add(json_nexthop_global,
9317 "hostname",
939a97f4 9318 path->peer->hostname);
515c2602 9319
a4d82a8a
PZ
9320 json_object_string_add(json_nexthop_global, "afi",
9321 "ipv6");
9322 json_object_string_add(json_nexthop_global, "scope",
9323 "global");
445c2480
DS
9324
9325 /* We display both LL & GL if both have been
9326 * received */
0606039c
DA
9327 if ((attr->mp_nexthop_len
9328 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9329 || (path->peer->conf_if)) {
a4d82a8a 9330 json_nexthop_ll = json_object_new_object();
c949c771
DA
9331 json_object_string_addf(
9332 json_nexthop_ll, "ip", "%pI6",
9333 &attr->mp_nexthop_local);
515c2602 9334
939a97f4 9335 if (path->peer->hostname)
515c2602
DA
9336 json_object_string_add(
9337 json_nexthop_ll, "hostname",
939a97f4 9338 path->peer->hostname);
515c2602 9339
a4d82a8a
PZ
9340 json_object_string_add(json_nexthop_ll, "afi",
9341 "ipv6");
9342 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9343 "link-local");
d62a17ae 9344
a4d82a8a 9345 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
2bb8b49c
DS
9346 &attr->mp_nexthop_local)
9347 != 0)
9348 && !attr->mp_nexthop_prefer_global)
d62a17ae 9349 json_object_boolean_true_add(
a4d82a8a 9350 json_nexthop_ll, "used");
445c2480
DS
9351 else
9352 json_object_boolean_true_add(
a4d82a8a 9353 json_nexthop_global, "used");
445c2480
DS
9354 } else
9355 json_object_boolean_true_add(
9356 json_nexthop_global, "used");
9357 } else {
9358 /* Display LL if LL/Global both in table unless
9359 * prefer-global is set */
2bb8b49c
DS
9360 if (((attr->mp_nexthop_len
9361 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9362 && !attr->mp_nexthop_prefer_global)
9363 || (path->peer->conf_if)) {
9b6d8fcf 9364 if (path->peer->conf_if) {
a4d82a8a 9365 len = vty_out(vty, "%s",
9b6d8fcf 9366 path->peer->conf_if);
ae248832
MK
9367 /* len of IPv6 addr + max len of def
9368 * ifname */
9369 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9370
9371 if (len < 1)
a4d82a8a 9372 vty_out(vty, "\n%*s", 36, " ");
445c2480 9373 else
a4d82a8a 9374 vty_out(vty, "%*s", len, " ");
d62a17ae 9375 } else {
aef999a2
DA
9376 if (nexthop_hostname)
9377 len = vty_out(
9378 vty, "%pI6(%s)%s",
9379 &attr->mp_nexthop_local,
9380 nexthop_hostname,
9381 vrf_id_str);
9382 else
9383 len = vty_out(
9384 vty, "%pI6%s",
9385 &attr->mp_nexthop_local,
9386 vrf_id_str);
9387
ae248832 9388 len = wide ? (41 - len) : (16 - len);
d62a17ae 9389
9390 if (len < 1)
a4d82a8a 9391 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9392 else
a4d82a8a 9393 vty_out(vty, "%*s", len, " ");
d62a17ae 9394 }
445c2480 9395 } else {
aef999a2
DA
9396 if (nexthop_hostname)
9397 len = vty_out(vty, "%pI6(%s)%s",
9398 &attr->mp_nexthop_global,
9399 nexthop_hostname,
9400 vrf_id_str);
9401 else
9402 len = vty_out(vty, "%pI6%s",
9403 &attr->mp_nexthop_global,
9404 vrf_id_str);
9405
ae248832 9406 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9407
9408 if (len < 1)
9409 vty_out(vty, "\n%*s", 36, " ");
9410 else
9411 vty_out(vty, "%*s", len, " ");
d62a17ae 9412 }
9413 }
445c2480 9414 }
718e3744 9415
445c2480
DS
9416 /* MED/Metric */
9417 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9418 if (json_paths)
50e05855 9419 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9420 else if (wide)
9421 vty_out(vty, "%7u", attr->med);
0fbac0b4 9422 else
445c2480 9423 vty_out(vty, "%10u", attr->med);
ae248832
MK
9424 else if (!json_paths) {
9425 if (wide)
9426 vty_out(vty, "%*s", 7, " ");
9427 else
9428 vty_out(vty, "%*s", 10, " ");
9429 }
d62a17ae 9430
445c2480
DS
9431 /* Local Pref */
9432 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9433 if (json_paths)
50e05855 9434 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9435 attr->local_pref);
9436 else
445c2480
DS
9437 vty_out(vty, "%7u", attr->local_pref);
9438 else if (!json_paths)
9439 vty_out(vty, " ");
d62a17ae 9440
445c2480
DS
9441 if (json_paths)
9442 json_object_int_add(json_path, "weight", attr->weight);
9443 else
9444 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9445
47e12884
DA
9446 if (json_paths)
9447 json_object_string_addf(json_path, "peerId", "%pSU",
9448 &path->peer->su);
b05a1c8b 9449
445c2480
DS
9450 /* Print aspath */
9451 if (attr->aspath) {
0fbac0b4 9452 if (json_paths)
50e05855 9453 json_object_string_add(json_path, "path",
0fbac0b4
DA
9454 attr->aspath->str);
9455 else
445c2480 9456 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9457 }
f1aa5d8a 9458
445c2480
DS
9459 /* Print origin */
9460 if (json_paths)
a4d82a8a
PZ
9461 json_object_string_add(json_path, "origin",
9462 bgp_origin_long_str[attr->origin]);
445c2480
DS
9463 else
9464 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9465
9df8b37c 9466 if (json_paths) {
d071f237 9467 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9468 json_object_string_add(json_path, "esi",
9469 esi_to_str(&attr->esi,
9470 esi_buf, sizeof(esi_buf)));
9471 }
6f214dd3
CS
9472 if (safi == SAFI_EVPN &&
9473 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9474 json_ext_community = json_object_new_object();
b53e67a3
DA
9475 json_object_string_add(
9476 json_ext_community, "string",
9477 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9478 json_object_object_add(json_path,
9479 "extendedCommunity",
9480 json_ext_community);
9481 }
9482
9df8b37c
PZ
9483 if (nexthop_self)
9484 json_object_boolean_true_add(json_path,
9485 "announceNexthopSelf");
9486 if (nexthop_othervrf) {
9487 json_object_string_add(json_path, "nhVrfName",
9488 nexthop_vrfname);
9489
9490 json_object_int_add(json_path, "nhVrfId",
9491 ((nexthop_vrfid == VRF_UNKNOWN)
9492 ? -1
9493 : (int)nexthop_vrfid));
9494 }
9495 }
9496
d62a17ae 9497 if (json_paths) {
9498 if (json_nexthop_global || json_nexthop_ll) {
9499 json_nexthops = json_object_new_array();
f1aa5d8a 9500
d62a17ae 9501 if (json_nexthop_global)
9502 json_object_array_add(json_nexthops,
9503 json_nexthop_global);
f1aa5d8a 9504
d62a17ae 9505 if (json_nexthop_ll)
9506 json_object_array_add(json_nexthops,
9507 json_nexthop_ll);
f1aa5d8a 9508
d62a17ae 9509 json_object_object_add(json_path, "nexthops",
9510 json_nexthops);
9511 }
9512
9513 json_object_array_add(json_paths, json_path);
9514 } else {
9515 vty_out(vty, "\n");
6f214dd3 9516
b5e140c8 9517 if (safi == SAFI_EVPN) {
d071f237 9518 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9519 /* XXX - add these params to the json out */
b5e140c8 9520 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9521 vty_out(vty, "ESI:%s",
9522 esi_to_str(&attr->esi, esi_buf,
9523 sizeof(esi_buf)));
60605cbc 9524
229587fb 9525 vty_out(vty, "\n");
b5e140c8
AK
9526 }
9527 if (attr->flag &
9528 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9529 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9530 vty_out(vty, "%s\n",
9531 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9532 }
6f214dd3
CS
9533 }
9534
49e5a4a0 9535#ifdef ENABLE_BGP_VNC
d62a17ae 9536 /* prints an additional line, indented, with VNC info, if
9537 * present */
9538 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9539 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9540#endif
d62a17ae 9541 }
9542}
718e3744 9543
9544/* called from terminal list command */
7d3cae70
DA
9545void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9546 const struct prefix *p, struct attr *attr, safi_t safi,
9547 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9548{
9549 json_object *json_status = NULL;
9550 json_object *json_net = NULL;
aef999a2 9551 int len;
d62a17ae 9552 char buff[BUFSIZ];
dc387b0f 9553
d62a17ae 9554 /* Route status display. */
9555 if (use_json) {
9556 json_status = json_object_new_object();
9557 json_net = json_object_new_object();
9558 } else {
146c574b 9559 vty_out(vty, " *");
d62a17ae 9560 vty_out(vty, ">");
9561 vty_out(vty, " ");
9562 }
718e3744 9563
d62a17ae 9564 /* print prefix and mask */
50e05855 9565 if (use_json) {
dc387b0f
LK
9566 if (safi == SAFI_EVPN)
9567 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9568 else if (p->family == AF_INET || p->family == AF_INET6) {
9569 json_object_string_add(
9570 json_net, "addrPrefix",
9571 inet_ntop(p->family, &p->u.prefix, buff,
9572 BUFSIZ));
9573 json_object_int_add(json_net, "prefixLen",
9574 p->prefixlen);
67d7e256 9575 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9576 }
50e05855 9577 } else
7d3cae70 9578 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9579
9580 /* Print attribute */
9581 if (attr) {
9582 if (use_json) {
7226bc40
TA
9583 if (p->family == AF_INET &&
9584 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9585 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9586 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9587 json_object_string_addf(
9588 json_net, "nextHop", "%pI4",
9589 &attr->mp_nexthop_global_in);
d62a17ae 9590 else
c949c771
DA
9591 json_object_string_addf(
9592 json_net, "nextHop", "%pI4",
9593 &attr->nexthop);
7226bc40
TA
9594 } else if (p->family == AF_INET6 ||
9595 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9596 json_object_string_addf(
9597 json_net, "nextHopGlobal", "%pI6",
9598 &attr->mp_nexthop_global);
7226bc40
TA
9599 } else if (p->family == AF_EVPN &&
9600 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9601 json_object_string_addf(
9602 json_net, "nextHop", "%pI4",
9603 &attr->mp_nexthop_global_in);
23d0a753 9604 }
d62a17ae 9605
9606 if (attr->flag
9607 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9608 json_object_int_add(json_net, "metric",
9609 attr->med);
9610
0fbac0b4 9611 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9612 json_object_int_add(json_net, "locPrf",
0fbac0b4 9613 attr->local_pref);
d62a17ae 9614
9615 json_object_int_add(json_net, "weight", attr->weight);
9616
9617 /* Print aspath */
0fbac0b4 9618 if (attr->aspath)
50e05855 9619 json_object_string_add(json_net, "path",
0fbac0b4 9620 attr->aspath->str);
d62a17ae 9621
9622 /* Print origin */
dd426a51
DA
9623#if CONFDATE > 20231208
9624CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9625#endif
d62a17ae 9626 json_object_string_add(json_net, "bgpOriginCode",
9627 bgp_origin_str[attr->origin]);
dd426a51
DA
9628 json_object_string_add(
9629 json_net, "origin",
9630 bgp_origin_long_str[attr->origin]);
d62a17ae 9631 } else {
7226bc40
TA
9632 if (p->family == AF_INET &&
9633 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9634 safi == SAFI_EVPN ||
9635 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9636 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9637 || safi == SAFI_EVPN)
23d0a753
DA
9638 vty_out(vty, "%-16pI4",
9639 &attr->mp_nexthop_global_in);
ae248832 9640 else if (wide)
23d0a753 9641 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9642 else
23d0a753 9643 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9644 } else if (p->family == AF_INET6 ||
9645 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9646 len = vty_out(vty, "%pI6",
9647 &attr->mp_nexthop_global);
ae248832 9648 len = wide ? (41 - len) : (16 - len);
d62a17ae 9649 if (len < 1)
9650 vty_out(vty, "\n%*s", 36, " ");
9651 else
9652 vty_out(vty, "%*s", len, " ");
9653 }
9654 if (attr->flag
9655 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9656 if (wide)
9657 vty_out(vty, "%7u", attr->med);
9658 else
9659 vty_out(vty, "%10u", attr->med);
9660 else if (wide)
9661 vty_out(vty, " ");
d62a17ae 9662 else
9663 vty_out(vty, " ");
718e3744 9664
d62a17ae 9665 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9666 vty_out(vty, "%7u", attr->local_pref);
9667 else
9668 vty_out(vty, " ");
9669
9670 vty_out(vty, "%7u ", attr->weight);
9671
9672 /* Print aspath */
9673 if (attr->aspath)
9674 aspath_print_vty(vty, "%s", attr->aspath, " ");
9675
9676 /* Print origin */
9677 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9678 }
9679 }
9680 if (use_json) {
4d65410c
DA
9681 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9682
dd426a51
DA
9683#if CONFDATE > 20231208
9684CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9685#endif
d62a17ae 9686 json_object_boolean_true_add(json_status, "*");
9687 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9688 json_object_boolean_true_add(json_net, "valid");
9689 json_object_boolean_true_add(json_net, "best");
4d65410c 9690
dd426a51 9691 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9692 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9693 json_object_boolean_true_add(json_net, "multipath");
9694 }
d62a17ae 9695 json_object_object_add(json_net, "appliedStatusSymbols",
9696 json_status);
511211bf 9697 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9698 } else
9699 vty_out(vty, "\n");
9700}
9701
bd494ec5 9702void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9703 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9704 json_object *json)
9705{
9706 json_object *json_out = NULL;
9707 struct attr *attr;
9708 mpls_label_t label = MPLS_INVALID_LABEL;
9709
9b6d8fcf 9710 if (!path->extra)
d62a17ae 9711 return;
9712
9713 if (json)
9714 json_out = json_object_new_object();
9715
9716 /* short status lead text */
82c298be 9717 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9718
9719 /* print prefix and mask */
9720 if (json == NULL) {
9721 if (!display)
7d3cae70 9722 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9723 else
9724 vty_out(vty, "%*s", 17, " ");
9725 }
9726
9727 /* Print attribute */
9b6d8fcf 9728 attr = path->attr;
7226bc40
TA
9729 if (((p->family == AF_INET) &&
9730 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9731 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9732 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9733 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9734 || safi == SAFI_EVPN) {
9735 if (json)
c949c771
DA
9736 json_object_string_addf(
9737 json_out, "mpNexthopGlobalIn", "%pI4",
9738 &attr->mp_nexthop_global_in);
05864da7 9739 else
23d0a753
DA
9740 vty_out(vty, "%-16pI4",
9741 &attr->mp_nexthop_global_in);
05864da7
DS
9742 } else {
9743 if (json)
c949c771
DA
9744 json_object_string_addf(json_out, "nexthop",
9745 "%pI4", &attr->nexthop);
05864da7 9746 else
23d0a753 9747 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9748 }
7226bc40
TA
9749 } else if (((p->family == AF_INET6) &&
9750 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9751 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9752 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9753 char buf_a[512];
9754
9755 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9756 if (json)
c949c771
DA
9757 json_object_string_addf(
9758 json_out, "mpNexthopGlobalIn", "%pI6",
9759 &attr->mp_nexthop_global);
05864da7
DS
9760 else
9761 vty_out(vty, "%s",
9762 inet_ntop(AF_INET6,
9763 &attr->mp_nexthop_global,
9764 buf_a, sizeof(buf_a)));
9765 } else if (attr->mp_nexthop_len
9766 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9767 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9768 &attr->mp_nexthop_global,
9769 &attr->mp_nexthop_local);
9770 if (json)
9771 json_object_string_add(json_out,
9772 "mpNexthopGlobalLocal",
9773 buf_a);
9774 else
9775 vty_out(vty, "%s", buf_a);
d62a17ae 9776 }
9777 }
9778
9b6d8fcf 9779 label = decode_label(&path->extra->label[0]);
d62a17ae 9780
9781 if (bgp_is_valid_label(&label)) {
9782 if (json) {
9783 json_object_int_add(json_out, "notag", label);
9784 json_object_array_add(json, json_out);
9785 } else {
9786 vty_out(vty, "notag/%d", label);
9787 vty_out(vty, "\n");
9788 }
700ddfed
PG
9789 } else if (!json)
9790 vty_out(vty, "\n");
d62a17ae 9791}
718e3744 9792
bd494ec5 9793void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9794 struct bgp_path_info *path, int display,
d62a17ae 9795 json_object *json_paths)
718e3744 9796{
d62a17ae 9797 struct attr *attr;
d62a17ae 9798 json_object *json_path = NULL;
14f51eba
LK
9799 json_object *json_nexthop = NULL;
9800 json_object *json_overlay = NULL;
856ca177 9801
9b6d8fcf 9802 if (!path->extra)
d62a17ae 9803 return;
718e3744 9804
14f51eba
LK
9805 if (json_paths) {
9806 json_path = json_object_new_object();
9807 json_overlay = json_object_new_object();
9808 json_nexthop = json_object_new_object();
9809 }
9810
d62a17ae 9811 /* short status lead text */
82c298be 9812 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9813
d62a17ae 9814 /* print prefix and mask */
9815 if (!display)
7d3cae70 9816 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9817 else
9818 vty_out(vty, "%*s", 17, " ");
9819
9820 /* Print attribute */
9b6d8fcf 9821 attr = path->attr;
05864da7 9822 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9823
05864da7
DS
9824 switch (af) {
9825 case AF_INET:
05864da7 9826 if (!json_path) {
db66cf7c 9827 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9828 } else {
db66cf7c
DA
9829 json_object_string_addf(json_nexthop, "ip", "%pI4",
9830 &attr->mp_nexthop_global_in);
14f51eba 9831
05864da7 9832 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9833
05864da7
DS
9834 json_object_object_add(json_path, "nexthop",
9835 json_nexthop);
9836 }
9837 break;
9838 case AF_INET6:
05864da7 9839 if (!json_path) {
db66cf7c
DA
9840 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9841 &attr->mp_nexthop_local);
05864da7 9842 } else {
db66cf7c
DA
9843 json_object_string_addf(json_nexthop, "ipv6Global",
9844 "%pI6",
9845 &attr->mp_nexthop_global);
14f51eba 9846
db66cf7c
DA
9847 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9848 "%pI6",
9849 &attr->mp_nexthop_local);
14f51eba 9850
05864da7 9851 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9852
05864da7
DS
9853 json_object_object_add(json_path, "nexthop",
9854 json_nexthop);
9855 }
9856 break;
9857 default:
9858 if (!json_path) {
9859 vty_out(vty, "?");
9860 } else {
9861 json_object_string_add(json_nexthop, "Error",
9862 "Unsupported address-family");
77a2f8e5
DA
9863 json_object_string_add(json_nexthop, "error",
9864 "Unsupported address-family");
d62a17ae 9865 }
05864da7 9866 }
988258b4 9867
6c924775
DS
9868 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9869
05864da7 9870 if (!json_path)
db66cf7c 9871 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9872 else
db66cf7c 9873 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9874
b53e67a3 9875 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9876 char *mac = NULL;
9877 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9878 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9879 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9880
9881 if (routermac)
9882 mac = ecom_mac2str((char *)routermac->val);
9883 if (mac) {
9884 if (!json_path) {
c4efd0f4 9885 vty_out(vty, "/%s", mac);
05864da7
DS
9886 } else {
9887 json_object_string_add(json_overlay, "rmac",
9888 mac);
988258b4 9889 }
05864da7 9890 XFREE(MTYPE_TMP, mac);
988258b4 9891 }
05864da7 9892 }
718e3744 9893
05864da7
DS
9894 if (!json_path) {
9895 vty_out(vty, "\n");
9896 } else {
9897 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9898
05864da7 9899 json_object_array_add(json_paths, json_path);
14f51eba 9900 }
d62a17ae 9901}
718e3744 9902
d62a17ae 9903/* dampening route */
5f040085
DS
9904static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9905 struct bgp_path_info *path, int display,
9906 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9907 json_object *json_paths)
d62a17ae 9908{
e5be8c1d 9909 struct attr *attr = path->attr;
d62a17ae 9910 int len;
9911 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9912 json_object *json_path = NULL;
9913
9914 if (use_json)
9915 json_path = json_object_new_object();
d62a17ae 9916
9917 /* short status lead text */
e5be8c1d 9918 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9919
9920 /* print prefix and mask */
9921 if (!use_json) {
9922 if (!display)
7d3cae70 9923 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9924 else
9925 vty_out(vty, "%*s", 17, " ");
d62a17ae 9926
e5be8c1d
DA
9927 len = vty_out(vty, "%s", path->peer->host);
9928 len = 17 - len;
9929
9930 if (len < 1)
d62a17ae 9931 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9932 else
9933 vty_out(vty, "%*s", len, " ");
d62a17ae 9934
9b6d8fcf
DS
9935 vty_out(vty, "%s ",
9936 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9937 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9938 use_json, NULL));
d62a17ae 9939
e5be8c1d 9940 if (attr->aspath)
05864da7 9941 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9942
05864da7
DS
9943 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9944
d62a17ae 9945 vty_out(vty, "\n");
e5be8c1d
DA
9946 } else {
9947 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9948 safi, use_json, json_path);
9949
9950 if (attr->aspath)
9951 json_object_string_add(json_path, "asPath",
9952 attr->aspath->str);
9953
9954 json_object_string_add(json_path, "origin",
9955 bgp_origin_str[attr->origin]);
9956 json_object_string_add(json_path, "peerHost", path->peer->host);
9957
9958 json_object_array_add(json_paths, json_path);
9959 }
d62a17ae 9960}
718e3744 9961
d62a17ae 9962/* flap route */
5f040085
DS
9963static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9964 struct bgp_path_info *path, int display,
9965 afi_t afi, safi_t safi, bool use_json,
31258046 9966 json_object *json_paths)
784d3a42 9967{
31258046 9968 struct attr *attr = path->attr;
d62a17ae 9969 struct bgp_damp_info *bdi;
9970 char timebuf[BGP_UPTIME_LEN];
9971 int len;
31258046 9972 json_object *json_path = NULL;
784d3a42 9973
9b6d8fcf 9974 if (!path->extra)
d62a17ae 9975 return;
784d3a42 9976
31258046
DA
9977 if (use_json)
9978 json_path = json_object_new_object();
9979
9b6d8fcf 9980 bdi = path->extra->damp_info;
784d3a42 9981
d62a17ae 9982 /* short status lead text */
31258046 9983 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9984
d62a17ae 9985 if (!use_json) {
9986 if (!display)
7d3cae70 9987 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9988 else
9989 vty_out(vty, "%*s", 17, " ");
784d3a42 9990
31258046
DA
9991 len = vty_out(vty, "%s", path->peer->host);
9992 len = 16 - len;
9993 if (len < 1)
d62a17ae 9994 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9995 else
9996 vty_out(vty, "%*s", len, " ");
784d3a42 9997
31258046
DA
9998 len = vty_out(vty, "%d", bdi->flap);
9999 len = 5 - len;
10000 if (len < 1)
d62a17ae 10001 vty_out(vty, " ");
d62a17ae 10002 else
10003 vty_out(vty, "%*s", len, " ");
d62a17ae 10004
996c9314
LB
10005 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10006 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10007
31258046
DA
10008 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10009 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10010 vty_out(vty, "%s ",
9b6d8fcf 10011 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10012 BGP_UPTIME_LEN, afi,
31258046
DA
10013 safi, use_json, NULL));
10014 else
d62a17ae 10015 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10016
31258046 10017 if (attr->aspath)
05864da7 10018 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10019
05864da7
DS
10020 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10021
d62a17ae 10022 vty_out(vty, "\n");
31258046
DA
10023 } else {
10024 json_object_string_add(json_path, "peerHost", path->peer->host);
10025 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10026
10027 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10028 json_path);
10029
10030 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10031 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10032 bgp_damp_reuse_time_vty(vty, path, timebuf,
10033 BGP_UPTIME_LEN, afi, safi,
10034 use_json, json_path);
10035
10036 if (attr->aspath)
10037 json_object_string_add(json_path, "asPath",
10038 attr->aspath->str);
10039
10040 json_object_string_add(json_path, "origin",
10041 bgp_origin_str[attr->origin]);
10042
10043 json_object_array_add(json_paths, json_path);
10044 }
d62a17ae 10045}
10046
10047static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10048 int *first, const char *header,
10049 json_object *json_adv_to)
10050{
d62a17ae 10051 json_object *json_peer = NULL;
10052
10053 if (json_adv_to) {
10054 /* 'advertised-to' is a dictionary of peers we have advertised
10055 * this
10056 * prefix too. The key is the peer's IP or swpX, the value is
10057 * the
10058 * hostname if we know it and "" if not.
10059 */
10060 json_peer = json_object_new_object();
10061
10062 if (peer->hostname)
10063 json_object_string_add(json_peer, "hostname",
10064 peer->hostname);
10065
10066 if (peer->conf_if)
10067 json_object_object_add(json_adv_to, peer->conf_if,
10068 json_peer);
10069 else
47e12884
DA
10070 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10071 &peer->su);
d62a17ae 10072 } else {
10073 if (*first) {
10074 vty_out(vty, "%s", header);
10075 *first = 0;
10076 }
10077
10078 if (peer->hostname
892fedb6 10079 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10080 if (peer->conf_if)
10081 vty_out(vty, " %s(%s)", peer->hostname,
10082 peer->conf_if);
10083 else
47e12884
DA
10084 vty_out(vty, " %s(%pSU)", peer->hostname,
10085 &peer->su);
d62a17ae 10086 } else {
10087 if (peer->conf_if)
10088 vty_out(vty, " %s", peer->conf_if);
10089 else
47e12884 10090 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10091 }
10092 }
784d3a42
PG
10093}
10094
dcc68b5e
MS
10095static void route_vty_out_tx_ids(struct vty *vty,
10096 struct bgp_addpath_info_data *d)
10097{
10098 int i;
10099
10100 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10101 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10102 d->addpath_tx_id[i],
10103 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10104 }
10105}
10106
5e4d4c8a 10107static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10108 struct bgp_path_info *pi,
10109 struct attr *attr,
10110 json_object *json_path)
5e4d4c8a
AK
10111{
10112 char esi_buf[ESI_STR_LEN];
10113 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10114 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10115 ATTR_ES_PEER_ROUTER);
10116 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10117 ATTR_ES_PEER_ACTIVE);
10118 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10119 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10120 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10121 if (json_path) {
10122 json_object *json_es_info = NULL;
10123
10124 json_object_string_add(
10125 json_path, "esi",
10126 esi_buf);
10127 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10128 json_es_info = json_object_new_object();
10129 if (es_local)
10130 json_object_boolean_true_add(
10131 json_es_info, "localEs");
10132 if (peer_active)
10133 json_object_boolean_true_add(
10134 json_es_info, "peerActive");
10135 if (peer_proxy)
10136 json_object_boolean_true_add(
10137 json_es_info, "peerProxy");
10138 if (peer_router)
10139 json_object_boolean_true_add(
10140 json_es_info, "peerRouter");
10141 if (attr->mm_sync_seqnum)
10142 json_object_int_add(
10143 json_es_info, "peerSeq",
10144 attr->mm_sync_seqnum);
10145 json_object_object_add(
10146 json_path, "es_info",
10147 json_es_info);
10148 }
10149 } else {
10150 if (bgp_evpn_attr_is_sync(attr))
10151 vty_out(vty,
10152 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10153 esi_buf,
10154 es_local ? "local-es":"",
10155 peer_proxy ? "proxy " : "",
10156 peer_active ? "active ":"",
10157 peer_router ? "router ":"",
10158 attr->mm_sync_seqnum);
10159 else
10160 vty_out(vty, " ESI %s %s\n",
10161 esi_buf,
10162 es_local ? "local-es":"");
10163 }
10164}
10165
4933eaaf 10166void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10167 const struct prefix *p, struct bgp_path_info *path,
10168 afi_t afi, safi_t safi,
4027d19b
DS
10169 enum rpki_states rpki_curr_state,
10170 json_object *json_paths)
d62a17ae 10171{
10172 char buf[INET6_ADDRSTRLEN];
100290e4 10173 char tag_buf[30];
515c2602 10174 struct attr *attr = path->attr;
d62a17ae 10175 time_t tbuf;
10176 json_object *json_bestpath = NULL;
10177 json_object *json_cluster_list = NULL;
10178 json_object *json_cluster_list_list = NULL;
10179 json_object *json_ext_community = NULL;
10180 json_object *json_last_update = NULL;
7fd077aa 10181 json_object *json_pmsi = NULL;
d62a17ae 10182 json_object *json_nexthop_global = NULL;
10183 json_object *json_nexthop_ll = NULL;
10184 json_object *json_nexthops = NULL;
10185 json_object *json_path = NULL;
10186 json_object *json_peer = NULL;
10187 json_object *json_string = NULL;
10188 json_object *json_adv_to = NULL;
10189 int first = 0;
10190 struct listnode *node, *nnode;
10191 struct peer *peer;
be92fc9f 10192 bool addpath_capable;
d62a17ae 10193 int has_adj;
10194 unsigned int first_as;
1defdda8 10195 bool nexthop_self =
9b6d8fcf 10196 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10197 int i;
2ba93fd6
DA
10198 char *nexthop_hostname =
10199 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10200 uint32_t ttl = 0;
10201 uint32_t bos = 0;
10202 uint32_t exp = 0;
10203 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10204 tag_buf[0] = '\0';
f0cde006
LS
10205 struct bgp_path_info *bpi_ultimate =
10206 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10207
10208 if (json_paths) {
10209 json_path = json_object_new_object();
10210 json_peer = json_object_new_object();
10211 json_nexthop_global = json_object_new_object();
10212 }
10213
8304dabf
AD
10214 if (safi == SAFI_EVPN) {
10215 if (!json_paths)
34c7f35f 10216 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10217 }
10218
44c69747 10219 if (path->extra) {
9b6d8fcf
DS
10220 if (path->extra && path->extra->num_labels) {
10221 bgp_evpn_label2str(path->extra->label,
10222 path->extra->num_labels, tag_buf,
a4d82a8a 10223 sizeof(tag_buf));
d62a17ae 10224 }
d7325ee7 10225 if (safi == SAFI_EVPN) {
44c69747 10226 if (!json_paths) {
44c69747
LK
10227 if (tag_buf[0] != '\0')
10228 vty_out(vty, " VNI %s", tag_buf);
44c69747 10229 } else {
77a2f8e5 10230 if (tag_buf[0]) {
44c69747
LK
10231 json_object_string_add(json_path, "VNI",
10232 tag_buf);
77a2f8e5
DA
10233 json_object_string_add(json_path, "vni",
10234 tag_buf);
10235 }
44c69747 10236 }
d7325ee7 10237 }
d62a17ae 10238 }
d62a17ae 10239
8304dabf
AD
10240 if (safi == SAFI_EVPN
10241 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10242 char gwip_buf[INET6_ADDRSTRLEN];
10243
860e740b
IR
10244 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10245 sizeof(gwip_buf));
8304dabf
AD
10246
10247 if (json_paths)
10248 json_object_string_add(json_path, "gatewayIP",
10249 gwip_buf);
10250 else
10251 vty_out(vty, " Gateway IP %s", gwip_buf);
10252 }
10253
2bf9780b 10254 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10255 vty_out(vty, "\n");
10256
100290e4
SW
10257
10258 if (path->extra && path->extra->parent && !json_paths) {
10259 struct bgp_path_info *parent_ri;
10260 struct bgp_dest *dest, *pdest;
10261
10262 parent_ri = (struct bgp_path_info *)path->extra->parent;
10263 dest = parent_ri->net;
10264 if (dest && dest->pdest) {
10265 pdest = dest->pdest;
10266 if (is_pi_family_evpn(parent_ri)) {
10267 vty_out(vty,
10268 " Imported from %pRD:%pFX, VNI %s",
10269 (struct prefix_rd *)bgp_dest_get_prefix(
10270 pdest),
10271 (struct prefix_evpn *)
10272 bgp_dest_get_prefix(dest),
10273 tag_buf);
6012963e 10274 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10275 vty_out(vty, ", L3NHG %s",
6012963e
SW
10276 CHECK_FLAG(
10277 attr->es_flags,
10278 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10279 ? "active"
10280 : "inactive");
10281 vty_out(vty, "\n");
10282
10283 } else
10284 vty_out(vty, " Imported from %pRD:%pFX\n",
10285 (struct prefix_rd *)bgp_dest_get_prefix(
10286 pdest),
10287 (struct prefix_evpn *)
10288 bgp_dest_get_prefix(dest));
10289 }
10290 }
10291
05864da7
DS
10292 /* Line1 display AS-path, Aggregator */
10293 if (attr->aspath) {
10294 if (json_paths) {
10295 if (!attr->aspath->json)
10296 aspath_str_update(attr->aspath, true);
10297 json_object_lock(attr->aspath->json);
10298 json_object_object_add(json_path, "aspath",
10299 attr->aspath->json);
10300 } else {
10301 if (attr->aspath->segments)
10302 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10303 else
05864da7 10304 vty_out(vty, " Local");
d62a17ae 10305 }
05864da7 10306 }
d62a17ae 10307
05864da7
DS
10308 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10309 if (json_paths)
10310 json_object_boolean_true_add(json_path, "removed");
10311 else
10312 vty_out(vty, ", (removed)");
10313 }
d62a17ae 10314
05864da7
DS
10315 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10316 if (json_paths)
10317 json_object_boolean_true_add(json_path, "stale");
10318 else
10319 vty_out(vty, ", (stale)");
10320 }
d62a17ae 10321
05864da7
DS
10322 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10323 if (json_paths) {
10324 json_object_int_add(json_path, "aggregatorAs",
10325 attr->aggregator_as);
c949c771
DA
10326 json_object_string_addf(json_path, "aggregatorId",
10327 "%pI4", &attr->aggregator_addr);
05864da7 10328 } else {
88d495a9
DA
10329 vty_out(vty, ", (aggregated by %u %pI4)",
10330 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10331 }
05864da7 10332 }
d62a17ae 10333
05864da7
DS
10334 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10335 PEER_FLAG_REFLECTOR_CLIENT)) {
10336 if (json_paths)
10337 json_object_boolean_true_add(json_path,
10338 "rxedFromRrClient");
10339 else
10340 vty_out(vty, ", (Received from a RR-client)");
10341 }
d62a17ae 10342
05864da7
DS
10343 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10344 PEER_FLAG_RSERVER_CLIENT)) {
10345 if (json_paths)
10346 json_object_boolean_true_add(json_path,
10347 "rxedFromRsClient");
10348 else
10349 vty_out(vty, ", (Received from a RS-client)");
10350 }
d62a17ae 10351
05864da7
DS
10352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10353 if (json_paths)
10354 json_object_boolean_true_add(json_path,
10355 "dampeningHistoryEntry");
10356 else
10357 vty_out(vty, ", (history entry)");
10358 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path,
10361 "dampeningSuppressed");
10362 else
10363 vty_out(vty, ", (suppressed due to dampening)");
10364 }
d62a17ae 10365
05864da7
DS
10366 if (!json_paths)
10367 vty_out(vty, "\n");
d62a17ae 10368
05864da7
DS
10369 /* Line2 display Next-hop, Neighbor, Router-id */
10370 /* Display the nexthop */
b54892e0 10371
34c7f35f
SW
10372 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10373 p->family == AF_EVPN) &&
7226bc40
TA
10374 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10375 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10376 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10377 || safi == SAFI_EVPN) {
515c2602 10378 if (json_paths) {
c949c771
DA
10379 json_object_string_addf(
10380 json_nexthop_global, "ip", "%pI4",
10381 &attr->mp_nexthop_global_in);
515c2602 10382
939a97f4 10383 if (path->peer->hostname)
515c2602
DA
10384 json_object_string_add(
10385 json_nexthop_global, "hostname",
939a97f4 10386 path->peer->hostname);
aef999a2
DA
10387 } else {
10388 if (nexthop_hostname)
10389 vty_out(vty, " %pI4(%s)",
10390 &attr->mp_nexthop_global_in,
10391 nexthop_hostname);
10392 else
10393 vty_out(vty, " %pI4",
10394 &attr->mp_nexthop_global_in);
10395 }
d62a17ae 10396 } else {
515c2602 10397 if (json_paths) {
c949c771
DA
10398 json_object_string_addf(json_nexthop_global,
10399 "ip", "%pI4",
10400 &attr->nexthop);
515c2602 10401
939a97f4 10402 if (path->peer->hostname)
515c2602
DA
10403 json_object_string_add(
10404 json_nexthop_global, "hostname",
939a97f4 10405 path->peer->hostname);
aef999a2
DA
10406 } else {
10407 if (nexthop_hostname)
10408 vty_out(vty, " %pI4(%s)",
10409 &attr->nexthop,
10410 nexthop_hostname);
10411 else
10412 vty_out(vty, " %pI4",
10413 &attr->nexthop);
10414 }
d62a17ae 10415 }
10416
05864da7
DS
10417 if (json_paths)
10418 json_object_string_add(json_nexthop_global, "afi",
10419 "ipv4");
10420 } else {
10421 if (json_paths) {
c949c771
DA
10422 json_object_string_addf(json_nexthop_global, "ip",
10423 "%pI6",
10424 &attr->mp_nexthop_global);
515c2602 10425
939a97f4 10426 if (path->peer->hostname)
515c2602
DA
10427 json_object_string_add(json_nexthop_global,
10428 "hostname",
939a97f4 10429 path->peer->hostname);
515c2602 10430
05864da7
DS
10431 json_object_string_add(json_nexthop_global, "afi",
10432 "ipv6");
10433 json_object_string_add(json_nexthop_global, "scope",
10434 "global");
10435 } else {
aef999a2
DA
10436 if (nexthop_hostname)
10437 vty_out(vty, " %pI6(%s)",
10438 &attr->mp_nexthop_global,
10439 nexthop_hostname);
10440 else
10441 vty_out(vty, " %pI6",
10442 &attr->mp_nexthop_global);
d62a17ae 10443 }
05864da7 10444 }
d62a17ae 10445
05864da7 10446 /* Display the IGP cost or 'inaccessible' */
f0cde006 10447 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10448 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10449
10450 if (json_paths) {
05864da7
DS
10451 json_object_boolean_false_add(json_nexthop_global,
10452 "accessible");
95ba22d5
DA
10453 json_object_boolean_add(json_nexthop_global,
10454 "importCheckEnabled", import);
10455 } else {
10456 vty_out(vty, " (inaccessible%s)",
10457 import ? ", import-check enabled" : "");
10458 }
05864da7 10459 } else {
f0cde006 10460 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10461 if (json_paths)
f0cde006
LS
10462 json_object_int_add(
10463 json_nexthop_global, "metric",
10464 bpi_ultimate->extra->igpmetric);
d62a17ae 10465 else
05864da7 10466 vty_out(vty, " (metric %u)",
f0cde006 10467 bpi_ultimate->extra->igpmetric);
d62a17ae 10468 }
10469
05864da7 10470 /* IGP cost is 0, display this only for json */
d62a17ae 10471 else {
d62a17ae 10472 if (json_paths)
05864da7
DS
10473 json_object_int_add(json_nexthop_global,
10474 "metric", 0);
d62a17ae 10475 }
d62a17ae 10476
05864da7
DS
10477 if (json_paths)
10478 json_object_boolean_true_add(json_nexthop_global,
10479 "accessible");
10480 }
d62a17ae 10481
05864da7
DS
10482 /* Display peer "from" output */
10483 /* This path was originated locally */
10484 if (path->peer == bgp->peer_self) {
d62a17ae 10485
34c7f35f 10486 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10487 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10488 if (json_paths)
05864da7
DS
10489 json_object_string_add(json_peer, "peerId",
10490 "0.0.0.0");
d62a17ae 10491 else
05864da7
DS
10492 vty_out(vty, " from 0.0.0.0 ");
10493 } else {
d62a17ae 10494 if (json_paths)
05864da7
DS
10495 json_object_string_add(json_peer, "peerId",
10496 "::");
d62a17ae 10497 else
05864da7 10498 vty_out(vty, " from :: ");
d62a17ae 10499 }
d62a17ae 10500
4e9a9863 10501 if (json_paths)
c949c771
DA
10502 json_object_string_addf(json_peer, "routerId", "%pI4",
10503 &bgp->router_id);
4e9a9863 10504 else
23d0a753 10505 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10506 }
d62a17ae 10507
05864da7
DS
10508 /* We RXed this path from one of our peers */
10509 else {
10510
10511 if (json_paths) {
47e12884
DA
10512 json_object_string_addf(json_peer, "peerId", "%pSU",
10513 &path->peer->su);
c949c771
DA
10514 json_object_string_addf(json_peer, "routerId", "%pI4",
10515 &path->peer->remote_id);
05864da7
DS
10516
10517 if (path->peer->hostname)
10518 json_object_string_add(json_peer, "hostname",
10519 path->peer->hostname);
10520
10521 if (path->peer->domainname)
10522 json_object_string_add(json_peer, "domainname",
10523 path->peer->domainname);
10524
10525 if (path->peer->conf_if)
10526 json_object_string_add(json_peer, "interface",
10527 path->peer->conf_if);
10528 } else {
10529 if (path->peer->conf_if) {
10530 if (path->peer->hostname
892fedb6
DA
10531 && CHECK_FLAG(path->peer->bgp->flags,
10532 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10533 vty_out(vty, " from %s(%s)",
10534 path->peer->hostname,
10535 path->peer->conf_if);
d62a17ae 10536 else
05864da7 10537 vty_out(vty, " from %s",
9b6d8fcf 10538 path->peer->conf_if);
d62a17ae 10539 } else {
05864da7 10540 if (path->peer->hostname
892fedb6
DA
10541 && CHECK_FLAG(path->peer->bgp->flags,
10542 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10543 vty_out(vty, " from %s(%s)",
10544 path->peer->hostname,
10545 path->peer->host);
d62a17ae 10546 else
47e12884
DA
10547 vty_out(vty, " from %pSU",
10548 &path->peer->su);
d62a17ae 10549 }
d62a17ae 10550
05864da7 10551 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10552 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10553 else
07380148 10554 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10555 }
05864da7 10556 }
9df8b37c 10557
05864da7
DS
10558 /*
10559 * Note when vrfid of nexthop is different from that of prefix
10560 */
10561 if (path->extra && path->extra->bgp_orig) {
10562 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10563
05864da7
DS
10564 if (json_paths) {
10565 const char *vn;
9df8b37c 10566
05864da7
DS
10567 if (path->extra->bgp_orig->inst_type
10568 == BGP_INSTANCE_TYPE_DEFAULT)
10569 vn = VRF_DEFAULT_NAME;
10570 else
10571 vn = path->extra->bgp_orig->name;
9df8b37c 10572
05864da7 10573 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10574
05864da7
DS
10575 if (nexthop_vrfid == VRF_UNKNOWN) {
10576 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10577 } else {
05864da7
DS
10578 json_object_int_add(json_path, "nhVrfId",
10579 (int)nexthop_vrfid);
9df8b37c 10580 }
05864da7
DS
10581 } else {
10582 if (nexthop_vrfid == VRF_UNKNOWN)
10583 vty_out(vty, " vrf ?");
137147c6
DS
10584 else {
10585 struct vrf *vrf;
10586
10587 vrf = vrf_lookup_by_id(nexthop_vrfid);
10588 vty_out(vty, " vrf %s(%u)",
10589 VRF_LOGNAME(vrf), nexthop_vrfid);
10590 }
9df8b37c 10591 }
05864da7 10592 }
9df8b37c 10593
05864da7
DS
10594 if (nexthop_self) {
10595 if (json_paths) {
10596 json_object_boolean_true_add(json_path,
10597 "announceNexthopSelf");
10598 } else {
10599 vty_out(vty, " announce-nh-self");
9df8b37c 10600 }
05864da7 10601 }
9df8b37c 10602
05864da7
DS
10603 if (!json_paths)
10604 vty_out(vty, "\n");
d62a17ae 10605
05864da7
DS
10606 /* display the link-local nexthop */
10607 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10608 if (json_paths) {
10609 json_nexthop_ll = json_object_new_object();
c949c771
DA
10610 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10611 &attr->mp_nexthop_local);
515c2602 10612
939a97f4 10613 if (path->peer->hostname)
515c2602
DA
10614 json_object_string_add(json_nexthop_ll,
10615 "hostname",
939a97f4 10616 path->peer->hostname);
515c2602 10617
05864da7
DS
10618 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10619 json_object_string_add(json_nexthop_ll, "scope",
10620 "link-local");
d62a17ae 10621
05864da7
DS
10622 json_object_boolean_true_add(json_nexthop_ll,
10623 "accessible");
d62a17ae 10624
2bb8b49c 10625 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10626 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10627 "used");
10628 else
10629 json_object_boolean_true_add(
10630 json_nexthop_global, "used");
10631 } else {
10632 vty_out(vty, " (%s) %s\n",
10633 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10634 buf, INET6_ADDRSTRLEN),
2bb8b49c 10635 attr->mp_nexthop_prefer_global
05864da7
DS
10636 ? "(prefer-global)"
10637 : "(used)");
d62a17ae 10638 }
05864da7
DS
10639 }
10640 /* If we do not have a link-local nexthop then we must flag the
10641 global as "used" */
10642 else {
10643 if (json_paths)
10644 json_object_boolean_true_add(json_nexthop_global,
10645 "used");
10646 }
d62a17ae 10647
b5e140c8 10648 if (safi == SAFI_EVPN &&
5e4d4c8a 10649 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10650 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10651 }
10652
05864da7
DS
10653 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10654 * Int/Ext/Local, Atomic, best */
10655 if (json_paths)
10656 json_object_string_add(json_path, "origin",
10657 bgp_origin_long_str[attr->origin]);
10658 else
10659 vty_out(vty, " Origin %s",
10660 bgp_origin_long_str[attr->origin]);
9df8b37c 10661
05864da7 10662 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10663 if (json_paths)
05864da7 10664 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10665 else
05864da7
DS
10666 vty_out(vty, ", metric %u", attr->med);
10667 }
9df8b37c 10668
05864da7
DS
10669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10670 if (json_paths)
0fbac0b4 10671 json_object_int_add(json_path, "locPrf",
05864da7
DS
10672 attr->local_pref);
10673 else
10674 vty_out(vty, ", localpref %u", attr->local_pref);
10675 }
9df8b37c 10676
97a52c82
DA
10677 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10678 if (json_paths)
10679 json_object_int_add(json_path, "aigpMetric",
10680 bgp_attr_get_aigp_metric(attr));
10681 else
10682 vty_out(vty, ", aigp-metric %" PRIu64,
10683 bgp_attr_get_aigp_metric(attr));
10684 }
10685
05864da7
DS
10686 if (attr->weight != 0) {
10687 if (json_paths)
10688 json_object_int_add(json_path, "weight", attr->weight);
10689 else
10690 vty_out(vty, ", weight %u", attr->weight);
10691 }
9df8b37c 10692
05864da7
DS
10693 if (attr->tag != 0) {
10694 if (json_paths)
10695 json_object_int_add(json_path, "tag", attr->tag);
10696 else
10697 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10698 }
9df8b37c 10699
05864da7
DS
10700 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10701 if (json_paths)
10702 json_object_boolean_false_add(json_path, "valid");
10703 else
10704 vty_out(vty, ", invalid");
10705 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10706 if (json_paths)
10707 json_object_boolean_true_add(json_path, "valid");
10708 else
10709 vty_out(vty, ", valid");
10710 }
9df8b37c 10711
7d3cae70
DA
10712 if (json_paths)
10713 json_object_int_add(json_path, "version", bn->version);
10714
05864da7
DS
10715 if (path->peer != bgp->peer_self) {
10716 if (path->peer->as == path->peer->local_as) {
10717 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10718 if (json_paths)
10719 json_object_string_add(
10720 json_peer, "type",
10721 "confed-internal");
d62a17ae 10722 else
05864da7 10723 vty_out(vty, ", confed-internal");
d62a17ae 10724 } else {
05864da7
DS
10725 if (json_paths)
10726 json_object_string_add(
10727 json_peer, "type", "internal");
10728 else
10729 vty_out(vty, ", internal");
9df8b37c 10730 }
05864da7
DS
10731 } else {
10732 if (bgp_confederation_peers_check(bgp,
10733 path->peer->as)) {
10734 if (json_paths)
10735 json_object_string_add(
10736 json_peer, "type",
10737 "confed-external");
d62a17ae 10738 else
05864da7 10739 vty_out(vty, ", confed-external");
d62a17ae 10740 } else {
05864da7
DS
10741 if (json_paths)
10742 json_object_string_add(
10743 json_peer, "type", "external");
10744 else
10745 vty_out(vty, ", external");
d62a17ae 10746 }
10747 }
05864da7
DS
10748 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10749 if (json_paths) {
10750 json_object_boolean_true_add(json_path, "aggregated");
10751 json_object_boolean_true_add(json_path, "local");
10752 } else {
10753 vty_out(vty, ", aggregated, local");
10754 }
10755 } else if (path->type != ZEBRA_ROUTE_BGP) {
10756 if (json_paths)
10757 json_object_boolean_true_add(json_path, "sourced");
10758 else
10759 vty_out(vty, ", sourced");
10760 } else {
10761 if (json_paths) {
10762 json_object_boolean_true_add(json_path, "sourced");
10763 json_object_boolean_true_add(json_path, "local");
10764 } else {
10765 vty_out(vty, ", sourced, local");
d62a17ae 10766 }
05864da7 10767 }
718e3744 10768
05864da7 10769 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10770 if (json_paths)
05864da7
DS
10771 json_object_boolean_true_add(json_path,
10772 "atomicAggregate");
d62a17ae 10773 else
05864da7
DS
10774 vty_out(vty, ", atomic-aggregate");
10775 }
d62a17ae 10776
d864dd9e
EB
10777 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10778 if (json_paths)
10779 json_object_int_add(json_path, "otc", attr->otc);
10780 else
10781 vty_out(vty, ", otc %u", attr->otc);
10782 }
10783
05864da7
DS
10784 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10785 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10786 && bgp_path_info_mpath_count(path))) {
10787 if (json_paths)
10788 json_object_boolean_true_add(json_path, "multipath");
10789 else
10790 vty_out(vty, ", multipath");
10791 }
50e05855 10792
05864da7
DS
10793 // Mark the bestpath(s)
10794 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10795 first_as = aspath_get_first_as(attr->aspath);
718e3744 10796
05864da7
DS
10797 if (json_paths) {
10798 if (!json_bestpath)
10799 json_bestpath = json_object_new_object();
10800 json_object_int_add(json_bestpath, "bestpathFromAs",
10801 first_as);
10802 } else {
10803 if (first_as)
10804 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10805 else
05864da7 10806 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10807 }
05864da7 10808 }
718e3744 10809
05864da7
DS
10810 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10811 if (json_paths) {
10812 if (!json_bestpath)
10813 json_bestpath = json_object_new_object();
10814 json_object_boolean_true_add(json_bestpath, "overall");
10815 json_object_string_add(
10816 json_bestpath, "selectionReason",
10817 bgp_path_selection_reason2str(bn->reason));
10818 } else {
10819 vty_out(vty, ", best");
10820 vty_out(vty, " (%s)",
10821 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10822 }
05864da7 10823 }
718e3744 10824
4027d19b 10825 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10826 if (json_paths)
10827 json_object_string_add(
10828 json_path, "rpkiValidationState",
4027d19b 10829 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10830 else
1d327209 10831 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10832 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10833 }
10834
05864da7
DS
10835 if (json_bestpath)
10836 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10837
05864da7
DS
10838 if (!json_paths)
10839 vty_out(vty, "\n");
10840
10841 /* Line 4 display Community */
29e72930 10842 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10843 if (json_paths) {
9a706b42
DA
10844 if (!bgp_attr_get_community(attr)->json)
10845 community_str(bgp_attr_get_community(attr),
c0945b78 10846 true, true);
9a706b42
DA
10847 json_object_lock(bgp_attr_get_community(attr)->json);
10848 json_object_object_add(
10849 json_path, "community",
10850 bgp_attr_get_community(attr)->json);
05864da7
DS
10851 } else {
10852 vty_out(vty, " Community: %s\n",
9a706b42 10853 bgp_attr_get_community(attr)->str);
d62a17ae 10854 }
05864da7 10855 }
718e3744 10856
05864da7
DS
10857 /* Line 5 display Extended-community */
10858 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10859 if (json_paths) {
10860 json_ext_community = json_object_new_object();
b53e67a3
DA
10861 json_object_string_add(
10862 json_ext_community, "string",
10863 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10864 json_object_object_add(json_path, "extendedCommunity",
10865 json_ext_community);
d62a17ae 10866 } else {
05864da7 10867 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10868 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10869 }
05864da7 10870 }
718e3744 10871
05864da7
DS
10872 /* Line 6 display Large community */
10873 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10874 if (json_paths) {
1bcf3a96
DA
10875 if (!bgp_attr_get_lcommunity(attr)->json)
10876 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10877 true, true);
1bcf3a96
DA
10878 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10879 json_object_object_add(
10880 json_path, "largeCommunity",
10881 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10882 } else {
10883 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10884 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10885 }
05864da7 10886 }
718e3744 10887
05864da7
DS
10888 /* Line 7 display Originator, Cluster-id */
10889 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10890 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10891 char buf[BUFSIZ] = {0};
10892
05864da7 10893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10894 if (json_paths)
c949c771
DA
10895 json_object_string_addf(json_path,
10896 "originatorId", "%pI4",
10897 &attr->originator_id);
d62a17ae 10898 else
23d0a753
DA
10899 vty_out(vty, " Originator: %pI4",
10900 &attr->originator_id);
d62a17ae 10901 }
856ca177 10902
05864da7 10903 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10904 struct cluster_list *cluster =
10905 bgp_attr_get_cluster(attr);
05864da7 10906 int i;
d62a17ae 10907
10908 if (json_paths) {
05864da7
DS
10909 json_cluster_list = json_object_new_object();
10910 json_cluster_list_list =
10911 json_object_new_array();
10912
779fee93 10913 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10914 json_string = json_object_new_string(
779fee93
DS
10915 inet_ntop(AF_INET,
10916 &cluster->list[i],
10917 buf, sizeof(buf)));
05864da7
DS
10918 json_object_array_add(
10919 json_cluster_list_list,
10920 json_string);
10921 }
718e3744 10922
05864da7
DS
10923 /*
10924 * struct cluster_list does not have
10925 * "str" variable like aspath and community
10926 * do. Add this someday if someone asks
10927 * for it.
10928 * json_object_string_add(json_cluster_list,
779fee93 10929 * "string", cluster->str);
05864da7
DS
10930 */
10931 json_object_object_add(json_cluster_list,
10932 "list",
10933 json_cluster_list_list);
10934 json_object_object_add(json_path, "clusterList",
10935 json_cluster_list);
0dc8ee70 10936 } else {
05864da7
DS
10937 vty_out(vty, ", Cluster list: ");
10938
779fee93 10939 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10940 vty_out(vty, "%pI4 ",
779fee93 10941 &cluster->list[i]);
05864da7 10942 }
0dc8ee70 10943 }
d62a17ae 10944 }
718e3744 10945
d62a17ae 10946 if (!json_paths)
10947 vty_out(vty, "\n");
05864da7 10948 }
d62a17ae 10949
05864da7 10950 if (path->extra && path->extra->damp_info)
b4f7f45b 10951 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10952
05864da7
DS
10953 /* Remote Label */
10954 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10955 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10956 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10957 &bos);
d62a17ae 10958
05864da7
DS
10959 if (json_paths)
10960 json_object_int_add(json_path, "remoteLabel", label);
10961 else
10962 vty_out(vty, " Remote label: %d\n", label);
10963 }
d62a17ae 10964
e496b420
HS
10965 /* Remote SID */
10966 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 10967 if (json_paths)
07380148
DA
10968 json_object_string_addf(json_path, "remoteSid", "%pI6",
10969 &path->extra->sid[0].sid);
e496b420 10970 else
07380148
DA
10971 vty_out(vty, " Remote SID: %pI6\n",
10972 &path->extra->sid[0].sid);
e496b420
HS
10973 }
10974
05864da7
DS
10975 /* Label Index */
10976 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10977 if (json_paths)
10978 json_object_int_add(json_path, "labelIndex",
10979 attr->label_index);
10980 else
10981 vty_out(vty, " Label Index: %d\n",
10982 attr->label_index);
10983 }
d62a17ae 10984
05864da7
DS
10985 /* Line 8 display Addpath IDs */
10986 if (path->addpath_rx_id
10987 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10988 if (json_paths) {
10989 json_object_int_add(json_path, "addpathRxId",
10990 path->addpath_rx_id);
d62a17ae 10991
05864da7
DS
10992 /* Keep backwards compatibility with the old API
10993 * by putting TX All's ID in the old field
10994 */
10995 json_object_int_add(
10996 json_path, "addpathTxId",
10997 path->tx_addpath
10998 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10999
05864da7
DS
11000 /* ... but create a specific field for each
11001 * strategy
11002 */
11003 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11004 json_object_int_add(
11005 json_path,
11006 bgp_addpath_names(i)->id_json_name,
11007 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11008 }
05864da7
DS
11009 } else {
11010 vty_out(vty, " AddPath ID: RX %u, ",
11011 path->addpath_rx_id);
d62a17ae 11012
05864da7 11013 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11014 }
05864da7 11015 }
520d5d76 11016
05864da7
DS
11017 /* If we used addpath to TX a non-bestpath we need to display
11018 * "Advertised to" on a path-by-path basis
11019 */
11020 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11021 first = 1;
dcc68b5e 11022
05864da7
DS
11023 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11024 addpath_capable =
11025 bgp_addpath_encode_tx(peer, afi, safi);
11026 has_adj = bgp_adj_out_lookup(
11027 peer, path->net,
11028 bgp_addpath_id_for_peer(peer, afi, safi,
11029 &path->tx_addpath));
11030
11031 if ((addpath_capable && has_adj)
11032 || (!addpath_capable && has_adj
11033 && CHECK_FLAG(path->flags,
11034 BGP_PATH_SELECTED))) {
11035 if (json_path && !json_adv_to)
11036 json_adv_to = json_object_new_object();
dcc68b5e 11037
05864da7
DS
11038 route_vty_out_advertised_to(
11039 vty, peer, &first,
11040 " Advertised to:", json_adv_to);
d62a17ae 11041 }
11042 }
718e3744 11043
05864da7
DS
11044 if (json_path) {
11045 if (json_adv_to) {
11046 json_object_object_add(
11047 json_path, "advertisedTo", json_adv_to);
d62a17ae 11048 }
05864da7
DS
11049 } else {
11050 if (!first) {
11051 vty_out(vty, "\n");
d62a17ae 11052 }
11053 }
05864da7 11054 }
b05a1c8b 11055
05864da7 11056 /* Line 9 display Uptime */
083ec940 11057 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11058 if (json_paths) {
11059 json_last_update = json_object_new_object();
11060 json_object_int_add(json_last_update, "epoch", tbuf);
11061 json_object_string_add(json_last_update, "string",
11062 ctime(&tbuf));
11063 json_object_object_add(json_path, "lastUpdate",
11064 json_last_update);
11065 } else
11066 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11067
05864da7
DS
11068 /* Line 10 display PMSI tunnel attribute, if present */
11069 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11070 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11071 bgp_attr_get_pmsi_tnl_type(attr),
11072 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11073
05864da7
DS
11074 if (json_paths) {
11075 json_pmsi = json_object_new_object();
11076 json_object_string_add(json_pmsi, "tunnelType", str);
11077 json_object_int_add(json_pmsi, "label",
11078 label2vni(&attr->label));
11079 json_object_object_add(json_path, "pmsi", json_pmsi);
11080 } else
11081 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11082 str, label2vni(&attr->label));
d62a17ae 11083 }
f1aa5d8a 11084
848e8cf6
DA
11085 if (path->peer->t_gr_restart &&
11086 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11087 unsigned long gr_remaining =
11088 thread_timer_remain_second(path->peer->t_gr_restart);
11089
11090 if (json_paths) {
11091 json_object_int_add(json_path,
11092 "gracefulRestartSecondsRemaining",
11093 gr_remaining);
11094 } else
11095 vty_out(vty,
11096 " Time until Graceful Restart stale route deleted: %lu\n",
11097 gr_remaining);
11098 }
11099
9a706b42
DA
11100 if (path->peer->t_llgr_stale[afi][safi] &&
11101 bgp_attr_get_community(attr) &&
11102 community_include(bgp_attr_get_community(attr),
11103 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11104 unsigned long llgr_remaining = thread_timer_remain_second(
11105 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11106
48ebba04
DA
11107 if (json_paths) {
11108 json_object_int_add(json_path, "llgrSecondsRemaining",
11109 llgr_remaining);
11110 } else
11111 vty_out(vty,
11112 " Time until Long-lived stale route deleted: %lu\n",
11113 llgr_remaining);
11114 }
11115
92269aa2
DS
11116 /* Output some debug about internal state of the dest flags */
11117 if (json_paths) {
11118 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11119 json_object_boolean_true_add(json_path, "processScheduled");
11120 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11121 json_object_boolean_true_add(json_path, "userCleared");
11122 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11123 json_object_boolean_true_add(json_path, "labelChanged");
11124 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11125 json_object_boolean_true_add(json_path, "registeredForLabel");
11126 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11127 json_object_boolean_true_add(json_path, "selectDefered");
11128 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11129 json_object_boolean_true_add(json_path, "fibInstalled");
11130 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11131 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11132
d62a17ae 11133 if (json_nexthop_global || json_nexthop_ll) {
11134 json_nexthops = json_object_new_array();
f1aa5d8a 11135
d62a17ae 11136 if (json_nexthop_global)
11137 json_object_array_add(json_nexthops,
11138 json_nexthop_global);
f1aa5d8a 11139
d62a17ae 11140 if (json_nexthop_ll)
11141 json_object_array_add(json_nexthops,
11142 json_nexthop_ll);
f1aa5d8a 11143
d62a17ae 11144 json_object_object_add(json_path, "nexthops",
11145 json_nexthops);
11146 }
11147
11148 json_object_object_add(json_path, "peer", json_peer);
11149 json_object_array_add(json_paths, json_path);
05864da7 11150 }
b366b518
BB
11151}
11152
96ade3ed 11153#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11154#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11155#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11156
a4d82a8a 11157static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11158 afi_t afi, safi_t safi, enum bgp_show_type type,
11159 bool use_json);
7f323236
DW
11160static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11161 const char *comstr, int exact, afi_t afi,
96c81f66 11162 safi_t safi, uint16_t show_flags);
d62a17ae 11163
1ae44dfc 11164static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11165 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11166 void *output_arg, const char *rd, int is_last,
96f3485c 11167 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11168 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11169 enum rpki_states rpki_target_state)
d62a17ae 11170{
40381db7 11171 struct bgp_path_info *pi;
9bcb3eef 11172 struct bgp_dest *dest;
2aad8c42
MS
11173 bool header = true;
11174 bool json_detail_header = false;
d62a17ae 11175 int display;
1ae44dfc
LB
11176 unsigned long output_count = 0;
11177 unsigned long total_count = 0;
d62a17ae 11178 struct prefix *p;
d62a17ae 11179 json_object *json_paths = NULL;
11180 int first = 1;
96f3485c
MK
11181 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11182 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11183 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
67799a48 11184 bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
509d82bd 11185 bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
d62a17ae 11186
1ae44dfc 11187 if (output_cum && *output_cum != 0)
2aad8c42 11188 header = false;
1ae44dfc 11189
9386b588 11190 if (use_json && !*json_header_depth) {
96f3485c
MK
11191 if (all)
11192 *json_header_depth = 1;
11193 else {
11194 vty_out(vty, "{\n");
11195 *json_header_depth = 2;
11196 }
11197
d62a17ae 11198 vty_out(vty,
23d0a753
DA
11199 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11200 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11201 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11202 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11203 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11204 ? VRF_DEFAULT_NAME
11205 : bgp->name,
11206 table->version, &bgp->router_id,
01eced22 11207 bgp->default_local_pref, bgp->as);
9386b588 11208 if (rd) {
445c2480 11209 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11210 ++*json_header_depth;
11211 }
d62a17ae 11212 }
718e3744 11213
445c2480
DS
11214 if (use_json && rd) {
11215 vty_out(vty, " \"%s\" : { ", rd);
11216 }
11217
2aad8c42 11218 /* Check for 'json detail', where we need header output once per dest */
67799a48 11219 if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
2aad8c42
MS
11220 type != bgp_show_type_damp_neighbor &&
11221 type != bgp_show_type_flap_statistics &&
11222 type != bgp_show_type_flap_neighbor)
11223 json_detail_header = true;
11224
d62a17ae 11225 /* Start processing of routes. */
9bcb3eef
DS
11226 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11227 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11228 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11229 bool json_detail = json_detail_header;
b54892e0 11230
9bcb3eef 11231 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11232 if (pi == NULL)
98ce9a06 11233 continue;
d62a17ae 11234
98ce9a06 11235 display = 0;
98ce9a06
DS
11236 if (use_json)
11237 json_paths = json_object_new_array();
11238 else
11239 json_paths = NULL;
d62a17ae 11240
6f94b685 11241 for (; pi; pi = pi->next) {
9a706b42
DA
11242 struct community *picomm = NULL;
11243
11244 picomm = bgp_attr_get_community(pi->attr);
11245
98ce9a06 11246 total_count++;
1e2ce4f1 11247
7d3cae70
DA
11248 if (type == bgp_show_type_prefix_version) {
11249 uint32_t version =
11250 strtoul(output_arg, NULL, 10);
11251 if (dest->version < version)
11252 continue;
11253 }
11254
a70a28a5
DA
11255 if (type == bgp_show_type_community_alias) {
11256 char *alias = output_arg;
11257 char **communities;
11258 int num;
11259 bool found = false;
11260
9a706b42
DA
11261 if (picomm) {
11262 frrstr_split(picomm->str, " ",
11263 &communities, &num);
a70a28a5
DA
11264 for (int i = 0; i < num; i++) {
11265 const char *com2alias =
11266 bgp_community2alias(
11267 communities[i]);
cd9cc0e6
IR
11268 if (!found
11269 && strcmp(alias, com2alias)
11270 == 0)
a70a28a5 11271 found = true;
cd9cc0e6
IR
11272 XFREE(MTYPE_TMP,
11273 communities[i]);
a70a28a5 11274 }
cd9cc0e6 11275 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11276 }
11277
1bcf3a96
DA
11278 if (!found &&
11279 bgp_attr_get_lcommunity(pi->attr)) {
11280 frrstr_split(bgp_attr_get_lcommunity(
11281 pi->attr)
11282 ->str,
a70a28a5
DA
11283 " ", &communities, &num);
11284 for (int i = 0; i < num; i++) {
11285 const char *com2alias =
11286 bgp_community2alias(
11287 communities[i]);
cd9cc0e6
IR
11288 if (!found
11289 && strcmp(alias, com2alias)
11290 == 0)
a70a28a5 11291 found = true;
cd9cc0e6
IR
11292 XFREE(MTYPE_TMP,
11293 communities[i]);
a70a28a5 11294 }
cd9cc0e6 11295 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11296 }
11297
11298 if (!found)
11299 continue;
11300 }
11301
1e2ce4f1
DS
11302 if (type == bgp_show_type_rpki) {
11303 if (dest_p->family == AF_INET
11304 || dest_p->family == AF_INET6)
4027d19b 11305 rpki_curr_state = hook_call(
1e2ce4f1
DS
11306 bgp_rpki_prefix_status,
11307 pi->peer, pi->attr, dest_p);
4027d19b
DS
11308 if (rpki_target_state != RPKI_NOT_BEING_USED
11309 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11310 continue;
11311 }
11312
98ce9a06
DS
11313 if (type == bgp_show_type_flap_statistics
11314 || type == bgp_show_type_flap_neighbor
11315 || type == bgp_show_type_dampend_paths
11316 || type == bgp_show_type_damp_neighbor) {
40381db7 11317 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11318 continue;
11319 }
11320 if (type == bgp_show_type_regexp) {
11321 regex_t *regex = output_arg;
d62a17ae 11322
40381db7 11323 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11324 == REG_NOMATCH)
11325 continue;
11326 }
11327 if (type == bgp_show_type_prefix_list) {
11328 struct prefix_list *plist = output_arg;
d62a17ae 11329
9bcb3eef 11330 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11331 != PREFIX_PERMIT)
11332 continue;
11333 }
ed126382
DA
11334 if (type == bgp_show_type_access_list) {
11335 struct access_list *alist = output_arg;
11336
11337 if (access_list_apply(alist, dest_p) !=
11338 FILTER_PERMIT)
11339 continue;
11340 }
98ce9a06
DS
11341 if (type == bgp_show_type_filter_list) {
11342 struct as_list *as_list = output_arg;
d62a17ae 11343
40381db7 11344 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11345 != AS_FILTER_PERMIT)
11346 continue;
11347 }
11348 if (type == bgp_show_type_route_map) {
11349 struct route_map *rmap = output_arg;
9b6d8fcf 11350 struct bgp_path_info path;
636632c3
DA
11351 struct bgp_path_info_extra extra;
11352 struct attr dummy_attr = {};
b68885f9 11353 route_map_result_t ret;
d62a17ae 11354
6f4f49b2 11355 dummy_attr = *pi->attr;
d62a17ae 11356
636632c3
DA
11357 prep_for_rmap_apply(&path, &extra, dest, pi,
11358 pi->peer, &dummy_attr);
d62a17ae 11359
1782514f 11360 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11361 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11362 if (ret == RMAP_DENYMATCH)
11363 continue;
11364 }
11365 if (type == bgp_show_type_neighbor
11366 || type == bgp_show_type_flap_neighbor
11367 || type == bgp_show_type_damp_neighbor) {
11368 union sockunion *su = output_arg;
11369
40381db7
DS
11370 if (pi->peer == NULL
11371 || pi->peer->su_remote == NULL
11372 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11373 continue;
11374 }
11375 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11376 uint32_t destination;
d62a17ae 11377
9bcb3eef 11378 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11379 if (IN_CLASSC(destination)
9bcb3eef 11380 && dest_p->prefixlen == 24)
98ce9a06
DS
11381 continue;
11382 if (IN_CLASSB(destination)
9bcb3eef 11383 && dest_p->prefixlen == 16)
98ce9a06
DS
11384 continue;
11385 if (IN_CLASSA(destination)
9bcb3eef 11386 && dest_p->prefixlen == 8)
98ce9a06
DS
11387 continue;
11388 }
11389 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11390 p = output_arg;
9bcb3eef 11391 if (!prefix_match(p, dest_p))
98ce9a06
DS
11392 continue;
11393 }
11394 if (type == bgp_show_type_community_all) {
9a706b42 11395 if (!picomm)
98ce9a06
DS
11396 continue;
11397 }
11398 if (type == bgp_show_type_community) {
11399 struct community *com = output_arg;
d62a17ae 11400
9a706b42 11401 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11402 continue;
11403 }
11404 if (type == bgp_show_type_community_exact) {
11405 struct community *com = output_arg;
d62a17ae 11406
9a706b42 11407 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11408 continue;
11409 }
11410 if (type == bgp_show_type_community_list) {
11411 struct community_list *list = output_arg;
d62a17ae 11412
9a706b42 11413 if (!community_list_match(picomm, list))
98ce9a06
DS
11414 continue;
11415 }
a4d82a8a 11416 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11417 struct community_list *list = output_arg;
d62a17ae 11418
9a706b42 11419 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11420 continue;
11421 }
11422 if (type == bgp_show_type_lcommunity) {
11423 struct lcommunity *lcom = output_arg;
d62a17ae 11424
1bcf3a96
DA
11425 if (!bgp_attr_get_lcommunity(pi->attr) ||
11426 !lcommunity_match(
11427 bgp_attr_get_lcommunity(pi->attr),
11428 lcom))
98ce9a06
DS
11429 continue;
11430 }
36a206db 11431
11432 if (type == bgp_show_type_lcommunity_exact) {
11433 struct lcommunity *lcom = output_arg;
11434
1bcf3a96
DA
11435 if (!bgp_attr_get_lcommunity(pi->attr) ||
11436 !lcommunity_cmp(
11437 bgp_attr_get_lcommunity(pi->attr),
11438 lcom))
36a206db 11439 continue;
11440 }
98ce9a06
DS
11441 if (type == bgp_show_type_lcommunity_list) {
11442 struct community_list *list = output_arg;
d62a17ae 11443
1bcf3a96
DA
11444 if (!lcommunity_list_match(
11445 bgp_attr_get_lcommunity(pi->attr),
11446 list))
98ce9a06
DS
11447 continue;
11448 }
36a206db 11449 if (type
11450 == bgp_show_type_lcommunity_list_exact) {
11451 struct community_list *list = output_arg;
11452
11453 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11454 bgp_attr_get_lcommunity(pi->attr),
11455 list))
36a206db 11456 continue;
11457 }
98ce9a06 11458 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11459 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11460 continue;
11461 }
11462 if (type == bgp_show_type_dampend_paths
11463 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11464 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11465 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11466 continue;
11467 }
11468
11469 if (!use_json && header) {
23d0a753
DA
11470 vty_out(vty,
11471 "BGP table version is %" PRIu64
11472 ", local router ID is %pI4, vrf id ",
11473 table->version, &bgp->router_id);
9df8b37c
PZ
11474 if (bgp->vrf_id == VRF_UNKNOWN)
11475 vty_out(vty, "%s", VRFID_NONE_STR);
11476 else
11477 vty_out(vty, "%u", bgp->vrf_id);
11478 vty_out(vty, "\n");
01eced22
AD
11479 vty_out(vty, "Default local pref %u, ",
11480 bgp->default_local_pref);
11481 vty_out(vty, "local AS %u\n", bgp->as);
509d82bd 11482 if (!detail_routes) {
9a1aae2d
DA
11483 vty_out(vty, BGP_SHOW_SCODE_HEADER);
11484 vty_out(vty, BGP_SHOW_NCODE_HEADER);
11485 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11486 vty_out(vty, BGP_SHOW_RPKI_HEADER);
11487 }
d62a17ae 11488 if (type == bgp_show_type_dampend_paths
11489 || type == bgp_show_type_damp_neighbor)
98ce9a06 11490 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11491 else if (type == bgp_show_type_flap_statistics
11492 || type == bgp_show_type_flap_neighbor)
98ce9a06 11493 vty_out(vty, BGP_SHOW_FLAP_HEADER);
509d82bd 11494 else if (!detail_routes)
ae248832
MK
11495 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11496 : BGP_SHOW_HEADER));
2aad8c42
MS
11497 header = false;
11498
11499 } else if (json_detail && json_paths != NULL) {
11500 const struct prefix_rd *prd;
11501 json_object *jtemp;
11502
11503 /* Use common detail header, for most types;
11504 * need a json 'object'.
11505 */
11506
11507 jtemp = json_object_new_object();
11508 prd = bgp_rd_from_dest(dest, safi);
11509
11510 route_vty_out_detail_header(
34c7f35f
SW
11511 vty, bgp, dest,
11512 bgp_dest_get_prefix(dest), prd,
11513 table->afi, safi, jtemp);
2aad8c42
MS
11514
11515 json_object_array_add(json_paths, jtemp);
11516
11517 json_detail = false;
d62a17ae 11518 }
2aad8c42 11519
98ce9a06
DS
11520 if (rd != NULL && !display && !output_count) {
11521 if (!use_json)
11522 vty_out(vty,
11523 "Route Distinguisher: %s\n",
11524 rd);
d62a17ae 11525 }
98ce9a06
DS
11526 if (type == bgp_show_type_dampend_paths
11527 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11528 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11529 AFI_IP, safi, use_json,
11530 json_paths);
98ce9a06
DS
11531 else if (type == bgp_show_type_flap_statistics
11532 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11533 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11534 AFI_IP, safi, use_json,
11535 json_paths);
f280c93b 11536 else {
27bb782a
DA
11537 if (detail_routes || detail_json) {
11538 const struct prefix_rd *prd = NULL;
9a1aae2d 11539
27bb782a
DA
11540 if (dest->pdest)
11541 prd = bgp_rd_from_dest(
11542 dest->pdest, safi);
9a1aae2d
DA
11543
11544 if (!use_json)
11545 route_vty_out_detail_header(
11546 vty, bgp, dest,
11547 bgp_dest_get_prefix(
11548 dest),
11549 prd, table->afi, safi,
11550 NULL);
11551
f280c93b 11552 route_vty_out_detail(
27bb782a 11553 vty, bgp, dest, dest_p, pi,
f280c93b
DA
11554 family2afi(dest_p->family),
11555 safi, RPKI_NOT_BEING_USED,
11556 json_paths);
9a1aae2d 11557 } else {
f280c93b
DA
11558 route_vty_out(vty, dest_p, pi, display,
11559 safi, json_paths, wide);
9a1aae2d 11560 }
f280c93b 11561 }
98ce9a06 11562 display++;
d62a17ae 11563 }
11564
98ce9a06
DS
11565 if (display) {
11566 output_count++;
11567 if (!use_json)
11568 continue;
11569
625d2931 11570 /* encode prefix */
9bcb3eef 11571 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11572 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11573
1840384b 11574
b54892e0
DS
11575 bgp_fs_nlri_get_string(
11576 (unsigned char *)
9bcb3eef
DS
11577 dest_p->u.prefix_flowspec.ptr,
11578 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11579 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11580 family2afi(dest_p->u
11581 .prefix_flowspec.family));
625d2931 11582 if (first)
b54892e0 11583 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11584 dest_p->u.prefix_flowspec
b54892e0 11585 .prefixlen);
625d2931 11586 else
b54892e0 11587 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11588 dest_p->u.prefix_flowspec
b54892e0 11589 .prefixlen);
625d2931 11590 } else {
625d2931 11591 if (first)
1b78780b 11592 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11593 else
1b78780b 11594 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11595 }
3757f964 11596 vty_json(vty, json_paths);
449feb8e 11597 json_paths = NULL;
98ce9a06 11598 first = 0;
1f83ed02
DS
11599 } else
11600 json_object_free(json_paths);
98ce9a06
DS
11601 }
11602
1ae44dfc
LB
11603 if (output_cum) {
11604 output_count += *output_cum;
11605 *output_cum = output_count;
11606 }
11607 if (total_cum) {
11608 total_count += *total_cum;
11609 *total_cum = total_count;
11610 }
d62a17ae 11611 if (use_json) {
9386b588 11612 if (rd) {
a4d82a8a 11613 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11614 }
11615 if (is_last) {
a4d82a8a
PZ
11616 unsigned long i;
11617 for (i = 0; i < *json_header_depth; ++i)
11618 vty_out(vty, " } ");
96f3485c
MK
11619 if (!all)
11620 vty_out(vty, "\n");
9386b588 11621 }
d62a17ae 11622 } else {
1ae44dfc
LB
11623 if (is_last) {
11624 /* No route is displayed */
11625 if (output_count == 0) {
11626 if (type == bgp_show_type_normal)
11627 vty_out(vty,
11628 "No BGP prefixes displayed, %ld exist\n",
11629 total_count);
11630 } else
d62a17ae 11631 vty_out(vty,
1ae44dfc
LB
11632 "\nDisplayed %ld routes and %ld total paths\n",
11633 output_count, total_count);
11634 }
d62a17ae 11635 }
718e3744 11636
d62a17ae 11637 return CMD_SUCCESS;
718e3744 11638}
11639
1ae44dfc
LB
11640int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11641 struct bgp_table *table, struct prefix_rd *prd_match,
27bb782a
DA
11642 enum bgp_show_type type, void *output_arg,
11643 uint16_t show_flags)
1ae44dfc 11644{
9bcb3eef 11645 struct bgp_dest *dest, *next;
1ae44dfc
LB
11646 unsigned long output_cum = 0;
11647 unsigned long total_cum = 0;
9386b588 11648 unsigned long json_header_depth = 0;
67009e22 11649 struct bgp_table *itable;
0136788c 11650 bool show_msg;
27bb782a 11651 bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0136788c
LB
11652
11653 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11654
9bcb3eef
DS
11655 for (dest = bgp_table_top(table); dest; dest = next) {
11656 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11657
9bcb3eef
DS
11658 next = bgp_route_next(dest);
11659 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11660 continue;
67009e22 11661
9bcb3eef 11662 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11663 if (itable != NULL) {
1ae44dfc 11664 struct prefix_rd prd;
06b9f471 11665 char rd[RD_ADDRSTRLEN];
1ae44dfc 11666
9bcb3eef 11667 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11668 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11669 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11670 rd, next == NULL, &output_cum,
11671 &total_cum, &json_header_depth,
1e2ce4f1 11672 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11673 if (next == NULL)
11674 show_msg = false;
1ae44dfc
LB
11675 }
11676 }
0136788c
LB
11677 if (show_msg) {
11678 if (output_cum == 0)
11679 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11680 total_cum);
11681 else
11682 vty_out(vty,
11683 "\nDisplayed %ld routes and %ld total paths\n",
11684 output_cum, total_cum);
0224b329
DA
11685 } else {
11686 if (use_json && output_cum == 0)
11687 vty_out(vty, "{}\n");
0136788c 11688 }
1ae44dfc
LB
11689 return CMD_SUCCESS;
11690}
2aad8c42 11691
d62a17ae 11692static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11693 enum bgp_show_type type, void *output_arg,
96c81f66 11694 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11695{
d62a17ae 11696 struct bgp_table *table;
9386b588 11697 unsigned long json_header_depth = 0;
96f3485c 11698 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11699
d62a17ae 11700 if (bgp == NULL) {
11701 bgp = bgp_get_default();
11702 }
fee0f4c6 11703
d62a17ae 11704 if (bgp == NULL) {
11705 if (!use_json)
11706 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11707 else
11708 vty_out(vty, "{}\n");
d62a17ae 11709 return CMD_WARNING;
11710 }
4dd6177e 11711
cd8c2a27
MS
11712 /* Labeled-unicast routes live in the unicast table. */
11713 if (safi == SAFI_LABELED_UNICAST)
11714 safi = SAFI_UNICAST;
11715
1ae44dfc 11716 table = bgp->rib[afi][safi];
d62a17ae 11717 /* use MPLS and ENCAP specific shows until they are merged */
11718 if (safi == SAFI_MPLS_VPN) {
1ae44dfc 11719 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
27bb782a 11720 output_arg, show_flags);
d62a17ae 11721 }
dba3c1d3
PG
11722
11723 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11724 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11725 output_arg, use_json,
11726 1, NULL, NULL);
11727 }
fee0f4c6 11728
0adc5bbb
LS
11729 if (safi == SAFI_EVPN)
11730 return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11731
96f3485c 11732 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11733 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11734 rpki_target_state);
fee0f4c6 11735}
11736
d62a17ae 11737static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11738 safi_t safi, uint16_t show_flags)
f186de26 11739{
d62a17ae 11740 struct listnode *node, *nnode;
11741 struct bgp *bgp;
11742 int is_first = 1;
9f049418 11743 bool route_output = false;
96f3485c 11744 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11745
d62a17ae 11746 if (use_json)
11747 vty_out(vty, "{\n");
9f689658 11748
d62a17ae 11749 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11750 route_output = true;
d62a17ae 11751 if (use_json) {
11752 if (!is_first)
11753 vty_out(vty, ",\n");
11754 else
11755 is_first = 0;
11756
11757 vty_out(vty, "\"%s\":",
11758 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11759 ? VRF_DEFAULT_NAME
d62a17ae 11760 : bgp->name);
11761 } else {
11762 vty_out(vty, "\nInstance %s:\n",
11763 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11764 ? VRF_DEFAULT_NAME
d62a17ae 11765 : bgp->name);
11766 }
11767 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11768 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11769 }
9f689658 11770
d62a17ae 11771 if (use_json)
11772 vty_out(vty, "}\n");
9f049418
DS
11773 else if (!route_output)
11774 vty_out(vty, "%% BGP instance not found\n");
f186de26 11775}
11776
718e3744 11777/* Header of detailed BGP route information */
d62a17ae 11778void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11779 struct bgp_dest *dest, const struct prefix *p,
11780 const struct prefix_rd *prd, afi_t afi,
11781 safi_t safi, json_object *json)
d62a17ae 11782{
40381db7 11783 struct bgp_path_info *pi;
d62a17ae 11784 struct peer *peer;
11785 struct listnode *node, *nnode;
06b9f471 11786 char buf1[RD_ADDRSTRLEN];
d62a17ae 11787 int count = 0;
11788 int best = 0;
11789 int suppress = 0;
c5f1e1b2
C
11790 int accept_own = 0;
11791 int route_filter_translated_v4 = 0;
11792 int route_filter_v4 = 0;
11793 int route_filter_translated_v6 = 0;
11794 int route_filter_v6 = 0;
11795 int llgr_stale = 0;
11796 int no_llgr = 0;
11797 int accept_own_nexthop = 0;
11798 int blackhole = 0;
d62a17ae 11799 int no_export = 0;
11800 int no_advertise = 0;
11801 int local_as = 0;
c5f1e1b2 11802 int no_peer = 0;
d62a17ae 11803 int first = 1;
11804 int has_valid_label = 0;
11805 mpls_label_t label = 0;
11806 json_object *json_adv_to = NULL;
67f67ba4
DA
11807 uint32_t ttl = 0;
11808 uint32_t bos = 0;
11809 uint32_t exp = 0;
9bedbb1e 11810
67f67ba4 11811 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11812
67f67ba4 11813 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11814
44c69747 11815 if (safi == SAFI_EVPN) {
44c69747 11816 if (!json) {
2dbe669b 11817 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11818 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11819 : "",
2dbe669b 11820 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11821 } else {
11822 json_object_string_add(json, "rd",
11823 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11824 "");
11825 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11826 }
11827 } else {
11828 if (!json) {
9119ef3a
DA
11829 vty_out(vty,
11830 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11831 "\n",
d62a17ae 11832 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11833 ? prefix_rd2str(prd, buf1,
11834 sizeof(buf1))
11835 : ""),
9119ef3a
DA
11836 safi == SAFI_MPLS_VPN ? ":" : "", p,
11837 dest->version);
cd1964ff 11838
9119ef3a 11839 } else {
67d7e256 11840 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11841 json_object_int_add(json, "version", dest->version);
11842
11843 }
44c69747
LK
11844 }
11845
11846 if (has_valid_label) {
11847 if (json)
11848 json_object_int_add(json, "localLabel", label);
11849 else
d62a17ae 11850 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11851 }
11852
11853 if (!json)
d62a17ae 11854 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11855 vty_out(vty, "not allocated\n");
718e3744 11856
9bcb3eef 11857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11858 struct community *picomm = NULL;
11859
11860 picomm = bgp_attr_get_community(pi->attr);
11861
d62a17ae 11862 count++;
40381db7 11863 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11864 best = count;
4056a5f6 11865 if (bgp_path_suppressed(pi))
d62a17ae 11866 suppress = 1;
cee9c031 11867
9a706b42 11868 if (!picomm)
cee9c031
QY
11869 continue;
11870
11871 no_advertise += community_include(
9a706b42
DA
11872 picomm, COMMUNITY_NO_ADVERTISE);
11873 no_export +=
11874 community_include(picomm, COMMUNITY_NO_EXPORT);
11875 local_as +=
11876 community_include(picomm, COMMUNITY_LOCAL_AS);
11877 accept_own +=
11878 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11879 route_filter_translated_v4 += community_include(
9a706b42 11880 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11881 route_filter_translated_v6 += community_include(
9a706b42 11882 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11883 route_filter_v4 += community_include(
9a706b42 11884 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11885 route_filter_v6 += community_include(
9a706b42
DA
11886 picomm, COMMUNITY_ROUTE_FILTER_v6);
11887 llgr_stale +=
11888 community_include(picomm, COMMUNITY_LLGR_STALE);
11889 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11890 accept_own_nexthop += community_include(
11891 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11892 blackhole +=
11893 community_include(picomm, COMMUNITY_BLACKHOLE);
11894 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11895 }
718e3744 11896 }
718e3744 11897
d62a17ae 11898 if (!json) {
11899 vty_out(vty, "Paths: (%d available", count);
11900 if (best) {
11901 vty_out(vty, ", best #%d", best);
b84060bb
PG
11902 if (safi == SAFI_UNICAST) {
11903 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11904 vty_out(vty, ", table %s",
11905 VRF_DEFAULT_NAME);
11906 else
11907 vty_out(vty, ", vrf %s",
11908 bgp->name);
11909 }
d62a17ae 11910 } else
11911 vty_out(vty, ", no best path");
11912
c5f1e1b2
C
11913 if (accept_own)
11914 vty_out(vty,
11915 ", accept own local route exported and imported in different VRF");
11916 else if (route_filter_translated_v4)
11917 vty_out(vty,
11918 ", mark translated RTs for VPNv4 route filtering");
11919 else if (route_filter_v4)
11920 vty_out(vty,
11921 ", attach RT as-is for VPNv4 route filtering");
11922 else if (route_filter_translated_v6)
11923 vty_out(vty,
11924 ", mark translated RTs for VPNv6 route filtering");
11925 else if (route_filter_v6)
11926 vty_out(vty,
11927 ", attach RT as-is for VPNv6 route filtering");
11928 else if (llgr_stale)
11929 vty_out(vty,
1479ed2f 11930 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11931 else if (no_llgr)
11932 vty_out(vty,
11933 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11934 else if (accept_own_nexthop)
11935 vty_out(vty,
11936 ", accept local nexthop");
11937 else if (blackhole)
11938 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11939 else if (no_export)
11940 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11941 else if (no_advertise)
11942 vty_out(vty, ", not advertised to any peer");
d62a17ae 11943 else if (local_as)
11944 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11945 else if (no_peer)
11946 vty_out(vty,
11947 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11948
11949 if (suppress)
11950 vty_out(vty,
11951 ", Advertisements suppressed by an aggregate.");
11952 vty_out(vty, ")\n");
11953 }
718e3744 11954
d62a17ae 11955 /* If we are not using addpath then we can display Advertised to and
11956 * that will
11957 * show what peers we advertised the bestpath to. If we are using
11958 * addpath
11959 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11960 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11961 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11962 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11963 if (json && !json_adv_to)
11964 json_adv_to = json_object_new_object();
11965
11966 route_vty_out_advertised_to(
11967 vty, peer, &first,
11968 " Advertised to non peer-group peers:\n ",
11969 json_adv_to);
11970 }
11971 }
11972
11973 if (json) {
11974 if (json_adv_to) {
11975 json_object_object_add(json, "advertisedTo",
11976 json_adv_to);
11977 }
11978 } else {
11979 if (first)
11980 vty_out(vty, " Not advertised to any peer");
11981 vty_out(vty, "\n");
11982 }
11983 }
718e3744 11984}
11985
edfee30d 11986static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11987 struct bgp_dest *bgp_node, struct vty *vty,
11988 struct bgp *bgp, afi_t afi, safi_t safi,
11989 json_object *json, enum bgp_path_type pathtype,
4027d19b 11990 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11991{
11992 struct bgp_path_info *pi;
11993 int header = 1;
44c69747
LK
11994 json_object *json_header = NULL;
11995 json_object *json_paths = NULL;
4933eaaf 11996 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11997
9bcb3eef 11998 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11999 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12000
12001 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12002 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12003 pi->peer, pi->attr, p);
4933eaaf 12004
4027d19b
DS
12005 if (rpki_target_state != RPKI_NOT_BEING_USED
12006 && rpki_curr_state != rpki_target_state)
4933eaaf 12007 continue;
44c69747
LK
12008
12009 if (json && !json_paths) {
12010 /* Instantiate json_paths only if path is valid */
12011 json_paths = json_object_new_array();
c4f64ea9 12012 if (pfx_rd)
44c69747 12013 json_header = json_object_new_object();
c4f64ea9 12014 else
44c69747
LK
12015 json_header = json;
12016 }
12017
12018 if (header) {
12019 route_vty_out_detail_header(
34c7f35f
SW
12020 vty, bgp, bgp_node,
12021 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12022 safi, json_header);
44c69747
LK
12023 header = 0;
12024 }
12025 (*display)++;
12026
12027 if (pathtype == BGP_PATH_SHOW_ALL
12028 || (pathtype == BGP_PATH_SHOW_BESTPATH
12029 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12030 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12031 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12032 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12033 route_vty_out_detail(vty, bgp, bgp_node,
12034 bgp_dest_get_prefix(bgp_node), pi,
12035 AFI_IP, safi, rpki_curr_state,
12036 json_paths);
44c69747
LK
12037 }
12038
12039 if (json && json_paths) {
12040 json_object_object_add(json_header, "paths", json_paths);
12041
12042 if (pfx_rd)
c4f64ea9
DA
12043 json_object_object_addf(json, json_header, "%pRD",
12044 pfx_rd);
44c69747
LK
12045 }
12046}
12047
2aad8c42
MS
12048/*
12049 * Return rd based on safi
12050 */
46dbf9d0
DA
12051const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12052 safi_t safi)
2aad8c42
MS
12053{
12054 switch (safi) {
12055 case SAFI_MPLS_VPN:
12056 case SAFI_ENCAP:
12057 case SAFI_EVPN:
12058 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12059 default:
12060 return NULL;
2aad8c42
MS
12061 }
12062}
12063
718e3744 12064/* Display specified route of BGP table. */
d62a17ae 12065static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12066 struct bgp_table *rib, const char *ip_str,
12067 afi_t afi, safi_t safi,
4027d19b 12068 enum rpki_states rpki_target_state,
d62a17ae 12069 struct prefix_rd *prd, int prefix_check,
9f049418 12070 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12071{
12072 int ret;
d62a17ae 12073 int display = 0;
12074 struct prefix match;
9bcb3eef
DS
12075 struct bgp_dest *dest;
12076 struct bgp_dest *rm;
d62a17ae 12077 struct bgp_table *table;
12078 json_object *json = NULL;
12079 json_object *json_paths = NULL;
12080
12081 /* Check IP address argument. */
12082 ret = str2prefix(ip_str, &match);
12083 if (!ret) {
12084 vty_out(vty, "address is malformed\n");
12085 return CMD_WARNING;
12086 }
718e3744 12087
d62a17ae 12088 match.family = afi2family(afi);
b05a1c8b 12089
44c69747 12090 if (use_json)
d62a17ae 12091 json = json_object_new_object();
718e3744 12092
44c69747 12093 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12094 for (dest = bgp_table_top(rib); dest;
12095 dest = bgp_route_next(dest)) {
12096 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12097
9bcb3eef 12098 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12099 continue;
9bcb3eef 12100 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12101 if (!table)
ea47320b 12102 continue;
d62a17ae 12103
4953391b
DA
12104 rm = bgp_node_match(table, &match);
12105 if (rm == NULL)
ea47320b 12106 continue;
d62a17ae 12107
9bcb3eef 12108 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12109 if (prefix_check
b54892e0 12110 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12111 bgp_dest_unlock_node(rm);
ea47320b
DL
12112 continue;
12113 }
d62a17ae 12114
9bcb3eef 12115 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12116 bgp, afi, safi, json, pathtype,
4027d19b 12117 &display, rpki_target_state);
44c69747 12118
9bcb3eef 12119 bgp_dest_unlock_node(rm);
44c69747
LK
12120 }
12121 } else if (safi == SAFI_EVPN) {
9bcb3eef 12122 struct bgp_dest *longest_pfx;
cded3b72 12123 bool is_exact_pfxlen_match = false;
44c69747 12124
9bcb3eef
DS
12125 for (dest = bgp_table_top(rib); dest;
12126 dest = bgp_route_next(dest)) {
12127 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12128
9bcb3eef 12129 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12130 continue;
9bcb3eef 12131 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12132 if (!table)
12133 continue;
12134
12135 longest_pfx = NULL;
cded3b72 12136 is_exact_pfxlen_match = false;
44c69747
LK
12137 /*
12138 * Search through all the prefixes for a match. The
12139 * pfx's are enumerated in ascending order of pfxlens.
12140 * So, the last pfx match is the longest match. Set
12141 * is_exact_pfxlen_match when we get exact pfxlen match
12142 */
12143 for (rm = bgp_table_top(table); rm;
12144 rm = bgp_route_next(rm)) {
b54892e0 12145 const struct prefix *rm_p =
9bcb3eef 12146 bgp_dest_get_prefix(rm);
44c69747
LK
12147 /*
12148 * Get prefixlen of the ip-prefix within type5
12149 * evpn route
12150 */
b54892e0
DS
12151 if (evpn_type5_prefix_match(rm_p, &match)
12152 && rm->info) {
44c69747
LK
12153 longest_pfx = rm;
12154 int type5_pfxlen =
b54892e0
DS
12155 bgp_evpn_get_type5_prefixlen(
12156 rm_p);
44c69747 12157 if (type5_pfxlen == match.prefixlen) {
cded3b72 12158 is_exact_pfxlen_match = true;
9bcb3eef 12159 bgp_dest_unlock_node(rm);
44c69747
LK
12160 break;
12161 }
d62a17ae 12162 }
12163 }
ea47320b 12164
44c69747
LK
12165 if (!longest_pfx)
12166 continue;
12167
12168 if (prefix_check && !is_exact_pfxlen_match)
12169 continue;
12170
12171 rm = longest_pfx;
9bcb3eef 12172 bgp_dest_lock_node(rm);
44c69747 12173
9bcb3eef 12174 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12175 bgp, afi, safi, json, pathtype,
4027d19b 12176 &display, rpki_target_state);
44c69747 12177
9bcb3eef 12178 bgp_dest_unlock_node(rm);
d62a17ae 12179 }
98a9dbc7 12180 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12181 if (use_json)
12182 json_paths = json_object_new_array();
12183
63a0b7a9
PG
12184 display = bgp_flowspec_display_match_per_ip(afi, rib,
12185 &match, prefix_check,
12186 vty,
12187 use_json,
12188 json_paths);
d5f20468
SP
12189 if (use_json) {
12190 if (display)
12191 json_object_object_add(json, "paths",
12192 json_paths);
12193 else
12194 json_object_free(json_paths);
12195 }
d62a17ae 12196 } else {
4953391b
DA
12197 dest = bgp_node_match(rib, &match);
12198 if (dest != NULL) {
9bcb3eef 12199 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12200 if (!prefix_check
9bcb3eef
DS
12201 || dest_p->prefixlen == match.prefixlen) {
12202 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12203 safi, json, pathtype,
4027d19b 12204 &display, rpki_target_state);
d62a17ae 12205 }
12206
9bcb3eef 12207 bgp_dest_unlock_node(dest);
d62a17ae 12208 }
12209 }
e5eee9af 12210
d62a17ae 12211 if (use_json) {
75eeda93 12212 vty_json(vty, json);
d62a17ae 12213 } else {
12214 if (!display) {
12215 vty_out(vty, "%% Network not in table\n");
12216 return CMD_WARNING;
12217 }
12218 }
b05a1c8b 12219
d62a17ae 12220 return CMD_SUCCESS;
718e3744 12221}
12222
fee0f4c6 12223/* Display specified route of Main RIB */
d62a17ae 12224static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12225 afi_t afi, safi_t safi, struct prefix_rd *prd,
12226 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12227 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12228{
9b86009a 12229 if (!bgp) {
d62a17ae 12230 bgp = bgp_get_default();
9b86009a
RW
12231 if (!bgp) {
12232 if (!use_json)
12233 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12234 else
12235 vty_out(vty, "{}\n");
9b86009a
RW
12236 return CMD_WARNING;
12237 }
12238 }
d62a17ae 12239
12240 /* labeled-unicast routes live in the unicast table */
12241 if (safi == SAFI_LABELED_UNICAST)
12242 safi = SAFI_UNICAST;
12243
12244 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12245 afi, safi, rpki_target_state, prd,
8aa22bbb 12246 prefix_check, pathtype, use_json);
d62a17ae 12247}
12248
12249static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12250 struct cmd_token **argv, bool exact, afi_t afi,
12251 safi_t safi, bool uj)
d62a17ae 12252{
12253 struct lcommunity *lcom;
12254 struct buffer *b;
12255 int i;
12256 char *str;
12257 int first = 0;
96c81f66 12258 uint16_t show_flags = 0;
4f28b2b5 12259 int ret;
96f3485c
MK
12260
12261 if (uj)
12262 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12263
12264 b = buffer_new(1024);
12265 for (i = 0; i < argc; i++) {
12266 if (first)
12267 buffer_putc(b, ' ');
12268 else {
12269 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12270 first = 1;
12271 buffer_putstr(b, argv[i]->arg);
12272 }
12273 }
12274 }
12275 buffer_putc(b, '\0');
57d187bc 12276
d62a17ae 12277 str = buffer_getstr(b);
12278 buffer_free(b);
57d187bc 12279
d62a17ae 12280 lcom = lcommunity_str2com(str);
12281 XFREE(MTYPE_TMP, str);
12282 if (!lcom) {
12283 vty_out(vty, "%% Large-community malformed\n");
12284 return CMD_WARNING;
12285 }
57d187bc 12286
4f28b2b5 12287 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12288 (exact ? bgp_show_type_lcommunity_exact
12289 : bgp_show_type_lcommunity),
12290 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12291
12292 lcommunity_free(&lcom);
12293 return ret;
57d187bc
JS
12294}
12295
d62a17ae 12296static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12297 const char *lcom, bool exact, afi_t afi,
12298 safi_t safi, bool uj)
57d187bc 12299{
d62a17ae 12300 struct community_list *list;
96c81f66 12301 uint16_t show_flags = 0;
96f3485c
MK
12302
12303 if (uj)
12304 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12305
57d187bc 12306
e237b0d2 12307 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12308 LARGE_COMMUNITY_LIST_MASTER);
12309 if (list == NULL) {
12310 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12311 lcom);
12312 return CMD_WARNING;
12313 }
57d187bc 12314
36a206db 12315 return bgp_show(vty, bgp, afi, safi,
12316 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12317 : bgp_show_type_lcommunity_list),
1e2ce4f1 12318 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12319}
12320
52951b63
DS
12321DEFUN (show_ip_bgp_large_community_list,
12322 show_ip_bgp_large_community_list_cmd,
77a3a95e 12323 "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
12324 SHOW_STR
12325 IP_STR
12326 BGP_STR
12327 BGP_INSTANCE_HELP_STR
9bedbb1e 12328 BGP_AFI_HELP_STR
4dd6177e 12329 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12330 "Display routes matching the large-community-list\n"
12331 "large-community-list number\n"
12332 "large-community-list name\n"
36a206db 12333 "Exact match of the large-communities\n"
52951b63
DS
12334 JSON_STR)
12335{
d62a17ae 12336 afi_t afi = AFI_IP6;
12337 safi_t safi = SAFI_UNICAST;
12338 int idx = 0;
36a206db 12339 bool exact_match = 0;
4d678463 12340 struct bgp *bgp = NULL;
9f049418 12341 bool uj = use_json(argc, argv);
d62a17ae 12342
ef3364f0
DA
12343 if (uj)
12344 argc--;
4d678463 12345
ef3364f0
DA
12346 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12347 &bgp, uj);
12348 if (!idx)
12349 return CMD_WARNING;
d62a17ae 12350
12351 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12352
12353 const char *clist_number_or_name = argv[++idx]->arg;
12354
12355 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12356 exact_match = 1;
12357
12358 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12359 exact_match, afi, safi, uj);
52951b63
DS
12360}
12361DEFUN (show_ip_bgp_large_community,
12362 show_ip_bgp_large_community_cmd,
36a206db 12363 "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
12364 SHOW_STR
12365 IP_STR
12366 BGP_STR
12367 BGP_INSTANCE_HELP_STR
9bedbb1e 12368 BGP_AFI_HELP_STR
4dd6177e 12369 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12370 "Display routes matching the large-communities\n"
12371 "List of large-community numbers\n"
36a206db 12372 "Exact match of the large-communities\n"
52951b63
DS
12373 JSON_STR)
12374{
d62a17ae 12375 afi_t afi = AFI_IP6;
12376 safi_t safi = SAFI_UNICAST;
12377 int idx = 0;
36a206db 12378 bool exact_match = 0;
4d678463 12379 struct bgp *bgp = NULL;
9f049418 12380 bool uj = use_json(argc, argv);
96c81f66 12381 uint16_t show_flags = 0;
d62a17ae 12382
96f3485c
MK
12383 if (uj) {
12384 argc--;
12385 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12386 }
4d678463 12387
96f3485c
MK
12388 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12389 &bgp, uj);
12390 if (!idx)
12391 return CMD_WARNING;
d62a17ae 12392
36a206db 12393 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12394 if (argv_find(argv, argc, "exact-match", &idx)) {
12395 argc--;
36a206db 12396 exact_match = 1;
1857760c 12397 }
36a206db 12398 return bgp_show_lcommunity(vty, bgp, argc, argv,
12399 exact_match, afi, safi, uj);
12400 } else
d62a17ae 12401 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12402 bgp_show_type_lcommunity_all, NULL, show_flags,
12403 RPKI_NOT_BEING_USED);
52951b63
DS
12404}
12405
71f1613a
DA
12406static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12407 safi_t safi, struct json_object *json_array);
d62a17ae 12408static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12409 safi_t safi, struct json_object *json);
e01ca200 12410
7b2ff250 12411
9ab0cf58
PG
12412DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12413 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12414 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12415 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12416{
12417 bool uj = use_json(argc, argv);
12418 struct bgp *bgp = NULL;
ec76a1d1
DA
12419 safi_t safi = SAFI_UNICAST;
12420 afi_t afi = AFI_IP6;
4265b261 12421 int idx = 0;
6c9d22e2
PG
12422 struct json_object *json_all = NULL;
12423 struct json_object *json_afi_safi = NULL;
4265b261
PG
12424
12425 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12426 &bgp, false);
71f1613a 12427 if (!idx)
4265b261 12428 return CMD_WARNING;
6c9d22e2 12429
4265b261 12430 if (uj)
6c9d22e2 12431 json_all = json_object_new_object();
4265b261 12432
9ab0cf58
PG
12433 FOREACH_AFI_SAFI (afi, safi) {
12434 /*
12435 * So limit output to those afi/safi pairs that
12436 * actually have something interesting in them
12437 */
12438 if (strmatch(get_afi_safi_str(afi, safi, true),
12439 "Unknown")) {
12440 continue;
12441 }
12442 if (uj) {
12443 json_afi_safi = json_object_new_array();
12444 json_object_object_add(
12445 json_all,
12446 get_afi_safi_str(afi, safi, true),
12447 json_afi_safi);
12448 } else {
12449 json_afi_safi = NULL;
6c9d22e2 12450 }
9ab0cf58
PG
12451
12452 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12453 }
6c9d22e2 12454
3757f964
DA
12455 if (uj)
12456 vty_json(vty, json_all);
6c9d22e2 12457
4265b261
PG
12458 return CMD_SUCCESS;
12459}
12460
7b2ff250 12461/* BGP route print out function without JSON */
14718643
PG
12462DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12463 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12464 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12465 SHOW_STR
12466 IP_STR
12467 BGP_STR
12468 BGP_INSTANCE_HELP_STR
12469 L2VPN_HELP_STR
12470 EVPN_HELP_STR
12471 "BGP RIB advertisement statistics\n"
12472 JSON_STR)
12473{
ec76a1d1
DA
12474 afi_t afi = AFI_IP6;
12475 safi_t safi = SAFI_UNICAST;
14718643
PG
12476 struct bgp *bgp = NULL;
12477 int idx = 0, ret;
12478 bool uj = use_json(argc, argv);
12479 struct json_object *json_afi_safi = NULL, *json = NULL;
12480
12481 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12482 &bgp, false);
12483 if (!idx)
12484 return CMD_WARNING;
12485
12486 if (uj)
12487 json_afi_safi = json_object_new_array();
12488 else
12489 json_afi_safi = NULL;
12490
12491 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12492
12493 if (uj) {
12494 json = json_object_new_object();
12495 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12496 json_afi_safi);
3757f964 12497 vty_json(vty, json);
14718643
PG
12498 }
12499 return ret;
12500}
12501
893cccd0 12502/* BGP route print out function without JSON */
9ab0cf58
PG
12503DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12504 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12505 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12506 "]]\
893cccd0 12507 statistics [json]",
9ab0cf58
PG
12508 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12509 BGP_SAFI_WITH_LABEL_HELP_STR
12510 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12511{
ec76a1d1
DA
12512 afi_t afi = AFI_IP6;
12513 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12514 struct bgp *bgp = NULL;
12515 int idx = 0, ret;
12516 bool uj = use_json(argc, argv);
6c9d22e2 12517 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12518
12519 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12520 &bgp, false);
12521 if (!idx)
12522 return CMD_WARNING;
6c9d22e2 12523
893cccd0 12524 if (uj)
6c9d22e2
PG
12525 json_afi_safi = json_object_new_array();
12526 else
12527 json_afi_safi = NULL;
12528
12529 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12530
12531 if (uj) {
12532 json = json_object_new_object();
12533 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12534 json_afi_safi);
3757f964 12535 vty_json(vty, json);
893cccd0
PG
12536 }
12537 return ret;
893cccd0 12538}
7b2ff250 12539
fe0f234d 12540DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12541 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12542 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12543 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12544 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12545 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12546 "Display the entries for all address families\n"
9ab0cf58
PG
12547 "Display detailed information about dampening\n"
12548 "Display detail of configured dampening parameters\n"
fe0f234d 12549 JSON_STR)
718e3744 12550{
d62a17ae 12551 afi_t afi = AFI_IP6;
12552 safi_t safi = SAFI_UNICAST;
d62a17ae 12553 struct bgp *bgp = NULL;
12554 int idx = 0;
96c81f66 12555 uint16_t show_flags = 0;
fe0f234d
RW
12556 bool uj = use_json(argc, argv);
12557
12558 if (uj) {
12559 argc--;
12560 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12561 }
96f3485c
MK
12562
12563 /* [<ipv4|ipv6> [all]] */
12564 if (all) {
12565 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12566 if (argv_find(argv, argc, "ipv4", &idx))
12567 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12568
12569 if (argv_find(argv, argc, "ipv6", &idx))
12570 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12571 }
d62a17ae 12572
12573 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12574 &bgp, false);
d62a17ae 12575 if (!idx)
12576 return CMD_WARNING;
12577
fe0f234d 12578 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12579}
12580
fe0f234d
RW
12581/* BGP route print out function */
12582DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12583 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12584 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12585 "]]\
96f3485c 12586 [all$all]\
cf4898bc
QY
12587 [cidr-only\
12588 |dampening <flap-statistics|dampened-paths>\
12589 |community [AA:NN|local-AS|no-advertise|no-export\
12590 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12591 |accept-own|accept-own-nexthop|route-filter-v6\
12592 |route-filter-v4|route-filter-translated-v6\
12593 |route-filter-translated-v4] [exact-match]\
70799983 12594 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12595 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12596 |prefix-list WORD\
ed126382 12597 |access-list ACCESSLIST_NAME\
70dd370f 12598 |route-map RMAP_NAME\
1e2ce4f1 12599 |rpki <invalid|valid|notfound>\
7d3cae70 12600 |version (1-4294967295)\
b4ad2fae 12601 |alias ALIAS_NAME\
39c3c736
RW
12602 |A.B.C.D/M longer-prefixes\
12603 |X:X::X:X/M longer-prefixes\
509d82bd 12604 |detail-routes$detail_routes\
67799a48 12605 ] [json$uj [detail$detail_json] | wide$wide]",
a70a28a5
DA
12606 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12607 BGP_SAFI_WITH_LABEL_HELP_STR
12608 "Display the entries for all address families\n"
12609 "Display only routes with non-natural netmasks\n"
12610 "Display detailed information about dampening\n"
12611 "Display flap statistics of routes\n"
12612 "Display paths suppressed due to dampening\n"
12613 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12614 "Do not send outside local AS (well-known community)\n"
12615 "Do not advertise to any peer (well-known community)\n"
12616 "Do not export to next AS (well-known community)\n"
12617 "Graceful shutdown (well-known community)\n"
12618 "Do not export to any peer (well-known community)\n"
12619 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12620 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12621 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12622 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12623 "Should accept VPN route with local nexthop (well-known community)\n"
12624 "RT VPNv6 route filtering (well-known community)\n"
12625 "RT VPNv4 route filtering (well-known community)\n"
12626 "RT translated VPNv6 route filtering (well-known community)\n"
12627 "RT translated VPNv4 route filtering (well-known community)\n"
12628 "Exact match of the communities\n"
70799983
RW
12629 "Community-list number\n"
12630 "Community-list name\n"
12631 "Display routes matching the community-list\n"
12632 "Exact match of the communities\n"
a7129347
RW
12633 "Display routes conforming to the filter-list\n"
12634 "Regular expression access list name\n"
6deaf579
RW
12635 "Display routes conforming to the prefix-list\n"
12636 "Prefix-list name\n"
ed126382
DA
12637 "Display routes conforming to the access-list\n"
12638 "Access-list name\n"
bf1a944a
RW
12639 "Display routes matching the route-map\n"
12640 "A route-map to match on\n"
a70a28a5
DA
12641 "RPKI route types\n"
12642 "A valid path as determined by rpki\n"
12643 "A invalid path as determined by rpki\n"
12644 "A path that has no rpki data\n"
12645 "Display prefixes with matching version numbers\n"
12646 "Version number and above\n"
12647 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12648 "BGP community alias\n"
12649 "IPv4 prefix\n"
12650 "Display route and more specific routes\n"
12651 "IPv6 prefix\n"
12652 "Display route and more specific routes\n"
509d82bd 12653 "Display detailed version of all routes\n"
39c3c736 12654 JSON_STR
a70a28a5
DA
12655 "Display detailed version of JSON output\n"
12656 "Increase table width for longer prefixes\n")
7b2ff250
DW
12657{
12658 afi_t afi = AFI_IP6;
12659 safi_t safi = SAFI_UNICAST;
12660 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12661 void *output_arg = NULL;
7b2ff250
DW
12662 struct bgp *bgp = NULL;
12663 int idx = 0;
d0086e8e 12664 int exact_match = 0;
96f3485c
MK
12665 char *community = NULL;
12666 bool first = true;
96c81f66 12667 uint16_t show_flags = 0;
4027d19b 12668 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12669 struct prefix p;
96f3485c
MK
12670
12671 if (uj) {
9f049418 12672 argc--;
96f3485c
MK
12673 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12674 }
12675
67799a48
DA
12676 if (detail_json)
12677 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
f280c93b 12678
509d82bd
DA
12679 if (detail_routes)
12680 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
f280c93b 12681
96f3485c
MK
12682 /* [<ipv4|ipv6> [all]] */
12683 if (all) {
12684 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12685
12686 if (argv_find(argv, argc, "ipv4", &idx))
12687 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12688
12689 if (argv_find(argv, argc, "ipv6", &idx))
12690 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12691 }
12692
12693 if (wide)
12694 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12695
12696 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12697 &bgp, uj);
7b2ff250
DW
12698 if (!idx)
12699 return CMD_WARNING;
12700
7b2ff250 12701 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12702 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12703
12704 if (argv_find(argv, argc, "dampening", &idx)) {
12705 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12706 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12707 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12708 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12709 }
12710
12711 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12712 char *maybecomm = NULL;
d0086e8e 12713
79bc257a
RW
12714 if (idx + 1 < argc) {
12715 if (argv[idx + 1]->type == VARIABLE_TKN)
12716 maybecomm = argv[idx + 1]->arg;
12717 else
12718 maybecomm = argv[idx + 1]->text;
12719 }
12720
cf4898bc
QY
12721 if (maybecomm && !strmatch(maybecomm, "json")
12722 && !strmatch(maybecomm, "exact-match"))
12723 community = maybecomm;
d0086e8e 12724
cf4898bc
QY
12725 if (argv_find(argv, argc, "exact-match", &idx))
12726 exact_match = 1;
d0086e8e 12727
96f3485c
MK
12728 if (!community)
12729 sh_type = bgp_show_type_community_all;
12730 }
12731
70799983
RW
12732 if (argv_find(argv, argc, "community-list", &idx)) {
12733 const char *clist_number_or_name = argv[++idx]->arg;
12734 struct community_list *list;
12735
12736 if (argv_find(argv, argc, "exact-match", &idx))
12737 exact_match = 1;
12738
12739 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12740 COMMUNITY_LIST_MASTER);
12741 if (list == NULL) {
606d49a4 12742 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12743 clist_number_or_name);
12744 return CMD_WARNING;
12745 }
12746
12747 if (exact_match)
12748 sh_type = bgp_show_type_community_list_exact;
12749 else
12750 sh_type = bgp_show_type_community_list;
12751 output_arg = list;
12752 }
12753
a7129347
RW
12754 if (argv_find(argv, argc, "filter-list", &idx)) {
12755 const char *filter = argv[++idx]->arg;
12756 struct as_list *as_list;
12757
12758 as_list = as_list_lookup(filter);
12759 if (as_list == NULL) {
606d49a4 12760 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12761 filter);
12762 return CMD_WARNING;
12763 }
12764
12765 sh_type = bgp_show_type_filter_list;
12766 output_arg = as_list;
12767 }
12768
6deaf579
RW
12769 if (argv_find(argv, argc, "prefix-list", &idx)) {
12770 const char *prefix_list_str = argv[++idx]->arg;
12771 struct prefix_list *plist;
12772
12773 plist = prefix_list_lookup(afi, prefix_list_str);
12774 if (plist == NULL) {
606d49a4 12775 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12776 prefix_list_str);
12777 return CMD_WARNING;
12778 }
12779
12780 sh_type = bgp_show_type_prefix_list;
12781 output_arg = plist;
12782 }
12783
ed126382
DA
12784 if (argv_find(argv, argc, "access-list", &idx)) {
12785 const char *access_list_str = argv[++idx]->arg;
12786 struct access_list *alist;
12787
12788 alist = access_list_lookup(afi, access_list_str);
12789 if (!alist) {
606d49a4 12790 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12791 access_list_str);
12792 return CMD_WARNING;
12793 }
12794
12795 sh_type = bgp_show_type_access_list;
12796 output_arg = alist;
12797 }
12798
bf1a944a
RW
12799 if (argv_find(argv, argc, "route-map", &idx)) {
12800 const char *rmap_str = argv[++idx]->arg;
12801 struct route_map *rmap;
12802
12803 rmap = route_map_lookup_by_name(rmap_str);
12804 if (!rmap) {
606d49a4 12805 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12806 return CMD_WARNING;
12807 }
12808
12809 sh_type = bgp_show_type_route_map;
12810 output_arg = rmap;
12811 }
12812
1e2ce4f1
DS
12813 if (argv_find(argv, argc, "rpki", &idx)) {
12814 sh_type = bgp_show_type_rpki;
12815 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12816 rpki_target_state = RPKI_VALID;
1e2ce4f1 12817 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12818 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12819 }
12820
7d3cae70
DA
12821 /* Display prefixes with matching version numbers */
12822 if (argv_find(argv, argc, "version", &idx)) {
12823 sh_type = bgp_show_type_prefix_version;
2391833e 12824 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12825 }
12826
a70a28a5
DA
12827 /* Display prefixes with matching BGP community alias */
12828 if (argv_find(argv, argc, "alias", &idx)) {
12829 sh_type = bgp_show_type_community_alias;
2391833e 12830 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12831 }
12832
39c3c736
RW
12833 /* prefix-longer */
12834 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12835 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12836 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12837
12838 if (!str2prefix(prefix_str, &p)) {
12839 vty_out(vty, "%% Malformed Prefix\n");
12840 return CMD_WARNING;
12841 }
12842
12843 sh_type = bgp_show_type_prefix_longer;
12844 output_arg = &p;
a70a28a5
DA
12845 }
12846
96f3485c
MK
12847 if (!all) {
12848 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12849 if (community)
12850 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12851 exact_match, afi, safi,
12852 show_flags);
2391833e 12853 else
a70a28a5 12854 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12855 output_arg, show_flags,
a70a28a5 12856 rpki_target_state);
96f3485c 12857 } else {
fa5ac378
DA
12858 struct listnode *node;
12859 struct bgp *abgp;
96f3485c
MK
12860 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12861 * AFI_IP6 */
12862
12863 if (uj)
12864 vty_out(vty, "{\n");
12865
12866 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12867 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12868 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12869 ? AFI_IP
12870 : AFI_IP6;
fa5ac378
DA
12871 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12872 FOREACH_SAFI (safi) {
12873 if (!bgp_afi_safi_peer_exists(abgp, afi,
12874 safi))
12875 continue;
96f3485c 12876
fa5ac378
DA
12877 if (uj) {
12878 if (first)
12879 first = false;
12880 else
12881 vty_out(vty, ",\n");
12882 vty_out(vty, "\"%s\":{\n",
12883 get_afi_safi_str(afi,
12884 safi,
12885 true));
12886 } else
12887 vty_out(vty,
12888 "\nFor address family: %s\n",
12889 get_afi_safi_str(
12890 afi, safi,
12891 false));
12892
12893 if (community)
12894 bgp_show_community(
12895 vty, abgp, community,
12896 exact_match, afi, safi,
12897 show_flags);
96f3485c 12898 else
fa5ac378
DA
12899 bgp_show(vty, abgp, afi, safi,
12900 sh_type, output_arg,
12901 show_flags,
12902 rpki_target_state);
12903 if (uj)
12904 vty_out(vty, "}\n");
12905 }
96f3485c
MK
12906 }
12907 } else {
12908 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12909 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12910 FOREACH_AFI_SAFI (afi, safi) {
12911 if (!bgp_afi_safi_peer_exists(abgp, afi,
12912 safi))
12913 continue;
96f3485c 12914
fa5ac378
DA
12915 if (uj) {
12916 if (first)
12917 first = false;
12918 else
12919 vty_out(vty, ",\n");
12920
12921 vty_out(vty, "\"%s\":{\n",
12922 get_afi_safi_str(afi,
12923 safi,
12924 true));
12925 } else
12926 vty_out(vty,
12927 "\nFor address family: %s\n",
12928 get_afi_safi_str(
12929 afi, safi,
12930 false));
12931
12932 if (community)
12933 bgp_show_community(
12934 vty, abgp, community,
12935 exact_match, afi, safi,
12936 show_flags);
96f3485c 12937 else
fa5ac378
DA
12938 bgp_show(vty, abgp, afi, safi,
12939 sh_type, output_arg,
12940 show_flags,
12941 rpki_target_state);
12942 if (uj)
12943 vty_out(vty, "}\n");
12944 }
96f3485c
MK
12945 }
12946 }
12947 if (uj)
12948 vty_out(vty, "}\n");
12949 }
12950 return CMD_SUCCESS;
a636c635 12951}
47fc97cc 12952
718e3744 12953DEFUN (show_ip_bgp_route,
12954 show_ip_bgp_route_cmd,
8aa22bbb 12955 "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 12956 SHOW_STR
12957 IP_STR
12958 BGP_STR
a636c635 12959 BGP_INSTANCE_HELP_STR
4f280b15 12960 BGP_AFI_HELP_STR
4dd6177e 12961 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12962 "Network in the BGP routing table to display\n"
0c7b1b01 12963 "IPv4 prefix\n"
8c3deaae 12964 "Network in the BGP routing table to display\n"
0c7b1b01 12965 "IPv6 prefix\n"
4092b06c 12966 "Display only the bestpath\n"
b05a1c8b 12967 "Display only multipaths\n"
8aa22bbb
DS
12968 "Display only paths that match the specified rpki state\n"
12969 "A valid path as determined by rpki\n"
12970 "A invalid path as determined by rpki\n"
12971 "A path that has no rpki data\n"
9973d184 12972 JSON_STR)
4092b06c 12973{
d62a17ae 12974 int prefix_check = 0;
ae19d7dd 12975
d62a17ae 12976 afi_t afi = AFI_IP6;
12977 safi_t safi = SAFI_UNICAST;
12978 char *prefix = NULL;
12979 struct bgp *bgp = NULL;
12980 enum bgp_path_type path_type;
9f049418 12981 bool uj = use_json(argc, argv);
b05a1c8b 12982
d62a17ae 12983 int idx = 0;
ae19d7dd 12984
d62a17ae 12985 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12986 &bgp, uj);
d62a17ae 12987 if (!idx)
12988 return CMD_WARNING;
c41247f5 12989
d62a17ae 12990 if (!bgp) {
12991 vty_out(vty,
12992 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12993 return CMD_WARNING;
12994 }
a636c635 12995
d62a17ae 12996 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12997 if (argv_find(argv, argc, "A.B.C.D", &idx)
12998 || argv_find(argv, argc, "X:X::X:X", &idx))
12999 prefix_check = 0;
13000 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13001 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13002 prefix_check = 1;
13003
13004 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13005 && afi != AFI_IP6) {
13006 vty_out(vty,
13007 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13008 return CMD_WARNING;
13009 }
13010 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13011 && afi != AFI_IP) {
13012 vty_out(vty,
13013 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13014 return CMD_WARNING;
13015 }
13016
13017 prefix = argv[idx]->arg;
13018
13019 /* [<bestpath|multipath>] */
13020 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13021 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13022 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13023 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13024 else
360660c6 13025 path_type = BGP_PATH_SHOW_ALL;
a636c635 13026
d62a17ae 13027 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13028 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13029}
13030
8c3deaae
QY
13031DEFUN (show_ip_bgp_regexp,
13032 show_ip_bgp_regexp_cmd,
3e5b31b3 13033 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13034 SHOW_STR
13035 IP_STR
13036 BGP_STR
b00b230a 13037 BGP_INSTANCE_HELP_STR
4f280b15 13038 BGP_AFI_HELP_STR
4dd6177e 13039 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13040 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13041 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13042 JSON_STR)
8c3deaae 13043{
d62a17ae 13044 afi_t afi = AFI_IP6;
13045 safi_t safi = SAFI_UNICAST;
13046 struct bgp *bgp = NULL;
3e5b31b3
DA
13047 bool uj = use_json(argc, argv);
13048 char *regstr = NULL;
8c3deaae 13049
d62a17ae 13050 int idx = 0;
13051 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13052 &bgp, false);
d62a17ae 13053 if (!idx)
13054 return CMD_WARNING;
8c3deaae 13055
d62a17ae 13056 // get index of regex
3e5b31b3
DA
13057 if (argv_find(argv, argc, "REGEX", &idx))
13058 regstr = argv[idx]->arg;
8c3deaae 13059
5f71d11c 13060 assert(regstr);
3e5b31b3
DA
13061 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13062 bgp_show_type_regexp, uj);
8c3deaae
QY
13063}
13064
ae248832 13065DEFPY (show_ip_bgp_instance_all,
a636c635 13066 show_ip_bgp_instance_all_cmd,
ae248832 13067 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13068 SHOW_STR
a636c635 13069 IP_STR
4092b06c 13070 BGP_STR
a636c635 13071 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13072 BGP_AFI_HELP_STR
4dd6177e 13073 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13074 JSON_STR
13075 "Increase table width for longer prefixes\n")
4092b06c 13076{
54d05dea 13077 afi_t afi = AFI_IP6;
d62a17ae 13078 safi_t safi = SAFI_UNICAST;
13079 struct bgp *bgp = NULL;
d62a17ae 13080 int idx = 0;
96c81f66 13081 uint16_t show_flags = 0;
ae19d7dd 13082
96f3485c 13083 if (uj) {
d62a17ae 13084 argc--;
96f3485c
MK
13085 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13086 }
13087
13088 if (wide)
13089 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13090
9f049418
DS
13091 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13092 &bgp, uj);
13093 if (!idx)
13094 return CMD_WARNING;
13095
96f3485c 13096 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13097 return CMD_SUCCESS;
e3e29b32
LB
13098}
13099
a4d82a8a 13100static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13101 afi_t afi, safi_t safi, enum bgp_show_type type,
13102 bool use_json)
718e3744 13103{
d62a17ae 13104 regex_t *regex;
13105 int rc;
96c81f66 13106 uint16_t show_flags = 0;
96f3485c
MK
13107
13108 if (use_json)
13109 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13110
c3900853 13111 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13112 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13113 regstr);
13114 return CMD_WARNING_CONFIG_FAILED;
13115 }
13116
d62a17ae 13117 regex = bgp_regcomp(regstr);
13118 if (!regex) {
13119 vty_out(vty, "Can't compile regexp %s\n", regstr);
13120 return CMD_WARNING;
13121 }
a636c635 13122
1e2ce4f1
DS
13123 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13124 RPKI_NOT_BEING_USED);
d62a17ae 13125 bgp_regex_free(regex);
13126 return rc;
e3e29b32
LB
13127}
13128
7f323236
DW
13129static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13130 const char *comstr, int exact, afi_t afi,
96c81f66 13131 safi_t safi, uint16_t show_flags)
d62a17ae 13132{
13133 struct community *com;
d62a17ae 13134 int ret = 0;
13135
7f323236 13136 com = community_str2com(comstr);
d62a17ae 13137 if (!com) {
7f323236 13138 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13139 return CMD_WARNING;
13140 }
13141
13142 ret = bgp_show(vty, bgp, afi, safi,
13143 (exact ? bgp_show_type_community_exact
13144 : bgp_show_type_community),
1e2ce4f1 13145 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13146 community_free(&com);
46c3ce83 13147
d62a17ae 13148 return ret;
718e3744 13149}
13150
d62a17ae 13151enum bgp_stats {
13152 BGP_STATS_MAXBITLEN = 0,
13153 BGP_STATS_RIB,
13154 BGP_STATS_PREFIXES,
13155 BGP_STATS_TOTPLEN,
13156 BGP_STATS_UNAGGREGATEABLE,
13157 BGP_STATS_MAX_AGGREGATEABLE,
13158 BGP_STATS_AGGREGATES,
13159 BGP_STATS_SPACE,
13160 BGP_STATS_ASPATH_COUNT,
13161 BGP_STATS_ASPATH_MAXHOPS,
13162 BGP_STATS_ASPATH_TOTHOPS,
13163 BGP_STATS_ASPATH_MAXSIZE,
13164 BGP_STATS_ASPATH_TOTSIZE,
13165 BGP_STATS_ASN_HIGHEST,
13166 BGP_STATS_MAX,
a636c635 13167};
2815e61f 13168
9ab0cf58 13169#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13170#define TABLE_STATS_IDX_JSON 1
13171
13172static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13173 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13174 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13175 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13176 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13177 "unaggregateablePrefixes"},
13178 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13179 "maximumAggregateablePrefixes"},
13180 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13181 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13182 [BGP_STATS_SPACE] = {"Address space advertised",
13183 "addressSpaceAdvertised"},
9ab0cf58
PG
13184 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13185 "advertisementsWithPaths"},
13186 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13187 "longestAsPath"},
13188 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13189 "largestAsPath"},
13190 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13191 "averageAsPathLengthHops"},
13192 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13193 "averageAsPathSizeBytes"},
13194 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13195 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13196};
2815e61f 13197
d62a17ae 13198struct bgp_table_stats {
13199 struct bgp_table *table;
13200 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13201
13202 unsigned long long
13203 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13204 1];
13205
8d0ab76d 13206 double total_space;
ff7924f6
PJ
13207};
13208
9bcb3eef 13209static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13210 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13211{
9bcb3eef 13212 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13213 struct bgp_path_info *pi;
b54892e0 13214 const struct prefix *rn_p;
d62a17ae 13215
9bcb3eef 13216 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13217 return;
d62a17ae 13218
9bcb3eef 13219 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13220 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13221 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13222
0747643e 13223 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13224 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13225 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13226 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13227
9bcb3eef 13228 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13229 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13230 /* announced address space */
13231 if (space)
b54892e0 13232 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13233 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13234 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13235
9c14ec72 13236
9bcb3eef 13237 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13238 ts->counts[BGP_STATS_RIB]++;
13239
05864da7
DS
13240 if (CHECK_FLAG(pi->attr->flag,
13241 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13242 ts->counts[BGP_STATS_AGGREGATES]++;
13243
13244 /* as-path stats */
05864da7 13245 if (pi->attr->aspath) {
9c14ec72
RW
13246 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13247 unsigned int size = aspath_size(pi->attr->aspath);
13248 as_t highest = aspath_highest(pi->attr->aspath);
13249
13250 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13251
13252 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13253 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13254
13255 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13256 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13257
13258 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13259 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13260 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13261 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13262 }
13263 }
13264}
13265
cc9f21da 13266static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13267{
9bcb3eef
DS
13268 struct bgp_dest *dest, *ndest;
13269 struct bgp_dest *top;
9c14ec72
RW
13270 struct bgp_table_stats *ts = THREAD_ARG(t);
13271 unsigned int space = 0;
13272
13273 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13274 return;
9c14ec72
RW
13275
13276 switch (ts->table->afi) {
13277 case AFI_IP:
13278 space = IPV4_MAX_BITLEN;
13279 break;
13280 case AFI_IP6:
13281 space = IPV6_MAX_BITLEN;
13282 break;
3ba7b4af
TA
13283 case AFI_L2VPN:
13284 space = EVPN_ROUTE_PREFIXLEN;
13285 break;
9c14ec72 13286 default:
cc9f21da 13287 return;
9c14ec72
RW
13288 }
13289
13290 ts->counts[BGP_STATS_MAXBITLEN] = space;
13291
9bcb3eef 13292 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13293 if (ts->table->safi == SAFI_MPLS_VPN
13294 || ts->table->safi == SAFI_ENCAP
13295 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13296 struct bgp_table *table;
13297
9bcb3eef 13298 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13299 if (!table)
13300 continue;
13301
13302 top = bgp_table_top(table);
9bcb3eef
DS
13303 for (ndest = bgp_table_top(table); ndest;
13304 ndest = bgp_route_next(ndest))
13305 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13306 } else {
9bcb3eef 13307 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13308 }
13309 }
2815e61f 13310}
ff7924f6 13311
71f1613a
DA
13312static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13313 struct json_object *json_array)
13314{
13315 struct listnode *node, *nnode;
13316 struct bgp *bgp;
13317
13318 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13319 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13320}
13321
13322static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13323 safi_t safi, struct json_object *json_array)
2815e61f 13324{
d62a17ae 13325 struct bgp_table_stats ts;
13326 unsigned int i;
893cccd0
PG
13327 int ret = CMD_SUCCESS;
13328 char temp_buf[20];
6c9d22e2 13329 struct json_object *json = NULL;
0747643e
AQ
13330 uint32_t bitlen = 0;
13331 struct json_object *json_bitlen;
6c9d22e2
PG
13332
13333 if (json_array)
13334 json = json_object_new_object();
019386c2 13335
d62a17ae 13336 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13337 char warning_msg[50];
13338
13339 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13340 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13341 safi);
6c9d22e2
PG
13342
13343 if (!json)
893cccd0
PG
13344 vty_out(vty, "%s\n", warning_msg);
13345 else
9ab0cf58 13346 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13347
893cccd0
PG
13348 ret = CMD_WARNING;
13349 goto end_table_stats;
d62a17ae 13350 }
019386c2 13351
893cccd0 13352 if (!json)
5290ceab
DA
13353 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13354 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13355 else
13356 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13357
d62a17ae 13358 /* labeled-unicast routes live in the unicast table */
13359 if (safi == SAFI_LABELED_UNICAST)
13360 safi = SAFI_UNICAST;
019386c2 13361
d62a17ae 13362 memset(&ts, 0, sizeof(ts));
13363 ts.table = bgp->rib[afi][safi];
13364 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13365
d62a17ae 13366 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13367 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13368 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13369 continue;
13370
13371 switch (i) {
d62a17ae 13372 case BGP_STATS_ASPATH_TOTHOPS:
13373 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13374 if (!json) {
9ab0cf58
PG
13375 snprintf(
13376 temp_buf, sizeof(temp_buf), "%12.2f",
13377 ts.counts[i]
13378 ? (float)ts.counts[i]
13379 / (float)ts.counts
13380 [BGP_STATS_ASPATH_COUNT]
13381 : 0);
893cccd0 13382 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13383 table_stats_strs[i]
13384 [TABLE_STATS_IDX_VTY],
893cccd0 13385 temp_buf);
9ab0cf58
PG
13386 } else {
13387 json_object_double_add(
13388 json,
13389 table_stats_strs[i]
13390 [TABLE_STATS_IDX_JSON],
13391 ts.counts[i]
13392 ? (double)ts.counts[i]
13393 / (double)ts.counts
d62a17ae 13394 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13395 : 0);
13396 }
d62a17ae 13397 break;
13398 case BGP_STATS_TOTPLEN:
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_PREFIXES]
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_PREFIXES]
9ab0cf58
PG
13420 : 0);
13421 }
d62a17ae 13422 break;
13423 case BGP_STATS_SPACE:
6c9d22e2
PG
13424 if (!json) {
13425 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13426 ts.total_space);
893cccd0 13427 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13428 table_stats_strs[i]
13429 [TABLE_STATS_IDX_VTY],
893cccd0 13430 temp_buf);
9ab0cf58
PG
13431 } else {
13432 json_object_double_add(
13433 json,
13434 table_stats_strs[i]
13435 [TABLE_STATS_IDX_JSON],
13436 (double)ts.total_space);
13437 }
8d0ab76d 13438 if (afi == AFI_IP6) {
6c9d22e2
PG
13439 if (!json) {
13440 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13441 "%12g",
13442 ts.total_space
13443 * pow(2.0, -128 + 32));
6c9d22e2
PG
13444 vty_out(vty, "%30s: %s\n",
13445 "/32 equivalent %s\n",
13446 temp_buf);
9ab0cf58
PG
13447 } else {
13448 json_object_double_add(
13449 json, "/32equivalent",
13450 (double)(ts.total_space
13451 * pow(2.0,
13452 -128 + 32)));
13453 }
6c9d22e2
PG
13454 if (!json) {
13455 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13456 "%12g",
13457 ts.total_space
13458 * pow(2.0, -128 + 48));
6c9d22e2
PG
13459 vty_out(vty, "%30s: %s\n",
13460 "/48 equivalent %s\n",
13461 temp_buf);
9ab0cf58
PG
13462 } else {
13463 json_object_double_add(
13464 json, "/48equivalent",
13465 (double)(ts.total_space
13466 * pow(2.0,
13467 -128 + 48)));
13468 }
8d0ab76d 13469 } else {
6c9d22e2
PG
13470 if (!json) {
13471 snprintf(temp_buf, sizeof(temp_buf),
13472 "%12.2f",
9ab0cf58
PG
13473 ts.total_space * 100.
13474 * pow(2.0, -32));
6c9d22e2 13475 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13476 "% announced ", temp_buf);
13477 } else {
13478 json_object_double_add(
13479 json, "%announced",
13480 (double)(ts.total_space * 100.
13481 * pow(2.0, -32)));
13482 }
6c9d22e2
PG
13483 if (!json) {
13484 snprintf(temp_buf, sizeof(temp_buf),
13485 "%12.2f",
9ab0cf58
PG
13486 ts.total_space
13487 * pow(2.0, -32 + 8));
6c9d22e2
PG
13488 vty_out(vty, "%30s: %s\n",
13489 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13490 } else {
13491 json_object_double_add(
13492 json, "/8equivalent",
13493 (double)(ts.total_space
13494 * pow(2.0, -32 + 8)));
13495 }
6c9d22e2
PG
13496 if (!json) {
13497 snprintf(temp_buf, sizeof(temp_buf),
13498 "%12.2f",
9ab0cf58
PG
13499 ts.total_space
13500 * pow(2.0, -32 + 24));
6c9d22e2 13501 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13502 "/24 equivalent ", temp_buf);
13503 } else {
13504 json_object_double_add(
13505 json, "/24equivalent",
13506 (double)(ts.total_space
13507 * pow(2.0, -32 + 24)));
13508 }
8d0ab76d 13509 }
d62a17ae 13510 break;
13511 default:
6c9d22e2
PG
13512 if (!json) {
13513 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13514 ts.counts[i]);
893cccd0 13515 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13516 table_stats_strs[i]
13517 [TABLE_STATS_IDX_VTY],
13518 temp_buf);
13519 } else {
13520 json_object_int_add(
13521 json,
13522 table_stats_strs[i]
13523 [TABLE_STATS_IDX_JSON],
13524 ts.counts[i]);
13525 }
d62a17ae 13526 }
893cccd0
PG
13527 if (!json)
13528 vty_out(vty, "\n");
d62a17ae 13529 }
0747643e
AQ
13530
13531 switch (afi) {
13532 case AFI_IP:
13533 bitlen = IPV4_MAX_BITLEN;
13534 break;
13535 case AFI_IP6:
13536 bitlen = IPV6_MAX_BITLEN;
13537 break;
13538 case AFI_L2VPN:
13539 bitlen = EVPN_ROUTE_PREFIXLEN;
13540 break;
13541 default:
13542 break;
13543 }
13544
13545 if (json) {
13546 json_bitlen = json_object_new_array();
13547
13548 for (i = 0; i <= bitlen; i++) {
13549 struct json_object *ind_bit = json_object_new_object();
13550
13551 if (!ts.prefix_len_count[i])
13552 continue;
13553
13554 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13555 json_object_int_add(ind_bit, temp_buf,
13556 ts.prefix_len_count[i]);
13557 json_object_array_add(json_bitlen, ind_bit);
13558 }
13559 json_object_object_add(json, "prefixLength", json_bitlen);
13560 }
13561
9ab0cf58 13562end_table_stats:
6c9d22e2
PG
13563 if (json)
13564 json_object_array_add(json_array, json);
893cccd0 13565 return ret;
d62a17ae 13566}
13567
71f1613a
DA
13568static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13569 safi_t safi, struct json_object *json_array)
13570{
13571 if (!bgp) {
13572 bgp_table_stats_all(vty, afi, safi, json_array);
13573 return CMD_SUCCESS;
13574 }
13575
13576 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13577}
13578
d62a17ae 13579enum bgp_pcounts {
13580 PCOUNT_ADJ_IN = 0,
13581 PCOUNT_DAMPED,
13582 PCOUNT_REMOVED,
13583 PCOUNT_HISTORY,
13584 PCOUNT_STALE,
13585 PCOUNT_VALID,
13586 PCOUNT_ALL,
13587 PCOUNT_COUNTED,
7e3d9632 13588 PCOUNT_BPATH_SELECTED,
d62a17ae 13589 PCOUNT_PFCNT, /* the figure we display to users */
13590 PCOUNT_MAX,
a636c635 13591};
718e3744 13592
2b64873d 13593static const char *const pcount_strs[] = {
9d303b37
DL
13594 [PCOUNT_ADJ_IN] = "Adj-in",
13595 [PCOUNT_DAMPED] = "Damped",
13596 [PCOUNT_REMOVED] = "Removed",
13597 [PCOUNT_HISTORY] = "History",
13598 [PCOUNT_STALE] = "Stale",
13599 [PCOUNT_VALID] = "Valid",
13600 [PCOUNT_ALL] = "All RIB",
13601 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13602 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13603 [PCOUNT_PFCNT] = "Useable",
13604 [PCOUNT_MAX] = NULL,
a636c635 13605};
718e3744 13606
d62a17ae 13607struct peer_pcounts {
13608 unsigned int count[PCOUNT_MAX];
13609 const struct peer *peer;
13610 const struct bgp_table *table;
54317cba 13611 safi_t safi;
a636c635 13612};
47fc97cc 13613
9bcb3eef 13614static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13615{
54317cba
JW
13616 const struct bgp_adj_in *ain;
13617 const struct bgp_path_info *pi;
d62a17ae 13618 const struct peer *peer = pc->peer;
13619
54317cba
JW
13620 for (ain = rn->adj_in; ain; ain = ain->next)
13621 if (ain->peer == peer)
13622 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13623
9bcb3eef 13624 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13625
54317cba
JW
13626 if (pi->peer != peer)
13627 continue;
d62a17ae 13628
54317cba 13629 pc->count[PCOUNT_ALL]++;
d62a17ae 13630
54317cba
JW
13631 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13632 pc->count[PCOUNT_DAMPED]++;
13633 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13634 pc->count[PCOUNT_HISTORY]++;
13635 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13636 pc->count[PCOUNT_REMOVED]++;
13637 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13638 pc->count[PCOUNT_STALE]++;
13639 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13640 pc->count[PCOUNT_VALID]++;
13641 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13642 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13643 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13644 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13645
13646 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13647 pc->count[PCOUNT_COUNTED]++;
13648 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13649 flog_err(
13650 EC_LIB_DEVELOPMENT,
13651 "Attempting to count but flags say it is unusable");
13652 } else {
40381db7 13653 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13654 flog_err(
13655 EC_LIB_DEVELOPMENT,
13656 "Not counted but flags say we should");
d62a17ae 13657 }
13658 }
54317cba
JW
13659}
13660
cc9f21da 13661static void bgp_peer_count_walker(struct thread *t)
54317cba 13662{
9bcb3eef 13663 struct bgp_dest *rn, *rm;
54317cba
JW
13664 const struct bgp_table *table;
13665 struct peer_pcounts *pc = THREAD_ARG(t);
13666
13667 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13668 || pc->safi == SAFI_EVPN) {
13669 /* Special handling for 2-level routing tables. */
13670 for (rn = bgp_table_top(pc->table); rn;
13671 rn = bgp_route_next(rn)) {
9bcb3eef 13672 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13673 if (table != NULL)
13674 for (rm = bgp_table_top(table); rm;
13675 rm = bgp_route_next(rm))
13676 bgp_peer_count_proc(rm, pc);
13677 }
13678 } else
13679 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13680 bgp_peer_count_proc(rn, pc);
718e3744 13681}
13682
d62a17ae 13683static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13684 safi_t safi, bool use_json)
856ca177 13685{
d62a17ae 13686 struct peer_pcounts pcounts = {.peer = peer};
13687 unsigned int i;
13688 json_object *json = NULL;
13689 json_object *json_loop = NULL;
856ca177 13690
d62a17ae 13691 if (use_json) {
13692 json = json_object_new_object();
13693 json_loop = json_object_new_object();
13694 }
718e3744 13695
d62a17ae 13696 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13697 || !peer->bgp->rib[afi][safi]) {
13698 if (use_json) {
13699 json_object_string_add(
13700 json, "warning",
13701 "No such neighbor or address family");
13702 vty_out(vty, "%s\n", json_object_to_json_string(json));
13703 json_object_free(json);
d5f20468 13704 json_object_free(json_loop);
d62a17ae 13705 } else
13706 vty_out(vty, "%% No such neighbor or address family\n");
13707
13708 return CMD_WARNING;
13709 }
2a71e9ce 13710
d62a17ae 13711 memset(&pcounts, 0, sizeof(pcounts));
13712 pcounts.peer = peer;
13713 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13714 pcounts.safi = safi;
d62a17ae 13715
13716 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13717 * stats for the thread-walk (i.e. ensure this can't be blamed on
13718 * on just vty_read()).
13719 */
d62a17ae 13720 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13721
13722 if (use_json) {
13723 json_object_string_add(json, "prefixCountsFor", peer->host);
13724 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13725 get_afi_safi_str(afi, safi, true));
d62a17ae 13726 json_object_int_add(json, "pfxCounter",
13727 peer->pcount[afi][safi]);
13728
13729 for (i = 0; i < PCOUNT_MAX; i++)
13730 json_object_int_add(json_loop, pcount_strs[i],
13731 pcounts.count[i]);
13732
13733 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13734
13735 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13736 json_object_string_add(json, "pfxctDriftFor",
13737 peer->host);
13738 json_object_string_add(
13739 json, "recommended",
13740 "Please report this bug, with the above command output");
13741 }
75eeda93 13742 vty_json(vty, json);
d62a17ae 13743 } else {
13744
13745 if (peer->hostname
892fedb6 13746 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13747 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13748 peer->hostname, peer->host,
5cb5f4d0 13749 get_afi_safi_str(afi, safi, false));
d62a17ae 13750 } else {
13751 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13752 get_afi_safi_str(afi, safi, false));
d62a17ae 13753 }
13754
6cde4b45 13755 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13756 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13757
13758 for (i = 0; i < PCOUNT_MAX; i++)
13759 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13760 pcounts.count[i]);
13761
13762 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13763 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13764 vty_out(vty,
13765 "Please report this bug, with the above command output\n");
13766 }
13767 }
13768
13769 return CMD_SUCCESS;
718e3744 13770}
13771
a636c635
DW
13772DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13773 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13774 "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 13775 SHOW_STR
13776 IP_STR
13777 BGP_STR
8386ac43 13778 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13779 BGP_AFI_HELP_STR
13780 BGP_SAFI_HELP_STR
0b16f239
DS
13781 "Detailed information on TCP and BGP neighbor connections\n"
13782 "Neighbor to display information about\n"
13783 "Neighbor to display information about\n"
91d37724 13784 "Neighbor on BGP configured interface\n"
a636c635 13785 "Display detailed prefix count information\n"
9973d184 13786 JSON_STR)
0b16f239 13787{
d62a17ae 13788 afi_t afi = AFI_IP6;
13789 safi_t safi = SAFI_UNICAST;
13790 struct peer *peer;
13791 int idx = 0;
13792 struct bgp *bgp = NULL;
9f049418
DS
13793 bool uj = use_json(argc, argv);
13794
13795 if (uj)
13796 argc--;
856ca177 13797
d62a17ae 13798 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13799 &bgp, uj);
d62a17ae 13800 if (!idx)
13801 return CMD_WARNING;
0b16f239 13802
d62a17ae 13803 argv_find(argv, argc, "neighbors", &idx);
13804 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13805 if (!peer)
13806 return CMD_WARNING;
bb46e94f 13807
29c8d9da 13808 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13809}
0b16f239 13810
d6902373
PG
13811#ifdef KEEP_OLD_VPN_COMMANDS
13812DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13813 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13814 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13815 SHOW_STR
13816 IP_STR
13817 BGP_STR
d6902373 13818 BGP_VPNVX_HELP_STR
91d37724 13819 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13820 "Detailed information on TCP and BGP neighbor connections\n"
13821 "Neighbor to display information about\n"
13822 "Neighbor to display information about\n"
91d37724 13823 "Neighbor on BGP configured interface\n"
a636c635 13824 "Display detailed prefix count information\n"
9973d184 13825 JSON_STR)
a636c635 13826{
d62a17ae 13827 int idx_peer = 6;
13828 struct peer *peer;
9f049418 13829 bool uj = use_json(argc, argv);
a636c635 13830
d62a17ae 13831 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13832 if (!peer)
13833 return CMD_WARNING;
13834
13835 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13836}
13837
d6902373
PG
13838DEFUN (show_ip_bgp_vpn_all_route_prefix,
13839 show_ip_bgp_vpn_all_route_prefix_cmd,
13840 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13841 SHOW_STR
13842 IP_STR
13843 BGP_STR
d6902373 13844 BGP_VPNVX_HELP_STR
91d37724
QY
13845 "Display information about all VPNv4 NLRIs\n"
13846 "Network in the BGP routing table to display\n"
3a2d747c 13847 "Network in the BGP routing table to display\n"
9973d184 13848 JSON_STR)
91d37724 13849{
d62a17ae 13850 int idx = 0;
13851 char *network = NULL;
13852 struct bgp *bgp = bgp_get_default();
13853 if (!bgp) {
13854 vty_out(vty, "Can't find default instance\n");
13855 return CMD_WARNING;
13856 }
87e34b58 13857
d62a17ae 13858 if (argv_find(argv, argc, "A.B.C.D", &idx))
13859 network = argv[idx]->arg;
13860 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13861 network = argv[idx]->arg;
13862 else {
13863 vty_out(vty, "Unable to figure out Network\n");
13864 return CMD_WARNING;
13865 }
87e34b58 13866
d62a17ae 13867 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13868 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13869 use_json(argc, argv));
91d37724 13870}
d6902373 13871#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13872
44c69747
LK
13873DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13874 show_bgp_l2vpn_evpn_route_prefix_cmd,
13875 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13876 SHOW_STR
4c63a661
PG
13877 BGP_STR
13878 L2VPN_HELP_STR
13879 EVPN_HELP_STR
44c69747
LK
13880 "Network in the BGP routing table to display\n"
13881 "Network in the BGP routing table to display\n"
4c63a661
PG
13882 "Network in the BGP routing table to display\n"
13883 "Network in the BGP routing table to display\n"
13884 JSON_STR)
13885{
d62a17ae 13886 int idx = 0;
13887 char *network = NULL;
44c69747 13888 int prefix_check = 0;
a636c635 13889
44c69747
LK
13890 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13891 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13892 network = argv[idx]->arg;
44c69747 13893 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13894 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13895 network = argv[idx]->arg;
44c69747
LK
13896 prefix_check = 1;
13897 } else {
d62a17ae 13898 vty_out(vty, "Unable to figure out Network\n");
13899 return CMD_WARNING;
13900 }
44c69747
LK
13901 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13902 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13903 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13904}
13905
114fc229 13906static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13907 struct bgp_table *table, int *header1,
13908 int *header2, json_object *json,
13909 json_object *json_scode,
e960b4ca
TA
13910 json_object *json_ocode, bool wide,
13911 bool detail)
2f9bc755
DS
13912{
13913 uint64_t version = table ? table->version : 0;
13914
13915 if (*header1) {
13916 if (json) {
13917 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13918 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13919 "%pI4", &peer->bgp->router_id);
2f9bc755 13920 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13921 peer->bgp->default_local_pref);
13922 json_object_int_add(json, "localAS",
13923 peer->change_local_as
13924 ? peer->change_local_as
13925 : peer->local_as);
2f9bc755
DS
13926 json_object_object_add(json, "bgpStatusCodes",
13927 json_scode);
13928 json_object_object_add(json, "bgpOriginCodes",
13929 json_ocode);
13930 } else {
13931 vty_out(vty,
23d0a753
DA
13932 "BGP table version is %" PRIu64
13933 ", local router ID is %pI4, vrf id ",
114fc229
DA
13934 version, &peer->bgp->router_id);
13935 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13936 vty_out(vty, "%s", VRFID_NONE_STR);
13937 else
114fc229 13938 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13939 vty_out(vty, "\n");
13940 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13941 peer->bgp->default_local_pref);
13942 vty_out(vty, "local AS %u\n",
13943 peer->change_local_as ? peer->change_local_as
13944 : peer->local_as);
e960b4ca
TA
13945 if (!detail) {
13946 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13947 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13948 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13949 vty_out(vty, BGP_SHOW_RPKI_HEADER);
13950 }
2f9bc755
DS
13951 }
13952 *header1 = 0;
13953 }
13954 if (*header2) {
e960b4ca 13955 if (!json && !detail)
2f9bc755
DS
13956 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13957 : BGP_SHOW_HEADER));
13958 *header2 = 0;
13959 }
13960}
13961
d9478df0
TA
13962static void
13963show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13964 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13965 const char *rmap_name, json_object *json, json_object *json_ar,
13966 json_object *json_scode, json_object *json_ocode,
96c81f66 13967 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13968 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13969{
d62a17ae 13970 struct bgp_adj_in *ain;
13971 struct bgp_adj_out *adj;
9bcb3eef 13972 struct bgp_dest *dest;
d62a17ae 13973 struct bgp *bgp;
d62a17ae 13974 struct attr attr;
13975 int ret;
13976 struct update_subgroup *subgrp;
d62a17ae 13977 struct peer_af *paf;
f99def61 13978 bool route_filtered;
e960b4ca 13979 bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
96f3485c
MK
13980 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13981 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13982 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13983 || (safi == SAFI_EVPN))
13984 ? true
13985 : false;
e960b4ca
TA
13986 int display = 0;
13987 json_object *json_net = NULL;
a636c635 13988
d62a17ae 13989 bgp = peer->bgp;
a636c635 13990
d62a17ae 13991 subgrp = peer_subgroup(peer, afi, safi);
13992
6392aaa6 13993 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13994 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13995 if (use_json) {
13996 json_object_int_add(json, "bgpTableVersion",
13997 table->version);
c949c771
DA
13998 json_object_string_addf(json, "bgpLocalRouterId",
13999 "%pI4", &bgp->router_id);
01eced22
AD
14000 json_object_int_add(json, "defaultLocPrf",
14001 bgp->default_local_pref);
114fc229
DA
14002 json_object_int_add(json, "localAS",
14003 peer->change_local_as
14004 ? peer->change_local_as
14005 : peer->local_as);
d62a17ae 14006 json_object_object_add(json, "bgpStatusCodes",
14007 json_scode);
14008 json_object_object_add(json, "bgpOriginCodes",
14009 json_ocode);
07d0c4ed
DA
14010 json_object_string_add(
14011 json, "bgpOriginatingDefaultNetwork",
14012 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14013 } else {
23d0a753
DA
14014 vty_out(vty,
14015 "BGP table version is %" PRIu64
14016 ", local router ID is %pI4, vrf id ",
14017 table->version, &bgp->router_id);
9df8b37c
PZ
14018 if (bgp->vrf_id == VRF_UNKNOWN)
14019 vty_out(vty, "%s", VRFID_NONE_STR);
14020 else
14021 vty_out(vty, "%u", bgp->vrf_id);
14022 vty_out(vty, "\n");
01eced22
AD
14023 vty_out(vty, "Default local pref %u, ",
14024 bgp->default_local_pref);
114fc229
DA
14025 vty_out(vty, "local AS %u\n",
14026 peer->change_local_as ? peer->change_local_as
14027 : peer->local_as);
e960b4ca
TA
14028 if (!detail) {
14029 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14030 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14031 vty_out(vty, BGP_SHOW_OCODE_HEADER);
14032 vty_out(vty, BGP_SHOW_RPKI_HEADER);
14033 }
d62a17ae 14034
07d0c4ed
DA
14035 vty_out(vty, "Originating default network %s\n\n",
14036 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14037 }
65565c9a 14038 (*output_count)++;
d9478df0 14039 *header1 = 0;
d62a17ae 14040 }
a636c635 14041
9bcb3eef 14042 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14043 if (type == bgp_show_adj_route_received
14044 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14045 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14046 if (ain->peer != peer)
ea47320b 14047 continue;
6392aaa6 14048
114fc229 14049 show_adj_route_header(vty, peer, table, header1,
d9478df0 14050 header2, json, json_scode,
e960b4ca 14051 json_ocode, wide, detail);
d9478df0
TA
14052
14053 if ((safi == SAFI_MPLS_VPN)
14054 || (safi == SAFI_ENCAP)
14055 || (safi == SAFI_EVPN)) {
14056 if (use_json)
14057 json_object_string_add(
14058 json_ar, "rd", rd_str);
14059 else if (show_rd && rd_str) {
14060 vty_out(vty,
14061 "Route Distinguisher: %s\n",
14062 rd_str);
14063 show_rd = false;
14064 }
14065 }
6392aaa6 14066
6f4f49b2 14067 attr = *ain->attr;
f99def61
AD
14068 route_filtered = false;
14069
14070 /* Filter prefix using distribute list,
14071 * filter list or prefix list
14072 */
b54892e0 14073 const struct prefix *rn_p =
9bcb3eef 14074 bgp_dest_get_prefix(dest);
b54892e0
DS
14075 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14076 safi))
14077 == FILTER_DENY)
f99def61
AD
14078 route_filtered = true;
14079
14080 /* Filter prefix using route-map */
b54892e0
DS
14081 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14082 safi, rmap_name, NULL,
14083 0, NULL);
6392aaa6 14084
13c8e163
AD
14085 if (type == bgp_show_adj_route_filtered &&
14086 !route_filtered && ret != RMAP_DENY) {
d498917e 14087 bgp_attr_flush(&attr);
6392aaa6 14088 continue;
d62a17ae 14089 }
6392aaa6 14090
d9478df0
TA
14091 if (type == bgp_show_adj_route_received
14092 && (route_filtered || ret == RMAP_DENY))
14093 (*filtered_count)++;
6392aaa6 14094
e960b4ca
TA
14095 if (detail) {
14096 if (use_json)
14097 json_net =
14098 json_object_new_object();
14099 bgp_show_path_info(
14100 NULL /* prefix_rd */, dest, vty,
14101 bgp, afi, safi, json_net,
14102 BGP_PATH_SHOW_ALL, &display,
14103 RPKI_NOT_BEING_USED);
14104 if (use_json)
14105 json_object_object_addf(
14106 json_ar, json_net,
14107 "%pFX", rn_p);
14108 } else
14109 route_vty_out_tmp(vty, dest, rn_p,
14110 &attr, safi, use_json,
14111 json_ar, wide);
d498917e 14112 bgp_attr_flush(&attr);
d9478df0 14113 (*output_count)++;
d62a17ae 14114 }
6392aaa6 14115 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14116 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14117 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14118 if (paf->peer != peer || !adj->attr)
924c3f6a 14119 continue;
d62a17ae 14120
e960b4ca
TA
14121 show_adj_route_header(
14122 vty, peer, table, header1,
14123 header2, json, json_scode,
14124 json_ocode, wide, detail);
d62a17ae 14125
b54892e0 14126 const struct prefix *rn_p =
9bcb3eef 14127 bgp_dest_get_prefix(dest);
b54892e0 14128
6f4f49b2 14129 attr = *adj->attr;
b755861b 14130 ret = bgp_output_modifier(
b54892e0 14131 peer, rn_p, &attr, afi, safi,
b755861b 14132 rmap_name);
f46d8e1e 14133
b755861b 14134 if (ret != RMAP_DENY) {
d9478df0
TA
14135 if ((safi == SAFI_MPLS_VPN)
14136 || (safi == SAFI_ENCAP)
14137 || (safi == SAFI_EVPN)) {
14138 if (use_json)
14139 json_object_string_add(
14140 json_ar,
14141 "rd",
14142 rd_str);
14143 else if (show_rd
14144 && rd_str) {
14145 vty_out(vty,
14146 "Route Distinguisher: %s\n",
14147 rd_str);
14148 show_rd = false;
14149 }
14150 }
e960b4ca
TA
14151 if (detail) {
14152 if (use_json)
14153 json_net =
14154 json_object_new_object();
14155 bgp_show_path_info(
14156 NULL /* prefix_rd
14157 */
14158 ,
14159 dest, vty, bgp,
14160 afi, safi,
14161 json_net,
14162 BGP_PATH_SHOW_ALL,
14163 &display,
14164 RPKI_NOT_BEING_USED);
14165 if (use_json)
14166 json_object_object_addf(
14167 json_ar,
14168 json_net,
14169 "%pFX",
14170 rn_p);
14171 } else
14172 route_vty_out_tmp(
14173 vty, dest, rn_p,
14174 &attr, safi,
14175 use_json,
14176 json_ar, wide);
d9478df0 14177 (*output_count)++;
b755861b 14178 } else {
d9478df0 14179 (*filtered_count)++;
a2addae8 14180 }
b755861b 14181
d498917e 14182 bgp_attr_flush(&attr);
924c3f6a 14183 }
f20ce998
DS
14184 } else if (type == bgp_show_adj_route_bestpath) {
14185 struct bgp_path_info *pi;
14186
114fc229
DA
14187 show_adj_route_header(vty, peer, table, header1,
14188 header2, json, json_scode,
e960b4ca 14189 json_ocode, wide, detail);
f20ce998
DS
14190
14191 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14192 pi = pi->next) {
14193 if (pi->peer != peer)
14194 continue;
14195
14196 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14197 continue;
14198
7d3cae70 14199 route_vty_out_tmp(vty, dest,
f20ce998
DS
14200 bgp_dest_get_prefix(dest),
14201 pi->attr, safi, use_json,
14202 json_ar, wide);
d9478df0 14203 (*output_count)++;
f20ce998 14204 }
d62a17ae 14205 }
14206 }
a636c635 14207}
2a71e9ce 14208
d62a17ae 14209static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14210 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14211 const char *rmap_name, uint16_t show_flags)
0b16f239 14212{
d9478df0
TA
14213 struct bgp *bgp;
14214 struct bgp_table *table;
d62a17ae 14215 json_object *json = NULL;
d9478df0
TA
14216 json_object *json_scode = NULL;
14217 json_object *json_ocode = NULL;
14218 json_object *json_ar = NULL;
96f3485c 14219 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14220
d9478df0
TA
14221 /* Init BGP headers here so they're only displayed once
14222 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14223 */
14224 int header1 = 1;
14225 int header2 = 1;
14226
14227 /*
14228 * Initialize variables for each RD
14229 * All prefixes under an RD is aggregated within "json_routes"
14230 */
14231 char rd_str[BUFSIZ] = {0};
14232 json_object *json_routes = NULL;
14233
14234
14235 /* For 2-tier tables, prefix counts need to be
14236 * maintained across multiple runs of show_adj_route()
14237 */
14238 unsigned long output_count_per_rd;
14239 unsigned long filtered_count_per_rd;
14240 unsigned long output_count = 0;
14241 unsigned long filtered_count = 0;
14242
14243 if (use_json) {
d62a17ae 14244 json = json_object_new_object();
d9478df0
TA
14245 json_ar = json_object_new_object();
14246 json_scode = json_object_new_object();
14247 json_ocode = json_object_new_object();
dd426a51
DA
14248#if CONFDATE > 20231208
14249CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14250#endif
d9478df0
TA
14251 json_object_string_add(json_scode, "suppressed", "s");
14252 json_object_string_add(json_scode, "damped", "d");
14253 json_object_string_add(json_scode, "history", "h");
14254 json_object_string_add(json_scode, "valid", "*");
14255 json_object_string_add(json_scode, "best", ">");
14256 json_object_string_add(json_scode, "multipath", "=");
14257 json_object_string_add(json_scode, "internal", "i");
14258 json_object_string_add(json_scode, "ribFailure", "r");
14259 json_object_string_add(json_scode, "stale", "S");
14260 json_object_string_add(json_scode, "removed", "R");
14261
dd426a51
DA
14262#if CONFDATE > 20231208
14263CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14264#endif
d9478df0
TA
14265 json_object_string_add(json_ocode, "igp", "i");
14266 json_object_string_add(json_ocode, "egp", "e");
14267 json_object_string_add(json_ocode, "incomplete", "?");
14268 }
0b16f239 14269
d62a17ae 14270 if (!peer || !peer->afc[afi][safi]) {
14271 if (use_json) {
14272 json_object_string_add(
14273 json, "warning",
14274 "No such neighbor or address family");
14275 vty_out(vty, "%s\n", json_object_to_json_string(json));
14276 json_object_free(json);
690c3134
MW
14277 json_object_free(json_ar);
14278 json_object_free(json_scode);
14279 json_object_free(json_ocode);
d62a17ae 14280 } else
14281 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14282
d62a17ae 14283 return CMD_WARNING;
14284 }
14285
6392aaa6
PM
14286 if ((type == bgp_show_adj_route_received
14287 || type == bgp_show_adj_route_filtered)
d62a17ae 14288 && !CHECK_FLAG(peer->af_flags[afi][safi],
14289 PEER_FLAG_SOFT_RECONFIG)) {
14290 if (use_json) {
14291 json_object_string_add(
14292 json, "warning",
14293 "Inbound soft reconfiguration not enabled");
14294 vty_out(vty, "%s\n", json_object_to_json_string(json));
14295 json_object_free(json);
690c3134
MW
14296 json_object_free(json_ar);
14297 json_object_free(json_scode);
14298 json_object_free(json_ocode);
d62a17ae 14299 } else
14300 vty_out(vty,
14301 "%% Inbound soft reconfiguration not enabled\n");
14302
14303 return CMD_WARNING;
14304 }
0b16f239 14305
d9478df0
TA
14306 bgp = peer->bgp;
14307
14308 /* labeled-unicast routes live in the unicast table */
14309 if (safi == SAFI_LABELED_UNICAST)
14310 table = bgp->rib[afi][SAFI_UNICAST];
14311 else
14312 table = bgp->rib[afi][safi];
14313
14314 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14315 || (safi == SAFI_EVPN)) {
14316
14317 struct bgp_dest *dest;
14318
14319 for (dest = bgp_table_top(table); dest;
14320 dest = bgp_route_next(dest)) {
14321 table = bgp_dest_get_bgp_table_info(dest);
14322 if (!table)
14323 continue;
14324
14325 output_count_per_rd = 0;
14326 filtered_count_per_rd = 0;
14327
14328 if (use_json)
14329 json_routes = json_object_new_object();
14330
14331 const struct prefix_rd *prd;
14332 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14333 dest);
14334
14335 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14336
14337 show_adj_route(vty, peer, table, afi, safi, type,
14338 rmap_name, json, json_routes, json_scode,
14339 json_ocode, show_flags, &header1,
14340 &header2, rd_str, &output_count_per_rd,
14341 &filtered_count_per_rd);
14342
14343 /* Don't include an empty RD in the output! */
14344 if (json_routes && (output_count_per_rd > 0))
14345 json_object_object_add(json_ar, rd_str,
14346 json_routes);
14347
14348 output_count += output_count_per_rd;
14349 filtered_count += filtered_count_per_rd;
14350 }
14351 } else
14352 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14353 json, json_ar, json_scode, json_ocode,
14354 show_flags, &header1, &header2, rd_str,
14355 &output_count, &filtered_count);
14356
14357 if (use_json) {
c1984955
TA
14358 if (type == bgp_show_adj_route_advertised)
14359 json_object_object_add(json, "advertisedRoutes",
14360 json_ar);
14361 else
14362 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14363 json_object_int_add(json, "totalPrefixCounter", output_count);
14364 json_object_int_add(json, "filteredPrefixCounter",
14365 filtered_count);
14366
690c3134
MW
14367 /*
14368 * These fields only give up ownership to `json` when `header1`
14369 * is used (set to zero). See code in `show_adj_route` and
14370 * `show_adj_route_header`.
14371 */
14372 if (header1 == 1) {
d9478df0
TA
14373 json_object_free(json_scode);
14374 json_object_free(json_ocode);
14375 }
14376
75eeda93 14377 vty_json(vty, json);
d9478df0
TA
14378 } else if (output_count > 0) {
14379 if (filtered_count > 0)
14380 vty_out(vty,
14381 "\nTotal number of prefixes %ld (%ld filtered)\n",
14382 output_count, filtered_count);
14383 else
14384 vty_out(vty, "\nTotal number of prefixes %ld\n",
14385 output_count);
14386 }
0b16f239 14387
d62a17ae 14388 return CMD_SUCCESS;
a636c635 14389}
50ef26d4 14390
f20ce998
DS
14391DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14392 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14393 "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 [json$uj | wide$wide]",
14394 SHOW_STR
14395 IP_STR
14396 BGP_STR
14397 BGP_INSTANCE_HELP_STR
14398 BGP_AFI_HELP_STR
14399 BGP_SAFI_WITH_LABEL_HELP_STR
14400 "Detailed information on TCP and BGP neighbor connections\n"
14401 "Neighbor to display information about\n"
14402 "Neighbor to display information about\n"
14403 "Neighbor on BGP configured interface\n"
14404 "Display the routes selected by best path\n"
14405 JSON_STR
14406 "Increase table width for longer prefixes\n")
14407{
14408 afi_t afi = AFI_IP6;
14409 safi_t safi = SAFI_UNICAST;
14410 char *rmap_name = NULL;
14411 char *peerstr = NULL;
14412 struct bgp *bgp = NULL;
14413 struct peer *peer;
14414 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14415 int idx = 0;
96c81f66 14416 uint16_t show_flags = 0;
96f3485c
MK
14417
14418 if (uj)
14419 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14420
14421 if (wide)
14422 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14423
14424 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14425 &bgp, uj);
14426
14427 if (!idx)
14428 return CMD_WARNING;
14429
14430 argv_find(argv, argc, "neighbors", &idx);
14431 peerstr = argv[++idx]->arg;
14432
14433 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14434 if (!peer)
14435 return CMD_WARNING;
14436
96f3485c
MK
14437 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14438 show_flags);
f20ce998
DS
14439}
14440
e960b4ca
TA
14441DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14442 show_ip_bgp_instance_neighbor_advertised_route_cmd,
14443 "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] [detail$detail] [json$uj | wide$wide]",
14444 SHOW_STR
14445 IP_STR
14446 BGP_STR
14447 BGP_INSTANCE_HELP_STR
14448 BGP_AFI_HELP_STR
14449 BGP_SAFI_WITH_LABEL_HELP_STR
14450 "Display the entries for all address families\n"
14451 "Detailed information on TCP and BGP neighbor connections\n"
14452 "Neighbor to display information about\n"
14453 "Neighbor to display information about\n"
14454 "Neighbor on BGP configured interface\n"
14455 "Display the routes advertised to a BGP neighbor\n"
14456 "Display the received routes from neighbor\n"
14457 "Display the filtered routes received from neighbor\n"
14458 "Route-map to modify the attributes\n"
14459 "Name of the route map\n"
14460 "Display detailed version of routes\n"
14461 JSON_STR
14462 "Increase table width for longer prefixes\n")
718e3744 14463{
d62a17ae 14464 afi_t afi = AFI_IP6;
14465 safi_t safi = SAFI_UNICAST;
d62a17ae 14466 char *peerstr = NULL;
d62a17ae 14467 struct bgp *bgp = NULL;
14468 struct peer *peer;
6392aaa6 14469 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14470 int idx = 0;
96f3485c 14471 bool first = true;
96c81f66 14472 uint16_t show_flags = 0;
75ce3b14
DA
14473 struct listnode *node;
14474 struct bgp *abgp;
6392aaa6 14475
e960b4ca
TA
14476 if (detail)
14477 SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14478
96f3485c 14479 if (uj) {
d62a17ae 14480 argc--;
96f3485c
MK
14481 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14482 }
14483
14484 if (all) {
14485 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14486 if (argv_find(argv, argc, "ipv4", &idx))
14487 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14488
14489 if (argv_find(argv, argc, "ipv6", &idx))
14490 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14491 }
14492
14493 if (wide)
14494 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14495
9f049418
DS
14496 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14497 &bgp, uj);
14498 if (!idx)
14499 return CMD_WARNING;
14500
d62a17ae 14501 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14502 argv_find(argv, argc, "neighbors", &idx);
14503 peerstr = argv[++idx]->arg;
8c3deaae 14504
d62a17ae 14505 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14506 if (!peer)
14507 return CMD_WARNING;
856ca177 14508
d62a17ae 14509 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14510 type = bgp_show_adj_route_advertised;
14511 else if (argv_find(argv, argc, "received-routes", &idx))
14512 type = bgp_show_adj_route_received;
14513 else if (argv_find(argv, argc, "filtered-routes", &idx))
14514 type = bgp_show_adj_route_filtered;
14515
96f3485c 14516 if (!all)
70dd370f 14517 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14518 show_flags);
14519 if (uj)
14520 vty_out(vty, "{\n");
14521
14522 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14523 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14524 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14525 : AFI_IP6;
75ce3b14
DA
14526 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14527 FOREACH_SAFI (safi) {
14528 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14529 continue;
96f3485c 14530
75ce3b14
DA
14531 if (uj) {
14532 if (first)
14533 first = false;
14534 else
14535 vty_out(vty, ",\n");
14536 vty_out(vty, "\"%s\":",
14537 get_afi_safi_str(afi, safi,
14538 true));
14539 } else
14540 vty_out(vty,
14541 "\nFor address family: %s\n",
14542 get_afi_safi_str(afi, safi,
14543 false));
96f3485c 14544
75ce3b14 14545 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14546 route_map, show_flags);
75ce3b14 14547 }
96f3485c
MK
14548 }
14549 } else {
75ce3b14
DA
14550 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14551 FOREACH_AFI_SAFI (afi, safi) {
14552 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14553 continue;
96f3485c 14554
75ce3b14
DA
14555 if (uj) {
14556 if (first)
14557 first = false;
14558 else
14559 vty_out(vty, ",\n");
14560 vty_out(vty, "\"%s\":",
14561 get_afi_safi_str(afi, safi,
14562 true));
14563 } else
14564 vty_out(vty,
14565 "\nFor address family: %s\n",
14566 get_afi_safi_str(afi, safi,
14567 false));
96f3485c 14568
75ce3b14 14569 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14570 route_map, show_flags);
75ce3b14 14571 }
96f3485c
MK
14572 }
14573 }
14574 if (uj)
14575 vty_out(vty, "}\n");
14576
14577 return CMD_SUCCESS;
95cbbd2a
ML
14578}
14579
718e3744 14580DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14581 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14582 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14583 SHOW_STR
14584 IP_STR
14585 BGP_STR
d3120452 14586 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14587 BGP_AF_STR
14588 BGP_AF_STR
14589 BGP_AF_MODIFIER_STR
718e3744 14590 "Detailed information on TCP and BGP neighbor connections\n"
14591 "Neighbor to display information about\n"
14592 "Neighbor to display information about\n"
91d37724 14593 "Neighbor on BGP configured interface\n"
718e3744 14594 "Display information received from a BGP neighbor\n"
856ca177 14595 "Display the prefixlist filter\n"
9973d184 14596 JSON_STR)
718e3744 14597{
d62a17ae 14598 afi_t afi = AFI_IP6;
14599 safi_t safi = SAFI_UNICAST;
14600 char *peerstr = NULL;
d62a17ae 14601 char name[BUFSIZ];
d62a17ae 14602 struct peer *peer;
d3120452 14603 int count;
d62a17ae 14604 int idx = 0;
d3120452
IR
14605 struct bgp *bgp = NULL;
14606 bool uj = use_json(argc, argv);
14607
14608 if (uj)
14609 argc--;
14610
14611 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14612 &bgp, uj);
14613 if (!idx)
14614 return CMD_WARNING;
d62a17ae 14615
d62a17ae 14616 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14617 argv_find(argv, argc, "neighbors", &idx);
14618 peerstr = argv[++idx]->arg;
14619
d3120452
IR
14620 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14621 if (!peer)
14622 return CMD_WARNING;
718e3744 14623
4ced1a2c 14624 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14625 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14626 if (count) {
14627 if (!uj)
14628 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14629 get_afi_safi_str(afi, safi, false));
d62a17ae 14630 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14631 } else {
14632 if (uj)
14633 vty_out(vty, "{}\n");
14634 else
14635 vty_out(vty, "No functional output\n");
14636 }
718e3744 14637
d62a17ae 14638 return CMD_SUCCESS;
14639}
14640
14641static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14642 afi_t afi, safi_t safi,
9f049418 14643 enum bgp_show_type type, bool use_json)
d62a17ae 14644{
96c81f66 14645 uint16_t show_flags = 0;
96f3485c
MK
14646
14647 if (use_json)
14648 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14649
d62a17ae 14650 if (!peer || !peer->afc[afi][safi]) {
14651 if (use_json) {
14652 json_object *json_no = NULL;
14653 json_no = json_object_new_object();
14654 json_object_string_add(
14655 json_no, "warning",
14656 "No such neighbor or address family");
14657 vty_out(vty, "%s\n",
14658 json_object_to_json_string(json_no));
14659 json_object_free(json_no);
14660 } else
14661 vty_out(vty, "%% No such neighbor or address family\n");
14662 return CMD_WARNING;
14663 }
47fc97cc 14664
7daf25a3
TA
14665 /* labeled-unicast routes live in the unicast table */
14666 if (safi == SAFI_LABELED_UNICAST)
14667 safi = SAFI_UNICAST;
14668
1e2ce4f1
DS
14669 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14670 RPKI_NOT_BEING_USED);
718e3744 14671}
14672
dba3c1d3
PG
14673DEFUN (show_ip_bgp_flowspec_routes_detailed,
14674 show_ip_bgp_flowspec_routes_detailed_cmd,
14675 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14676 SHOW_STR
14677 IP_STR
14678 BGP_STR
14679 BGP_INSTANCE_HELP_STR
14680 BGP_AFI_HELP_STR
14681 "SAFI Flowspec\n"
14682 "Detailed information on flowspec entries\n"
14683 JSON_STR)
14684{
458c1475 14685 afi_t afi = AFI_IP6;
dba3c1d3
PG
14686 safi_t safi = SAFI_UNICAST;
14687 struct bgp *bgp = NULL;
14688 int idx = 0;
9f049418 14689 bool uj = use_json(argc, argv);
81dcd881 14690 uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
9f049418 14691
96f3485c 14692 if (uj) {
9f049418 14693 argc--;
96f3485c
MK
14694 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14695 }
dba3c1d3
PG
14696
14697 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14698 &bgp, uj);
dba3c1d3
PG
14699 if (!idx)
14700 return CMD_WARNING;
14701
96f3485c 14702 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14703 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14704}
14705
718e3744 14706DEFUN (show_ip_bgp_neighbor_routes,
14707 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14708 "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 14709 SHOW_STR
14710 IP_STR
14711 BGP_STR
8386ac43 14712 BGP_INSTANCE_HELP_STR
4f280b15 14713 BGP_AFI_HELP_STR
4dd6177e 14714 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14715 "Detailed information on TCP and BGP neighbor connections\n"
14716 "Neighbor to display information about\n"
14717 "Neighbor to display information about\n"
91d37724 14718 "Neighbor on BGP configured interface\n"
2525cf39 14719 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14720 "Display the dampened routes received from neighbor\n"
14721 "Display routes learned from neighbor\n"
9973d184 14722 JSON_STR)
718e3744 14723{
d62a17ae 14724 char *peerstr = NULL;
14725 struct bgp *bgp = NULL;
14726 afi_t afi = AFI_IP6;
14727 safi_t safi = SAFI_UNICAST;
14728 struct peer *peer;
14729 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14730 int idx = 0;
9f049418
DS
14731 bool uj = use_json(argc, argv);
14732
14733 if (uj)
14734 argc--;
bb46e94f 14735
d62a17ae 14736 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14737 &bgp, uj);
d62a17ae 14738 if (!idx)
14739 return CMD_WARNING;
c493f2d8 14740
d62a17ae 14741 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14742 argv_find(argv, argc, "neighbors", &idx);
14743 peerstr = argv[++idx]->arg;
8c3deaae 14744
d62a17ae 14745 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14746 if (!peer)
d62a17ae 14747 return CMD_WARNING;
bb46e94f 14748
d62a17ae 14749 if (argv_find(argv, argc, "flap-statistics", &idx))
14750 sh_type = bgp_show_type_flap_neighbor;
14751 else if (argv_find(argv, argc, "dampened-routes", &idx))
14752 sh_type = bgp_show_type_damp_neighbor;
14753 else if (argv_find(argv, argc, "routes", &idx))
14754 sh_type = bgp_show_type_neighbor;
2525cf39 14755
d62a17ae 14756 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14757}
6b0655a2 14758
734b349e 14759struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14760
d62a17ae 14761struct bgp_distance {
14762 /* Distance value for the IP source prefix. */
d7c0a89a 14763 uint8_t distance;
718e3744 14764
d62a17ae 14765 /* Name of the access-list to be matched. */
14766 char *access_list;
718e3744 14767};
14768
4f280b15
LB
14769DEFUN (show_bgp_afi_vpn_rd_route,
14770 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14771 "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
14772 SHOW_STR
14773 BGP_STR
14774 BGP_AFI_HELP_STR
00e6edb9 14775 BGP_AF_MODIFIER_STR
4f280b15
LB
14776 "Display information for a route distinguisher\n"
14777 "Route Distinguisher\n"
a111dd97 14778 "All Route Distinguishers\n"
7395a2c9
DS
14779 "Network in the BGP routing table to display\n"
14780 "Network in the BGP routing table to display\n"
14781 JSON_STR)
4f280b15 14782{
d62a17ae 14783 int ret;
14784 struct prefix_rd prd;
14785 afi_t afi = AFI_MAX;
14786 int idx = 0;
4f280b15 14787
ff6566f3
DS
14788 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14789 vty_out(vty, "%% Malformed Address Family\n");
14790 return CMD_WARNING;
14791 }
14792
a111dd97
TA
14793 if (!strcmp(argv[5]->arg, "all"))
14794 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14795 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14796 RPKI_NOT_BEING_USED,
14797 use_json(argc, argv));
14798
d62a17ae 14799 ret = str2prefix_rd(argv[5]->arg, &prd);
14800 if (!ret) {
14801 vty_out(vty, "%% Malformed Route Distinguisher\n");
14802 return CMD_WARNING;
14803 }
ff6566f3 14804
d62a17ae 14805 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14806 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14807 use_json(argc, argv));
4f280b15
LB
14808}
14809
d62a17ae 14810static struct bgp_distance *bgp_distance_new(void)
718e3744 14811{
d62a17ae 14812 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14813}
14814
d62a17ae 14815static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14816{
d62a17ae 14817 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14818}
14819
585f1adc
IR
14820static int bgp_distance_set(struct vty *vty, const char *distance_str,
14821 const char *ip_str, const char *access_list_str)
718e3744 14822{
d62a17ae 14823 int ret;
585f1adc
IR
14824 afi_t afi;
14825 safi_t safi;
d62a17ae 14826 struct prefix p;
585f1adc 14827 uint8_t distance;
9bcb3eef 14828 struct bgp_dest *dest;
d62a17ae 14829 struct bgp_distance *bdistance;
718e3744 14830
585f1adc
IR
14831 afi = bgp_node_afi(vty);
14832 safi = bgp_node_safi(vty);
14833
d62a17ae 14834 ret = str2prefix(ip_str, &p);
14835 if (ret == 0) {
585f1adc 14836 vty_out(vty, "Malformed prefix\n");
d62a17ae 14837 return CMD_WARNING_CONFIG_FAILED;
14838 }
718e3744 14839
585f1adc
IR
14840 distance = atoi(distance_str);
14841
d62a17ae 14842 /* Get BGP distance node. */
9bcb3eef
DS
14843 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14844 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14845 if (bdistance)
9bcb3eef 14846 bgp_dest_unlock_node(dest);
ca2e160d 14847 else {
d62a17ae 14848 bdistance = bgp_distance_new();
9bcb3eef 14849 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14850 }
718e3744 14851
d62a17ae 14852 /* Set distance value. */
14853 bdistance->distance = distance;
718e3744 14854
d62a17ae 14855 /* Reset access-list configuration. */
e1b36e13 14856 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14857 if (access_list_str)
14858 bdistance->access_list =
14859 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14860
d62a17ae 14861 return CMD_SUCCESS;
718e3744 14862}
14863
585f1adc
IR
14864static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14865 const char *ip_str, const char *access_list_str)
718e3744 14866{
d62a17ae 14867 int ret;
585f1adc
IR
14868 afi_t afi;
14869 safi_t safi;
d62a17ae 14870 struct prefix p;
585f1adc 14871 int distance;
9bcb3eef 14872 struct bgp_dest *dest;
d62a17ae 14873 struct bgp_distance *bdistance;
718e3744 14874
585f1adc
IR
14875 afi = bgp_node_afi(vty);
14876 safi = bgp_node_safi(vty);
14877
d62a17ae 14878 ret = str2prefix(ip_str, &p);
14879 if (ret == 0) {
585f1adc 14880 vty_out(vty, "Malformed prefix\n");
d62a17ae 14881 return CMD_WARNING_CONFIG_FAILED;
14882 }
718e3744 14883
9bcb3eef
DS
14884 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14885 if (!dest) {
585f1adc 14886 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14887 return CMD_WARNING_CONFIG_FAILED;
14888 }
718e3744 14889
9bcb3eef 14890 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14891 distance = atoi(distance_str);
1f9a9fff 14892
d62a17ae 14893 if (bdistance->distance != distance) {
585f1adc 14894 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14895 bgp_dest_unlock_node(dest);
d62a17ae 14896 return CMD_WARNING_CONFIG_FAILED;
14897 }
718e3744 14898
0a22ddfb 14899 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14900 bgp_distance_free(bdistance);
718e3744 14901
9bcb3eef
DS
14902 bgp_dest_set_bgp_path_info(dest, NULL);
14903 bgp_dest_unlock_node(dest);
14904 bgp_dest_unlock_node(dest);
718e3744 14905
d62a17ae 14906 return CMD_SUCCESS;
718e3744 14907}
14908
718e3744 14909/* Apply BGP information to distance method. */
b8685f9b 14910uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14911 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14912{
9bcb3eef 14913 struct bgp_dest *dest;
801bb996 14914 struct prefix q = {0};
d62a17ae 14915 struct peer *peer;
14916 struct bgp_distance *bdistance;
14917 struct access_list *alist;
14918 struct bgp_static *bgp_static;
a04f1c42 14919 struct bgp_path_info *bpi_ultimate;
d62a17ae 14920
14921 if (!bgp)
14922 return 0;
14923
40381db7 14924 peer = pinfo->peer;
d62a17ae 14925
7b7d48e5
DS
14926 if (pinfo->attr->distance)
14927 return pinfo->attr->distance;
14928
a04f1c42
PG
14929 /* get peer origin to calculate appropriate distance */
14930 if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
14931 bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
14932 peer = bpi_ultimate->peer;
14933 }
14934
801bb996
CS
14935 /* Check source address.
14936 * Note: for aggregate route, peer can have unspec af type.
14937 */
14938 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14939 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14940 return 0;
14941
9bcb3eef
DS
14942 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14943 if (dest) {
14944 bdistance = bgp_dest_get_bgp_distance_info(dest);
14945 bgp_dest_unlock_node(dest);
d62a17ae 14946
14947 if (bdistance->access_list) {
14948 alist = access_list_lookup(afi, bdistance->access_list);
14949 if (alist
14950 && access_list_apply(alist, p) == FILTER_PERMIT)
14951 return bdistance->distance;
14952 } else
14953 return bdistance->distance;
718e3744 14954 }
718e3744 14955
d62a17ae 14956 /* Backdoor check. */
9bcb3eef
DS
14957 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14958 if (dest) {
14959 bgp_static = bgp_dest_get_bgp_static_info(dest);
14960 bgp_dest_unlock_node(dest);
718e3744 14961
d62a17ae 14962 if (bgp_static->backdoor) {
14963 if (bgp->distance_local[afi][safi])
14964 return bgp->distance_local[afi][safi];
14965 else
14966 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14967 }
718e3744 14968 }
718e3744 14969
d62a17ae 14970 if (peer->sort == BGP_PEER_EBGP) {
14971 if (bgp->distance_ebgp[afi][safi])
14972 return bgp->distance_ebgp[afi][safi];
14973 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14974 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14975 if (bgp->distance_ibgp[afi][safi])
14976 return bgp->distance_ibgp[afi][safi];
14977 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14978 } else {
14979 if (bgp->distance_local[afi][safi])
14980 return bgp->distance_local[afi][safi];
14981 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14982 }
718e3744 14983}
14984
a612fb77
DA
14985/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14986 * we should tell ZEBRA update the routes for a specific
14987 * AFI/SAFI to reflect changes in RIB.
14988 */
585f1adc
IR
14989static void bgp_announce_routes_distance_update(struct bgp *bgp,
14990 afi_t update_afi,
14991 safi_t update_safi)
a612fb77
DA
14992{
14993 afi_t afi;
14994 safi_t safi;
14995
14996 FOREACH_AFI_SAFI (afi, safi) {
14997 if (!bgp_fibupd_safi(safi))
14998 continue;
14999
8b54bc30
DA
15000 if (afi != update_afi && safi != update_safi)
15001 continue;
15002
15003 if (BGP_DEBUG(zebra, ZEBRA))
15004 zlog_debug(
15005 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15006 __func__, afi, safi);
15007 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15008 }
15009}
15010
585f1adc
IR
15011DEFUN (bgp_distance,
15012 bgp_distance_cmd,
15013 "distance bgp (1-255) (1-255) (1-255)",
15014 "Define an administrative distance\n"
15015 "BGP distance\n"
15016 "Distance for routes external to the AS\n"
15017 "Distance for routes internal to the AS\n"
15018 "Distance for local routes\n")
718e3744 15019{
585f1adc 15020 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15021 int idx_number = 2;
15022 int idx_number_2 = 3;
15023 int idx_number_3 = 4;
585f1adc
IR
15024 int distance_ebgp = atoi(argv[idx_number]->arg);
15025 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15026 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15027 afi_t afi;
15028 safi_t safi;
718e3744 15029
d62a17ae 15030 afi = bgp_node_afi(vty);
15031 safi = bgp_node_safi(vty);
718e3744 15032
585f1adc
IR
15033 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15034 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15035 || bgp->distance_local[afi][safi] != distance_local) {
15036 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15037 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15038 bgp->distance_local[afi][safi] = distance_local;
15039 bgp_announce_routes_distance_update(bgp, afi, safi);
15040 }
15041 return CMD_SUCCESS;
15042}
37a87b8f 15043
585f1adc
IR
15044DEFUN (no_bgp_distance,
15045 no_bgp_distance_cmd,
15046 "no distance bgp [(1-255) (1-255) (1-255)]",
15047 NO_STR
15048 "Define an administrative distance\n"
15049 "BGP distance\n"
15050 "Distance for routes external to the AS\n"
15051 "Distance for routes internal to the AS\n"
15052 "Distance for local routes\n")
718e3744 15053{
585f1adc 15054 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15055 afi_t afi;
15056 safi_t safi;
37a87b8f
CS
15057
15058 afi = bgp_node_afi(vty);
15059 safi = bgp_node_safi(vty);
15060
585f1adc
IR
15061 if (bgp->distance_ebgp[afi][safi] != 0
15062 || bgp->distance_ibgp[afi][safi] != 0
15063 || bgp->distance_local[afi][safi] != 0) {
15064 bgp->distance_ebgp[afi][safi] = 0;
15065 bgp->distance_ibgp[afi][safi] = 0;
15066 bgp->distance_local[afi][safi] = 0;
15067 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15068 }
585f1adc
IR
15069 return CMD_SUCCESS;
15070}
37a87b8f 15071
37a87b8f 15072
585f1adc
IR
15073DEFUN (bgp_distance_source,
15074 bgp_distance_source_cmd,
15075 "distance (1-255) A.B.C.D/M",
15076 "Define an administrative distance\n"
15077 "Administrative distance\n"
15078 "IP source prefix\n")
15079{
15080 int idx_number = 1;
15081 int idx_ipv4_prefixlen = 2;
15082 bgp_distance_set(vty, argv[idx_number]->arg,
15083 argv[idx_ipv4_prefixlen]->arg, NULL);
15084 return CMD_SUCCESS;
734b349e
MZ
15085}
15086
585f1adc
IR
15087DEFUN (no_bgp_distance_source,
15088 no_bgp_distance_source_cmd,
15089 "no distance (1-255) A.B.C.D/M",
15090 NO_STR
15091 "Define an administrative distance\n"
15092 "Administrative distance\n"
15093 "IP source prefix\n")
37a87b8f 15094{
585f1adc
IR
15095 int idx_number = 2;
15096 int idx_ipv4_prefixlen = 3;
15097 bgp_distance_unset(vty, argv[idx_number]->arg,
15098 argv[idx_ipv4_prefixlen]->arg, NULL);
15099 return CMD_SUCCESS;
37a87b8f
CS
15100}
15101
585f1adc
IR
15102DEFUN (bgp_distance_source_access_list,
15103 bgp_distance_source_access_list_cmd,
15104 "distance (1-255) A.B.C.D/M WORD",
15105 "Define an administrative distance\n"
15106 "Administrative distance\n"
15107 "IP source prefix\n"
15108 "Access list name\n")
37a87b8f 15109{
585f1adc
IR
15110 int idx_number = 1;
15111 int idx_ipv4_prefixlen = 2;
15112 int idx_word = 3;
15113 bgp_distance_set(vty, argv[idx_number]->arg,
15114 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15115 return CMD_SUCCESS;
15116}
718e3744 15117
585f1adc
IR
15118DEFUN (no_bgp_distance_source_access_list,
15119 no_bgp_distance_source_access_list_cmd,
15120 "no distance (1-255) A.B.C.D/M WORD",
15121 NO_STR
15122 "Define an administrative distance\n"
15123 "Administrative distance\n"
15124 "IP source prefix\n"
15125 "Access list name\n")
15126{
15127 int idx_number = 2;
15128 int idx_ipv4_prefixlen = 3;
15129 int idx_word = 4;
15130 bgp_distance_unset(vty, argv[idx_number]->arg,
15131 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15132 return CMD_SUCCESS;
15133}
37a87b8f 15134
585f1adc
IR
15135DEFUN (ipv6_bgp_distance_source,
15136 ipv6_bgp_distance_source_cmd,
15137 "distance (1-255) X:X::X:X/M",
15138 "Define an administrative distance\n"
15139 "Administrative distance\n"
15140 "IP source prefix\n")
15141{
15142 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15143 return CMD_SUCCESS;
15144}
7ebe9748 15145
585f1adc
IR
15146DEFUN (no_ipv6_bgp_distance_source,
15147 no_ipv6_bgp_distance_source_cmd,
15148 "no distance (1-255) X:X::X:X/M",
15149 NO_STR
15150 "Define an administrative distance\n"
15151 "Administrative distance\n"
15152 "IP source prefix\n")
15153{
15154 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15155 return CMD_SUCCESS;
15156}
37a87b8f 15157
585f1adc
IR
15158DEFUN (ipv6_bgp_distance_source_access_list,
15159 ipv6_bgp_distance_source_access_list_cmd,
15160 "distance (1-255) X:X::X:X/M WORD",
15161 "Define an administrative distance\n"
15162 "Administrative distance\n"
15163 "IP source prefix\n"
15164 "Access list name\n")
15165{
15166 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15167 return CMD_SUCCESS;
718e3744 15168}
15169
585f1adc
IR
15170DEFUN (no_ipv6_bgp_distance_source_access_list,
15171 no_ipv6_bgp_distance_source_access_list_cmd,
15172 "no distance (1-255) X:X::X:X/M WORD",
15173 NO_STR
15174 "Define an administrative distance\n"
15175 "Administrative distance\n"
15176 "IP source prefix\n"
15177 "Access list name\n")
718e3744 15178{
585f1adc
IR
15179 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15180 return CMD_SUCCESS;
15181}
37a87b8f 15182
585f1adc
IR
15183DEFUN (bgp_damp_set,
15184 bgp_damp_set_cmd,
a30fec23 15185 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15186 "BGP Specific commands\n"
15187 "Enable route-flap dampening\n"
15188 "Half-life time for the penalty\n"
15189 "Value to start reusing a route\n"
15190 "Value to start suppressing a route\n"
15191 "Maximum duration to suppress a stable route\n")
15192{
15193 VTY_DECLVAR_CONTEXT(bgp, bgp);
15194 int idx_half_life = 2;
15195 int idx_reuse = 3;
15196 int idx_suppress = 4;
15197 int idx_max_suppress = 5;
37a87b8f
CS
15198 int half = DEFAULT_HALF_LIFE * 60;
15199 int reuse = DEFAULT_REUSE;
15200 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15201 int max = 4 * half;
15202
15203 if (argc == 6) {
15204 half = atoi(argv[idx_half_life]->arg) * 60;
15205 reuse = atoi(argv[idx_reuse]->arg);
15206 suppress = atoi(argv[idx_suppress]->arg);
15207 max = atoi(argv[idx_max_suppress]->arg) * 60;
15208 } else if (argc == 3) {
15209 half = atoi(argv[idx_half_life]->arg) * 60;
15210 max = 4 * half;
15211 }
15212
15213 /*
15214 * These can't be 0 but our SA doesn't understand the
15215 * way our cli is constructed
15216 */
15217 assert(reuse);
15218 assert(half);
15219 if (suppress < reuse) {
15220 vty_out(vty,
15221 "Suppress value cannot be less than reuse value \n");
15222 return 0;
15223 }
15224
15225 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15226 reuse, suppress, max);
15227}
15228
15229DEFUN (bgp_damp_unset,
15230 bgp_damp_unset_cmd,
a30fec23 15231 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15232 NO_STR
15233 "BGP Specific commands\n"
15234 "Enable route-flap dampening\n"
15235 "Half-life time for the penalty\n"
15236 "Value to start reusing a route\n"
15237 "Value to start suppressing a route\n"
15238 "Maximum duration to suppress a stable route\n")
15239{
15240 VTY_DECLVAR_CONTEXT(bgp, bgp);
15241 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15242}
15243
718e3744 15244/* Display specified route of BGP table. */
d62a17ae 15245static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15246 const char *ip_str, afi_t afi, safi_t safi,
15247 struct prefix_rd *prd, int prefix_check)
15248{
15249 int ret;
15250 struct prefix match;
9bcb3eef
DS
15251 struct bgp_dest *dest;
15252 struct bgp_dest *rm;
40381db7
DS
15253 struct bgp_path_info *pi;
15254 struct bgp_path_info *pi_temp;
d62a17ae 15255 struct bgp *bgp;
15256 struct bgp_table *table;
15257
15258 /* BGP structure lookup. */
15259 if (view_name) {
15260 bgp = bgp_lookup_by_name(view_name);
15261 if (bgp == NULL) {
15262 vty_out(vty, "%% Can't find BGP instance %s\n",
15263 view_name);
15264 return CMD_WARNING;
15265 }
15266 } else {
15267 bgp = bgp_get_default();
15268 if (bgp == NULL) {
15269 vty_out(vty, "%% No BGP process is configured\n");
15270 return CMD_WARNING;
15271 }
718e3744 15272 }
718e3744 15273
d62a17ae 15274 /* Check IP address argument. */
15275 ret = str2prefix(ip_str, &match);
15276 if (!ret) {
15277 vty_out(vty, "%% address is malformed\n");
15278 return CMD_WARNING;
15279 }
718e3744 15280
d62a17ae 15281 match.family = afi2family(afi);
15282
15283 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15284 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15285 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15286 dest = bgp_route_next(dest)) {
15287 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15288
9bcb3eef 15289 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15290 continue;
9bcb3eef 15291 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15292 if (!table)
ea47320b 15293 continue;
4953391b
DA
15294 rm = bgp_node_match(table, &match);
15295 if (rm == NULL)
ea47320b 15296 continue;
d62a17ae 15297
9bcb3eef 15298 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15299
ea47320b 15300 if (!prefix_check
b54892e0 15301 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15302 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15303 while (pi) {
15304 if (pi->extra && pi->extra->damp_info) {
15305 pi_temp = pi->next;
ea47320b 15306 bgp_damp_info_free(
19971c9a 15307 pi->extra->damp_info,
5c8846f6 15308 1, afi, safi);
40381db7 15309 pi = pi_temp;
ea47320b 15310 } else
40381db7 15311 pi = pi->next;
d62a17ae 15312 }
ea47320b
DL
15313 }
15314
9bcb3eef 15315 bgp_dest_unlock_node(rm);
d62a17ae 15316 }
15317 } else {
4953391b
DA
15318 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15319 if (dest != NULL) {
9bcb3eef 15320 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15321
d62a17ae 15322 if (!prefix_check
9bcb3eef
DS
15323 || dest_p->prefixlen == match.prefixlen) {
15324 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15325 while (pi) {
15326 if (pi->extra && pi->extra->damp_info) {
15327 pi_temp = pi->next;
d62a17ae 15328 bgp_damp_info_free(
19971c9a 15329 pi->extra->damp_info,
5c8846f6 15330 1, afi, safi);
40381db7 15331 pi = pi_temp;
d62a17ae 15332 } else
40381db7 15333 pi = pi->next;
d62a17ae 15334 }
15335 }
15336
9bcb3eef 15337 bgp_dest_unlock_node(dest);
d62a17ae 15338 }
15339 }
718e3744 15340
d62a17ae 15341 return CMD_SUCCESS;
718e3744 15342}
15343
15344DEFUN (clear_ip_bgp_dampening,
15345 clear_ip_bgp_dampening_cmd,
15346 "clear ip bgp dampening",
15347 CLEAR_STR
15348 IP_STR
15349 BGP_STR
15350 "Clear route flap dampening information\n")
15351{
b4f7f45b 15352 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15353 return CMD_SUCCESS;
718e3744 15354}
15355
15356DEFUN (clear_ip_bgp_dampening_prefix,
15357 clear_ip_bgp_dampening_prefix_cmd,
15358 "clear ip bgp dampening A.B.C.D/M",
15359 CLEAR_STR
15360 IP_STR
15361 BGP_STR
15362 "Clear route flap dampening information\n"
0c7b1b01 15363 "IPv4 prefix\n")
718e3744 15364{
d62a17ae 15365 int idx_ipv4_prefixlen = 4;
15366 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15367 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15368}
15369
15370DEFUN (clear_ip_bgp_dampening_address,
15371 clear_ip_bgp_dampening_address_cmd,
15372 "clear ip bgp dampening A.B.C.D",
15373 CLEAR_STR
15374 IP_STR
15375 BGP_STR
15376 "Clear route flap dampening information\n"
15377 "Network to clear damping information\n")
15378{
d62a17ae 15379 int idx_ipv4 = 4;
15380 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15381 SAFI_UNICAST, NULL, 0);
718e3744 15382}
15383
15384DEFUN (clear_ip_bgp_dampening_address_mask,
15385 clear_ip_bgp_dampening_address_mask_cmd,
15386 "clear ip bgp dampening A.B.C.D A.B.C.D",
15387 CLEAR_STR
15388 IP_STR
15389 BGP_STR
15390 "Clear route flap dampening information\n"
15391 "Network to clear damping information\n"
15392 "Network mask\n")
15393{
d62a17ae 15394 int idx_ipv4 = 4;
15395 int idx_ipv4_2 = 5;
15396 int ret;
15397 char prefix_str[BUFSIZ];
718e3744 15398
d62a17ae 15399 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15400 prefix_str, sizeof(prefix_str));
d62a17ae 15401 if (!ret) {
15402 vty_out(vty, "%% Inconsistent address and mask\n");
15403 return CMD_WARNING;
15404 }
718e3744 15405
d62a17ae 15406 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15407 NULL, 0);
718e3744 15408}
6b0655a2 15409
e3b78da8 15410static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15411{
15412 struct vty *vty = arg;
e3b78da8 15413 struct peer *peer = bucket->data;
825d9834 15414
47e12884 15415 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15416}
15417
2a0e69ae
DS
15418DEFUN (show_bgp_listeners,
15419 show_bgp_listeners_cmd,
15420 "show bgp listeners",
15421 SHOW_STR
15422 BGP_STR
15423 "Display Listen Sockets and who created them\n")
15424{
15425 bgp_dump_listener_info(vty);
15426
15427 return CMD_SUCCESS;
15428}
15429
825d9834
DS
15430DEFUN (show_bgp_peerhash,
15431 show_bgp_peerhash_cmd,
15432 "show bgp peerhash",
15433 SHOW_STR
15434 BGP_STR
15435 "Display information about the BGP peerhash\n")
15436{
15437 struct list *instances = bm->bgp;
15438 struct listnode *node;
15439 struct bgp *bgp;
15440
15441 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15442 vty_out(vty, "BGP: %s\n", bgp->name);
15443 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15444 vty);
15445 }
15446
15447 return CMD_SUCCESS;
15448}
15449
587ff0fd 15450/* also used for encap safi */
2b791107
DL
15451static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15452 afi_t afi, safi_t safi)
d62a17ae 15453{
9bcb3eef
DS
15454 struct bgp_dest *pdest;
15455 struct bgp_dest *dest;
d62a17ae 15456 struct bgp_table *table;
b54892e0
DS
15457 const struct prefix *p;
15458 const struct prefix_rd *prd;
d62a17ae 15459 struct bgp_static *bgp_static;
15460 mpls_label_t label;
d62a17ae 15461
15462 /* Network configuration. */
9bcb3eef
DS
15463 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15464 pdest = bgp_route_next(pdest)) {
15465 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15466 if (!table)
ea47320b 15467 continue;
d62a17ae 15468
9bcb3eef
DS
15469 for (dest = bgp_table_top(table); dest;
15470 dest = bgp_route_next(dest)) {
15471 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15472 if (bgp_static == NULL)
ea47320b 15473 continue;
d62a17ae 15474
9bcb3eef
DS
15475 p = bgp_dest_get_prefix(dest);
15476 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15477 pdest);
d62a17ae 15478
ea47320b 15479 /* "network" configuration display. */
ea47320b
DL
15480 label = decode_label(&bgp_static->label);
15481
c4f64ea9 15482 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15483 if (safi == SAFI_MPLS_VPN)
15484 vty_out(vty, " label %u", label);
15485
15486 if (bgp_static->rmap.name)
15487 vty_out(vty, " route-map %s",
15488 bgp_static->rmap.name);
e2a86ad9
DS
15489
15490 if (bgp_static->backdoor)
15491 vty_out(vty, " backdoor");
15492
ea47320b
DL
15493 vty_out(vty, "\n");
15494 }
15495 }
d62a17ae 15496}
15497
2b791107
DL
15498static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15499 afi_t afi, safi_t safi)
d62a17ae 15500{
9bcb3eef
DS
15501 struct bgp_dest *pdest;
15502 struct bgp_dest *dest;
d62a17ae 15503 struct bgp_table *table;
b54892e0
DS
15504 const struct prefix *p;
15505 const struct prefix_rd *prd;
d62a17ae 15506 struct bgp_static *bgp_static;
ff44f570 15507 char buf[PREFIX_STRLEN * 2];
d62a17ae 15508 char buf2[SU_ADDRSTRLEN];
5f933e1e 15509 char esi_buf[ESI_STR_LEN];
d62a17ae 15510
15511 /* Network configuration. */
9bcb3eef
DS
15512 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15513 pdest = bgp_route_next(pdest)) {
15514 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15515 if (!table)
ea47320b 15516 continue;
d62a17ae 15517
9bcb3eef
DS
15518 for (dest = bgp_table_top(table); dest;
15519 dest = bgp_route_next(dest)) {
15520 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15521 if (bgp_static == NULL)
ea47320b 15522 continue;
d62a17ae 15523
ea47320b 15524 char *macrouter = NULL;
d62a17ae 15525
ea47320b
DL
15526 if (bgp_static->router_mac)
15527 macrouter = prefix_mac2str(
15528 bgp_static->router_mac, NULL, 0);
15529 if (bgp_static->eth_s_id)
0a50c248
AK
15530 esi_to_str(bgp_static->eth_s_id,
15531 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15532 p = bgp_dest_get_prefix(dest);
15533 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15534
ea47320b 15535 /* "network" configuration display. */
197cb530
PG
15536 if (p->u.prefix_evpn.route_type == 5) {
15537 char local_buf[PREFIX_STRLEN];
07380148 15538
3714a385 15539 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15540 struct prefix_evpn *)p)
15541 ? AF_INET
15542 : AF_INET6;
3714a385 15543 inet_ntop(family,
07380148
DA
15544 &p->u.prefix_evpn.prefix_addr.ip.ip
15545 .addr,
15546 local_buf, sizeof(local_buf));
772270f3
QY
15547 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15548 p->u.prefix_evpn.prefix_addr
15549 .ip_prefix_length);
197cb530
PG
15550 } else {
15551 prefix2str(p, buf, sizeof(buf));
15552 }
ea47320b 15553
a4d82a8a
PZ
15554 if (bgp_static->gatewayIp.family == AF_INET
15555 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15556 inet_ntop(bgp_static->gatewayIp.family,
15557 &bgp_static->gatewayIp.u.prefix, buf2,
15558 sizeof(buf2));
ea47320b 15559 vty_out(vty,
c4f64ea9
DA
15560 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15561 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15562 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15563 macrouter);
15564
0a22ddfb 15565 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15566 }
15567 }
3da6fcd5
PG
15568}
15569
718e3744 15570/* Configuration of static route announcement and aggregate
15571 information. */
2b791107
DL
15572void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15573 safi_t safi)
d62a17ae 15574{
9bcb3eef 15575 struct bgp_dest *dest;
b54892e0 15576 const struct prefix *p;
d62a17ae 15577 struct bgp_static *bgp_static;
15578 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15579
2b791107
DL
15580 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15581 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15582 return;
15583 }
d62a17ae 15584
2b791107
DL
15585 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15586 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15587 return;
15588 }
d62a17ae 15589
15590 /* Network configuration. */
9bcb3eef
DS
15591 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15592 dest = bgp_route_next(dest)) {
15593 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15594 if (bgp_static == NULL)
ea47320b 15595 continue;
d62a17ae 15596
9bcb3eef 15597 p = bgp_dest_get_prefix(dest);
d62a17ae 15598
8228a9a7 15599 vty_out(vty, " network %pFX", p);
d62a17ae 15600
ea47320b
DL
15601 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15602 vty_out(vty, " label-index %u",
15603 bgp_static->label_index);
d62a17ae 15604
ea47320b
DL
15605 if (bgp_static->rmap.name)
15606 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15607
15608 if (bgp_static->backdoor)
15609 vty_out(vty, " backdoor");
718e3744 15610
ea47320b
DL
15611 vty_out(vty, "\n");
15612 }
15613
d62a17ae 15614 /* Aggregate-address configuration. */
9bcb3eef
DS
15615 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15616 dest = bgp_route_next(dest)) {
15617 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15618 if (bgp_aggregate == NULL)
ea47320b 15619 continue;
d62a17ae 15620
9bcb3eef 15621 p = bgp_dest_get_prefix(dest);
d62a17ae 15622
8228a9a7 15623 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15624
ea47320b
DL
15625 if (bgp_aggregate->as_set)
15626 vty_out(vty, " as-set");
d62a17ae 15627
ea47320b
DL
15628 if (bgp_aggregate->summary_only)
15629 vty_out(vty, " summary-only");
718e3744 15630
20894f50
DA
15631 if (bgp_aggregate->rmap.name)
15632 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15633
229757f1
DA
15634 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15635 vty_out(vty, " origin %s",
15636 bgp_origin2str(bgp_aggregate->origin));
15637
6aabb15d
RZ
15638 if (bgp_aggregate->match_med)
15639 vty_out(vty, " matching-MED-only");
15640
365ab2e7
RZ
15641 if (bgp_aggregate->suppress_map_name)
15642 vty_out(vty, " suppress-map %s",
15643 bgp_aggregate->suppress_map_name);
15644
ea47320b
DL
15645 vty_out(vty, "\n");
15646 }
d62a17ae 15647}
734b349e 15648
2b791107 15649void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15650 safi_t safi)
d62a17ae 15651{
9bcb3eef 15652 struct bgp_dest *dest;
d62a17ae 15653 struct bgp_distance *bdistance;
15654
15655 /* Distance configuration. */
15656 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15657 && bgp->distance_local[afi][safi]
15658 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15659 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15660 || bgp->distance_local[afi][safi]
15661 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15662 vty_out(vty, " distance bgp %d %d %d\n",
15663 bgp->distance_ebgp[afi][safi],
15664 bgp->distance_ibgp[afi][safi],
15665 bgp->distance_local[afi][safi]);
15666 }
734b349e 15667
9bcb3eef
DS
15668 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15669 dest = bgp_route_next(dest)) {
15670 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15671 if (bdistance != NULL)
56ca3b5b 15672 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15673 bdistance->distance, dest,
d62a17ae 15674 bdistance->access_list ? bdistance->access_list
15675 : "");
ca2e160d 15676 }
718e3744 15677}
15678
15679/* Allocate routing table structure and install commands. */
d62a17ae 15680void bgp_route_init(void)
15681{
15682 afi_t afi;
15683 safi_t safi;
15684
15685 /* Init BGP distance table. */
05c7a1cc 15686 FOREACH_AFI_SAFI (afi, safi)
960035b2 15687 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15688
15689 /* IPv4 BGP commands. */
15690 install_element(BGP_NODE, &bgp_table_map_cmd);
15691 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15692 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15693
554b3b10 15694 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15695
15696 /* IPv4 unicast configuration. */
15697 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15698 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15699 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15700
554b3b10 15701 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15702
15703 /* IPv4 multicast configuration. */
15704 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15705 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15706 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15707 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15708
15709 /* IPv4 labeled-unicast configuration. */
fb985e0c 15710 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15711 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15712
d62a17ae 15713 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15714 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15715 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15716 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15717 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15718 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15719 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15720 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15721
15722 install_element(VIEW_NODE,
15723 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15724 install_element(VIEW_NODE,
15725 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15726 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15727 install_element(VIEW_NODE,
15728 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15729#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15730 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15731#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15732 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15733 install_element(VIEW_NODE,
44c69747 15734 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15735
d62a17ae 15736 /* BGP dampening clear commands */
15737 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15738 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15739
d62a17ae 15740 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15741 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15742
15743 /* prefix count */
15744 install_element(ENABLE_NODE,
15745 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15746#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15747 install_element(ENABLE_NODE,
15748 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15749#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15750
d62a17ae 15751 /* New config IPv6 BGP commands. */
15752 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15753 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15754 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15755
554b3b10 15756 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15757
15758 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15759
fb985e0c
DA
15760 /* IPv6 labeled unicast address family. */
15761 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15762 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15763
d62a17ae 15764 install_element(BGP_NODE, &bgp_distance_cmd);
15765 install_element(BGP_NODE, &no_bgp_distance_cmd);
15766 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15767 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15768 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15769 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15770 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15771 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15772 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15773 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15774 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15775 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15776 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15777 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15778 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15779 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15780 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15781 install_element(BGP_IPV4M_NODE,
15782 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15783 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15784 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15785 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15786 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15787 install_element(BGP_IPV6_NODE,
15788 &ipv6_bgp_distance_source_access_list_cmd);
15789 install_element(BGP_IPV6_NODE,
15790 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15791 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15792 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15793 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15794 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15795 install_element(BGP_IPV6M_NODE,
15796 &ipv6_bgp_distance_source_access_list_cmd);
15797 install_element(BGP_IPV6M_NODE,
15798 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15799
ef5f4b23 15800 /* BGP dampening */
585f1adc
IR
15801 install_element(BGP_NODE, &bgp_damp_set_cmd);
15802 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15803 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15804 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15805 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15806 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15807 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15808 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15809 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15810 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15811 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15812 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15813 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15814 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15815
15816 /* Large Communities */
15817 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15818 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15819
15820 /* show bgp ipv4 flowspec detailed */
15821 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15822
2a0e69ae 15823 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15824 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15825}
15826
15827void bgp_route_finish(void)
15828{
15829 afi_t afi;
15830 safi_t safi;
15831
05c7a1cc
QY
15832 FOREACH_AFI_SAFI (afi, safi) {
15833 bgp_table_unlock(bgp_distance_table[afi][safi]);
15834 bgp_distance_table[afi][safi] = NULL;
15835 }
228da428 15836}