]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
tests: Check if labeled-unicast works correctly with addpath capability
[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"
70cd87ca 75#include "bgpd/bgp_orr.h"
6401252f 76#include "bgpd/bgp_trace.h"
fdeb5a81 77#include "bgpd/bgp_rpki.h"
718e3744 78
49e5a4a0 79#ifdef ENABLE_BGP_VNC
f8b6f499
LB
80#include "bgpd/rfapi/rfapi_backend.h"
81#include "bgpd/rfapi/vnc_import_bgp.h"
82#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 83#endif
aee875b5
PG
84#include "bgpd/bgp_encap_types.h"
85#include "bgpd/bgp_encap_tlv.h"
684a7227 86#include "bgpd/bgp_evpn.h"
0a50c248 87#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 88#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 89#include "bgpd/bgp_flowspec.h"
98a9dbc7 90#include "bgpd/bgp_flowspec_util.h"
45918cfb 91#include "bgpd/bgp_pbr.h"
65efcfce 92
e2a86ad9 93#include "bgpd/bgp_route_clippy.c"
aee875b5 94
7fd28dd2
PR
95DEFINE_HOOK(bgp_snmp_update_stats,
96 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 97 (rn, pi, added));
7fd28dd2 98
b5b99af8
DS
99DEFINE_HOOK(bgp_rpki_prefix_status,
100 (struct peer *peer, struct attr *attr,
101 const struct prefix *prefix),
8451921b 102 (peer, attr, prefix));
b5b99af8 103
718e3744 104/* Extern from bgp_dump.c */
dde72586
SH
105extern const char *bgp_origin_str[];
106extern const char *bgp_origin_long_str[];
3742de8d 107
b7d08f5a 108/* PMSI strings. */
109#define PMSI_TNLTYPE_STR_NO_INFO "No info"
110#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
111static const struct message bgp_pmsi_tnltype_str[] = {
112 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
113 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
114 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
115 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
116 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
117 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
118 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
119 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 120 {0}
121};
b7d08f5a 122
9df8b37c 123#define VRFID_NONE_STR "-"
46aeabed 124#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 125
4a11bf2c 126DEFINE_HOOK(bgp_process,
9bcb3eef
DS
127 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
128 struct peer *peer, bool withdraw),
8451921b 129 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 130
4056a5f6
RZ
131/** Test if path is suppressed. */
132static bool bgp_path_suppressed(struct bgp_path_info *pi)
133{
134 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
135 return false;
136
137 return listcount(pi->extra->aggr_suppressors) > 0;
138}
4a11bf2c 139
9bcb3eef 140struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 141 safi_t safi, const struct prefix *p,
d62a17ae 142 struct prefix_rd *prd)
143{
9bcb3eef
DS
144 struct bgp_dest *dest;
145 struct bgp_dest *pdest = NULL;
d62a17ae 146
147 assert(table);
d62a17ae 148
149 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
150 || (safi == SAFI_EVPN)) {
9bcb3eef 151 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 152
9bcb3eef
DS
153 if (!bgp_dest_has_bgp_path_info_data(pdest))
154 bgp_dest_set_bgp_table_info(
155 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 156 else
9bcb3eef
DS
157 bgp_dest_unlock_node(pdest);
158 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 159 }
718e3744 160
9bcb3eef 161 dest = bgp_node_get(table, p);
718e3744 162
d62a17ae 163 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
164 || (safi == SAFI_EVPN))
9bcb3eef 165 dest->pdest = pdest;
718e3744 166
9bcb3eef 167 return dest;
718e3744 168}
6b0655a2 169
9bcb3eef 170struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 171 safi_t safi, const struct prefix *p,
d62a17ae 172 struct prefix_rd *prd)
128ea8ab 173{
9bcb3eef
DS
174 struct bgp_dest *dest;
175 struct bgp_dest *pdest = NULL;
128ea8ab 176
d62a17ae 177 if (!table)
178 return NULL;
128ea8ab 179
d62a17ae 180 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
181 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
182 pdest = bgp_node_lookup(table, (struct prefix *)prd);
183 if (!pdest)
d62a17ae 184 return NULL;
128ea8ab 185
9bcb3eef
DS
186 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
187 bgp_dest_unlock_node(pdest);
d62a17ae 188 return NULL;
189 }
128ea8ab 190
9bcb3eef 191 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 192 }
128ea8ab 193
9bcb3eef 194 dest = bgp_node_lookup(table, p);
128ea8ab 195
9bcb3eef 196 return dest;
128ea8ab 197}
198
18ee8310
DS
199/* Allocate bgp_path_info_extra */
200static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 201{
4b7e6066
DS
202 struct bgp_path_info_extra *new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
204 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
205 new->label[0] = MPLS_INVALID_LABEL;
206 new->num_labels = 0;
3e3708cb
PG
207 new->bgp_fs_pbr = NULL;
208 new->bgp_fs_iprule = NULL;
d62a17ae 209 return new;
fb982c25
PJ
210}
211
a2e219fe 212void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 213{
4b7e6066 214 struct bgp_path_info_extra *e;
d62a17ae 215
c93a3b77
DS
216 if (!extra || !*extra)
217 return;
d62a17ae 218
c93a3b77 219 e = *extra;
4538f895 220 if (e->damp_info)
b4f7f45b
IR
221 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
222 e->damp_info->safi);
4538f895 223
c93a3b77
DS
224 e->damp_info = NULL;
225 if (e->parent) {
40381db7 226 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 227
40381db7 228 if (bpi->net) {
0e70e6c8
DL
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
232 *
40381db7
DS
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
0e70e6c8
DL
236 */
237 unsigned refcount;
238
40381db7 239 bpi = bgp_path_info_lock(bpi);
c10e14e9 240 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 241 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 242 if (!refcount)
40381db7
DS
243 bpi->net = NULL;
244 bgp_path_info_unlock(bpi);
0e70e6c8 245 }
18ee8310 246 bgp_path_info_unlock(e->parent);
c93a3b77 247 e->parent = NULL;
d62a17ae 248 }
c93a3b77
DS
249
250 if (e->bgp_orig)
251 bgp_unlock(e->bgp_orig);
c26edcda 252
4cd690ae
PG
253 if (e->peer_orig)
254 peer_unlock(e->peer_orig);
255
ff3bf9a4
DS
256 if (e->aggr_suppressors)
257 list_delete(&e->aggr_suppressors);
258
60605cbc
AK
259 if (e->mh_info)
260 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 261
ce3c0614
PG
262 if ((*extra)->bgp_fs_iprule)
263 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 264 if ((*extra)->bgp_fs_pbr)
6a154c88 265 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 266 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
267}
268
18ee8310
DS
269/* Get bgp_path_info extra information for the given bgp_path_info, lazy
270 * allocated if required.
fb982c25 271 */
40381db7 272struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 273{
40381db7
DS
274 if (!pi->extra)
275 pi->extra = bgp_path_info_extra_new();
276 return pi->extra;
fb982c25
PJ
277}
278
718e3744 279/* Free bgp route information. */
9b6d8fcf 280static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 281{
05864da7 282 bgp_attr_unintern(&path->attr);
fb018d25 283
9b6d8fcf
DS
284 bgp_unlink_nexthop(path);
285 bgp_path_info_extra_free(&path->extra);
286 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
287 if (path->net)
288 bgp_addpath_free_info_data(&path->tx_addpath,
289 &path->net->tx_addpath);
718e3744 290
9b6d8fcf 291 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 292
9b6d8fcf 293 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 294}
295
9b6d8fcf 296struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 297{
9b6d8fcf
DS
298 path->lock++;
299 return path;
200df115 300}
301
9b6d8fcf 302struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 303{
9b6d8fcf
DS
304 assert(path && path->lock > 0);
305 path->lock--;
d62a17ae 306
9b6d8fcf 307 if (path->lock == 0) {
9b6d8fcf 308 bgp_path_info_free(path);
d62a17ae 309 return NULL;
310 }
200df115 311
9b6d8fcf 312 return path;
200df115 313}
314
f009ff26 315/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 316static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 317{
318 struct peer *peer;
319 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 320 bool set_flag = false;
f009ff26 321 struct bgp *bgp = NULL;
322 struct bgp_table *table = NULL;
323 afi_t afi = 0;
324 safi_t safi = 0;
f009ff26 325
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
328 */
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 330 return 0;
331
9bcb3eef 332 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 333 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 334 zlog_debug(
56ca3b5b
DL
335 "Route %pBD is in workqueue and being processed, not deferred.",
336 dest);
b54892e0 337
5f9c1aa2 338 return 0;
339 }
340
9bcb3eef 341 table = bgp_dest_table(dest);
f009ff26 342 if (table) {
343 bgp = table->bgp;
344 afi = table->afi;
345 safi = table->safi;
346 }
347
9bcb3eef 348 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 349 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
351 continue;
352
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
355 */
36235319
QY
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
357 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 358 set_flag = true;
f009ff26 359 } else {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
362 */
363 peer = old_pi->peer;
36235319
QY
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
365 && BGP_PEER_RESTARTING_MODE(peer)
366 && (old_pi
367 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 }
370 }
371 if (set_flag)
372 break;
373 }
374
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
376 * is active
377 */
2ba1fe69 378 if (set_flag && table) {
f009ff26 379 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
380 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
381 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 382 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 383 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
384 zlog_debug("DEFER route %pBD, dest %p", dest,
385 dest);
f009ff26 386 return 0;
387 }
388 }
389 return -1;
390}
391
9bcb3eef 392void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 393{
4b7e6066 394 struct bgp_path_info *top;
718e3744 395
9bcb3eef 396 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 397
6f94b685 398 pi->next = top;
40381db7 399 pi->prev = NULL;
d62a17ae 400 if (top)
40381db7 401 top->prev = pi;
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 403
40381db7 404 bgp_path_info_lock(pi);
9bcb3eef 405 bgp_dest_lock_node(dest);
40381db7 406 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 407 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 408 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 409}
410
d62a17ae 411/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 412 completion callback *only* */
9bcb3eef 413void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 414{
40381db7
DS
415 if (pi->next)
416 pi->next->prev = pi->prev;
417 if (pi->prev)
418 pi->prev->next = pi->next;
d62a17ae 419 else
9bcb3eef 420 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 421
40381db7
DS
422 bgp_path_info_mpath_dequeue(pi);
423 bgp_path_info_unlock(pi);
7fd28dd2 424 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 425 bgp_dest_unlock_node(dest);
718e3744 426}
427
9bcb3eef 428void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 429{
9bcb3eef 430 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 431 /* set of previous already took care of pcount */
40381db7 432 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 433}
434
18ee8310 435/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
436 called when a route is deleted and then quickly re-added before the
437 deletion has been processed */
9bcb3eef 438void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 439{
9bcb3eef 440 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 441 /* unset of previous already took care of pcount */
40381db7 442 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
443}
444
d62a17ae 445/* Adjust pcount as required */
9bcb3eef 446static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 447{
d62a17ae 448 struct bgp_table *table;
67174041 449
9bcb3eef 450 assert(dest && bgp_dest_table(dest));
40381db7 451 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 452
9bcb3eef 453 table = bgp_dest_table(dest);
67174041 454
40381db7 455 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 456 return;
457
40381db7
DS
458 if (!BGP_PATH_COUNTABLE(pi)
459 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 460
40381db7 461 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 462
463 /* slight hack, but more robust against errors. */
40381db7
DS
464 if (pi->peer->pcount[table->afi][table->safi])
465 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 466 else
450971aa 467 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 468 "Asked to decrement 0 prefix count for peer");
40381db7
DS
469 } else if (BGP_PATH_COUNTABLE(pi)
470 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
471 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
472 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 473 }
1a392d46
PJ
474}
475
40381db7
DS
476static int bgp_label_index_differs(struct bgp_path_info *pi1,
477 struct bgp_path_info *pi2)
28d58fd7 478{
40381db7 479 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 480}
1a392d46 481
18ee8310 482/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
483 * This is here primarily to keep prefix-count in check.
484 */
9bcb3eef 485void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 486 uint32_t flag)
1a392d46 487{
40381db7 488 SET_FLAG(pi->flags, flag);
d62a17ae 489
490 /* early bath if we know it's not a flag that changes countability state
491 */
492 if (!CHECK_FLAG(flag,
1defdda8 493 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 494 return;
495
9bcb3eef 496 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
497}
498
9bcb3eef 499void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 500 uint32_t flag)
1a392d46 501{
40381db7 502 UNSET_FLAG(pi->flags, flag);
d62a17ae 503
504 /* early bath if we know it's not a flag that changes countability state
505 */
506 if (!CHECK_FLAG(flag,
1defdda8 507 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 508 return;
509
9bcb3eef 510 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
511}
512
718e3744 513/* Get MED value. If MED value is missing and "bgp bestpath
514 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 515static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 516{
517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
518 return attr->med;
519 else {
892fedb6 520 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 521 return BGP_MED_MAX;
522 else
523 return 0;
524 }
718e3744 525}
526
7533cad7
QY
527void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
528 size_t buf_len)
2ec1e66f 529{
40381db7 530 if (pi->addpath_rx_id)
7533cad7
QY
531 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
532 pi->peer->host, pi->addpath_rx_id);
d62a17ae 533 else
7533cad7 534 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 535}
9fbdd100 536
da0c0ef7
KM
537
538/*
539 * Get the ultimate path info.
540 */
541struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
542{
543 struct bgp_path_info *bpi_ultimate;
544
545 if (info->sub_type != BGP_ROUTE_IMPORTED)
546 return info;
547
548 for (bpi_ultimate = info;
549 bpi_ultimate->extra && bpi_ultimate->extra->parent;
550 bpi_ultimate = bpi_ultimate->extra->parent)
551 ;
552
553 return bpi_ultimate;
554}
555
d62a17ae 556/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
557 */
18ee8310
DS
558static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
559 struct bgp_path_info *exist, int *paths_eq,
560 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
561 char *pfx_buf, afi_t afi, safi_t safi,
562 enum bgp_path_selection_reason *reason)
d62a17ae 563{
5df26422 564 const struct prefix *new_p;
70cd87ca 565 struct prefix exist_p;
d62a17ae 566 struct attr *newattr, *existattr;
3061acc2
DA
567 enum bgp_peer_sort new_sort;
568 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
569 uint32_t new_pref;
570 uint32_t exist_pref;
571 uint32_t new_med;
572 uint32_t exist_med;
573 uint32_t new_weight;
574 uint32_t exist_weight;
d62a17ae 575 uint32_t newm, existm;
576 struct in_addr new_id;
577 struct in_addr exist_id;
578 int new_cluster;
579 int exist_cluster;
580 int internal_as_route;
581 int confed_as_route;
04d14c8b 582 int ret = 0;
ee88563a
JM
583 int igp_metric_ret = 0;
584 int peer_sort_ret = -1;
d62a17ae 585 char new_buf[PATH_ADDPATH_STR_BUFFER];
586 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
587 uint32_t new_mm_seq;
588 uint32_t exist_mm_seq;
6d8c603a 589 int nh_cmp;
d071f237
AK
590 esi_t *exist_esi;
591 esi_t *new_esi;
592 bool same_esi;
593 bool old_proxy;
594 bool new_proxy;
33c6e933 595 bool new_origin, exist_origin;
da0c0ef7 596 struct bgp_path_info *bpi_ultimate;
d62a17ae 597
70cd87ca
MK
598 struct bgp_orr_group *orr_group = NULL;
599 struct listnode *node;
600 struct bgp_orr_igp_metric *igp_metric = NULL;
601 struct list *orr_group_igp_metric_info = NULL;
602
d62a17ae 603 *paths_eq = 0;
604
605 /* 0. Null check. */
606 if (new == NULL) {
fdf81fa0 607 *reason = bgp_path_selection_none;
d62a17ae 608 if (debug)
609 zlog_debug("%s: new is NULL", pfx_buf);
610 return 0;
611 }
2ec1e66f 612
da0c0ef7
KM
613 if (debug) {
614 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
615 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 616 sizeof(new_buf));
da0c0ef7 617 }
718e3744 618
d62a17ae 619 if (exist == NULL) {
fdf81fa0 620 *reason = bgp_path_selection_first;
d62a17ae 621 if (debug)
4378495a
DS
622 zlog_debug("%s(%s): %s is the initial bestpath",
623 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 624 return 1;
625 }
2ec1e66f 626
d62a17ae 627 if (debug) {
da0c0ef7
KM
628 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
629 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 630 sizeof(exist_buf));
4378495a
DS
631 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
632 pfx_buf, bgp->name_pretty, new_buf, new->flags,
633 exist_buf, exist->flags);
d62a17ae 634 }
8ff56318 635
d62a17ae 636 newattr = new->attr;
637 existattr = exist->attr;
638
1479ed2f
DA
639 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
640 * Capability" to a neighbor MUST perform the following upon receiving
641 * a route from that neighbor with the "LLGR_STALE" community, or upon
642 * attaching the "LLGR_STALE" community itself per Section 4.2:
643 *
644 * Treat the route as the least-preferred in route selection (see
645 * below). See the Risks of Depreferencing Routes section (Section 5.2)
646 * for a discussion of potential risks inherent in doing this.
647 */
9a706b42
DA
648 if (bgp_attr_get_community(newattr) &&
649 community_include(bgp_attr_get_community(newattr),
650 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to LLGR_STALE community",
654 pfx_buf, new_buf, exist_buf);
655 return 0;
656 }
657
9a706b42
DA
658 if (bgp_attr_get_community(existattr) &&
659 community_include(bgp_attr_get_community(existattr),
660 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to LLGR_STALE community",
664 pfx_buf, new_buf, exist_buf);
665 return 1;
666 }
667
5df26422
NS
668 new_p = bgp_dest_get_prefix(new->net);
669
d62a17ae 670 /* For EVPN routes, we cannot just go by local vs remote, we have to
671 * look at the MAC mobility sequence number, if present.
672 */
5df26422
NS
673 if ((safi == SAFI_EVPN)
674 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 675 /* This is an error condition described in RFC 7432 Section
676 * 15.2. The RFC
677 * states that in this scenario "the PE MUST alert the operator"
678 * but it
679 * does not state what other action to take. In order to provide
680 * some
681 * consistency in this scenario we are going to prefer the path
682 * with the
683 * sticky flag.
684 */
685 if (newattr->sticky != existattr->sticky) {
686 if (!debug) {
5df26422
NS
687 prefix2str(new_p, pfx_buf,
688 sizeof(*pfx_buf)
689 * PREFIX2STR_BUFFER);
18ee8310 690 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
691 new, new_buf, sizeof(new_buf));
692 bgp_path_info_path_with_addpath_rx_str(
693 exist, exist_buf, sizeof(exist_buf));
d62a17ae 694 }
695
696 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 697 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
698 if (debug)
699 zlog_debug(
700 "%s: %s wins over %s due to sticky MAC flag",
701 pfx_buf, new_buf, exist_buf);
d62a17ae 702 return 1;
703 }
704
705 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 706 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
707 if (debug)
708 zlog_debug(
709 "%s: %s loses to %s due to sticky MAC flag",
710 pfx_buf, new_buf, exist_buf);
d62a17ae 711 return 0;
712 }
713 }
128ea8ab 714
d071f237
AK
715 new_esi = bgp_evpn_attr_get_esi(newattr);
716 exist_esi = bgp_evpn_attr_get_esi(existattr);
717 if (bgp_evpn_is_esi_valid(new_esi) &&
718 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
719 same_esi = true;
720 } else {
721 same_esi = false;
722 }
723
724 /* If both paths have the same non-zero ES and
725 * one path is local it wins.
726 * PS: Note the local path wins even if the remote
727 * has the higher MM seq. The local path's
728 * MM seq will be fixed up to match the highest
729 * rem seq, subsequently.
730 */
731 if (same_esi) {
732 char esi_buf[ESI_STR_LEN];
733
734 if (bgp_evpn_is_path_local(bgp, new)) {
735 *reason = bgp_path_selection_evpn_local_path;
736 if (debug)
737 zlog_debug(
738 "%s: %s wins over %s as ES %s is same and local",
739 pfx_buf, new_buf, exist_buf,
740 esi_to_str(new_esi, esi_buf,
741 sizeof(esi_buf)));
742 return 1;
743 }
744 if (bgp_evpn_is_path_local(bgp, exist)) {
745 *reason = bgp_path_selection_evpn_local_path;
746 if (debug)
747 zlog_debug(
748 "%s: %s loses to %s as ES %s is same and local",
749 pfx_buf, new_buf, exist_buf,
750 esi_to_str(new_esi, esi_buf,
751 sizeof(esi_buf)));
752 return 0;
753 }
754 }
755
d62a17ae 756 new_mm_seq = mac_mobility_seqnum(newattr);
757 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 758
d62a17ae 759 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 760 *reason = bgp_path_selection_evpn_seq;
d62a17ae 761 if (debug)
762 zlog_debug(
763 "%s: %s wins over %s due to MM seq %u > %u",
764 pfx_buf, new_buf, exist_buf, new_mm_seq,
765 exist_mm_seq);
766 return 1;
767 }
8ff56318 768
d62a17ae 769 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 770 *reason = bgp_path_selection_evpn_seq;
d62a17ae 771 if (debug)
772 zlog_debug(
773 "%s: %s loses to %s due to MM seq %u < %u",
774 pfx_buf, new_buf, exist_buf, new_mm_seq,
775 exist_mm_seq);
776 return 0;
777 }
6d8c603a 778
d071f237
AK
779 /* if the sequence numbers and ESI are the same and one path
780 * is non-proxy it wins (over proxy)
781 */
782 new_proxy = bgp_evpn_attr_is_proxy(newattr);
783 old_proxy = bgp_evpn_attr_is_proxy(existattr);
784 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
785 old_proxy != new_proxy) {
786 if (!new_proxy) {
787 *reason = bgp_path_selection_evpn_non_proxy;
788 if (debug)
789 zlog_debug(
790 "%s: %s wins over %s, same seq/es and non-proxy",
791 pfx_buf, new_buf, exist_buf);
792 return 1;
793 }
794
795 *reason = bgp_path_selection_evpn_non_proxy;
796 if (debug)
797 zlog_debug(
798 "%s: %s loses to %s, same seq/es and non-proxy",
799 pfx_buf, new_buf, exist_buf);
800 return 0;
801 }
802
6d8c603a
AK
803 /*
804 * if sequence numbers are the same path with the lowest IP
805 * wins
806 */
807 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
808 if (nh_cmp < 0) {
fdf81fa0 809 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
810 if (debug)
811 zlog_debug(
23d0a753 812 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 813 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 814 &new->attr->nexthop);
6d8c603a
AK
815 return 1;
816 }
817 if (nh_cmp > 0) {
fdf81fa0 818 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
819 if (debug)
820 zlog_debug(
23d0a753 821 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 822 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 823 &new->attr->nexthop);
6d8c603a
AK
824 return 0;
825 }
d62a17ae 826 }
9fbdd100 827
d62a17ae 828 /* 1. Weight check. */
d62a17ae 829 new_weight = newattr->weight;
830 exist_weight = existattr->weight;
8ff56318 831
d62a17ae 832 if (new_weight > exist_weight) {
fdf81fa0 833 *reason = bgp_path_selection_weight;
d62a17ae 834 if (debug)
835 zlog_debug("%s: %s wins over %s due to weight %d > %d",
836 pfx_buf, new_buf, exist_buf, new_weight,
837 exist_weight);
838 return 1;
839 }
718e3744 840
d62a17ae 841 if (new_weight < exist_weight) {
fdf81fa0 842 *reason = bgp_path_selection_weight;
d62a17ae 843 if (debug)
844 zlog_debug("%s: %s loses to %s due to weight %d < %d",
845 pfx_buf, new_buf, exist_buf, new_weight,
846 exist_weight);
847 return 0;
848 }
9fbdd100 849
d62a17ae 850 /* 2. Local preference check. */
851 new_pref = exist_pref = bgp->default_local_pref;
852
853 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
854 new_pref = newattr->local_pref;
855 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
856 exist_pref = existattr->local_pref;
857
858 if (new_pref > exist_pref) {
fdf81fa0 859 *reason = bgp_path_selection_local_pref;
d62a17ae 860 if (debug)
861 zlog_debug(
862 "%s: %s wins over %s due to localpref %d > %d",
863 pfx_buf, new_buf, exist_buf, new_pref,
864 exist_pref);
865 return 1;
866 }
718e3744 867
d62a17ae 868 if (new_pref < exist_pref) {
fdf81fa0 869 *reason = bgp_path_selection_local_pref;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s loses to %s due to localpref %d < %d",
873 pfx_buf, new_buf, exist_buf, new_pref,
874 exist_pref);
875 return 0;
876 }
9fbdd100 877
46dbf9d0
DA
878 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
879 * extensions defined in this document, the following step is inserted
880 * after the LOCAL_PREF comparison step in the BGP decision process:
881 * When comparing a pair of routes for a BGP destination, the
882 * route with the ACCEPT_OWN community attached is preferred over
883 * the route that does not have the community.
884 * This extra step MUST only be invoked during the best path selection
885 * process of VPN-IP routes.
886 */
887 if (safi == SAFI_MPLS_VPN &&
888 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
889 CHECK_FLAG(exist->peer->af_flags[afi][safi],
890 PEER_FLAG_ACCEPT_OWN))) {
891 bool new_accept_own = false;
892 bool exist_accept_own = false;
893 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
894
895 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
896 new_accept_own = community_include(
897 bgp_attr_get_community(newattr), accept_own);
898 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
899 exist_accept_own = community_include(
900 bgp_attr_get_community(existattr), accept_own);
901
902 if (new_accept_own && !exist_accept_own) {
903 *reason = bgp_path_selection_accept_own;
904 if (debug)
905 zlog_debug(
906 "%s: %s wins over %s due to accept-own",
907 pfx_buf, new_buf, exist_buf);
908 return 1;
909 }
910
911 if (!new_accept_own && exist_accept_own) {
912 *reason = bgp_path_selection_accept_own;
913 if (debug)
914 zlog_debug(
915 "%s: %s loses to %s due to accept-own",
916 pfx_buf, new_buf, exist_buf);
917 return 0;
918 }
919 }
920
97a52c82
DA
921 /* Tie-breaker - AIGP (Metric TLV) attribute */
922 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
923 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
924 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
925 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
926 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
927
928 if (new_aigp < exist_aigp) {
929 *reason = bgp_path_selection_aigp;
930 if (debug)
931 zlog_debug(
932 "%s: %s wins over %s due to AIGP %" PRIu64
933 " < %" PRIu64,
934 pfx_buf, new_buf, exist_buf, new_aigp,
935 exist_aigp);
936 return 1;
937 }
938
939 if (new_aigp > exist_aigp) {
940 *reason = bgp_path_selection_aigp;
941 if (debug)
942 zlog_debug(
943 "%s: %s loses to %s due to AIGP %" PRIu64
944 " > %" PRIu64,
945 pfx_buf, new_buf, exist_buf, new_aigp,
946 exist_aigp);
947 return 0;
948 }
949 }
950
d62a17ae 951 /* 3. Local route check. We prefer:
952 * - BGP_ROUTE_STATIC
953 * - BGP_ROUTE_AGGREGATE
954 * - BGP_ROUTE_REDISTRIBUTE
955 */
33c6e933
DS
956 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
957 new->sub_type == BGP_ROUTE_IMPORTED);
958 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
959 exist->sub_type == BGP_ROUTE_IMPORTED);
960
961 if (new_origin && !exist_origin) {
fdf81fa0 962 *reason = bgp_path_selection_local_route;
d62a17ae 963 if (debug)
964 zlog_debug(
965 "%s: %s wins over %s due to preferred BGP_ROUTE type",
966 pfx_buf, new_buf, exist_buf);
967 return 1;
968 }
718e3744 969
33c6e933 970 if (!new_origin && exist_origin) {
fdf81fa0 971 *reason = bgp_path_selection_local_route;
d62a17ae 972 if (debug)
973 zlog_debug(
974 "%s: %s loses to %s due to preferred BGP_ROUTE type",
975 pfx_buf, new_buf, exist_buf);
976 return 0;
6811845b 977 }
718e3744 978
da0c0ef7
KM
979 /* Here if these are imported routes then get ultimate pi for
980 * path compare.
981 */
982 new = bgp_get_imported_bpi_ultimate(new);
983 exist = bgp_get_imported_bpi_ultimate(exist);
984 newattr = new->attr;
985 existattr = exist->attr;
986
d62a17ae 987 /* 4. AS path length check. */
892fedb6 988 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 989 int exist_hops = aspath_count_hops(existattr->aspath);
990 int exist_confeds = aspath_count_confeds(existattr->aspath);
991
892fedb6 992 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 993 int aspath_hops;
994
995 aspath_hops = aspath_count_hops(newattr->aspath);
996 aspath_hops += aspath_count_confeds(newattr->aspath);
997
998 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 999 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1000 if (debug)
1001 zlog_debug(
1002 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1003 pfx_buf, new_buf, exist_buf,
1004 aspath_hops,
1005 (exist_hops + exist_confeds));
1006 return 1;
1007 }
1008
1009 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1010 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1011 if (debug)
1012 zlog_debug(
1013 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1014 pfx_buf, new_buf, exist_buf,
1015 aspath_hops,
1016 (exist_hops + exist_confeds));
1017 return 0;
1018 }
1019 } else {
1020 int newhops = aspath_count_hops(newattr->aspath);
1021
1022 if (newhops < exist_hops) {
fdf81fa0 1023 *reason = bgp_path_selection_as_path;
d62a17ae 1024 if (debug)
1025 zlog_debug(
1026 "%s: %s wins over %s due to aspath hopcount %d < %d",
1027 pfx_buf, new_buf, exist_buf,
1028 newhops, exist_hops);
1029 return 1;
1030 }
1031
1032 if (newhops > exist_hops) {
fdf81fa0 1033 *reason = bgp_path_selection_as_path;
d62a17ae 1034 if (debug)
1035 zlog_debug(
1036 "%s: %s loses to %s due to aspath hopcount %d > %d",
1037 pfx_buf, new_buf, exist_buf,
1038 newhops, exist_hops);
1039 return 0;
1040 }
1041 }
1042 }
9fbdd100 1043
d62a17ae 1044 /* 5. Origin check. */
1045 if (newattr->origin < existattr->origin) {
fdf81fa0 1046 *reason = bgp_path_selection_origin;
d62a17ae 1047 if (debug)
1048 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1049 pfx_buf, new_buf, exist_buf,
1050 bgp_origin_long_str[newattr->origin],
1051 bgp_origin_long_str[existattr->origin]);
1052 return 1;
1053 }
718e3744 1054
d62a17ae 1055 if (newattr->origin > existattr->origin) {
fdf81fa0 1056 *reason = bgp_path_selection_origin;
d62a17ae 1057 if (debug)
1058 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1059 pfx_buf, new_buf, exist_buf,
1060 bgp_origin_long_str[newattr->origin],
1061 bgp_origin_long_str[existattr->origin]);
1062 return 0;
1063 }
718e3744 1064
d62a17ae 1065 /* 6. MED check. */
1066 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1067 && aspath_count_hops(existattr->aspath) == 0);
1068 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1069 && aspath_count_confeds(existattr->aspath) > 0
1070 && aspath_count_hops(newattr->aspath) == 0
1071 && aspath_count_hops(existattr->aspath) == 0);
1072
892fedb6
DA
1073 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1074 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1075 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1076 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1077 || internal_as_route) {
1078 new_med = bgp_med_value(new->attr, bgp);
1079 exist_med = bgp_med_value(exist->attr, bgp);
1080
1081 if (new_med < exist_med) {
fdf81fa0 1082 *reason = bgp_path_selection_med;
d62a17ae 1083 if (debug)
1084 zlog_debug(
1085 "%s: %s wins over %s due to MED %d < %d",
1086 pfx_buf, new_buf, exist_buf, new_med,
1087 exist_med);
1088 return 1;
1089 }
8ff56318 1090
d62a17ae 1091 if (new_med > exist_med) {
fdf81fa0 1092 *reason = bgp_path_selection_med;
d62a17ae 1093 if (debug)
1094 zlog_debug(
1095 "%s: %s loses to %s due to MED %d > %d",
1096 pfx_buf, new_buf, exist_buf, new_med,
1097 exist_med);
1098 return 0;
1099 }
1100 }
9fbdd100 1101
d62a17ae 1102 /* 7. Peer type check. */
1103 new_sort = new->peer->sort;
1104 exist_sort = exist->peer->sort;
1105
1106 if (new_sort == BGP_PEER_EBGP
1107 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1108 *reason = bgp_path_selection_peer;
d62a17ae 1109 if (debug)
1110 zlog_debug(
1111 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1112 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1113 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1114 return 1;
1115 peer_sort_ret = 1;
d62a17ae 1116 }
718e3744 1117
d62a17ae 1118 if (exist_sort == BGP_PEER_EBGP
1119 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1120 *reason = bgp_path_selection_peer;
d62a17ae 1121 if (debug)
1122 zlog_debug(
1123 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1124 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1125 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1126 return 0;
1127 peer_sort_ret = 0;
d62a17ae 1128 }
8ff56318 1129
d62a17ae 1130 /* 8. IGP metric check. */
1131 newm = existm = 0;
8ff56318 1132
d62a17ae 1133 if (new->extra)
1134 newm = new->extra->igpmetric;
1135 if (exist->extra)
1136 existm = exist->extra->igpmetric;
9fbdd100 1137
70cd87ca
MK
1138 if (new->peer->orr_group_name[afi][safi]) {
1139 ret = str2prefix(new->peer->host, &exist_p);
1140 orr_group = bgp_orr_group_lookup_by_name(
1141 bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
1142 if (orr_group) {
1143 orr_group_igp_metric_info = orr_group->igp_metric_info;
1144 if (orr_group_igp_metric_info) {
1145 for (ALL_LIST_ELEMENTS_RO(
1146 orr_group_igp_metric_info, node,
1147 igp_metric)) {
1148 if (ret &&
1149 prefix_cmp(&exist_p,
1150 &igp_metric->prefix) ==
1151 0) {
1152 newm = igp_metric->igp_metric;
1153 break;
1154 }
1155 }
1156 }
1157 }
1158 }
1159 if (exist->peer->orr_group_name[afi][safi]) {
1160 ret = str2prefix(exist->peer->host, &exist_p);
1161 orr_group = bgp_orr_group_lookup_by_name(
1162 bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
1163 if (orr_group) {
1164 orr_group_igp_metric_info = orr_group->igp_metric_info;
1165 if (orr_group_igp_metric_info) {
1166 for (ALL_LIST_ELEMENTS_RO(
1167 orr_group_igp_metric_info, node,
1168 igp_metric)) {
1169 if (ret &&
1170 prefix_cmp(&exist_p,
1171 &igp_metric->prefix) ==
1172 0) {
1173 existm = igp_metric->igp_metric;
1174 break;
1175 }
1176 }
1177 }
1178 }
1179 }
1180
d62a17ae 1181 if (newm < existm) {
ee88563a 1182 if (debug && peer_sort_ret < 0)
d62a17ae 1183 zlog_debug(
d588b995 1184 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1185 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1186 igp_metric_ret = 1;
d62a17ae 1187 }
718e3744 1188
d62a17ae 1189 if (newm > existm) {
ee88563a 1190 if (debug && peer_sort_ret < 0)
d62a17ae 1191 zlog_debug(
d588b995 1192 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1193 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1194 igp_metric_ret = 0;
5e242b0d 1195 }
5e242b0d 1196
d62a17ae 1197 /* 9. Same IGP metric. Compare the cluster list length as
1198 representative of IGP hops metric. Rewrite the metric value
1199 pair (newm, existm) with the cluster list length. Prefer the
1200 path with smaller cluster list length. */
1201 if (newm == existm) {
aa53c036
DS
1202 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1203 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1204 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1205 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1206 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1207
1208 if (newm < existm) {
ee88563a 1209 if (debug && peer_sort_ret < 0)
d62a17ae 1210 zlog_debug(
d588b995 1211 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1212 pfx_buf, new_buf, exist_buf,
1213 newm, existm);
ee88563a 1214 igp_metric_ret = 1;
d62a17ae 1215 }
1216
1217 if (newm > existm) {
ee88563a 1218 if (debug && peer_sort_ret < 0)
d62a17ae 1219 zlog_debug(
d588b995 1220 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1221 pfx_buf, new_buf, exist_buf,
1222 newm, existm);
ee88563a 1223 igp_metric_ret = 0;
d62a17ae 1224 }
1225 }
1226 }
31a4638f 1227
d62a17ae 1228 /* 10. confed-external vs. confed-internal */
1229 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1230 if (new_sort == BGP_PEER_CONFED
1231 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1232 *reason = bgp_path_selection_confed;
d62a17ae 1233 if (debug)
1234 zlog_debug(
1235 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1236 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1237 if (!CHECK_FLAG(bgp->flags,
1238 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1239 return 1;
1240 peer_sort_ret = 1;
d62a17ae 1241 }
718e3744 1242
d62a17ae 1243 if (exist_sort == BGP_PEER_CONFED
1244 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1245 *reason = bgp_path_selection_confed;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1249 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1250 if (!CHECK_FLAG(bgp->flags,
1251 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1252 return 0;
1253 peer_sort_ret = 0;
d62a17ae 1254 }
1255 }
718e3744 1256
d62a17ae 1257 /* 11. Maximum path check. */
1258 if (newm == existm) {
1259 /* If one path has a label but the other does not, do not treat
1260 * them as equals for multipath
1261 */
a4d82a8a 1262 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1263 != (exist->extra
b57ba6d2 1264 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1265 if (debug)
1266 zlog_debug(
1267 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1268 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1269 } else if (CHECK_FLAG(bgp->flags,
1270 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1271
1272 /*
1273 * For the two paths, all comparison steps till IGP
1274 * metric
1275 * have succeeded - including AS_PATH hop count. Since
1276 * 'bgp
1277 * bestpath as-path multipath-relax' knob is on, we
1278 * don't need
1279 * an exact match of AS_PATH. Thus, mark the paths are
1280 * equal.
1281 * That will trigger both these paths to get into the
1282 * multipath
1283 * array.
1284 */
1285 *paths_eq = 1;
1286
1287 if (debug)
1288 zlog_debug(
1289 "%s: %s and %s are equal via multipath-relax",
1290 pfx_buf, new_buf, exist_buf);
1291 } else if (new->peer->sort == BGP_PEER_IBGP) {
1292 if (aspath_cmp(new->attr->aspath,
1293 exist->attr->aspath)) {
1294 *paths_eq = 1;
1295
1296 if (debug)
1297 zlog_debug(
1298 "%s: %s and %s are equal via matching aspaths",
1299 pfx_buf, new_buf, exist_buf);
1300 }
1301 } else if (new->peer->as == exist->peer->as) {
1302 *paths_eq = 1;
1303
1304 if (debug)
1305 zlog_debug(
1306 "%s: %s and %s are equal via same remote-as",
1307 pfx_buf, new_buf, exist_buf);
1308 }
1309 } else {
1310 /*
1311 * TODO: If unequal cost ibgp multipath is enabled we can
1312 * mark the paths as equal here instead of returning
1313 */
ee88563a
JM
1314
1315 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1316 * if either step 7 or 10 (peer type checks) yielded a winner,
1317 * that result was returned immediately. Returning from step 10
1318 * ignored the return value computed in steps 8 and 9 (IGP
1319 * metric checks). In order to preserve that behavior, if
1320 * peer_sort_ret is set, return that rather than igp_metric_ret.
1321 */
1322 ret = peer_sort_ret;
1323 if (peer_sort_ret < 0) {
1324 ret = igp_metric_ret;
1325 if (debug) {
1326 if (ret == 1)
1327 zlog_debug(
1328 "%s: %s wins over %s after IGP metric comparison",
1329 pfx_buf, new_buf, exist_buf);
1330 else
1331 zlog_debug(
1332 "%s: %s loses to %s after IGP metric comparison",
1333 pfx_buf, new_buf, exist_buf);
1334 }
1335 *reason = bgp_path_selection_igp_metric;
d62a17ae 1336 }
1337 return ret;
1338 }
718e3744 1339
ee88563a
JM
1340 /*
1341 * At this point, the decision whether to set *paths_eq = 1 has been
1342 * completed. If we deferred returning because of bestpath peer-type
1343 * relax configuration, return now.
1344 */
1345 if (peer_sort_ret >= 0)
1346 return peer_sort_ret;
1347
d62a17ae 1348 /* 12. If both paths are external, prefer the path that was received
1349 first (the oldest one). This step minimizes route-flap, since a
1350 newer path won't displace an older one, even if it was the
1351 preferred route based on the additional decision criteria below. */
892fedb6 1352 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1353 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1354 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1355 *reason = bgp_path_selection_older;
d62a17ae 1356 if (debug)
1357 zlog_debug(
1358 "%s: %s wins over %s due to oldest external",
1359 pfx_buf, new_buf, exist_buf);
1360 return 1;
1361 }
9fbdd100 1362
1defdda8 1363 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1364 *reason = bgp_path_selection_older;
d62a17ae 1365 if (debug)
1366 zlog_debug(
1367 "%s: %s loses to %s due to oldest external",
1368 pfx_buf, new_buf, exist_buf);
1369 return 0;
1370 }
1371 }
718e3744 1372
ce5002c6 1373 /* 13. Router-ID comparison. */
d62a17ae 1374 /* If one of the paths is "stale", the corresponding peer router-id will
1375 * be 0 and would always win over the other path. If originator id is
ce5002c6 1376 * used for the comparison, it will decide which path is better.
d62a17ae 1377 */
1378 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1379 new_id.s_addr = newattr->originator_id.s_addr;
1380 else
1381 new_id.s_addr = new->peer->remote_id.s_addr;
1382 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1383 exist_id.s_addr = existattr->originator_id.s_addr;
1384 else
1385 exist_id.s_addr = exist->peer->remote_id.s_addr;
1386
1387 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1388 *reason = bgp_path_selection_router_id;
d62a17ae 1389 if (debug)
1390 zlog_debug(
1391 "%s: %s wins over %s due to Router-ID comparison",
1392 pfx_buf, new_buf, exist_buf);
1393 return 1;
1394 }
718e3744 1395
d62a17ae 1396 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1397 *reason = bgp_path_selection_router_id;
d62a17ae 1398 if (debug)
1399 zlog_debug(
1400 "%s: %s loses to %s due to Router-ID comparison",
1401 pfx_buf, new_buf, exist_buf);
1402 return 0;
1403 }
9fbdd100 1404
ce5002c6 1405 /* 14. Cluster length comparison. */
d62a17ae 1406 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1407 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1408
1409 if (new_cluster < exist_cluster) {
fdf81fa0 1410 *reason = bgp_path_selection_cluster_length;
d62a17ae 1411 if (debug)
1412 zlog_debug(
1413 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1414 pfx_buf, new_buf, exist_buf, new_cluster,
1415 exist_cluster);
1416 return 1;
1417 }
718e3744 1418
d62a17ae 1419 if (new_cluster > exist_cluster) {
fdf81fa0 1420 *reason = bgp_path_selection_cluster_length;
d62a17ae 1421 if (debug)
1422 zlog_debug(
1423 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1424 pfx_buf, new_buf, exist_buf, new_cluster,
1425 exist_cluster);
1426 return 0;
1427 }
9fbdd100 1428
ce5002c6 1429 /* 15. Neighbor address comparison. */
d62a17ae 1430 /* Do this only if neither path is "stale" as stale paths do not have
1431 * valid peer information (as the connection may or may not be up).
1432 */
1defdda8 1433 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1434 *reason = bgp_path_selection_stale;
d62a17ae 1435 if (debug)
1436 zlog_debug(
1437 "%s: %s wins over %s due to latter path being STALE",
1438 pfx_buf, new_buf, exist_buf);
1439 return 1;
1440 }
0de5153c 1441
1defdda8 1442 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1443 *reason = bgp_path_selection_stale;
d62a17ae 1444 if (debug)
1445 zlog_debug(
1446 "%s: %s loses to %s due to former path being STALE",
1447 pfx_buf, new_buf, exist_buf);
1448 return 0;
1449 }
718e3744 1450
d62a17ae 1451 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1452 if (new->peer->su_remote == NULL) {
1453 *reason = bgp_path_selection_local_configured;
d62a17ae 1454 return 0;
fdf81fa0
DS
1455 }
1456 if (exist->peer->su_remote == NULL) {
1457 *reason = bgp_path_selection_local_configured;
d62a17ae 1458 return 1;
fdf81fa0 1459 }
9fbdd100 1460
d62a17ae 1461 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1462
1463 if (ret == 1) {
fdf81fa0 1464 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1465 if (debug)
1466 zlog_debug(
1467 "%s: %s loses to %s due to Neighor IP comparison",
1468 pfx_buf, new_buf, exist_buf);
1469 return 0;
1470 }
1471
1472 if (ret == -1) {
fdf81fa0 1473 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1474 if (debug)
1475 zlog_debug(
1476 "%s: %s wins over %s due to Neighor IP comparison",
1477 pfx_buf, new_buf, exist_buf);
1478 return 1;
1479 }
9fbdd100 1480
fdf81fa0 1481 *reason = bgp_path_selection_default;
d62a17ae 1482 if (debug)
1483 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1484 pfx_buf, new_buf, exist_buf);
718e3744 1485
d62a17ae 1486 return 1;
718e3744 1487}
1488
d071f237
AK
1489
1490int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1491 struct bgp_path_info *exist, int *paths_eq)
1492{
1493 enum bgp_path_selection_reason reason;
1494 char pfx_buf[PREFIX2STR_BUFFER];
1495
1496 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1497 AFI_L2VPN, SAFI_EVPN, &reason);
1498}
1499
65efcfce
LB
1500/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1501 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1502 * multipath is enabled
65efcfce 1503 * This version is compatible with */
18ee8310
DS
1504int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1505 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1506 afi_t afi, safi_t safi,
1507 enum bgp_path_selection_reason *reason)
d62a17ae 1508{
1509 int paths_eq;
1510 int ret;
18ee8310 1511 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1512 afi, safi, reason);
d62a17ae 1513
1514 if (paths_eq)
1515 ret = 0;
1516 else {
1517 if (ret == 1)
1518 ret = -1;
1519 else
1520 ret = 1;
1521 }
1522 return ret;
65efcfce
LB
1523}
1524
5a1ae2c2
DS
1525static enum filter_type bgp_input_filter(struct peer *peer,
1526 const struct prefix *p,
d62a17ae 1527 struct attr *attr, afi_t afi,
1528 safi_t safi)
718e3744 1529{
d62a17ae 1530 struct bgp_filter *filter;
6401252f 1531 enum filter_type ret = FILTER_PERMIT;
718e3744 1532
d62a17ae 1533 filter = &peer->filter[afi][safi];
718e3744 1534
d62a17ae 1535#define FILTER_EXIST_WARN(F, f, filter) \
1536 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1537 zlog_debug("%s: Could not find configured input %s-list %s!", \
1538 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1539
1540 if (DISTRIBUTE_IN_NAME(filter)) {
1541 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1542
6401252f
QY
1543 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1544 == FILTER_DENY) {
1545 ret = FILTER_DENY;
1546 goto done;
1547 }
d62a17ae 1548 }
1549
1550 if (PREFIX_LIST_IN_NAME(filter)) {
1551 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1552
6401252f
QY
1553 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1554 == PREFIX_DENY) {
1555 ret = FILTER_DENY;
1556 goto done;
1557 }
d62a17ae 1558 }
1559
1560 if (FILTER_LIST_IN_NAME(filter)) {
1561 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1562
1563 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1564 == AS_FILTER_DENY) {
1565 ret = FILTER_DENY;
1566 goto done;
1567 }
d62a17ae 1568 }
1569
6401252f 1570done:
c7bb4f00 1571 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1572 char pfxprint[PREFIX2STR_BUFFER];
1573
1574 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1575 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1576 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1577 }
1578
1579 return ret;
650f76c2 1580#undef FILTER_EXIST_WARN
718e3744 1581}
1582
b8685f9b
DS
1583static enum filter_type bgp_output_filter(struct peer *peer,
1584 const struct prefix *p,
d62a17ae 1585 struct attr *attr, afi_t afi,
1586 safi_t safi)
718e3744 1587{
d62a17ae 1588 struct bgp_filter *filter;
6401252f 1589 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1590
1591 filter = &peer->filter[afi][safi];
1592
1593#define FILTER_EXIST_WARN(F, f, filter) \
1594 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1595 zlog_debug("%s: Could not find configured output %s-list %s!", \
1596 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1597
d62a17ae 1598 if (DISTRIBUTE_OUT_NAME(filter)) {
1599 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1600
6401252f
QY
1601 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1602 == FILTER_DENY) {
1603 ret = FILTER_DENY;
1604 goto done;
1605 }
d62a17ae 1606 }
1607
1608 if (PREFIX_LIST_OUT_NAME(filter)) {
1609 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1610
d62a17ae 1611 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1612 == PREFIX_DENY) {
1613 ret = FILTER_DENY;
1614 goto done;
1615 }
d62a17ae 1616 }
718e3744 1617
d62a17ae 1618 if (FILTER_LIST_OUT_NAME(filter)) {
1619 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1620
d62a17ae 1621 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1622 == AS_FILTER_DENY) {
1623 ret = FILTER_DENY;
1624 goto done;
1625 }
1626 }
1627
c7bb4f00 1628 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1629 char pfxprint[PREFIX2STR_BUFFER];
1630
1631 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1632 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1633 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1634 }
718e3744 1635
6401252f
QY
1636done:
1637 return ret;
650f76c2 1638#undef FILTER_EXIST_WARN
718e3744 1639}
1640
1641/* If community attribute includes no_export then return 1. */
3dc339cd 1642static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1643{
9a706b42 1644 if (bgp_attr_get_community(attr)) {
d62a17ae 1645 /* NO_ADVERTISE check. */
9a706b42
DA
1646 if (community_include(bgp_attr_get_community(attr),
1647 COMMUNITY_NO_ADVERTISE))
3dc339cd 1648 return true;
d62a17ae 1649
1650 /* NO_EXPORT check. */
9a706b42
DA
1651 if (peer->sort == BGP_PEER_EBGP &&
1652 community_include(bgp_attr_get_community(attr),
1653 COMMUNITY_NO_EXPORT))
3dc339cd 1654 return true;
d62a17ae 1655
1656 /* NO_EXPORT_SUBCONFED check. */
1657 if (peer->sort == BGP_PEER_EBGP
1658 || peer->sort == BGP_PEER_CONFED)
9a706b42 1659 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1660 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1661 return true;
d62a17ae 1662 }
3dc339cd 1663 return false;
718e3744 1664}
1665
1666/* Route reflection loop check. */
3dc339cd 1667static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1668{
d62a17ae 1669 struct in_addr cluster_id;
779fee93 1670 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1671
779fee93 1672 if (cluster) {
d62a17ae 1673 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1674 cluster_id = peer->bgp->cluster_id;
1675 else
1676 cluster_id = peer->bgp->router_id;
1677
779fee93 1678 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1679 return true;
d62a17ae 1680 }
3dc339cd 1681 return false;
718e3744 1682}
6b0655a2 1683
d864dd9e
EB
1684static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1685{
1686 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1687 if (peer->local_role == ROLE_PROVIDER ||
1688 peer->local_role == ROLE_RS_SERVER)
1689 return true;
1690 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1691 return true;
1692 return false;
1693 }
1694 if (peer->local_role == ROLE_CUSTOMER ||
1695 peer->local_role == ROLE_PEER ||
1696 peer->local_role == ROLE_RS_CLIENT) {
1697 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1698 attr->otc = peer->as;
1699 }
1700 return false;
1701}
1702
1703static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1704{
1705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1706 if (peer->local_role == ROLE_CUSTOMER ||
1707 peer->local_role == ROLE_RS_CLIENT ||
1708 peer->local_role == ROLE_PEER)
1709 return true;
1710 return false;
1711 }
1712 if (peer->local_role == ROLE_PROVIDER ||
1713 peer->local_role == ROLE_PEER ||
1714 peer->local_role == ROLE_RS_SERVER) {
1715 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1716 attr->otc = peer->bgp->as;
1717 }
1718 return false;
1719}
1720
5a78f2bc
EB
1721static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1722{
1723 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1724}
1725
5a1ae2c2 1726static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1727 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1728 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1729 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1730{
d62a17ae 1731 struct bgp_filter *filter;
82b692c0
LK
1732 struct bgp_path_info rmap_path = { 0 };
1733 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1734 route_map_result_t ret;
1735 struct route_map *rmap = NULL;
718e3744 1736
d62a17ae 1737 filter = &peer->filter[afi][safi];
718e3744 1738
d62a17ae 1739 /* Apply default weight value. */
1740 if (peer->weight[afi][safi])
1741 attr->weight = peer->weight[afi][safi];
718e3744 1742
d62a17ae 1743 if (rmap_name) {
1744 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1745
d62a17ae 1746 if (rmap == NULL)
1747 return RMAP_DENY;
1748 } else {
1749 if (ROUTE_MAP_IN_NAME(filter)) {
1750 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1751
d62a17ae 1752 if (rmap == NULL)
1753 return RMAP_DENY;
1754 }
1755 }
0b16f239 1756
d62a17ae 1757 /* Route map apply. */
1758 if (rmap) {
6006b807 1759 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1760 /* Duplicate current value to new structure for modification. */
40381db7
DS
1761 rmap_path.peer = peer;
1762 rmap_path.attr = attr;
82b692c0 1763 rmap_path.extra = &extra;
9bcb3eef 1764 rmap_path.net = dest;
196c6b09 1765
82b692c0
LK
1766 extra.num_labels = num_labels;
1767 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1768 memcpy(extra.label, label,
1769 num_labels * sizeof(mpls_label_t));
718e3744 1770
d62a17ae 1771 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1772
d62a17ae 1773 /* Apply BGP route map to the attribute. */
1782514f 1774 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1775
d62a17ae 1776 peer->rmap_type = 0;
0b16f239 1777
1f2263be 1778 if (ret == RMAP_DENYMATCH)
d62a17ae 1779 return RMAP_DENY;
0b16f239 1780 }
d62a17ae 1781 return RMAP_PERMIT;
0b16f239
DS
1782}
1783
5f040085 1784static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1785 struct attr *attr, afi_t afi, safi_t safi,
1786 const char *rmap_name)
0b16f239 1787{
40381db7 1788 struct bgp_path_info rmap_path;
d62a17ae 1789 route_map_result_t ret;
1790 struct route_map *rmap = NULL;
d7c0a89a 1791 uint8_t rmap_type;
0b16f239 1792
b787157a
DS
1793 /*
1794 * So if we get to this point and have no rmap_name
1795 * we want to just show the output as it currently
1796 * exists.
1797 */
1798 if (!rmap_name)
1799 return RMAP_PERMIT;
0b16f239 1800
d62a17ae 1801 /* Apply default weight value. */
1802 if (peer->weight[afi][safi])
1803 attr->weight = peer->weight[afi][safi];
0b16f239 1804
b787157a 1805 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1806
b787157a
DS
1807 /*
1808 * If we have a route map name and we do not find
1809 * the routemap that means we have an implicit
1810 * deny.
1811 */
1812 if (rmap == NULL)
1813 return RMAP_DENY;
0b16f239 1814
6006b807 1815 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1816 /* Route map apply. */
544be979 1817 /* Duplicate current value to new structure for modification. */
40381db7
DS
1818 rmap_path.peer = peer;
1819 rmap_path.attr = attr;
0b16f239 1820
0f672529 1821 rmap_type = peer->rmap_type;
b787157a 1822 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1823
b787157a 1824 /* Apply BGP route map to the attribute. */
1782514f 1825 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1826
0f672529 1827 peer->rmap_type = rmap_type;
b787157a
DS
1828
1829 if (ret == RMAP_DENYMATCH)
1830 /*
1831 * caller has multiple error paths with bgp_attr_flush()
1832 */
1833 return RMAP_DENY;
ac41b2a2 1834
d62a17ae 1835 return RMAP_PERMIT;
718e3744 1836}
6b0655a2 1837
5000f21c 1838/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1839static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1840 struct peer *peer, struct attr *attr)
1841{
1842 if (peer->sort == BGP_PEER_EBGP
1843 && (peer_af_flag_check(peer, afi, safi,
1844 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1845 || peer_af_flag_check(peer, afi, safi,
1846 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1847 || peer_af_flag_check(peer, afi, safi,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1849 || peer_af_flag_check(peer, afi, safi,
1850 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1851 // Take action on the entire aspath
1852 if (peer_af_flag_check(peer, afi, safi,
1853 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1854 || peer_af_flag_check(peer, afi, safi,
1855 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1856 if (peer_af_flag_check(
1857 peer, afi, safi,
1858 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1859 attr->aspath = aspath_replace_private_asns(
bf26b80e 1860 attr->aspath, bgp->as, peer->as);
d62a17ae 1861
179d5a0e
TA
1862 /*
1863 * Even if the aspath consists of just private ASNs we
1864 * need to walk the AS-Path to maintain all instances
1865 * of the peer's ASN to break possible loops.
1866 */
d62a17ae 1867 else
1868 attr->aspath = aspath_remove_private_asns(
bf26b80e 1869 attr->aspath, peer->as);
d62a17ae 1870 }
1871
1872 // 'all' was not specified so the entire aspath must be private
1873 // ASNs
1874 // for us to do anything
1875 else if (aspath_private_as_check(attr->aspath)) {
1876 if (peer_af_flag_check(
1877 peer, afi, safi,
1878 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1879 attr->aspath = aspath_replace_private_asns(
bf26b80e 1880 attr->aspath, bgp->as, peer->as);
d62a17ae 1881 else
179d5a0e
TA
1882 /*
1883 * Walk the aspath to retain any instances of
1884 * the peer_asn
1885 */
1886 attr->aspath = aspath_remove_private_asns(
1887 attr->aspath, peer->as);
d62a17ae 1888 }
1889 }
5000f21c
DS
1890}
1891
c7122e14 1892/* If this is an EBGP peer with as-override */
d62a17ae 1893static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1894 struct peer *peer, struct attr *attr)
1895{
bbe7bc46
DA
1896 struct aspath *aspath;
1897
9bbdb457 1898 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1899 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1900 if (attr->aspath->refcnt)
1901 aspath = aspath_dup(attr->aspath);
1902 else
1903 aspath = attr->aspath;
1904
1905 attr->aspath = aspath_intern(
1906 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1907
1908 aspath_free(aspath);
1909 }
d62a17ae 1910}
1911
1479ed2f
DA
1912void bgp_attr_add_llgr_community(struct attr *attr)
1913{
1914 struct community *old;
1915 struct community *new;
1916 struct community *merge;
1917 struct community *llgr;
1918
9a706b42 1919 old = bgp_attr_get_community(attr);
1479ed2f
DA
1920 llgr = community_str2com("llgr-stale");
1921
1922 assert(llgr);
1923
1924 if (old) {
1925 merge = community_merge(community_dup(old), llgr);
1926
1927 if (old->refcnt == 0)
1928 community_free(&old);
1929
1930 new = community_uniq_sort(merge);
1931 community_free(&merge);
1932 } else {
1933 new = community_dup(llgr);
1934 }
1935
1936 community_free(&llgr);
1937
9a706b42 1938 bgp_attr_set_community(attr, new);
1479ed2f
DA
1939}
1940
7f323236
DW
1941void bgp_attr_add_gshut_community(struct attr *attr)
1942{
1943 struct community *old;
1944 struct community *new;
1945 struct community *merge;
1946 struct community *gshut;
1947
9a706b42 1948 old = bgp_attr_get_community(attr);
7f323236
DW
1949 gshut = community_str2com("graceful-shutdown");
1950
990f4f91 1951 assert(gshut);
1952
7f323236
DW
1953 if (old) {
1954 merge = community_merge(community_dup(old), gshut);
1955
a4d82a8a 1956 if (old->refcnt == 0)
3c1f53de 1957 community_free(&old);
7f323236
DW
1958
1959 new = community_uniq_sort(merge);
3c1f53de 1960 community_free(&merge);
7f323236
DW
1961 } else {
1962 new = community_dup(gshut);
1963 }
1964
3c1f53de 1965 community_free(&gshut);
9a706b42 1966 bgp_attr_set_community(attr, new);
7f323236
DW
1967
1968 /* When we add the graceful-shutdown community we must also
1969 * lower the local-preference */
1970 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1971 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1972}
1973
1974
e73c112e
MK
1975/* Notify BGP Conditional advertisement scanner process. */
1976void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1977{
e73c112e 1978 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1979 afi_t afi = SUBGRP_AFI(subgrp);
1980 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1981 struct bgp_filter *filter = &peer->filter[afi][safi];
1982
1983 if (!ADVERTISE_MAP_NAME(filter))
1984 return;
1985
52979c3b
DS
1986 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1987 return;
e73c112e 1988
52979c3b 1989 peer->advmap_table_change = true;
e73c112e
MK
1990}
1991
1992
f2ee6d5c 1993void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1994{
960035b2 1995 if (family == AF_INET) {
975a328e
DA
1996 attr->nexthop.s_addr = INADDR_ANY;
1997 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1998 }
d62a17ae 1999 if (family == AF_INET6)
2000 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
2001 if (family == AF_EVPN)
2002 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
2003}
2004
9bcb3eef 2005bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 2006 struct update_subgroup *subgrp,
7f7940e6 2007 const struct prefix *p, struct attr *attr,
51c3a7de 2008 struct attr *post_attr)
d62a17ae 2009{
2010 struct bgp_filter *filter;
2011 struct peer *from;
2012 struct peer *peer;
2013 struct peer *onlypeer;
2014 struct bgp *bgp;
40381db7 2015 struct attr *piattr;
b68885f9 2016 route_map_result_t ret;
d62a17ae 2017 int transparent;
2018 int reflect;
2019 afi_t afi;
2020 safi_t safi;
2021 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 2022 bool nh_reset = false;
2023 uint64_t cum_bw;
d62a17ae 2024
2025 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 2026 return false;
d62a17ae 2027
2028 afi = SUBGRP_AFI(subgrp);
2029 safi = SUBGRP_SAFI(subgrp);
2030 peer = SUBGRP_PEER(subgrp);
2031 onlypeer = NULL;
2032 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2033 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2034
40381db7 2035 from = pi->peer;
d62a17ae 2036 filter = &peer->filter[afi][safi];
2037 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2038 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2039 : pi->attr;
3f9c7369 2040
d0bf49ec
LS
2041 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2042 peer->pmax_out[afi][safi] != 0 &&
2043 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2044 if (BGP_DEBUG(update, UPDATE_OUT) ||
2045 BGP_DEBUG(update, UPDATE_PREFIX)) {
2046 zlog_debug("%s reached maximum prefix to be send (%u)",
2047 peer->host, peer->pmax_out[afi][safi]);
2048 }
2049 return false;
2050 }
2051
49e5a4a0 2052#ifdef ENABLE_BGP_VNC
d62a17ae 2053 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2054 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2055 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2056
2057 /*
2058 * direct and direct_ext type routes originate internally even
2059 * though they can have peer pointers that reference other
2060 * systems
2061 */
8228a9a7
DS
2062 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2063 __func__, p);
d62a17ae 2064 samepeer_safe = 1;
2065 }
65efcfce
LB
2066#endif
2067
ddb5b488
PZ
2068 if (((afi == AFI_IP) || (afi == AFI_IP6))
2069 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2070 && (pi->type == ZEBRA_ROUTE_BGP)
2071 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2072
2073 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2074
2075 samepeer_safe = 1;
2076 }
2077
d62a17ae 2078 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2079 * pi is valid */
2080 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2081 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2082 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2083 return false;
d62a17ae 2084 }
adbac85e 2085
d62a17ae 2086 /* If this is not the bestpath then check to see if there is an enabled
2087 * addpath
2088 * feature that requires us to advertise it */
40381db7 2089 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 2090 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 2091 return false;
d62a17ae 2092 }
2093 }
06370dac 2094
d62a17ae 2095 /* Aggregate-address suppress check. */
4056a5f6
RZ
2096 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2097 return false;
3f9c7369 2098
13b7e7f0
DS
2099 /*
2100 * If we are doing VRF 2 VRF leaking via the import
2101 * statement, we want to prevent the route going
2102 * off box as that the RT and RD created are localy
2103 * significant and globaly useless.
2104 */
40381db7
DS
2105 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2106 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2107 return false;
13b7e7f0 2108
d62a17ae 2109 /* If it's labeled safi, make sure the route has a valid label. */
2110 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2111 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2112 if (!bgp_is_valid_label(&label)) {
2113 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2114 zlog_debug("u%" PRIu64 ":s%" PRIu64
2115 " %pFX is filtered - no label (%p)",
d62a17ae 2116 subgrp->update_group->id, subgrp->id,
8228a9a7 2117 p, &label);
3dc339cd 2118 return false;
d62a17ae 2119 }
2120 }
cd1964ff 2121
d62a17ae 2122 /* Do not send back route to sender. */
2123 if (onlypeer && from == onlypeer) {
3dc339cd 2124 return false;
d62a17ae 2125 }
3f9c7369 2126
d62a17ae 2127 /* Do not send the default route in the BGP table if the neighbor is
2128 * configured for default-originate */
2129 if (CHECK_FLAG(peer->af_flags[afi][safi],
2130 PEER_FLAG_DEFAULT_ORIGINATE)) {
2131 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2132 return false;
d62a17ae 2133 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2134 return false;
d62a17ae 2135 }
4125bb67 2136
d62a17ae 2137 /* Transparency check. */
2138 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2139 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2140 transparent = 1;
2141 else
2142 transparent = 0;
2143
2144 /* If community is not disabled check the no-export and local. */
40381db7 2145 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2146 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2147 zlog_debug("%s: community filter check fail for %pFX",
2148 __func__, p);
3dc339cd 2149 return false;
d62a17ae 2150 }
3f9c7369 2151
d62a17ae 2152 /* If the attribute has originator-id and it is same as remote
2153 peer's id. */
40381db7
DS
2154 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2155 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2156 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2157 zlog_debug(
a9f3f4f5
DA
2158 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2159 onlypeer, p);
3dc339cd 2160 return false;
d62a17ae 2161 }
3f9c7369 2162
d62a17ae 2163 /* ORF prefix-list filter check */
2164 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2165 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2166 || CHECK_FLAG(peer->af_cap[afi][safi],
2167 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2168 if (peer->orf_plist[afi][safi]) {
2169 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2170 == PREFIX_DENY) {
2171 if (bgp_debug_update(NULL, p,
2172 subgrp->update_group, 0))
2173 zlog_debug(
a9f3f4f5
DA
2174 "%pBP [Update:SEND] %pFX is filtered via ORF",
2175 peer, p);
3dc339cd 2176 return false;
d62a17ae 2177 }
2178 }
2179
2180 /* Output filter check. */
40381db7 2181 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2182 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2183 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2184 p);
3dc339cd 2185 return false;
d62a17ae 2186 }
3f9c7369 2187
d62a17ae 2188 /* AS path loop check. */
2b31007c
RZ
2189 if (onlypeer && onlypeer->as_path_loop_detection
2190 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2191 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2192 zlog_debug(
a9f3f4f5
DA
2193 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2194 onlypeer, onlypeer->as);
3dc339cd 2195 return false;
d62a17ae 2196 }
3f9c7369 2197
d62a17ae 2198 /* If we're a CONFED we need to loop check the CONFED ID too */
2199 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2200 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2201 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2202 zlog_debug(
a9f3f4f5
DA
2203 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2204 peer, bgp->confed_id);
3dc339cd 2205 return false;
d62a17ae 2206 }
3f9c7369 2207 }
3f9c7369 2208
d62a17ae 2209 /* Route-Reflect check. */
2210 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2211 reflect = 1;
2212 else
2213 reflect = 0;
2214
2215 /* IBGP reflection check. */
2216 if (reflect && !samepeer_safe) {
2217 /* A route from a Client peer. */
2218 if (CHECK_FLAG(from->af_flags[afi][safi],
2219 PEER_FLAG_REFLECTOR_CLIENT)) {
2220 /* Reflect to all the Non-Client peers and also to the
2221 Client peers other than the originator. Originator
2222 check
2223 is already done. So there is noting to do. */
2224 /* no bgp client-to-client reflection check. */
892fedb6
DA
2225 if (CHECK_FLAG(bgp->flags,
2226 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2227 if (CHECK_FLAG(peer->af_flags[afi][safi],
2228 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2229 return false;
d62a17ae 2230 } else {
2231 /* A route from a Non-client peer. Reflect to all other
2232 clients. */
2233 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2234 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2235 return false;
d62a17ae 2236 }
2237 }
3f9c7369 2238
51c3a7de
DA
2239 /* For modify attribute, copy it to temporary structure.
2240 * post_attr comes from BGP conditional advertisements, where
2241 * attributes are already processed by advertise-map route-map,
2242 * and this needs to be saved instead of overwriting from the
2243 * path attributes.
2244 */
2245 if (post_attr)
2246 *attr = *post_attr;
2247 else
2248 *attr = *piattr;
d62a17ae 2249
2250 /* If local-preference is not set. */
2251 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2252 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2253 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2254 attr->local_pref = bgp->default_local_pref;
3f9c7369 2255 }
3f9c7369 2256
d62a17ae 2257 /* If originator-id is not set and the route is to be reflected,
2258 set the originator id */
2259 if (reflect
2260 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2261 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2262 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2263 }
3f9c7369 2264
d62a17ae 2265 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2266 */
2267 if (peer->sort == BGP_PEER_EBGP
2268 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2269 if (from != bgp->peer_self && !transparent
2270 && !CHECK_FLAG(peer->af_flags[afi][safi],
2271 PEER_FLAG_MED_UNCHANGED))
2272 attr->flag &=
2273 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2274 }
3f9c7369 2275
d62a17ae 2276 /* Since the nexthop attribute can vary per peer, it is not explicitly
2277 * set
2278 * in announce check, only certain flags and length (or number of
2279 * nexthops
2280 * -- for IPv6/MP_REACH) are set here in order to guide the update
2281 * formation
2282 * code in setting the nexthop(s) on a per peer basis in
2283 * reformat_peer().
2284 * Typically, the source nexthop in the attribute is preserved but in
2285 * the
2286 * scenarios where we know it will always be overwritten, we reset the
2287 * nexthop to "0" in an attempt to achieve better Update packing. An
2288 * example of this is when a prefix from each of 2 IBGP peers needs to
2289 * be
2290 * announced to an EBGP peer (and they have the same attributes barring
2291 * their nexthop).
2292 */
2293 if (reflect)
2294 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2295
2296#define NEXTHOP_IS_V6 \
2297 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2298 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2299 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2300 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2301
2302 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2303 * if
2304 * the peer (group) is configured to receive link-local nexthop
2305 * unchanged
c728d027
DA
2306 * and it is available in the prefix OR we're not reflecting the route,
2307 * link-local nexthop address is valid and
d62a17ae 2308 * the peer (group) to whom we're going to announce is on a shared
2309 * network
2310 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2311 * By checking if nexthop LL address is valid we are sure that
2312 * we do not announce LL address as `::`.
d62a17ae 2313 */
2314 if (NEXTHOP_IS_V6) {
2315 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2316 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2317 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2318 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2319 || (!reflect && !transparent
c728d027
DA
2320 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2321 && peer->shared_network
d62a17ae 2322 && (from == bgp->peer_self
2323 || peer->sort == BGP_PEER_EBGP))) {
2324 attr->mp_nexthop_len =
2325 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2326 }
3f9c7369 2327
d62a17ae 2328 /* Clear off link-local nexthop in source, whenever it is not
2329 * needed to
2330 * ensure more prefixes share the same attribute for
2331 * announcement.
2332 */
2333 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2334 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2335 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2336 }
3f9c7369 2337
5a78f2bc
EB
2338 if (bgp_check_role_applicability(afi, safi) &&
2339 bgp_otc_egress(peer, attr))
d864dd9e
EB
2340 return false;
2341
d62a17ae 2342 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2343 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2344
0655090c
QY
2345 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2346 filter->advmap.aname &&
2347 route_map_lookup_by_name(filter->advmap.aname)) {
2348 struct bgp_path_info rmap_path = {0};
2349 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2350 struct attr dummy_attr = *attr;
2351
2352 /* Fill temp path_info */
2353 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2354 pi, peer, &dummy_attr);
2355
2356 struct route_map *amap =
2357 route_map_lookup_by_name(filter->advmap.aname);
2358
2359 ret = route_map_apply(amap, p, &rmap_path);
2360
2361 bgp_attr_flush(&dummy_attr);
2362
2363 /*
2364 * The conditional advertisement mode is Withdraw and this
2365 * prefix is a conditional prefix. Don't advertise it
2366 */
2367 if (ret == RMAP_PERMITMATCH)
2368 return false;
2369 }
2370
d62a17ae 2371 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2372 if (!post_attr &&
2373 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2374 struct bgp_path_info rmap_path = {0};
2375 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2376 struct attr dummy_attr = {0};
d62a17ae 2377
e34291b8 2378 /* Fill temp path_info */
9bcb3eef
DS
2379 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2380 pi, peer, attr);
16f7ce2b 2381
d62a17ae 2382 /* don't confuse inbound and outbound setting */
2383 RESET_FLAG(attr->rmap_change_flags);
2384
2385 /*
2386 * The route reflector is not allowed to modify the attributes
2387 * of the reflected IBGP routes unless explicitly allowed.
2388 */
2389 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2390 && !CHECK_FLAG(bgp->flags,
2391 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2392 dummy_attr = *attr;
40381db7 2393 rmap_path.attr = &dummy_attr;
d62a17ae 2394 }
3f9c7369 2395
d62a17ae 2396 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2397
4056a5f6 2398 if (bgp_path_suppressed(pi))
d62a17ae 2399 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2400 &rmap_path);
d62a17ae 2401 else
2402 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2403 &rmap_path);
d62a17ae 2404
7e7639f5 2405 bgp_attr_flush(&dummy_attr);
d62a17ae 2406 peer->rmap_type = 0;
2407
2408 if (ret == RMAP_DENYMATCH) {
778048bf 2409 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2410 zlog_debug(
a9f3f4f5
DA
2411 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2412 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2413 bgp_attr_flush(rmap_path.attr);
3dc339cd 2414 return false;
d62a17ae 2415 }
3f9c7369 2416 }
3f9c7369 2417
9dac9fc8
DA
2418 /* RFC 8212 to prevent route leaks.
2419 * This specification intends to improve this situation by requiring the
2420 * explicit configuration of both BGP Import and Export Policies for any
2421 * External BGP (EBGP) session such as customers, peers, or
2422 * confederation boundaries for all enabled address families. Through
2423 * codification of the aforementioned requirement, operators will
2424 * benefit from consistent behavior across different BGP
2425 * implementations.
2426 */
1d3fdccf 2427 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2428 if (!bgp_outbound_policy_exists(peer, filter)) {
2429 if (monotime_since(&bgp->ebgprequirespolicywarning,
2430 NULL) > FIFTEENMINUTE2USEC ||
2431 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2432 zlog_warn(
2433 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2434 monotime(&bgp->ebgprequirespolicywarning);
2435 }
3dc339cd 2436 return false;
b17826b7 2437 }
9dac9fc8 2438
fb29348a
DA
2439 /* draft-ietf-idr-deprecate-as-set-confed-set
2440 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2441 * Eventually, This document (if approved) updates RFC 4271
2442 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2443 * and obsoletes RFC 6472.
2444 */
7f972cd8 2445 if (peer->bgp->reject_as_sets)
fb29348a 2446 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2447 return false;
fb29348a 2448
8c4d4624 2449 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2450 * SoO extended community and validate against the configured
2451 * one. If they match, do not announce, to prevent routing
2452 * loops.
2453 */
2454 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2455 peer->soo[afi][safi]) {
2456 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2457 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2458
2459 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2460 ECOMMUNITY_SITE_ORIGIN) ||
2461 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2462 ECOMMUNITY_SITE_ORIGIN) ||
2463 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2464 ECOMMUNITY_SITE_ORIGIN)) &&
2465 ecommunity_include(ecomm, ecomm_soo)) {
2466 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2467 zlog_debug(
2468 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2469 peer, p, ecommunity_str(ecomm_soo));
2470 return false;
2471 }
2472 }
2473
33d022bc
DA
2474 /* Codification of AS 0 Processing */
2475 if (aspath_check_as_zero(attr->aspath))
e2369003 2476 return false;
33d022bc 2477
637e5ba4 2478 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2479 if (peer->sort == BGP_PEER_IBGP
2480 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2481 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2482 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2483 } else {
2484 bgp_attr_add_gshut_community(attr);
2485 }
2486 }
2487
1479ed2f
DA
2488 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2489 * Capability" to a neighbor MUST perform the following upon receiving
2490 * a route from that neighbor with the "LLGR_STALE" community, or upon
2491 * attaching the "LLGR_STALE" community itself per Section 4.2:
2492 *
2493 * The route SHOULD NOT be advertised to any neighbor from which the
2494 * Long-lived Graceful Restart Capability has not been received.
2495 */
9a706b42
DA
2496 if (bgp_attr_get_community(attr) &&
2497 community_include(bgp_attr_get_community(attr),
2498 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2499 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2500 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2501 return false;
2502
d62a17ae 2503 /* After route-map has been applied, we check to see if the nexthop to
2504 * be carried in the attribute (that is used for the announcement) can
2505 * be cleared off or not. We do this in all cases where we would be
2506 * setting the nexthop to "ourselves". For IPv6, we only need to
2507 * consider
2508 * the global nexthop here; the link-local nexthop would have been
2509 * cleared
2510 * already, and if not, it is required by the update formation code.
2511 * Also see earlier comments in this function.
2512 */
2513 /*
2514 * If route-map has performed some operation on the nexthop or the peer
2515 * configuration says to pass it unchanged, we cannot reset the nexthop
2516 * here, so only attempt to do it if these aren't true. Note that the
2517 * route-map handler itself might have cleared the nexthop, if for
2518 * example,
2519 * it is configured as 'peer-address'.
2520 */
2521 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2522 piattr->rmap_change_flags)
d62a17ae 2523 && !transparent
2524 && !CHECK_FLAG(peer->af_flags[afi][safi],
2525 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2526 /* We can reset the nexthop, if setting (or forcing) it to
2527 * 'self' */
2528 if (CHECK_FLAG(peer->af_flags[afi][safi],
2529 PEER_FLAG_NEXTHOP_SELF)
2530 || CHECK_FLAG(peer->af_flags[afi][safi],
2531 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2532 if (!reflect
2533 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2534 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2535 subgroup_announce_reset_nhop(
2536 (peer_cap_enhe(peer, afi, safi)
2537 ? AF_INET6
2538 : p->family),
2539 attr);
7b651a32 2540 nh_reset = true;
2541 }
d62a17ae 2542 } else if (peer->sort == BGP_PEER_EBGP) {
2543 /* Can also reset the nexthop if announcing to EBGP, but
2544 * only if
2545 * no peer in the subgroup is on a shared subnet.
2546 * Note: 3rd party nexthop currently implemented for
2547 * IPv4 only.
2548 */
737af885
BS
2549 if ((p->family == AF_INET) &&
2550 (!bgp_subgrp_multiaccess_check_v4(
2551 piattr->nexthop,
7b651a32 2552 subgrp, from))) {
d62a17ae 2553 subgroup_announce_reset_nhop(
2554 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2555 ? AF_INET6
2556 : p->family),
737af885 2557 attr);
7b651a32 2558 nh_reset = true;
2559 }
737af885
BS
2560
2561 if ((p->family == AF_INET6) &&
2562 (!bgp_subgrp_multiaccess_check_v6(
2563 piattr->mp_nexthop_global,
7b651a32 2564 subgrp, from))) {
737af885
BS
2565 subgroup_announce_reset_nhop(
2566 (peer_cap_enhe(peer, afi, safi)
2567 ? AF_INET6
2568 : p->family),
2569 attr);
7b651a32 2570 nh_reset = true;
2571 }
737af885
BS
2572
2573
2574
40381db7 2575 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2576 /*
2577 * This flag is used for leaked vpn-vrf routes
2578 */
2579 int family = p->family;
2580
2581 if (peer_cap_enhe(peer, afi, safi))
2582 family = AF_INET6;
2583
2584 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2585 zlog_debug(
6cf8a4bf
DA
2586 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2587 __func__, p, family2str(family));
960035b2 2588 subgroup_announce_reset_nhop(family, attr);
7b651a32 2589 nh_reset = true;
d62a17ae 2590 }
63696f1d 2591 }
960035b2 2592
63696f1d 2593 /* If IPv6/MP and nexthop does not have any override and happens
2594 * to
2595 * be a link-local address, reset it so that we don't pass along
2596 * the
2597 * source's link-local IPv6 address to recipients who may not be
2598 * on
2599 * the same interface.
2600 */
2601 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2602 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2603 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2604 nh_reset = true;
2605 }
d62a17ae 2606 }
3f9c7369 2607
7b27cf7b
DA
2608 /* If this is an iBGP, send Origin Validation State (OVS)
2609 * extended community (rfc8097).
2610 */
2611 if (peer->sort == BGP_PEER_IBGP) {
2612 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2613
2614 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2615
2616 if (rpki_state != RPKI_NOT_BEING_USED)
2617 bgp_attr_set_ecommunity(
2618 attr, ecommunity_add_origin_validation_state(
2619 rpki_state,
2620 bgp_attr_get_ecommunity(attr)));
2621 }
2622
7b651a32 2623 /*
2624 * When the next hop is set to ourselves, if all multipaths have
2625 * link-bandwidth announce the cumulative bandwidth as that makes
2626 * the most sense. However, don't modify if the link-bandwidth has
2627 * been explicitly set by user policy.
2628 */
2629 if (nh_reset &&
f7e1c681 2630 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2631 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2632 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2633 bgp_attr_set_ecommunity(
2634 attr,
2635 ecommunity_replace_linkbw(
2636 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2637 CHECK_FLAG(
2638 peer->flags,
2639 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2640
3dc339cd 2641 return true;
3f9c7369
DS
2642}
2643
cc9f21da 2644static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2645{
2646 struct afi_safi_info *info;
2647 afi_t afi;
2648 safi_t safi;
2649 struct bgp *bgp;
2650
2651 info = THREAD_ARG(thread);
2652 afi = info->afi;
2653 safi = info->safi;
2654 bgp = info->bgp;
2655
f009ff26 2656 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2657 XFREE(MTYPE_TMP, info);
2658
2659 /* Best path selection */
cc9f21da 2660 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2661}
2662
9bcb3eef 2663void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2664 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2665 struct bgp_path_info_pair *result, afi_t afi,
2666 safi_t safi)
2667{
2668 struct bgp_path_info *new_select;
2669 struct bgp_path_info *old_select;
40381db7
DS
2670 struct bgp_path_info *pi;
2671 struct bgp_path_info *pi1;
2672 struct bgp_path_info *pi2;
2673 struct bgp_path_info *nextpi = NULL;
d62a17ae 2674 int paths_eq, do_mpath, debug;
2675 struct list mp_list;
2676 char pfx_buf[PREFIX2STR_BUFFER];
2677 char path_buf[PATH_ADDPATH_STR_BUFFER];
2678
2679 bgp_mp_list_init(&mp_list);
2680 do_mpath =
2681 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2682
9bcb3eef 2683 debug = bgp_debug_bestpath(dest);
d62a17ae 2684
2685 if (debug)
9bcb3eef 2686 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2687
9bcb3eef 2688 dest->reason = bgp_path_selection_none;
d62a17ae 2689 /* bgp deterministic-med */
2690 new_select = NULL;
892fedb6 2691 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2692
1defdda8 2693 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2694 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2695 pi1 = pi1->next)
9bcb3eef 2696 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2697 BGP_PATH_DMED_SELECTED);
d62a17ae 2698
9bcb3eef 2699 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2700 pi1 = pi1->next) {
40381db7 2701 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2702 continue;
40381db7 2703 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2704 continue;
ea8b2282 2705 if (pi1->peer != bgp->peer_self)
feb17238 2706 if (!peer_established(pi1->peer))
d62a17ae 2707 continue;
2708
40381db7
DS
2709 new_select = pi1;
2710 if (pi1->next) {
2711 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2712 if (CHECK_FLAG(pi2->flags,
1defdda8 2713 BGP_PATH_DMED_CHECK))
d62a17ae 2714 continue;
40381db7 2715 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2716 continue;
ea8b2282 2717 if (pi2->peer != bgp->peer_self
d62a17ae 2718 && !CHECK_FLAG(
ea8b2282
DS
2719 pi2->peer->sflags,
2720 PEER_STATUS_NSF_WAIT))
40381db7 2721 if (pi2->peer->status
d62a17ae 2722 != Established)
2723 continue;
2724
121e245d
DS
2725 if (!aspath_cmp_left(pi1->attr->aspath,
2726 pi2->attr->aspath)
2727 && !aspath_cmp_left_confed(
40381db7 2728 pi1->attr->aspath,
121e245d
DS
2729 pi2->attr->aspath))
2730 continue;
d62a17ae 2731
121e245d
DS
2732 if (bgp_path_info_cmp(
2733 bgp, pi2, new_select,
2734 &paths_eq, mpath_cfg, debug,
fdf81fa0 2735 pfx_buf, afi, safi,
9bcb3eef 2736 &dest->reason)) {
121e245d 2737 bgp_path_info_unset_flag(
9bcb3eef 2738 dest, new_select,
121e245d
DS
2739 BGP_PATH_DMED_SELECTED);
2740 new_select = pi2;
d62a17ae 2741 }
121e245d
DS
2742
2743 bgp_path_info_set_flag(
9bcb3eef 2744 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2745 }
2746 }
9bcb3eef 2747 bgp_path_info_set_flag(dest, new_select,
18ee8310 2748 BGP_PATH_DMED_CHECK);
9bcb3eef 2749 bgp_path_info_set_flag(dest, new_select,
18ee8310 2750 BGP_PATH_DMED_SELECTED);
d62a17ae 2751
2752 if (debug) {
18ee8310 2753 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2754 new_select, path_buf, sizeof(path_buf));
8228a9a7 2755 zlog_debug(
4378495a
DS
2756 "%pBD(%s): %s is the bestpath from AS %u",
2757 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2758 aspath_get_first_as(
2759 new_select->attr->aspath));
d62a17ae 2760 }
2761 }
2762 }
96450faf 2763
d62a17ae 2764 /* Check old selected route and new selected route. */
2765 old_select = NULL;
2766 new_select = NULL;
9bcb3eef 2767 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2768 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2769 enum bgp_path_selection_reason reason;
2770
40381db7
DS
2771 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2772 old_select = pi;
d62a17ae 2773
40381db7 2774 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2775 /* reap REMOVED routes, if needs be
2776 * selected route must stay for a while longer though
2777 */
40381db7
DS
2778 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2779 && (pi != old_select))
9bcb3eef 2780 bgp_path_info_reap(dest, pi);
d62a17ae 2781
ddb5b488 2782 if (debug)
40381db7
DS
2783 zlog_debug("%s: pi %p in holddown", __func__,
2784 pi);
ddb5b488 2785
d62a17ae 2786 continue;
2787 }
96450faf 2788
40381db7
DS
2789 if (pi->peer && pi->peer != bgp->peer_self
2790 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2791 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2792
2793 if (debug)
2794 zlog_debug(
40381db7
DS
2795 "%s: pi %p non self peer %s not estab state",
2796 __func__, pi, pi->peer->host);
ddb5b488 2797
d62a17ae 2798 continue;
ddb5b488 2799 }
9fbdd100 2800
892fedb6 2801 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2802 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2803 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2804 if (debug)
40381db7 2805 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2806 continue;
2807 }
9fbdd100 2808
9bcb3eef 2809 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2810
9bcb3eef 2811 reason = dest->reason;
40381db7 2812 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2813 debug, pfx_buf, afi, safi,
2814 &dest->reason)) {
19ea4cec
DS
2815 if (new_select == NULL &&
2816 reason != bgp_path_selection_none)
9bcb3eef 2817 dest->reason = reason;
40381db7 2818 new_select = pi;
d62a17ae 2819 }
2820 }
718e3744 2821
d62a17ae 2822 /* Now that we know which path is the bestpath see if any of the other
2823 * paths
2824 * qualify as multipaths
2825 */
2826 if (debug) {
2827 if (new_select)
7533cad7
QY
2828 bgp_path_info_path_with_addpath_rx_str(
2829 new_select, path_buf, sizeof(path_buf));
d62a17ae 2830 else
772270f3 2831 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2832 zlog_debug(
4378495a
DS
2833 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2834 dest, bgp->name_pretty, path_buf,
d62a17ae 2835 old_select ? old_select->peer->host : "NONE");
96450faf 2836 }
9fbdd100 2837
d62a17ae 2838 if (do_mpath && new_select) {
9bcb3eef 2839 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2840 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2841
2842 if (debug)
18ee8310 2843 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2844 pi, path_buf, sizeof(path_buf));
d62a17ae 2845
40381db7 2846 if (pi == new_select) {
d62a17ae 2847 if (debug)
2848 zlog_debug(
4378495a
DS
2849 "%pBD(%s): %s is the bestpath, add to the multipath list",
2850 dest, bgp->name_pretty,
2851 path_buf);
40381db7 2852 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2853 continue;
2854 }
2855
40381db7 2856 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2857 continue;
2858
40381db7
DS
2859 if (pi->peer && pi->peer != bgp->peer_self
2860 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2861 PEER_STATUS_NSF_WAIT))
feb17238 2862 if (!peer_established(pi->peer))
d62a17ae 2863 continue;
2864
40381db7 2865 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2866 if (debug)
2867 zlog_debug(
8228a9a7
DS
2868 "%pBD: %s has the same nexthop as the bestpath, skip it",
2869 dest, path_buf);
d62a17ae 2870 continue;
2871 }
2872
40381db7 2873 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2874 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2875 &dest->reason);
d62a17ae 2876
2877 if (paths_eq) {
2878 if (debug)
2879 zlog_debug(
8228a9a7
DS
2880 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2881 dest, path_buf);
40381db7 2882 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2883 }
2884 }
2885 }
fee0f4c6 2886
4378495a 2887 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2888 mpath_cfg);
2889 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2890 bgp_mp_list_clear(&mp_list);
96450faf 2891
9bcb3eef 2892 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2893
d62a17ae 2894 result->old = old_select;
2895 result->new = new_select;
96450faf 2896
d62a17ae 2897 return;
fee0f4c6 2898}
2899
3f9c7369
DS
2900/*
2901 * A new route/change in bestpath of an existing route. Evaluate the path
2902 * for advertisement to the subgroup.
2903 */
3dc339cd
DA
2904void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2905 struct bgp_path_info *selected,
9bcb3eef 2906 struct bgp_dest *dest,
3dc339cd 2907 uint32_t addpath_tx_id)
d62a17ae 2908{
b54892e0 2909 const struct prefix *p;
d62a17ae 2910 struct peer *onlypeer;
2911 struct attr attr;
2912 afi_t afi;
2913 safi_t safi;
a77e2f4b
S
2914 struct bgp *bgp;
2915 bool advertise;
adbac85e 2916
9bcb3eef 2917 p = bgp_dest_get_prefix(dest);
d62a17ae 2918 afi = SUBGRP_AFI(subgrp);
2919 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2920 bgp = SUBGRP_INST(subgrp);
d62a17ae 2921 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2922 : NULL);
2923
2dbe669b
DA
2924 if (BGP_DEBUG(update, UPDATE_OUT))
2925 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2926
d62a17ae 2927 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2928 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2929 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2930 return;
d62a17ae 2931
6006b807 2932 memset(&attr, 0, sizeof(attr));
d62a17ae 2933 /* It's initialized in bgp_announce_check() */
2934
a77e2f4b
S
2935 /* Announcement to the subgroup. If the route is filtered withdraw it.
2936 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2937 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2938 * route
d62a17ae 2939 */
a77e2f4b
S
2940 advertise = bgp_check_advertise(bgp, dest);
2941
d62a17ae 2942 if (selected) {
7f7940e6 2943 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2944 NULL)) {
a77e2f4b
S
2945 /* Route is selected, if the route is already installed
2946 * in FIB, then it is advertised
2947 */
be785e35
DS
2948 if (advertise) {
2949 if (!bgp_check_withdrawal(bgp, dest))
2950 bgp_adj_out_set_subgroup(
2951 dest, subgrp, &attr, selected);
2952 else
2953 bgp_adj_out_unset_subgroup(
2954 dest, subgrp, 1, addpath_tx_id);
2955 }
a77e2f4b 2956 } else
9bcb3eef 2957 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2958 addpath_tx_id);
d62a17ae 2959 }
2960
2961 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2962 else {
9bcb3eef 2963 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2964 }
200df115 2965}
fee0f4c6 2966
3064bf43 2967/*
e1072051 2968 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2969 * This is called at the end of route processing.
3064bf43 2970 */
9bcb3eef 2971void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2972{
40381db7 2973 struct bgp_path_info *pi;
3064bf43 2974
9bcb3eef 2975 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2976 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2977 continue;
40381db7
DS
2978 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2979 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2980 }
3064bf43 2981}
2982
2983/*
2984 * Has the route changed from the RIB's perspective? This is invoked only
2985 * if the route selection returns the same best route as earlier - to
2986 * determine if we need to update zebra or not.
2987 */
9bcb3eef 2988bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2989{
4b7e6066 2990 struct bgp_path_info *mpinfo;
d62a17ae 2991
2bb9eff4
DS
2992 /* If this is multipath, check all selected paths for any nexthop
2993 * change or attribute change. Some attribute changes (e.g., community)
2994 * aren't of relevance to the RIB, but we'll update zebra to ensure
2995 * we handle the case of BGP nexthop change. This is the behavior
2996 * when the best path has an attribute change anyway.
d62a17ae 2997 */
1defdda8 2998 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2999 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
3000 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 3001 return true;
d62a17ae 3002
2bb9eff4
DS
3003 /*
3004 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 3005 */
18ee8310
DS
3006 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
3007 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3008 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3009 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3010 return true;
d62a17ae 3011 }
3064bf43 3012
d62a17ae 3013 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3014 return false;
3064bf43 3015}
3016
d62a17ae 3017struct bgp_process_queue {
3018 struct bgp *bgp;
9bcb3eef 3019 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3020#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3021 unsigned int flags;
3022 unsigned int queued;
200df115 3023};
3024
3b0c17e1 3025static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3026 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3027 struct bgp_path_info *new_select,
3028 struct bgp_path_info *old_select)
3029{
9bcb3eef 3030 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3031
3032 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3033 return;
3034
3035 if (advertise_type5_routes(bgp, afi) && new_select
3036 && is_route_injectable_into_evpn(new_select)) {
3037
3038 /* apply the route-map */
3039 if (bgp->adv_cmd_rmap[afi][safi].map) {
3040 route_map_result_t ret;
3041 struct bgp_path_info rmap_path;
3042 struct bgp_path_info_extra rmap_path_extra;
3043 struct attr dummy_attr;
3044
3045 dummy_attr = *new_select->attr;
3046
3047 /* Fill temp path_info */
9bcb3eef 3048 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3049 new_select, new_select->peer,
3050 &dummy_attr);
3051
3052 RESET_FLAG(dummy_attr.rmap_change_flags);
3053
3054 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3055 p, &rmap_path);
3b0c17e1 3056
3057 if (ret == RMAP_DENYMATCH) {
3058 bgp_attr_flush(&dummy_attr);
3059 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3060 safi);
3061 } else
3062 bgp_evpn_advertise_type5_route(
3063 bgp, p, &dummy_attr, afi, safi);
3064 } else {
3065 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3066 afi, safi);
3067 }
3068 } else if (advertise_type5_routes(bgp, afi) && old_select
3069 && is_route_injectable_into_evpn(old_select))
3070 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3071}
3072
bb2ca692
MS
3073/*
3074 * Utility to determine whether a particular path_info should use
3075 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3076 * in a path where we basically _know_ this is a BGP-LU route.
3077 */
3078static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3079{
3080 /* Certain types get imp null; so do paths where the nexthop is
3081 * not labeled.
3082 */
3083 if (new_select->sub_type == BGP_ROUTE_STATIC
3084 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3085 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3086 return true;
3087 else if (new_select->extra == NULL ||
3088 !bgp_is_valid_label(&new_select->extra->label[0]))
3089 /* TODO -- should be configurable? */
3090 return true;
3091 else
3092 return false;
3093}
3094
3103e8d2
DS
3095/*
3096 * old_select = The old best path
3097 * new_select = the new best path
3098 *
3099 * if (!old_select && new_select)
3100 * We are sending new information on.
3101 *
3102 * if (old_select && new_select) {
3103 * if (new_select != old_select)
3104 * We have a new best path send a change
3105 * else
3106 * We've received a update with new attributes that needs
3107 * to be passed on.
3108 * }
3109 *
3110 * if (old_select && !new_select)
3111 * We have no eligible route that we can announce or the rn
3112 * is being removed.
3113 */
9bcb3eef 3114static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3115 afi_t afi, safi_t safi)
d62a17ae 3116{
4b7e6066
DS
3117 struct bgp_path_info *new_select;
3118 struct bgp_path_info *old_select;
3119 struct bgp_path_info_pair old_and_new;
ddb5b488 3120 int debug = 0;
d62a17ae 3121
892fedb6 3122 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3123 if (dest)
3124 debug = bgp_debug_bestpath(dest);
b54892e0 3125 if (debug)
f4c713ae 3126 zlog_debug(
56ca3b5b 3127 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3128 __func__, dest);
f4c713ae
LB
3129 return;
3130 }
d62a17ae 3131 /* Is it end of initial update? (after startup) */
9bcb3eef 3132 if (!dest) {
e36f61b5
DS
3133 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3134 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3135
3136 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3137 FOREACH_AFI_SAFI (afi, safi) {
3138 if (bgp_fibupd_safi(safi))
3139 bgp_zebra_announce_table(bgp, afi, safi);
3140 }
d62a17ae 3141 bgp->main_peers_update_hold = 0;
3142
3143 bgp_start_routeadv(bgp);
aac24838 3144 return;
d62a17ae 3145 }
cb1faec9 3146
9bcb3eef 3147 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3148
9bcb3eef 3149 debug = bgp_debug_bestpath(dest);
b54892e0 3150 if (debug)
4378495a
DS
3151 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3152 dest, bgp->name_pretty, afi2str(afi),
3153 safi2str(safi));
ddb5b488 3154
f009ff26 3155 /* The best path calculation for the route is deferred if
3156 * BGP_NODE_SELECT_DEFER is set
3157 */
9bcb3eef 3158 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3159 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3160 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3161 return;
3162 }
3163
d62a17ae 3164 /* Best path selection. */
9bcb3eef 3165 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3166 afi, safi);
3167 old_select = old_and_new.old;
3168 new_select = old_and_new.new;
3169
3170 /* Do we need to allocate or free labels?
3171 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3172 * necessary to do this upon changes to best path. Exceptions:
3173 * - label index has changed -> recalculate resulting label
3174 * - path_info sub_type changed -> switch to/from implicit-null
3175 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3176 */
318cac96 3177 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3178 if (new_select) {
3179 if (!old_select
3180 || bgp_label_index_differs(new_select, old_select)
57592a53 3181 || new_select->sub_type != old_select->sub_type
9bcb3eef 3182 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3183 /* Enforced penultimate hop popping:
3184 * implicit-null for local routes, aggregate
3185 * and redistributed routes
3186 */
bb2ca692 3187 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3188 if (CHECK_FLAG(
9bcb3eef 3189 dest->flags,
992dd67e
PR
3190 BGP_NODE_REGISTERED_FOR_LABEL)
3191 || CHECK_FLAG(
3192 dest->flags,
3193 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3194 bgp_unregister_for_label(dest);
67f67ba4
DA
3195 dest->local_label = mpls_lse_encode(
3196 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3197 1);
9bcb3eef 3198 bgp_set_valid_label(&dest->local_label);
d62a17ae 3199 } else
9bcb3eef
DS
3200 bgp_register_for_label(dest,
3201 new_select);
d62a17ae 3202 }
9bcb3eef 3203 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3204 BGP_NODE_REGISTERED_FOR_LABEL)
3205 || CHECK_FLAG(dest->flags,
3206 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3207 bgp_unregister_for_label(dest);
318cac96 3208 }
992dd67e
PR
3209 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3210 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3211 bgp_unregister_for_label(dest);
d62a17ae 3212 }
cd1964ff 3213
b54892e0 3214 if (debug)
ddb5b488 3215 zlog_debug(
4378495a
DS
3216 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3217 __func__, dest, bgp->name_pretty, afi2str(afi),
3218 safi2str(safi), old_select, new_select);
ddb5b488 3219
d62a17ae 3220 /* If best route remains the same and this is not due to user-initiated
3221 * clear, see exactly what needs to be done.
3222 */
d62a17ae 3223 if (old_select && old_select == new_select
9bcb3eef 3224 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3225 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3226 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3227 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3228#ifdef ENABLE_BGP_VNC
d62a17ae 3229 vnc_import_bgp_add_route(bgp, p, old_select);
3230 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3231#endif
bb744275 3232 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3233 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3234
be785e35
DS
3235 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3236 && new_select->sub_type == BGP_ROUTE_NORMAL)
3237 SET_FLAG(dest->flags,
3238 BGP_NODE_FIB_INSTALL_PENDING);
3239
ddb5b488
PZ
3240 if (new_select->type == ZEBRA_ROUTE_BGP
3241 && (new_select->sub_type == BGP_ROUTE_NORMAL
3242 || new_select->sub_type
3243 == BGP_ROUTE_IMPORTED))
3244
9bcb3eef 3245 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3246 bgp, afi, safi);
3247 }
d62a17ae 3248 }
d62a17ae 3249
3250 /* If there is a change of interest to peers, reannounce the
3251 * route. */
1defdda8 3252 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3253 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3254 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3255 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3256
3257 /* unicast routes must also be annouced to
3258 * labeled-unicast update-groups */
3259 if (safi == SAFI_UNICAST)
3260 group_announce_route(bgp, afi,
9bcb3eef 3261 SAFI_LABELED_UNICAST, dest,
d62a17ae 3262 new_select);
3263
1defdda8 3264 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3265 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3266 }
fee0f4c6 3267
3b0c17e1 3268 /* advertise/withdraw type-5 routes */
3269 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3270 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3271 bgp_process_evpn_route_injection(
9bcb3eef 3272 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3273
b1875e65 3274 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3275 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3276 bgp_zebra_clear_route_change_flags(dest);
3277 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3278 return;
d62a17ae 3279 }
8ad7271d 3280
d62a17ae 3281 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3282 */
9bcb3eef 3283 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3284
3285 /* bestpath has changed; bump version */
3286 if (old_select || new_select) {
9bcb3eef 3287 bgp_bump_version(dest);
d62a17ae 3288
3289 if (!bgp->t_rmap_def_originate_eval) {
3290 bgp_lock(bgp);
3291 thread_add_timer(
3292 bm->master,
3293 update_group_refresh_default_originate_route_map,
3294 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3295 &bgp->t_rmap_def_originate_eval);
3296 }
3297 }
3f9c7369 3298
d62a17ae 3299 if (old_select)
9bcb3eef 3300 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3301 if (new_select) {
ddb5b488
PZ
3302 if (debug)
3303 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3304 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3305 bgp_path_info_unset_flag(dest, new_select,
3306 BGP_PATH_ATTR_CHANGED);
1defdda8 3307 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3308 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3309 }
338b3424 3310
49e5a4a0 3311#ifdef ENABLE_BGP_VNC
d62a17ae 3312 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3313 if (old_select != new_select) {
3314 if (old_select) {
3315 vnc_import_bgp_exterior_del_route(bgp, p,
3316 old_select);
3317 vnc_import_bgp_del_route(bgp, p, old_select);
3318 }
3319 if (new_select) {
3320 vnc_import_bgp_exterior_add_route(bgp, p,
3321 new_select);
3322 vnc_import_bgp_add_route(bgp, p, new_select);
3323 }
3324 }
3325 }
65efcfce
LB
3326#endif
3327
9bcb3eef 3328 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3329
3330 /* unicast routes must also be annouced to labeled-unicast update-groups
3331 */
3332 if (safi == SAFI_UNICAST)
9bcb3eef 3333 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3334 new_select);
3335
3336 /* FIB update. */
3337 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3338 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3339
d62a17ae 3340 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3341 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3342 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3343 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3344
be785e35
DS
3345 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3346 SET_FLAG(dest->flags,
3347 BGP_NODE_FIB_INSTALL_PENDING);
3348
2b659f33
MK
3349 /* if this is an evpn imported type-5 prefix,
3350 * we need to withdraw the route first to clear
3351 * the nh neigh and the RMAC entry.
3352 */
3353 if (old_select &&
3354 is_route_parent_evpn(old_select))
3355 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3356
9bcb3eef 3357 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3358 } else {
d62a17ae 3359 /* Withdraw the route from the kernel. */
3360 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3361 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3362 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3363 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3364
568e10ca 3365 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3366 }
718e3744 3367 }
3064bf43 3368
9bcb3eef 3369 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3370 old_select);
5424b7ba 3371
d62a17ae 3372 /* Clear any route change flags. */
9bcb3eef 3373 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3374
18ee8310 3375 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3376 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3377 bgp_path_info_reap(dest, old_select);
d62a17ae 3378
9bcb3eef 3379 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3380 return;
718e3744 3381}
3382
f009ff26 3383/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3384void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3385{
9bcb3eef 3386 struct bgp_dest *dest;
f009ff26 3387 int cnt = 0;
3388 struct afi_safi_info *thread_info;
f009ff26 3389
56c226e7
DS
3390 if (bgp->gr_info[afi][safi].t_route_select) {
3391 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3392
3393 thread_info = THREAD_ARG(t);
3394 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3395 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3396 }
f009ff26 3397
3398 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3399 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3400 get_afi_safi_str(afi, safi, false),
26742171 3401 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3402 }
3403
3404 /* Process the route list */
6338d242 3405 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3406 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3407 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3408 dest = bgp_route_next(dest)) {
3409 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3410 continue;
3411
3412 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3413 bgp->gr_info[afi][safi].gr_deferred--;
3414 bgp_process_main_one(bgp, dest, afi, safi);
3415 cnt++;
067ea165
CB
3416 }
3417 /* If iteration stopped before the entire table was traversed then the
3418 * node needs to be unlocked.
3419 */
3420 if (dest) {
3421 bgp_dest_unlock_node(dest);
3422 dest = NULL;
f009ff26 3423 }
3424
9e3b51a7 3425 /* Send EOR message when all routes are processed */
6338d242 3426 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3427 bgp_send_delayed_eor(bgp);
8c48b3b6 3428 /* Send route processing complete message to RIB */
3429 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3430 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3431 return;
9e3b51a7 3432 }
f009ff26 3433
3434 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3435
3436 thread_info->afi = afi;
3437 thread_info->safi = safi;
3438 thread_info->bgp = bgp;
3439
3440 /* If there are more routes to be processed, start the
3441 * selection timer
3442 */
3443 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3444 BGP_ROUTE_SELECT_DELAY,
3445 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3446}
3447
aac24838 3448static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3449{
aac24838
JB
3450 struct bgp_process_queue *pqnode = data;
3451 struct bgp *bgp = pqnode->bgp;
d62a17ae 3452 struct bgp_table *table;
9bcb3eef 3453 struct bgp_dest *dest;
aac24838
JB
3454
3455 /* eoiu marker */
3456 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3457 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3458 /* should always have dedicated wq call */
3459 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3460 return WQ_SUCCESS;
3461 }
3462
ac021f40 3463 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3464 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3465 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3466 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3467 table = bgp_dest_table(dest);
3468 /* note, new DESTs may be added as part of processing */
3469 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3470
9bcb3eef 3471 bgp_dest_unlock_node(dest);
d62a17ae 3472 bgp_table_unlock(table);
3473 }
aac24838
JB
3474
3475 return WQ_SUCCESS;
3476}
3477
3478static void bgp_processq_del(struct work_queue *wq, void *data)
3479{
3480 struct bgp_process_queue *pqnode = data;
3481
3482 bgp_unlock(pqnode->bgp);
3483
3484 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3485}
3486
b6c386bb 3487void bgp_process_queue_init(struct bgp *bgp)
200df115 3488{
b6c386bb
DS
3489 if (!bgp->process_queue) {
3490 char name[BUFSIZ];
3491
3492 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3493 bgp->process_queue = work_queue_new(bm->master, name);
3494 }
3495
3496 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3497 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3498 bgp->process_queue->spec.max_retries = 0;
3499 bgp->process_queue->spec.hold = 50;
d62a17ae 3500 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3501 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3502}
3503
cfe8d15a 3504static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3505{
3506 struct bgp_process_queue *pqnode;
3507
a4d82a8a
PZ
3508 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3509 sizeof(struct bgp_process_queue));
aac24838
JB
3510
3511 /* unlocked in bgp_processq_del */
3512 pqnode->bgp = bgp_lock(bgp);
3513 STAILQ_INIT(&pqnode->pqueue);
3514
aac24838
JB
3515 return pqnode;
3516}
3517
9bcb3eef 3518void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3519{
aac24838 3520#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3521 struct work_queue *wq = bgp->process_queue;
d62a17ae 3522 struct bgp_process_queue *pqnode;
cfe8d15a 3523 int pqnode_reuse = 0;
495f0b13 3524
d62a17ae 3525 /* already scheduled for processing? */
9bcb3eef 3526 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3527 return;
2e02b9b2 3528
f009ff26 3529 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3530 * the workqueue
3531 */
9bcb3eef 3532 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3533 if (BGP_DEBUG(update, UPDATE_OUT))
3534 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3535 dest);
f009ff26 3536 return;
3537 }
3538
46aeabed
LS
3539 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3540 if (BGP_DEBUG(update, UPDATE_OUT))
3541 zlog_debug(
3542 "Soft reconfigure table in progress for route %p",
3543 dest);
3544 return;
3545 }
3546
aac24838 3547 if (wq == NULL)
d62a17ae 3548 return;
3549
aac24838 3550 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3551 limit only if is from the same BGP view and it's not an EOIU marker
3552 */
aac24838
JB
3553 if (work_queue_item_count(wq)) {
3554 struct work_queue_item *item = work_queue_last_item(wq);
3555 pqnode = item->data;
228da428 3556
a4d82a8a
PZ
3557 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3558 || pqnode->bgp != bgp
3559 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3560 pqnode = bgp_processq_alloc(bgp);
3561 else
3562 pqnode_reuse = 1;
aac24838 3563 } else
cfe8d15a 3564 pqnode = bgp_processq_alloc(bgp);
aac24838 3565 /* all unlocked in bgp_process_wq */
9bcb3eef 3566 bgp_table_lock(bgp_dest_table(dest));
aac24838 3567
9bcb3eef
DS
3568 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3569 bgp_dest_lock_node(dest);
aac24838 3570
60466a63 3571 /* can't be enqueued twice */
9bcb3eef
DS
3572 assert(STAILQ_NEXT(dest, pq) == NULL);
3573 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3574 pqnode->queued++;
3575
cfe8d15a
LB
3576 if (!pqnode_reuse)
3577 work_queue_add(wq, pqnode);
3578
d62a17ae 3579 return;
fee0f4c6 3580}
0a486e5f 3581
d62a17ae 3582void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3583{
d62a17ae 3584 struct bgp_process_queue *pqnode;
cb1faec9 3585
b6c386bb 3586 if (bgp->process_queue == NULL)
d62a17ae 3587 return;
2e02b9b2 3588
cfe8d15a 3589 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3590
aac24838 3591 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3592 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3593}
3594
cc9f21da 3595static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3596{
d62a17ae 3597 struct peer *peer;
0a486e5f 3598
d62a17ae 3599 peer = THREAD_ARG(thread);
3600 peer->t_pmax_restart = NULL;
0a486e5f 3601
d62a17ae 3602 if (bgp_debug_neighbor_events(peer))
3603 zlog_debug(
3604 "%s Maximum-prefix restart timer expired, restore peering",
3605 peer->host);
0a486e5f 3606
a9bafa95 3607 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3608 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3609}
3610
9cbd06e0
DA
3611static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3612 safi_t safi)
3613{
3614 uint32_t count = 0;
f41b0459 3615 bool filtered = false;
9cbd06e0
DA
3616 struct bgp_dest *dest;
3617 struct bgp_adj_in *ain;
40bb2ccf 3618 struct attr attr = {};
9cbd06e0
DA
3619 struct bgp_table *table = peer->bgp->rib[afi][safi];
3620
3621 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3622 for (ain = dest->adj_in; ain; ain = ain->next) {
3623 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3624
3625 attr = *ain->attr;
9cbd06e0
DA
3626
3627 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3628 == FILTER_DENY)
f41b0459
DA
3629 filtered = true;
3630
3631 if (bgp_input_modifier(
3632 peer, rn_p, &attr, afi, safi,
3633 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3634 NULL, 0, NULL)
3635 == RMAP_DENY)
3636 filtered = true;
3637
3638 if (filtered)
9cbd06e0 3639 count++;
f41b0459 3640
d498917e 3641 bgp_attr_flush(&attr);
9cbd06e0
DA
3642 }
3643 }
3644
3645 return count;
3646}
3647
3dc339cd
DA
3648bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3649 int always)
718e3744 3650{
d62a17ae 3651 iana_afi_t pkt_afi;
5c525538 3652 iana_safi_t pkt_safi;
9cbd06e0
DA
3653 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3654 PEER_FLAG_MAX_PREFIX_FORCE))
3655 ? bgp_filtered_routes_count(peer, afi, safi)
3656 + peer->pcount[afi][safi]
3657 : peer->pcount[afi][safi];
9cabb64b 3658
d62a17ae 3659 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3660 return false;
e0701b79 3661
9cbd06e0 3662 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3663 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3664 PEER_STATUS_PREFIX_LIMIT)
3665 && !always)
3dc339cd 3666 return false;
e0701b79 3667
d62a17ae 3668 zlog_info(
f70c91dc
DA
3669 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3670 get_afi_safi_str(afi, safi, false), peer, pcount,
3671 peer->pmax[afi][safi]);
d62a17ae 3672 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3673
3674 if (CHECK_FLAG(peer->af_flags[afi][safi],
3675 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3676 return false;
d62a17ae 3677
3678 /* Convert AFI, SAFI to values for packet. */
3679 pkt_afi = afi_int2iana(afi);
3680 pkt_safi = safi_int2iana(safi);
3681 {
d7c0a89a 3682 uint8_t ndata[7];
d62a17ae 3683
3684 ndata[0] = (pkt_afi >> 8);
3685 ndata[1] = pkt_afi;
3686 ndata[2] = pkt_safi;
3687 ndata[3] = (peer->pmax[afi][safi] >> 24);
3688 ndata[4] = (peer->pmax[afi][safi] >> 16);
3689 ndata[5] = (peer->pmax[afi][safi] >> 8);
3690 ndata[6] = (peer->pmax[afi][safi]);
3691
3692 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3693 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3694 BGP_NOTIFY_CEASE_MAX_PREFIX,
3695 ndata, 7);
3696 }
3697
3698 /* Dynamic peers will just close their connection. */
3699 if (peer_dynamic_neighbor(peer))
3dc339cd 3700 return true;
d62a17ae 3701
3702 /* restart timer start */
3703 if (peer->pmax_restart[afi][safi]) {
3704 peer->v_pmax_restart =
3705 peer->pmax_restart[afi][safi] * 60;
3706
3707 if (bgp_debug_neighbor_events(peer))
3708 zlog_debug(
f70c91dc
DA
3709 "%pBP Maximum-prefix restart timer started for %d secs",
3710 peer, peer->v_pmax_restart);
d62a17ae 3711
3712 BGP_TIMER_ON(peer->t_pmax_restart,
3713 bgp_maximum_prefix_restart_timer,
3714 peer->v_pmax_restart);
3715 }
3716
3dc339cd 3717 return true;
d62a17ae 3718 } else
3719 UNSET_FLAG(peer->af_sflags[afi][safi],
3720 PEER_STATUS_PREFIX_LIMIT);
3721
b1823b69
DS
3722 if (pcount
3723 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3724 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3725 PEER_STATUS_PREFIX_THRESHOLD)
3726 && !always)
3dc339cd 3727 return false;
d62a17ae 3728
3729 zlog_info(
f70c91dc
DA
3730 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3731 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3732 peer->pmax[afi][safi]);
d62a17ae 3733 SET_FLAG(peer->af_sflags[afi][safi],
3734 PEER_STATUS_PREFIX_THRESHOLD);
3735 } else
3736 UNSET_FLAG(peer->af_sflags[afi][safi],
3737 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3738 return false;
718e3744 3739}
3740
b40d939b 3741/* Unconditionally remove the route from the RIB, without taking
3742 * damping into consideration (eg, because the session went down)
3743 */
9bcb3eef 3744void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3745 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3746{
f009ff26 3747
3748 struct bgp *bgp = NULL;
3749 bool delete_route = false;
3750
9bcb3eef
DS
3751 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3752 safi);
d62a17ae 3753
f009ff26 3754 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3755 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3756
f009ff26 3757 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3758 * flag
3759 */
3760 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3761 delete_route = true;
9bcb3eef 3762 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3763 delete_route = true;
f009ff26 3764 if (delete_route) {
9bcb3eef
DS
3765 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3766 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3767 bgp = pi->peer->bgp;
26742171 3768 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3769 }
3770 }
3771 }
4a11bf2c 3772
9bcb3eef
DS
3773 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3774 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3775}
3776
9bcb3eef 3777static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3778 struct peer *peer, afi_t afi, safi_t safi,
3779 struct prefix_rd *prd)
3780{
9bcb3eef 3781 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3782
d62a17ae 3783 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3784 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3785 */
b4f7f45b
IR
3786 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3787 && peer->sort == BGP_PEER_EBGP)
3788 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3789 == BGP_DAMP_SUPPRESSED) {
3790 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3791 safi);
3792 return;
d62a17ae 3793 }
3794
49e5a4a0 3795#ifdef ENABLE_BGP_VNC
d62a17ae 3796 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3797 struct bgp_dest *pdest = NULL;
d62a17ae 3798 struct bgp_table *table = NULL;
3799
9bcb3eef
DS
3800 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3801 (struct prefix *)prd);
3802 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3803 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3804
3805 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3806 peer->bgp, prd, table, p, pi);
d62a17ae 3807 }
9bcb3eef 3808 bgp_dest_unlock_node(pdest);
d62a17ae 3809 }
3810 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3811 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3812
b54892e0
DS
3813 vnc_import_bgp_del_route(peer->bgp, p, pi);
3814 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3815 }
65efcfce 3816 }
d62a17ae 3817#endif
128ea8ab 3818
d62a17ae 3819 /* If this is an EVPN route, process for un-import. */
3820 if (safi == SAFI_EVPN)
b54892e0 3821 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3822
9bcb3eef 3823 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3824}
3825
4b7e6066
DS
3826struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3827 struct peer *peer, struct attr *attr,
9bcb3eef 3828 struct bgp_dest *dest)
fb018d25 3829{
4b7e6066 3830 struct bgp_path_info *new;
fb018d25 3831
d62a17ae 3832 /* Make new BGP info. */
4b7e6066 3833 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3834 new->type = type;
3835 new->instance = instance;
3836 new->sub_type = sub_type;
3837 new->peer = peer;
3838 new->attr = attr;
083ec940 3839 new->uptime = monotime(NULL);
9bcb3eef 3840 new->net = dest;
d62a17ae 3841 return new;
fb018d25
DS
3842}
3843
c265ee22 3844/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3845bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3846 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3847 struct bgp_dest *dest)
d62a17ae 3848{
2dbe3fa9 3849 bool ret = false;
b099a5c8
DA
3850 bool is_bgp_static_route =
3851 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3852 : false;
d62a17ae 3853
e8442016
DS
3854 /*
3855 * Only validated for unicast and multicast currently.
3856 * Also valid for EVPN where the nexthop is an IP address.
3857 * If we are a bgp static route being checked then there is
3858 * no need to check to see if the nexthop is martian as
3859 * that it should be ok.
3860 */
3861 if (is_bgp_static_route ||
3862 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3863 return false;
d62a17ae 3864
3865 /* If NEXT_HOP is present, validate it. */
3866 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3867 if (attr->nexthop.s_addr == INADDR_ANY ||
3868 !ipv4_unicast_valid(&attr->nexthop) ||
3869 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3870 return true;
d62a17ae 3871 }
c265ee22 3872
d62a17ae 3873 /* If MP_NEXTHOP is present, validate it. */
3874 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3875 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3876 * it is not an IPv6 link-local address.
0355b41d
DA
3877 *
3878 * If we receive an UPDATE with nexthop length set to 32 bytes
3879 * we shouldn't discard an UPDATE if it's set to (::).
3880 * The link-local (2st) is validated along the code path later.
d62a17ae 3881 */
3882 if (attr->mp_nexthop_len) {
3883 switch (attr->mp_nexthop_len) {
3884 case BGP_ATTR_NHLEN_IPV4:
3885 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3886 ret = (attr->mp_nexthop_global_in.s_addr ==
3887 INADDR_ANY ||
3888 !ipv4_unicast_valid(
3889 &attr->mp_nexthop_global_in) ||
3890 bgp_nexthop_self(bgp, afi, type, stype, attr,
3891 dest));
d62a17ae 3892 break;
3893
3894 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3895 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3896 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3897 &attr->mp_nexthop_global)
d62a17ae 3898 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3899 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3900 &attr->mp_nexthop_global)
3901 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3902 dest));
d62a17ae 3903 break;
0355b41d
DA
3904 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3905 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3906 || IN6_IS_ADDR_MULTICAST(
3907 &attr->mp_nexthop_global)
3908 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3909 dest));
0355b41d 3910 break;
d62a17ae 3911
3912 default:
3dc339cd 3913 ret = true;
d62a17ae 3914 break;
3915 }
3916 }
c265ee22 3917
d62a17ae 3918 return ret;
3919}
3920
aade37d7 3921static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3922{
3923 struct community *old;
3924 struct community *new;
3925 struct community *merge;
aade37d7 3926 struct community *no_export;
2721dd61 3927
9a706b42 3928 old = bgp_attr_get_community(attr);
aade37d7 3929 no_export = community_str2com("no-export");
2721dd61 3930
b4efa101
DA
3931 assert(no_export);
3932
2721dd61 3933 if (old) {
aade37d7 3934 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3935
3936 if (!old->refcnt)
3937 community_free(&old);
3938
3939 new = community_uniq_sort(merge);
3940 community_free(&merge);
3941 } else {
aade37d7 3942 new = community_dup(no_export);
2721dd61
DA
3943 }
3944
aade37d7 3945 community_free(&no_export);
2721dd61 3946
9a706b42 3947 bgp_attr_set_community(attr, new);
2721dd61
DA
3948}
3949
46dbf9d0
DA
3950static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3951 struct attr *attr, const struct prefix *prefix,
3952 int *sub_type)
3953{
3954 struct listnode *node, *nnode;
3955 struct bgp *bgp;
3956 bool accept_own_found = false;
3957
3958 if (safi != SAFI_MPLS_VPN)
3959 return false;
3960
3961 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3962 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3963 return false;
3964
3965 /* The route in question carries the ACCEPT_OWN community */
3966 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3967 struct community *comm = bgp_attr_get_community(attr);
3968
3969 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3970 accept_own_found = true;
3971 }
3972
3973 /* The route in question is targeted to one or more destination VRFs
3974 * on the router (as determined by inspecting the Route Target(s)).
3975 */
3976 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3977 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3978 continue;
3979
3980 if (accept_own_found &&
3981 ecommunity_include(
3982 bgp->vpn_policy[afi]
3983 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3984 bgp_attr_get_ecommunity(attr))) {
3985 if (bgp_debug_update(peer, prefix, NULL, 1))
3986 zlog_debug(
3987 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3988 peer, prefix);
3989
3990 /* Treat this route as imported, because it's leaked
3991 * already from another VRF, and we got an updated
3992 * version from route-reflector with ACCEPT_OWN
3993 * community.
3994 */
3995 *sub_type = BGP_ROUTE_IMPORTED;
3996
3997 return true;
3998 }
3999 }
4000
4001 return false;
4002}
4003
5a1ae2c2 4004int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4005 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4006 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4007 uint32_t num_labels, int soft_reconfig,
a4d82a8a 4008 struct bgp_route_evpn *evpn)
d62a17ae 4009{
4010 int ret;
4011 int aspath_loop_count = 0;
9bcb3eef 4012 struct bgp_dest *dest;
d62a17ae 4013 struct bgp *bgp;
4014 struct attr new_attr;
4015 struct attr *attr_new;
40381db7 4016 struct bgp_path_info *pi;
4b7e6066
DS
4017 struct bgp_path_info *new;
4018 struct bgp_path_info_extra *extra;
d62a17ae 4019 const char *reason;
4020 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4021 int connected = 0;
4022 int do_loop_check = 1;
4023 int has_valid_label = 0;
7c312383 4024 afi_t nh_afi;
9146341f 4025 bool force_evpn_import = false;
907707db 4026 safi_t orig_safi = safi;
a486300b 4027 bool leak_success = true;
b2ac1d0d 4028 int allowas_in = 0;
949b0f24 4029
c7bb4f00 4030 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4031 char pfxprint[PREFIX2STR_BUFFER];
4032
4033 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4034 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4035 afi, safi, attr);
6401252f
QY
4036 }
4037
49e5a4a0 4038#ifdef ENABLE_BGP_VNC
d62a17ae 4039 int vnc_implicit_withdraw = 0;
65efcfce 4040#endif
d62a17ae 4041 int same_attr = 0;
f8745525 4042 const struct prefix *bgp_nht_param_prefix;
718e3744 4043
907707db
MS
4044 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4045 if (orig_safi == SAFI_LABELED_UNICAST)
4046 safi = SAFI_UNICAST;
4047
6006b807 4048 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4049 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4050 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4051
d62a17ae 4052 bgp = peer->bgp;
9bcb3eef 4053 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4054 /* TODO: Check to see if we can get rid of "is_valid_label" */
4055 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4056 has_valid_label = (num_labels > 0) ? 1 : 0;
4057 else
4058 has_valid_label = bgp_is_valid_label(label);
718e3744 4059
28f66de2
MS
4060 if (has_valid_label)
4061 assert(label != NULL);
4062
66ff6089
AD
4063 /* Update overlay index of the attribute */
4064 if (afi == AFI_L2VPN && evpn)
4065 memcpy(&attr->evpn_overlay, evpn,
4066 sizeof(struct bgp_route_evpn));
4067
d62a17ae 4068 /* When peer's soft reconfiguration enabled. Record input packet in
4069 Adj-RIBs-In. */
4070 if (!soft_reconfig
4071 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4072 && peer != bgp->peer_self)
9bcb3eef 4073 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4074
b2ac1d0d
MS
4075 /* Update permitted loop count */
4076 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4077 allowas_in = peer->allowas_in[afi][safi];
4078
d62a17ae 4079 /* Check previously received route. */
9bcb3eef 4080 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4081 if (pi->peer == peer && pi->type == type
4082 && pi->sub_type == sub_type
4083 && pi->addpath_rx_id == addpath_id)
d62a17ae 4084 break;
4085
4086 /* AS path local-as loop check. */
4087 if (peer->change_local_as) {
b2ac1d0d
MS
4088 if (allowas_in)
4089 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4090 else if (!CHECK_FLAG(peer->flags,
4091 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4092 aspath_loop_count = 1;
4093
4094 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4095 > aspath_loop_count) {
b4d46cc9 4096 peer->stat_pfx_aspath_loop++;
692174a1 4097 reason = "as-path contains our own AS;";
d62a17ae 4098 goto filtered;
4099 }
718e3744 4100 }
718e3744 4101
d62a17ae 4102 /* If the peer is configured for "allowas-in origin" and the last ASN in
4103 * the
4104 * as-path is our ASN then we do not need to call aspath_loop_check
4105 */
4106 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4107 if (aspath_get_last_as(attr->aspath) == bgp->as)
4108 do_loop_check = 0;
4109
f8745525
PG
4110 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4111 bgp_nht_param_prefix = NULL;
4112 else
4113 bgp_nht_param_prefix = p;
4114
d62a17ae 4115 /* AS path loop check. */
4116 if (do_loop_check) {
b2ac1d0d
MS
4117 if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
4118 (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
4119 (aspath_loop_check(attr->aspath, bgp->confed_id) >
4120 allowas_in))) {
b4d46cc9 4121 peer->stat_pfx_aspath_loop++;
d62a17ae 4122 reason = "as-path contains our own AS;";
4123 goto filtered;
4124 }
4125 }
aac9ef6c 4126
46dbf9d0
DA
4127 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4128 * enabled, then take care of that too.
4129 */
4130 bool accept_own = false;
4131
d62a17ae 4132 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4133 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4134 accept_own =
4135 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4136 if (!accept_own) {
4137 peer->stat_pfx_originator_loop++;
4138 reason = "originator is us;";
4139 goto filtered;
4140 }
d62a17ae 4141 }
718e3744 4142
d62a17ae 4143 /* Route reflector cluster ID check. */
4144 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4145 peer->stat_pfx_cluster_loop++;
d62a17ae 4146 reason = "reflected from the same cluster;";
4147 goto filtered;
4148 }
718e3744 4149
d62a17ae 4150 /* Apply incoming filter. */
907707db 4151 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4152 peer->stat_pfx_filter++;
d62a17ae 4153 reason = "filter;";
4154 goto filtered;
4155 }
718e3744 4156
a8b72dc6
DA
4157 /* RFC 8212 to prevent route leaks.
4158 * This specification intends to improve this situation by requiring the
4159 * explicit configuration of both BGP Import and Export Policies for any
4160 * External BGP (EBGP) session such as customers, peers, or
4161 * confederation boundaries for all enabled address families. Through
4162 * codification of the aforementioned requirement, operators will
4163 * benefit from consistent behavior across different BGP
4164 * implementations.
4165 */
1d3fdccf 4166 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4167 if (!bgp_inbound_policy_exists(peer,
4168 &peer->filter[afi][safi])) {
4169 reason = "inbound policy missing";
b17826b7
DS
4170 if (monotime_since(&bgp->ebgprequirespolicywarning,
4171 NULL) > FIFTEENMINUTE2USEC ||
4172 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4173 zlog_warn(
4174 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4175 monotime(&bgp->ebgprequirespolicywarning);
4176 }
a8b72dc6
DA
4177 goto filtered;
4178 }
4179
fb29348a
DA
4180 /* draft-ietf-idr-deprecate-as-set-confed-set
4181 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4182 * Eventually, This document (if approved) updates RFC 4271
4183 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4184 * and obsoletes RFC 6472.
4185 */
7f972cd8 4186 if (peer->bgp->reject_as_sets)
fb29348a
DA
4187 if (aspath_check_as_sets(attr->aspath)) {
4188 reason =
4189 "as-path contains AS_SET or AS_CONFED_SET type;";
4190 goto filtered;
4191 }
4192
6f4f49b2 4193 new_attr = *attr;
d62a17ae 4194
4195 /* Apply incoming route-map.
4196 * NB: new_attr may now contain newly allocated values from route-map
4197 * "set"
4198 * commands, so we need bgp_attr_flush in the error paths, until we
4199 * intern
4200 * the attr (which takes over the memory references) */
907707db 4201 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4202 num_labels, dest)
4203 == RMAP_DENY) {
b4d46cc9 4204 peer->stat_pfx_filter++;
d62a17ae 4205 reason = "route-map;";
4206 bgp_attr_flush(&new_attr);
4207 goto filtered;
4208 }
718e3744 4209
05864da7 4210 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4211 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4212 /* remove from RIB previous entry */
4213 bgp_zebra_withdraw(p, pi, bgp, safi);
4214 }
4215
7f323236
DW
4216 if (peer->sort == BGP_PEER_EBGP) {
4217
2721dd61
DA
4218 /* rfc7999:
4219 * A BGP speaker receiving an announcement tagged with the
4220 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4221 * NO_EXPORT community as defined in RFC1997, or a
4222 * similar community, to prevent propagation of the
4223 * prefix outside the local AS. The community to prevent
4224 * propagation SHOULD be chosen according to the operator's
4225 * routing policy.
4226 */
9a706b42
DA
4227 if (bgp_attr_get_community(&new_attr) &&
4228 community_include(bgp_attr_get_community(&new_attr),
4229 COMMUNITY_BLACKHOLE))
aade37d7 4230 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4231
a4d82a8a
PZ
4232 /* If we receive the graceful-shutdown community from an eBGP
4233 * peer we must lower local-preference */
9a706b42
DA
4234 if (bgp_attr_get_community(&new_attr) &&
4235 community_include(bgp_attr_get_community(&new_attr),
4236 COMMUNITY_GSHUT)) {
7f323236
DW
4237 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4238 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4239
4f770cf1
DA
4240 /* If graceful-shutdown is configured globally or
4241 * per neighbor, then add the GSHUT community to
4242 * all paths received from eBGP peers. */
4243 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4244 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4245 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4246 }
4247
d62a17ae 4248 /* next hop check. */
860ad3f9
DS
4249 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4250 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4251 &new_attr, dest)) {
b4d46cc9 4252 peer->stat_pfx_nh_invalid++;
d62a17ae 4253 reason = "martian or self next-hop;";
4254 bgp_attr_flush(&new_attr);
4255 goto filtered;
4256 }
718e3744 4257
5c14a191 4258 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4259 peer->stat_pfx_nh_invalid++;
4e802e66 4260 reason = "self mac;";
4dbf2038 4261 bgp_attr_flush(&new_attr);
4e802e66
DS
4262 goto filtered;
4263 }
4264
5a78f2bc
EB
4265 if (bgp_check_role_applicability(afi, safi) &&
4266 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4267 reason = "failing otc validation";
4268 bgp_attr_flush(&new_attr);
4269 goto filtered;
4270 }
a1b773e2
DS
4271 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4272 * condition :
4273 * Suppress fib is enabled
4274 * BGP_OPT_NO_FIB is not enabled
4275 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4276 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4277 */
4278 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4279 && (sub_type == BGP_ROUTE_NORMAL)
4280 && (!bgp_option_check(BGP_OPT_NO_FIB))
4281 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4282 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4283
01da2d26
DA
4284 /* If neighbor soo is configured, tag all incoming routes with
4285 * this SoO tag and then filter out advertisements in
4286 * subgroup_announce_check() if it matches the configured SoO
4287 * on the other peer.
4288 */
4289 if (peer->soo[afi][safi]) {
4290 struct ecommunity *old_ecomm =
4291 bgp_attr_get_ecommunity(&new_attr);
4292 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4293 struct ecommunity *new_ecomm;
4294
4295 if (old_ecomm) {
4296 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4297 ecomm_soo);
4298
4299 if (!old_ecomm->refcnt)
4300 ecommunity_free(&old_ecomm);
4301 } else {
4302 new_ecomm = ecommunity_dup(ecomm_soo);
4303 }
4304
4305 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4306 }
4307
4dbf2038 4308 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4309
d62a17ae 4310 /* If the update is implicit withdraw. */
40381db7 4311 if (pi) {
083ec940 4312 pi->uptime = monotime(NULL);
40381db7 4313 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4314
9bcb3eef 4315 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4316
d62a17ae 4317 /* Same attribute comes in. */
40381db7 4318 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4319 && same_attr
d62a17ae 4320 && (!has_valid_label
40381db7 4321 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4322 num_labels * sizeof(mpls_label_t))
66ff6089 4323 == 0)) {
b4f7f45b
IR
4324 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4325 BGP_CONFIG_DAMPENING)
d62a17ae 4326 && peer->sort == BGP_PEER_EBGP
40381db7 4327 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4328 if (bgp_debug_update(peer, p, NULL, 1)) {
4329 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4330 afi, safi, prd, p, label,
4331 num_labels, addpath_id ? 1 : 0,
66ff6089 4332 addpath_id, evpn, pfx_buf,
a4d82a8a 4333 sizeof(pfx_buf));
f70c91dc 4334 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4335 pfx_buf);
4336 }
4337
9bcb3eef 4338 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4339 != BGP_DAMP_SUPPRESSED) {
40381db7 4340 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4341 safi);
9bcb3eef 4342 bgp_process(bgp, dest, afi, safi);
d62a17ae 4343 }
4344 } else /* Duplicate - odd */
4345 {
4346 if (bgp_debug_update(peer, p, NULL, 1)) {
4347 if (!peer->rcvd_attr_printed) {
4348 zlog_debug(
f70c91dc
DA
4349 "%pBP rcvd UPDATE w/ attr: %s",
4350 peer,
d62a17ae 4351 peer->rcvd_attr_str);
4352 peer->rcvd_attr_printed = 1;
4353 }
4354
4355 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4356 afi, safi, prd, p, label,
4357 num_labels, addpath_id ? 1 : 0,
66ff6089 4358 addpath_id, evpn, pfx_buf,
a4d82a8a 4359 sizeof(pfx_buf));
d62a17ae 4360 zlog_debug(
f70c91dc
DA
4361 "%pBP rcvd %s...duplicate ignored",
4362 peer, pfx_buf);
d62a17ae 4363 }
4364
4365 /* graceful restart STALE flag unset. */
40381db7 4366 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4367 bgp_path_info_unset_flag(
9bcb3eef
DS
4368 dest, pi, BGP_PATH_STALE);
4369 bgp_dest_set_defer_flag(dest, false);
4370 bgp_process(bgp, dest, afi, safi);
d62a17ae 4371 }
4372 }
4373
9bcb3eef 4374 bgp_dest_unlock_node(dest);
d62a17ae 4375 bgp_attr_unintern(&attr_new);
4376
4377 return 0;
4378 }
718e3744 4379
d62a17ae 4380 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4381 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4382 if (bgp_debug_update(peer, p, NULL, 1)) {
4383 bgp_debug_rdpfxpath2str(
a4d82a8a 4384 afi, safi, prd, p, label, num_labels,
66ff6089 4385 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4386 pfx_buf, sizeof(pfx_buf));
d62a17ae 4387 zlog_debug(
f70c91dc
DA
4388 "%pBP rcvd %s, flapped quicker than processing",
4389 peer, pfx_buf);
d62a17ae 4390 }
4391
9bcb3eef 4392 bgp_path_info_restore(dest, pi);
9146341f 4393
4394 /*
4395 * If the BGP_PATH_REMOVED flag is set, then EVPN
4396 * routes would have been unimported already when a
4397 * prior BGP withdraw processing happened. Such routes
4398 * need to be imported again, so flag accordingly.
4399 */
4400 force_evpn_import = true;
d62a17ae 4401 }
718e3744 4402
d62a17ae 4403 /* Received Logging. */
4404 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4405 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4406 num_labels, addpath_id ? 1 : 0,
66ff6089 4407 addpath_id, evpn, pfx_buf,
a4d82a8a 4408 sizeof(pfx_buf));
f70c91dc 4409 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4410 }
718e3744 4411
d62a17ae 4412 /* graceful restart STALE flag unset. */
f009ff26 4413 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4414 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4415 bgp_dest_set_defer_flag(dest, false);
f009ff26 4416 }
d62a17ae 4417
4418 /* The attribute is changed. */
9bcb3eef 4419 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4420
4421 /* implicit withdraw, decrement aggregate and pcount here.
4422 * only if update is accepted, they'll increment below.
4423 */
40381db7 4424 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4425
4426 /* Update bgp route dampening information. */
b4f7f45b 4427 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4428 && peer->sort == BGP_PEER_EBGP) {
4429 /* This is implicit withdraw so we should update
b4f7f45b
IR
4430 dampening
4431 information. */
40381db7 4432 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4433 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4434 }
49e5a4a0 4435#ifdef ENABLE_BGP_VNC
d62a17ae 4436 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4437 struct bgp_dest *pdest = NULL;
d62a17ae 4438 struct bgp_table *table = NULL;
4439
9bcb3eef
DS
4440 pdest = bgp_node_get(bgp->rib[afi][safi],
4441 (struct prefix *)prd);
4442 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4443 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4444
4445 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4446 bgp, prd, table, p, pi);
d62a17ae 4447 }
9bcb3eef 4448 bgp_dest_unlock_node(pdest);
d62a17ae 4449 }
4450 if ((afi == AFI_IP || afi == AFI_IP6)
4451 && (safi == SAFI_UNICAST)) {
40381db7 4452 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4453 /*
4454 * Implicit withdraw case.
4455 */
4456 ++vnc_implicit_withdraw;
40381db7
DS
4457 vnc_import_bgp_del_route(bgp, p, pi);
4458 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4459 }
4460 }
65efcfce 4461#endif
128ea8ab 4462
d62a17ae 4463 /* Special handling for EVPN update of an existing route. If the
4464 * extended community attribute has changed, we need to
4465 * un-import
4466 * the route using its existing extended community. It will be
4467 * subsequently processed for import with the new extended
4468 * community.
4469 */
6f8c9c11
PR
4470 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4471 && !same_attr) {
40381db7 4472 if ((pi->attr->flag
d62a17ae 4473 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4474 && (attr_new->flag
4475 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4476 int cmp;
4477
b53e67a3
DA
4478 cmp = ecommunity_cmp(
4479 bgp_attr_get_ecommunity(pi->attr),
4480 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4481 if (!cmp) {
4482 if (bgp_debug_update(peer, p, NULL, 1))
4483 zlog_debug(
4484 "Change in EXT-COMM, existing %s new %s",
4485 ecommunity_str(
b53e67a3
DA
4486 bgp_attr_get_ecommunity(
4487 pi->attr)),
d62a17ae 4488 ecommunity_str(
b53e67a3
DA
4489 bgp_attr_get_ecommunity(
4490 attr_new)));
6f8c9c11
PR
4491 if (safi == SAFI_EVPN)
4492 bgp_evpn_unimport_route(
4493 bgp, afi, safi, p, pi);
4494 else /* SAFI_MPLS_VPN */
4495 vpn_leak_to_vrf_withdraw(bgp,
4496 pi);
d62a17ae 4497 }
4498 }
4499 }
718e3744 4500
d62a17ae 4501 /* Update to new attribute. */
40381db7
DS
4502 bgp_attr_unintern(&pi->attr);
4503 pi->attr = attr_new;
d62a17ae 4504
4505 /* Update MPLS label */
4506 if (has_valid_label) {
40381db7 4507 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4508 if (extra->label != label) {
4509 memcpy(&extra->label, label,
dbd587da 4510 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4511 extra->num_labels = num_labels;
4512 }
b57ba6d2
MK
4513 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4514 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4515 }
718e3744 4516
e496b420
HS
4517 /* Update SRv6 SID */
4518 if (attr->srv6_l3vpn) {
4519 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4520 if (sid_diff(&extra->sid[0].sid,
4521 &attr->srv6_l3vpn->sid)) {
4522 sid_copy(&extra->sid[0].sid,
e496b420
HS
4523 &attr->srv6_l3vpn->sid);
4524 extra->num_sids = 1;
cc8f05df 4525
16f3db2d
RS
4526 extra->sid[0].loc_block_len = 0;
4527 extra->sid[0].loc_node_len = 0;
4528 extra->sid[0].func_len = 0;
4529 extra->sid[0].arg_len = 0;
ea7cd161
RS
4530 extra->sid[0].transposition_len = 0;
4531 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4532
4533 if (attr->srv6_l3vpn->loc_block_len != 0) {
4534 extra->sid[0].loc_block_len =
4535 attr->srv6_l3vpn->loc_block_len;
4536 extra->sid[0].loc_node_len =
4537 attr->srv6_l3vpn->loc_node_len;
4538 extra->sid[0].func_len =
4539 attr->srv6_l3vpn->func_len;
4540 extra->sid[0].arg_len =
4541 attr->srv6_l3vpn->arg_len;
ea7cd161 4542 extra->sid[0].transposition_len =
cc8f05df 4543 attr->srv6_l3vpn
ea7cd161
RS
4544 ->transposition_len;
4545 extra->sid[0].transposition_offset =
cc8f05df 4546 attr->srv6_l3vpn
ea7cd161
RS
4547 ->transposition_offset;
4548 }
e496b420
HS
4549 }
4550 } else if (attr->srv6_vpn) {
4551 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4552 if (sid_diff(&extra->sid[0].sid,
4553 &attr->srv6_vpn->sid)) {
4554 sid_copy(&extra->sid[0].sid,
4555 &attr->srv6_vpn->sid);
e496b420
HS
4556 extra->num_sids = 1;
4557 }
4558 }
4559
49e5a4a0 4560#ifdef ENABLE_BGP_VNC
d62a17ae 4561 if ((afi == AFI_IP || afi == AFI_IP6)
4562 && (safi == SAFI_UNICAST)) {
4563 if (vnc_implicit_withdraw) {
4564 /*
4565 * Add back the route with its new attributes
4566 * (e.g., nexthop).
4567 * The route is still selected, until the route
4568 * selection
4569 * queued by bgp_process actually runs. We have
4570 * to make this
4571 * update to the VNC side immediately to avoid
4572 * racing against
4573 * configuration changes (e.g., route-map
4574 * changes) which
4575 * trigger re-importation of the entire RIB.
4576 */
40381db7
DS
4577 vnc_import_bgp_add_route(bgp, p, pi);
4578 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4579 }
4580 }
65efcfce
LB
4581#endif
4582
d62a17ae 4583 /* Update bgp route dampening information. */
b4f7f45b 4584 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4585 && peer->sort == BGP_PEER_EBGP) {
4586 /* Now we do normal update dampening. */
9bcb3eef 4587 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4588 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4589 bgp_dest_unlock_node(dest);
d62a17ae 4590 return 0;
4591 }
4592 }
128ea8ab 4593
d62a17ae 4594 /* Nexthop reachability check - for unicast and
4595 * labeled-unicast.. */
7c312383
AD
4596 if (((afi == AFI_IP || afi == AFI_IP6)
4597 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4598 || (safi == SAFI_EVPN &&
4599 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4600 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4601 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4602 && !CHECK_FLAG(peer->flags,
4603 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4604 && !CHECK_FLAG(bgp->flags,
4605 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4606 connected = 1;
4607 else
4608 connected = 0;
4609
960035b2
PZ
4610 struct bgp *bgp_nexthop = bgp;
4611
40381db7
DS
4612 if (pi->extra && pi->extra->bgp_orig)
4613 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4614
7c312383
AD
4615 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4616
4617 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4618 safi, pi, NULL, connected,
f8745525
PG
4619 bgp_nht_param_prefix) ||
4620 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4621 bgp_path_info_set_flag(dest, pi,
4622 BGP_PATH_VALID);
d62a17ae 4623 else {
4624 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4625 zlog_debug("%s(%pI4): NH unresolved",
4626 __func__,
4627 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4628 }
9bcb3eef 4629 bgp_path_info_unset_flag(dest, pi,
18ee8310 4630 BGP_PATH_VALID);
d62a17ae 4631 }
46dbf9d0
DA
4632 } else {
4633 if (accept_own)
4634 bgp_path_info_set_flag(dest, pi,
4635 BGP_PATH_ACCEPT_OWN);
4636
9bcb3eef 4637 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4638 }
d62a17ae 4639
49e5a4a0 4640#ifdef ENABLE_BGP_VNC
d62a17ae 4641 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4642 struct bgp_dest *pdest = NULL;
d62a17ae 4643 struct bgp_table *table = NULL;
4644
9bcb3eef
DS
4645 pdest = bgp_node_get(bgp->rib[afi][safi],
4646 (struct prefix *)prd);
4647 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4648 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4649
4650 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4651 bgp, prd, table, p, pi);
d62a17ae 4652 }
9bcb3eef 4653 bgp_dest_unlock_node(pdest);
d62a17ae 4654 }
4655#endif
718e3744 4656
d62a17ae 4657 /* If this is an EVPN route and some attribute has changed,
9146341f 4658 * or we are explicitly told to perform a route import, process
d62a17ae 4659 * route for import. If the extended community has changed, we
4660 * would
4661 * have done the un-import earlier and the import would result
4662 * in the
4663 * route getting injected into appropriate L2 VNIs. If it is
4664 * just
4665 * some other attribute change, the import will result in
4666 * updating
4667 * the attributes for the route in the VNI(s).
4668 */
9146341f 4669 if (safi == SAFI_EVPN &&
4670 (!same_attr || force_evpn_import) &&
7c312383 4671 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4672 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4673
4674 /* Process change. */
40381db7 4675 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4676
9bcb3eef
DS
4677 bgp_process(bgp, dest, afi, safi);
4678 bgp_dest_unlock_node(dest);
558d1fec 4679
ddb5b488
PZ
4680 if (SAFI_UNICAST == safi
4681 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4682 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4683
40381db7 4684 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4685 }
4686 if ((SAFI_MPLS_VPN == safi)
4687 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4688 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4689 }
4690
49e5a4a0 4691#ifdef ENABLE_BGP_VNC
d62a17ae 4692 if (SAFI_MPLS_VPN == safi) {
4693 mpls_label_t label_decoded = decode_label(label);
28070ee3 4694
d62a17ae 4695 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4696 type, sub_type, &label_decoded);
4697 }
4698 if (SAFI_ENCAP == safi) {
4699 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4700 type, sub_type, NULL);
4701 }
28070ee3 4702#endif
a486300b
PG
4703 if ((safi == SAFI_MPLS_VPN) &&
4704 !CHECK_FLAG(bgp->af_flags[afi][safi],
4705 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4706 !leak_success) {
4707 bgp_unlink_nexthop(pi);
4708 bgp_path_info_delete(dest, pi);
4709 }
d62a17ae 4710 return 0;
4711 } // End of implicit withdraw
718e3744 4712
d62a17ae 4713 /* Received Logging. */
4714 if (bgp_debug_update(peer, p, NULL, 1)) {
4715 if (!peer->rcvd_attr_printed) {
f70c91dc 4716 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4717 peer->rcvd_attr_str);
4718 peer->rcvd_attr_printed = 1;
4719 }
718e3744 4720
a4d82a8a 4721 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4722 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4723 pfx_buf, sizeof(pfx_buf));
f70c91dc 4724 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4725 }
718e3744 4726
d62a17ae 4727 /* Make new BGP info. */
9bcb3eef 4728 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4729
d62a17ae 4730 /* Update MPLS label */
4731 if (has_valid_label) {
18ee8310 4732 extra = bgp_path_info_extra_get(new);
8ba71050 4733 if (extra->label != label) {
dbd587da
QY
4734 memcpy(&extra->label, label,
4735 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4736 extra->num_labels = num_labels;
4737 }
b57ba6d2
MK
4738 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4739 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4740 }
718e3744 4741
e496b420
HS
4742 /* Update SRv6 SID */
4743 if (safi == SAFI_MPLS_VPN) {
4744 extra = bgp_path_info_extra_get(new);
4745 if (attr->srv6_l3vpn) {
16f3db2d 4746 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4747 extra->num_sids = 1;
cc8f05df 4748
16f3db2d
RS
4749 extra->sid[0].loc_block_len =
4750 attr->srv6_l3vpn->loc_block_len;
4751 extra->sid[0].loc_node_len =
4752 attr->srv6_l3vpn->loc_node_len;
4753 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4754 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4755 extra->sid[0].transposition_len =
4756 attr->srv6_l3vpn->transposition_len;
4757 extra->sid[0].transposition_offset =
4758 attr->srv6_l3vpn->transposition_offset;
e496b420 4759 } else if (attr->srv6_vpn) {
16f3db2d 4760 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4761 extra->num_sids = 1;
4762 }
4763 }
4764
d62a17ae 4765 /* Nexthop reachability check. */
7c312383
AD
4766 if (((afi == AFI_IP || afi == AFI_IP6)
4767 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4768 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4769 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4770 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4771 && !CHECK_FLAG(peer->flags,
4772 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4773 && !CHECK_FLAG(bgp->flags,
4774 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4775 connected = 1;
4776 else
4777 connected = 0;
4778
7c312383
AD
4779 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4780
4053e952 4781 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4782 connected, bgp_nht_param_prefix) ||
4783 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4784 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4785 else {
07380148
DA
4786 if (BGP_DEBUG(nht, NHT))
4787 zlog_debug("%s(%pI4): NH unresolved", __func__,
4788 &attr_new->nexthop);
9bcb3eef 4789 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4790 }
46dbf9d0
DA
4791 } else {
4792 if (accept_own)
4793 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4794
9bcb3eef 4795 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4796 }
a82478b9 4797
b381ed97
DA
4798 /* If maximum prefix count is configured and current prefix
4799 * count exeed it.
4800 */
4801 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4802 reason = "maximum-prefix overflow";
4803 bgp_attr_flush(&new_attr);
4804 bgp_unlink_nexthop(new);
4805 bgp_path_info_delete(dest, new);
4806 goto filtered;
4807 }
4808
d62a17ae 4809 /* Addpath ID */
4810 new->addpath_rx_id = addpath_id;
4811
4812 /* Increment prefix */
4813 bgp_aggregate_increment(bgp, p, new, afi, safi);
4814
4815 /* Register new BGP information. */
9bcb3eef 4816 bgp_path_info_add(dest, new);
d62a17ae 4817
4818 /* route_node_get lock */
9bcb3eef 4819 bgp_dest_unlock_node(dest);
558d1fec 4820
49e5a4a0 4821#ifdef ENABLE_BGP_VNC
d62a17ae 4822 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4823 struct bgp_dest *pdest = NULL;
d62a17ae 4824 struct bgp_table *table = NULL;
4825
9bcb3eef
DS
4826 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4827 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4828 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4829
4830 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4831 bgp, prd, table, p, new);
4832 }
9bcb3eef 4833 bgp_dest_unlock_node(pdest);
d62a17ae 4834 }
65efcfce
LB
4835#endif
4836
d62a17ae 4837 /* If this is an EVPN route, process for import. */
7c312383 4838 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4839 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4840
9bcb3eef 4841 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4842
d62a17ae 4843 /* Process change. */
9bcb3eef 4844 bgp_process(bgp, dest, afi, safi);
718e3744 4845
ddb5b488
PZ
4846 if (SAFI_UNICAST == safi
4847 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4848 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4849 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4850 }
4851 if ((SAFI_MPLS_VPN == safi)
4852 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4853 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4854 }
49e5a4a0 4855#ifdef ENABLE_BGP_VNC
d62a17ae 4856 if (SAFI_MPLS_VPN == safi) {
4857 mpls_label_t label_decoded = decode_label(label);
28070ee3 4858
d62a17ae 4859 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4860 sub_type, &label_decoded);
4861 }
4862 if (SAFI_ENCAP == safi) {
4863 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4864 sub_type, NULL);
4865 }
28070ee3 4866#endif
a486300b
PG
4867 if ((safi == SAFI_MPLS_VPN) &&
4868 !CHECK_FLAG(bgp->af_flags[afi][safi],
4869 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4870 !leak_success) {
4871 bgp_unlink_nexthop(new);
4872 bgp_path_info_delete(dest, new);
4873 }
28070ee3 4874
d62a17ae 4875 return 0;
718e3744 4876
d62a17ae 4877/* This BGP update is filtered. Log the reason then update BGP
4878 entry. */
4879filtered:
9bcb3eef 4880 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4881
d62a17ae 4882 if (bgp_debug_update(peer, p, NULL, 1)) {
4883 if (!peer->rcvd_attr_printed) {
f70c91dc 4884 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4885 peer->rcvd_attr_str);
4886 peer->rcvd_attr_printed = 1;
4887 }
718e3744 4888
a4d82a8a 4889 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4890 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4891 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4892 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4893 peer, pfx_buf, reason);
d62a17ae 4894 }
128ea8ab 4895
40381db7 4896 if (pi) {
d62a17ae 4897 /* If this is an EVPN route, un-import it as it is now filtered.
4898 */
4899 if (safi == SAFI_EVPN)
40381db7 4900 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4901
ddb5b488
PZ
4902 if (SAFI_UNICAST == safi
4903 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4904 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4905
40381db7 4906 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4907 }
4908 if ((SAFI_MPLS_VPN == safi)
4909 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4910
40381db7 4911 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4912 }
4913
9bcb3eef 4914 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4915 }
4916
9bcb3eef 4917 bgp_dest_unlock_node(dest);
558d1fec 4918
49e5a4a0 4919#ifdef ENABLE_BGP_VNC
d62a17ae 4920 /*
4921 * Filtered update is treated as an implicit withdrawal (see
4922 * bgp_rib_remove()
4923 * a few lines above)
4924 */
4925 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4926 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4927 0);
4928 }
97736e32
PZ
4929#endif
4930
d62a17ae 4931 return 0;
718e3744 4932}
4933
26a3ffd6 4934int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4935 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4936 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4937 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4938{
d62a17ae 4939 struct bgp *bgp;
4940 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4941 struct bgp_dest *dest;
40381db7 4942 struct bgp_path_info *pi;
718e3744 4943
49e5a4a0 4944#ifdef ENABLE_BGP_VNC
d62a17ae 4945 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4946 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4947 0);
4948 }
28070ee3
PZ
4949#endif
4950
d62a17ae 4951 bgp = peer->bgp;
4952
4953 /* Lookup node. */
9bcb3eef 4954 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4955
4956 /* If peer is soft reconfiguration enabled. Record input packet for
4957 * further calculation.
4958 *
4959 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4960 * routes that are filtered. This tanks out Quagga RS pretty badly due
4961 * to
4962 * the iteration over all RS clients.
4963 * Since we need to remove the entry from adj_in anyway, do that first
4964 * and
4965 * if there was no entry, we don't need to do anything more.
4966 */
4967 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4968 && peer != bgp->peer_self)
9bcb3eef 4969 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4970 peer->stat_pfx_dup_withdraw++;
4971
d62a17ae 4972 if (bgp_debug_update(peer, p, NULL, 1)) {
4973 bgp_debug_rdpfxpath2str(
a4d82a8a 4974 afi, safi, prd, p, label, num_labels,
6c995628
AD
4975 addpath_id ? 1 : 0, addpath_id, NULL,
4976 pfx_buf, sizeof(pfx_buf));
d62a17ae 4977 zlog_debug(
4978 "%s withdrawing route %s not in adj-in",
4979 peer->host, pfx_buf);
4980 }
9bcb3eef 4981 bgp_dest_unlock_node(dest);
d62a17ae 4982 return 0;
4983 }
cd808e74 4984
d62a17ae 4985 /* Lookup withdrawn route. */
9bcb3eef 4986 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4987 if (pi->peer == peer && pi->type == type
4988 && pi->sub_type == sub_type
4989 && pi->addpath_rx_id == addpath_id)
d62a17ae 4990 break;
4991
4992 /* Logging. */
4993 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4994 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4995 addpath_id ? 1 : 0, addpath_id, NULL,
4996 pfx_buf, sizeof(pfx_buf));
f70c91dc 4997 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4998 pfx_buf);
4999 }
718e3744 5000
d62a17ae 5001 /* Withdraw specified route from routing table. */
40381db7 5002 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5003 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5004 if (SAFI_UNICAST == safi
5005 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5006 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5007 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5008 }
5009 if ((SAFI_MPLS_VPN == safi)
5010 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5011
40381db7 5012 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
5013 }
5014 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5015 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5016 addpath_id ? 1 : 0, addpath_id, NULL,
5017 pfx_buf, sizeof(pfx_buf));
d62a17ae 5018 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5019 }
718e3744 5020
d62a17ae 5021 /* Unlock bgp_node_get() lock. */
9bcb3eef 5022 bgp_dest_unlock_node(dest);
d62a17ae 5023
5024 return 0;
718e3744 5025}
6b0655a2 5026
d62a17ae 5027void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5028 int withdraw)
718e3744 5029{
d62a17ae 5030 struct update_subgroup *subgrp;
5031 subgrp = peer_subgroup(peer, afi, safi);
5032 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5033}
6182d65b 5034
718e3744 5035
3f9c7369
DS
5036/*
5037 * bgp_stop_announce_route_timer
5038 */
d62a17ae 5039void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5040{
d62a17ae 5041 if (!paf->t_announce_route)
5042 return;
5043
c3aaa89a 5044 THREAD_OFF(paf->t_announce_route);
718e3744 5045}
6b0655a2 5046
3f9c7369
DS
5047/*
5048 * bgp_announce_route_timer_expired
5049 *
5050 * Callback that is invoked when the route announcement timer for a
5051 * peer_af expires.
5052 */
cc9f21da 5053static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5054{
d62a17ae 5055 struct peer_af *paf;
5056 struct peer *peer;
558d1fec 5057
d62a17ae 5058 paf = THREAD_ARG(t);
5059 peer = paf->peer;
718e3744 5060
feb17238 5061 if (!peer_established(peer))
cc9f21da 5062 return;
3f9c7369 5063
d62a17ae 5064 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5065 return;
3f9c7369 5066
d62a17ae 5067 peer_af_announce_route(paf, 1);
c5aec50b
MK
5068
5069 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5070 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5071}
5072
3f9c7369
DS
5073/*
5074 * bgp_announce_route
5075 *
5076 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5077 *
5078 * if force is true we will force an update even if the update
5079 * limiting code is attempted to kick in.
3f9c7369 5080 */
e1a32ec1 5081void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5082{
5083 struct peer_af *paf;
5084 struct update_subgroup *subgrp;
5085
5086 paf = peer_af_find(peer, afi, safi);
5087 if (!paf)
5088 return;
5089 subgrp = PAF_SUBGRP(paf);
5090
5091 /*
5092 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5093 * or a refresh has already been triggered.
5094 */
5095 if (!subgrp || paf->t_announce_route)
5096 return;
5097
e1a32ec1
DS
5098 if (force)
5099 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5100
d62a17ae 5101 /*
5102 * Start a timer to stagger/delay the announce. This serves
5103 * two purposes - announcement can potentially be combined for
5104 * multiple peers and the announcement doesn't happen in the
5105 * vty context.
5106 */
5107 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5108 (subgrp->peer_count == 1)
5109 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5110 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5111 &paf->t_announce_route);
3f9c7369
DS
5112}
5113
5114/*
5115 * Announce routes from all AF tables to a peer.
5116 *
5117 * This should ONLY be called when there is a need to refresh the
5118 * routes to the peer based on a policy change for this peer alone
5119 * or a route refresh request received from the peer.
5120 * The operation will result in splitting the peer from its existing
5121 * subgroups and putting it in new subgroups.
5122 */
d62a17ae 5123void bgp_announce_route_all(struct peer *peer)
718e3744 5124{
d62a17ae 5125 afi_t afi;
5126 safi_t safi;
5127
05c7a1cc 5128 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5129 bgp_announce_route(peer, afi, safi, false);
718e3744 5130}
6b0655a2 5131
46aeabed
LS
5132/* Flag or unflag bgp_dest to determine whether it should be treated by
5133 * bgp_soft_reconfig_table_task.
5134 * Flag if flag is true. Unflag if flag is false.
5135 */
5136static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5137{
5138 struct bgp_dest *dest;
5139 struct bgp_adj_in *ain;
5140
5141 if (!table)
5142 return;
5143
5144 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5145 for (ain = dest->adj_in; ain; ain = ain->next) {
5146 if (ain->peer != NULL)
5147 break;
5148 }
5149 if (flag && ain != NULL && ain->peer != NULL)
5150 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5151 else
5152 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5153 }
5154}
5155
5156static int bgp_soft_reconfig_table_update(struct peer *peer,
5157 struct bgp_dest *dest,
5158 struct bgp_adj_in *ain, afi_t afi,
5159 safi_t safi, struct prefix_rd *prd)
5160{
5161 struct bgp_path_info *pi;
5162 uint32_t num_labels = 0;
5163 mpls_label_t *label_pnt = NULL;
5164 struct bgp_route_evpn evpn;
5165
5166 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5167 if (pi->peer == peer)
5168 break;
5169
5170 if (pi && pi->extra)
5171 num_labels = pi->extra->num_labels;
5172 if (num_labels)
5173 label_pnt = &pi->extra->label[0];
5174 if (pi)
5175 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5176 sizeof(evpn));
5177 else
5178 memset(&evpn, 0, sizeof(evpn));
5179
5180 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5181 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
5182 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
5183 &evpn);
5184}
5185
d62a17ae 5186static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5187 struct bgp_table *table,
5188 struct prefix_rd *prd)
718e3744 5189{
d62a17ae 5190 int ret;
9bcb3eef 5191 struct bgp_dest *dest;
d62a17ae 5192 struct bgp_adj_in *ain;
718e3744 5193
d62a17ae 5194 if (!table)
5195 table = peer->bgp->rib[afi][safi];
718e3744 5196
9bcb3eef
DS
5197 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5198 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5199 if (ain->peer != peer)
5200 continue;
8692c506 5201
46aeabed
LS
5202 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5203 afi, safi, prd);
ea47320b
DL
5204
5205 if (ret < 0) {
9bcb3eef 5206 bgp_dest_unlock_node(dest);
ea47320b 5207 return;
d62a17ae 5208 }
5209 }
718e3744 5210}
5211
46aeabed
LS
5212/* Do soft reconfig table per bgp table.
5213 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5214 * when BGP_NODE_SOFT_RECONFIG is set,
5215 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5216 * Schedule a new thread to continue the job.
5217 * Without splitting the full job into several part,
5218 * vtysh waits for the job to finish before responding to a BGP command
5219 */
cc9f21da 5220static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5221{
5222 uint32_t iter, max_iter;
5223 int ret;
5224 struct bgp_dest *dest;
5225 struct bgp_adj_in *ain;
5226 struct peer *peer;
5227 struct bgp_table *table;
5228 struct prefix_rd *prd;
5229 struct listnode *node, *nnode;
5230
5231 table = THREAD_ARG(thread);
5232 prd = NULL;
5233
5234 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5235 if (table->soft_reconfig_init) {
5236 /* first call of the function with a new srta structure.
5237 * Don't do any treatment this time on nodes
5238 * in order vtysh to respond quickly
5239 */
5240 max_iter = 0;
5241 }
5242
5243 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5244 dest = bgp_route_next(dest)) {
5245 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5246 continue;
5247
5248 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5249
5250 for (ain = dest->adj_in; ain; ain = ain->next) {
5251 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5252 nnode, peer)) {
5253 if (ain->peer != peer)
5254 continue;
5255
5256 ret = bgp_soft_reconfig_table_update(
5257 peer, dest, ain, table->afi,
5258 table->safi, prd);
5259 iter++;
5260
5261 if (ret < 0) {
5262 bgp_dest_unlock_node(dest);
5263 listnode_delete(
5264 table->soft_reconfig_peers,
5265 peer);
5266 bgp_announce_route(peer, table->afi,
e1a32ec1 5267 table->safi, false);
46aeabed
LS
5268 if (list_isempty(
5269 table->soft_reconfig_peers)) {
5270 list_delete(
5271 &table->soft_reconfig_peers);
5272 bgp_soft_reconfig_table_flag(
5273 table, false);
cc9f21da 5274 return;
46aeabed
LS
5275 }
5276 }
5277 }
5278 }
5279 }
5280
5281 /* we're either starting the initial iteration,
5282 * or we're going to continue an ongoing iteration
5283 */
5284 if (dest || table->soft_reconfig_init) {
5285 table->soft_reconfig_init = false;
5286 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5287 table, 0, &table->soft_reconfig_thread);
cc9f21da 5288 return;
46aeabed
LS
5289 }
5290 /* we're done, clean up the background iteration context info and
5291 schedule route annoucement
5292 */
5293 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5294 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5295 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5296 }
5297
5298 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5299}
5300
5301
5302/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5303 * and peer.
5304 * - bgp cannot be NULL
5305 * - if table and peer are NULL, cancel all threads within the bgp instance
5306 * - if table is NULL and peer is not,
5307 * remove peer in all threads within the bgp instance
5308 * - if peer is NULL, cancel all threads matching table within the bgp instance
5309 */
5310void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5311 const struct bgp_table *table,
5312 const struct peer *peer)
5313{
5314 struct peer *npeer;
5315 struct listnode *node, *nnode;
5316 int afi, safi;
5317 struct bgp_table *ntable;
5318
5319 if (!bgp)
5320 return;
5321
5322 FOREACH_AFI_SAFI (afi, safi) {
5323 ntable = bgp->rib[afi][safi];
5324 if (!ntable)
5325 continue;
5326 if (table && table != ntable)
5327 continue;
5328
5329 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5330 npeer)) {
5331 if (peer && peer != npeer)
5332 continue;
5333 listnode_delete(ntable->soft_reconfig_peers, npeer);
5334 }
5335
5336 if (!ntable->soft_reconfig_peers
5337 || !list_isempty(ntable->soft_reconfig_peers))
5338 continue;
5339
5340 list_delete(&ntable->soft_reconfig_peers);
5341 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5342 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5343 }
5344}
5345
89c73443
DS
5346/*
5347 * Returns false if the peer is not configured for soft reconfig in
5348 */
5349bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5350{
9bcb3eef 5351 struct bgp_dest *dest;
d62a17ae 5352 struct bgp_table *table;
46aeabed
LS
5353 struct listnode *node, *nnode;
5354 struct peer *npeer;
5355 struct peer_af *paf;
718e3744 5356
89c73443
DS
5357 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5358 return false;
718e3744 5359
d62a17ae 5360 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5361 && (safi != SAFI_EVPN)) {
5362 table = peer->bgp->rib[afi][safi];
5363 if (!table)
89c73443 5364 return true;
46aeabed
LS
5365
5366 table->soft_reconfig_init = true;
5367
5368 if (!table->soft_reconfig_peers)
5369 table->soft_reconfig_peers = list_new();
5370 npeer = NULL;
5371 /* add peer to the table soft_reconfig_peers if not already
5372 * there
5373 */
5374 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5375 npeer)) {
5376 if (peer == npeer)
5377 break;
5378 }
5379 if (peer != npeer)
5380 listnode_add(table->soft_reconfig_peers, peer);
5381
5382 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5383 * on table would start back at the beginning.
5384 */
5385 bgp_soft_reconfig_table_flag(table, true);
5386
5387 if (!table->soft_reconfig_thread)
5388 thread_add_event(bm->master,
5389 bgp_soft_reconfig_table_task, table, 0,
5390 &table->soft_reconfig_thread);
5391 /* Cancel bgp_announce_route_timer_expired threads.
5392 * bgp_announce_route_timer_expired threads have been scheduled
5393 * to announce routes as soon as the soft_reconfigure process
5394 * finishes.
5395 * In this case, soft_reconfigure is also scheduled by using
5396 * a thread but is planned after the
5397 * bgp_announce_route_timer_expired threads. It means that,
5398 * without cancelling the threads, the route announcement task
5399 * would run before the soft reconfiguration one. That would
5400 * useless and would block vtysh during several seconds. Route
5401 * announcements are rescheduled as soon as the soft_reconfigure
5402 * process finishes.
5403 */
5404 paf = peer_af_find(peer, afi, safi);
5405 if (paf)
5406 bgp_stop_announce_route_timer(paf);
5407 } else
9bcb3eef
DS
5408 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5409 dest = bgp_route_next(dest)) {
5410 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5411
b54892e0
DS
5412 if (table == NULL)
5413 continue;
8692c506 5414
9bcb3eef 5415 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5416 struct prefix_rd prd;
5417
5418 prd.family = AF_UNSPEC;
5419 prd.prefixlen = 64;
5420 memcpy(&prd.val, p->u.val, 8);
5421
5422 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5423 }
89c73443
DS
5424
5425 return true;
718e3744 5426}
6b0655a2 5427
228da428 5428
d62a17ae 5429struct bgp_clear_node_queue {
9bcb3eef 5430 struct bgp_dest *dest;
228da428
CC
5431};
5432
d62a17ae 5433static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5434{
d62a17ae 5435 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5436 struct bgp_dest *dest = cnq->dest;
d62a17ae 5437 struct peer *peer = wq->spec.data;
40381db7 5438 struct bgp_path_info *pi;
3103e8d2 5439 struct bgp *bgp;
9bcb3eef
DS
5440 afi_t afi = bgp_dest_table(dest)->afi;
5441 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5442
9bcb3eef 5443 assert(dest && peer);
3103e8d2 5444 bgp = peer->bgp;
d62a17ae 5445
5446 /* It is possible that we have multiple paths for a prefix from a peer
5447 * if that peer is using AddPath.
5448 */
9bcb3eef 5449 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5450 if (pi->peer != peer)
ea47320b
DL
5451 continue;
5452
5453 /* graceful restart STALE flag set. */
9af52ccf
DA
5454 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5455 && peer->nsf[afi][safi])
5456 || CHECK_FLAG(peer->af_sflags[afi][safi],
5457 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5458 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5459 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5460 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5461 else {
5462 /* If this is an EVPN route, process for
5463 * un-import. */
5464 if (safi == SAFI_EVPN)
9bcb3eef
DS
5465 bgp_evpn_unimport_route(
5466 bgp, afi, safi,
5467 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5468 /* Handle withdraw for VRF route-leaking and L3VPN */
5469 if (SAFI_UNICAST == safi
5470 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5471 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5472 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5473 bgp, pi);
960035b2 5474 }
3103e8d2 5475 if (SAFI_MPLS_VPN == safi &&
960035b2 5476 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5477 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5478 }
3103e8d2 5479
9bcb3eef 5480 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5481 }
ea47320b 5482 }
d62a17ae 5483 return WQ_SUCCESS;
200df115 5484}
5485
d62a17ae 5486static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5487{
d62a17ae 5488 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5489 struct bgp_dest *dest = cnq->dest;
5490 struct bgp_table *table = bgp_dest_table(dest);
228da428 5491
9bcb3eef 5492 bgp_dest_unlock_node(dest);
d62a17ae 5493 bgp_table_unlock(table);
5494 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5495}
5496
d62a17ae 5497static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5498{
d62a17ae 5499 struct peer *peer = wq->spec.data;
64e580a7 5500
d62a17ae 5501 /* Tickle FSM to start moving again */
5502 BGP_EVENT_ADD(peer, Clearing_Completed);
5503
5504 peer_unlock(peer); /* bgp_clear_route */
200df115 5505}
718e3744 5506
d62a17ae 5507static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5508{
d62a17ae 5509 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5510
5511 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5512#undef CLEAR_QUEUE_NAME_LEN
5513
0ce1ca80 5514 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5515 peer->clear_node_queue->spec.hold = 10;
5516 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5517 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5518 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5519 peer->clear_node_queue->spec.max_retries = 0;
5520
5521 /* we only 'lock' this peer reference when the queue is actually active
5522 */
5523 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5524}
5525
d62a17ae 5526static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5527 struct bgp_table *table)
65ca75e0 5528{
9bcb3eef 5529 struct bgp_dest *dest;
b6c386bb 5530 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5531
d62a17ae 5532 if (!table)
5533 table = peer->bgp->rib[afi][safi];
dc83d712 5534
d62a17ae 5535 /* If still no table => afi/safi isn't configured at all or smth. */
5536 if (!table)
5537 return;
dc83d712 5538
9bcb3eef 5539 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5540 struct bgp_path_info *pi, *next;
d62a17ae 5541 struct bgp_adj_in *ain;
5542 struct bgp_adj_in *ain_next;
5543
5544 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5545 * queued for every clearing peer, regardless of whether it is
5546 * relevant to the peer at hand.
5547 *
5548 * Overview: There are 3 different indices which need to be
5549 * scrubbed, potentially, when a peer is removed:
5550 *
5551 * 1 peer's routes visible via the RIB (ie accepted routes)
5552 * 2 peer's routes visible by the (optional) peer's adj-in index
5553 * 3 other routes visible by the peer's adj-out index
5554 *
5555 * 3 there is no hurry in scrubbing, once the struct peer is
5556 * removed from bgp->peer, we could just GC such deleted peer's
5557 * adj-outs at our leisure.
5558 *
5559 * 1 and 2 must be 'scrubbed' in some way, at least made
5560 * invisible via RIB index before peer session is allowed to be
5561 * brought back up. So one needs to know when such a 'search' is
5562 * complete.
5563 *
5564 * Ideally:
5565 *
5566 * - there'd be a single global queue or a single RIB walker
5567 * - rather than tracking which route_nodes still need to be
5568 * examined on a peer basis, we'd track which peers still
5569 * aren't cleared
5570 *
5571 * Given that our per-peer prefix-counts now should be reliable,
5572 * this may actually be achievable. It doesn't seem to be a huge
5573 * problem at this time,
5574 *
5575 * It is possible that we have multiple paths for a prefix from
5576 * a peer
5577 * if that peer is using AddPath.
5578 */
9bcb3eef 5579 ain = dest->adj_in;
d62a17ae 5580 while (ain) {
5581 ain_next = ain->next;
5582
6a840fd9 5583 if (ain->peer == peer)
9bcb3eef 5584 bgp_adj_in_remove(dest, ain);
d62a17ae 5585
5586 ain = ain_next;
5587 }
5588
9bcb3eef 5589 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5590 next = pi->next;
5591 if (pi->peer != peer)
d62a17ae 5592 continue;
5593
5594 if (force)
9bcb3eef 5595 bgp_path_info_reap(dest, pi);
d62a17ae 5596 else {
5597 struct bgp_clear_node_queue *cnq;
5598
5599 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5600 bgp_table_lock(bgp_dest_table(dest));
5601 bgp_dest_lock_node(dest);
d62a17ae 5602 cnq = XCALLOC(
5603 MTYPE_BGP_CLEAR_NODE_QUEUE,
5604 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5605 cnq->dest = dest;
d62a17ae 5606 work_queue_add(peer->clear_node_queue, cnq);
5607 break;
5608 }
5609 }
5610 }
5611 return;
5612}
5613
5614void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5615{
9bcb3eef 5616 struct bgp_dest *dest;
d62a17ae 5617 struct bgp_table *table;
5618
5619 if (peer->clear_node_queue == NULL)
5620 bgp_clear_node_queue_init(peer);
5621
5622 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5623 * Idle until it receives a Clearing_Completed event. This protects
5624 * against peers which flap faster than we can we clear, which could
5625 * lead to:
5626 *
5627 * a) race with routes from the new session being installed before
5628 * clear_route_node visits the node (to delete the route of that
5629 * peer)
5630 * b) resource exhaustion, clear_route_node likely leads to an entry
5631 * on the process_main queue. Fast-flapping could cause that queue
5632 * to grow and grow.
5633 */
5634
5635 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5636 * the unlock will happen upon work-queue completion; other wise, the
5637 * unlock happens at the end of this function.
5638 */
5639 if (!peer->clear_node_queue->thread)
5640 peer_lock(peer);
5641
5642 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5643 bgp_clear_route_table(peer, afi, safi, NULL);
5644 else
9bcb3eef
DS
5645 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5646 dest = bgp_route_next(dest)) {
5647 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5648 if (!table)
5649 continue;
5650
5651 bgp_clear_route_table(peer, afi, safi, table);
5652 }
d62a17ae 5653
5654 /* unlock if no nodes got added to the clear-node-queue. */
5655 if (!peer->clear_node_queue->thread)
5656 peer_unlock(peer);
718e3744 5657}
d62a17ae 5658
5659void bgp_clear_route_all(struct peer *peer)
718e3744 5660{
d62a17ae 5661 afi_t afi;
5662 safi_t safi;
718e3744 5663
05c7a1cc
QY
5664 FOREACH_AFI_SAFI (afi, safi)
5665 bgp_clear_route(peer, afi, safi);
65efcfce 5666
49e5a4a0 5667#ifdef ENABLE_BGP_VNC
d62a17ae 5668 rfapiProcessPeerDown(peer);
65efcfce 5669#endif
718e3744 5670}
5671
d62a17ae 5672void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5673{
d62a17ae 5674 struct bgp_table *table;
9bcb3eef 5675 struct bgp_dest *dest;
d62a17ae 5676 struct bgp_adj_in *ain;
5677 struct bgp_adj_in *ain_next;
718e3744 5678
d62a17ae 5679 table = peer->bgp->rib[afi][safi];
718e3744 5680
d62a17ae 5681 /* It is possible that we have multiple paths for a prefix from a peer
5682 * if that peer is using AddPath.
5683 */
9bcb3eef
DS
5684 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5685 ain = dest->adj_in;
43143c8f 5686
d62a17ae 5687 while (ain) {
5688 ain_next = ain->next;
43143c8f 5689
6a840fd9 5690 if (ain->peer == peer)
9bcb3eef 5691 bgp_adj_in_remove(dest, ain);
43143c8f 5692
d62a17ae 5693 ain = ain_next;
5694 }
5695 }
718e3744 5696}
93406d87 5697
1479ed2f
DA
5698/* If any of the routes from the peer have been marked with the NO_LLGR
5699 * community, either as sent by the peer, or as the result of a configured
5700 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5701 * operation of [RFC4271].
5702 */
d62a17ae 5703void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5704{
9bcb3eef 5705 struct bgp_dest *dest;
40381db7 5706 struct bgp_path_info *pi;
d62a17ae 5707 struct bgp_table *table;
5708
9af52ccf 5709 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5710 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5711 dest = bgp_route_next(dest)) {
5712 struct bgp_dest *rm;
d62a17ae 5713
5714 /* look for neighbor in tables */
9bcb3eef 5715 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5716 if (!table)
ea47320b
DL
5717 continue;
5718
5719 for (rm = bgp_table_top(table); rm;
5720 rm = bgp_route_next(rm))
9bcb3eef 5721 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5722 pi = pi->next) {
40381db7 5723 if (pi->peer != peer)
ea47320b 5724 continue;
1479ed2f
DA
5725 if (CHECK_FLAG(
5726 peer->af_sflags[afi][safi],
5727 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5728 bgp_attr_get_community(pi->attr) &&
1479ed2f 5729 !community_include(
9a706b42
DA
5730 bgp_attr_get_community(
5731 pi->attr),
1479ed2f 5732 COMMUNITY_NO_LLGR))
e3015d91 5733 continue;
40381db7 5734 if (!CHECK_FLAG(pi->flags,
1defdda8 5735 BGP_PATH_STALE))
e3015d91 5736 continue;
ea47320b 5737
641065d4
KM
5738 /*
5739 * If this is VRF leaked route
5740 * process for withdraw.
5741 */
5742 if (pi->sub_type ==
5743 BGP_ROUTE_IMPORTED &&
5744 peer->bgp->inst_type ==
5745 BGP_INSTANCE_TYPE_DEFAULT)
5746 vpn_leak_to_vrf_withdraw(
5747 peer->bgp, pi);
5748
40381db7 5749 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5750 break;
5751 }
d62a17ae 5752 }
5753 } else {
9bcb3eef
DS
5754 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5755 dest = bgp_route_next(dest))
5756 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5757 pi = pi->next) {
40381db7 5758 if (pi->peer != peer)
ea47320b 5759 continue;
1479ed2f
DA
5760 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5761 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5762 bgp_attr_get_community(pi->attr) &&
5763 !community_include(
5764 bgp_attr_get_community(pi->attr),
5765 COMMUNITY_NO_LLGR))
e3015d91 5766 continue;
40381db7 5767 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5768 continue;
641065d4
KM
5769 if (safi == SAFI_UNICAST &&
5770 (peer->bgp->inst_type ==
5771 BGP_INSTANCE_TYPE_VRF ||
5772 peer->bgp->inst_type ==
5773 BGP_INSTANCE_TYPE_DEFAULT))
5774 vpn_leak_from_vrf_withdraw(
5775 bgp_get_default(), peer->bgp,
5776 pi);
5777
9bcb3eef 5778 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5779 break;
5780 }
d62a17ae 5781 }
93406d87 5782}
6b0655a2 5783
9af52ccf
DA
5784void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5785{
5786 struct bgp_dest *dest, *ndest;
5787 struct bgp_path_info *pi;
5788 struct bgp_table *table;
5789
5790 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5791 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5792 dest = bgp_route_next(dest)) {
5793 table = bgp_dest_get_bgp_table_info(dest);
5794 if (!table)
5795 continue;
5796
5797 for (ndest = bgp_table_top(table); ndest;
5798 ndest = bgp_route_next(ndest)) {
5799 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5800 pi = pi->next) {
5801 if (pi->peer != peer)
5802 continue;
5803
5804 if ((CHECK_FLAG(
5805 peer->af_sflags[afi][safi],
5806 PEER_STATUS_ENHANCED_REFRESH))
5807 && !CHECK_FLAG(pi->flags,
5808 BGP_PATH_STALE)
5809 && !CHECK_FLAG(
5810 pi->flags,
5811 BGP_PATH_UNUSEABLE)) {
5812 if (bgp_debug_neighbor_events(
5813 peer))
5814 zlog_debug(
58e111f6
DA
5815 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5816 peer,
9af52ccf
DA
5817 afi2str(afi),
5818 safi2str(safi),
5819 bgp_dest_get_prefix(
5820 ndest));
5821
5822 bgp_path_info_set_flag(
5823 ndest, pi,
5824 BGP_PATH_STALE);
5825 }
5826 }
5827 }
5828 }
5829 } else {
5830 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5831 dest = bgp_route_next(dest)) {
5832 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5833 pi = pi->next) {
5834 if (pi->peer != peer)
5835 continue;
5836
5837 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5838 PEER_STATUS_ENHANCED_REFRESH))
5839 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5840 && !CHECK_FLAG(pi->flags,
5841 BGP_PATH_UNUSEABLE)) {
5842 if (bgp_debug_neighbor_events(peer))
5843 zlog_debug(
58e111f6
DA
5844 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5845 peer, afi2str(afi),
9af52ccf
DA
5846 safi2str(safi),
5847 bgp_dest_get_prefix(
5848 dest));
5849
5850 bgp_path_info_set_flag(dest, pi,
5851 BGP_PATH_STALE);
5852 }
5853 }
5854 }
5855 }
5856}
5857
3dc339cd 5858bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5859{
e0df4c04 5860 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5861 return true;
e0df4c04 5862
9dac9fc8
DA
5863 if (peer->sort == BGP_PEER_EBGP
5864 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5865 || FILTER_LIST_OUT_NAME(filter)
5866 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5867 return true;
5868 return false;
9dac9fc8
DA
5869}
5870
3dc339cd 5871bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5872{
e0df4c04 5873 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5874 return true;
e0df4c04 5875
9dac9fc8
DA
5876 if (peer->sort == BGP_PEER_EBGP
5877 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5878 || FILTER_LIST_IN_NAME(filter)
5879 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5880 return true;
5881 return false;
9dac9fc8
DA
5882}
5883
568e10ca 5884static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5885 safi_t safi)
bb86c601 5886{
9bcb3eef 5887 struct bgp_dest *dest;
40381db7 5888 struct bgp_path_info *pi;
4b7e6066 5889 struct bgp_path_info *next;
bb86c601 5890
9bcb3eef
DS
5891 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5892 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5893 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5894
40381db7 5895 next = pi->next;
1b7bb747
CS
5896
5897 /* Unimport EVPN routes from VRFs */
5898 if (safi == SAFI_EVPN)
5899 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5900 SAFI_EVPN, p, pi);
1b7bb747 5901
40381db7
DS
5902 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5903 && pi->type == ZEBRA_ROUTE_BGP
5904 && (pi->sub_type == BGP_ROUTE_NORMAL
5905 || pi->sub_type == BGP_ROUTE_AGGREGATE
5906 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5907
d62a17ae 5908 if (bgp_fibupd_safi(safi))
b54892e0 5909 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5910 }
9514b37d 5911
9bcb3eef 5912 bgp_path_info_reap(dest, pi);
d62a17ae 5913 }
bb86c601
LB
5914}
5915
718e3744 5916/* Delete all kernel routes. */
d62a17ae 5917void bgp_cleanup_routes(struct bgp *bgp)
5918{
5919 afi_t afi;
9bcb3eef 5920 struct bgp_dest *dest;
67009e22 5921 struct bgp_table *table;
d62a17ae 5922
5923 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5924 if (afi == AFI_L2VPN)
5925 continue;
568e10ca 5926 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5927 SAFI_UNICAST);
d62a17ae 5928 /*
5929 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5930 */
5931 if (afi != AFI_L2VPN) {
5932 safi_t safi;
5933 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5934 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5935 dest = bgp_route_next(dest)) {
5936 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5937 if (table != NULL) {
5938 bgp_cleanup_table(bgp, table, safi);
5939 bgp_table_finish(&table);
9bcb3eef
DS
5940 bgp_dest_set_bgp_table_info(dest, NULL);
5941 bgp_dest_unlock_node(dest);
d62a17ae 5942 }
5943 }
5944 safi = SAFI_ENCAP;
9bcb3eef
DS
5945 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5946 dest = bgp_route_next(dest)) {
5947 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5948 if (table != NULL) {
5949 bgp_cleanup_table(bgp, table, safi);
5950 bgp_table_finish(&table);
9bcb3eef
DS
5951 bgp_dest_set_bgp_table_info(dest, NULL);
5952 bgp_dest_unlock_node(dest);
d62a17ae 5953 }
5954 }
5955 }
5956 }
9bcb3eef
DS
5957 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5958 dest = bgp_route_next(dest)) {
5959 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5960 if (table != NULL) {
5961 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5962 bgp_table_finish(&table);
9bcb3eef
DS
5963 bgp_dest_set_bgp_table_info(dest, NULL);
5964 bgp_dest_unlock_node(dest);
d62a17ae 5965 }
bb86c601 5966 }
718e3744 5967}
5968
d62a17ae 5969void bgp_reset(void)
718e3744 5970{
d62a17ae 5971 vty_reset();
5972 bgp_zclient_reset();
5973 access_list_reset();
5974 prefix_list_reset();
718e3744 5975}
6b0655a2 5976
be92fc9f 5977bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5978{
d62a17ae 5979 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5980 && CHECK_FLAG(peer->af_cap[afi][safi],
5981 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5982}
5983
718e3744 5984/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5985 value. */
d62a17ae 5986int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5987 struct bgp_nlri *packet)
5988{
d7c0a89a
QY
5989 uint8_t *pnt;
5990 uint8_t *lim;
d62a17ae 5991 struct prefix p;
5992 int psize;
5993 int ret;
5994 afi_t afi;
5995 safi_t safi;
be92fc9f 5996 bool addpath_capable;
d7c0a89a 5997 uint32_t addpath_id;
d62a17ae 5998
d62a17ae 5999 pnt = packet->nlri;
6000 lim = pnt + packet->length;
6001 afi = packet->afi;
6002 safi = packet->safi;
6003 addpath_id = 0;
be92fc9f 6004 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 6005
6006 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6007 syntactic validity. If the field is syntactically incorrect,
6008 then the Error Subcode is set to Invalid Network Field. */
6009 for (; pnt < lim; pnt += psize) {
6010 /* Clear prefix structure. */
6006b807 6011 memset(&p, 0, sizeof(p));
d62a17ae 6012
be92fc9f 6013 if (addpath_capable) {
d62a17ae 6014
6015 /* When packet overflow occurs return immediately. */
761ed665 6016 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6017 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6018
a3a850a1 6019 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6020 addpath_id = ntohl(addpath_id);
d62a17ae 6021 pnt += BGP_ADDPATH_ID_LEN;
6022 }
718e3744 6023
d62a17ae 6024 /* Fetch prefix length. */
6025 p.prefixlen = *pnt++;
6026 /* afi/safi validity already verified by caller,
6027 * bgp_update_receive */
6028 p.family = afi2family(afi);
6029
6030 /* Prefix length check. */
6031 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6032 flog_err(
e50f7cfd 6033 EC_BGP_UPDATE_RCV,
14454c9f 6034 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6035 peer->host, p.prefixlen, packet->afi);
513386b5 6036 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6037 }
6b0655a2 6038
d62a17ae 6039 /* Packet size overflow check. */
6040 psize = PSIZE(p.prefixlen);
6041
6042 /* When packet overflow occur return immediately. */
6043 if (pnt + psize > lim) {
af4c2728 6044 flog_err(
e50f7cfd 6045 EC_BGP_UPDATE_RCV,
d62a17ae 6046 "%s [Error] Update packet error (prefix length %d overflows packet)",
6047 peer->host, p.prefixlen);
513386b5 6048 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6049 }
6050
6051 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6052 * prefix for the v4 and v6 afi's and unicast/multicast */
6053 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6054 flog_err(
e50f7cfd 6055 EC_BGP_UPDATE_RCV,
d62a17ae 6056 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6057 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6058 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6059 }
6060
6061 /* Fetch prefix from NLRI packet. */
a85297a7 6062 memcpy(p.u.val, pnt, psize);
d62a17ae 6063
6064 /* Check address. */
6065 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6066 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6067 /* From RFC4271 Section 6.3:
6068 *
6069 * If a prefix in the NLRI field is semantically
6070 * incorrect
6071 * (e.g., an unexpected multicast IP address),
6072 * an error SHOULD
6073 * be logged locally, and the prefix SHOULD be
6074 * ignored.
a4d82a8a 6075 */
af4c2728 6076 flog_err(
e50f7cfd 6077 EC_BGP_UPDATE_RCV,
23d0a753
DA
6078 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6079 peer->host, &p.u.prefix4);
d62a17ae 6080 continue;
6081 }
6082 }
6083
6084 /* Check address. */
6085 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6086 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6087 flog_err(
e50f7cfd 6088 EC_BGP_UPDATE_RCV,
c0d72166
DS
6089 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6090 peer->host, &p.u.prefix6);
d62a17ae 6091
6092 continue;
6093 }
6094 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6095 flog_err(
e50f7cfd 6096 EC_BGP_UPDATE_RCV,
c0d72166
DS
6097 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6098 peer->host, &p.u.prefix6);
d62a17ae 6099
6100 continue;
6101 }
6102 }
6103
6104 /* Normal process. */
6105 if (attr)
6106 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
6107 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 6108 NULL, NULL, 0, 0, NULL);
d62a17ae 6109 else
6110 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
6111 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
6112 BGP_ROUTE_NORMAL, NULL, NULL, 0,
6113 NULL);
d62a17ae 6114
513386b5
DA
6115 /* Do not send BGP notification twice when maximum-prefix count
6116 * overflow. */
6117 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6118 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6119
6120 /* Address family configuration mismatch. */
d62a17ae 6121 if (ret < 0)
513386b5 6122 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 6123 }
6124
6125 /* Packet length consistency check. */
6126 if (pnt != lim) {
af4c2728 6127 flog_err(
e50f7cfd 6128 EC_BGP_UPDATE_RCV,
d62a17ae 6129 "%s [Error] Update packet error (prefix length mismatch with total length)",
6130 peer->host);
513386b5 6131 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6132 }
6b0655a2 6133
513386b5 6134 return BGP_NLRI_PARSE_OK;
718e3744 6135}
6136
d62a17ae 6137static struct bgp_static *bgp_static_new(void)
718e3744 6138{
d62a17ae 6139 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6140}
6141
d62a17ae 6142static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6143{
0a22ddfb 6144 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6145 route_map_counter_decrement(bgp_static->rmap.map);
6146
0a22ddfb 6147 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6148 XFREE(MTYPE_BGP_STATIC, bgp_static);
6149}
6150
5f040085 6151void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6152 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6153{
9bcb3eef 6154 struct bgp_dest *dest;
40381db7 6155 struct bgp_path_info *pi;
4b7e6066 6156 struct bgp_path_info *new;
40381db7 6157 struct bgp_path_info rmap_path;
d62a17ae 6158 struct attr attr;
6159 struct attr *attr_new;
b68885f9 6160 route_map_result_t ret;
49e5a4a0 6161#ifdef ENABLE_BGP_VNC
d62a17ae 6162 int vnc_implicit_withdraw = 0;
65efcfce 6163#endif
fee0f4c6 6164
d62a17ae 6165 assert(bgp_static);
dd8103a9 6166
9bcb3eef 6167 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6168
0f05ea43 6169 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6170
d62a17ae 6171 attr.nexthop = bgp_static->igpnexthop;
6172 attr.med = bgp_static->igpmetric;
6173 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6174
7226bc40
TA
6175 if (afi == AFI_IP)
6176 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6177
97a52c82
DA
6178 if (bgp_static->igpmetric)
6179 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6180
d62a17ae 6181 if (bgp_static->atomic)
6182 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6183
d62a17ae 6184 /* Store label index, if required. */
6185 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6186 attr.label_index = bgp_static->label_index;
6187 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6188 }
718e3744 6189
d62a17ae 6190 /* Apply route-map. */
6191 if (bgp_static->rmap.name) {
6192 struct attr attr_tmp = attr;
80ced710 6193
6006b807 6194 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6195 rmap_path.peer = bgp->peer_self;
6196 rmap_path.attr = &attr_tmp;
fee0f4c6 6197
d62a17ae 6198 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6199
1782514f 6200 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6201
d62a17ae 6202 bgp->peer_self->rmap_type = 0;
718e3744 6203
d62a17ae 6204 if (ret == RMAP_DENYMATCH) {
6205 /* Free uninterned attribute. */
6206 bgp_attr_flush(&attr_tmp);
718e3744 6207
d62a17ae 6208 /* Unintern original. */
6209 aspath_unintern(&attr.aspath);
6210 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6211 bgp_dest_unlock_node(dest);
d62a17ae 6212 return;
6213 }
7f323236 6214
637e5ba4 6215 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6216 bgp_attr_add_gshut_community(&attr_tmp);
6217
d62a17ae 6218 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6219 } else {
6220
637e5ba4 6221 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6222 bgp_attr_add_gshut_community(&attr);
6223
d62a17ae 6224 attr_new = bgp_attr_intern(&attr);
7f323236 6225 }
718e3744 6226
9bcb3eef 6227 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6228 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6229 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6230 break;
6231
40381db7
DS
6232 if (pi) {
6233 if (attrhash_cmp(pi->attr, attr_new)
6234 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6235 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6236 bgp_dest_unlock_node(dest);
d62a17ae 6237 bgp_attr_unintern(&attr_new);
6238 aspath_unintern(&attr.aspath);
6239 return;
6240 } else {
6241 /* The attribute is changed. */
9bcb3eef 6242 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6243
6244 /* Rewrite BGP route information. */
40381db7 6245 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6246 bgp_path_info_restore(dest, pi);
d62a17ae 6247 else
40381db7 6248 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6249#ifdef ENABLE_BGP_VNC
d62a17ae 6250 if ((afi == AFI_IP || afi == AFI_IP6)
6251 && (safi == SAFI_UNICAST)) {
40381db7 6252 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6253 /*
6254 * Implicit withdraw case.
40381db7 6255 * We have to do this before pi is
d62a17ae 6256 * changed
6257 */
6258 ++vnc_implicit_withdraw;
40381db7 6259 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6260 vnc_import_bgp_exterior_del_route(
40381db7 6261 bgp, p, pi);
d62a17ae 6262 }
6263 }
65efcfce 6264#endif
40381db7
DS
6265 bgp_attr_unintern(&pi->attr);
6266 pi->attr = attr_new;
083ec940 6267 pi->uptime = monotime(NULL);
49e5a4a0 6268#ifdef ENABLE_BGP_VNC
d62a17ae 6269 if ((afi == AFI_IP || afi == AFI_IP6)
6270 && (safi == SAFI_UNICAST)) {
6271 if (vnc_implicit_withdraw) {
40381db7 6272 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6273 vnc_import_bgp_exterior_add_route(
40381db7 6274 bgp, p, pi);
d62a17ae 6275 }
6276 }
65efcfce 6277#endif
718e3744 6278
d62a17ae 6279 /* Nexthop reachability check. */
892fedb6 6280 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6281 && (safi == SAFI_UNICAST
6282 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6283
6284 struct bgp *bgp_nexthop = bgp;
6285
40381db7
DS
6286 if (pi->extra && pi->extra->bgp_orig)
6287 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6288
6289 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6290 afi, safi, pi, NULL,
654a5978 6291 0, p))
9bcb3eef 6292 bgp_path_info_set_flag(dest, pi,
18ee8310 6293 BGP_PATH_VALID);
d62a17ae 6294 else {
6295 if (BGP_DEBUG(nht, NHT)) {
6296 char buf1[INET6_ADDRSTRLEN];
6297 inet_ntop(p->family,
6298 &p->u.prefix, buf1,
07380148 6299 sizeof(buf1));
d62a17ae 6300 zlog_debug(
6301 "%s(%s): Route not in table, not advertising",
15569c58 6302 __func__, buf1);
d62a17ae 6303 }
18ee8310 6304 bgp_path_info_unset_flag(
9bcb3eef 6305 dest, pi, BGP_PATH_VALID);
d62a17ae 6306 }
6307 } else {
6308 /* Delete the NHT structure if any, if we're
6309 * toggling between
6310 * enabling/disabling import check. We
6311 * deregister the route
6312 * from NHT to avoid overloading NHT and the
6313 * process interaction
6314 */
40381db7 6315 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6316 bgp_path_info_set_flag(dest, pi,
6317 BGP_PATH_VALID);
d62a17ae 6318 }
6319 /* Process change. */
40381db7 6320 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6321 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6322
6323 if (SAFI_UNICAST == safi
6324 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6325 || bgp->inst_type
6326 == BGP_INSTANCE_TYPE_DEFAULT)) {
6327 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6328 pi);
ddb5b488
PZ
6329 }
6330
9bcb3eef 6331 bgp_dest_unlock_node(dest);
d62a17ae 6332 aspath_unintern(&attr.aspath);
6333 return;
6334 }
718e3744 6335 }
718e3744 6336
d62a17ae 6337 /* Make new BGP info. */
6338 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6339 attr_new, dest);
d62a17ae 6340 /* Nexthop reachability check. */
892fedb6 6341 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6342 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6343 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6344 p))
9bcb3eef 6345 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6346 else {
6347 if (BGP_DEBUG(nht, NHT)) {
6348 char buf1[INET6_ADDRSTRLEN];
07380148 6349
d62a17ae 6350 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6351 sizeof(buf1));
d62a17ae 6352 zlog_debug(
6353 "%s(%s): Route not in table, not advertising",
15569c58 6354 __func__, buf1);
d62a17ae 6355 }
9bcb3eef 6356 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6357 }
6358 } else {
6359 /* Delete the NHT structure if any, if we're toggling between
6360 * enabling/disabling import check. We deregister the route
6361 * from NHT to avoid overloading NHT and the process interaction
6362 */
6363 bgp_unlink_nexthop(new);
6364
9bcb3eef 6365 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6366 }
078430f6 6367
d62a17ae 6368 /* Aggregate address increment. */
6369 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6370
d62a17ae 6371 /* Register new BGP information. */
9bcb3eef 6372 bgp_path_info_add(dest, new);
718e3744 6373
d62a17ae 6374 /* route_node_get lock */
9bcb3eef 6375 bgp_dest_unlock_node(dest);
d62a17ae 6376
6377 /* Process change. */
9bcb3eef 6378 bgp_process(bgp, dest, afi, safi);
d62a17ae 6379
ddb5b488
PZ
6380 if (SAFI_UNICAST == safi
6381 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6382 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6383 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6384 }
6385
d62a17ae 6386 /* Unintern original. */
6387 aspath_unintern(&attr.aspath);
718e3744 6388}
6389
5f040085 6390void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6391 safi_t safi)
718e3744 6392{
9bcb3eef 6393 struct bgp_dest *dest;
40381db7 6394 struct bgp_path_info *pi;
718e3744 6395
9bcb3eef 6396 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6397
d62a17ae 6398 /* Check selected route and self inserted route. */
9bcb3eef 6399 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6400 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6401 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6402 break;
6403
6404 /* Withdraw static BGP route from routing table. */
40381db7 6405 if (pi) {
ddb5b488
PZ
6406 if (SAFI_UNICAST == safi
6407 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6408 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6409 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6410 }
40381db7
DS
6411 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6412 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6413 bgp_path_info_delete(dest, pi);
6414 bgp_process(bgp, dest, afi, safi);
d62a17ae 6415 }
718e3744 6416
d62a17ae 6417 /* Unlock bgp_node_lookup. */
9bcb3eef 6418 bgp_dest_unlock_node(dest);
718e3744 6419}
6420
137446f9
LB
6421/*
6422 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6423 */
5f040085 6424static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6425 afi_t afi, safi_t safi,
6426 struct prefix_rd *prd)
718e3744 6427{
9bcb3eef 6428 struct bgp_dest *dest;
40381db7 6429 struct bgp_path_info *pi;
718e3744 6430
9bcb3eef 6431 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6432
d62a17ae 6433 /* Check selected route and self inserted route. */
9bcb3eef 6434 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6435 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6436 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6437 break;
718e3744 6438
d62a17ae 6439 /* Withdraw static BGP route from routing table. */
40381db7 6440 if (pi) {
49e5a4a0 6441#ifdef ENABLE_BGP_VNC
d62a17ae 6442 rfapiProcessWithdraw(
40381db7 6443 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6444 1); /* Kill, since it is an administrative change */
65efcfce 6445#endif
ddb5b488
PZ
6446 if (SAFI_MPLS_VPN == safi
6447 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6448 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6449 }
40381db7 6450 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6451 bgp_path_info_delete(dest, pi);
6452 bgp_process(bgp, dest, afi, safi);
d62a17ae 6453 }
718e3744 6454
d62a17ae 6455 /* Unlock bgp_node_lookup. */
9bcb3eef 6456 bgp_dest_unlock_node(dest);
718e3744 6457}
6458
5f040085 6459static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6460 struct bgp_static *bgp_static, afi_t afi,
6461 safi_t safi)
137446f9 6462{
9bcb3eef 6463 struct bgp_dest *dest;
4b7e6066 6464 struct bgp_path_info *new;
d62a17ae 6465 struct attr *attr_new;
6466 struct attr attr = {0};
40381db7 6467 struct bgp_path_info *pi;
49e5a4a0 6468#ifdef ENABLE_BGP_VNC
d62a17ae 6469 mpls_label_t label = 0;
65efcfce 6470#endif
d7c0a89a 6471 uint32_t num_labels = 0;
137446f9 6472
d62a17ae 6473 assert(bgp_static);
137446f9 6474
b57ba6d2
MK
6475 if (bgp_static->label != MPLS_INVALID_LABEL)
6476 num_labels = 1;
9bcb3eef
DS
6477 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6478 &bgp_static->prd);
137446f9 6479
0f05ea43 6480 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6481
d62a17ae 6482 attr.nexthop = bgp_static->igpnexthop;
6483 attr.med = bgp_static->igpmetric;
6484 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6485
d62a17ae 6486 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6487 || (safi == SAFI_ENCAP)) {
6488 if (afi == AFI_IP) {
6489 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6490 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6491 }
6492 }
6493 if (afi == AFI_L2VPN) {
b04c1e99
IR
6494 if (bgp_static->gatewayIp.family == AF_INET) {
6495 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6496 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6497 &bgp_static->gatewayIp.u.prefix4,
6498 IPV4_MAX_BYTELEN);
b04c1e99
IR
6499 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6500 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6501 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6502 &bgp_static->gatewayIp.u.prefix6,
6503 IPV6_MAX_BYTELEN);
b04c1e99 6504 }
0a50c248 6505 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6506 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6507 struct bgp_encap_type_vxlan bet;
6006b807 6508 memset(&bet, 0, sizeof(bet));
3714a385 6509 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6510 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6511 }
6512 if (bgp_static->router_mac) {
6513 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6514 }
6515 }
6516 /* Apply route-map. */
6517 if (bgp_static->rmap.name) {
6518 struct attr attr_tmp = attr;
40381db7 6519 struct bgp_path_info rmap_path;
b68885f9 6520 route_map_result_t ret;
137446f9 6521
40381db7
DS
6522 rmap_path.peer = bgp->peer_self;
6523 rmap_path.attr = &attr_tmp;
137446f9 6524
d62a17ae 6525 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6526
1782514f 6527 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6528
d62a17ae 6529 bgp->peer_self->rmap_type = 0;
137446f9 6530
d62a17ae 6531 if (ret == RMAP_DENYMATCH) {
6532 /* Free uninterned attribute. */
6533 bgp_attr_flush(&attr_tmp);
137446f9 6534
d62a17ae 6535 /* Unintern original. */
6536 aspath_unintern(&attr.aspath);
6537 bgp_static_withdraw_safi(bgp, p, afi, safi,
6538 &bgp_static->prd);
bbc52106 6539 bgp_dest_unlock_node(dest);
d62a17ae 6540 return;
6541 }
137446f9 6542
d62a17ae 6543 attr_new = bgp_attr_intern(&attr_tmp);
6544 } else {
6545 attr_new = bgp_attr_intern(&attr);
6546 }
137446f9 6547
9bcb3eef 6548 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6549 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6550 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6551 break;
6552
40381db7 6553 if (pi) {
40381db7 6554 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6555 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6556 bgp_dest_unlock_node(dest);
d62a17ae 6557 bgp_attr_unintern(&attr_new);
6558 aspath_unintern(&attr.aspath);
6559 return;
6560 } else {
6561 /* The attribute is changed. */
9bcb3eef 6562 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6563
6564 /* Rewrite BGP route information. */
40381db7 6565 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6566 bgp_path_info_restore(dest, pi);
d62a17ae 6567 else
40381db7
DS
6568 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6569 bgp_attr_unintern(&pi->attr);
6570 pi->attr = attr_new;
083ec940 6571 pi->uptime = monotime(NULL);
49e5a4a0 6572#ifdef ENABLE_BGP_VNC
40381db7
DS
6573 if (pi->extra)
6574 label = decode_label(&pi->extra->label[0]);
65efcfce 6575#endif
137446f9 6576
d62a17ae 6577 /* Process change. */
40381db7 6578 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6579 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6580
6581 if (SAFI_MPLS_VPN == safi
6582 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6583 vpn_leak_to_vrf_update(bgp, pi,
6584 &bgp_static->prd);
ddb5b488 6585 }
49e5a4a0 6586#ifdef ENABLE_BGP_VNC
40381db7
DS
6587 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6588 pi->attr, afi, safi, pi->type,
6589 pi->sub_type, &label);
65efcfce 6590#endif
9bcb3eef 6591 bgp_dest_unlock_node(dest);
d62a17ae 6592 aspath_unintern(&attr.aspath);
6593 return;
6594 }
6595 }
137446f9
LB
6596
6597
d62a17ae 6598 /* Make new BGP info. */
6599 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6600 attr_new, dest);
1defdda8 6601 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6602 bgp_path_info_extra_get(new);
b57ba6d2
MK
6603 if (num_labels) {
6604 new->extra->label[0] = bgp_static->label;
6605 new->extra->num_labels = num_labels;
6606 }
49e5a4a0 6607#ifdef ENABLE_BGP_VNC
d62a17ae 6608 label = decode_label(&bgp_static->label);
65efcfce 6609#endif
137446f9 6610
d62a17ae 6611 /* Aggregate address increment. */
6612 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6613
d62a17ae 6614 /* Register new BGP information. */
9bcb3eef 6615 bgp_path_info_add(dest, new);
d62a17ae 6616 /* route_node_get lock */
9bcb3eef 6617 bgp_dest_unlock_node(dest);
137446f9 6618
d62a17ae 6619 /* Process change. */
9bcb3eef 6620 bgp_process(bgp, dest, afi, safi);
137446f9 6621
ddb5b488
PZ
6622 if (SAFI_MPLS_VPN == safi
6623 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6624 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6625 }
49e5a4a0 6626#ifdef ENABLE_BGP_VNC
d62a17ae 6627 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6628 safi, new->type, new->sub_type, &label);
65efcfce
LB
6629#endif
6630
d62a17ae 6631 /* Unintern original. */
6632 aspath_unintern(&attr.aspath);
137446f9
LB
6633}
6634
718e3744 6635/* Configure static BGP network. When user don't run zebra, static
6636 route should be installed as valid. */
585f1adc
IR
6637static int bgp_static_set(struct vty *vty, const char *negate,
6638 const char *ip_str, afi_t afi, safi_t safi,
6639 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6640{
585f1adc
IR
6641 VTY_DECLVAR_CONTEXT(bgp, bgp);
6642 int ret;
d62a17ae 6643 struct prefix p;
6644 struct bgp_static *bgp_static;
9bcb3eef 6645 struct bgp_dest *dest;
d7c0a89a 6646 uint8_t need_update = 0;
d62a17ae 6647
585f1adc
IR
6648 /* Convert IP prefix string to struct prefix. */
6649 ret = str2prefix(ip_str, &p);
6650 if (!ret) {
6651 vty_out(vty, "%% Malformed prefix\n");
6652 return CMD_WARNING_CONFIG_FAILED;
6653 }
6654 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6655 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6656 return CMD_WARNING_CONFIG_FAILED;
6657 }
6658
d62a17ae 6659 apply_mask(&p);
718e3744 6660
e2a86ad9 6661 if (negate) {
718e3744 6662
e2a86ad9 6663 /* Set BGP static route configuration. */
9bcb3eef 6664 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6665
9bcb3eef 6666 if (!dest) {
585f1adc
IR
6667 vty_out(vty, "%% Can't find static route specified\n");
6668 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6669 }
6670
9bcb3eef 6671 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6672
e2a86ad9
DS
6673 if ((label_index != BGP_INVALID_LABEL_INDEX)
6674 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6675 vty_out(vty,
6676 "%% label-index doesn't match static route\n");
70d9b134 6677 bgp_dest_unlock_node(dest);
585f1adc 6678 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6679 }
d62a17ae 6680
e2a86ad9
DS
6681 if ((rmap && bgp_static->rmap.name)
6682 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6683 vty_out(vty,
6684 "%% route-map name doesn't match static route\n");
70d9b134 6685 bgp_dest_unlock_node(dest);
585f1adc 6686 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6687 }
718e3744 6688
e2a86ad9
DS
6689 /* Update BGP RIB. */
6690 if (!bgp_static->backdoor)
6691 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6692
e2a86ad9
DS
6693 /* Clear configuration. */
6694 bgp_static_free(bgp_static);
9bcb3eef
DS
6695 bgp_dest_set_bgp_static_info(dest, NULL);
6696 bgp_dest_unlock_node(dest);
6697 bgp_dest_unlock_node(dest);
e2a86ad9 6698 } else {
718e3744 6699
e2a86ad9 6700 /* Set BGP static route configuration. */
9bcb3eef
DS
6701 dest = bgp_node_get(bgp->route[afi][safi], &p);
6702 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6703 if (bgp_static) {
e2a86ad9 6704 /* Configuration change. */
e2a86ad9
DS
6705 /* Label index cannot be changed. */
6706 if (bgp_static->label_index != label_index) {
585f1adc 6707 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6708 bgp_dest_unlock_node(dest);
585f1adc 6709 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6710 }
d62a17ae 6711
e2a86ad9 6712 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6713 if (bgp_static->valid
6714 && bgp_static->backdoor != backdoor)
e2a86ad9 6715 need_update = 1;
718e3744 6716
e2a86ad9 6717 bgp_static->backdoor = backdoor;
718e3744 6718
e2a86ad9 6719 if (rmap) {
0a22ddfb
QY
6720 XFREE(MTYPE_ROUTE_MAP_NAME,
6721 bgp_static->rmap.name);
b4897fa5 6722 route_map_counter_decrement(
6723 bgp_static->rmap.map);
e2a86ad9
DS
6724 bgp_static->rmap.name =
6725 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6726 bgp_static->rmap.map =
6727 route_map_lookup_by_name(rmap);
b4897fa5 6728 route_map_counter_increment(
6729 bgp_static->rmap.map);
e2a86ad9 6730 } else {
0a22ddfb
QY
6731 XFREE(MTYPE_ROUTE_MAP_NAME,
6732 bgp_static->rmap.name);
b4897fa5 6733 route_map_counter_decrement(
6734 bgp_static->rmap.map);
e2a86ad9
DS
6735 bgp_static->rmap.map = NULL;
6736 bgp_static->valid = 0;
6737 }
9bcb3eef 6738 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6739 } else {
6740 /* New configuration. */
6741 bgp_static = bgp_static_new();
6742 bgp_static->backdoor = backdoor;
6743 bgp_static->valid = 0;
6744 bgp_static->igpmetric = 0;
975a328e 6745 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6746 bgp_static->label_index = label_index;
718e3744 6747
e2a86ad9 6748 if (rmap) {
0a22ddfb
QY
6749 XFREE(MTYPE_ROUTE_MAP_NAME,
6750 bgp_static->rmap.name);
b4897fa5 6751 route_map_counter_decrement(
6752 bgp_static->rmap.map);
e2a86ad9
DS
6753 bgp_static->rmap.name =
6754 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6755 bgp_static->rmap.map =
6756 route_map_lookup_by_name(rmap);
b4897fa5 6757 route_map_counter_increment(
6758 bgp_static->rmap.map);
e2a86ad9 6759 }
9bcb3eef 6760 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6761 }
d62a17ae 6762
e2a86ad9
DS
6763 bgp_static->valid = 1;
6764 if (need_update)
6765 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6766
e2a86ad9
DS
6767 if (!bgp_static->backdoor)
6768 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6769 }
d62a17ae 6770
585f1adc 6771 return CMD_SUCCESS;
d62a17ae 6772}
6773
6774void bgp_static_add(struct bgp *bgp)
6775{
6776 afi_t afi;
6777 safi_t safi;
9bcb3eef
DS
6778 struct bgp_dest *dest;
6779 struct bgp_dest *rm;
d62a17ae 6780 struct bgp_table *table;
6781 struct bgp_static *bgp_static;
6782
47fc6261 6783 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6784 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6785 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6786 dest = bgp_route_next(dest)) {
6787 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6788 continue;
ea47320b 6789
05c7a1cc
QY
6790 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6791 || (safi == SAFI_EVPN)) {
9bcb3eef 6792 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6793
6794 for (rm = bgp_table_top(table); rm;
6795 rm = bgp_route_next(rm)) {
a78beeb5 6796 bgp_static =
9bcb3eef 6797 bgp_dest_get_bgp_static_info(
5a8ba9fc 6798 rm);
9bcb3eef
DS
6799 bgp_static_update_safi(
6800 bgp, bgp_dest_get_prefix(rm),
6801 bgp_static, afi, safi);
d62a17ae 6802 }
05c7a1cc 6803 } else {
5a8ba9fc 6804 bgp_static_update(
9bcb3eef
DS
6805 bgp, bgp_dest_get_prefix(dest),
6806 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6807 safi);
ea47320b 6808 }
05c7a1cc 6809 }
47fc6261 6810 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6811}
6812
718e3744 6813/* Called from bgp_delete(). Delete all static routes from the BGP
6814 instance. */
d62a17ae 6815void bgp_static_delete(struct bgp *bgp)
6816{
6817 afi_t afi;
6818 safi_t safi;
9bcb3eef
DS
6819 struct bgp_dest *dest;
6820 struct bgp_dest *rm;
d62a17ae 6821 struct bgp_table *table;
6822 struct bgp_static *bgp_static;
6823
05c7a1cc 6824 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6825 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6826 dest = bgp_route_next(dest)) {
6827 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6828 continue;
ea47320b 6829
05c7a1cc
QY
6830 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6831 || (safi == SAFI_EVPN)) {
9bcb3eef 6832 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6833
6834 for (rm = bgp_table_top(table); rm;
6835 rm = bgp_route_next(rm)) {
a78beeb5 6836 bgp_static =
9bcb3eef 6837 bgp_dest_get_bgp_static_info(
5a8ba9fc 6838 rm);
c7d14ba6
PG
6839 if (!bgp_static)
6840 continue;
6841
05c7a1cc 6842 bgp_static_withdraw_safi(
9bcb3eef 6843 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6844 AFI_IP, safi,
6845 (struct prefix_rd *)
9bcb3eef
DS
6846 bgp_dest_get_prefix(
6847 dest));
ea47320b 6848 bgp_static_free(bgp_static);
811c6797 6849 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6850 NULL);
811c6797 6851 bgp_dest_unlock_node(rm);
d62a17ae 6852 }
05c7a1cc 6853 } else {
9bcb3eef 6854 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6855 bgp_static_withdraw(bgp,
9bcb3eef 6856 bgp_dest_get_prefix(dest),
b54892e0 6857 afi, safi);
05c7a1cc 6858 bgp_static_free(bgp_static);
9bcb3eef
DS
6859 bgp_dest_set_bgp_static_info(dest, NULL);
6860 bgp_dest_unlock_node(dest);
ea47320b 6861 }
05c7a1cc 6862 }
d62a17ae 6863}
6864
6865void bgp_static_redo_import_check(struct bgp *bgp)
6866{
6867 afi_t afi;
6868 safi_t safi;
9bcb3eef
DS
6869 struct bgp_dest *dest;
6870 struct bgp_dest *rm;
d62a17ae 6871 struct bgp_table *table;
6872 struct bgp_static *bgp_static;
6873
6874 /* Use this flag to force reprocessing of the route */
892fedb6 6875 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6876 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6877 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6878 dest = bgp_route_next(dest)) {
6879 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6880 continue;
ea47320b 6881
05c7a1cc
QY
6882 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6883 || (safi == SAFI_EVPN)) {
9bcb3eef 6884 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6885
6886 for (rm = bgp_table_top(table); rm;
6887 rm = bgp_route_next(rm)) {
a78beeb5 6888 bgp_static =
9bcb3eef 6889 bgp_dest_get_bgp_static_info(
5a8ba9fc 6890 rm);
9bcb3eef
DS
6891 bgp_static_update_safi(
6892 bgp, bgp_dest_get_prefix(rm),
6893 bgp_static, afi, safi);
d62a17ae 6894 }
05c7a1cc 6895 } else {
9bcb3eef
DS
6896 bgp_static = bgp_dest_get_bgp_static_info(dest);
6897 bgp_static_update(bgp,
6898 bgp_dest_get_prefix(dest),
6899 bgp_static, afi, safi);
ea47320b 6900 }
05c7a1cc
QY
6901 }
6902 }
892fedb6 6903 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6904}
6905
6906static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6907 safi_t safi)
6908{
6909 struct bgp_table *table;
9bcb3eef 6910 struct bgp_dest *dest;
40381db7 6911 struct bgp_path_info *pi;
d62a17ae 6912
dfb6fd1d
NT
6913 /* Do not install the aggregate route if BGP is in the
6914 * process of termination.
6915 */
892fedb6
DA
6916 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6917 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6918 return;
6919
d62a17ae 6920 table = bgp->rib[afi][safi];
9bcb3eef
DS
6921 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6922 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6923 if (pi->peer == bgp->peer_self
6924 && ((pi->type == ZEBRA_ROUTE_BGP
6925 && pi->sub_type == BGP_ROUTE_STATIC)
6926 || (pi->type != ZEBRA_ROUTE_BGP
6927 && pi->sub_type
d62a17ae 6928 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6929 bgp_aggregate_decrement(
6930 bgp, bgp_dest_get_prefix(dest), pi, afi,
6931 safi);
40381db7 6932 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6933 bgp_path_info_delete(dest, pi);
6934 bgp_process(bgp, dest, afi, safi);
d62a17ae 6935 }
6936 }
6937 }
ad4cbda1 6938}
6939
6940/*
6941 * Purge all networks and redistributed routes from routing table.
6942 * Invoked upon the instance going down.
6943 */
d62a17ae 6944void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6945{
d62a17ae 6946 afi_t afi;
6947 safi_t safi;
ad4cbda1 6948
05c7a1cc
QY
6949 FOREACH_AFI_SAFI (afi, safi)
6950 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6951}
6952
137446f9
LB
6953/*
6954 * gpz 110624
6955 * Currently this is used to set static routes for VPN and ENCAP.
6956 * I think it can probably be factored with bgp_static_set.
6957 */
d62a17ae 6958int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6959 const char *ip_str, const char *rd_str,
6960 const char *label_str, const char *rmap_str,
6961 int evpn_type, const char *esi, const char *gwip,
6962 const char *ethtag, const char *routermac)
6963{
6964 VTY_DECLVAR_CONTEXT(bgp, bgp);
6965 int ret;
6966 struct prefix p;
6967 struct prefix_rd prd;
9bcb3eef
DS
6968 struct bgp_dest *pdest;
6969 struct bgp_dest *dest;
d62a17ae 6970 struct bgp_table *table;
6971 struct bgp_static *bgp_static;
6972 mpls_label_t label = MPLS_INVALID_LABEL;
6973 struct prefix gw_ip;
6974
6975 /* validate ip prefix */
6976 ret = str2prefix(ip_str, &p);
6977 if (!ret) {
6978 vty_out(vty, "%% Malformed prefix\n");
6979 return CMD_WARNING_CONFIG_FAILED;
6980 }
6981 apply_mask(&p);
6982 if ((afi == AFI_L2VPN)
6983 && (bgp_build_evpn_prefix(evpn_type,
6984 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6985 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6986 return CMD_WARNING_CONFIG_FAILED;
6987 }
718e3744 6988
d62a17ae 6989 ret = str2prefix_rd(rd_str, &prd);
6990 if (!ret) {
6991 vty_out(vty, "%% Malformed rd\n");
6992 return CMD_WARNING_CONFIG_FAILED;
6993 }
718e3744 6994
d62a17ae 6995 if (label_str) {
6996 unsigned long label_val;
6997 label_val = strtoul(label_str, NULL, 10);
6998 encode_label(label_val, &label);
6999 }
9bedbb1e 7000
d62a17ae 7001 if (safi == SAFI_EVPN) {
7002 if (esi && str2esi(esi, NULL) == 0) {
7003 vty_out(vty, "%% Malformed ESI\n");
7004 return CMD_WARNING_CONFIG_FAILED;
7005 }
7006 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7007 vty_out(vty, "%% Malformed Router MAC\n");
7008 return CMD_WARNING_CONFIG_FAILED;
7009 }
7010 if (gwip) {
6006b807 7011 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7012 ret = str2prefix(gwip, &gw_ip);
7013 if (!ret) {
7014 vty_out(vty, "%% Malformed GatewayIp\n");
7015 return CMD_WARNING_CONFIG_FAILED;
7016 }
7017 if ((gw_ip.family == AF_INET
3714a385 7018 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7019 (struct prefix_evpn *)&p))
7020 || (gw_ip.family == AF_INET6
3714a385 7021 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7022 (struct prefix_evpn *)&p))) {
7023 vty_out(vty,
7024 "%% GatewayIp family differs with IP prefix\n");
7025 return CMD_WARNING_CONFIG_FAILED;
7026 }
7027 }
7028 }
9bcb3eef
DS
7029 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7030 if (!bgp_dest_has_bgp_path_info_data(pdest))
7031 bgp_dest_set_bgp_table_info(pdest,
67009e22 7032 bgp_table_init(bgp, afi, safi));
9bcb3eef 7033 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7034
9bcb3eef 7035 dest = bgp_node_get(table, &p);
d62a17ae 7036
9bcb3eef 7037 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7038 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7039 bgp_dest_unlock_node(dest);
d62a17ae 7040 } else {
7041 /* New configuration. */
7042 bgp_static = bgp_static_new();
7043 bgp_static->backdoor = 0;
7044 bgp_static->valid = 0;
7045 bgp_static->igpmetric = 0;
975a328e 7046 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7047 bgp_static->label = label;
7048 bgp_static->prd = prd;
7049
7050 if (rmap_str) {
0a22ddfb 7051 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7052 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7053 bgp_static->rmap.name =
7054 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7055 bgp_static->rmap.map =
7056 route_map_lookup_by_name(rmap_str);
b4897fa5 7057 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7058 }
718e3744 7059
d62a17ae 7060 if (safi == SAFI_EVPN) {
7061 if (esi) {
7062 bgp_static->eth_s_id =
7063 XCALLOC(MTYPE_ATTR,
0a50c248 7064 sizeof(esi_t));
d62a17ae 7065 str2esi(esi, bgp_static->eth_s_id);
7066 }
7067 if (routermac) {
7068 bgp_static->router_mac =
28328ea9 7069 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7070 (void)prefix_str2mac(routermac,
7071 bgp_static->router_mac);
d62a17ae 7072 }
7073 if (gwip)
7074 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7075 }
9bcb3eef 7076 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7077
d62a17ae 7078 bgp_static->valid = 1;
7079 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7080 }
718e3744 7081
d62a17ae 7082 return CMD_SUCCESS;
718e3744 7083}
7084
7085/* Configure static BGP network. */
d62a17ae 7086int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7087 const char *ip_str, const char *rd_str,
7088 const char *label_str, int evpn_type, const char *esi,
7089 const char *gwip, const char *ethtag)
7090{
7091 VTY_DECLVAR_CONTEXT(bgp, bgp);
7092 int ret;
7093 struct prefix p;
7094 struct prefix_rd prd;
9bcb3eef
DS
7095 struct bgp_dest *pdest;
7096 struct bgp_dest *dest;
d62a17ae 7097 struct bgp_table *table;
7098 struct bgp_static *bgp_static;
7099 mpls_label_t label = MPLS_INVALID_LABEL;
7100
7101 /* Convert IP prefix string to struct prefix. */
7102 ret = str2prefix(ip_str, &p);
7103 if (!ret) {
7104 vty_out(vty, "%% Malformed prefix\n");
7105 return CMD_WARNING_CONFIG_FAILED;
7106 }
7107 apply_mask(&p);
7108 if ((afi == AFI_L2VPN)
7109 && (bgp_build_evpn_prefix(evpn_type,
7110 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7111 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7112 return CMD_WARNING_CONFIG_FAILED;
7113 }
7114 ret = str2prefix_rd(rd_str, &prd);
7115 if (!ret) {
7116 vty_out(vty, "%% Malformed rd\n");
7117 return CMD_WARNING_CONFIG_FAILED;
7118 }
718e3744 7119
d62a17ae 7120 if (label_str) {
7121 unsigned long label_val;
7122 label_val = strtoul(label_str, NULL, 10);
7123 encode_label(label_val, &label);
7124 }
718e3744 7125
9bcb3eef
DS
7126 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7127 if (!bgp_dest_has_bgp_path_info_data(pdest))
7128 bgp_dest_set_bgp_table_info(pdest,
67009e22 7129 bgp_table_init(bgp, afi, safi));
d62a17ae 7130 else
9bcb3eef
DS
7131 bgp_dest_unlock_node(pdest);
7132 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7133
9bcb3eef 7134 dest = bgp_node_lookup(table, &p);
6b0655a2 7135
9bcb3eef 7136 if (dest) {
d62a17ae 7137 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7138
9bcb3eef 7139 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7140 bgp_static_free(bgp_static);
9bcb3eef
DS
7141 bgp_dest_set_bgp_static_info(dest, NULL);
7142 bgp_dest_unlock_node(dest);
7143 bgp_dest_unlock_node(dest);
d62a17ae 7144 } else
7145 vty_out(vty, "%% Can't find the route\n");
7146
7147 return CMD_SUCCESS;
7148}
7149
7150static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7151 const char *rmap_name)
7152{
7153 VTY_DECLVAR_CONTEXT(bgp, bgp);
7154 struct bgp_rmap *rmap;
7155
7156 rmap = &bgp->table_map[afi][safi];
7157 if (rmap_name) {
0a22ddfb 7158 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7159 route_map_counter_decrement(rmap->map);
d62a17ae 7160 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7161 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7162 route_map_counter_increment(rmap->map);
d62a17ae 7163 } else {
0a22ddfb 7164 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7165 route_map_counter_decrement(rmap->map);
d62a17ae 7166 rmap->map = NULL;
7167 }
73ac8160 7168
d62a17ae 7169 if (bgp_fibupd_safi(safi))
7170 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7171
d62a17ae 7172 return CMD_SUCCESS;
73ac8160
DS
7173}
7174
d62a17ae 7175static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7176 const char *rmap_name)
73ac8160 7177{
d62a17ae 7178 VTY_DECLVAR_CONTEXT(bgp, bgp);
7179 struct bgp_rmap *rmap;
73ac8160 7180
d62a17ae 7181 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7182 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7183 route_map_counter_decrement(rmap->map);
d62a17ae 7184 rmap->map = NULL;
73ac8160 7185
d62a17ae 7186 if (bgp_fibupd_safi(safi))
7187 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7188
d62a17ae 7189 return CMD_SUCCESS;
73ac8160
DS
7190}
7191
2b791107 7192void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7193 safi_t safi)
73ac8160 7194{
d62a17ae 7195 if (bgp->table_map[afi][safi].name) {
d62a17ae 7196 vty_out(vty, " table-map %s\n",
7197 bgp->table_map[afi][safi].name);
7198 }
73ac8160
DS
7199}
7200
73ac8160
DS
7201DEFUN (bgp_table_map,
7202 bgp_table_map_cmd,
7203 "table-map WORD",
7204 "BGP table to RIB route download filter\n"
7205 "Name of the route map\n")
7206{
d62a17ae 7207 int idx_word = 1;
7208 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7209 argv[idx_word]->arg);
73ac8160
DS
7210}
7211DEFUN (no_bgp_table_map,
7212 no_bgp_table_map_cmd,
7213 "no table-map WORD",
3a2d747c 7214 NO_STR
73ac8160
DS
7215 "BGP table to RIB route download filter\n"
7216 "Name of the route map\n")
7217{
d62a17ae 7218 int idx_word = 2;
7219 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7220 argv[idx_word]->arg);
73ac8160
DS
7221}
7222
585f1adc
IR
7223DEFPY(bgp_network,
7224 bgp_network_cmd,
7225 "[no] network \
7226 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7227 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7228 backdoor$backdoor}]",
7229 NO_STR
7230 "Specify a network to announce via BGP\n"
7231 "IPv4 prefix\n"
7232 "Network number\n"
7233 "Network mask\n"
7234 "Network mask\n"
7235 "Route-map to modify the attributes\n"
7236 "Name of the route map\n"
7237 "Label index to associate with the prefix\n"
7238 "Label index value\n"
7239 "Specify a BGP backdoor route\n")
7240{
7241 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7242
7243 if (address_str) {
7244 int ret;
718e3744 7245
e2a86ad9 7246 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7247 addr_prefix_str,
7248 sizeof(addr_prefix_str));
e2a86ad9
DS
7249 if (!ret) {
7250 vty_out(vty, "%% Inconsistent address and mask\n");
7251 return CMD_WARNING_CONFIG_FAILED;
7252 }
d62a17ae 7253 }
718e3744 7254
585f1adc
IR
7255 return bgp_static_set(
7256 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7257 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7258 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7259}
7260
585f1adc
IR
7261DEFPY(ipv6_bgp_network,
7262 ipv6_bgp_network_cmd,
7263 "[no] network X:X::X:X/M$prefix \
70dd370f 7264 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7265 NO_STR
7266 "Specify a network to announce via BGP\n"
7267 "IPv6 prefix\n"
7268 "Route-map to modify the attributes\n"
7269 "Name of the route map\n"
7270 "Label index to associate with the prefix\n"
7271 "Label index value\n")
37a87b8f 7272{
585f1adc
IR
7273 return bgp_static_set(
7274 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7275 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7276}
7277
d62a17ae 7278static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7279{
d62a17ae 7280 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7281}
7282
d62a17ae 7283static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7284{
365ab2e7
RZ
7285 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7286 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7287 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7288 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7289 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7290}
718e3744 7291
365ab2e7
RZ
7292/**
7293 * Helper function to avoid repeated code: prepare variables for a
7294 * `route_map_apply` call.
7295 *
7296 * \returns `true` on route map match, otherwise `false`.
7297 */
7298static bool aggr_suppress_map_test(struct bgp *bgp,
7299 struct bgp_aggregate *aggregate,
7300 struct bgp_path_info *pi)
7301{
7302 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7303 route_map_result_t rmr = RMAP_DENYMATCH;
7304 struct bgp_path_info rmap_path = {};
7305 struct attr attr = {};
7306
7307 /* No route map entries created, just don't match. */
7308 if (aggregate->suppress_map == NULL)
7309 return false;
7310
7311 /* Call route map matching and return result. */
7312 attr.aspath = aspath_empty();
7313 rmap_path.peer = bgp->peer_self;
7314 rmap_path.attr = &attr;
7315
7316 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7317 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7318 bgp->peer_self->rmap_type = 0;
7319
7320 bgp_attr_flush(&attr);
afb254d7 7321 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7322
7323 return rmr == RMAP_PERMITMATCH;
7324}
7325
4056a5f6
RZ
7326/** Test whether the aggregation has suppressed this path or not. */
7327static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7328 struct bgp_path_info *pi)
7329{
7330 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7331 return false;
7332
7333 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7334}
7335
7336/**
7337 * Suppress this path and keep the reference.
7338 *
7339 * \returns `true` if needs processing otherwise `false`.
7340 */
7341static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7342 struct bgp_path_info *pi)
7343{
7344 struct bgp_path_info_extra *pie;
7345
7346 /* Path is already suppressed by this aggregation. */
7347 if (aggr_suppress_exists(aggregate, pi))
7348 return false;
7349
7350 pie = bgp_path_info_extra_get(pi);
7351
7352 /* This is the first suppression, allocate memory and list it. */
7353 if (pie->aggr_suppressors == NULL)
7354 pie->aggr_suppressors = list_new();
7355
7356 listnode_add(pie->aggr_suppressors, aggregate);
7357
7358 /* Only mark for processing if suppressed. */
7359 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7360 if (BGP_DEBUG(update, UPDATE_OUT))
7361 zlog_debug("aggregate-address suppressing: %pFX",
7362 bgp_dest_get_prefix(pi->net));
7363
4056a5f6
RZ
7364 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7365 return true;
7366 }
7367
7368 return false;
7369}
7370
7371/**
7372 * Unsuppress this path and remove the reference.
7373 *
7374 * \returns `true` if needs processing otherwise `false`.
7375 */
7376static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7377 struct bgp_path_info *pi)
7378{
7379 /* Path wasn't suppressed. */
7380 if (!aggr_suppress_exists(aggregate, pi))
7381 return false;
7382
7383 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7384
7385 /* Unsuppress and free extra memory if last item. */
7386 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7387 if (BGP_DEBUG(update, UPDATE_OUT))
7388 zlog_debug("aggregate-address unsuppressing: %pFX",
7389 bgp_dest_get_prefix(pi->net));
7390
4056a5f6
RZ
7391 list_delete(&pi->extra->aggr_suppressors);
7392 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7393 return true;
7394 }
7395
7396 return false;
7397}
7398
3dc339cd
DA
7399static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7400 struct aspath *aspath,
7401 struct community *comm,
7402 struct ecommunity *ecomm,
7403 struct lcommunity *lcomm)
eaaf8adb
DS
7404{
7405 static struct aspath *ae = NULL;
7406
7407 if (!ae)
7408 ae = aspath_empty();
7409
40381db7 7410 if (!pi)
3dc339cd 7411 return false;
eaaf8adb 7412
40381db7 7413 if (origin != pi->attr->origin)
3dc339cd 7414 return false;
eaaf8adb 7415
40381db7 7416 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7417 return false;
29f7d023 7418
9a706b42 7419 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7420 return false;
eaaf8adb 7421
b53e67a3 7422 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7423 return false;
eaaf8adb 7424
1bcf3a96 7425 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7426 return false;
dd18c5a9 7427
40381db7 7428 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7429 return false;
7ce8a8e0 7430
3dc339cd 7431 return true;
eaaf8adb
DS
7432}
7433
5f040085
DS
7434static void bgp_aggregate_install(
7435 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7436 uint8_t origin, struct aspath *aspath, struct community *community,
7437 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7438 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7439{
9bcb3eef 7440 struct bgp_dest *dest;
c701010e 7441 struct bgp_table *table;
6f94b685 7442 struct bgp_path_info *pi, *orig, *new;
20894f50 7443 struct attr *attr;
c701010e
DS
7444
7445 table = bgp->rib[afi][safi];
7446
9bcb3eef 7447 dest = bgp_node_get(table, p);
eaaf8adb 7448
9bcb3eef 7449 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7450 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7451 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7452 break;
7453
6aabb15d
RZ
7454 /*
7455 * If we have paths with different MEDs, then don't install
7456 * (or uninstall) the aggregate route.
7457 */
7458 if (aggregate->match_med && aggregate->med_mismatched)
7459 goto uninstall_aggregate_route;
7460
c701010e 7461 if (aggregate->count > 0) {
eaaf8adb
DS
7462 /*
7463 * If the aggregate information has not changed
7464 * no need to re-install it again.
7465 */
6f94b685 7466 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7467 ecommunity, lcommunity)) {
9bcb3eef 7468 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7469
7470 if (aspath)
7471 aspath_free(aspath);
7472 if (community)
3c1f53de 7473 community_free(&community);
3da2cc32
DS
7474 if (ecommunity)
7475 ecommunity_free(&ecommunity);
dd18c5a9
DS
7476 if (lcommunity)
7477 lcommunity_free(&lcommunity);
eaaf8adb
DS
7478
7479 return;
7480 }
7481
7482 /*
7483 * Mark the old as unusable
7484 */
40381db7 7485 if (pi)
9bcb3eef 7486 bgp_path_info_delete(dest, pi);
eaaf8adb 7487
20894f50
DA
7488 attr = bgp_attr_aggregate_intern(
7489 bgp, origin, aspath, community, ecommunity, lcommunity,
7490 aggregate, atomic_aggregate, p);
7491
7492 if (!attr) {
8c0044f3 7493 bgp_dest_unlock_node(dest);
20894f50 7494 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7495 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7496 zlog_debug("%s: %pFX null attribute", __func__,
7497 p);
20894f50
DA
7498 return;
7499 }
7500
3da2cc32 7501 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7502 bgp->peer_self, attr, dest);
20894f50 7503
1defdda8 7504 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7505
9bcb3eef
DS
7506 bgp_path_info_add(dest, new);
7507 bgp_process(bgp, dest, afi, safi);
c701010e 7508 } else {
6aabb15d 7509 uninstall_aggregate_route:
6f94b685 7510 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7511 if (pi->peer == bgp->peer_self
7512 && pi->type == ZEBRA_ROUTE_BGP
7513 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7514 break;
7515
7516 /* Withdraw static BGP route from routing table. */
40381db7 7517 if (pi) {
9bcb3eef
DS
7518 bgp_path_info_delete(dest, pi);
7519 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7520 }
7521 }
7522
9bcb3eef 7523 bgp_dest_unlock_node(dest);
c701010e
DS
7524}
7525
6aabb15d
RZ
7526/**
7527 * Check if the current path has different MED than other known paths.
7528 *
7529 * \returns `true` if the MED matched the others else `false`.
7530 */
7531static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7532 struct bgp *bgp, struct bgp_path_info *pi)
7533{
7534 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7535
7536 /* This is the first route being analyzed. */
7537 if (!aggregate->med_initialized) {
7538 aggregate->med_initialized = true;
7539 aggregate->med_mismatched = false;
7540 aggregate->med_matched_value = cur_med;
7541 } else {
7542 /* Check if routes with different MED showed up. */
7543 if (cur_med != aggregate->med_matched_value)
7544 aggregate->med_mismatched = true;
7545 }
7546
7547 return !aggregate->med_mismatched;
7548}
7549
7550/**
7551 * Initializes and tests all routes in the aggregate address path for MED
7552 * values.
7553 *
7554 * \returns `true` if all MEDs are the same otherwise `false`.
7555 */
7556static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7557 struct bgp *bgp, const struct prefix *p,
7558 afi_t afi, safi_t safi)
7559{
7560 struct bgp_table *table = bgp->rib[afi][safi];
7561 const struct prefix *dest_p;
7562 struct bgp_dest *dest, *top;
7563 struct bgp_path_info *pi;
7564 bool med_matched = true;
7565
7566 aggregate->med_initialized = false;
7567
7568 top = bgp_node_get(table, p);
7569 for (dest = bgp_node_get(table, p); dest;
7570 dest = bgp_route_next_until(dest, top)) {
7571 dest_p = bgp_dest_get_prefix(dest);
7572 if (dest_p->prefixlen <= p->prefixlen)
7573 continue;
7574
7575 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7576 if (BGP_PATH_HOLDDOWN(pi))
7577 continue;
7578 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7579 continue;
7580 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7581 med_matched = false;
7582 break;
7583 }
7584 }
7585 if (!med_matched)
7586 break;
7587 }
7588 bgp_dest_unlock_node(top);
7589
7590 return med_matched;
7591}
7592
7593/**
7594 * Toggles the route suppression status for this aggregate address
7595 * configuration.
7596 */
4056a5f6
RZ
7597void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7598 struct bgp *bgp, const struct prefix *p,
7599 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7600{
7601 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7602 const struct prefix *dest_p;
7603 struct bgp_dest *dest, *top;
7604 struct bgp_path_info *pi;
7605 bool toggle_suppression;
7606
7607 /* We've found a different MED we must revert any suppressed routes. */
7608 top = bgp_node_get(table, p);
7609 for (dest = bgp_node_get(table, p); dest;
7610 dest = bgp_route_next_until(dest, top)) {
7611 dest_p = bgp_dest_get_prefix(dest);
7612 if (dest_p->prefixlen <= p->prefixlen)
7613 continue;
7614
7615 toggle_suppression = false;
7616 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7617 if (BGP_PATH_HOLDDOWN(pi))
7618 continue;
7619 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7620 continue;
7621
6aabb15d
RZ
7622 /* We are toggling suppression back. */
7623 if (suppress) {
6aabb15d 7624 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7625 if (aggr_suppress_path(aggregate, pi))
7626 toggle_suppression = true;
6aabb15d
RZ
7627 continue;
7628 }
7629
6aabb15d 7630 /* Install route if there is no more suppression. */
4056a5f6 7631 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7632 toggle_suppression = true;
6aabb15d
RZ
7633 }
7634
7635 if (toggle_suppression)
7636 bgp_process(bgp, dest, afi, safi);
7637 }
7638 bgp_dest_unlock_node(top);
7639}
7640
7641/**
7642 * Aggregate address MED matching incremental test: this function is called
7643 * when the initial aggregation occurred and we are only testing a single
7644 * new path.
7645 *
7646 * In addition to testing and setting the MED validity it also installs back
7647 * suppressed routes (if summary is configured).
7648 *
7649 * Must not be called in `bgp_aggregate_route`.
7650 */
7651static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7652 struct bgp *bgp, const struct prefix *p,
7653 afi_t afi, safi_t safi,
f66624f5 7654 struct bgp_path_info *pi)
6aabb15d
RZ
7655{
7656 /* MED matching disabled. */
7657 if (!aggregate->match_med)
7658 return;
7659
f66624f5
DA
7660 /* Aggregation with different MED, recheck if we have got equal MEDs
7661 * now.
6aabb15d 7662 */
f66624f5
DA
7663 if (aggregate->med_mismatched &&
7664 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7665 aggregate->summary_only)
7666 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7667 true);
7668 else
6aabb15d
RZ
7669 bgp_aggregate_med_match(aggregate, bgp, pi);
7670
7671 /* No mismatches, just quit. */
7672 if (!aggregate->med_mismatched)
7673 return;
7674
7675 /* Route summarization is disabled. */
7676 if (!aggregate->summary_only)
7677 return;
7678
7679 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7680}
7681
b5d58c32 7682/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7683void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7684 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7685{
7686 struct bgp_table *table;
9bcb3eef
DS
7687 struct bgp_dest *top;
7688 struct bgp_dest *dest;
d7c0a89a 7689 uint8_t origin;
d62a17ae 7690 struct aspath *aspath = NULL;
d62a17ae 7691 struct community *community = NULL;
3da2cc32 7692 struct ecommunity *ecommunity = NULL;
dd18c5a9 7693 struct lcommunity *lcommunity = NULL;
40381db7 7694 struct bgp_path_info *pi;
d62a17ae 7695 unsigned long match = 0;
d7c0a89a 7696 uint8_t atomic_aggregate = 0;
d62a17ae 7697
9f822fa2
S
7698 /* If the bgp instance is being deleted or self peer is deleted
7699 * then do not create aggregate route
7700 */
892fedb6
DA
7701 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7702 || (bgp->peer_self == NULL))
9f822fa2
S
7703 return;
7704
6aabb15d
RZ
7705 /* Initialize and test routes for MED difference. */
7706 if (aggregate->match_med)
7707 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7708
4056a5f6
RZ
7709 /*
7710 * Reset aggregate count: we might've been called from route map
7711 * update so in that case we must retest all more specific routes.
7712 *
7713 * \see `bgp_route_map_process_update`.
7714 */
7715 aggregate->count = 0;
7716 aggregate->incomplete_origin_count = 0;
7717 aggregate->incomplete_origin_count = 0;
7718 aggregate->egp_origin_count = 0;
7719
d62a17ae 7720 /* ORIGIN attribute: If at least one route among routes that are
7721 aggregated has ORIGIN with the value INCOMPLETE, then the
7722 aggregated route must have the ORIGIN attribute with the value
7723 INCOMPLETE. Otherwise, if at least one route among routes that
7724 are aggregated has ORIGIN with the value EGP, then the aggregated
7725 route must have the origin attribute with the value EGP. In all
7726 other case the value of the ORIGIN attribute of the aggregated
7727 route is INTERNAL. */
7728 origin = BGP_ORIGIN_IGP;
718e3744 7729
d62a17ae 7730 table = bgp->rib[afi][safi];
718e3744 7731
d62a17ae 7732 top = bgp_node_get(table, p);
9bcb3eef
DS
7733 for (dest = bgp_node_get(table, p); dest;
7734 dest = bgp_route_next_until(dest, top)) {
7735 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7736
9bcb3eef 7737 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7738 continue;
d62a17ae 7739
a77e2f4b
S
7740 /* If suppress fib is enabled and route not installed
7741 * in FIB, skip the route
7742 */
7743 if (!bgp_check_advertise(bgp, dest))
7744 continue;
7745
c2ff8b3e 7746 match = 0;
d62a17ae 7747
9bcb3eef 7748 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7749 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7750 continue;
718e3744 7751
40381db7 7752 if (pi->attr->flag
c2ff8b3e
DS
7753 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7754 atomic_aggregate = 1;
d62a17ae 7755
40381db7 7756 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7757 continue;
d62a17ae 7758
f273fef1
DS
7759 /*
7760 * summary-only aggregate route suppress
7761 * aggregated route announcements.
6aabb15d
RZ
7762 *
7763 * MED matching:
7764 * Don't create summaries if MED didn't match
7765 * otherwise neither the specific routes and the
7766 * aggregation will be announced.
f273fef1 7767 */
6aabb15d
RZ
7768 if (aggregate->summary_only
7769 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7770 if (aggr_suppress_path(aggregate, pi))
7771 match++;
d62a17ae 7772 }
c2ff8b3e 7773
365ab2e7
RZ
7774 /*
7775 * Suppress more specific routes that match the route
7776 * map results.
7777 *
7778 * MED matching:
7779 * Don't suppress routes if MED matching is enabled and
7780 * it mismatched otherwise we might end up with no
7781 * routes for this path.
7782 */
7783 if (aggregate->suppress_map_name
7784 && AGGREGATE_MED_VALID(aggregate)
7785 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7786 if (aggr_suppress_path(aggregate, pi))
7787 match++;
d62a17ae 7788 }
c2ff8b3e
DS
7789
7790 aggregate->count++;
7791
f273fef1
DS
7792 /*
7793 * If at least one route among routes that are
7794 * aggregated has ORIGIN with the value INCOMPLETE,
7795 * then the aggregated route MUST have the ORIGIN
7796 * attribute with the value INCOMPLETE. Otherwise, if
7797 * at least one route among routes that are aggregated
7798 * has ORIGIN with the value EGP, then the aggregated
7799 * route MUST have the ORIGIN attribute with the value
7800 * EGP.
7801 */
fc968841
NT
7802 switch (pi->attr->origin) {
7803 case BGP_ORIGIN_INCOMPLETE:
7804 aggregate->incomplete_origin_count++;
7805 break;
7806 case BGP_ORIGIN_EGP:
7807 aggregate->egp_origin_count++;
7808 break;
7809 default:
7810 /*Do nothing.
7811 */
7812 break;
7813 }
c2ff8b3e
DS
7814
7815 if (!aggregate->as_set)
7816 continue;
7817
f273fef1
DS
7818 /*
7819 * as-set aggregate route generate origin, as path,
7820 * and community aggregation.
7821 */
fc968841
NT
7822 /* Compute aggregate route's as-path.
7823 */
ef51a7d8 7824 bgp_compute_aggregate_aspath_hash(aggregate,
7825 pi->attr->aspath);
c2ff8b3e 7826
fc968841
NT
7827 /* Compute aggregate route's community.
7828 */
9a706b42 7829 if (bgp_attr_get_community(pi->attr))
21fec674 7830 bgp_compute_aggregate_community_hash(
9a706b42
DA
7831 aggregate,
7832 bgp_attr_get_community(pi->attr));
dd18c5a9 7833
fc968841
NT
7834 /* Compute aggregate route's extended community.
7835 */
b53e67a3 7836 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7837 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7838 aggregate,
7839 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7840
7841 /* Compute aggregate route's large community.
7842 */
1bcf3a96 7843 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7844 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7845 aggregate,
7846 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7847 }
c2ff8b3e 7848 if (match)
9bcb3eef 7849 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7850 }
21fec674 7851 if (aggregate->as_set) {
ef51a7d8 7852 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7853 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7854 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7855 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7856 }
7857
f1eb1f05 7858
9bcb3eef 7859 bgp_dest_unlock_node(top);
718e3744 7860
718e3744 7861
fc968841
NT
7862 if (aggregate->incomplete_origin_count > 0)
7863 origin = BGP_ORIGIN_INCOMPLETE;
7864 else if (aggregate->egp_origin_count > 0)
7865 origin = BGP_ORIGIN_EGP;
d62a17ae 7866
229757f1
DA
7867 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7868 origin = aggregate->origin;
7869
fc968841
NT
7870 if (aggregate->as_set) {
7871 if (aggregate->aspath)
7872 /* Retrieve aggregate route's as-path.
7873 */
7874 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7875
fc968841
NT
7876 if (aggregate->community)
7877 /* Retrieve aggregate route's community.
7878 */
7879 community = community_dup(aggregate->community);
3da2cc32 7880
fc968841
NT
7881 if (aggregate->ecommunity)
7882 /* Retrieve aggregate route's ecommunity.
7883 */
7884 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7885
fc968841
NT
7886 if (aggregate->lcommunity)
7887 /* Retrieve aggregate route's lcommunity.
7888 */
7889 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7890 }
718e3744 7891
c701010e 7892 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7893 ecommunity, lcommunity, atomic_aggregate,
7894 aggregate);
718e3744 7895}
7896
5f040085
DS
7897void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7898 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7899{
7900 struct bgp_table *table;
9bcb3eef
DS
7901 struct bgp_dest *top;
7902 struct bgp_dest *dest;
40381db7 7903 struct bgp_path_info *pi;
3b7db173
DS
7904 unsigned long match;
7905
7906 table = bgp->rib[afi][safi];
7907
7908 /* If routes exists below this node, generate aggregate routes. */
7909 top = bgp_node_get(table, p);
9bcb3eef
DS
7910 for (dest = bgp_node_get(table, p); dest;
7911 dest = bgp_route_next_until(dest, top)) {
7912 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7913
9bcb3eef 7914 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7915 continue;
7916 match = 0;
7917
9bcb3eef 7918 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7919 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7920 continue;
7921
40381db7 7922 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7923 continue;
7924
92b175bd
RZ
7925 /*
7926 * This route is suppressed: attempt to unsuppress it.
7927 *
7928 * `aggr_unsuppress_path` will fail if this particular
7929 * aggregate route was not the suppressor.
7930 */
7931 if (pi->extra && pi->extra->aggr_suppressors &&
7932 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7933 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7934 match++;
3b7db173 7935 }
365ab2e7 7936
3b7db173 7937 aggregate->count--;
fc968841
NT
7938
7939 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7940 aggregate->incomplete_origin_count--;
7941 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7942 aggregate->egp_origin_count--;
7943
7944 if (aggregate->as_set) {
7945 /* Remove as-path from aggregate.
7946 */
ef51a7d8 7947 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7948 aggregate,
7949 pi->attr->aspath);
7950
9a706b42 7951 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7952 /* Remove community from aggregate.
7953 */
21fec674 7954 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7955 aggregate,
7956 bgp_attr_get_community(
7957 pi->attr));
fc968841 7958
b53e67a3 7959 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7960 /* Remove ecommunity from aggregate.
7961 */
4edd83f9 7962 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7963 aggregate,
7964 bgp_attr_get_ecommunity(
7965 pi->attr));
fc968841 7966
1bcf3a96 7967 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7968 /* Remove lcommunity from aggregate.
7969 */
f1eb1f05 7970 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7971 aggregate,
7972 bgp_attr_get_lcommunity(
7973 pi->attr));
fc968841 7974 }
3b7db173
DS
7975 }
7976
7977 /* If this node was suppressed, process the change. */
7978 if (match)
9bcb3eef 7979 bgp_process(bgp, dest, afi, safi);
3b7db173 7980 }
f1eb1f05 7981 if (aggregate->as_set) {
ef51a7d8 7982 aspath_free(aggregate->aspath);
7983 aggregate->aspath = NULL;
21fec674 7984 if (aggregate->community)
7985 community_free(&aggregate->community);
4edd83f9 7986 if (aggregate->ecommunity)
7987 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7988 if (aggregate->lcommunity)
7989 lcommunity_free(&aggregate->lcommunity);
7990 }
7991
9bcb3eef 7992 bgp_dest_unlock_node(top);
3b7db173 7993}
718e3744 7994
5f040085
DS
7995static void bgp_add_route_to_aggregate(struct bgp *bgp,
7996 const struct prefix *aggr_p,
fc968841
NT
7997 struct bgp_path_info *pinew, afi_t afi,
7998 safi_t safi,
7999 struct bgp_aggregate *aggregate)
8000{
8001 uint8_t origin;
8002 struct aspath *aspath = NULL;
8003 uint8_t atomic_aggregate = 0;
8004 struct community *community = NULL;
8005 struct ecommunity *ecommunity = NULL;
8006 struct lcommunity *lcommunity = NULL;
8007
a4559740 8008 /* If the bgp instance is being deleted or self peer is deleted
8009 * then do not create aggregate route
8010 */
8011 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8012 || (bgp->peer_self == NULL))
8013 return;
8014
fc968841
NT
8015 /* ORIGIN attribute: If at least one route among routes that are
8016 * aggregated has ORIGIN with the value INCOMPLETE, then the
8017 * aggregated route must have the ORIGIN attribute with the value
8018 * INCOMPLETE. Otherwise, if at least one route among routes that
8019 * are aggregated has ORIGIN with the value EGP, then the aggregated
8020 * route must have the origin attribute with the value EGP. In all
8021 * other case the value of the ORIGIN attribute of the aggregated
8022 * route is INTERNAL.
8023 */
8024 origin = BGP_ORIGIN_IGP;
8025
8026 aggregate->count++;
8027
6aabb15d
RZ
8028 /*
8029 * This must be called before `summary` check to avoid
8030 * "suppressing" twice.
8031 */
8032 if (aggregate->match_med)
8033 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8034 pinew);
6aabb15d
RZ
8035
8036 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8037 aggr_suppress_path(aggregate, pinew);
fc968841 8038
365ab2e7
RZ
8039 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8040 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8041 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8042
8043 switch (pinew->attr->origin) {
8044 case BGP_ORIGIN_INCOMPLETE:
8045 aggregate->incomplete_origin_count++;
8046 break;
8047 case BGP_ORIGIN_EGP:
8048 aggregate->egp_origin_count++;
8049 break;
8050 default:
8051 /* Do nothing.
8052 */
8053 break;
8054 }
8055
8056 if (aggregate->incomplete_origin_count > 0)
8057 origin = BGP_ORIGIN_INCOMPLETE;
8058 else if (aggregate->egp_origin_count > 0)
8059 origin = BGP_ORIGIN_EGP;
8060
229757f1
DA
8061 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8062 origin = aggregate->origin;
8063
fc968841
NT
8064 if (aggregate->as_set) {
8065 /* Compute aggregate route's as-path.
8066 */
8067 bgp_compute_aggregate_aspath(aggregate,
8068 pinew->attr->aspath);
8069
8070 /* Compute aggregate route's community.
8071 */
9a706b42 8072 if (bgp_attr_get_community(pinew->attr))
fc968841 8073 bgp_compute_aggregate_community(
9a706b42 8074 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8075
8076 /* Compute aggregate route's extended community.
8077 */
b53e67a3 8078 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8079 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8080 aggregate,
8081 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8082
8083 /* Compute aggregate route's large community.
8084 */
1bcf3a96 8085 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8086 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8087 aggregate,
8088 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8089
8090 /* Retrieve aggregate route's as-path.
8091 */
8092 if (aggregate->aspath)
8093 aspath = aspath_dup(aggregate->aspath);
8094
8095 /* Retrieve aggregate route's community.
8096 */
8097 if (aggregate->community)
8098 community = community_dup(aggregate->community);
8099
8100 /* Retrieve aggregate route's ecommunity.
8101 */
8102 if (aggregate->ecommunity)
8103 ecommunity = ecommunity_dup(aggregate->ecommunity);
8104
8105 /* Retrieve aggregate route's lcommunity.
8106 */
8107 if (aggregate->lcommunity)
8108 lcommunity = lcommunity_dup(aggregate->lcommunity);
8109 }
8110
8111 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8112 aspath, community, ecommunity,
8113 lcommunity, atomic_aggregate, aggregate);
8114}
8115
8116static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8117 safi_t safi,
8118 struct bgp_path_info *pi,
8119 struct bgp_aggregate *aggregate,
5f040085 8120 const struct prefix *aggr_p)
fc968841
NT
8121{
8122 uint8_t origin;
8123 struct aspath *aspath = NULL;
8124 uint8_t atomic_aggregate = 0;
8125 struct community *community = NULL;
8126 struct ecommunity *ecommunity = NULL;
8127 struct lcommunity *lcommunity = NULL;
8128 unsigned long match = 0;
8129
a4559740 8130 /* If the bgp instance is being deleted or self peer is deleted
8131 * then do not create aggregate route
8132 */
8133 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8134 || (bgp->peer_self == NULL))
8135 return;
8136
fc968841
NT
8137 if (BGP_PATH_HOLDDOWN(pi))
8138 return;
8139
8140 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8141 return;
8142
4056a5f6
RZ
8143 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8144 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8145 match++;
fc968841 8146
365ab2e7 8147 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8148 && aggr_suppress_map_test(bgp, aggregate, pi))
8149 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8150 match++;
fc968841 8151
6aabb15d 8152 /*
365ab2e7 8153 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8154 * "unsuppressing" twice.
8155 */
8156 if (aggregate->match_med)
f66624f5 8157 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8158
fc968841
NT
8159 if (aggregate->count > 0)
8160 aggregate->count--;
8161
8162 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8163 aggregate->incomplete_origin_count--;
8164 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8165 aggregate->egp_origin_count--;
8166
8167 if (aggregate->as_set) {
8168 /* Remove as-path from aggregate.
8169 */
8170 bgp_remove_aspath_from_aggregate(aggregate,
8171 pi->attr->aspath);
8172
9a706b42 8173 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8174 /* Remove community from aggregate.
8175 */
8176 bgp_remove_community_from_aggregate(
9a706b42 8177 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8178
b53e67a3 8179 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8180 /* Remove ecommunity from aggregate.
8181 */
8182 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8183 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8184
1bcf3a96 8185 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8186 /* Remove lcommunity from aggregate.
8187 */
8188 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8189 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8190 }
8191
8192 /* If this node was suppressed, process the change. */
8193 if (match)
8194 bgp_process(bgp, pi->net, afi, safi);
8195
8196 origin = BGP_ORIGIN_IGP;
8197 if (aggregate->incomplete_origin_count > 0)
8198 origin = BGP_ORIGIN_INCOMPLETE;
8199 else if (aggregate->egp_origin_count > 0)
8200 origin = BGP_ORIGIN_EGP;
8201
229757f1
DA
8202 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8203 origin = aggregate->origin;
8204
fc968841
NT
8205 if (aggregate->as_set) {
8206 /* Retrieve aggregate route's as-path.
8207 */
8208 if (aggregate->aspath)
8209 aspath = aspath_dup(aggregate->aspath);
8210
8211 /* Retrieve aggregate route's community.
8212 */
8213 if (aggregate->community)
8214 community = community_dup(aggregate->community);
8215
8216 /* Retrieve aggregate route's ecommunity.
8217 */
8218 if (aggregate->ecommunity)
8219 ecommunity = ecommunity_dup(aggregate->ecommunity);
8220
8221 /* Retrieve aggregate route's lcommunity.
8222 */
8223 if (aggregate->lcommunity)
8224 lcommunity = lcommunity_dup(aggregate->lcommunity);
8225 }
8226
8227 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8228 aspath, community, ecommunity,
8229 lcommunity, atomic_aggregate, aggregate);
8230}
8231
5a1ae2c2 8232void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8233 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8234{
9bcb3eef
DS
8235 struct bgp_dest *child;
8236 struct bgp_dest *dest;
d62a17ae 8237 struct bgp_aggregate *aggregate;
8238 struct bgp_table *table;
718e3744 8239
d62a17ae 8240 table = bgp->aggregate[afi][safi];
f018db83 8241
d62a17ae 8242 /* No aggregates configured. */
8243 if (bgp_table_top_nolock(table) == NULL)
8244 return;
f018db83 8245
d62a17ae 8246 if (p->prefixlen == 0)
8247 return;
718e3744 8248
40381db7 8249 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8250 return;
718e3744 8251
a77e2f4b
S
8252 /* If suppress fib is enabled and route not installed
8253 * in FIB, do not update the aggregate route
8254 */
8255 if (!bgp_check_advertise(bgp, pi->net))
8256 return;
8257
d62a17ae 8258 child = bgp_node_get(table, p);
718e3744 8259
d62a17ae 8260 /* Aggregate address configuration check. */
9bcb3eef
DS
8261 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8262 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8263
9bcb3eef
DS
8264 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8265 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8266 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8267 aggregate);
d62a17ae 8268 }
b1e62edd 8269 }
9bcb3eef 8270 bgp_dest_unlock_node(child);
718e3744 8271}
8272
5a1ae2c2 8273void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8274 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8275{
9bcb3eef
DS
8276 struct bgp_dest *child;
8277 struct bgp_dest *dest;
d62a17ae 8278 struct bgp_aggregate *aggregate;
8279 struct bgp_table *table;
718e3744 8280
d62a17ae 8281 table = bgp->aggregate[afi][safi];
718e3744 8282
d62a17ae 8283 /* No aggregates configured. */
8284 if (bgp_table_top_nolock(table) == NULL)
8285 return;
718e3744 8286
d62a17ae 8287 if (p->prefixlen == 0)
8288 return;
718e3744 8289
d62a17ae 8290 child = bgp_node_get(table, p);
718e3744 8291
d62a17ae 8292 /* Aggregate address configuration check. */
9bcb3eef
DS
8293 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8294 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8295
9bcb3eef
DS
8296 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8297 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8298 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8299 aggregate, dest_p);
d62a17ae 8300 }
b1e62edd 8301 }
9bcb3eef 8302 bgp_dest_unlock_node(child);
d62a17ae 8303}
718e3744 8304
718e3744 8305/* Aggregate route attribute. */
8306#define AGGREGATE_SUMMARY_ONLY 1
8307#define AGGREGATE_AS_SET 1
fb29348a 8308#define AGGREGATE_AS_UNSET 0
718e3744 8309
229757f1
DA
8310static const char *bgp_origin2str(uint8_t origin)
8311{
8312 switch (origin) {
8313 case BGP_ORIGIN_IGP:
8314 return "igp";
8315 case BGP_ORIGIN_EGP:
8316 return "egp";
8317 case BGP_ORIGIN_INCOMPLETE:
8318 return "incomplete";
8319 }
8320 return "n/a";
8321}
8322
fdeb5a81 8323static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8324{
8325 switch (v_state) {
fdeb5a81
DS
8326 case RPKI_NOT_BEING_USED:
8327 return "not used";
8328 case RPKI_VALID:
b5b99af8 8329 return "valid";
fdeb5a81 8330 case RPKI_NOTFOUND:
b5b99af8 8331 return "not found";
fdeb5a81 8332 case RPKI_INVALID:
b5b99af8 8333 return "invalid";
b5b99af8 8334 }
fdeb5a81
DS
8335
8336 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8337 return "ERROR";
8338}
8339
585f1adc
IR
8340static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8341 afi_t afi, safi_t safi)
718e3744 8342{
585f1adc
IR
8343 VTY_DECLVAR_CONTEXT(bgp, bgp);
8344 int ret;
8345 struct prefix p;
9bcb3eef 8346 struct bgp_dest *dest;
d62a17ae 8347 struct bgp_aggregate *aggregate;
718e3744 8348
585f1adc
IR
8349 /* Convert string to prefix structure. */
8350 ret = str2prefix(prefix_str, &p);
8351 if (!ret) {
8352 vty_out(vty, "Malformed prefix\n");
8353 return CMD_WARNING_CONFIG_FAILED;
8354 }
8355 apply_mask(&p);
a4559740 8356
d62a17ae 8357 /* Old configuration check. */
585f1adc 8358 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8359 if (!dest) {
585f1adc
IR
8360 vty_out(vty,
8361 "%% There is no aggregate-address configuration.\n");
8362 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8363 }
f6269b4f 8364
9bcb3eef 8365 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8366 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8367 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8368 NULL, NULL, 0, aggregate);
d62a17ae 8369
8370 /* Unlock aggregate address configuration. */
9bcb3eef 8371 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8372
8373 if (aggregate->community)
8374 community_free(&aggregate->community);
8375
8376 if (aggregate->community_hash) {
8377 /* Delete all communities in the hash.
8378 */
8379 hash_clean(aggregate->community_hash,
8380 bgp_aggr_community_remove);
8381 /* Free up the community_hash.
8382 */
8383 hash_free(aggregate->community_hash);
8384 }
8385
8386 if (aggregate->ecommunity)
8387 ecommunity_free(&aggregate->ecommunity);
8388
8389 if (aggregate->ecommunity_hash) {
8390 /* Delete all ecommunities in the hash.
8391 */
8392 hash_clean(aggregate->ecommunity_hash,
8393 bgp_aggr_ecommunity_remove);
8394 /* Free up the ecommunity_hash.
8395 */
8396 hash_free(aggregate->ecommunity_hash);
8397 }
8398
8399 if (aggregate->lcommunity)
8400 lcommunity_free(&aggregate->lcommunity);
8401
8402 if (aggregate->lcommunity_hash) {
8403 /* Delete all lcommunities in the hash.
8404 */
8405 hash_clean(aggregate->lcommunity_hash,
8406 bgp_aggr_lcommunity_remove);
8407 /* Free up the lcommunity_hash.
8408 */
8409 hash_free(aggregate->lcommunity_hash);
8410 }
8411
8412 if (aggregate->aspath)
8413 aspath_free(aggregate->aspath);
8414
8415 if (aggregate->aspath_hash) {
8416 /* Delete all as-paths in the hash.
8417 */
8418 hash_clean(aggregate->aspath_hash,
8419 bgp_aggr_aspath_remove);
8420 /* Free up the aspath_hash.
8421 */
8422 hash_free(aggregate->aspath_hash);
8423 }
8424
d62a17ae 8425 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8426 bgp_dest_unlock_node(dest);
8427 bgp_dest_unlock_node(dest);
d62a17ae 8428
585f1adc 8429 return CMD_SUCCESS;
d62a17ae 8430}
8431
585f1adc
IR
8432static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8433 safi_t safi, const char *rmap,
8434 uint8_t summary_only, uint8_t as_set,
8435 uint8_t origin, bool match_med,
8436 const char *suppress_map)
d62a17ae 8437{
585f1adc 8438 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8439 int ret;
585f1adc 8440 struct prefix p;
9bcb3eef 8441 struct bgp_dest *dest;
d62a17ae 8442 struct bgp_aggregate *aggregate;
fb29348a 8443 uint8_t as_set_new = as_set;
d62a17ae 8444
365ab2e7 8445 if (suppress_map && summary_only) {
585f1adc 8446 vty_out(vty,
365ab2e7 8447 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8448 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8449 }
8450
585f1adc
IR
8451 /* Convert string to prefix structure. */
8452 ret = str2prefix(prefix_str, &p);
8453 if (!ret) {
8454 vty_out(vty, "Malformed prefix\n");
8455 return CMD_WARNING_CONFIG_FAILED;
8456 }
8457 apply_mask(&p);
d62a17ae 8458
585f1adc
IR
8459 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8460 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8461 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8462 prefix_str);
8463 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8464 }
8465
d62a17ae 8466 /* Old configuration check. */
585f1adc 8467 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8468 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8469
20894f50 8470 if (aggregate) {
585f1adc 8471 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8472 /* try to remove the old entry */
585f1adc 8473 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8474 if (ret) {
585f1adc 8475 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8476 bgp_dest_unlock_node(dest);
585f1adc 8477 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8478 }
8479 }
718e3744 8480
d62a17ae 8481 /* Make aggregate address structure. */
8482 aggregate = bgp_aggregate_new();
8483 aggregate->summary_only = summary_only;
6aabb15d 8484 aggregate->match_med = match_med;
fb29348a
DA
8485
8486 /* Network operators MUST NOT locally generate any new
8487 * announcements containing AS_SET or AS_CONFED_SET. If they have
8488 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8489 * SHOULD withdraw those routes and re-announce routes for the
8490 * aggregate or component prefixes (i.e., the more-specific routes
8491 * subsumed by the previously aggregated route) without AS_SET
8492 * or AS_CONFED_SET in the updates.
8493 */
7f972cd8 8494 if (bgp->reject_as_sets) {
fb29348a
DA
8495 if (as_set == AGGREGATE_AS_SET) {
8496 as_set_new = AGGREGATE_AS_UNSET;
8497 zlog_warn(
63efca0e 8498 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8499 __func__);
585f1adc 8500 vty_out(vty,
fb29348a
DA
8501 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8502 }
8503 }
8504
8505 aggregate->as_set = as_set_new;
d62a17ae 8506 aggregate->safi = safi;
229757f1
DA
8507 /* Override ORIGIN attribute if defined.
8508 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8509 * to IGP which is not what rfc4271 says.
8510 * This enables the same behavior, optionally.
8511 */
8512 aggregate->origin = origin;
20894f50
DA
8513
8514 if (rmap) {
8515 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8516 route_map_counter_decrement(aggregate->rmap.map);
8517 aggregate->rmap.name =
8518 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8519 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8520 route_map_counter_increment(aggregate->rmap.map);
8521 }
365ab2e7
RZ
8522
8523 if (suppress_map) {
8524 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8525 route_map_counter_decrement(aggregate->suppress_map);
8526
8527 aggregate->suppress_map_name =
8528 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8529 aggregate->suppress_map =
8530 route_map_lookup_by_name(aggregate->suppress_map_name);
8531 route_map_counter_increment(aggregate->suppress_map);
8532 }
8533
9bcb3eef 8534 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8535
d62a17ae 8536 /* Aggregate address insert into BGP routing table. */
585f1adc 8537 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8538
585f1adc 8539 return CMD_SUCCESS;
718e3744 8540}
8541
585f1adc
IR
8542DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8543 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8544 "as-set$as_set_s"
8545 "|summary-only$summary_only"
cacba915 8546 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8547 "|origin <egp|igp|incomplete>$origin_s"
8548 "|matching-MED-only$match_med"
cacba915 8549 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8550 "}]",
8551 NO_STR
8552 "Configure BGP aggregate entries\n"
764402fe
DA
8553 "Aggregate prefix\n"
8554 "Aggregate address\n"
8555 "Aggregate mask\n"
585f1adc
IR
8556 "Generate AS set path information\n"
8557 "Filter more specific routes from updates\n"
8558 "Apply route map to aggregate network\n"
8559 "Route map name\n"
8560 "BGP origin code\n"
8561 "Remote EGP\n"
8562 "Local IGP\n"
8563 "Unknown heritage\n"
8564 "Only aggregate routes with matching MED\n"
8565 "Suppress the selected more specific routes\n"
8566 "Route map with the route selectors\n")
8567{
8568 const char *prefix_s = NULL;
554b3b10 8569 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8570 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8571 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8572 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8573
554b3b10 8574 if (addr_str) {
7533cad7
QY
8575 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8576 sizeof(prefix_buf))
554b3b10
RZ
8577 == 0) {
8578 vty_out(vty, "%% Inconsistent address and mask\n");
8579 return CMD_WARNING_CONFIG_FAILED;
8580 }
585f1adc
IR
8581 prefix_s = prefix_buf;
8582 } else
8583 prefix_s = prefix_str;
37a87b8f 8584
585f1adc
IR
8585 if (origin_s) {
8586 if (strcmp(origin_s, "egp") == 0)
8587 origin = BGP_ORIGIN_EGP;
8588 else if (strcmp(origin_s, "igp") == 0)
8589 origin = BGP_ORIGIN_IGP;
8590 else if (strcmp(origin_s, "incomplete") == 0)
8591 origin = BGP_ORIGIN_INCOMPLETE;
8592 }
90e21f35 8593
585f1adc
IR
8594 if (as_set_s)
8595 as_set = AGGREGATE_AS_SET;
554b3b10 8596
585f1adc 8597 /* Handle configuration removal, otherwise installation. */
554b3b10 8598 if (no)
585f1adc
IR
8599 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8600
8601 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8602 summary_only != NULL, as_set, origin,
8603 match_med != NULL, suppress_map);
8604}
8605
8606DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8607 "[no] aggregate-address X:X::X:X/M$prefix [{"
8608 "as-set$as_set_s"
8609 "|summary-only$summary_only"
cacba915 8610 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8611 "|origin <egp|igp|incomplete>$origin_s"
8612 "|matching-MED-only$match_med"
cacba915 8613 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8614 "}]",
8615 NO_STR
8616 "Configure BGP aggregate entries\n"
8617 "Aggregate prefix\n"
8618 "Generate AS set path information\n"
8619 "Filter more specific routes from updates\n"
8620 "Apply route map to aggregate network\n"
8621 "Route map name\n"
8622 "BGP origin code\n"
8623 "Remote EGP\n"
8624 "Local IGP\n"
8625 "Unknown heritage\n"
8626 "Only aggregate routes with matching MED\n"
8627 "Suppress the selected more specific routes\n"
8628 "Route map with the route selectors\n")
8629{
8630 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8631 int as_set = AGGREGATE_AS_UNSET;
8632
8633 if (origin_s) {
8634 if (strcmp(origin_s, "egp") == 0)
8635 origin = BGP_ORIGIN_EGP;
8636 else if (strcmp(origin_s, "igp") == 0)
8637 origin = BGP_ORIGIN_IGP;
8638 else if (strcmp(origin_s, "incomplete") == 0)
8639 origin = BGP_ORIGIN_INCOMPLETE;
8640 }
8641
8642 if (as_set_s)
8643 as_set = AGGREGATE_AS_SET;
8644
8645 /* Handle configuration removal, otherwise installation. */
554b3b10 8646 if (no)
585f1adc
IR
8647 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8648 SAFI_UNICAST);
554b3b10 8649
585f1adc
IR
8650 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8651 rmap_name, summary_only != NULL, as_set,
8652 origin, match_med != NULL, suppress_map);
718e3744 8653}
8654
718e3744 8655/* Redistribute route treatment. */
d62a17ae 8656void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8657 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8658 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8659 enum blackhole_type bhtype, uint32_t metric,
8660 uint8_t type, unsigned short instance,
8661 route_tag_t tag)
d62a17ae 8662{
4b7e6066 8663 struct bgp_path_info *new;
40381db7
DS
8664 struct bgp_path_info *bpi;
8665 struct bgp_path_info rmap_path;
9bcb3eef 8666 struct bgp_dest *bn;
d62a17ae 8667 struct attr attr;
8668 struct attr *new_attr;
8669 afi_t afi;
b68885f9 8670 route_map_result_t ret;
d62a17ae 8671 struct bgp_redist *red;
8672
8673 /* Make default attribute. */
0f05ea43 8674 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8675 /*
8676 * This must not be NULL to satisfy Coverity SA
8677 */
8678 assert(attr.aspath);
9de1f7ff 8679
a4d82a8a 8680 switch (nhtype) {
9de1f7ff 8681 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8682 switch (p->family) {
8683 case AF_INET:
8684 attr.nexthop.s_addr = INADDR_ANY;
8685 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8686 break;
8687 case AF_INET6:
8688 memset(&attr.mp_nexthop_global, 0,
8689 sizeof(attr.mp_nexthop_global));
8690 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8691 break;
8692 }
9de1f7ff
DS
8693 break;
8694 case NEXTHOP_TYPE_IPV4:
8695 case NEXTHOP_TYPE_IPV4_IFINDEX:
8696 attr.nexthop = nexthop->ipv4;
7226bc40 8697 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8698 break;
8699 case NEXTHOP_TYPE_IPV6:
8700 case NEXTHOP_TYPE_IPV6_IFINDEX:
8701 attr.mp_nexthop_global = nexthop->ipv6;
8702 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8703 break;
8704 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8705 switch (p->family) {
8706 case AF_INET:
9de1f7ff 8707 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8708 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8709 break;
8710 case AF_INET6:
9de1f7ff
DS
8711 memset(&attr.mp_nexthop_global, 0,
8712 sizeof(attr.mp_nexthop_global));
74489921 8713 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8714 break;
74489921 8715 }
0789eb69 8716 attr.bh_type = bhtype;
9de1f7ff 8717 break;
d62a17ae 8718 }
0789eb69 8719 attr.nh_type = nhtype;
74489921 8720 attr.nh_ifindex = ifindex;
f04a80a5 8721
d62a17ae 8722 attr.med = metric;
957f74c3 8723 attr.distance = distance;
d62a17ae 8724 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8725 attr.tag = tag;
718e3744 8726
97a52c82
DA
8727 if (metric)
8728 bgp_attr_set_aigp_metric(&attr, metric);
8729
d62a17ae 8730 afi = family2afi(p->family);
6aeb9e78 8731
d62a17ae 8732 red = bgp_redist_lookup(bgp, afi, type, instance);
8733 if (red) {
8734 struct attr attr_new;
718e3744 8735
d62a17ae 8736 /* Copy attribute for modification. */
6f4f49b2 8737 attr_new = attr;
718e3744 8738
97a52c82 8739 if (red->redist_metric_flag) {
d62a17ae 8740 attr_new.med = red->redist_metric;
97a52c82
DA
8741 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8742 }
718e3744 8743
d62a17ae 8744 /* Apply route-map. */
8745 if (red->rmap.name) {
6006b807 8746 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8747 rmap_path.peer = bgp->peer_self;
8748 rmap_path.attr = &attr_new;
718e3744 8749
d62a17ae 8750 SET_FLAG(bgp->peer_self->rmap_type,
8751 PEER_RMAP_TYPE_REDISTRIBUTE);
8752
1782514f 8753 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8754
8755 bgp->peer_self->rmap_type = 0;
8756
8757 if (ret == RMAP_DENYMATCH) {
8758 /* Free uninterned attribute. */
8759 bgp_attr_flush(&attr_new);
8760
8761 /* Unintern original. */
8762 aspath_unintern(&attr.aspath);
8763 bgp_redistribute_delete(bgp, p, type, instance);
8764 return;
8765 }
8766 }
8767
637e5ba4 8768 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8769 bgp_attr_add_gshut_community(&attr_new);
8770
d62a17ae 8771 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8772 SAFI_UNICAST, p, NULL);
8773
8774 new_attr = bgp_attr_intern(&attr_new);
8775
9bcb3eef 8776 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8777 if (bpi->peer == bgp->peer_self
8778 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8779 break;
8780
40381db7 8781 if (bpi) {
d62a17ae 8782 /* Ensure the (source route) type is updated. */
40381db7
DS
8783 bpi->type = type;
8784 if (attrhash_cmp(bpi->attr, new_attr)
8785 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8786 bgp_attr_unintern(&new_attr);
8787 aspath_unintern(&attr.aspath);
9bcb3eef 8788 bgp_dest_unlock_node(bn);
d62a17ae 8789 return;
8790 } else {
8791 /* The attribute is changed. */
40381db7 8792 bgp_path_info_set_flag(bn, bpi,
18ee8310 8793 BGP_PATH_ATTR_CHANGED);
d62a17ae 8794
8795 /* Rewrite BGP route information. */
40381db7
DS
8796 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8797 bgp_path_info_restore(bn, bpi);
d62a17ae 8798 else
40381db7
DS
8799 bgp_aggregate_decrement(
8800 bgp, p, bpi, afi, SAFI_UNICAST);
8801 bgp_attr_unintern(&bpi->attr);
8802 bpi->attr = new_attr;
083ec940 8803 bpi->uptime = monotime(NULL);
d62a17ae 8804
8805 /* Process change. */
40381db7 8806 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8807 SAFI_UNICAST);
8808 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8809 bgp_dest_unlock_node(bn);
d62a17ae 8810 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8811
8812 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8813 || (bgp->inst_type
8814 == BGP_INSTANCE_TYPE_DEFAULT)) {
8815
8816 vpn_leak_from_vrf_update(
40381db7 8817 bgp_get_default(), bgp, bpi);
ddb5b488 8818 }
d62a17ae 8819 return;
8820 }
8821 }
8822
8823 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8824 bgp->peer_self, new_attr, bn);
1defdda8 8825 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8826
8827 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8828 bgp_path_info_add(bn, new);
9bcb3eef 8829 bgp_dest_unlock_node(bn);
be785e35 8830 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8831 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8832
8833 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8834 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8835
8836 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8837 }
d62a17ae 8838 }
8839
8840 /* Unintern original. */
8841 aspath_unintern(&attr.aspath);
718e3744 8842}
8843
d7c0a89a
QY
8844void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8845 unsigned short instance)
718e3744 8846{
d62a17ae 8847 afi_t afi;
9bcb3eef 8848 struct bgp_dest *dest;
40381db7 8849 struct bgp_path_info *pi;
d62a17ae 8850 struct bgp_redist *red;
718e3744 8851
d62a17ae 8852 afi = family2afi(p->family);
718e3744 8853
d62a17ae 8854 red = bgp_redist_lookup(bgp, afi, type, instance);
8855 if (red) {
9bcb3eef
DS
8856 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8857 SAFI_UNICAST, p, NULL);
d62a17ae 8858
9bcb3eef 8859 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8860 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8861 break;
8862
40381db7 8863 if (pi) {
ddb5b488
PZ
8864 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8865 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8866
8867 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8868 bgp, pi);
ddb5b488 8869 }
40381db7 8870 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8871 bgp_path_info_delete(dest, pi);
8872 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8873 }
9bcb3eef 8874 bgp_dest_unlock_node(dest);
d62a17ae 8875 }
8876}
8877
8878/* Withdraw specified route type's route. */
8879void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8880 unsigned short instance)
d62a17ae 8881{
9bcb3eef 8882 struct bgp_dest *dest;
40381db7 8883 struct bgp_path_info *pi;
d62a17ae 8884 struct bgp_table *table;
8885
8886 table = bgp->rib[afi][SAFI_UNICAST];
8887
9bcb3eef
DS
8888 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8889 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8890 if (pi->peer == bgp->peer_self && pi->type == type
8891 && pi->instance == instance)
d62a17ae 8892 break;
8893
40381db7 8894 if (pi) {
ddb5b488
PZ
8895 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8896 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8897
8898 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8899 bgp, pi);
ddb5b488 8900 }
9bcb3eef 8901 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8902 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8903 bgp_path_info_delete(dest, pi);
8904 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8905 }
718e3744 8906 }
718e3744 8907}
6b0655a2 8908
718e3744 8909/* Static function to display route. */
7d3cae70
DA
8910static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8911 struct vty *vty, json_object *json, bool wide)
718e3744 8912{
be054588 8913 int len = 0;
07380148 8914 char buf[INET6_ADDRSTRLEN];
718e3744 8915
d62a17ae 8916 if (p->family == AF_INET) {
c6462ff4 8917 if (!json) {
8228a9a7 8918 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8919 } else {
8920 json_object_string_add(json, "prefix",
8921 inet_ntop(p->family,
8922 &p->u.prefix, buf,
07380148 8923 sizeof(buf)));
c6462ff4 8924 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8925 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8926 json_object_int_add(json, "version", dest->version);
c6462ff4 8927 }
d62a17ae 8928 } else if (p->family == AF_ETHERNET) {
8228a9a7 8929 len = vty_out(vty, "%pFX", p);
b03b8898 8930 } else if (p->family == AF_EVPN) {
57f7feb6 8931 if (!json)
2dbe669b 8932 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8933 else
60466a63 8934 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8935 } else if (p->family == AF_FLOWSPEC) {
8936 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8937 json ?
8938 NLRI_STRING_FORMAT_JSON_SIMPLE :
8939 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8940 } else {
c6462ff4 8941 if (!json)
8228a9a7 8942 len = vty_out(vty, "%pFX", p);
50e05855
AD
8943 else {
8944 json_object_string_add(json, "prefix",
07380148
DA
8945 inet_ntop(p->family,
8946 &p->u.prefix, buf,
8947 sizeof(buf)));
50e05855 8948 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8949 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8950 json_object_int_add(json, "version", dest->version);
37d4e0df 8951 }
9c92b5f7 8952 }
d62a17ae 8953
9c92b5f7 8954 if (!json) {
ae248832 8955 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8956 if (len < 1)
8957 vty_out(vty, "\n%*s", 20, " ");
8958 else
8959 vty_out(vty, "%*s", len, " ");
8960 }
718e3744 8961}
8962
d62a17ae 8963enum bgp_display_type {
8964 normal_list,
718e3744 8965};
8966
1d7260a1 8967const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8968{
8969 switch (reason) {
8970 case bgp_path_selection_none:
8971 return "Nothing to Select";
8972 case bgp_path_selection_first:
8973 return "First path received";
8974 case bgp_path_selection_evpn_sticky_mac:
8975 return "EVPN Sticky Mac";
8976 case bgp_path_selection_evpn_seq:
8977 return "EVPN sequence number";
8978 case bgp_path_selection_evpn_lower_ip:
8979 return "EVPN lower IP";
8980 case bgp_path_selection_evpn_local_path:
8981 return "EVPN local ES path";
8982 case bgp_path_selection_evpn_non_proxy:
8983 return "EVPN non proxy";
8984 case bgp_path_selection_weight:
8985 return "Weight";
8986 case bgp_path_selection_local_pref:
8987 return "Local Pref";
46dbf9d0
DA
8988 case bgp_path_selection_accept_own:
8989 return "Accept Own";
bbb46eb5
DA
8990 case bgp_path_selection_local_route:
8991 return "Local Route";
97a52c82
DA
8992 case bgp_path_selection_aigp:
8993 return "AIGP";
bbb46eb5
DA
8994 case bgp_path_selection_confed_as_path:
8995 return "Confederation based AS Path";
8996 case bgp_path_selection_as_path:
8997 return "AS Path";
8998 case bgp_path_selection_origin:
8999 return "Origin";
9000 case bgp_path_selection_med:
9001 return "MED";
9002 case bgp_path_selection_peer:
9003 return "Peer Type";
9004 case bgp_path_selection_confed:
9005 return "Confed Peer Type";
9006 case bgp_path_selection_igp_metric:
9007 return "IGP Metric";
9008 case bgp_path_selection_older:
9009 return "Older Path";
9010 case bgp_path_selection_router_id:
9011 return "Router ID";
9012 case bgp_path_selection_cluster_length:
bcab253c 9013 return "Cluster length";
bbb46eb5
DA
9014 case bgp_path_selection_stale:
9015 return "Path Staleness";
9016 case bgp_path_selection_local_configured:
9017 return "Locally configured route";
9018 case bgp_path_selection_neighbor_ip:
9019 return "Neighbor IP";
9020 case bgp_path_selection_default:
9021 return "Nothing left to compare";
9022 }
9023 return "Invalid (internal error)";
9024}
9025
18ee8310 9026/* Print the short form route status for a bgp_path_info */
4b7e6066 9027static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9028 struct bgp_path_info *path,
82c298be 9029 const struct prefix *p,
d62a17ae 9030 json_object *json_path)
718e3744 9031{
82c298be
DA
9032 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9033
d62a17ae 9034 if (json_path) {
b05a1c8b 9035
d62a17ae 9036 /* Route status display. */
9b6d8fcf 9037 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9038 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9039
9b6d8fcf 9040 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9041 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9042
4056a5f6 9043 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9044 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9045
9b6d8fcf
DS
9046 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9047 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9048 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9049
d62a17ae 9050 /* Selected */
9b6d8fcf 9051 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9052 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9053
9b6d8fcf 9054 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9055 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9056
bbb46eb5 9057 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9058 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9059 json_object_string_add(json_path, "selectionReason",
9060 bgp_path_selection_reason2str(
9061 path->net->reason));
9062 }
b05a1c8b 9063
9b6d8fcf 9064 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9065 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9066
d62a17ae 9067 /* Internal route. */
9b6d8fcf
DS
9068 if ((path->peer->as)
9069 && (path->peer->as == path->peer->local_as))
d62a17ae 9070 json_object_string_add(json_path, "pathFrom",
9071 "internal");
9072 else
9073 json_object_string_add(json_path, "pathFrom",
9074 "external");
b05a1c8b 9075
d62a17ae 9076 return;
9077 }
b05a1c8b 9078
82c298be
DA
9079 /* RPKI validation state */
9080 rpki_state =
9081 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9082
9083 if (rpki_state == RPKI_VALID)
9084 vty_out(vty, "V");
9085 else if (rpki_state == RPKI_INVALID)
9086 vty_out(vty, "I");
9087 else if (rpki_state == RPKI_NOTFOUND)
9088 vty_out(vty, "N");
eaeba5e8
WM
9089 else
9090 vty_out(vty, " ");
82c298be 9091
d62a17ae 9092 /* Route status display. */
9b6d8fcf 9093 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9094 vty_out(vty, "R");
9b6d8fcf 9095 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9096 vty_out(vty, "S");
4056a5f6 9097 else if (bgp_path_suppressed(path))
d62a17ae 9098 vty_out(vty, "s");
9b6d8fcf
DS
9099 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9100 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9101 vty_out(vty, "*");
9102 else
9103 vty_out(vty, " ");
9104
9105 /* Selected */
9b6d8fcf 9106 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9107 vty_out(vty, "h");
9b6d8fcf 9108 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9109 vty_out(vty, "d");
9b6d8fcf 9110 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9111 vty_out(vty, ">");
9b6d8fcf 9112 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9113 vty_out(vty, "=");
9114 else
9115 vty_out(vty, " ");
718e3744 9116
d62a17ae 9117 /* Internal route. */
9b6d8fcf
DS
9118 if (path->peer && (path->peer->as)
9119 && (path->peer->as == path->peer->local_as))
d62a17ae 9120 vty_out(vty, "i");
9121 else
9122 vty_out(vty, " ");
b40d939b 9123}
9124
2ba93fd6
DA
9125static char *bgp_nexthop_hostname(struct peer *peer,
9126 struct bgp_nexthop_cache *bnc)
25b5da8d 9127{
892fedb6 9128 if (peer->hostname
aef999a2 9129 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9130 return peer->hostname;
9131 return NULL;
9132}
9133
b40d939b 9134/* called from terminal list command */
bd494ec5 9135void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9136 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9137 json_object *json_paths, bool wide)
d62a17ae 9138{
aef999a2 9139 int len;
515c2602 9140 struct attr *attr = path->attr;
d62a17ae 9141 json_object *json_path = NULL;
9142 json_object *json_nexthops = NULL;
9143 json_object *json_nexthop_global = NULL;
9144 json_object *json_nexthop_ll = NULL;
6f214dd3 9145 json_object *json_ext_community = NULL;
9df8b37c 9146 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9147 bool nexthop_self =
9b6d8fcf 9148 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9149 bool nexthop_othervrf = false;
43089216 9150 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9151 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9152 char *nexthop_hostname =
9153 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9154 char esi_buf[ESI_STR_LEN];
d62a17ae 9155
9156 if (json_paths)
9157 json_path = json_object_new_object();
9158
9159 /* short status lead text */
82c298be 9160 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9161
9162 if (!json_paths) {
9163 /* print prefix and mask */
9164 if (!display)
7d3cae70 9165 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9166 else
ae248832 9167 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9168 } else {
7d3cae70 9169 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9170 }
47fc97cc 9171
9df8b37c
PZ
9172 /*
9173 * If vrf id of nexthop is different from that of prefix,
9174 * set up printable string to append
9175 */
9b6d8fcf 9176 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9177 const char *self = "";
9178
9179 if (nexthop_self)
9180 self = "<";
9181
9182 nexthop_othervrf = true;
9b6d8fcf 9183 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9184
9b6d8fcf 9185 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9186 snprintf(vrf_id_str, sizeof(vrf_id_str),
9187 "@%s%s", VRFID_NONE_STR, self);
9188 else
9189 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9190 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9191
9b6d8fcf
DS
9192 if (path->extra->bgp_orig->inst_type
9193 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9194
9b6d8fcf 9195 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9196 } else {
9197 const char *self = "";
9198
9199 if (nexthop_self)
9200 self = "<";
9201
9202 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9203 }
9204
445c2480
DS
9205 /*
9206 * For ENCAP and EVPN routes, nexthop address family is not
9207 * neccessarily the same as the prefix address family.
9208 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9209 * EVPN routes are also exchanged with a MP nexthop. Currently,
9210 * this
9211 * is only IPv4, the value will be present in either
9212 * attr->nexthop or
9213 * attr->mp_nexthop_global_in
9214 */
9215 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9216 char nexthop[128];
9217 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9218
9219 switch (af) {
9220 case AF_INET:
07380148
DA
9221 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9222 &attr->mp_nexthop_global_in);
445c2480
DS
9223 break;
9224 case AF_INET6:
07380148
DA
9225 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9226 &attr->mp_nexthop_global);
445c2480
DS
9227 break;
9228 default:
772270f3 9229 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9230 break;
d62a17ae 9231 }
d62a17ae 9232
445c2480
DS
9233 if (json_paths) {
9234 json_nexthop_global = json_object_new_object();
9235
515c2602
DA
9236 json_object_string_add(json_nexthop_global, "ip",
9237 nexthop);
9238
939a97f4 9239 if (path->peer->hostname)
515c2602
DA
9240 json_object_string_add(json_nexthop_global,
9241 "hostname",
939a97f4 9242 path->peer->hostname);
515c2602
DA
9243
9244 json_object_string_add(json_nexthop_global, "afi",
9245 (af == AF_INET) ? "ipv4"
9246 : "ipv6");
445c2480
DS
9247 json_object_boolean_true_add(json_nexthop_global,
9248 "used");
aef999a2
DA
9249 } else {
9250 if (nexthop_hostname)
9251 len = vty_out(vty, "%s(%s)%s", nexthop,
9252 nexthop_hostname, vrf_id_str);
9253 else
9254 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9255
ae248832 9256 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9257 if (len < 1)
9258 vty_out(vty, "\n%*s", 36, " ");
9259 else
9260 vty_out(vty, "%*s", len, " ");
9261 }
445c2480
DS
9262 } else if (safi == SAFI_EVPN) {
9263 if (json_paths) {
9264 json_nexthop_global = json_object_new_object();
9265
c949c771 9266 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9267 "%pI4",
9268 &attr->mp_nexthop_global_in);
515c2602 9269
939a97f4 9270 if (path->peer->hostname)
515c2602
DA
9271 json_object_string_add(json_nexthop_global,
9272 "hostname",
939a97f4 9273 path->peer->hostname);
515c2602 9274
a4d82a8a
PZ
9275 json_object_string_add(json_nexthop_global, "afi",
9276 "ipv4");
445c2480
DS
9277 json_object_boolean_true_add(json_nexthop_global,
9278 "used");
aef999a2
DA
9279 } else {
9280 if (nexthop_hostname)
7226bc40
TA
9281 len = vty_out(vty, "%pI4(%s)%s",
9282 &attr->mp_nexthop_global_in,
aef999a2
DA
9283 nexthop_hostname, vrf_id_str);
9284 else
7226bc40
TA
9285 len = vty_out(vty, "%pI4%s",
9286 &attr->mp_nexthop_global_in,
aef999a2
DA
9287 vrf_id_str);
9288
ae248832 9289 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9290 if (len < 1)
9291 vty_out(vty, "\n%*s", 36, " ");
9292 else
9293 vty_out(vty, "%*s", len, " ");
9294 }
d33fc23b 9295 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9296 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9297 if (json_paths) {
9298 json_nexthop_global = json_object_new_object();
515c2602 9299
026b914a
PG
9300 json_object_string_add(json_nexthop_global,
9301 "afi", "ipv4");
c949c771
DA
9302 json_object_string_addf(json_nexthop_global,
9303 "ip", "%pI4",
9304 &attr->nexthop);
515c2602 9305
939a97f4 9306 if (path->peer->hostname)
515c2602
DA
9307 json_object_string_add(
9308 json_nexthop_global, "hostname",
939a97f4 9309 path->peer->hostname);
515c2602 9310
50e05855
AD
9311 json_object_boolean_true_add(
9312 json_nexthop_global,
026b914a
PG
9313 "used");
9314 } else {
aef999a2
DA
9315 if (nexthop_hostname)
9316 len = vty_out(vty, "%pI4(%s)%s",
9317 &attr->nexthop,
9318 nexthop_hostname,
9319 vrf_id_str);
9320 else
9321 len = vty_out(vty, "%pI4%s",
9322 &attr->nexthop,
9323 vrf_id_str);
9324
ae248832 9325 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9326 if (len < 1)
9327 vty_out(vty, "\n%*s", 36, " ");
9328 else
9329 vty_out(vty, "%*s", len, " ");
026b914a
PG
9330 }
9331 }
7226bc40 9332 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9333 if (json_paths) {
9334 json_nexthop_global = json_object_new_object();
d62a17ae 9335
c949c771
DA
9336 json_object_string_addf(json_nexthop_global, "ip",
9337 "%pI4", &attr->nexthop);
515c2602 9338
939a97f4 9339 if (path->peer->hostname)
515c2602
DA
9340 json_object_string_add(json_nexthop_global,
9341 "hostname",
939a97f4 9342 path->peer->hostname);
445c2480 9343
a4d82a8a
PZ
9344 json_object_string_add(json_nexthop_global, "afi",
9345 "ipv4");
445c2480
DS
9346 json_object_boolean_true_add(json_nexthop_global,
9347 "used");
9348 } else {
aef999a2
DA
9349 if (nexthop_hostname)
9350 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9351 nexthop_hostname, vrf_id_str);
9352 else
9353 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9354 vrf_id_str);
9df8b37c 9355
ae248832 9356 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9357 if (len < 1)
9358 vty_out(vty, "\n%*s", 36, " ");
9359 else
9360 vty_out(vty, "%*s", len, " ");
d62a17ae 9361 }
445c2480 9362 }
b05a1c8b 9363
445c2480 9364 /* IPv6 Next Hop */
7226bc40 9365 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9366 if (json_paths) {
9367 json_nexthop_global = json_object_new_object();
c949c771
DA
9368 json_object_string_addf(json_nexthop_global, "ip",
9369 "%pI6",
9370 &attr->mp_nexthop_global);
515c2602 9371
939a97f4 9372 if (path->peer->hostname)
515c2602
DA
9373 json_object_string_add(json_nexthop_global,
9374 "hostname",
939a97f4 9375 path->peer->hostname);
515c2602 9376
a4d82a8a
PZ
9377 json_object_string_add(json_nexthop_global, "afi",
9378 "ipv6");
9379 json_object_string_add(json_nexthop_global, "scope",
9380 "global");
445c2480
DS
9381
9382 /* We display both LL & GL if both have been
9383 * received */
0606039c
DA
9384 if ((attr->mp_nexthop_len
9385 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9386 || (path->peer->conf_if)) {
a4d82a8a 9387 json_nexthop_ll = json_object_new_object();
c949c771
DA
9388 json_object_string_addf(
9389 json_nexthop_ll, "ip", "%pI6",
9390 &attr->mp_nexthop_local);
515c2602 9391
939a97f4 9392 if (path->peer->hostname)
515c2602
DA
9393 json_object_string_add(
9394 json_nexthop_ll, "hostname",
939a97f4 9395 path->peer->hostname);
515c2602 9396
a4d82a8a
PZ
9397 json_object_string_add(json_nexthop_ll, "afi",
9398 "ipv6");
9399 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9400 "link-local");
d62a17ae 9401
a4d82a8a
PZ
9402 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9403 &attr->mp_nexthop_local)
445c2480
DS
9404 != 0)
9405 && !attr->mp_nexthop_prefer_global)
d62a17ae 9406 json_object_boolean_true_add(
a4d82a8a 9407 json_nexthop_ll, "used");
445c2480
DS
9408 else
9409 json_object_boolean_true_add(
a4d82a8a 9410 json_nexthop_global, "used");
445c2480
DS
9411 } else
9412 json_object_boolean_true_add(
9413 json_nexthop_global, "used");
9414 } else {
9415 /* Display LL if LL/Global both in table unless
9416 * prefer-global is set */
0606039c
DA
9417 if (((attr->mp_nexthop_len
9418 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9419 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9420 || (path->peer->conf_if)) {
9421 if (path->peer->conf_if) {
a4d82a8a 9422 len = vty_out(vty, "%s",
9b6d8fcf 9423 path->peer->conf_if);
ae248832
MK
9424 /* len of IPv6 addr + max len of def
9425 * ifname */
9426 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9427
9428 if (len < 1)
a4d82a8a 9429 vty_out(vty, "\n%*s", 36, " ");
445c2480 9430 else
a4d82a8a 9431 vty_out(vty, "%*s", len, " ");
d62a17ae 9432 } else {
aef999a2
DA
9433 if (nexthop_hostname)
9434 len = vty_out(
9435 vty, "%pI6(%s)%s",
9436 &attr->mp_nexthop_local,
9437 nexthop_hostname,
9438 vrf_id_str);
9439 else
9440 len = vty_out(
9441 vty, "%pI6%s",
9442 &attr->mp_nexthop_local,
9443 vrf_id_str);
9444
ae248832 9445 len = wide ? (41 - len) : (16 - len);
d62a17ae 9446
9447 if (len < 1)
a4d82a8a 9448 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9449 else
a4d82a8a 9450 vty_out(vty, "%*s", len, " ");
d62a17ae 9451 }
445c2480 9452 } else {
aef999a2
DA
9453 if (nexthop_hostname)
9454 len = vty_out(vty, "%pI6(%s)%s",
9455 &attr->mp_nexthop_global,
9456 nexthop_hostname,
9457 vrf_id_str);
9458 else
9459 len = vty_out(vty, "%pI6%s",
9460 &attr->mp_nexthop_global,
9461 vrf_id_str);
9462
ae248832 9463 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9464
9465 if (len < 1)
9466 vty_out(vty, "\n%*s", 36, " ");
9467 else
9468 vty_out(vty, "%*s", len, " ");
d62a17ae 9469 }
9470 }
445c2480 9471 }
718e3744 9472
445c2480
DS
9473 /* MED/Metric */
9474 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9475 if (json_paths)
50e05855 9476 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9477 else if (wide)
9478 vty_out(vty, "%7u", attr->med);
0fbac0b4 9479 else
445c2480 9480 vty_out(vty, "%10u", attr->med);
ae248832
MK
9481 else if (!json_paths) {
9482 if (wide)
9483 vty_out(vty, "%*s", 7, " ");
9484 else
9485 vty_out(vty, "%*s", 10, " ");
9486 }
d62a17ae 9487
445c2480
DS
9488 /* Local Pref */
9489 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9490 if (json_paths)
50e05855 9491 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9492 attr->local_pref);
9493 else
445c2480
DS
9494 vty_out(vty, "%7u", attr->local_pref);
9495 else if (!json_paths)
9496 vty_out(vty, " ");
d62a17ae 9497
445c2480
DS
9498 if (json_paths)
9499 json_object_int_add(json_path, "weight", attr->weight);
9500 else
9501 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9502
47e12884
DA
9503 if (json_paths)
9504 json_object_string_addf(json_path, "peerId", "%pSU",
9505 &path->peer->su);
b05a1c8b 9506
445c2480
DS
9507 /* Print aspath */
9508 if (attr->aspath) {
0fbac0b4 9509 if (json_paths)
50e05855 9510 json_object_string_add(json_path, "path",
0fbac0b4
DA
9511 attr->aspath->str);
9512 else
445c2480 9513 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9514 }
f1aa5d8a 9515
445c2480
DS
9516 /* Print origin */
9517 if (json_paths)
a4d82a8a
PZ
9518 json_object_string_add(json_path, "origin",
9519 bgp_origin_long_str[attr->origin]);
445c2480
DS
9520 else
9521 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9522
9df8b37c 9523 if (json_paths) {
d071f237 9524 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9525 json_object_string_add(json_path, "esi",
9526 esi_to_str(&attr->esi,
9527 esi_buf, sizeof(esi_buf)));
9528 }
6f214dd3
CS
9529 if (safi == SAFI_EVPN &&
9530 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9531 json_ext_community = json_object_new_object();
b53e67a3
DA
9532 json_object_string_add(
9533 json_ext_community, "string",
9534 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9535 json_object_object_add(json_path,
9536 "extendedCommunity",
9537 json_ext_community);
9538 }
9539
9df8b37c
PZ
9540 if (nexthop_self)
9541 json_object_boolean_true_add(json_path,
9542 "announceNexthopSelf");
9543 if (nexthop_othervrf) {
9544 json_object_string_add(json_path, "nhVrfName",
9545 nexthop_vrfname);
9546
9547 json_object_int_add(json_path, "nhVrfId",
9548 ((nexthop_vrfid == VRF_UNKNOWN)
9549 ? -1
9550 : (int)nexthop_vrfid));
9551 }
9552 }
9553
d62a17ae 9554 if (json_paths) {
9555 if (json_nexthop_global || json_nexthop_ll) {
9556 json_nexthops = json_object_new_array();
f1aa5d8a 9557
d62a17ae 9558 if (json_nexthop_global)
9559 json_object_array_add(json_nexthops,
9560 json_nexthop_global);
f1aa5d8a 9561
d62a17ae 9562 if (json_nexthop_ll)
9563 json_object_array_add(json_nexthops,
9564 json_nexthop_ll);
f1aa5d8a 9565
d62a17ae 9566 json_object_object_add(json_path, "nexthops",
9567 json_nexthops);
9568 }
9569
9570 json_object_array_add(json_paths, json_path);
9571 } else {
9572 vty_out(vty, "\n");
6f214dd3 9573
b5e140c8 9574 if (safi == SAFI_EVPN) {
d071f237 9575 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9576 /* XXX - add these params to the json out */
b5e140c8 9577 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9578 vty_out(vty, "ESI:%s",
9579 esi_to_str(&attr->esi, esi_buf,
9580 sizeof(esi_buf)));
60605cbc 9581
229587fb 9582 vty_out(vty, "\n");
b5e140c8
AK
9583 }
9584 if (attr->flag &
9585 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9586 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9587 vty_out(vty, "%s\n",
9588 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9589 }
6f214dd3
CS
9590 }
9591
49e5a4a0 9592#ifdef ENABLE_BGP_VNC
d62a17ae 9593 /* prints an additional line, indented, with VNC info, if
9594 * present */
9595 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9596 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9597#endif
d62a17ae 9598 }
9599}
718e3744 9600
9601/* called from terminal list command */
7d3cae70
DA
9602void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9603 const struct prefix *p, struct attr *attr, safi_t safi,
9604 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9605{
9606 json_object *json_status = NULL;
9607 json_object *json_net = NULL;
aef999a2 9608 int len;
d62a17ae 9609 char buff[BUFSIZ];
dc387b0f 9610
d62a17ae 9611 /* Route status display. */
9612 if (use_json) {
9613 json_status = json_object_new_object();
9614 json_net = json_object_new_object();
9615 } else {
146c574b 9616 vty_out(vty, " *");
d62a17ae 9617 vty_out(vty, ">");
9618 vty_out(vty, " ");
9619 }
718e3744 9620
d62a17ae 9621 /* print prefix and mask */
50e05855 9622 if (use_json) {
dc387b0f
LK
9623 if (safi == SAFI_EVPN)
9624 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9625 else if (p->family == AF_INET || p->family == AF_INET6) {
9626 json_object_string_add(
9627 json_net, "addrPrefix",
9628 inet_ntop(p->family, &p->u.prefix, buff,
9629 BUFSIZ));
9630 json_object_int_add(json_net, "prefixLen",
9631 p->prefixlen);
67d7e256 9632 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9633 }
50e05855 9634 } else
7d3cae70 9635 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9636
9637 /* Print attribute */
9638 if (attr) {
9639 if (use_json) {
7226bc40
TA
9640 if (p->family == AF_INET &&
9641 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9642 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9643 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9644 json_object_string_addf(
9645 json_net, "nextHop", "%pI4",
9646 &attr->mp_nexthop_global_in);
d62a17ae 9647 else
c949c771
DA
9648 json_object_string_addf(
9649 json_net, "nextHop", "%pI4",
9650 &attr->nexthop);
7226bc40
TA
9651 } else if (p->family == AF_INET6 ||
9652 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9653 json_object_string_addf(
9654 json_net, "nextHopGlobal", "%pI6",
9655 &attr->mp_nexthop_global);
7226bc40
TA
9656 } else if (p->family == AF_EVPN &&
9657 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9658 json_object_string_addf(
9659 json_net, "nextHop", "%pI4",
9660 &attr->mp_nexthop_global_in);
23d0a753 9661 }
d62a17ae 9662
9663 if (attr->flag
9664 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9665 json_object_int_add(json_net, "metric",
9666 attr->med);
9667
0fbac0b4 9668 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9669 json_object_int_add(json_net, "locPrf",
0fbac0b4 9670 attr->local_pref);
d62a17ae 9671
9672 json_object_int_add(json_net, "weight", attr->weight);
9673
9674 /* Print aspath */
0fbac0b4 9675 if (attr->aspath)
50e05855 9676 json_object_string_add(json_net, "path",
0fbac0b4 9677 attr->aspath->str);
d62a17ae 9678
9679 /* Print origin */
9680 json_object_string_add(json_net, "bgpOriginCode",
9681 bgp_origin_str[attr->origin]);
9682 } else {
7226bc40
TA
9683 if (p->family == AF_INET &&
9684 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9685 safi == SAFI_EVPN ||
9686 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9687 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9688 || safi == SAFI_EVPN)
23d0a753
DA
9689 vty_out(vty, "%-16pI4",
9690 &attr->mp_nexthop_global_in);
ae248832 9691 else if (wide)
23d0a753 9692 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9693 else
23d0a753 9694 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9695 } else if (p->family == AF_INET6 ||
9696 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9697 len = vty_out(vty, "%pI6",
9698 &attr->mp_nexthop_global);
ae248832 9699 len = wide ? (41 - len) : (16 - len);
d62a17ae 9700 if (len < 1)
9701 vty_out(vty, "\n%*s", 36, " ");
9702 else
9703 vty_out(vty, "%*s", len, " ");
9704 }
9705 if (attr->flag
9706 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9707 if (wide)
9708 vty_out(vty, "%7u", attr->med);
9709 else
9710 vty_out(vty, "%10u", attr->med);
9711 else if (wide)
9712 vty_out(vty, " ");
d62a17ae 9713 else
9714 vty_out(vty, " ");
718e3744 9715
d62a17ae 9716 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9717 vty_out(vty, "%7u", attr->local_pref);
9718 else
9719 vty_out(vty, " ");
9720
9721 vty_out(vty, "%7u ", attr->weight);
9722
9723 /* Print aspath */
9724 if (attr->aspath)
9725 aspath_print_vty(vty, "%s", attr->aspath, " ");
9726
9727 /* Print origin */
9728 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9729 }
9730 }
9731 if (use_json) {
9732 json_object_boolean_true_add(json_status, "*");
9733 json_object_boolean_true_add(json_status, ">");
9734 json_object_object_add(json_net, "appliedStatusSymbols",
9735 json_status);
511211bf 9736 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9737 } else
9738 vty_out(vty, "\n");
9739}
9740
bd494ec5 9741void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9742 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9743 json_object *json)
9744{
9745 json_object *json_out = NULL;
9746 struct attr *attr;
9747 mpls_label_t label = MPLS_INVALID_LABEL;
9748
9b6d8fcf 9749 if (!path->extra)
d62a17ae 9750 return;
9751
9752 if (json)
9753 json_out = json_object_new_object();
9754
9755 /* short status lead text */
82c298be 9756 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9757
9758 /* print prefix and mask */
9759 if (json == NULL) {
9760 if (!display)
7d3cae70 9761 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9762 else
9763 vty_out(vty, "%*s", 17, " ");
9764 }
9765
9766 /* Print attribute */
9b6d8fcf 9767 attr = path->attr;
7226bc40
TA
9768 if (((p->family == AF_INET) &&
9769 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9770 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9771 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9772 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9773 || safi == SAFI_EVPN) {
9774 if (json)
c949c771
DA
9775 json_object_string_addf(
9776 json_out, "mpNexthopGlobalIn", "%pI4",
9777 &attr->mp_nexthop_global_in);
05864da7 9778 else
23d0a753
DA
9779 vty_out(vty, "%-16pI4",
9780 &attr->mp_nexthop_global_in);
05864da7
DS
9781 } else {
9782 if (json)
c949c771
DA
9783 json_object_string_addf(json_out, "nexthop",
9784 "%pI4", &attr->nexthop);
05864da7 9785 else
23d0a753 9786 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9787 }
7226bc40
TA
9788 } else if (((p->family == AF_INET6) &&
9789 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9790 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9791 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9792 char buf_a[512];
9793
9794 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9795 if (json)
c949c771
DA
9796 json_object_string_addf(
9797 json_out, "mpNexthopGlobalIn", "%pI6",
9798 &attr->mp_nexthop_global);
05864da7
DS
9799 else
9800 vty_out(vty, "%s",
9801 inet_ntop(AF_INET6,
9802 &attr->mp_nexthop_global,
9803 buf_a, sizeof(buf_a)));
9804 } else if (attr->mp_nexthop_len
9805 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9806 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9807 &attr->mp_nexthop_global,
9808 &attr->mp_nexthop_local);
9809 if (json)
9810 json_object_string_add(json_out,
9811 "mpNexthopGlobalLocal",
9812 buf_a);
9813 else
9814 vty_out(vty, "%s", buf_a);
d62a17ae 9815 }
9816 }
9817
9b6d8fcf 9818 label = decode_label(&path->extra->label[0]);
d62a17ae 9819
9820 if (bgp_is_valid_label(&label)) {
9821 if (json) {
9822 json_object_int_add(json_out, "notag", label);
9823 json_object_array_add(json, json_out);
9824 } else {
9825 vty_out(vty, "notag/%d", label);
9826 vty_out(vty, "\n");
9827 }
700ddfed
PG
9828 } else if (!json)
9829 vty_out(vty, "\n");
d62a17ae 9830}
718e3744 9831
bd494ec5 9832void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9833 struct bgp_path_info *path, int display,
d62a17ae 9834 json_object *json_paths)
718e3744 9835{
d62a17ae 9836 struct attr *attr;
d62a17ae 9837 json_object *json_path = NULL;
14f51eba
LK
9838 json_object *json_nexthop = NULL;
9839 json_object *json_overlay = NULL;
856ca177 9840
9b6d8fcf 9841 if (!path->extra)
d62a17ae 9842 return;
718e3744 9843
14f51eba
LK
9844 if (json_paths) {
9845 json_path = json_object_new_object();
9846 json_overlay = json_object_new_object();
9847 json_nexthop = json_object_new_object();
9848 }
9849
d62a17ae 9850 /* short status lead text */
82c298be 9851 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9852
d62a17ae 9853 /* print prefix and mask */
9854 if (!display)
7d3cae70 9855 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9856 else
9857 vty_out(vty, "%*s", 17, " ");
9858
9859 /* Print attribute */
9b6d8fcf 9860 attr = path->attr;
05864da7 9861 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9862
05864da7
DS
9863 switch (af) {
9864 case AF_INET:
05864da7 9865 if (!json_path) {
db66cf7c 9866 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9867 } else {
db66cf7c
DA
9868 json_object_string_addf(json_nexthop, "ip", "%pI4",
9869 &attr->mp_nexthop_global_in);
14f51eba 9870
05864da7 9871 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9872
05864da7
DS
9873 json_object_object_add(json_path, "nexthop",
9874 json_nexthop);
9875 }
9876 break;
9877 case AF_INET6:
05864da7 9878 if (!json_path) {
db66cf7c
DA
9879 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9880 &attr->mp_nexthop_local);
05864da7 9881 } else {
db66cf7c
DA
9882 json_object_string_addf(json_nexthop, "ipv6Global",
9883 "%pI6",
9884 &attr->mp_nexthop_global);
14f51eba 9885
db66cf7c
DA
9886 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9887 "%pI6",
9888 &attr->mp_nexthop_local);
14f51eba 9889
05864da7 9890 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9891
05864da7
DS
9892 json_object_object_add(json_path, "nexthop",
9893 json_nexthop);
9894 }
9895 break;
9896 default:
9897 if (!json_path) {
9898 vty_out(vty, "?");
9899 } else {
9900 json_object_string_add(json_nexthop, "Error",
9901 "Unsupported address-family");
77a2f8e5
DA
9902 json_object_string_add(json_nexthop, "error",
9903 "Unsupported address-family");
d62a17ae 9904 }
05864da7 9905 }
988258b4 9906
6c924775
DS
9907 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9908
05864da7 9909 if (!json_path)
db66cf7c 9910 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9911 else
db66cf7c 9912 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9913
b53e67a3 9914 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9915 char *mac = NULL;
9916 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9917 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9918 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9919
9920 if (routermac)
9921 mac = ecom_mac2str((char *)routermac->val);
9922 if (mac) {
9923 if (!json_path) {
c4efd0f4 9924 vty_out(vty, "/%s", mac);
05864da7
DS
9925 } else {
9926 json_object_string_add(json_overlay, "rmac",
9927 mac);
988258b4 9928 }
05864da7 9929 XFREE(MTYPE_TMP, mac);
988258b4 9930 }
05864da7 9931 }
718e3744 9932
05864da7
DS
9933 if (!json_path) {
9934 vty_out(vty, "\n");
9935 } else {
9936 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9937
05864da7 9938 json_object_array_add(json_paths, json_path);
14f51eba 9939 }
d62a17ae 9940}
718e3744 9941
d62a17ae 9942/* dampening route */
5f040085
DS
9943static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9944 struct bgp_path_info *path, int display,
9945 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9946 json_object *json_paths)
d62a17ae 9947{
e5be8c1d 9948 struct attr *attr = path->attr;
d62a17ae 9949 int len;
9950 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9951 json_object *json_path = NULL;
9952
9953 if (use_json)
9954 json_path = json_object_new_object();
d62a17ae 9955
9956 /* short status lead text */
e5be8c1d 9957 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9958
9959 /* print prefix and mask */
9960 if (!use_json) {
9961 if (!display)
7d3cae70 9962 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9963 else
9964 vty_out(vty, "%*s", 17, " ");
d62a17ae 9965
e5be8c1d
DA
9966 len = vty_out(vty, "%s", path->peer->host);
9967 len = 17 - len;
9968
9969 if (len < 1)
d62a17ae 9970 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9971 else
9972 vty_out(vty, "%*s", len, " ");
d62a17ae 9973
9b6d8fcf
DS
9974 vty_out(vty, "%s ",
9975 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9976 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9977 use_json, NULL));
d62a17ae 9978
e5be8c1d 9979 if (attr->aspath)
05864da7 9980 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9981
05864da7
DS
9982 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9983
d62a17ae 9984 vty_out(vty, "\n");
e5be8c1d
DA
9985 } else {
9986 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9987 safi, use_json, json_path);
9988
9989 if (attr->aspath)
9990 json_object_string_add(json_path, "asPath",
9991 attr->aspath->str);
9992
9993 json_object_string_add(json_path, "origin",
9994 bgp_origin_str[attr->origin]);
9995 json_object_string_add(json_path, "peerHost", path->peer->host);
9996
9997 json_object_array_add(json_paths, json_path);
9998 }
d62a17ae 9999}
718e3744 10000
d62a17ae 10001/* flap route */
5f040085
DS
10002static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10003 struct bgp_path_info *path, int display,
10004 afi_t afi, safi_t safi, bool use_json,
31258046 10005 json_object *json_paths)
784d3a42 10006{
31258046 10007 struct attr *attr = path->attr;
d62a17ae 10008 struct bgp_damp_info *bdi;
10009 char timebuf[BGP_UPTIME_LEN];
10010 int len;
31258046 10011 json_object *json_path = NULL;
784d3a42 10012
9b6d8fcf 10013 if (!path->extra)
d62a17ae 10014 return;
784d3a42 10015
31258046
DA
10016 if (use_json)
10017 json_path = json_object_new_object();
10018
9b6d8fcf 10019 bdi = path->extra->damp_info;
784d3a42 10020
d62a17ae 10021 /* short status lead text */
31258046 10022 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10023
d62a17ae 10024 if (!use_json) {
10025 if (!display)
7d3cae70 10026 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10027 else
10028 vty_out(vty, "%*s", 17, " ");
784d3a42 10029
31258046
DA
10030 len = vty_out(vty, "%s", path->peer->host);
10031 len = 16 - len;
10032 if (len < 1)
d62a17ae 10033 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10034 else
10035 vty_out(vty, "%*s", len, " ");
784d3a42 10036
31258046
DA
10037 len = vty_out(vty, "%d", bdi->flap);
10038 len = 5 - len;
10039 if (len < 1)
d62a17ae 10040 vty_out(vty, " ");
d62a17ae 10041 else
10042 vty_out(vty, "%*s", len, " ");
d62a17ae 10043
996c9314
LB
10044 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10045 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10046
31258046
DA
10047 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10048 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10049 vty_out(vty, "%s ",
9b6d8fcf 10050 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10051 BGP_UPTIME_LEN, afi,
31258046
DA
10052 safi, use_json, NULL));
10053 else
d62a17ae 10054 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10055
31258046 10056 if (attr->aspath)
05864da7 10057 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10058
05864da7
DS
10059 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10060
d62a17ae 10061 vty_out(vty, "\n");
31258046
DA
10062 } else {
10063 json_object_string_add(json_path, "peerHost", path->peer->host);
10064 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10065
10066 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10067 json_path);
10068
10069 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10070 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10071 bgp_damp_reuse_time_vty(vty, path, timebuf,
10072 BGP_UPTIME_LEN, afi, safi,
10073 use_json, json_path);
10074
10075 if (attr->aspath)
10076 json_object_string_add(json_path, "asPath",
10077 attr->aspath->str);
10078
10079 json_object_string_add(json_path, "origin",
10080 bgp_origin_str[attr->origin]);
10081
10082 json_object_array_add(json_paths, json_path);
10083 }
d62a17ae 10084}
10085
10086static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10087 int *first, const char *header,
10088 json_object *json_adv_to)
10089{
d62a17ae 10090 json_object *json_peer = NULL;
10091
10092 if (json_adv_to) {
10093 /* 'advertised-to' is a dictionary of peers we have advertised
10094 * this
10095 * prefix too. The key is the peer's IP or swpX, the value is
10096 * the
10097 * hostname if we know it and "" if not.
10098 */
10099 json_peer = json_object_new_object();
10100
10101 if (peer->hostname)
10102 json_object_string_add(json_peer, "hostname",
10103 peer->hostname);
10104
10105 if (peer->conf_if)
10106 json_object_object_add(json_adv_to, peer->conf_if,
10107 json_peer);
10108 else
47e12884
DA
10109 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10110 &peer->su);
d62a17ae 10111 } else {
10112 if (*first) {
10113 vty_out(vty, "%s", header);
10114 *first = 0;
10115 }
10116
10117 if (peer->hostname
892fedb6 10118 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10119 if (peer->conf_if)
10120 vty_out(vty, " %s(%s)", peer->hostname,
10121 peer->conf_if);
10122 else
47e12884
DA
10123 vty_out(vty, " %s(%pSU)", peer->hostname,
10124 &peer->su);
d62a17ae 10125 } else {
10126 if (peer->conf_if)
10127 vty_out(vty, " %s", peer->conf_if);
10128 else
47e12884 10129 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10130 }
10131 }
784d3a42
PG
10132}
10133
dcc68b5e
MS
10134static void route_vty_out_tx_ids(struct vty *vty,
10135 struct bgp_addpath_info_data *d)
10136{
10137 int i;
10138
10139 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10140 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10141 d->addpath_tx_id[i],
10142 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10143 }
10144}
10145
5e4d4c8a 10146static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10147 struct bgp_path_info *pi,
10148 struct attr *attr,
10149 json_object *json_path)
5e4d4c8a
AK
10150{
10151 char esi_buf[ESI_STR_LEN];
10152 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10153 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10154 ATTR_ES_PEER_ROUTER);
10155 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10156 ATTR_ES_PEER_ACTIVE);
10157 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10158 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10159 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10160 if (json_path) {
10161 json_object *json_es_info = NULL;
10162
10163 json_object_string_add(
10164 json_path, "esi",
10165 esi_buf);
10166 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10167 json_es_info = json_object_new_object();
10168 if (es_local)
10169 json_object_boolean_true_add(
10170 json_es_info, "localEs");
10171 if (peer_active)
10172 json_object_boolean_true_add(
10173 json_es_info, "peerActive");
10174 if (peer_proxy)
10175 json_object_boolean_true_add(
10176 json_es_info, "peerProxy");
10177 if (peer_router)
10178 json_object_boolean_true_add(
10179 json_es_info, "peerRouter");
10180 if (attr->mm_sync_seqnum)
10181 json_object_int_add(
10182 json_es_info, "peerSeq",
10183 attr->mm_sync_seqnum);
10184 json_object_object_add(
10185 json_path, "es_info",
10186 json_es_info);
10187 }
10188 } else {
10189 if (bgp_evpn_attr_is_sync(attr))
10190 vty_out(vty,
10191 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10192 esi_buf,
10193 es_local ? "local-es":"",
10194 peer_proxy ? "proxy " : "",
10195 peer_active ? "active ":"",
10196 peer_router ? "router ":"",
10197 attr->mm_sync_seqnum);
10198 else
10199 vty_out(vty, " ESI %s %s\n",
10200 esi_buf,
10201 es_local ? "local-es":"");
10202 }
10203}
10204
4933eaaf 10205void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10206 const struct prefix *p, struct bgp_path_info *path,
10207 afi_t afi, safi_t safi,
4027d19b
DS
10208 enum rpki_states rpki_curr_state,
10209 json_object *json_paths)
d62a17ae 10210{
10211 char buf[INET6_ADDRSTRLEN];
100290e4 10212 char tag_buf[30];
515c2602 10213 struct attr *attr = path->attr;
d62a17ae 10214 time_t tbuf;
10215 json_object *json_bestpath = NULL;
10216 json_object *json_cluster_list = NULL;
10217 json_object *json_cluster_list_list = NULL;
10218 json_object *json_ext_community = NULL;
10219 json_object *json_last_update = NULL;
7fd077aa 10220 json_object *json_pmsi = NULL;
d62a17ae 10221 json_object *json_nexthop_global = NULL;
10222 json_object *json_nexthop_ll = NULL;
10223 json_object *json_nexthops = NULL;
10224 json_object *json_path = NULL;
10225 json_object *json_peer = NULL;
10226 json_object *json_string = NULL;
10227 json_object *json_adv_to = NULL;
10228 int first = 0;
10229 struct listnode *node, *nnode;
10230 struct peer *peer;
be92fc9f 10231 bool addpath_capable;
d62a17ae 10232 int has_adj;
10233 unsigned int first_as;
1defdda8 10234 bool nexthop_self =
9b6d8fcf 10235 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10236 int i;
2ba93fd6
DA
10237 char *nexthop_hostname =
10238 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10239 uint32_t ttl = 0;
10240 uint32_t bos = 0;
10241 uint32_t exp = 0;
10242 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10243 tag_buf[0] = '\0';
d62a17ae 10244
10245 if (json_paths) {
10246 json_path = json_object_new_object();
10247 json_peer = json_object_new_object();
10248 json_nexthop_global = json_object_new_object();
10249 }
10250
8304dabf
AD
10251 if (safi == SAFI_EVPN) {
10252 if (!json_paths)
34c7f35f 10253 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10254 }
10255
44c69747 10256 if (path->extra) {
9b6d8fcf
DS
10257 if (path->extra && path->extra->num_labels) {
10258 bgp_evpn_label2str(path->extra->label,
10259 path->extra->num_labels, tag_buf,
a4d82a8a 10260 sizeof(tag_buf));
d62a17ae 10261 }
d7325ee7 10262 if (safi == SAFI_EVPN) {
44c69747 10263 if (!json_paths) {
44c69747
LK
10264 if (tag_buf[0] != '\0')
10265 vty_out(vty, " VNI %s", tag_buf);
44c69747 10266 } else {
77a2f8e5 10267 if (tag_buf[0]) {
44c69747
LK
10268 json_object_string_add(json_path, "VNI",
10269 tag_buf);
77a2f8e5
DA
10270 json_object_string_add(json_path, "vni",
10271 tag_buf);
10272 }
44c69747 10273 }
d7325ee7 10274 }
d62a17ae 10275 }
d62a17ae 10276
8304dabf
AD
10277 if (safi == SAFI_EVPN
10278 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10279 char gwip_buf[INET6_ADDRSTRLEN];
10280
860e740b
IR
10281 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10282 sizeof(gwip_buf));
8304dabf
AD
10283
10284 if (json_paths)
10285 json_object_string_add(json_path, "gatewayIP",
10286 gwip_buf);
10287 else
10288 vty_out(vty, " Gateway IP %s", gwip_buf);
10289 }
10290
2bf9780b 10291 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10292 vty_out(vty, "\n");
10293
100290e4
SW
10294
10295 if (path->extra && path->extra->parent && !json_paths) {
10296 struct bgp_path_info *parent_ri;
10297 struct bgp_dest *dest, *pdest;
10298
10299 parent_ri = (struct bgp_path_info *)path->extra->parent;
10300 dest = parent_ri->net;
10301 if (dest && dest->pdest) {
10302 pdest = dest->pdest;
10303 if (is_pi_family_evpn(parent_ri)) {
10304 vty_out(vty,
10305 " Imported from %pRD:%pFX, VNI %s",
10306 (struct prefix_rd *)bgp_dest_get_prefix(
10307 pdest),
10308 (struct prefix_evpn *)
10309 bgp_dest_get_prefix(dest),
10310 tag_buf);
6012963e 10311 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10312 vty_out(vty, ", L3NHG %s",
6012963e
SW
10313 CHECK_FLAG(
10314 attr->es_flags,
10315 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10316 ? "active"
10317 : "inactive");
10318 vty_out(vty, "\n");
10319
10320 } else
10321 vty_out(vty, " Imported from %pRD:%pFX\n",
10322 (struct prefix_rd *)bgp_dest_get_prefix(
10323 pdest),
10324 (struct prefix_evpn *)
10325 bgp_dest_get_prefix(dest));
10326 }
10327 }
10328
05864da7
DS
10329 /* Line1 display AS-path, Aggregator */
10330 if (attr->aspath) {
10331 if (json_paths) {
10332 if (!attr->aspath->json)
10333 aspath_str_update(attr->aspath, true);
10334 json_object_lock(attr->aspath->json);
10335 json_object_object_add(json_path, "aspath",
10336 attr->aspath->json);
10337 } else {
10338 if (attr->aspath->segments)
10339 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10340 else
05864da7 10341 vty_out(vty, " Local");
d62a17ae 10342 }
05864da7 10343 }
d62a17ae 10344
05864da7
DS
10345 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10346 if (json_paths)
10347 json_object_boolean_true_add(json_path, "removed");
10348 else
10349 vty_out(vty, ", (removed)");
10350 }
d62a17ae 10351
05864da7
DS
10352 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10353 if (json_paths)
10354 json_object_boolean_true_add(json_path, "stale");
10355 else
10356 vty_out(vty, ", (stale)");
10357 }
d62a17ae 10358
05864da7
DS
10359 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10360 if (json_paths) {
10361 json_object_int_add(json_path, "aggregatorAs",
10362 attr->aggregator_as);
c949c771
DA
10363 json_object_string_addf(json_path, "aggregatorId",
10364 "%pI4", &attr->aggregator_addr);
05864da7 10365 } else {
88d495a9
DA
10366 vty_out(vty, ", (aggregated by %u %pI4)",
10367 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10368 }
05864da7 10369 }
d62a17ae 10370
05864da7
DS
10371 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10372 PEER_FLAG_REFLECTOR_CLIENT)) {
10373 if (json_paths)
10374 json_object_boolean_true_add(json_path,
10375 "rxedFromRrClient");
10376 else
10377 vty_out(vty, ", (Received from a RR-client)");
10378 }
d62a17ae 10379
05864da7
DS
10380 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10381 PEER_FLAG_RSERVER_CLIENT)) {
10382 if (json_paths)
10383 json_object_boolean_true_add(json_path,
10384 "rxedFromRsClient");
10385 else
10386 vty_out(vty, ", (Received from a RS-client)");
10387 }
d62a17ae 10388
05864da7
DS
10389 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10390 if (json_paths)
10391 json_object_boolean_true_add(json_path,
10392 "dampeningHistoryEntry");
10393 else
10394 vty_out(vty, ", (history entry)");
10395 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10396 if (json_paths)
10397 json_object_boolean_true_add(json_path,
10398 "dampeningSuppressed");
10399 else
10400 vty_out(vty, ", (suppressed due to dampening)");
10401 }
d62a17ae 10402
05864da7
DS
10403 if (!json_paths)
10404 vty_out(vty, "\n");
d62a17ae 10405
05864da7
DS
10406 /* Line2 display Next-hop, Neighbor, Router-id */
10407 /* Display the nexthop */
b54892e0 10408
34c7f35f
SW
10409 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10410 p->family == AF_EVPN) &&
7226bc40
TA
10411 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10412 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10413 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10414 || safi == SAFI_EVPN) {
515c2602 10415 if (json_paths) {
c949c771
DA
10416 json_object_string_addf(
10417 json_nexthop_global, "ip", "%pI4",
10418 &attr->mp_nexthop_global_in);
515c2602 10419
939a97f4 10420 if (path->peer->hostname)
515c2602
DA
10421 json_object_string_add(
10422 json_nexthop_global, "hostname",
939a97f4 10423 path->peer->hostname);
aef999a2
DA
10424 } else {
10425 if (nexthop_hostname)
10426 vty_out(vty, " %pI4(%s)",
10427 &attr->mp_nexthop_global_in,
10428 nexthop_hostname);
10429 else
10430 vty_out(vty, " %pI4",
10431 &attr->mp_nexthop_global_in);
10432 }
d62a17ae 10433 } else {
515c2602 10434 if (json_paths) {
c949c771
DA
10435 json_object_string_addf(json_nexthop_global,
10436 "ip", "%pI4",
10437 &attr->nexthop);
515c2602 10438
939a97f4 10439 if (path->peer->hostname)
515c2602
DA
10440 json_object_string_add(
10441 json_nexthop_global, "hostname",
939a97f4 10442 path->peer->hostname);
aef999a2
DA
10443 } else {
10444 if (nexthop_hostname)
10445 vty_out(vty, " %pI4(%s)",
10446 &attr->nexthop,
10447 nexthop_hostname);
10448 else
10449 vty_out(vty, " %pI4",
10450 &attr->nexthop);
10451 }
d62a17ae 10452 }
10453
05864da7
DS
10454 if (json_paths)
10455 json_object_string_add(json_nexthop_global, "afi",
10456 "ipv4");
10457 } else {
10458 if (json_paths) {
c949c771
DA
10459 json_object_string_addf(json_nexthop_global, "ip",
10460 "%pI6",
10461 &attr->mp_nexthop_global);
515c2602 10462
939a97f4 10463 if (path->peer->hostname)
515c2602
DA
10464 json_object_string_add(json_nexthop_global,
10465 "hostname",
939a97f4 10466 path->peer->hostname);
515c2602 10467
05864da7
DS
10468 json_object_string_add(json_nexthop_global, "afi",
10469 "ipv6");
10470 json_object_string_add(json_nexthop_global, "scope",
10471 "global");
10472 } else {
aef999a2
DA
10473 if (nexthop_hostname)
10474 vty_out(vty, " %pI6(%s)",
10475 &attr->mp_nexthop_global,
10476 nexthop_hostname);
10477 else
10478 vty_out(vty, " %pI6",
10479 &attr->mp_nexthop_global);
d62a17ae 10480 }
05864da7 10481 }
d62a17ae 10482
05864da7
DS
10483 /* Display the IGP cost or 'inaccessible' */
10484 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10485 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10486
10487 if (json_paths) {
05864da7
DS
10488 json_object_boolean_false_add(json_nexthop_global,
10489 "accessible");
95ba22d5
DA
10490 json_object_boolean_add(json_nexthop_global,
10491 "importCheckEnabled", import);
10492 } else {
10493 vty_out(vty, " (inaccessible%s)",
10494 import ? ", import-check enabled" : "");
10495 }
05864da7
DS
10496 } else {
10497 if (path->extra && path->extra->igpmetric) {
d62a17ae 10498 if (json_paths)
05864da7
DS
10499 json_object_int_add(json_nexthop_global,
10500 "metric",
10501 path->extra->igpmetric);
d62a17ae 10502 else
05864da7
DS
10503 vty_out(vty, " (metric %u)",
10504 path->extra->igpmetric);
d62a17ae 10505 }
10506
05864da7 10507 /* IGP cost is 0, display this only for json */
d62a17ae 10508 else {
d62a17ae 10509 if (json_paths)
05864da7
DS
10510 json_object_int_add(json_nexthop_global,
10511 "metric", 0);
d62a17ae 10512 }
d62a17ae 10513
05864da7
DS
10514 if (json_paths)
10515 json_object_boolean_true_add(json_nexthop_global,
10516 "accessible");
10517 }
d62a17ae 10518
05864da7
DS
10519 /* Display peer "from" output */
10520 /* This path was originated locally */
10521 if (path->peer == bgp->peer_self) {
d62a17ae 10522
34c7f35f 10523 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10524 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10525 if (json_paths)
05864da7
DS
10526 json_object_string_add(json_peer, "peerId",
10527 "0.0.0.0");
d62a17ae 10528 else
05864da7
DS
10529 vty_out(vty, " from 0.0.0.0 ");
10530 } else {
d62a17ae 10531 if (json_paths)
05864da7
DS
10532 json_object_string_add(json_peer, "peerId",
10533 "::");
d62a17ae 10534 else
05864da7 10535 vty_out(vty, " from :: ");
d62a17ae 10536 }
d62a17ae 10537
4e9a9863 10538 if (json_paths)
c949c771
DA
10539 json_object_string_addf(json_peer, "routerId", "%pI4",
10540 &bgp->router_id);
4e9a9863 10541 else
23d0a753 10542 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10543 }
d62a17ae 10544
05864da7
DS
10545 /* We RXed this path from one of our peers */
10546 else {
10547
10548 if (json_paths) {
47e12884
DA
10549 json_object_string_addf(json_peer, "peerId", "%pSU",
10550 &path->peer->su);
c949c771
DA
10551 json_object_string_addf(json_peer, "routerId", "%pI4",
10552 &path->peer->remote_id);
05864da7
DS
10553
10554 if (path->peer->hostname)
10555 json_object_string_add(json_peer, "hostname",
10556 path->peer->hostname);
10557
10558 if (path->peer->domainname)
10559 json_object_string_add(json_peer, "domainname",
10560 path->peer->domainname);
10561
10562 if (path->peer->conf_if)
10563 json_object_string_add(json_peer, "interface",
10564 path->peer->conf_if);
10565 } else {
10566 if (path->peer->conf_if) {
10567 if (path->peer->hostname
892fedb6
DA
10568 && CHECK_FLAG(path->peer->bgp->flags,
10569 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10570 vty_out(vty, " from %s(%s)",
10571 path->peer->hostname,
10572 path->peer->conf_if);
d62a17ae 10573 else
05864da7 10574 vty_out(vty, " from %s",
9b6d8fcf 10575 path->peer->conf_if);
d62a17ae 10576 } else {
05864da7 10577 if (path->peer->hostname
892fedb6
DA
10578 && CHECK_FLAG(path->peer->bgp->flags,
10579 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10580 vty_out(vty, " from %s(%s)",
10581 path->peer->hostname,
10582 path->peer->host);
d62a17ae 10583 else
47e12884
DA
10584 vty_out(vty, " from %pSU",
10585 &path->peer->su);
d62a17ae 10586 }
d62a17ae 10587
05864da7 10588 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10589 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10590 else
07380148 10591 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10592 }
05864da7 10593 }
9df8b37c 10594
05864da7
DS
10595 /*
10596 * Note when vrfid of nexthop is different from that of prefix
10597 */
10598 if (path->extra && path->extra->bgp_orig) {
10599 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10600
05864da7
DS
10601 if (json_paths) {
10602 const char *vn;
9df8b37c 10603
05864da7
DS
10604 if (path->extra->bgp_orig->inst_type
10605 == BGP_INSTANCE_TYPE_DEFAULT)
10606 vn = VRF_DEFAULT_NAME;
10607 else
10608 vn = path->extra->bgp_orig->name;
9df8b37c 10609
05864da7 10610 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10611
05864da7
DS
10612 if (nexthop_vrfid == VRF_UNKNOWN) {
10613 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10614 } else {
05864da7
DS
10615 json_object_int_add(json_path, "nhVrfId",
10616 (int)nexthop_vrfid);
9df8b37c 10617 }
05864da7
DS
10618 } else {
10619 if (nexthop_vrfid == VRF_UNKNOWN)
10620 vty_out(vty, " vrf ?");
137147c6
DS
10621 else {
10622 struct vrf *vrf;
10623
10624 vrf = vrf_lookup_by_id(nexthop_vrfid);
10625 vty_out(vty, " vrf %s(%u)",
10626 VRF_LOGNAME(vrf), nexthop_vrfid);
10627 }
9df8b37c 10628 }
05864da7 10629 }
9df8b37c 10630
05864da7
DS
10631 if (nexthop_self) {
10632 if (json_paths) {
10633 json_object_boolean_true_add(json_path,
10634 "announceNexthopSelf");
10635 } else {
10636 vty_out(vty, " announce-nh-self");
9df8b37c 10637 }
05864da7 10638 }
9df8b37c 10639
05864da7
DS
10640 if (!json_paths)
10641 vty_out(vty, "\n");
d62a17ae 10642
05864da7
DS
10643 /* display the link-local nexthop */
10644 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10645 if (json_paths) {
10646 json_nexthop_ll = json_object_new_object();
c949c771
DA
10647 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10648 &attr->mp_nexthop_local);
515c2602 10649
939a97f4 10650 if (path->peer->hostname)
515c2602
DA
10651 json_object_string_add(json_nexthop_ll,
10652 "hostname",
939a97f4 10653 path->peer->hostname);
515c2602 10654
05864da7
DS
10655 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10656 json_object_string_add(json_nexthop_ll, "scope",
10657 "link-local");
d62a17ae 10658
05864da7
DS
10659 json_object_boolean_true_add(json_nexthop_ll,
10660 "accessible");
d62a17ae 10661
05864da7 10662 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10663 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10664 "used");
10665 else
10666 json_object_boolean_true_add(
10667 json_nexthop_global, "used");
10668 } else {
10669 vty_out(vty, " (%s) %s\n",
10670 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10671 buf, INET6_ADDRSTRLEN),
10672 attr->mp_nexthop_prefer_global
10673 ? "(prefer-global)"
10674 : "(used)");
d62a17ae 10675 }
05864da7
DS
10676 }
10677 /* If we do not have a link-local nexthop then we must flag the
10678 global as "used" */
10679 else {
10680 if (json_paths)
10681 json_object_boolean_true_add(json_nexthop_global,
10682 "used");
10683 }
d62a17ae 10684
b5e140c8 10685 if (safi == SAFI_EVPN &&
5e4d4c8a 10686 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10687 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10688 }
10689
05864da7
DS
10690 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10691 * Int/Ext/Local, Atomic, best */
10692 if (json_paths)
10693 json_object_string_add(json_path, "origin",
10694 bgp_origin_long_str[attr->origin]);
10695 else
10696 vty_out(vty, " Origin %s",
10697 bgp_origin_long_str[attr->origin]);
9df8b37c 10698
05864da7 10699 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10700 if (json_paths)
05864da7 10701 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10702 else
05864da7
DS
10703 vty_out(vty, ", metric %u", attr->med);
10704 }
9df8b37c 10705
05864da7
DS
10706 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10707 if (json_paths)
0fbac0b4 10708 json_object_int_add(json_path, "locPrf",
05864da7
DS
10709 attr->local_pref);
10710 else
10711 vty_out(vty, ", localpref %u", attr->local_pref);
10712 }
9df8b37c 10713
97a52c82
DA
10714 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10715 if (json_paths)
10716 json_object_int_add(json_path, "aigpMetric",
10717 bgp_attr_get_aigp_metric(attr));
10718 else
10719 vty_out(vty, ", aigp-metric %" PRIu64,
10720 bgp_attr_get_aigp_metric(attr));
10721 }
10722
05864da7
DS
10723 if (attr->weight != 0) {
10724 if (json_paths)
10725 json_object_int_add(json_path, "weight", attr->weight);
10726 else
10727 vty_out(vty, ", weight %u", attr->weight);
10728 }
9df8b37c 10729
05864da7
DS
10730 if (attr->tag != 0) {
10731 if (json_paths)
10732 json_object_int_add(json_path, "tag", attr->tag);
10733 else
10734 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10735 }
9df8b37c 10736
05864da7
DS
10737 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10738 if (json_paths)
10739 json_object_boolean_false_add(json_path, "valid");
10740 else
10741 vty_out(vty, ", invalid");
10742 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10743 if (json_paths)
10744 json_object_boolean_true_add(json_path, "valid");
10745 else
10746 vty_out(vty, ", valid");
10747 }
9df8b37c 10748
7d3cae70
DA
10749 if (json_paths)
10750 json_object_int_add(json_path, "version", bn->version);
10751
05864da7
DS
10752 if (path->peer != bgp->peer_self) {
10753 if (path->peer->as == path->peer->local_as) {
10754 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10755 if (json_paths)
10756 json_object_string_add(
10757 json_peer, "type",
10758 "confed-internal");
d62a17ae 10759 else
05864da7 10760 vty_out(vty, ", confed-internal");
d62a17ae 10761 } else {
05864da7
DS
10762 if (json_paths)
10763 json_object_string_add(
10764 json_peer, "type", "internal");
10765 else
10766 vty_out(vty, ", internal");
9df8b37c 10767 }
05864da7
DS
10768 } else {
10769 if (bgp_confederation_peers_check(bgp,
10770 path->peer->as)) {
10771 if (json_paths)
10772 json_object_string_add(
10773 json_peer, "type",
10774 "confed-external");
d62a17ae 10775 else
05864da7 10776 vty_out(vty, ", confed-external");
d62a17ae 10777 } else {
05864da7
DS
10778 if (json_paths)
10779 json_object_string_add(
10780 json_peer, "type", "external");
10781 else
10782 vty_out(vty, ", external");
d62a17ae 10783 }
10784 }
05864da7
DS
10785 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10786 if (json_paths) {
10787 json_object_boolean_true_add(json_path, "aggregated");
10788 json_object_boolean_true_add(json_path, "local");
10789 } else {
10790 vty_out(vty, ", aggregated, local");
10791 }
10792 } else if (path->type != ZEBRA_ROUTE_BGP) {
10793 if (json_paths)
10794 json_object_boolean_true_add(json_path, "sourced");
10795 else
10796 vty_out(vty, ", sourced");
10797 } else {
10798 if (json_paths) {
10799 json_object_boolean_true_add(json_path, "sourced");
10800 json_object_boolean_true_add(json_path, "local");
10801 } else {
10802 vty_out(vty, ", sourced, local");
d62a17ae 10803 }
05864da7 10804 }
718e3744 10805
05864da7 10806 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10807 if (json_paths)
05864da7
DS
10808 json_object_boolean_true_add(json_path,
10809 "atomicAggregate");
d62a17ae 10810 else
05864da7
DS
10811 vty_out(vty, ", atomic-aggregate");
10812 }
d62a17ae 10813
d864dd9e
EB
10814 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10815 if (json_paths)
10816 json_object_int_add(json_path, "otc", attr->otc);
10817 else
10818 vty_out(vty, ", otc %u", attr->otc);
10819 }
10820
05864da7
DS
10821 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10822 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10823 && bgp_path_info_mpath_count(path))) {
10824 if (json_paths)
10825 json_object_boolean_true_add(json_path, "multipath");
10826 else
10827 vty_out(vty, ", multipath");
10828 }
50e05855 10829
05864da7
DS
10830 // Mark the bestpath(s)
10831 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10832 first_as = aspath_get_first_as(attr->aspath);
718e3744 10833
05864da7
DS
10834 if (json_paths) {
10835 if (!json_bestpath)
10836 json_bestpath = json_object_new_object();
10837 json_object_int_add(json_bestpath, "bestpathFromAs",
10838 first_as);
10839 } else {
10840 if (first_as)
10841 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10842 else
05864da7 10843 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10844 }
05864da7 10845 }
718e3744 10846
05864da7
DS
10847 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10848 if (json_paths) {
10849 if (!json_bestpath)
10850 json_bestpath = json_object_new_object();
10851 json_object_boolean_true_add(json_bestpath, "overall");
10852 json_object_string_add(
10853 json_bestpath, "selectionReason",
10854 bgp_path_selection_reason2str(bn->reason));
10855 } else {
10856 vty_out(vty, ", best");
10857 vty_out(vty, " (%s)",
10858 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10859 }
05864da7 10860 }
718e3744 10861
4027d19b 10862 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10863 if (json_paths)
10864 json_object_string_add(
10865 json_path, "rpkiValidationState",
4027d19b 10866 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10867 else
1d327209 10868 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10869 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10870 }
10871
05864da7
DS
10872 if (json_bestpath)
10873 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10874
05864da7
DS
10875 if (!json_paths)
10876 vty_out(vty, "\n");
10877
10878 /* Line 4 display Community */
29e72930 10879 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10880 if (json_paths) {
9a706b42
DA
10881 if (!bgp_attr_get_community(attr)->json)
10882 community_str(bgp_attr_get_community(attr),
c0945b78 10883 true, true);
9a706b42
DA
10884 json_object_lock(bgp_attr_get_community(attr)->json);
10885 json_object_object_add(
10886 json_path, "community",
10887 bgp_attr_get_community(attr)->json);
05864da7
DS
10888 } else {
10889 vty_out(vty, " Community: %s\n",
9a706b42 10890 bgp_attr_get_community(attr)->str);
d62a17ae 10891 }
05864da7 10892 }
718e3744 10893
05864da7
DS
10894 /* Line 5 display Extended-community */
10895 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10896 if (json_paths) {
10897 json_ext_community = json_object_new_object();
b53e67a3
DA
10898 json_object_string_add(
10899 json_ext_community, "string",
10900 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10901 json_object_object_add(json_path, "extendedCommunity",
10902 json_ext_community);
d62a17ae 10903 } else {
05864da7 10904 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10905 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10906 }
05864da7 10907 }
718e3744 10908
05864da7
DS
10909 /* Line 6 display Large community */
10910 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10911 if (json_paths) {
1bcf3a96
DA
10912 if (!bgp_attr_get_lcommunity(attr)->json)
10913 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10914 true, true);
1bcf3a96
DA
10915 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10916 json_object_object_add(
10917 json_path, "largeCommunity",
10918 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10919 } else {
10920 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10921 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10922 }
05864da7 10923 }
718e3744 10924
05864da7
DS
10925 /* Line 7 display Originator, Cluster-id */
10926 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10927 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10928 char buf[BUFSIZ] = {0};
10929
05864da7 10930 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10931 if (json_paths)
c949c771
DA
10932 json_object_string_addf(json_path,
10933 "originatorId", "%pI4",
10934 &attr->originator_id);
d62a17ae 10935 else
23d0a753
DA
10936 vty_out(vty, " Originator: %pI4",
10937 &attr->originator_id);
d62a17ae 10938 }
856ca177 10939
05864da7 10940 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10941 struct cluster_list *cluster =
10942 bgp_attr_get_cluster(attr);
05864da7 10943 int i;
d62a17ae 10944
10945 if (json_paths) {
05864da7
DS
10946 json_cluster_list = json_object_new_object();
10947 json_cluster_list_list =
10948 json_object_new_array();
10949
779fee93 10950 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10951 json_string = json_object_new_string(
779fee93
DS
10952 inet_ntop(AF_INET,
10953 &cluster->list[i],
10954 buf, sizeof(buf)));
05864da7
DS
10955 json_object_array_add(
10956 json_cluster_list_list,
10957 json_string);
10958 }
718e3744 10959
05864da7
DS
10960 /*
10961 * struct cluster_list does not have
10962 * "str" variable like aspath and community
10963 * do. Add this someday if someone asks
10964 * for it.
10965 * json_object_string_add(json_cluster_list,
779fee93 10966 * "string", cluster->str);
05864da7
DS
10967 */
10968 json_object_object_add(json_cluster_list,
10969 "list",
10970 json_cluster_list_list);
10971 json_object_object_add(json_path, "clusterList",
10972 json_cluster_list);
0dc8ee70 10973 } else {
05864da7
DS
10974 vty_out(vty, ", Cluster list: ");
10975
779fee93 10976 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10977 vty_out(vty, "%pI4 ",
779fee93 10978 &cluster->list[i]);
05864da7 10979 }
0dc8ee70 10980 }
d62a17ae 10981 }
718e3744 10982
d62a17ae 10983 if (!json_paths)
10984 vty_out(vty, "\n");
05864da7 10985 }
d62a17ae 10986
05864da7 10987 if (path->extra && path->extra->damp_info)
b4f7f45b 10988 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10989
05864da7
DS
10990 /* Remote Label */
10991 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10992 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10993 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10994 &bos);
d62a17ae 10995
05864da7
DS
10996 if (json_paths)
10997 json_object_int_add(json_path, "remoteLabel", label);
10998 else
10999 vty_out(vty, " Remote label: %d\n", label);
11000 }
d62a17ae 11001
e496b420
HS
11002 /* Remote SID */
11003 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 11004 if (json_paths)
07380148
DA
11005 json_object_string_addf(json_path, "remoteSid", "%pI6",
11006 &path->extra->sid[0].sid);
e496b420 11007 else
07380148
DA
11008 vty_out(vty, " Remote SID: %pI6\n",
11009 &path->extra->sid[0].sid);
e496b420
HS
11010 }
11011
05864da7
DS
11012 /* Label Index */
11013 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11014 if (json_paths)
11015 json_object_int_add(json_path, "labelIndex",
11016 attr->label_index);
11017 else
11018 vty_out(vty, " Label Index: %d\n",
11019 attr->label_index);
11020 }
d62a17ae 11021
05864da7
DS
11022 /* Line 8 display Addpath IDs */
11023 if (path->addpath_rx_id
11024 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11025 if (json_paths) {
11026 json_object_int_add(json_path, "addpathRxId",
11027 path->addpath_rx_id);
d62a17ae 11028
05864da7
DS
11029 /* Keep backwards compatibility with the old API
11030 * by putting TX All's ID in the old field
11031 */
11032 json_object_int_add(
11033 json_path, "addpathTxId",
11034 path->tx_addpath
11035 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11036
05864da7
DS
11037 /* ... but create a specific field for each
11038 * strategy
11039 */
11040 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11041 json_object_int_add(
11042 json_path,
11043 bgp_addpath_names(i)->id_json_name,
11044 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11045 }
05864da7
DS
11046 } else {
11047 vty_out(vty, " AddPath ID: RX %u, ",
11048 path->addpath_rx_id);
d62a17ae 11049
05864da7 11050 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11051 }
05864da7 11052 }
520d5d76 11053
05864da7
DS
11054 /* If we used addpath to TX a non-bestpath we need to display
11055 * "Advertised to" on a path-by-path basis
11056 */
11057 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11058 first = 1;
dcc68b5e 11059
05864da7
DS
11060 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11061 addpath_capable =
11062 bgp_addpath_encode_tx(peer, afi, safi);
11063 has_adj = bgp_adj_out_lookup(
11064 peer, path->net,
11065 bgp_addpath_id_for_peer(peer, afi, safi,
11066 &path->tx_addpath));
11067
11068 if ((addpath_capable && has_adj)
11069 || (!addpath_capable && has_adj
11070 && CHECK_FLAG(path->flags,
11071 BGP_PATH_SELECTED))) {
11072 if (json_path && !json_adv_to)
11073 json_adv_to = json_object_new_object();
dcc68b5e 11074
05864da7
DS
11075 route_vty_out_advertised_to(
11076 vty, peer, &first,
11077 " Advertised to:", json_adv_to);
d62a17ae 11078 }
11079 }
718e3744 11080
05864da7
DS
11081 if (json_path) {
11082 if (json_adv_to) {
11083 json_object_object_add(
11084 json_path, "advertisedTo", json_adv_to);
d62a17ae 11085 }
05864da7
DS
11086 } else {
11087 if (!first) {
11088 vty_out(vty, "\n");
d62a17ae 11089 }
11090 }
05864da7 11091 }
b05a1c8b 11092
05864da7 11093 /* Line 9 display Uptime */
083ec940 11094 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11095 if (json_paths) {
11096 json_last_update = json_object_new_object();
11097 json_object_int_add(json_last_update, "epoch", tbuf);
11098 json_object_string_add(json_last_update, "string",
11099 ctime(&tbuf));
11100 json_object_object_add(json_path, "lastUpdate",
11101 json_last_update);
11102 } else
11103 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11104
05864da7
DS
11105 /* Line 10 display PMSI tunnel attribute, if present */
11106 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11107 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11108 bgp_attr_get_pmsi_tnl_type(attr),
11109 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11110
05864da7
DS
11111 if (json_paths) {
11112 json_pmsi = json_object_new_object();
11113 json_object_string_add(json_pmsi, "tunnelType", str);
11114 json_object_int_add(json_pmsi, "label",
11115 label2vni(&attr->label));
11116 json_object_object_add(json_path, "pmsi", json_pmsi);
11117 } else
11118 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11119 str, label2vni(&attr->label));
d62a17ae 11120 }
f1aa5d8a 11121
848e8cf6
DA
11122 if (path->peer->t_gr_restart &&
11123 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11124 unsigned long gr_remaining =
11125 thread_timer_remain_second(path->peer->t_gr_restart);
11126
11127 if (json_paths) {
11128 json_object_int_add(json_path,
11129 "gracefulRestartSecondsRemaining",
11130 gr_remaining);
11131 } else
11132 vty_out(vty,
11133 " Time until Graceful Restart stale route deleted: %lu\n",
11134 gr_remaining);
11135 }
11136
9a706b42
DA
11137 if (path->peer->t_llgr_stale[afi][safi] &&
11138 bgp_attr_get_community(attr) &&
11139 community_include(bgp_attr_get_community(attr),
11140 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11141 unsigned long llgr_remaining = thread_timer_remain_second(
11142 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11143
48ebba04
DA
11144 if (json_paths) {
11145 json_object_int_add(json_path, "llgrSecondsRemaining",
11146 llgr_remaining);
11147 } else
11148 vty_out(vty,
11149 " Time until Long-lived stale route deleted: %lu\n",
11150 llgr_remaining);
11151 }
11152
92269aa2
DS
11153 /* Output some debug about internal state of the dest flags */
11154 if (json_paths) {
11155 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11156 json_object_boolean_true_add(json_path, "processScheduled");
11157 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11158 json_object_boolean_true_add(json_path, "userCleared");
11159 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11160 json_object_boolean_true_add(json_path, "labelChanged");
11161 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11162 json_object_boolean_true_add(json_path, "registeredForLabel");
11163 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11164 json_object_boolean_true_add(json_path, "selectDefered");
11165 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11166 json_object_boolean_true_add(json_path, "fibInstalled");
11167 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11168 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11169
d62a17ae 11170 if (json_nexthop_global || json_nexthop_ll) {
11171 json_nexthops = json_object_new_array();
f1aa5d8a 11172
d62a17ae 11173 if (json_nexthop_global)
11174 json_object_array_add(json_nexthops,
11175 json_nexthop_global);
f1aa5d8a 11176
d62a17ae 11177 if (json_nexthop_ll)
11178 json_object_array_add(json_nexthops,
11179 json_nexthop_ll);
f1aa5d8a 11180
d62a17ae 11181 json_object_object_add(json_path, "nexthops",
11182 json_nexthops);
11183 }
11184
11185 json_object_object_add(json_path, "peer", json_peer);
11186 json_object_array_add(json_paths, json_path);
05864da7 11187 }
b366b518
BB
11188}
11189
96ade3ed 11190#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11191#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11192#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11193
a4d82a8a 11194static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11195 afi_t afi, safi_t safi, enum bgp_show_type type,
11196 bool use_json);
7f323236
DW
11197static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11198 const char *comstr, int exact, afi_t afi,
96c81f66 11199 safi_t safi, uint16_t show_flags);
d62a17ae 11200
1ae44dfc 11201static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11202 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11203 void *output_arg, const char *rd, int is_last,
96f3485c 11204 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11205 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11206 enum rpki_states rpki_target_state)
d62a17ae 11207{
40381db7 11208 struct bgp_path_info *pi;
9bcb3eef 11209 struct bgp_dest *dest;
2aad8c42
MS
11210 bool header = true;
11211 bool json_detail_header = false;
d62a17ae 11212 int display;
1ae44dfc
LB
11213 unsigned long output_count = 0;
11214 unsigned long total_count = 0;
d62a17ae 11215 struct prefix *p;
d62a17ae 11216 json_object *json_paths = NULL;
11217 int first = 1;
96f3485c
MK
11218 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11219 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11220 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11221
1ae44dfc 11222 if (output_cum && *output_cum != 0)
2aad8c42 11223 header = false;
1ae44dfc 11224
9386b588 11225 if (use_json && !*json_header_depth) {
96f3485c
MK
11226 if (all)
11227 *json_header_depth = 1;
11228 else {
11229 vty_out(vty, "{\n");
11230 *json_header_depth = 2;
11231 }
11232
d62a17ae 11233 vty_out(vty,
23d0a753
DA
11234 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11235 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11236 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11237 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11238 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11239 ? VRF_DEFAULT_NAME
11240 : bgp->name,
11241 table->version, &bgp->router_id,
01eced22 11242 bgp->default_local_pref, bgp->as);
9386b588 11243 if (rd) {
445c2480 11244 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11245 ++*json_header_depth;
11246 }
d62a17ae 11247 }
718e3744 11248
445c2480
DS
11249 if (use_json && rd) {
11250 vty_out(vty, " \"%s\" : { ", rd);
11251 }
11252
2aad8c42
MS
11253 /* Check for 'json detail', where we need header output once per dest */
11254 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11255 type != bgp_show_type_dampend_paths &&
11256 type != bgp_show_type_damp_neighbor &&
11257 type != bgp_show_type_flap_statistics &&
11258 type != bgp_show_type_flap_neighbor)
11259 json_detail_header = true;
11260
d62a17ae 11261 /* Start processing of routes. */
9bcb3eef
DS
11262 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11263 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11264 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11265 bool json_detail = json_detail_header;
b54892e0 11266
9bcb3eef 11267 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11268 if (pi == NULL)
98ce9a06 11269 continue;
d62a17ae 11270
98ce9a06 11271 display = 0;
98ce9a06
DS
11272 if (use_json)
11273 json_paths = json_object_new_array();
11274 else
11275 json_paths = NULL;
d62a17ae 11276
6f94b685 11277 for (; pi; pi = pi->next) {
9a706b42
DA
11278 struct community *picomm = NULL;
11279
11280 picomm = bgp_attr_get_community(pi->attr);
11281
98ce9a06 11282 total_count++;
1e2ce4f1 11283
7d3cae70
DA
11284 if (type == bgp_show_type_prefix_version) {
11285 uint32_t version =
11286 strtoul(output_arg, NULL, 10);
11287 if (dest->version < version)
11288 continue;
11289 }
11290
a70a28a5
DA
11291 if (type == bgp_show_type_community_alias) {
11292 char *alias = output_arg;
11293 char **communities;
11294 int num;
11295 bool found = false;
11296
9a706b42
DA
11297 if (picomm) {
11298 frrstr_split(picomm->str, " ",
11299 &communities, &num);
a70a28a5
DA
11300 for (int i = 0; i < num; i++) {
11301 const char *com2alias =
11302 bgp_community2alias(
11303 communities[i]);
cd9cc0e6
IR
11304 if (!found
11305 && strcmp(alias, com2alias)
11306 == 0)
a70a28a5 11307 found = true;
cd9cc0e6
IR
11308 XFREE(MTYPE_TMP,
11309 communities[i]);
a70a28a5 11310 }
cd9cc0e6 11311 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11312 }
11313
1bcf3a96
DA
11314 if (!found &&
11315 bgp_attr_get_lcommunity(pi->attr)) {
11316 frrstr_split(bgp_attr_get_lcommunity(
11317 pi->attr)
11318 ->str,
a70a28a5
DA
11319 " ", &communities, &num);
11320 for (int i = 0; i < num; i++) {
11321 const char *com2alias =
11322 bgp_community2alias(
11323 communities[i]);
cd9cc0e6
IR
11324 if (!found
11325 && strcmp(alias, com2alias)
11326 == 0)
a70a28a5 11327 found = true;
cd9cc0e6
IR
11328 XFREE(MTYPE_TMP,
11329 communities[i]);
a70a28a5 11330 }
cd9cc0e6 11331 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11332 }
11333
11334 if (!found)
11335 continue;
11336 }
11337
1e2ce4f1
DS
11338 if (type == bgp_show_type_rpki) {
11339 if (dest_p->family == AF_INET
11340 || dest_p->family == AF_INET6)
4027d19b 11341 rpki_curr_state = hook_call(
1e2ce4f1
DS
11342 bgp_rpki_prefix_status,
11343 pi->peer, pi->attr, dest_p);
4027d19b
DS
11344 if (rpki_target_state != RPKI_NOT_BEING_USED
11345 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11346 continue;
11347 }
11348
98ce9a06
DS
11349 if (type == bgp_show_type_flap_statistics
11350 || type == bgp_show_type_flap_neighbor
11351 || type == bgp_show_type_dampend_paths
11352 || type == bgp_show_type_damp_neighbor) {
40381db7 11353 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11354 continue;
11355 }
11356 if (type == bgp_show_type_regexp) {
11357 regex_t *regex = output_arg;
d62a17ae 11358
40381db7 11359 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11360 == REG_NOMATCH)
11361 continue;
11362 }
11363 if (type == bgp_show_type_prefix_list) {
11364 struct prefix_list *plist = output_arg;
d62a17ae 11365
9bcb3eef 11366 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11367 != PREFIX_PERMIT)
11368 continue;
11369 }
ed126382
DA
11370 if (type == bgp_show_type_access_list) {
11371 struct access_list *alist = output_arg;
11372
11373 if (access_list_apply(alist, dest_p) !=
11374 FILTER_PERMIT)
11375 continue;
11376 }
98ce9a06
DS
11377 if (type == bgp_show_type_filter_list) {
11378 struct as_list *as_list = output_arg;
d62a17ae 11379
40381db7 11380 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11381 != AS_FILTER_PERMIT)
11382 continue;
11383 }
11384 if (type == bgp_show_type_route_map) {
11385 struct route_map *rmap = output_arg;
9b6d8fcf 11386 struct bgp_path_info path;
636632c3
DA
11387 struct bgp_path_info_extra extra;
11388 struct attr dummy_attr = {};
b68885f9 11389 route_map_result_t ret;
d62a17ae 11390
6f4f49b2 11391 dummy_attr = *pi->attr;
d62a17ae 11392
636632c3
DA
11393 prep_for_rmap_apply(&path, &extra, dest, pi,
11394 pi->peer, &dummy_attr);
d62a17ae 11395
1782514f 11396 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11397 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11398 if (ret == RMAP_DENYMATCH)
11399 continue;
11400 }
11401 if (type == bgp_show_type_neighbor
11402 || type == bgp_show_type_flap_neighbor
11403 || type == bgp_show_type_damp_neighbor) {
11404 union sockunion *su = output_arg;
11405
40381db7
DS
11406 if (pi->peer == NULL
11407 || pi->peer->su_remote == NULL
11408 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11409 continue;
11410 }
11411 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11412 uint32_t destination;
d62a17ae 11413
9bcb3eef 11414 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11415 if (IN_CLASSC(destination)
9bcb3eef 11416 && dest_p->prefixlen == 24)
98ce9a06
DS
11417 continue;
11418 if (IN_CLASSB(destination)
9bcb3eef 11419 && dest_p->prefixlen == 16)
98ce9a06
DS
11420 continue;
11421 if (IN_CLASSA(destination)
9bcb3eef 11422 && dest_p->prefixlen == 8)
98ce9a06
DS
11423 continue;
11424 }
11425 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11426 p = output_arg;
9bcb3eef 11427 if (!prefix_match(p, dest_p))
98ce9a06
DS
11428 continue;
11429 }
11430 if (type == bgp_show_type_community_all) {
9a706b42 11431 if (!picomm)
98ce9a06
DS
11432 continue;
11433 }
11434 if (type == bgp_show_type_community) {
11435 struct community *com = output_arg;
d62a17ae 11436
9a706b42 11437 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11438 continue;
11439 }
11440 if (type == bgp_show_type_community_exact) {
11441 struct community *com = output_arg;
d62a17ae 11442
9a706b42 11443 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11444 continue;
11445 }
11446 if (type == bgp_show_type_community_list) {
11447 struct community_list *list = output_arg;
d62a17ae 11448
9a706b42 11449 if (!community_list_match(picomm, list))
98ce9a06
DS
11450 continue;
11451 }
a4d82a8a 11452 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11453 struct community_list *list = output_arg;
d62a17ae 11454
9a706b42 11455 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11456 continue;
11457 }
11458 if (type == bgp_show_type_lcommunity) {
11459 struct lcommunity *lcom = output_arg;
d62a17ae 11460
1bcf3a96
DA
11461 if (!bgp_attr_get_lcommunity(pi->attr) ||
11462 !lcommunity_match(
11463 bgp_attr_get_lcommunity(pi->attr),
11464 lcom))
98ce9a06
DS
11465 continue;
11466 }
36a206db 11467
11468 if (type == bgp_show_type_lcommunity_exact) {
11469 struct lcommunity *lcom = output_arg;
11470
1bcf3a96
DA
11471 if (!bgp_attr_get_lcommunity(pi->attr) ||
11472 !lcommunity_cmp(
11473 bgp_attr_get_lcommunity(pi->attr),
11474 lcom))
36a206db 11475 continue;
11476 }
98ce9a06
DS
11477 if (type == bgp_show_type_lcommunity_list) {
11478 struct community_list *list = output_arg;
d62a17ae 11479
1bcf3a96
DA
11480 if (!lcommunity_list_match(
11481 bgp_attr_get_lcommunity(pi->attr),
11482 list))
98ce9a06
DS
11483 continue;
11484 }
36a206db 11485 if (type
11486 == bgp_show_type_lcommunity_list_exact) {
11487 struct community_list *list = output_arg;
11488
11489 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11490 bgp_attr_get_lcommunity(pi->attr),
11491 list))
36a206db 11492 continue;
11493 }
98ce9a06 11494 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11495 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11496 continue;
11497 }
11498 if (type == bgp_show_type_dampend_paths
11499 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11500 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11501 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11502 continue;
11503 }
11504
11505 if (!use_json && header) {
23d0a753
DA
11506 vty_out(vty,
11507 "BGP table version is %" PRIu64
11508 ", local router ID is %pI4, vrf id ",
11509 table->version, &bgp->router_id);
9df8b37c
PZ
11510 if (bgp->vrf_id == VRF_UNKNOWN)
11511 vty_out(vty, "%s", VRFID_NONE_STR);
11512 else
11513 vty_out(vty, "%u", bgp->vrf_id);
11514 vty_out(vty, "\n");
01eced22
AD
11515 vty_out(vty, "Default local pref %u, ",
11516 bgp->default_local_pref);
11517 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11518 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11519 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11520 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11521 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11522 if (type == bgp_show_type_dampend_paths
11523 || type == bgp_show_type_damp_neighbor)
98ce9a06 11524 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11525 else if (type == bgp_show_type_flap_statistics
11526 || type == bgp_show_type_flap_neighbor)
98ce9a06 11527 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11528 else
ae248832
MK
11529 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11530 : BGP_SHOW_HEADER));
2aad8c42
MS
11531 header = false;
11532
11533 } else if (json_detail && json_paths != NULL) {
11534 const struct prefix_rd *prd;
11535 json_object *jtemp;
11536
11537 /* Use common detail header, for most types;
11538 * need a json 'object'.
11539 */
11540
11541 jtemp = json_object_new_object();
11542 prd = bgp_rd_from_dest(dest, safi);
11543
11544 route_vty_out_detail_header(
34c7f35f
SW
11545 vty, bgp, dest,
11546 bgp_dest_get_prefix(dest), prd,
11547 table->afi, safi, jtemp);
2aad8c42
MS
11548
11549 json_object_array_add(json_paths, jtemp);
11550
11551 json_detail = false;
d62a17ae 11552 }
2aad8c42 11553
98ce9a06
DS
11554 if (rd != NULL && !display && !output_count) {
11555 if (!use_json)
11556 vty_out(vty,
11557 "Route Distinguisher: %s\n",
11558 rd);
d62a17ae 11559 }
98ce9a06
DS
11560 if (type == bgp_show_type_dampend_paths
11561 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11562 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11563 AFI_IP, safi, use_json,
11564 json_paths);
98ce9a06
DS
11565 else if (type == bgp_show_type_flap_statistics
11566 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11567 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11568 AFI_IP, safi, use_json,
11569 json_paths);
f280c93b
DA
11570 else {
11571 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11572 route_vty_out_detail(
34c7f35f
SW
11573 vty, bgp, dest,
11574 bgp_dest_get_prefix(dest), pi,
f280c93b
DA
11575 family2afi(dest_p->family),
11576 safi, RPKI_NOT_BEING_USED,
11577 json_paths);
11578 else
11579 route_vty_out(vty, dest_p, pi, display,
11580 safi, json_paths, wide);
11581 }
98ce9a06 11582 display++;
d62a17ae 11583 }
11584
98ce9a06
DS
11585 if (display) {
11586 output_count++;
11587 if (!use_json)
11588 continue;
11589
625d2931 11590 /* encode prefix */
9bcb3eef 11591 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11592 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11593
1840384b 11594
b54892e0
DS
11595 bgp_fs_nlri_get_string(
11596 (unsigned char *)
9bcb3eef
DS
11597 dest_p->u.prefix_flowspec.ptr,
11598 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11599 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11600 family2afi(dest_p->u
11601 .prefix_flowspec.family));
625d2931 11602 if (first)
b54892e0 11603 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11604 dest_p->u.prefix_flowspec
b54892e0 11605 .prefixlen);
625d2931 11606 else
b54892e0 11607 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11608 dest_p->u.prefix_flowspec
b54892e0 11609 .prefixlen);
625d2931 11610 } else {
625d2931 11611 if (first)
1b78780b 11612 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11613 else
1b78780b 11614 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11615 }
3757f964 11616 vty_json(vty, json_paths);
449feb8e 11617 json_paths = NULL;
98ce9a06 11618 first = 0;
1f83ed02
DS
11619 } else
11620 json_object_free(json_paths);
98ce9a06
DS
11621 }
11622
1ae44dfc
LB
11623 if (output_cum) {
11624 output_count += *output_cum;
11625 *output_cum = output_count;
11626 }
11627 if (total_cum) {
11628 total_count += *total_cum;
11629 *total_cum = total_count;
11630 }
d62a17ae 11631 if (use_json) {
9386b588 11632 if (rd) {
a4d82a8a 11633 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11634 }
11635 if (is_last) {
a4d82a8a
PZ
11636 unsigned long i;
11637 for (i = 0; i < *json_header_depth; ++i)
11638 vty_out(vty, " } ");
96f3485c
MK
11639 if (!all)
11640 vty_out(vty, "\n");
9386b588 11641 }
d62a17ae 11642 } else {
1ae44dfc
LB
11643 if (is_last) {
11644 /* No route is displayed */
11645 if (output_count == 0) {
11646 if (type == bgp_show_type_normal)
11647 vty_out(vty,
11648 "No BGP prefixes displayed, %ld exist\n",
11649 total_count);
11650 } else
d62a17ae 11651 vty_out(vty,
1ae44dfc
LB
11652 "\nDisplayed %ld routes and %ld total paths\n",
11653 output_count, total_count);
11654 }
d62a17ae 11655 }
718e3744 11656
d62a17ae 11657 return CMD_SUCCESS;
718e3744 11658}
11659
1ae44dfc
LB
11660int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11661 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11662 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11663{
9bcb3eef 11664 struct bgp_dest *dest, *next;
1ae44dfc
LB
11665 unsigned long output_cum = 0;
11666 unsigned long total_cum = 0;
9386b588 11667 unsigned long json_header_depth = 0;
67009e22 11668 struct bgp_table *itable;
0136788c 11669 bool show_msg;
96c81f66 11670 uint16_t show_flags = 0;
0136788c
LB
11671
11672 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11673
96f3485c
MK
11674 if (use_json)
11675 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11676
9bcb3eef
DS
11677 for (dest = bgp_table_top(table); dest; dest = next) {
11678 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11679
9bcb3eef
DS
11680 next = bgp_route_next(dest);
11681 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11682 continue;
67009e22 11683
9bcb3eef 11684 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11685 if (itable != NULL) {
1ae44dfc 11686 struct prefix_rd prd;
06b9f471 11687 char rd[RD_ADDRSTRLEN];
1ae44dfc 11688
9bcb3eef 11689 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11690 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11691 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11692 rd, next == NULL, &output_cum,
11693 &total_cum, &json_header_depth,
1e2ce4f1 11694 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11695 if (next == NULL)
11696 show_msg = false;
1ae44dfc
LB
11697 }
11698 }
0136788c
LB
11699 if (show_msg) {
11700 if (output_cum == 0)
11701 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11702 total_cum);
11703 else
11704 vty_out(vty,
11705 "\nDisplayed %ld routes and %ld total paths\n",
11706 output_cum, total_cum);
0224b329
DA
11707 } else {
11708 if (use_json && output_cum == 0)
11709 vty_out(vty, "{}\n");
0136788c 11710 }
1ae44dfc
LB
11711 return CMD_SUCCESS;
11712}
2aad8c42 11713
d62a17ae 11714static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11715 enum bgp_show_type type, void *output_arg,
96c81f66 11716 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11717{
d62a17ae 11718 struct bgp_table *table;
9386b588 11719 unsigned long json_header_depth = 0;
96f3485c 11720 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11721
d62a17ae 11722 if (bgp == NULL) {
11723 bgp = bgp_get_default();
11724 }
fee0f4c6 11725
d62a17ae 11726 if (bgp == NULL) {
11727 if (!use_json)
11728 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11729 else
11730 vty_out(vty, "{}\n");
d62a17ae 11731 return CMD_WARNING;
11732 }
4dd6177e 11733
cd8c2a27
MS
11734 /* Labeled-unicast routes live in the unicast table. */
11735 if (safi == SAFI_LABELED_UNICAST)
11736 safi = SAFI_UNICAST;
11737
1ae44dfc 11738 table = bgp->rib[afi][safi];
d62a17ae 11739 /* use MPLS and ENCAP specific shows until they are merged */
11740 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11741 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11742 output_arg, use_json);
d62a17ae 11743 }
dba3c1d3
PG
11744
11745 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11746 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11747 output_arg, use_json,
11748 1, NULL, NULL);
11749 }
fee0f4c6 11750
96f3485c 11751 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11752 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11753 rpki_target_state);
fee0f4c6 11754}
11755
d62a17ae 11756static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11757 safi_t safi, uint16_t show_flags)
f186de26 11758{
d62a17ae 11759 struct listnode *node, *nnode;
11760 struct bgp *bgp;
11761 int is_first = 1;
9f049418 11762 bool route_output = false;
96f3485c 11763 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11764
d62a17ae 11765 if (use_json)
11766 vty_out(vty, "{\n");
9f689658 11767
d62a17ae 11768 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11769 route_output = true;
d62a17ae 11770 if (use_json) {
11771 if (!is_first)
11772 vty_out(vty, ",\n");
11773 else
11774 is_first = 0;
11775
11776 vty_out(vty, "\"%s\":",
11777 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11778 ? VRF_DEFAULT_NAME
d62a17ae 11779 : bgp->name);
11780 } else {
11781 vty_out(vty, "\nInstance %s:\n",
11782 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11783 ? VRF_DEFAULT_NAME
d62a17ae 11784 : bgp->name);
11785 }
11786 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11787 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11788 }
9f689658 11789
d62a17ae 11790 if (use_json)
11791 vty_out(vty, "}\n");
9f049418
DS
11792 else if (!route_output)
11793 vty_out(vty, "%% BGP instance not found\n");
f186de26 11794}
11795
718e3744 11796/* Header of detailed BGP route information */
d62a17ae 11797void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11798 struct bgp_dest *dest, const struct prefix *p,
11799 const struct prefix_rd *prd, afi_t afi,
11800 safi_t safi, json_object *json)
d62a17ae 11801{
40381db7 11802 struct bgp_path_info *pi;
d62a17ae 11803 struct peer *peer;
11804 struct listnode *node, *nnode;
06b9f471 11805 char buf1[RD_ADDRSTRLEN];
d62a17ae 11806 int count = 0;
11807 int best = 0;
11808 int suppress = 0;
c5f1e1b2
C
11809 int accept_own = 0;
11810 int route_filter_translated_v4 = 0;
11811 int route_filter_v4 = 0;
11812 int route_filter_translated_v6 = 0;
11813 int route_filter_v6 = 0;
11814 int llgr_stale = 0;
11815 int no_llgr = 0;
11816 int accept_own_nexthop = 0;
11817 int blackhole = 0;
d62a17ae 11818 int no_export = 0;
11819 int no_advertise = 0;
11820 int local_as = 0;
c5f1e1b2 11821 int no_peer = 0;
d62a17ae 11822 int first = 1;
11823 int has_valid_label = 0;
11824 mpls_label_t label = 0;
11825 json_object *json_adv_to = NULL;
67f67ba4
DA
11826 uint32_t ttl = 0;
11827 uint32_t bos = 0;
11828 uint32_t exp = 0;
9bedbb1e 11829
67f67ba4 11830 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11831
67f67ba4 11832 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11833
44c69747 11834 if (safi == SAFI_EVPN) {
44c69747 11835 if (!json) {
2dbe669b 11836 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11837 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11838 : "",
2dbe669b 11839 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11840 } else {
11841 json_object_string_add(json, "rd",
11842 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11843 "");
11844 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11845 }
11846 } else {
11847 if (!json) {
9119ef3a
DA
11848 vty_out(vty,
11849 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11850 "\n",
d62a17ae 11851 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11852 ? prefix_rd2str(prd, buf1,
11853 sizeof(buf1))
11854 : ""),
9119ef3a
DA
11855 safi == SAFI_MPLS_VPN ? ":" : "", p,
11856 dest->version);
cd1964ff 11857
9119ef3a 11858 } else {
67d7e256 11859 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11860 json_object_int_add(json, "version", dest->version);
11861
11862 }
44c69747
LK
11863 }
11864
11865 if (has_valid_label) {
11866 if (json)
11867 json_object_int_add(json, "localLabel", label);
11868 else
d62a17ae 11869 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11870 }
11871
11872 if (!json)
d62a17ae 11873 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11874 vty_out(vty, "not allocated\n");
718e3744 11875
9bcb3eef 11876 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11877 struct community *picomm = NULL;
11878
11879 picomm = bgp_attr_get_community(pi->attr);
11880
d62a17ae 11881 count++;
40381db7 11882 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11883 best = count;
4056a5f6 11884 if (bgp_path_suppressed(pi))
d62a17ae 11885 suppress = 1;
cee9c031 11886
9a706b42 11887 if (!picomm)
cee9c031
QY
11888 continue;
11889
11890 no_advertise += community_include(
9a706b42
DA
11891 picomm, COMMUNITY_NO_ADVERTISE);
11892 no_export +=
11893 community_include(picomm, COMMUNITY_NO_EXPORT);
11894 local_as +=
11895 community_include(picomm, COMMUNITY_LOCAL_AS);
11896 accept_own +=
11897 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11898 route_filter_translated_v4 += community_include(
9a706b42 11899 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11900 route_filter_translated_v6 += community_include(
9a706b42 11901 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11902 route_filter_v4 += community_include(
9a706b42 11903 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11904 route_filter_v6 += community_include(
9a706b42
DA
11905 picomm, COMMUNITY_ROUTE_FILTER_v6);
11906 llgr_stale +=
11907 community_include(picomm, COMMUNITY_LLGR_STALE);
11908 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11909 accept_own_nexthop += community_include(
11910 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11911 blackhole +=
11912 community_include(picomm, COMMUNITY_BLACKHOLE);
11913 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11914 }
718e3744 11915 }
718e3744 11916
d62a17ae 11917 if (!json) {
11918 vty_out(vty, "Paths: (%d available", count);
11919 if (best) {
11920 vty_out(vty, ", best #%d", best);
b84060bb
PG
11921 if (safi == SAFI_UNICAST) {
11922 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11923 vty_out(vty, ", table %s",
11924 VRF_DEFAULT_NAME);
11925 else
11926 vty_out(vty, ", vrf %s",
11927 bgp->name);
11928 }
d62a17ae 11929 } else
11930 vty_out(vty, ", no best path");
11931
c5f1e1b2
C
11932 if (accept_own)
11933 vty_out(vty,
11934 ", accept own local route exported and imported in different VRF");
11935 else if (route_filter_translated_v4)
11936 vty_out(vty,
11937 ", mark translated RTs for VPNv4 route filtering");
11938 else if (route_filter_v4)
11939 vty_out(vty,
11940 ", attach RT as-is for VPNv4 route filtering");
11941 else if (route_filter_translated_v6)
11942 vty_out(vty,
11943 ", mark translated RTs for VPNv6 route filtering");
11944 else if (route_filter_v6)
11945 vty_out(vty,
11946 ", attach RT as-is for VPNv6 route filtering");
11947 else if (llgr_stale)
11948 vty_out(vty,
1479ed2f 11949 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11950 else if (no_llgr)
11951 vty_out(vty,
11952 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11953 else if (accept_own_nexthop)
11954 vty_out(vty,
11955 ", accept local nexthop");
11956 else if (blackhole)
11957 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11958 else if (no_export)
11959 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11960 else if (no_advertise)
11961 vty_out(vty, ", not advertised to any peer");
d62a17ae 11962 else if (local_as)
11963 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11964 else if (no_peer)
11965 vty_out(vty,
11966 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11967
11968 if (suppress)
11969 vty_out(vty,
11970 ", Advertisements suppressed by an aggregate.");
11971 vty_out(vty, ")\n");
11972 }
718e3744 11973
d62a17ae 11974 /* If we are not using addpath then we can display Advertised to and
11975 * that will
11976 * show what peers we advertised the bestpath to. If we are using
11977 * addpath
11978 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11979 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11980 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11981 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11982 if (json && !json_adv_to)
11983 json_adv_to = json_object_new_object();
11984
11985 route_vty_out_advertised_to(
11986 vty, peer, &first,
11987 " Advertised to non peer-group peers:\n ",
11988 json_adv_to);
11989 }
11990 }
11991
11992 if (json) {
11993 if (json_adv_to) {
11994 json_object_object_add(json, "advertisedTo",
11995 json_adv_to);
11996 }
11997 } else {
11998 if (first)
11999 vty_out(vty, " Not advertised to any peer");
12000 vty_out(vty, "\n");
12001 }
12002 }
718e3744 12003}
12004
edfee30d 12005static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12006 struct bgp_dest *bgp_node, struct vty *vty,
12007 struct bgp *bgp, afi_t afi, safi_t safi,
12008 json_object *json, enum bgp_path_type pathtype,
4027d19b 12009 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12010{
12011 struct bgp_path_info *pi;
12012 int header = 1;
44c69747
LK
12013 json_object *json_header = NULL;
12014 json_object *json_paths = NULL;
4933eaaf 12015 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12016
9bcb3eef 12017 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12018 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12019
12020 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12021 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12022 pi->peer, pi->attr, p);
4933eaaf 12023
4027d19b
DS
12024 if (rpki_target_state != RPKI_NOT_BEING_USED
12025 && rpki_curr_state != rpki_target_state)
4933eaaf 12026 continue;
44c69747
LK
12027
12028 if (json && !json_paths) {
12029 /* Instantiate json_paths only if path is valid */
12030 json_paths = json_object_new_array();
c4f64ea9 12031 if (pfx_rd)
44c69747 12032 json_header = json_object_new_object();
c4f64ea9 12033 else
44c69747
LK
12034 json_header = json;
12035 }
12036
12037 if (header) {
12038 route_vty_out_detail_header(
34c7f35f
SW
12039 vty, bgp, bgp_node,
12040 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12041 safi, json_header);
44c69747
LK
12042 header = 0;
12043 }
12044 (*display)++;
12045
12046 if (pathtype == BGP_PATH_SHOW_ALL
12047 || (pathtype == BGP_PATH_SHOW_BESTPATH
12048 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12049 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12050 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12051 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12052 route_vty_out_detail(vty, bgp, bgp_node,
12053 bgp_dest_get_prefix(bgp_node), pi,
12054 AFI_IP, safi, rpki_curr_state,
12055 json_paths);
44c69747
LK
12056 }
12057
12058 if (json && json_paths) {
12059 json_object_object_add(json_header, "paths", json_paths);
12060
12061 if (pfx_rd)
c4f64ea9
DA
12062 json_object_object_addf(json, json_header, "%pRD",
12063 pfx_rd);
44c69747
LK
12064 }
12065}
12066
2aad8c42
MS
12067/*
12068 * Return rd based on safi
12069 */
46dbf9d0
DA
12070const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12071 safi_t safi)
2aad8c42
MS
12072{
12073 switch (safi) {
12074 case SAFI_MPLS_VPN:
12075 case SAFI_ENCAP:
12076 case SAFI_EVPN:
12077 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12078 default:
12079 return NULL;
2aad8c42
MS
12080 }
12081}
12082
718e3744 12083/* Display specified route of BGP table. */
d62a17ae 12084static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12085 struct bgp_table *rib, const char *ip_str,
12086 afi_t afi, safi_t safi,
4027d19b 12087 enum rpki_states rpki_target_state,
d62a17ae 12088 struct prefix_rd *prd, int prefix_check,
9f049418 12089 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12090{
12091 int ret;
d62a17ae 12092 int display = 0;
12093 struct prefix match;
9bcb3eef
DS
12094 struct bgp_dest *dest;
12095 struct bgp_dest *rm;
d62a17ae 12096 struct bgp_table *table;
12097 json_object *json = NULL;
12098 json_object *json_paths = NULL;
12099
12100 /* Check IP address argument. */
12101 ret = str2prefix(ip_str, &match);
12102 if (!ret) {
12103 vty_out(vty, "address is malformed\n");
12104 return CMD_WARNING;
12105 }
718e3744 12106
d62a17ae 12107 match.family = afi2family(afi);
b05a1c8b 12108
44c69747 12109 if (use_json)
d62a17ae 12110 json = json_object_new_object();
718e3744 12111
44c69747 12112 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12113 for (dest = bgp_table_top(rib); dest;
12114 dest = bgp_route_next(dest)) {
12115 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12116
9bcb3eef 12117 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12118 continue;
9bcb3eef 12119 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12120 if (!table)
ea47320b 12121 continue;
d62a17ae 12122
4953391b
DA
12123 rm = bgp_node_match(table, &match);
12124 if (rm == NULL)
ea47320b 12125 continue;
d62a17ae 12126
9bcb3eef 12127 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12128 if (prefix_check
b54892e0 12129 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12130 bgp_dest_unlock_node(rm);
ea47320b
DL
12131 continue;
12132 }
d62a17ae 12133
9bcb3eef 12134 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12135 bgp, afi, safi, json, pathtype,
4027d19b 12136 &display, rpki_target_state);
44c69747 12137
9bcb3eef 12138 bgp_dest_unlock_node(rm);
44c69747
LK
12139 }
12140 } else if (safi == SAFI_EVPN) {
9bcb3eef 12141 struct bgp_dest *longest_pfx;
cded3b72 12142 bool is_exact_pfxlen_match = false;
44c69747 12143
9bcb3eef
DS
12144 for (dest = bgp_table_top(rib); dest;
12145 dest = bgp_route_next(dest)) {
12146 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12147
9bcb3eef 12148 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12149 continue;
9bcb3eef 12150 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12151 if (!table)
12152 continue;
12153
12154 longest_pfx = NULL;
cded3b72 12155 is_exact_pfxlen_match = false;
44c69747
LK
12156 /*
12157 * Search through all the prefixes for a match. The
12158 * pfx's are enumerated in ascending order of pfxlens.
12159 * So, the last pfx match is the longest match. Set
12160 * is_exact_pfxlen_match when we get exact pfxlen match
12161 */
12162 for (rm = bgp_table_top(table); rm;
12163 rm = bgp_route_next(rm)) {
b54892e0 12164 const struct prefix *rm_p =
9bcb3eef 12165 bgp_dest_get_prefix(rm);
44c69747
LK
12166 /*
12167 * Get prefixlen of the ip-prefix within type5
12168 * evpn route
12169 */
b54892e0
DS
12170 if (evpn_type5_prefix_match(rm_p, &match)
12171 && rm->info) {
44c69747
LK
12172 longest_pfx = rm;
12173 int type5_pfxlen =
b54892e0
DS
12174 bgp_evpn_get_type5_prefixlen(
12175 rm_p);
44c69747 12176 if (type5_pfxlen == match.prefixlen) {
cded3b72 12177 is_exact_pfxlen_match = true;
9bcb3eef 12178 bgp_dest_unlock_node(rm);
44c69747
LK
12179 break;
12180 }
d62a17ae 12181 }
12182 }
ea47320b 12183
44c69747
LK
12184 if (!longest_pfx)
12185 continue;
12186
12187 if (prefix_check && !is_exact_pfxlen_match)
12188 continue;
12189
12190 rm = longest_pfx;
9bcb3eef 12191 bgp_dest_lock_node(rm);
44c69747 12192
9bcb3eef 12193 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12194 bgp, afi, safi, json, pathtype,
4027d19b 12195 &display, rpki_target_state);
44c69747 12196
9bcb3eef 12197 bgp_dest_unlock_node(rm);
d62a17ae 12198 }
98a9dbc7 12199 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12200 if (use_json)
12201 json_paths = json_object_new_array();
12202
63a0b7a9
PG
12203 display = bgp_flowspec_display_match_per_ip(afi, rib,
12204 &match, prefix_check,
12205 vty,
12206 use_json,
12207 json_paths);
d5f20468
SP
12208 if (use_json) {
12209 if (display)
12210 json_object_object_add(json, "paths",
12211 json_paths);
12212 else
12213 json_object_free(json_paths);
12214 }
d62a17ae 12215 } else {
4953391b
DA
12216 dest = bgp_node_match(rib, &match);
12217 if (dest != NULL) {
9bcb3eef 12218 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12219 if (!prefix_check
9bcb3eef
DS
12220 || dest_p->prefixlen == match.prefixlen) {
12221 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12222 safi, json, pathtype,
4027d19b 12223 &display, rpki_target_state);
d62a17ae 12224 }
12225
9bcb3eef 12226 bgp_dest_unlock_node(dest);
d62a17ae 12227 }
12228 }
e5eee9af 12229
d62a17ae 12230 if (use_json) {
75eeda93 12231 vty_json(vty, json);
d62a17ae 12232 } else {
12233 if (!display) {
12234 vty_out(vty, "%% Network not in table\n");
12235 return CMD_WARNING;
12236 }
12237 }
b05a1c8b 12238
d62a17ae 12239 return CMD_SUCCESS;
718e3744 12240}
12241
fee0f4c6 12242/* Display specified route of Main RIB */
d62a17ae 12243static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12244 afi_t afi, safi_t safi, struct prefix_rd *prd,
12245 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12246 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12247{
9b86009a 12248 if (!bgp) {
d62a17ae 12249 bgp = bgp_get_default();
9b86009a
RW
12250 if (!bgp) {
12251 if (!use_json)
12252 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12253 else
12254 vty_out(vty, "{}\n");
9b86009a
RW
12255 return CMD_WARNING;
12256 }
12257 }
d62a17ae 12258
12259 /* labeled-unicast routes live in the unicast table */
12260 if (safi == SAFI_LABELED_UNICAST)
12261 safi = SAFI_UNICAST;
12262
12263 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12264 afi, safi, rpki_target_state, prd,
8aa22bbb 12265 prefix_check, pathtype, use_json);
d62a17ae 12266}
12267
12268static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12269 struct cmd_token **argv, bool exact, afi_t afi,
12270 safi_t safi, bool uj)
d62a17ae 12271{
12272 struct lcommunity *lcom;
12273 struct buffer *b;
12274 int i;
12275 char *str;
12276 int first = 0;
96c81f66 12277 uint16_t show_flags = 0;
4f28b2b5 12278 int ret;
96f3485c
MK
12279
12280 if (uj)
12281 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12282
12283 b = buffer_new(1024);
12284 for (i = 0; i < argc; i++) {
12285 if (first)
12286 buffer_putc(b, ' ');
12287 else {
12288 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12289 first = 1;
12290 buffer_putstr(b, argv[i]->arg);
12291 }
12292 }
12293 }
12294 buffer_putc(b, '\0');
57d187bc 12295
d62a17ae 12296 str = buffer_getstr(b);
12297 buffer_free(b);
57d187bc 12298
d62a17ae 12299 lcom = lcommunity_str2com(str);
12300 XFREE(MTYPE_TMP, str);
12301 if (!lcom) {
12302 vty_out(vty, "%% Large-community malformed\n");
12303 return CMD_WARNING;
12304 }
57d187bc 12305
4f28b2b5 12306 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12307 (exact ? bgp_show_type_lcommunity_exact
12308 : bgp_show_type_lcommunity),
12309 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12310
12311 lcommunity_free(&lcom);
12312 return ret;
57d187bc
JS
12313}
12314
d62a17ae 12315static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12316 const char *lcom, bool exact, afi_t afi,
12317 safi_t safi, bool uj)
57d187bc 12318{
d62a17ae 12319 struct community_list *list;
96c81f66 12320 uint16_t show_flags = 0;
96f3485c
MK
12321
12322 if (uj)
12323 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12324
57d187bc 12325
e237b0d2 12326 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12327 LARGE_COMMUNITY_LIST_MASTER);
12328 if (list == NULL) {
12329 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12330 lcom);
12331 return CMD_WARNING;
12332 }
57d187bc 12333
36a206db 12334 return bgp_show(vty, bgp, afi, safi,
12335 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12336 : bgp_show_type_lcommunity_list),
1e2ce4f1 12337 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12338}
12339
52951b63
DS
12340DEFUN (show_ip_bgp_large_community_list,
12341 show_ip_bgp_large_community_list_cmd,
77a3a95e 12342 "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
12343 SHOW_STR
12344 IP_STR
12345 BGP_STR
12346 BGP_INSTANCE_HELP_STR
9bedbb1e 12347 BGP_AFI_HELP_STR
4dd6177e 12348 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12349 "Display routes matching the large-community-list\n"
12350 "large-community-list number\n"
12351 "large-community-list name\n"
36a206db 12352 "Exact match of the large-communities\n"
52951b63
DS
12353 JSON_STR)
12354{
d62a17ae 12355 afi_t afi = AFI_IP6;
12356 safi_t safi = SAFI_UNICAST;
12357 int idx = 0;
36a206db 12358 bool exact_match = 0;
4d678463 12359 struct bgp *bgp = NULL;
9f049418 12360 bool uj = use_json(argc, argv);
d62a17ae 12361
ef3364f0
DA
12362 if (uj)
12363 argc--;
4d678463 12364
ef3364f0
DA
12365 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12366 &bgp, uj);
12367 if (!idx)
12368 return CMD_WARNING;
d62a17ae 12369
12370 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12371
12372 const char *clist_number_or_name = argv[++idx]->arg;
12373
12374 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12375 exact_match = 1;
12376
12377 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12378 exact_match, afi, safi, uj);
52951b63
DS
12379}
12380DEFUN (show_ip_bgp_large_community,
12381 show_ip_bgp_large_community_cmd,
36a206db 12382 "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
12383 SHOW_STR
12384 IP_STR
12385 BGP_STR
12386 BGP_INSTANCE_HELP_STR
9bedbb1e 12387 BGP_AFI_HELP_STR
4dd6177e 12388 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12389 "Display routes matching the large-communities\n"
12390 "List of large-community numbers\n"
36a206db 12391 "Exact match of the large-communities\n"
52951b63
DS
12392 JSON_STR)
12393{
d62a17ae 12394 afi_t afi = AFI_IP6;
12395 safi_t safi = SAFI_UNICAST;
12396 int idx = 0;
36a206db 12397 bool exact_match = 0;
4d678463 12398 struct bgp *bgp = NULL;
9f049418 12399 bool uj = use_json(argc, argv);
96c81f66 12400 uint16_t show_flags = 0;
d62a17ae 12401
96f3485c
MK
12402 if (uj) {
12403 argc--;
12404 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12405 }
4d678463 12406
96f3485c
MK
12407 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12408 &bgp, uj);
12409 if (!idx)
12410 return CMD_WARNING;
d62a17ae 12411
36a206db 12412 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12413 if (argv_find(argv, argc, "exact-match", &idx)) {
12414 argc--;
36a206db 12415 exact_match = 1;
1857760c 12416 }
36a206db 12417 return bgp_show_lcommunity(vty, bgp, argc, argv,
12418 exact_match, afi, safi, uj);
12419 } else
d62a17ae 12420 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12421 bgp_show_type_lcommunity_all, NULL, show_flags,
12422 RPKI_NOT_BEING_USED);
52951b63
DS
12423}
12424
71f1613a
DA
12425static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12426 safi_t safi, struct json_object *json_array);
d62a17ae 12427static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12428 safi_t safi, struct json_object *json);
e01ca200 12429
7b2ff250 12430
9ab0cf58
PG
12431DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12432 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12433 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12434 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12435{
12436 bool uj = use_json(argc, argv);
12437 struct bgp *bgp = NULL;
ec76a1d1
DA
12438 safi_t safi = SAFI_UNICAST;
12439 afi_t afi = AFI_IP6;
4265b261 12440 int idx = 0;
6c9d22e2
PG
12441 struct json_object *json_all = NULL;
12442 struct json_object *json_afi_safi = NULL;
4265b261
PG
12443
12444 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12445 &bgp, false);
71f1613a 12446 if (!idx)
4265b261 12447 return CMD_WARNING;
6c9d22e2 12448
4265b261 12449 if (uj)
6c9d22e2 12450 json_all = json_object_new_object();
4265b261 12451
9ab0cf58
PG
12452 FOREACH_AFI_SAFI (afi, safi) {
12453 /*
12454 * So limit output to those afi/safi pairs that
12455 * actually have something interesting in them
12456 */
12457 if (strmatch(get_afi_safi_str(afi, safi, true),
12458 "Unknown")) {
12459 continue;
12460 }
12461 if (uj) {
12462 json_afi_safi = json_object_new_array();
12463 json_object_object_add(
12464 json_all,
12465 get_afi_safi_str(afi, safi, true),
12466 json_afi_safi);
12467 } else {
12468 json_afi_safi = NULL;
6c9d22e2 12469 }
9ab0cf58
PG
12470
12471 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12472 }
6c9d22e2 12473
3757f964
DA
12474 if (uj)
12475 vty_json(vty, json_all);
6c9d22e2 12476
4265b261
PG
12477 return CMD_SUCCESS;
12478}
12479
7b2ff250 12480/* BGP route print out function without JSON */
14718643
PG
12481DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12482 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12483 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12484 SHOW_STR
12485 IP_STR
12486 BGP_STR
12487 BGP_INSTANCE_HELP_STR
12488 L2VPN_HELP_STR
12489 EVPN_HELP_STR
12490 "BGP RIB advertisement statistics\n"
12491 JSON_STR)
12492{
ec76a1d1
DA
12493 afi_t afi = AFI_IP6;
12494 safi_t safi = SAFI_UNICAST;
14718643
PG
12495 struct bgp *bgp = NULL;
12496 int idx = 0, ret;
12497 bool uj = use_json(argc, argv);
12498 struct json_object *json_afi_safi = NULL, *json = NULL;
12499
12500 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12501 &bgp, false);
12502 if (!idx)
12503 return CMD_WARNING;
12504
12505 if (uj)
12506 json_afi_safi = json_object_new_array();
12507 else
12508 json_afi_safi = NULL;
12509
12510 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12511
12512 if (uj) {
12513 json = json_object_new_object();
12514 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12515 json_afi_safi);
3757f964 12516 vty_json(vty, json);
14718643
PG
12517 }
12518 return ret;
12519}
12520
893cccd0 12521/* BGP route print out function without JSON */
9ab0cf58
PG
12522DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12523 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12524 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12525 "]]\
893cccd0 12526 statistics [json]",
9ab0cf58
PG
12527 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12528 BGP_SAFI_WITH_LABEL_HELP_STR
12529 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12530{
ec76a1d1
DA
12531 afi_t afi = AFI_IP6;
12532 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12533 struct bgp *bgp = NULL;
12534 int idx = 0, ret;
12535 bool uj = use_json(argc, argv);
6c9d22e2 12536 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12537
12538 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12539 &bgp, false);
12540 if (!idx)
12541 return CMD_WARNING;
6c9d22e2 12542
893cccd0 12543 if (uj)
6c9d22e2
PG
12544 json_afi_safi = json_object_new_array();
12545 else
12546 json_afi_safi = NULL;
12547
12548 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12549
12550 if (uj) {
12551 json = json_object_new_object();
12552 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12553 json_afi_safi);
3757f964 12554 vty_json(vty, json);
893cccd0
PG
12555 }
12556 return ret;
893cccd0 12557}
7b2ff250 12558
fe0f234d 12559DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12560 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12561 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12562 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12563 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12564 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12565 "Display the entries for all address families\n"
9ab0cf58
PG
12566 "Display detailed information about dampening\n"
12567 "Display detail of configured dampening parameters\n"
fe0f234d 12568 JSON_STR)
718e3744 12569{
d62a17ae 12570 afi_t afi = AFI_IP6;
12571 safi_t safi = SAFI_UNICAST;
d62a17ae 12572 struct bgp *bgp = NULL;
12573 int idx = 0;
96c81f66 12574 uint16_t show_flags = 0;
fe0f234d
RW
12575 bool uj = use_json(argc, argv);
12576
12577 if (uj) {
12578 argc--;
12579 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12580 }
96f3485c
MK
12581
12582 /* [<ipv4|ipv6> [all]] */
12583 if (all) {
12584 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12585 if (argv_find(argv, argc, "ipv4", &idx))
12586 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12587
12588 if (argv_find(argv, argc, "ipv6", &idx))
12589 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12590 }
d62a17ae 12591
12592 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12593 &bgp, false);
d62a17ae 12594 if (!idx)
12595 return CMD_WARNING;
12596
fe0f234d 12597 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12598}
12599
fe0f234d
RW
12600/* BGP route print out function */
12601DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12602 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12603 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12604 "]]\
96f3485c 12605 [all$all]\
cf4898bc
QY
12606 [cidr-only\
12607 |dampening <flap-statistics|dampened-paths>\
12608 |community [AA:NN|local-AS|no-advertise|no-export\
12609 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12610 |accept-own|accept-own-nexthop|route-filter-v6\
12611 |route-filter-v4|route-filter-translated-v6\
12612 |route-filter-translated-v4] [exact-match]\
70799983 12613 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12614 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12615 |prefix-list WORD\
ed126382 12616 |access-list ACCESSLIST_NAME\
70dd370f 12617 |route-map RMAP_NAME\
1e2ce4f1 12618 |rpki <invalid|valid|notfound>\
7d3cae70 12619 |version (1-4294967295)\
b4ad2fae 12620 |alias ALIAS_NAME\
39c3c736
RW
12621 |A.B.C.D/M longer-prefixes\
12622 |X:X::X:X/M longer-prefixes\
70cd87ca 12623 |optimal-route-reflection [WORD$orr_group_name]\
f280c93b 12624 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12625 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12626 BGP_SAFI_WITH_LABEL_HELP_STR
12627 "Display the entries for all address families\n"
12628 "Display only routes with non-natural netmasks\n"
12629 "Display detailed information about dampening\n"
12630 "Display flap statistics of routes\n"
12631 "Display paths suppressed due to dampening\n"
12632 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12633 "Do not send outside local AS (well-known community)\n"
12634 "Do not advertise to any peer (well-known community)\n"
12635 "Do not export to next AS (well-known community)\n"
12636 "Graceful shutdown (well-known community)\n"
12637 "Do not export to any peer (well-known community)\n"
12638 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12639 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12640 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12641 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12642 "Should accept VPN route with local nexthop (well-known community)\n"
12643 "RT VPNv6 route filtering (well-known community)\n"
12644 "RT VPNv4 route filtering (well-known community)\n"
12645 "RT translated VPNv6 route filtering (well-known community)\n"
12646 "RT translated VPNv4 route filtering (well-known community)\n"
12647 "Exact match of the communities\n"
70799983
RW
12648 "Community-list number\n"
12649 "Community-list name\n"
12650 "Display routes matching the community-list\n"
12651 "Exact match of the communities\n"
a7129347
RW
12652 "Display routes conforming to the filter-list\n"
12653 "Regular expression access list name\n"
6deaf579
RW
12654 "Display routes conforming to the prefix-list\n"
12655 "Prefix-list name\n"
ed126382
DA
12656 "Display routes conforming to the access-list\n"
12657 "Access-list name\n"
bf1a944a
RW
12658 "Display routes matching the route-map\n"
12659 "A route-map to match on\n"
a70a28a5
DA
12660 "RPKI route types\n"
12661 "A valid path as determined by rpki\n"
12662 "A invalid path as determined by rpki\n"
12663 "A path that has no rpki data\n"
12664 "Display prefixes with matching version numbers\n"
12665 "Version number and above\n"
12666 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12667 "BGP community alias\n"
12668 "IPv4 prefix\n"
12669 "Display route and more specific routes\n"
12670 "IPv6 prefix\n"
12671 "Display route and more specific routes\n"
70cd87ca
MK
12672 "Display Optimal Route Reflection RR Clients\n"
12673 "ORR Group name\n"
39c3c736 12674 JSON_STR
a70a28a5
DA
12675 "Display detailed version of JSON output\n"
12676 "Increase table width for longer prefixes\n")
7b2ff250
DW
12677{
12678 afi_t afi = AFI_IP6;
12679 safi_t safi = SAFI_UNICAST;
12680 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12681 void *output_arg = NULL;
7b2ff250
DW
12682 struct bgp *bgp = NULL;
12683 int idx = 0;
d0086e8e 12684 int exact_match = 0;
96f3485c
MK
12685 char *community = NULL;
12686 bool first = true;
96c81f66 12687 uint16_t show_flags = 0;
4027d19b 12688 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12689 struct prefix p;
70cd87ca 12690 bool orr_group = false;
96f3485c
MK
12691
12692 if (uj) {
9f049418 12693 argc--;
96f3485c
MK
12694 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12695 }
12696
f280c93b
DA
12697 if (detail)
12698 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12699
96f3485c
MK
12700 /* [<ipv4|ipv6> [all]] */
12701 if (all) {
12702 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12703
12704 if (argv_find(argv, argc, "ipv4", &idx))
12705 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12706
12707 if (argv_find(argv, argc, "ipv6", &idx))
12708 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12709 }
12710
12711 if (wide)
12712 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12713
12714 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12715 &bgp, uj);
7b2ff250
DW
12716 if (!idx)
12717 return CMD_WARNING;
12718
7b2ff250 12719 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12720 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12721
12722 if (argv_find(argv, argc, "dampening", &idx)) {
12723 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12724 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12725 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12726 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12727 }
12728
12729 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12730 char *maybecomm = NULL;
d0086e8e 12731
79bc257a
RW
12732 if (idx + 1 < argc) {
12733 if (argv[idx + 1]->type == VARIABLE_TKN)
12734 maybecomm = argv[idx + 1]->arg;
12735 else
12736 maybecomm = argv[idx + 1]->text;
12737 }
12738
cf4898bc
QY
12739 if (maybecomm && !strmatch(maybecomm, "json")
12740 && !strmatch(maybecomm, "exact-match"))
12741 community = maybecomm;
d0086e8e 12742
cf4898bc
QY
12743 if (argv_find(argv, argc, "exact-match", &idx))
12744 exact_match = 1;
d0086e8e 12745
96f3485c
MK
12746 if (!community)
12747 sh_type = bgp_show_type_community_all;
12748 }
12749
70799983
RW
12750 if (argv_find(argv, argc, "community-list", &idx)) {
12751 const char *clist_number_or_name = argv[++idx]->arg;
12752 struct community_list *list;
12753
12754 if (argv_find(argv, argc, "exact-match", &idx))
12755 exact_match = 1;
12756
12757 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12758 COMMUNITY_LIST_MASTER);
12759 if (list == NULL) {
606d49a4 12760 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12761 clist_number_or_name);
12762 return CMD_WARNING;
12763 }
12764
12765 if (exact_match)
12766 sh_type = bgp_show_type_community_list_exact;
12767 else
12768 sh_type = bgp_show_type_community_list;
12769 output_arg = list;
12770 }
12771
a7129347
RW
12772 if (argv_find(argv, argc, "filter-list", &idx)) {
12773 const char *filter = argv[++idx]->arg;
12774 struct as_list *as_list;
12775
12776 as_list = as_list_lookup(filter);
12777 if (as_list == NULL) {
606d49a4 12778 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12779 filter);
12780 return CMD_WARNING;
12781 }
12782
12783 sh_type = bgp_show_type_filter_list;
12784 output_arg = as_list;
12785 }
12786
6deaf579
RW
12787 if (argv_find(argv, argc, "prefix-list", &idx)) {
12788 const char *prefix_list_str = argv[++idx]->arg;
12789 struct prefix_list *plist;
12790
12791 plist = prefix_list_lookup(afi, prefix_list_str);
12792 if (plist == NULL) {
606d49a4 12793 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12794 prefix_list_str);
12795 return CMD_WARNING;
12796 }
12797
12798 sh_type = bgp_show_type_prefix_list;
12799 output_arg = plist;
12800 }
12801
ed126382
DA
12802 if (argv_find(argv, argc, "access-list", &idx)) {
12803 const char *access_list_str = argv[++idx]->arg;
12804 struct access_list *alist;
12805
12806 alist = access_list_lookup(afi, access_list_str);
12807 if (!alist) {
606d49a4 12808 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12809 access_list_str);
12810 return CMD_WARNING;
12811 }
12812
12813 sh_type = bgp_show_type_access_list;
12814 output_arg = alist;
12815 }
12816
bf1a944a
RW
12817 if (argv_find(argv, argc, "route-map", &idx)) {
12818 const char *rmap_str = argv[++idx]->arg;
12819 struct route_map *rmap;
12820
12821 rmap = route_map_lookup_by_name(rmap_str);
12822 if (!rmap) {
606d49a4 12823 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12824 return CMD_WARNING;
12825 }
12826
12827 sh_type = bgp_show_type_route_map;
12828 output_arg = rmap;
12829 }
12830
1e2ce4f1
DS
12831 if (argv_find(argv, argc, "rpki", &idx)) {
12832 sh_type = bgp_show_type_rpki;
12833 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12834 rpki_target_state = RPKI_VALID;
1e2ce4f1 12835 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12836 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12837 }
12838
7d3cae70
DA
12839 /* Display prefixes with matching version numbers */
12840 if (argv_find(argv, argc, "version", &idx)) {
12841 sh_type = bgp_show_type_prefix_version;
2391833e 12842 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12843 }
12844
a70a28a5
DA
12845 /* Display prefixes with matching BGP community alias */
12846 if (argv_find(argv, argc, "alias", &idx)) {
12847 sh_type = bgp_show_type_community_alias;
2391833e 12848 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12849 }
12850
39c3c736
RW
12851 /* prefix-longer */
12852 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12853 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12854 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12855
12856 if (!str2prefix(prefix_str, &p)) {
12857 vty_out(vty, "%% Malformed Prefix\n");
12858 return CMD_WARNING;
12859 }
12860
12861 sh_type = bgp_show_type_prefix_longer;
12862 output_arg = &p;
a70a28a5
DA
12863 }
12864
70cd87ca
MK
12865 if (argv_find(argv, argc, "optimal-route-reflection", &idx))
12866 orr_group = true;
12867
96f3485c
MK
12868 if (!all) {
12869 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12870 if (community)
12871 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12872 exact_match, afi, safi,
12873 show_flags);
70cd87ca
MK
12874 else if (orr_group)
12875 return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
12876 show_flags);
2391833e 12877 else
a70a28a5 12878 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12879 output_arg, show_flags,
a70a28a5 12880 rpki_target_state);
96f3485c 12881 } else {
fa5ac378
DA
12882 struct listnode *node;
12883 struct bgp *abgp;
96f3485c
MK
12884 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12885 * AFI_IP6 */
12886
12887 if (uj)
12888 vty_out(vty, "{\n");
12889
12890 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12891 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12892 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12893 ? AFI_IP
12894 : AFI_IP6;
fa5ac378
DA
12895 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12896 FOREACH_SAFI (safi) {
12897 if (!bgp_afi_safi_peer_exists(abgp, afi,
12898 safi))
12899 continue;
96f3485c 12900
fa5ac378
DA
12901 if (uj) {
12902 if (first)
12903 first = false;
12904 else
12905 vty_out(vty, ",\n");
12906 vty_out(vty, "\"%s\":{\n",
12907 get_afi_safi_str(afi,
12908 safi,
12909 true));
12910 } else
12911 vty_out(vty,
12912 "\nFor address family: %s\n",
12913 get_afi_safi_str(
12914 afi, safi,
12915 false));
12916
12917 if (community)
12918 bgp_show_community(
12919 vty, abgp, community,
12920 exact_match, afi, safi,
12921 show_flags);
70cd87ca
MK
12922 else if (orr_group)
12923 bgp_show_orr(vty, bgp, afi,
12924 safi,
12925 orr_group_name,
12926 show_flags);
96f3485c 12927 else
fa5ac378
DA
12928 bgp_show(vty, abgp, afi, safi,
12929 sh_type, output_arg,
12930 show_flags,
12931 rpki_target_state);
12932 if (uj)
12933 vty_out(vty, "}\n");
12934 }
96f3485c
MK
12935 }
12936 } else {
12937 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12938 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12939 FOREACH_AFI_SAFI (afi, safi) {
12940 if (!bgp_afi_safi_peer_exists(abgp, afi,
12941 safi))
12942 continue;
96f3485c 12943
fa5ac378
DA
12944 if (uj) {
12945 if (first)
12946 first = false;
12947 else
12948 vty_out(vty, ",\n");
12949
12950 vty_out(vty, "\"%s\":{\n",
12951 get_afi_safi_str(afi,
12952 safi,
12953 true));
12954 } else
12955 vty_out(vty,
12956 "\nFor address family: %s\n",
12957 get_afi_safi_str(
12958 afi, safi,
12959 false));
12960
12961 if (community)
12962 bgp_show_community(
12963 vty, abgp, community,
12964 exact_match, afi, safi,
12965 show_flags);
70cd87ca
MK
12966 else if (orr_group)
12967 bgp_show_orr(vty, bgp, afi,
12968 safi,
12969 orr_group_name,
12970 show_flags);
96f3485c 12971 else
fa5ac378
DA
12972 bgp_show(vty, abgp, afi, safi,
12973 sh_type, output_arg,
12974 show_flags,
12975 rpki_target_state);
12976 if (uj)
12977 vty_out(vty, "}\n");
12978 }
96f3485c
MK
12979 }
12980 }
12981 if (uj)
12982 vty_out(vty, "}\n");
12983 }
12984 return CMD_SUCCESS;
a636c635 12985}
47fc97cc 12986
718e3744 12987DEFUN (show_ip_bgp_route,
12988 show_ip_bgp_route_cmd,
8aa22bbb 12989 "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 12990 SHOW_STR
12991 IP_STR
12992 BGP_STR
a636c635 12993 BGP_INSTANCE_HELP_STR
4f280b15 12994 BGP_AFI_HELP_STR
4dd6177e 12995 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12996 "Network in the BGP routing table to display\n"
0c7b1b01 12997 "IPv4 prefix\n"
8c3deaae 12998 "Network in the BGP routing table to display\n"
0c7b1b01 12999 "IPv6 prefix\n"
4092b06c 13000 "Display only the bestpath\n"
b05a1c8b 13001 "Display only multipaths\n"
8aa22bbb
DS
13002 "Display only paths that match the specified rpki state\n"
13003 "A valid path as determined by rpki\n"
13004 "A invalid path as determined by rpki\n"
13005 "A path that has no rpki data\n"
9973d184 13006 JSON_STR)
4092b06c 13007{
d62a17ae 13008 int prefix_check = 0;
ae19d7dd 13009
d62a17ae 13010 afi_t afi = AFI_IP6;
13011 safi_t safi = SAFI_UNICAST;
13012 char *prefix = NULL;
13013 struct bgp *bgp = NULL;
13014 enum bgp_path_type path_type;
9f049418 13015 bool uj = use_json(argc, argv);
b05a1c8b 13016
d62a17ae 13017 int idx = 0;
ae19d7dd 13018
d62a17ae 13019 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13020 &bgp, uj);
d62a17ae 13021 if (!idx)
13022 return CMD_WARNING;
c41247f5 13023
d62a17ae 13024 if (!bgp) {
13025 vty_out(vty,
13026 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13027 return CMD_WARNING;
13028 }
a636c635 13029
d62a17ae 13030 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13031 if (argv_find(argv, argc, "A.B.C.D", &idx)
13032 || argv_find(argv, argc, "X:X::X:X", &idx))
13033 prefix_check = 0;
13034 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13035 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13036 prefix_check = 1;
13037
13038 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13039 && afi != AFI_IP6) {
13040 vty_out(vty,
13041 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13042 return CMD_WARNING;
13043 }
13044 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13045 && afi != AFI_IP) {
13046 vty_out(vty,
13047 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13048 return CMD_WARNING;
13049 }
13050
13051 prefix = argv[idx]->arg;
13052
13053 /* [<bestpath|multipath>] */
13054 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13055 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13056 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13057 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13058 else
360660c6 13059 path_type = BGP_PATH_SHOW_ALL;
a636c635 13060
d62a17ae 13061 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13062 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13063}
13064
8c3deaae
QY
13065DEFUN (show_ip_bgp_regexp,
13066 show_ip_bgp_regexp_cmd,
3e5b31b3 13067 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13068 SHOW_STR
13069 IP_STR
13070 BGP_STR
b00b230a 13071 BGP_INSTANCE_HELP_STR
4f280b15 13072 BGP_AFI_HELP_STR
4dd6177e 13073 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13074 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13075 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13076 JSON_STR)
8c3deaae 13077{
d62a17ae 13078 afi_t afi = AFI_IP6;
13079 safi_t safi = SAFI_UNICAST;
13080 struct bgp *bgp = NULL;
3e5b31b3
DA
13081 bool uj = use_json(argc, argv);
13082 char *regstr = NULL;
8c3deaae 13083
d62a17ae 13084 int idx = 0;
13085 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13086 &bgp, false);
d62a17ae 13087 if (!idx)
13088 return CMD_WARNING;
8c3deaae 13089
d62a17ae 13090 // get index of regex
3e5b31b3
DA
13091 if (argv_find(argv, argc, "REGEX", &idx))
13092 regstr = argv[idx]->arg;
8c3deaae 13093
5f71d11c 13094 assert(regstr);
3e5b31b3
DA
13095 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13096 bgp_show_type_regexp, uj);
8c3deaae
QY
13097}
13098
ae248832 13099DEFPY (show_ip_bgp_instance_all,
a636c635 13100 show_ip_bgp_instance_all_cmd,
ae248832 13101 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13102 SHOW_STR
a636c635 13103 IP_STR
4092b06c 13104 BGP_STR
a636c635 13105 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13106 BGP_AFI_HELP_STR
4dd6177e 13107 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13108 JSON_STR
13109 "Increase table width for longer prefixes\n")
4092b06c 13110{
54d05dea 13111 afi_t afi = AFI_IP6;
d62a17ae 13112 safi_t safi = SAFI_UNICAST;
13113 struct bgp *bgp = NULL;
d62a17ae 13114 int idx = 0;
96c81f66 13115 uint16_t show_flags = 0;
ae19d7dd 13116
96f3485c 13117 if (uj) {
d62a17ae 13118 argc--;
96f3485c
MK
13119 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13120 }
13121
13122 if (wide)
13123 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13124
9f049418
DS
13125 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13126 &bgp, uj);
13127 if (!idx)
13128 return CMD_WARNING;
13129
96f3485c 13130 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13131 return CMD_SUCCESS;
e3e29b32
LB
13132}
13133
a4d82a8a 13134static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13135 afi_t afi, safi_t safi, enum bgp_show_type type,
13136 bool use_json)
718e3744 13137{
d62a17ae 13138 regex_t *regex;
13139 int rc;
96c81f66 13140 uint16_t show_flags = 0;
96f3485c
MK
13141
13142 if (use_json)
13143 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13144
c3900853 13145 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13146 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13147 regstr);
13148 return CMD_WARNING_CONFIG_FAILED;
13149 }
13150
d62a17ae 13151 regex = bgp_regcomp(regstr);
13152 if (!regex) {
13153 vty_out(vty, "Can't compile regexp %s\n", regstr);
13154 return CMD_WARNING;
13155 }
a636c635 13156
1e2ce4f1
DS
13157 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13158 RPKI_NOT_BEING_USED);
d62a17ae 13159 bgp_regex_free(regex);
13160 return rc;
e3e29b32
LB
13161}
13162
7f323236
DW
13163static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13164 const char *comstr, int exact, afi_t afi,
96c81f66 13165 safi_t safi, uint16_t show_flags)
d62a17ae 13166{
13167 struct community *com;
d62a17ae 13168 int ret = 0;
13169
7f323236 13170 com = community_str2com(comstr);
d62a17ae 13171 if (!com) {
7f323236 13172 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13173 return CMD_WARNING;
13174 }
13175
13176 ret = bgp_show(vty, bgp, afi, safi,
13177 (exact ? bgp_show_type_community_exact
13178 : bgp_show_type_community),
1e2ce4f1 13179 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13180 community_free(&com);
46c3ce83 13181
d62a17ae 13182 return ret;
718e3744 13183}
13184
d62a17ae 13185enum bgp_stats {
13186 BGP_STATS_MAXBITLEN = 0,
13187 BGP_STATS_RIB,
13188 BGP_STATS_PREFIXES,
13189 BGP_STATS_TOTPLEN,
13190 BGP_STATS_UNAGGREGATEABLE,
13191 BGP_STATS_MAX_AGGREGATEABLE,
13192 BGP_STATS_AGGREGATES,
13193 BGP_STATS_SPACE,
13194 BGP_STATS_ASPATH_COUNT,
13195 BGP_STATS_ASPATH_MAXHOPS,
13196 BGP_STATS_ASPATH_TOTHOPS,
13197 BGP_STATS_ASPATH_MAXSIZE,
13198 BGP_STATS_ASPATH_TOTSIZE,
13199 BGP_STATS_ASN_HIGHEST,
13200 BGP_STATS_MAX,
a636c635 13201};
2815e61f 13202
9ab0cf58 13203#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13204#define TABLE_STATS_IDX_JSON 1
13205
13206static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13207 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13208 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13209 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13210 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13211 "unaggregateablePrefixes"},
13212 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13213 "maximumAggregateablePrefixes"},
13214 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13215 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13216 [BGP_STATS_SPACE] = {"Address space advertised",
13217 "addressSpaceAdvertised"},
9ab0cf58
PG
13218 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13219 "advertisementsWithPaths"},
13220 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13221 "longestAsPath"},
13222 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13223 "largestAsPath"},
13224 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13225 "averageAsPathLengthHops"},
13226 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13227 "averageAsPathSizeBytes"},
13228 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13229 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13230};
2815e61f 13231
d62a17ae 13232struct bgp_table_stats {
13233 struct bgp_table *table;
13234 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13235
13236 unsigned long long
13237 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13238 1];
13239
8d0ab76d 13240 double total_space;
ff7924f6
PJ
13241};
13242
9bcb3eef 13243static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13244 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13245{
9bcb3eef 13246 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13247 struct bgp_path_info *pi;
b54892e0 13248 const struct prefix *rn_p;
d62a17ae 13249
9bcb3eef 13250 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13251 return;
d62a17ae 13252
9bcb3eef 13253 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13254 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13255 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13256
0747643e 13257 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13258 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13259 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13260 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13261
9bcb3eef 13262 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13263 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13264 /* announced address space */
13265 if (space)
b54892e0 13266 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13267 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13268 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13269
9c14ec72 13270
9bcb3eef 13271 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13272 ts->counts[BGP_STATS_RIB]++;
13273
05864da7
DS
13274 if (CHECK_FLAG(pi->attr->flag,
13275 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13276 ts->counts[BGP_STATS_AGGREGATES]++;
13277
13278 /* as-path stats */
05864da7 13279 if (pi->attr->aspath) {
9c14ec72
RW
13280 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13281 unsigned int size = aspath_size(pi->attr->aspath);
13282 as_t highest = aspath_highest(pi->attr->aspath);
13283
13284 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13285
13286 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13287 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13288
13289 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13290 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13291
13292 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13293 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13294 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13295 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13296 }
13297 }
13298}
13299
cc9f21da 13300static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13301{
9bcb3eef
DS
13302 struct bgp_dest *dest, *ndest;
13303 struct bgp_dest *top;
9c14ec72
RW
13304 struct bgp_table_stats *ts = THREAD_ARG(t);
13305 unsigned int space = 0;
13306
13307 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13308 return;
9c14ec72
RW
13309
13310 switch (ts->table->afi) {
13311 case AFI_IP:
13312 space = IPV4_MAX_BITLEN;
13313 break;
13314 case AFI_IP6:
13315 space = IPV6_MAX_BITLEN;
13316 break;
3ba7b4af
TA
13317 case AFI_L2VPN:
13318 space = EVPN_ROUTE_PREFIXLEN;
13319 break;
9c14ec72 13320 default:
cc9f21da 13321 return;
9c14ec72
RW
13322 }
13323
13324 ts->counts[BGP_STATS_MAXBITLEN] = space;
13325
9bcb3eef 13326 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13327 if (ts->table->safi == SAFI_MPLS_VPN
13328 || ts->table->safi == SAFI_ENCAP
13329 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13330 struct bgp_table *table;
13331
9bcb3eef 13332 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13333 if (!table)
13334 continue;
13335
13336 top = bgp_table_top(table);
9bcb3eef
DS
13337 for (ndest = bgp_table_top(table); ndest;
13338 ndest = bgp_route_next(ndest))
13339 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13340 } else {
9bcb3eef 13341 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13342 }
13343 }
2815e61f 13344}
ff7924f6 13345
71f1613a
DA
13346static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13347 struct json_object *json_array)
13348{
13349 struct listnode *node, *nnode;
13350 struct bgp *bgp;
13351
13352 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13353 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13354}
13355
13356static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13357 safi_t safi, struct json_object *json_array)
2815e61f 13358{
d62a17ae 13359 struct bgp_table_stats ts;
13360 unsigned int i;
893cccd0
PG
13361 int ret = CMD_SUCCESS;
13362 char temp_buf[20];
6c9d22e2 13363 struct json_object *json = NULL;
0747643e
AQ
13364 uint32_t bitlen = 0;
13365 struct json_object *json_bitlen;
6c9d22e2
PG
13366
13367 if (json_array)
13368 json = json_object_new_object();
019386c2 13369
d62a17ae 13370 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13371 char warning_msg[50];
13372
13373 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13374 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13375 safi);
6c9d22e2
PG
13376
13377 if (!json)
893cccd0
PG
13378 vty_out(vty, "%s\n", warning_msg);
13379 else
9ab0cf58 13380 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13381
893cccd0
PG
13382 ret = CMD_WARNING;
13383 goto end_table_stats;
d62a17ae 13384 }
019386c2 13385
893cccd0 13386 if (!json)
5290ceab
DA
13387 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13388 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13389 else
13390 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13391
d62a17ae 13392 /* labeled-unicast routes live in the unicast table */
13393 if (safi == SAFI_LABELED_UNICAST)
13394 safi = SAFI_UNICAST;
019386c2 13395
d62a17ae 13396 memset(&ts, 0, sizeof(ts));
13397 ts.table = bgp->rib[afi][safi];
13398 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13399
d62a17ae 13400 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13401 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13402 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13403 continue;
13404
13405 switch (i) {
d62a17ae 13406 case BGP_STATS_ASPATH_TOTHOPS:
13407 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13408 if (!json) {
9ab0cf58
PG
13409 snprintf(
13410 temp_buf, sizeof(temp_buf), "%12.2f",
13411 ts.counts[i]
13412 ? (float)ts.counts[i]
13413 / (float)ts.counts
13414 [BGP_STATS_ASPATH_COUNT]
13415 : 0);
893cccd0 13416 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13417 table_stats_strs[i]
13418 [TABLE_STATS_IDX_VTY],
893cccd0 13419 temp_buf);
9ab0cf58
PG
13420 } else {
13421 json_object_double_add(
13422 json,
13423 table_stats_strs[i]
13424 [TABLE_STATS_IDX_JSON],
13425 ts.counts[i]
13426 ? (double)ts.counts[i]
13427 / (double)ts.counts
d62a17ae 13428 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13429 : 0);
13430 }
d62a17ae 13431 break;
13432 case BGP_STATS_TOTPLEN:
6c9d22e2 13433 if (!json) {
9ab0cf58
PG
13434 snprintf(
13435 temp_buf, sizeof(temp_buf), "%12.2f",
13436 ts.counts[i]
13437 ? (float)ts.counts[i]
13438 / (float)ts.counts
13439 [BGP_STATS_PREFIXES]
13440 : 0);
893cccd0 13441 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13442 table_stats_strs[i]
13443 [TABLE_STATS_IDX_VTY],
893cccd0 13444 temp_buf);
9ab0cf58
PG
13445 } else {
13446 json_object_double_add(
13447 json,
13448 table_stats_strs[i]
13449 [TABLE_STATS_IDX_JSON],
13450 ts.counts[i]
13451 ? (double)ts.counts[i]
13452 / (double)ts.counts
d62a17ae 13453 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13454 : 0);
13455 }
d62a17ae 13456 break;
13457 case BGP_STATS_SPACE:
6c9d22e2
PG
13458 if (!json) {
13459 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13460 ts.total_space);
893cccd0 13461 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13462 table_stats_strs[i]
13463 [TABLE_STATS_IDX_VTY],
893cccd0 13464 temp_buf);
9ab0cf58
PG
13465 } else {
13466 json_object_double_add(
13467 json,
13468 table_stats_strs[i]
13469 [TABLE_STATS_IDX_JSON],
13470 (double)ts.total_space);
13471 }
8d0ab76d 13472 if (afi == AFI_IP6) {
6c9d22e2
PG
13473 if (!json) {
13474 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13475 "%12g",
13476 ts.total_space
13477 * pow(2.0, -128 + 32));
6c9d22e2
PG
13478 vty_out(vty, "%30s: %s\n",
13479 "/32 equivalent %s\n",
13480 temp_buf);
9ab0cf58
PG
13481 } else {
13482 json_object_double_add(
13483 json, "/32equivalent",
13484 (double)(ts.total_space
13485 * pow(2.0,
13486 -128 + 32)));
13487 }
6c9d22e2
PG
13488 if (!json) {
13489 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13490 "%12g",
13491 ts.total_space
13492 * pow(2.0, -128 + 48));
6c9d22e2
PG
13493 vty_out(vty, "%30s: %s\n",
13494 "/48 equivalent %s\n",
13495 temp_buf);
9ab0cf58
PG
13496 } else {
13497 json_object_double_add(
13498 json, "/48equivalent",
13499 (double)(ts.total_space
13500 * pow(2.0,
13501 -128 + 48)));
13502 }
8d0ab76d 13503 } else {
6c9d22e2
PG
13504 if (!json) {
13505 snprintf(temp_buf, sizeof(temp_buf),
13506 "%12.2f",
9ab0cf58
PG
13507 ts.total_space * 100.
13508 * pow(2.0, -32));
6c9d22e2 13509 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13510 "% announced ", temp_buf);
13511 } else {
13512 json_object_double_add(
13513 json, "%announced",
13514 (double)(ts.total_space * 100.
13515 * pow(2.0, -32)));
13516 }
6c9d22e2
PG
13517 if (!json) {
13518 snprintf(temp_buf, sizeof(temp_buf),
13519 "%12.2f",
9ab0cf58
PG
13520 ts.total_space
13521 * pow(2.0, -32 + 8));
6c9d22e2
PG
13522 vty_out(vty, "%30s: %s\n",
13523 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13524 } else {
13525 json_object_double_add(
13526 json, "/8equivalent",
13527 (double)(ts.total_space
13528 * pow(2.0, -32 + 8)));
13529 }
6c9d22e2
PG
13530 if (!json) {
13531 snprintf(temp_buf, sizeof(temp_buf),
13532 "%12.2f",
9ab0cf58
PG
13533 ts.total_space
13534 * pow(2.0, -32 + 24));
6c9d22e2 13535 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13536 "/24 equivalent ", temp_buf);
13537 } else {
13538 json_object_double_add(
13539 json, "/24equivalent",
13540 (double)(ts.total_space
13541 * pow(2.0, -32 + 24)));
13542 }
8d0ab76d 13543 }
d62a17ae 13544 break;
13545 default:
6c9d22e2
PG
13546 if (!json) {
13547 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13548 ts.counts[i]);
893cccd0 13549 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13550 table_stats_strs[i]
13551 [TABLE_STATS_IDX_VTY],
13552 temp_buf);
13553 } else {
13554 json_object_int_add(
13555 json,
13556 table_stats_strs[i]
13557 [TABLE_STATS_IDX_JSON],
13558 ts.counts[i]);
13559 }
d62a17ae 13560 }
893cccd0
PG
13561 if (!json)
13562 vty_out(vty, "\n");
d62a17ae 13563 }
0747643e
AQ
13564
13565 switch (afi) {
13566 case AFI_IP:
13567 bitlen = IPV4_MAX_BITLEN;
13568 break;
13569 case AFI_IP6:
13570 bitlen = IPV6_MAX_BITLEN;
13571 break;
13572 case AFI_L2VPN:
13573 bitlen = EVPN_ROUTE_PREFIXLEN;
13574 break;
13575 default:
13576 break;
13577 }
13578
13579 if (json) {
13580 json_bitlen = json_object_new_array();
13581
13582 for (i = 0; i <= bitlen; i++) {
13583 struct json_object *ind_bit = json_object_new_object();
13584
13585 if (!ts.prefix_len_count[i])
13586 continue;
13587
13588 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13589 json_object_int_add(ind_bit, temp_buf,
13590 ts.prefix_len_count[i]);
13591 json_object_array_add(json_bitlen, ind_bit);
13592 }
13593 json_object_object_add(json, "prefixLength", json_bitlen);
13594 }
13595
9ab0cf58 13596end_table_stats:
6c9d22e2
PG
13597 if (json)
13598 json_object_array_add(json_array, json);
893cccd0 13599 return ret;
d62a17ae 13600}
13601
71f1613a
DA
13602static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13603 safi_t safi, struct json_object *json_array)
13604{
13605 if (!bgp) {
13606 bgp_table_stats_all(vty, afi, safi, json_array);
13607 return CMD_SUCCESS;
13608 }
13609
13610 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13611}
13612
d62a17ae 13613enum bgp_pcounts {
13614 PCOUNT_ADJ_IN = 0,
13615 PCOUNT_DAMPED,
13616 PCOUNT_REMOVED,
13617 PCOUNT_HISTORY,
13618 PCOUNT_STALE,
13619 PCOUNT_VALID,
13620 PCOUNT_ALL,
13621 PCOUNT_COUNTED,
7e3d9632 13622 PCOUNT_BPATH_SELECTED,
d62a17ae 13623 PCOUNT_PFCNT, /* the figure we display to users */
13624 PCOUNT_MAX,
a636c635 13625};
718e3744 13626
2b64873d 13627static const char *const pcount_strs[] = {
9d303b37
DL
13628 [PCOUNT_ADJ_IN] = "Adj-in",
13629 [PCOUNT_DAMPED] = "Damped",
13630 [PCOUNT_REMOVED] = "Removed",
13631 [PCOUNT_HISTORY] = "History",
13632 [PCOUNT_STALE] = "Stale",
13633 [PCOUNT_VALID] = "Valid",
13634 [PCOUNT_ALL] = "All RIB",
13635 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13636 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13637 [PCOUNT_PFCNT] = "Useable",
13638 [PCOUNT_MAX] = NULL,
a636c635 13639};
718e3744 13640
d62a17ae 13641struct peer_pcounts {
13642 unsigned int count[PCOUNT_MAX];
13643 const struct peer *peer;
13644 const struct bgp_table *table;
54317cba 13645 safi_t safi;
a636c635 13646};
47fc97cc 13647
9bcb3eef 13648static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13649{
54317cba
JW
13650 const struct bgp_adj_in *ain;
13651 const struct bgp_path_info *pi;
d62a17ae 13652 const struct peer *peer = pc->peer;
13653
54317cba
JW
13654 for (ain = rn->adj_in; ain; ain = ain->next)
13655 if (ain->peer == peer)
13656 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13657
9bcb3eef 13658 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13659
54317cba
JW
13660 if (pi->peer != peer)
13661 continue;
d62a17ae 13662
54317cba 13663 pc->count[PCOUNT_ALL]++;
d62a17ae 13664
54317cba
JW
13665 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13666 pc->count[PCOUNT_DAMPED]++;
13667 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13668 pc->count[PCOUNT_HISTORY]++;
13669 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13670 pc->count[PCOUNT_REMOVED]++;
13671 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13672 pc->count[PCOUNT_STALE]++;
13673 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13674 pc->count[PCOUNT_VALID]++;
13675 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13676 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13677 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13678 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13679
13680 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13681 pc->count[PCOUNT_COUNTED]++;
13682 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13683 flog_err(
13684 EC_LIB_DEVELOPMENT,
13685 "Attempting to count but flags say it is unusable");
13686 } else {
40381db7 13687 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13688 flog_err(
13689 EC_LIB_DEVELOPMENT,
13690 "Not counted but flags say we should");
d62a17ae 13691 }
13692 }
54317cba
JW
13693}
13694
cc9f21da 13695static void bgp_peer_count_walker(struct thread *t)
54317cba 13696{
9bcb3eef 13697 struct bgp_dest *rn, *rm;
54317cba
JW
13698 const struct bgp_table *table;
13699 struct peer_pcounts *pc = THREAD_ARG(t);
13700
13701 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13702 || pc->safi == SAFI_EVPN) {
13703 /* Special handling for 2-level routing tables. */
13704 for (rn = bgp_table_top(pc->table); rn;
13705 rn = bgp_route_next(rn)) {
9bcb3eef 13706 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13707 if (table != NULL)
13708 for (rm = bgp_table_top(table); rm;
13709 rm = bgp_route_next(rm))
13710 bgp_peer_count_proc(rm, pc);
13711 }
13712 } else
13713 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13714 bgp_peer_count_proc(rn, pc);
718e3744 13715}
13716
d62a17ae 13717static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13718 safi_t safi, bool use_json)
856ca177 13719{
d62a17ae 13720 struct peer_pcounts pcounts = {.peer = peer};
13721 unsigned int i;
13722 json_object *json = NULL;
13723 json_object *json_loop = NULL;
856ca177 13724
d62a17ae 13725 if (use_json) {
13726 json = json_object_new_object();
13727 json_loop = json_object_new_object();
13728 }
718e3744 13729
d62a17ae 13730 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13731 || !peer->bgp->rib[afi][safi]) {
13732 if (use_json) {
13733 json_object_string_add(
13734 json, "warning",
13735 "No such neighbor or address family");
13736 vty_out(vty, "%s\n", json_object_to_json_string(json));
13737 json_object_free(json);
d5f20468 13738 json_object_free(json_loop);
d62a17ae 13739 } else
13740 vty_out(vty, "%% No such neighbor or address family\n");
13741
13742 return CMD_WARNING;
13743 }
2a71e9ce 13744
d62a17ae 13745 memset(&pcounts, 0, sizeof(pcounts));
13746 pcounts.peer = peer;
13747 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13748 pcounts.safi = safi;
d62a17ae 13749
13750 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13751 * stats for the thread-walk (i.e. ensure this can't be blamed on
13752 * on just vty_read()).
13753 */
d62a17ae 13754 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13755
13756 if (use_json) {
13757 json_object_string_add(json, "prefixCountsFor", peer->host);
13758 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13759 get_afi_safi_str(afi, safi, true));
d62a17ae 13760 json_object_int_add(json, "pfxCounter",
13761 peer->pcount[afi][safi]);
13762
13763 for (i = 0; i < PCOUNT_MAX; i++)
13764 json_object_int_add(json_loop, pcount_strs[i],
13765 pcounts.count[i]);
13766
13767 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13768
13769 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13770 json_object_string_add(json, "pfxctDriftFor",
13771 peer->host);
13772 json_object_string_add(
13773 json, "recommended",
13774 "Please report this bug, with the above command output");
13775 }
75eeda93 13776 vty_json(vty, json);
d62a17ae 13777 } else {
13778
13779 if (peer->hostname
892fedb6 13780 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13781 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13782 peer->hostname, peer->host,
5cb5f4d0 13783 get_afi_safi_str(afi, safi, false));
d62a17ae 13784 } else {
13785 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13786 get_afi_safi_str(afi, safi, false));
d62a17ae 13787 }
13788
6cde4b45 13789 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13790 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13791
13792 for (i = 0; i < PCOUNT_MAX; i++)
13793 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13794 pcounts.count[i]);
13795
13796 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13797 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13798 vty_out(vty,
13799 "Please report this bug, with the above command output\n");
13800 }
13801 }
13802
13803 return CMD_SUCCESS;
718e3744 13804}
13805
a636c635
DW
13806DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13807 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13808 "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 13809 SHOW_STR
13810 IP_STR
13811 BGP_STR
8386ac43 13812 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13813 BGP_AFI_HELP_STR
13814 BGP_SAFI_HELP_STR
0b16f239
DS
13815 "Detailed information on TCP and BGP neighbor connections\n"
13816 "Neighbor to display information about\n"
13817 "Neighbor to display information about\n"
91d37724 13818 "Neighbor on BGP configured interface\n"
a636c635 13819 "Display detailed prefix count information\n"
9973d184 13820 JSON_STR)
0b16f239 13821{
d62a17ae 13822 afi_t afi = AFI_IP6;
13823 safi_t safi = SAFI_UNICAST;
13824 struct peer *peer;
13825 int idx = 0;
13826 struct bgp *bgp = NULL;
9f049418
DS
13827 bool uj = use_json(argc, argv);
13828
13829 if (uj)
13830 argc--;
856ca177 13831
d62a17ae 13832 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13833 &bgp, uj);
d62a17ae 13834 if (!idx)
13835 return CMD_WARNING;
0b16f239 13836
d62a17ae 13837 argv_find(argv, argc, "neighbors", &idx);
13838 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13839 if (!peer)
13840 return CMD_WARNING;
bb46e94f 13841
29c8d9da 13842 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13843}
0b16f239 13844
d6902373
PG
13845#ifdef KEEP_OLD_VPN_COMMANDS
13846DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13847 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13848 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13849 SHOW_STR
13850 IP_STR
13851 BGP_STR
d6902373 13852 BGP_VPNVX_HELP_STR
91d37724 13853 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13854 "Detailed information on TCP and BGP neighbor connections\n"
13855 "Neighbor to display information about\n"
13856 "Neighbor to display information about\n"
91d37724 13857 "Neighbor on BGP configured interface\n"
a636c635 13858 "Display detailed prefix count information\n"
9973d184 13859 JSON_STR)
a636c635 13860{
d62a17ae 13861 int idx_peer = 6;
13862 struct peer *peer;
9f049418 13863 bool uj = use_json(argc, argv);
a636c635 13864
d62a17ae 13865 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13866 if (!peer)
13867 return CMD_WARNING;
13868
13869 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13870}
13871
d6902373
PG
13872DEFUN (show_ip_bgp_vpn_all_route_prefix,
13873 show_ip_bgp_vpn_all_route_prefix_cmd,
13874 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13875 SHOW_STR
13876 IP_STR
13877 BGP_STR
d6902373 13878 BGP_VPNVX_HELP_STR
91d37724
QY
13879 "Display information about all VPNv4 NLRIs\n"
13880 "Network in the BGP routing table to display\n"
3a2d747c 13881 "Network in the BGP routing table to display\n"
9973d184 13882 JSON_STR)
91d37724 13883{
d62a17ae 13884 int idx = 0;
13885 char *network = NULL;
13886 struct bgp *bgp = bgp_get_default();
13887 if (!bgp) {
13888 vty_out(vty, "Can't find default instance\n");
13889 return CMD_WARNING;
13890 }
87e34b58 13891
d62a17ae 13892 if (argv_find(argv, argc, "A.B.C.D", &idx))
13893 network = argv[idx]->arg;
13894 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13895 network = argv[idx]->arg;
13896 else {
13897 vty_out(vty, "Unable to figure out Network\n");
13898 return CMD_WARNING;
13899 }
87e34b58 13900
d62a17ae 13901 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13902 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13903 use_json(argc, argv));
91d37724 13904}
d6902373 13905#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13906
44c69747
LK
13907DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13908 show_bgp_l2vpn_evpn_route_prefix_cmd,
13909 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13910 SHOW_STR
4c63a661
PG
13911 BGP_STR
13912 L2VPN_HELP_STR
13913 EVPN_HELP_STR
44c69747
LK
13914 "Network in the BGP routing table to display\n"
13915 "Network in the BGP routing table to display\n"
4c63a661
PG
13916 "Network in the BGP routing table to display\n"
13917 "Network in the BGP routing table to display\n"
13918 JSON_STR)
13919{
d62a17ae 13920 int idx = 0;
13921 char *network = NULL;
44c69747 13922 int prefix_check = 0;
a636c635 13923
44c69747
LK
13924 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13925 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13926 network = argv[idx]->arg;
44c69747 13927 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13928 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13929 network = argv[idx]->arg;
44c69747
LK
13930 prefix_check = 1;
13931 } else {
d62a17ae 13932 vty_out(vty, "Unable to figure out Network\n");
13933 return CMD_WARNING;
13934 }
44c69747
LK
13935 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13936 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13937 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13938}
13939
114fc229 13940static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13941 struct bgp_table *table, int *header1,
13942 int *header2, json_object *json,
13943 json_object *json_scode,
13944 json_object *json_ocode, bool wide)
13945{
13946 uint64_t version = table ? table->version : 0;
13947
13948 if (*header1) {
13949 if (json) {
13950 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13951 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13952 "%pI4", &peer->bgp->router_id);
2f9bc755 13953 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13954 peer->bgp->default_local_pref);
13955 json_object_int_add(json, "localAS",
13956 peer->change_local_as
13957 ? peer->change_local_as
13958 : peer->local_as);
2f9bc755
DS
13959 json_object_object_add(json, "bgpStatusCodes",
13960 json_scode);
13961 json_object_object_add(json, "bgpOriginCodes",
13962 json_ocode);
13963 } else {
13964 vty_out(vty,
23d0a753
DA
13965 "BGP table version is %" PRIu64
13966 ", local router ID is %pI4, vrf id ",
114fc229
DA
13967 version, &peer->bgp->router_id);
13968 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13969 vty_out(vty, "%s", VRFID_NONE_STR);
13970 else
114fc229 13971 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13972 vty_out(vty, "\n");
13973 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13974 peer->bgp->default_local_pref);
13975 vty_out(vty, "local AS %u\n",
13976 peer->change_local_as ? peer->change_local_as
13977 : peer->local_as);
2f9bc755
DS
13978 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13979 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13980 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13981 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13982 }
13983 *header1 = 0;
13984 }
13985 if (*header2) {
13986 if (!json)
13987 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13988 : BGP_SHOW_HEADER));
13989 *header2 = 0;
13990 }
13991}
13992
d9478df0
TA
13993static void
13994show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13995 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13996 const char *rmap_name, json_object *json, json_object *json_ar,
13997 json_object *json_scode, json_object *json_ocode,
96c81f66 13998 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13999 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 14000{
d62a17ae 14001 struct bgp_adj_in *ain;
14002 struct bgp_adj_out *adj;
9bcb3eef 14003 struct bgp_dest *dest;
d62a17ae 14004 struct bgp *bgp;
d62a17ae 14005 struct attr attr;
14006 int ret;
14007 struct update_subgroup *subgrp;
d62a17ae 14008 struct peer_af *paf;
f99def61 14009 bool route_filtered;
96f3485c
MK
14010 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14011 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14012 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14013 || (safi == SAFI_EVPN))
14014 ? true
14015 : false;
a636c635 14016
d62a17ae 14017 bgp = peer->bgp;
a636c635 14018
d62a17ae 14019 subgrp = peer_subgroup(peer, afi, safi);
14020
6392aaa6 14021 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14022 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14023 if (use_json) {
14024 json_object_int_add(json, "bgpTableVersion",
14025 table->version);
c949c771
DA
14026 json_object_string_addf(json, "bgpLocalRouterId",
14027 "%pI4", &bgp->router_id);
01eced22
AD
14028 json_object_int_add(json, "defaultLocPrf",
14029 bgp->default_local_pref);
114fc229
DA
14030 json_object_int_add(json, "localAS",
14031 peer->change_local_as
14032 ? peer->change_local_as
14033 : peer->local_as);
d62a17ae 14034 json_object_object_add(json, "bgpStatusCodes",
14035 json_scode);
14036 json_object_object_add(json, "bgpOriginCodes",
14037 json_ocode);
07d0c4ed
DA
14038 json_object_string_add(
14039 json, "bgpOriginatingDefaultNetwork",
14040 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14041 } else {
23d0a753
DA
14042 vty_out(vty,
14043 "BGP table version is %" PRIu64
14044 ", local router ID is %pI4, vrf id ",
14045 table->version, &bgp->router_id);
9df8b37c
PZ
14046 if (bgp->vrf_id == VRF_UNKNOWN)
14047 vty_out(vty, "%s", VRFID_NONE_STR);
14048 else
14049 vty_out(vty, "%u", bgp->vrf_id);
14050 vty_out(vty, "\n");
01eced22
AD
14051 vty_out(vty, "Default local pref %u, ",
14052 bgp->default_local_pref);
114fc229
DA
14053 vty_out(vty, "local AS %u\n",
14054 peer->change_local_as ? peer->change_local_as
14055 : peer->local_as);
d62a17ae 14056 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 14057 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 14058 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14059 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 14060
07d0c4ed
DA
14061 vty_out(vty, "Originating default network %s\n\n",
14062 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14063 }
d9478df0 14064 *header1 = 0;
d62a17ae 14065 }
a636c635 14066
9bcb3eef 14067 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14068 if (type == bgp_show_adj_route_received
14069 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14070 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14071 if (ain->peer != peer)
ea47320b 14072 continue;
6392aaa6 14073
114fc229 14074 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
14075 header2, json, json_scode,
14076 json_ocode, wide);
14077
14078 if ((safi == SAFI_MPLS_VPN)
14079 || (safi == SAFI_ENCAP)
14080 || (safi == SAFI_EVPN)) {
14081 if (use_json)
14082 json_object_string_add(
14083 json_ar, "rd", rd_str);
14084 else if (show_rd && rd_str) {
14085 vty_out(vty,
14086 "Route Distinguisher: %s\n",
14087 rd_str);
14088 show_rd = false;
14089 }
14090 }
6392aaa6 14091
6f4f49b2 14092 attr = *ain->attr;
f99def61
AD
14093 route_filtered = false;
14094
14095 /* Filter prefix using distribute list,
14096 * filter list or prefix list
14097 */
b54892e0 14098 const struct prefix *rn_p =
9bcb3eef 14099 bgp_dest_get_prefix(dest);
b54892e0
DS
14100 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14101 safi))
14102 == FILTER_DENY)
f99def61
AD
14103 route_filtered = true;
14104
14105 /* Filter prefix using route-map */
b54892e0
DS
14106 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14107 safi, rmap_name, NULL,
14108 0, NULL);
6392aaa6 14109
13c8e163
AD
14110 if (type == bgp_show_adj_route_filtered &&
14111 !route_filtered && ret != RMAP_DENY) {
d498917e 14112 bgp_attr_flush(&attr);
6392aaa6 14113 continue;
d62a17ae 14114 }
6392aaa6 14115
d9478df0
TA
14116 if (type == bgp_show_adj_route_received
14117 && (route_filtered || ret == RMAP_DENY))
14118 (*filtered_count)++;
6392aaa6 14119
7d3cae70 14120 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 14121 use_json, json_ar, wide);
d498917e 14122 bgp_attr_flush(&attr);
d9478df0 14123 (*output_count)++;
d62a17ae 14124 }
6392aaa6 14125 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14126 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14127 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14128 if (paf->peer != peer || !adj->attr)
924c3f6a 14129 continue;
d62a17ae 14130
114fc229 14131 show_adj_route_header(vty, peer, table,
d9478df0
TA
14132 header1, header2,
14133 json, json_scode,
14134 json_ocode, wide);
d62a17ae 14135
b54892e0 14136 const struct prefix *rn_p =
9bcb3eef 14137 bgp_dest_get_prefix(dest);
b54892e0 14138
6f4f49b2 14139 attr = *adj->attr;
b755861b 14140 ret = bgp_output_modifier(
b54892e0 14141 peer, rn_p, &attr, afi, safi,
b755861b 14142 rmap_name);
f46d8e1e 14143
b755861b 14144 if (ret != RMAP_DENY) {
d9478df0
TA
14145 if ((safi == SAFI_MPLS_VPN)
14146 || (safi == SAFI_ENCAP)
14147 || (safi == SAFI_EVPN)) {
14148 if (use_json)
14149 json_object_string_add(
14150 json_ar,
14151 "rd",
14152 rd_str);
14153 else if (show_rd
14154 && rd_str) {
14155 vty_out(vty,
14156 "Route Distinguisher: %s\n",
14157 rd_str);
14158 show_rd = false;
14159 }
14160 }
b54892e0 14161 route_vty_out_tmp(
7d3cae70
DA
14162 vty, dest, rn_p, &attr,
14163 safi, use_json, json_ar,
ae248832 14164 wide);
d9478df0 14165 (*output_count)++;
b755861b 14166 } else {
d9478df0 14167 (*filtered_count)++;
a2addae8 14168 }
b755861b 14169
d498917e 14170 bgp_attr_flush(&attr);
924c3f6a 14171 }
f20ce998
DS
14172 } else if (type == bgp_show_adj_route_bestpath) {
14173 struct bgp_path_info *pi;
14174
114fc229
DA
14175 show_adj_route_header(vty, peer, table, header1,
14176 header2, json, json_scode,
14177 json_ocode, wide);
f20ce998
DS
14178
14179 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14180 pi = pi->next) {
14181 if (pi->peer != peer)
14182 continue;
14183
14184 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14185 continue;
14186
7d3cae70 14187 route_vty_out_tmp(vty, dest,
f20ce998
DS
14188 bgp_dest_get_prefix(dest),
14189 pi->attr, safi, use_json,
14190 json_ar, wide);
d9478df0 14191 (*output_count)++;
f20ce998 14192 }
d62a17ae 14193 }
14194 }
a636c635 14195}
2a71e9ce 14196
d62a17ae 14197static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14198 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14199 const char *rmap_name, uint16_t show_flags)
0b16f239 14200{
d9478df0
TA
14201 struct bgp *bgp;
14202 struct bgp_table *table;
d62a17ae 14203 json_object *json = NULL;
d9478df0
TA
14204 json_object *json_scode = NULL;
14205 json_object *json_ocode = NULL;
14206 json_object *json_ar = NULL;
96f3485c 14207 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14208
d9478df0
TA
14209 /* Init BGP headers here so they're only displayed once
14210 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14211 */
14212 int header1 = 1;
14213 int header2 = 1;
14214
14215 /*
14216 * Initialize variables for each RD
14217 * All prefixes under an RD is aggregated within "json_routes"
14218 */
14219 char rd_str[BUFSIZ] = {0};
14220 json_object *json_routes = NULL;
14221
14222
14223 /* For 2-tier tables, prefix counts need to be
14224 * maintained across multiple runs of show_adj_route()
14225 */
14226 unsigned long output_count_per_rd;
14227 unsigned long filtered_count_per_rd;
14228 unsigned long output_count = 0;
14229 unsigned long filtered_count = 0;
14230
14231 if (use_json) {
d62a17ae 14232 json = json_object_new_object();
d9478df0
TA
14233 json_ar = json_object_new_object();
14234 json_scode = json_object_new_object();
14235 json_ocode = json_object_new_object();
14236
14237 json_object_string_add(json_scode, "suppressed", "s");
14238 json_object_string_add(json_scode, "damped", "d");
14239 json_object_string_add(json_scode, "history", "h");
14240 json_object_string_add(json_scode, "valid", "*");
14241 json_object_string_add(json_scode, "best", ">");
14242 json_object_string_add(json_scode, "multipath", "=");
14243 json_object_string_add(json_scode, "internal", "i");
14244 json_object_string_add(json_scode, "ribFailure", "r");
14245 json_object_string_add(json_scode, "stale", "S");
14246 json_object_string_add(json_scode, "removed", "R");
14247
14248 json_object_string_add(json_ocode, "igp", "i");
14249 json_object_string_add(json_ocode, "egp", "e");
14250 json_object_string_add(json_ocode, "incomplete", "?");
14251 }
0b16f239 14252
d62a17ae 14253 if (!peer || !peer->afc[afi][safi]) {
14254 if (use_json) {
14255 json_object_string_add(
14256 json, "warning",
14257 "No such neighbor or address family");
14258 vty_out(vty, "%s\n", json_object_to_json_string(json));
14259 json_object_free(json);
690c3134
MW
14260 json_object_free(json_ar);
14261 json_object_free(json_scode);
14262 json_object_free(json_ocode);
d62a17ae 14263 } else
14264 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14265
d62a17ae 14266 return CMD_WARNING;
14267 }
14268
6392aaa6
PM
14269 if ((type == bgp_show_adj_route_received
14270 || type == bgp_show_adj_route_filtered)
d62a17ae 14271 && !CHECK_FLAG(peer->af_flags[afi][safi],
14272 PEER_FLAG_SOFT_RECONFIG)) {
14273 if (use_json) {
14274 json_object_string_add(
14275 json, "warning",
14276 "Inbound soft reconfiguration not enabled");
14277 vty_out(vty, "%s\n", json_object_to_json_string(json));
14278 json_object_free(json);
690c3134
MW
14279 json_object_free(json_ar);
14280 json_object_free(json_scode);
14281 json_object_free(json_ocode);
d62a17ae 14282 } else
14283 vty_out(vty,
14284 "%% Inbound soft reconfiguration not enabled\n");
14285
14286 return CMD_WARNING;
14287 }
0b16f239 14288
d9478df0
TA
14289 bgp = peer->bgp;
14290
14291 /* labeled-unicast routes live in the unicast table */
14292 if (safi == SAFI_LABELED_UNICAST)
14293 table = bgp->rib[afi][SAFI_UNICAST];
14294 else
14295 table = bgp->rib[afi][safi];
14296
14297 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14298 || (safi == SAFI_EVPN)) {
14299
14300 struct bgp_dest *dest;
14301
14302 for (dest = bgp_table_top(table); dest;
14303 dest = bgp_route_next(dest)) {
14304 table = bgp_dest_get_bgp_table_info(dest);
14305 if (!table)
14306 continue;
14307
14308 output_count_per_rd = 0;
14309 filtered_count_per_rd = 0;
14310
14311 if (use_json)
14312 json_routes = json_object_new_object();
14313
14314 const struct prefix_rd *prd;
14315 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14316 dest);
14317
14318 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14319
14320 show_adj_route(vty, peer, table, afi, safi, type,
14321 rmap_name, json, json_routes, json_scode,
14322 json_ocode, show_flags, &header1,
14323 &header2, rd_str, &output_count_per_rd,
14324 &filtered_count_per_rd);
14325
14326 /* Don't include an empty RD in the output! */
14327 if (json_routes && (output_count_per_rd > 0))
14328 json_object_object_add(json_ar, rd_str,
14329 json_routes);
14330
14331 output_count += output_count_per_rd;
14332 filtered_count += filtered_count_per_rd;
14333 }
14334 } else
14335 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14336 json, json_ar, json_scode, json_ocode,
14337 show_flags, &header1, &header2, rd_str,
14338 &output_count, &filtered_count);
14339
14340 if (use_json) {
c1984955
TA
14341 if (type == bgp_show_adj_route_advertised)
14342 json_object_object_add(json, "advertisedRoutes",
14343 json_ar);
14344 else
14345 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14346 json_object_int_add(json, "totalPrefixCounter", output_count);
14347 json_object_int_add(json, "filteredPrefixCounter",
14348 filtered_count);
14349
690c3134
MW
14350 /*
14351 * These fields only give up ownership to `json` when `header1`
14352 * is used (set to zero). See code in `show_adj_route` and
14353 * `show_adj_route_header`.
14354 */
14355 if (header1 == 1) {
d9478df0
TA
14356 json_object_free(json_scode);
14357 json_object_free(json_ocode);
14358 }
14359
75eeda93 14360 vty_json(vty, json);
d9478df0
TA
14361 } else if (output_count > 0) {
14362 if (filtered_count > 0)
14363 vty_out(vty,
14364 "\nTotal number of prefixes %ld (%ld filtered)\n",
14365 output_count, filtered_count);
14366 else
14367 vty_out(vty, "\nTotal number of prefixes %ld\n",
14368 output_count);
14369 }
0b16f239 14370
d62a17ae 14371 return CMD_SUCCESS;
a636c635 14372}
50ef26d4 14373
f20ce998
DS
14374DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14375 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14376 "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]",
14377 SHOW_STR
14378 IP_STR
14379 BGP_STR
14380 BGP_INSTANCE_HELP_STR
14381 BGP_AFI_HELP_STR
14382 BGP_SAFI_WITH_LABEL_HELP_STR
14383 "Detailed information on TCP and BGP neighbor connections\n"
14384 "Neighbor to display information about\n"
14385 "Neighbor to display information about\n"
14386 "Neighbor on BGP configured interface\n"
14387 "Display the routes selected by best path\n"
14388 JSON_STR
14389 "Increase table width for longer prefixes\n")
14390{
14391 afi_t afi = AFI_IP6;
14392 safi_t safi = SAFI_UNICAST;
14393 char *rmap_name = NULL;
14394 char *peerstr = NULL;
14395 struct bgp *bgp = NULL;
14396 struct peer *peer;
14397 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14398 int idx = 0;
96c81f66 14399 uint16_t show_flags = 0;
96f3485c
MK
14400
14401 if (uj)
14402 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14403
14404 if (wide)
14405 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14406
14407 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14408 &bgp, uj);
14409
14410 if (!idx)
14411 return CMD_WARNING;
14412
14413 argv_find(argv, argc, "neighbors", &idx);
14414 peerstr = argv[++idx]->arg;
14415
14416 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14417 if (!peer)
14418 return CMD_WARNING;
14419
96f3485c
MK
14420 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14421 show_flags);
f20ce998
DS
14422}
14423
ae248832 14424DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14425 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14426 "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] [json$uj | wide$wide]",
718e3744 14427 SHOW_STR
14428 IP_STR
14429 BGP_STR
a636c635 14430 BGP_INSTANCE_HELP_STR
7395a2c9 14431 BGP_AFI_HELP_STR
4dd6177e 14432 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14433 "Display the entries for all address families\n"
718e3744 14434 "Detailed information on TCP and BGP neighbor connections\n"
14435 "Neighbor to display information about\n"
14436 "Neighbor to display information about\n"
91d37724 14437 "Neighbor on BGP configured interface\n"
a636c635 14438 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14439 "Display the received routes from neighbor\n"
14440 "Display the filtered routes received from neighbor\n"
a636c635
DW
14441 "Route-map to modify the attributes\n"
14442 "Name of the route map\n"
ae248832
MK
14443 JSON_STR
14444 "Increase table width for longer prefixes\n")
718e3744 14445{
d62a17ae 14446 afi_t afi = AFI_IP6;
14447 safi_t safi = SAFI_UNICAST;
d62a17ae 14448 char *peerstr = NULL;
d62a17ae 14449 struct bgp *bgp = NULL;
14450 struct peer *peer;
6392aaa6 14451 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14452 int idx = 0;
96f3485c 14453 bool first = true;
96c81f66 14454 uint16_t show_flags = 0;
75ce3b14
DA
14455 struct listnode *node;
14456 struct bgp *abgp;
6392aaa6 14457
96f3485c 14458 if (uj) {
d62a17ae 14459 argc--;
96f3485c
MK
14460 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14461 }
14462
14463 if (all) {
14464 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14465 if (argv_find(argv, argc, "ipv4", &idx))
14466 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14467
14468 if (argv_find(argv, argc, "ipv6", &idx))
14469 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14470 }
14471
14472 if (wide)
14473 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14474
9f049418
DS
14475 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14476 &bgp, uj);
14477 if (!idx)
14478 return CMD_WARNING;
14479
d62a17ae 14480 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14481 argv_find(argv, argc, "neighbors", &idx);
14482 peerstr = argv[++idx]->arg;
8c3deaae 14483
d62a17ae 14484 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14485 if (!peer)
14486 return CMD_WARNING;
856ca177 14487
d62a17ae 14488 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14489 type = bgp_show_adj_route_advertised;
14490 else if (argv_find(argv, argc, "received-routes", &idx))
14491 type = bgp_show_adj_route_received;
14492 else if (argv_find(argv, argc, "filtered-routes", &idx))
14493 type = bgp_show_adj_route_filtered;
14494
96f3485c 14495 if (!all)
70dd370f 14496 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14497 show_flags);
14498 if (uj)
14499 vty_out(vty, "{\n");
14500
14501 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14502 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14503 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14504 : AFI_IP6;
75ce3b14
DA
14505 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14506 FOREACH_SAFI (safi) {
14507 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14508 continue;
96f3485c 14509
75ce3b14
DA
14510 if (uj) {
14511 if (first)
14512 first = false;
14513 else
14514 vty_out(vty, ",\n");
14515 vty_out(vty, "\"%s\":",
14516 get_afi_safi_str(afi, safi,
14517 true));
14518 } else
14519 vty_out(vty,
14520 "\nFor address family: %s\n",
14521 get_afi_safi_str(afi, safi,
14522 false));
96f3485c 14523
75ce3b14 14524 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14525 route_map, show_flags);
75ce3b14 14526 }
96f3485c
MK
14527 }
14528 } else {
75ce3b14
DA
14529 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14530 FOREACH_AFI_SAFI (afi, safi) {
14531 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14532 continue;
96f3485c 14533
75ce3b14
DA
14534 if (uj) {
14535 if (first)
14536 first = false;
14537 else
14538 vty_out(vty, ",\n");
14539 vty_out(vty, "\"%s\":",
14540 get_afi_safi_str(afi, safi,
14541 true));
14542 } else
14543 vty_out(vty,
14544 "\nFor address family: %s\n",
14545 get_afi_safi_str(afi, safi,
14546 false));
96f3485c 14547
75ce3b14 14548 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14549 route_map, show_flags);
75ce3b14 14550 }
96f3485c
MK
14551 }
14552 }
14553 if (uj)
14554 vty_out(vty, "}\n");
14555
14556 return CMD_SUCCESS;
95cbbd2a
ML
14557}
14558
718e3744 14559DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14560 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14561 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14562 SHOW_STR
14563 IP_STR
14564 BGP_STR
d3120452 14565 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14566 BGP_AF_STR
14567 BGP_AF_STR
14568 BGP_AF_MODIFIER_STR
718e3744 14569 "Detailed information on TCP and BGP neighbor connections\n"
14570 "Neighbor to display information about\n"
14571 "Neighbor to display information about\n"
91d37724 14572 "Neighbor on BGP configured interface\n"
718e3744 14573 "Display information received from a BGP neighbor\n"
856ca177 14574 "Display the prefixlist filter\n"
9973d184 14575 JSON_STR)
718e3744 14576{
d62a17ae 14577 afi_t afi = AFI_IP6;
14578 safi_t safi = SAFI_UNICAST;
14579 char *peerstr = NULL;
d62a17ae 14580 char name[BUFSIZ];
d62a17ae 14581 struct peer *peer;
d3120452 14582 int count;
d62a17ae 14583 int idx = 0;
d3120452
IR
14584 struct bgp *bgp = NULL;
14585 bool uj = use_json(argc, argv);
14586
14587 if (uj)
14588 argc--;
14589
14590 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14591 &bgp, uj);
14592 if (!idx)
14593 return CMD_WARNING;
d62a17ae 14594
d62a17ae 14595 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14596 argv_find(argv, argc, "neighbors", &idx);
14597 peerstr = argv[++idx]->arg;
14598
d3120452
IR
14599 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14600 if (!peer)
14601 return CMD_WARNING;
718e3744 14602
4ced1a2c 14603 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14604 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14605 if (count) {
14606 if (!uj)
14607 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14608 get_afi_safi_str(afi, safi, false));
d62a17ae 14609 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14610 } else {
14611 if (uj)
14612 vty_out(vty, "{}\n");
14613 else
14614 vty_out(vty, "No functional output\n");
14615 }
718e3744 14616
d62a17ae 14617 return CMD_SUCCESS;
14618}
14619
14620static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14621 afi_t afi, safi_t safi,
9f049418 14622 enum bgp_show_type type, bool use_json)
d62a17ae 14623{
96c81f66 14624 uint16_t show_flags = 0;
96f3485c
MK
14625
14626 if (use_json)
14627 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14628
d62a17ae 14629 if (!peer || !peer->afc[afi][safi]) {
14630 if (use_json) {
14631 json_object *json_no = NULL;
14632 json_no = json_object_new_object();
14633 json_object_string_add(
14634 json_no, "warning",
14635 "No such neighbor or address family");
14636 vty_out(vty, "%s\n",
14637 json_object_to_json_string(json_no));
14638 json_object_free(json_no);
14639 } else
14640 vty_out(vty, "%% No such neighbor or address family\n");
14641 return CMD_WARNING;
14642 }
47fc97cc 14643
7daf25a3
TA
14644 /* labeled-unicast routes live in the unicast table */
14645 if (safi == SAFI_LABELED_UNICAST)
14646 safi = SAFI_UNICAST;
14647
1e2ce4f1
DS
14648 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14649 RPKI_NOT_BEING_USED);
718e3744 14650}
14651
dba3c1d3
PG
14652DEFUN (show_ip_bgp_flowspec_routes_detailed,
14653 show_ip_bgp_flowspec_routes_detailed_cmd,
14654 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14655 SHOW_STR
14656 IP_STR
14657 BGP_STR
14658 BGP_INSTANCE_HELP_STR
14659 BGP_AFI_HELP_STR
14660 "SAFI Flowspec\n"
14661 "Detailed information on flowspec entries\n"
14662 JSON_STR)
14663{
458c1475 14664 afi_t afi = AFI_IP6;
dba3c1d3
PG
14665 safi_t safi = SAFI_UNICAST;
14666 struct bgp *bgp = NULL;
14667 int idx = 0;
9f049418 14668 bool uj = use_json(argc, argv);
5be6fa9b 14669 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14670
96f3485c 14671 if (uj) {
9f049418 14672 argc--;
96f3485c
MK
14673 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14674 }
dba3c1d3
PG
14675
14676 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14677 &bgp, uj);
dba3c1d3
PG
14678 if (!idx)
14679 return CMD_WARNING;
14680
96f3485c 14681 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14682 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14683}
14684
718e3744 14685DEFUN (show_ip_bgp_neighbor_routes,
14686 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14687 "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 14688 SHOW_STR
14689 IP_STR
14690 BGP_STR
8386ac43 14691 BGP_INSTANCE_HELP_STR
4f280b15 14692 BGP_AFI_HELP_STR
4dd6177e 14693 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14694 "Detailed information on TCP and BGP neighbor connections\n"
14695 "Neighbor to display information about\n"
14696 "Neighbor to display information about\n"
91d37724 14697 "Neighbor on BGP configured interface\n"
2525cf39 14698 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14699 "Display the dampened routes received from neighbor\n"
14700 "Display routes learned from neighbor\n"
9973d184 14701 JSON_STR)
718e3744 14702{
d62a17ae 14703 char *peerstr = NULL;
14704 struct bgp *bgp = NULL;
14705 afi_t afi = AFI_IP6;
14706 safi_t safi = SAFI_UNICAST;
14707 struct peer *peer;
14708 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14709 int idx = 0;
9f049418
DS
14710 bool uj = use_json(argc, argv);
14711
14712 if (uj)
14713 argc--;
bb46e94f 14714
d62a17ae 14715 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14716 &bgp, uj);
d62a17ae 14717 if (!idx)
14718 return CMD_WARNING;
c493f2d8 14719
d62a17ae 14720 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14721 argv_find(argv, argc, "neighbors", &idx);
14722 peerstr = argv[++idx]->arg;
8c3deaae 14723
d62a17ae 14724 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14725 if (!peer)
d62a17ae 14726 return CMD_WARNING;
bb46e94f 14727
d62a17ae 14728 if (argv_find(argv, argc, "flap-statistics", &idx))
14729 sh_type = bgp_show_type_flap_neighbor;
14730 else if (argv_find(argv, argc, "dampened-routes", &idx))
14731 sh_type = bgp_show_type_damp_neighbor;
14732 else if (argv_find(argv, argc, "routes", &idx))
14733 sh_type = bgp_show_type_neighbor;
2525cf39 14734
d62a17ae 14735 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14736}
6b0655a2 14737
734b349e 14738struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14739
d62a17ae 14740struct bgp_distance {
14741 /* Distance value for the IP source prefix. */
d7c0a89a 14742 uint8_t distance;
718e3744 14743
d62a17ae 14744 /* Name of the access-list to be matched. */
14745 char *access_list;
718e3744 14746};
14747
4f280b15
LB
14748DEFUN (show_bgp_afi_vpn_rd_route,
14749 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14750 "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
14751 SHOW_STR
14752 BGP_STR
14753 BGP_AFI_HELP_STR
00e6edb9 14754 BGP_AF_MODIFIER_STR
4f280b15
LB
14755 "Display information for a route distinguisher\n"
14756 "Route Distinguisher\n"
a111dd97 14757 "All Route Distinguishers\n"
7395a2c9
DS
14758 "Network in the BGP routing table to display\n"
14759 "Network in the BGP routing table to display\n"
14760 JSON_STR)
4f280b15 14761{
d62a17ae 14762 int ret;
14763 struct prefix_rd prd;
14764 afi_t afi = AFI_MAX;
14765 int idx = 0;
4f280b15 14766
ff6566f3
DS
14767 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14768 vty_out(vty, "%% Malformed Address Family\n");
14769 return CMD_WARNING;
14770 }
14771
a111dd97
TA
14772 if (!strcmp(argv[5]->arg, "all"))
14773 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14774 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14775 RPKI_NOT_BEING_USED,
14776 use_json(argc, argv));
14777
d62a17ae 14778 ret = str2prefix_rd(argv[5]->arg, &prd);
14779 if (!ret) {
14780 vty_out(vty, "%% Malformed Route Distinguisher\n");
14781 return CMD_WARNING;
14782 }
ff6566f3 14783
d62a17ae 14784 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14785 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14786 use_json(argc, argv));
4f280b15
LB
14787}
14788
d62a17ae 14789static struct bgp_distance *bgp_distance_new(void)
718e3744 14790{
d62a17ae 14791 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14792}
14793
d62a17ae 14794static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14795{
d62a17ae 14796 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14797}
14798
585f1adc
IR
14799static int bgp_distance_set(struct vty *vty, const char *distance_str,
14800 const char *ip_str, const char *access_list_str)
718e3744 14801{
d62a17ae 14802 int ret;
585f1adc
IR
14803 afi_t afi;
14804 safi_t safi;
d62a17ae 14805 struct prefix p;
585f1adc 14806 uint8_t distance;
9bcb3eef 14807 struct bgp_dest *dest;
d62a17ae 14808 struct bgp_distance *bdistance;
718e3744 14809
585f1adc
IR
14810 afi = bgp_node_afi(vty);
14811 safi = bgp_node_safi(vty);
14812
d62a17ae 14813 ret = str2prefix(ip_str, &p);
14814 if (ret == 0) {
585f1adc 14815 vty_out(vty, "Malformed prefix\n");
d62a17ae 14816 return CMD_WARNING_CONFIG_FAILED;
14817 }
718e3744 14818
585f1adc
IR
14819 distance = atoi(distance_str);
14820
d62a17ae 14821 /* Get BGP distance node. */
9bcb3eef
DS
14822 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14823 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14824 if (bdistance)
9bcb3eef 14825 bgp_dest_unlock_node(dest);
ca2e160d 14826 else {
d62a17ae 14827 bdistance = bgp_distance_new();
9bcb3eef 14828 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14829 }
718e3744 14830
d62a17ae 14831 /* Set distance value. */
14832 bdistance->distance = distance;
718e3744 14833
d62a17ae 14834 /* Reset access-list configuration. */
e1b36e13 14835 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14836 if (access_list_str)
14837 bdistance->access_list =
14838 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14839
d62a17ae 14840 return CMD_SUCCESS;
718e3744 14841}
14842
585f1adc
IR
14843static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14844 const char *ip_str, const char *access_list_str)
718e3744 14845{
d62a17ae 14846 int ret;
585f1adc
IR
14847 afi_t afi;
14848 safi_t safi;
d62a17ae 14849 struct prefix p;
585f1adc 14850 int distance;
9bcb3eef 14851 struct bgp_dest *dest;
d62a17ae 14852 struct bgp_distance *bdistance;
718e3744 14853
585f1adc
IR
14854 afi = bgp_node_afi(vty);
14855 safi = bgp_node_safi(vty);
14856
d62a17ae 14857 ret = str2prefix(ip_str, &p);
14858 if (ret == 0) {
585f1adc 14859 vty_out(vty, "Malformed prefix\n");
d62a17ae 14860 return CMD_WARNING_CONFIG_FAILED;
14861 }
718e3744 14862
9bcb3eef
DS
14863 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14864 if (!dest) {
585f1adc 14865 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14866 return CMD_WARNING_CONFIG_FAILED;
14867 }
718e3744 14868
9bcb3eef 14869 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14870 distance = atoi(distance_str);
1f9a9fff 14871
d62a17ae 14872 if (bdistance->distance != distance) {
585f1adc 14873 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14874 bgp_dest_unlock_node(dest);
d62a17ae 14875 return CMD_WARNING_CONFIG_FAILED;
14876 }
718e3744 14877
0a22ddfb 14878 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14879 bgp_distance_free(bdistance);
718e3744 14880
9bcb3eef
DS
14881 bgp_dest_set_bgp_path_info(dest, NULL);
14882 bgp_dest_unlock_node(dest);
14883 bgp_dest_unlock_node(dest);
718e3744 14884
d62a17ae 14885 return CMD_SUCCESS;
718e3744 14886}
14887
718e3744 14888/* Apply BGP information to distance method. */
b8685f9b 14889uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14890 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14891{
9bcb3eef 14892 struct bgp_dest *dest;
801bb996 14893 struct prefix q = {0};
d62a17ae 14894 struct peer *peer;
14895 struct bgp_distance *bdistance;
14896 struct access_list *alist;
14897 struct bgp_static *bgp_static;
14898
14899 if (!bgp)
14900 return 0;
14901
40381db7 14902 peer = pinfo->peer;
d62a17ae 14903
7b7d48e5
DS
14904 if (pinfo->attr->distance)
14905 return pinfo->attr->distance;
14906
801bb996
CS
14907 /* Check source address.
14908 * Note: for aggregate route, peer can have unspec af type.
14909 */
14910 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14911 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14912 return 0;
14913
9bcb3eef
DS
14914 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14915 if (dest) {
14916 bdistance = bgp_dest_get_bgp_distance_info(dest);
14917 bgp_dest_unlock_node(dest);
d62a17ae 14918
14919 if (bdistance->access_list) {
14920 alist = access_list_lookup(afi, bdistance->access_list);
14921 if (alist
14922 && access_list_apply(alist, p) == FILTER_PERMIT)
14923 return bdistance->distance;
14924 } else
14925 return bdistance->distance;
718e3744 14926 }
718e3744 14927
d62a17ae 14928 /* Backdoor check. */
9bcb3eef
DS
14929 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14930 if (dest) {
14931 bgp_static = bgp_dest_get_bgp_static_info(dest);
14932 bgp_dest_unlock_node(dest);
718e3744 14933
d62a17ae 14934 if (bgp_static->backdoor) {
14935 if (bgp->distance_local[afi][safi])
14936 return bgp->distance_local[afi][safi];
14937 else
14938 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14939 }
718e3744 14940 }
718e3744 14941
d62a17ae 14942 if (peer->sort == BGP_PEER_EBGP) {
14943 if (bgp->distance_ebgp[afi][safi])
14944 return bgp->distance_ebgp[afi][safi];
14945 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14946 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14947 if (bgp->distance_ibgp[afi][safi])
14948 return bgp->distance_ibgp[afi][safi];
14949 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14950 } else {
14951 if (bgp->distance_local[afi][safi])
14952 return bgp->distance_local[afi][safi];
14953 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14954 }
718e3744 14955}
14956
a612fb77
DA
14957/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14958 * we should tell ZEBRA update the routes for a specific
14959 * AFI/SAFI to reflect changes in RIB.
14960 */
585f1adc
IR
14961static void bgp_announce_routes_distance_update(struct bgp *bgp,
14962 afi_t update_afi,
14963 safi_t update_safi)
a612fb77
DA
14964{
14965 afi_t afi;
14966 safi_t safi;
14967
14968 FOREACH_AFI_SAFI (afi, safi) {
14969 if (!bgp_fibupd_safi(safi))
14970 continue;
14971
8b54bc30
DA
14972 if (afi != update_afi && safi != update_safi)
14973 continue;
14974
14975 if (BGP_DEBUG(zebra, ZEBRA))
14976 zlog_debug(
14977 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14978 __func__, afi, safi);
14979 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14980 }
14981}
14982
585f1adc
IR
14983DEFUN (bgp_distance,
14984 bgp_distance_cmd,
14985 "distance bgp (1-255) (1-255) (1-255)",
14986 "Define an administrative distance\n"
14987 "BGP distance\n"
14988 "Distance for routes external to the AS\n"
14989 "Distance for routes internal to the AS\n"
14990 "Distance for local routes\n")
718e3744 14991{
585f1adc 14992 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14993 int idx_number = 2;
14994 int idx_number_2 = 3;
14995 int idx_number_3 = 4;
585f1adc
IR
14996 int distance_ebgp = atoi(argv[idx_number]->arg);
14997 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14998 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14999 afi_t afi;
15000 safi_t safi;
718e3744 15001
d62a17ae 15002 afi = bgp_node_afi(vty);
15003 safi = bgp_node_safi(vty);
718e3744 15004
585f1adc
IR
15005 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15006 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15007 || bgp->distance_local[afi][safi] != distance_local) {
15008 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15009 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15010 bgp->distance_local[afi][safi] = distance_local;
15011 bgp_announce_routes_distance_update(bgp, afi, safi);
15012 }
15013 return CMD_SUCCESS;
15014}
37a87b8f 15015
585f1adc
IR
15016DEFUN (no_bgp_distance,
15017 no_bgp_distance_cmd,
15018 "no distance bgp [(1-255) (1-255) (1-255)]",
15019 NO_STR
15020 "Define an administrative distance\n"
15021 "BGP distance\n"
15022 "Distance for routes external to the AS\n"
15023 "Distance for routes internal to the AS\n"
15024 "Distance for local routes\n")
718e3744 15025{
585f1adc 15026 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15027 afi_t afi;
15028 safi_t safi;
37a87b8f
CS
15029
15030 afi = bgp_node_afi(vty);
15031 safi = bgp_node_safi(vty);
15032
585f1adc
IR
15033 if (bgp->distance_ebgp[afi][safi] != 0
15034 || bgp->distance_ibgp[afi][safi] != 0
15035 || bgp->distance_local[afi][safi] != 0) {
15036 bgp->distance_ebgp[afi][safi] = 0;
15037 bgp->distance_ibgp[afi][safi] = 0;
15038 bgp->distance_local[afi][safi] = 0;
15039 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15040 }
585f1adc
IR
15041 return CMD_SUCCESS;
15042}
37a87b8f 15043
37a87b8f 15044
585f1adc
IR
15045DEFUN (bgp_distance_source,
15046 bgp_distance_source_cmd,
15047 "distance (1-255) A.B.C.D/M",
15048 "Define an administrative distance\n"
15049 "Administrative distance\n"
15050 "IP source prefix\n")
15051{
15052 int idx_number = 1;
15053 int idx_ipv4_prefixlen = 2;
15054 bgp_distance_set(vty, argv[idx_number]->arg,
15055 argv[idx_ipv4_prefixlen]->arg, NULL);
15056 return CMD_SUCCESS;
734b349e
MZ
15057}
15058
585f1adc
IR
15059DEFUN (no_bgp_distance_source,
15060 no_bgp_distance_source_cmd,
15061 "no distance (1-255) A.B.C.D/M",
15062 NO_STR
15063 "Define an administrative distance\n"
15064 "Administrative distance\n"
15065 "IP source prefix\n")
37a87b8f 15066{
585f1adc
IR
15067 int idx_number = 2;
15068 int idx_ipv4_prefixlen = 3;
15069 bgp_distance_unset(vty, argv[idx_number]->arg,
15070 argv[idx_ipv4_prefixlen]->arg, NULL);
15071 return CMD_SUCCESS;
37a87b8f
CS
15072}
15073
585f1adc
IR
15074DEFUN (bgp_distance_source_access_list,
15075 bgp_distance_source_access_list_cmd,
15076 "distance (1-255) A.B.C.D/M WORD",
15077 "Define an administrative distance\n"
15078 "Administrative distance\n"
15079 "IP source prefix\n"
15080 "Access list name\n")
37a87b8f 15081{
585f1adc
IR
15082 int idx_number = 1;
15083 int idx_ipv4_prefixlen = 2;
15084 int idx_word = 3;
15085 bgp_distance_set(vty, argv[idx_number]->arg,
15086 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15087 return CMD_SUCCESS;
15088}
718e3744 15089
585f1adc
IR
15090DEFUN (no_bgp_distance_source_access_list,
15091 no_bgp_distance_source_access_list_cmd,
15092 "no distance (1-255) A.B.C.D/M WORD",
15093 NO_STR
15094 "Define an administrative distance\n"
15095 "Administrative distance\n"
15096 "IP source prefix\n"
15097 "Access list name\n")
15098{
15099 int idx_number = 2;
15100 int idx_ipv4_prefixlen = 3;
15101 int idx_word = 4;
15102 bgp_distance_unset(vty, argv[idx_number]->arg,
15103 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15104 return CMD_SUCCESS;
15105}
37a87b8f 15106
585f1adc
IR
15107DEFUN (ipv6_bgp_distance_source,
15108 ipv6_bgp_distance_source_cmd,
15109 "distance (1-255) X:X::X:X/M",
15110 "Define an administrative distance\n"
15111 "Administrative distance\n"
15112 "IP source prefix\n")
15113{
15114 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15115 return CMD_SUCCESS;
15116}
7ebe9748 15117
585f1adc
IR
15118DEFUN (no_ipv6_bgp_distance_source,
15119 no_ipv6_bgp_distance_source_cmd,
15120 "no distance (1-255) X:X::X:X/M",
15121 NO_STR
15122 "Define an administrative distance\n"
15123 "Administrative distance\n"
15124 "IP source prefix\n")
15125{
15126 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15127 return CMD_SUCCESS;
15128}
37a87b8f 15129
585f1adc
IR
15130DEFUN (ipv6_bgp_distance_source_access_list,
15131 ipv6_bgp_distance_source_access_list_cmd,
15132 "distance (1-255) X:X::X:X/M WORD",
15133 "Define an administrative distance\n"
15134 "Administrative distance\n"
15135 "IP source prefix\n"
15136 "Access list name\n")
15137{
15138 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15139 return CMD_SUCCESS;
718e3744 15140}
15141
585f1adc
IR
15142DEFUN (no_ipv6_bgp_distance_source_access_list,
15143 no_ipv6_bgp_distance_source_access_list_cmd,
15144 "no distance (1-255) X:X::X:X/M WORD",
15145 NO_STR
15146 "Define an administrative distance\n"
15147 "Administrative distance\n"
15148 "IP source prefix\n"
15149 "Access list name\n")
718e3744 15150{
585f1adc
IR
15151 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15152 return CMD_SUCCESS;
15153}
37a87b8f 15154
585f1adc
IR
15155DEFUN (bgp_damp_set,
15156 bgp_damp_set_cmd,
a30fec23 15157 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15158 "BGP Specific commands\n"
15159 "Enable route-flap dampening\n"
15160 "Half-life time for the penalty\n"
15161 "Value to start reusing a route\n"
15162 "Value to start suppressing a route\n"
15163 "Maximum duration to suppress a stable route\n")
15164{
15165 VTY_DECLVAR_CONTEXT(bgp, bgp);
15166 int idx_half_life = 2;
15167 int idx_reuse = 3;
15168 int idx_suppress = 4;
15169 int idx_max_suppress = 5;
37a87b8f
CS
15170 int half = DEFAULT_HALF_LIFE * 60;
15171 int reuse = DEFAULT_REUSE;
15172 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15173 int max = 4 * half;
15174
15175 if (argc == 6) {
15176 half = atoi(argv[idx_half_life]->arg) * 60;
15177 reuse = atoi(argv[idx_reuse]->arg);
15178 suppress = atoi(argv[idx_suppress]->arg);
15179 max = atoi(argv[idx_max_suppress]->arg) * 60;
15180 } else if (argc == 3) {
15181 half = atoi(argv[idx_half_life]->arg) * 60;
15182 max = 4 * half;
15183 }
15184
15185 /*
15186 * These can't be 0 but our SA doesn't understand the
15187 * way our cli is constructed
15188 */
15189 assert(reuse);
15190 assert(half);
15191 if (suppress < reuse) {
15192 vty_out(vty,
15193 "Suppress value cannot be less than reuse value \n");
15194 return 0;
15195 }
15196
15197 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15198 reuse, suppress, max);
15199}
15200
15201DEFUN (bgp_damp_unset,
15202 bgp_damp_unset_cmd,
a30fec23 15203 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15204 NO_STR
15205 "BGP Specific commands\n"
15206 "Enable route-flap dampening\n"
15207 "Half-life time for the penalty\n"
15208 "Value to start reusing a route\n"
15209 "Value to start suppressing a route\n"
15210 "Maximum duration to suppress a stable route\n")
15211{
15212 VTY_DECLVAR_CONTEXT(bgp, bgp);
15213 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15214}
15215
718e3744 15216/* Display specified route of BGP table. */
d62a17ae 15217static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15218 const char *ip_str, afi_t afi, safi_t safi,
15219 struct prefix_rd *prd, int prefix_check)
15220{
15221 int ret;
15222 struct prefix match;
9bcb3eef
DS
15223 struct bgp_dest *dest;
15224 struct bgp_dest *rm;
40381db7
DS
15225 struct bgp_path_info *pi;
15226 struct bgp_path_info *pi_temp;
d62a17ae 15227 struct bgp *bgp;
15228 struct bgp_table *table;
15229
15230 /* BGP structure lookup. */
15231 if (view_name) {
15232 bgp = bgp_lookup_by_name(view_name);
15233 if (bgp == NULL) {
15234 vty_out(vty, "%% Can't find BGP instance %s\n",
15235 view_name);
15236 return CMD_WARNING;
15237 }
15238 } else {
15239 bgp = bgp_get_default();
15240 if (bgp == NULL) {
15241 vty_out(vty, "%% No BGP process is configured\n");
15242 return CMD_WARNING;
15243 }
718e3744 15244 }
718e3744 15245
d62a17ae 15246 /* Check IP address argument. */
15247 ret = str2prefix(ip_str, &match);
15248 if (!ret) {
15249 vty_out(vty, "%% address is malformed\n");
15250 return CMD_WARNING;
15251 }
718e3744 15252
d62a17ae 15253 match.family = afi2family(afi);
15254
15255 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15256 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15257 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15258 dest = bgp_route_next(dest)) {
15259 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15260
9bcb3eef 15261 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15262 continue;
9bcb3eef 15263 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15264 if (!table)
ea47320b 15265 continue;
4953391b
DA
15266 rm = bgp_node_match(table, &match);
15267 if (rm == NULL)
ea47320b 15268 continue;
d62a17ae 15269
9bcb3eef 15270 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15271
ea47320b 15272 if (!prefix_check
b54892e0 15273 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15274 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15275 while (pi) {
15276 if (pi->extra && pi->extra->damp_info) {
15277 pi_temp = pi->next;
ea47320b 15278 bgp_damp_info_free(
19971c9a 15279 pi->extra->damp_info,
5c8846f6 15280 1, afi, safi);
40381db7 15281 pi = pi_temp;
ea47320b 15282 } else
40381db7 15283 pi = pi->next;
d62a17ae 15284 }
ea47320b
DL
15285 }
15286
9bcb3eef 15287 bgp_dest_unlock_node(rm);
d62a17ae 15288 }
15289 } else {
4953391b
DA
15290 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15291 if (dest != NULL) {
9bcb3eef 15292 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15293
d62a17ae 15294 if (!prefix_check
9bcb3eef
DS
15295 || dest_p->prefixlen == match.prefixlen) {
15296 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15297 while (pi) {
15298 if (pi->extra && pi->extra->damp_info) {
15299 pi_temp = pi->next;
d62a17ae 15300 bgp_damp_info_free(
19971c9a 15301 pi->extra->damp_info,
5c8846f6 15302 1, afi, safi);
40381db7 15303 pi = pi_temp;
d62a17ae 15304 } else
40381db7 15305 pi = pi->next;
d62a17ae 15306 }
15307 }
15308
9bcb3eef 15309 bgp_dest_unlock_node(dest);
d62a17ae 15310 }
15311 }
718e3744 15312
d62a17ae 15313 return CMD_SUCCESS;
718e3744 15314}
15315
15316DEFUN (clear_ip_bgp_dampening,
15317 clear_ip_bgp_dampening_cmd,
15318 "clear ip bgp dampening",
15319 CLEAR_STR
15320 IP_STR
15321 BGP_STR
15322 "Clear route flap dampening information\n")
15323{
b4f7f45b 15324 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15325 return CMD_SUCCESS;
718e3744 15326}
15327
15328DEFUN (clear_ip_bgp_dampening_prefix,
15329 clear_ip_bgp_dampening_prefix_cmd,
15330 "clear ip bgp dampening A.B.C.D/M",
15331 CLEAR_STR
15332 IP_STR
15333 BGP_STR
15334 "Clear route flap dampening information\n"
0c7b1b01 15335 "IPv4 prefix\n")
718e3744 15336{
d62a17ae 15337 int idx_ipv4_prefixlen = 4;
15338 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15339 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15340}
15341
15342DEFUN (clear_ip_bgp_dampening_address,
15343 clear_ip_bgp_dampening_address_cmd,
15344 "clear ip bgp dampening A.B.C.D",
15345 CLEAR_STR
15346 IP_STR
15347 BGP_STR
15348 "Clear route flap dampening information\n"
15349 "Network to clear damping information\n")
15350{
d62a17ae 15351 int idx_ipv4 = 4;
15352 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15353 SAFI_UNICAST, NULL, 0);
718e3744 15354}
15355
15356DEFUN (clear_ip_bgp_dampening_address_mask,
15357 clear_ip_bgp_dampening_address_mask_cmd,
15358 "clear ip bgp dampening A.B.C.D A.B.C.D",
15359 CLEAR_STR
15360 IP_STR
15361 BGP_STR
15362 "Clear route flap dampening information\n"
15363 "Network to clear damping information\n"
15364 "Network mask\n")
15365{
d62a17ae 15366 int idx_ipv4 = 4;
15367 int idx_ipv4_2 = 5;
15368 int ret;
15369 char prefix_str[BUFSIZ];
718e3744 15370
d62a17ae 15371 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15372 prefix_str, sizeof(prefix_str));
d62a17ae 15373 if (!ret) {
15374 vty_out(vty, "%% Inconsistent address and mask\n");
15375 return CMD_WARNING;
15376 }
718e3744 15377
d62a17ae 15378 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15379 NULL, 0);
718e3744 15380}
6b0655a2 15381
e3b78da8 15382static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15383{
15384 struct vty *vty = arg;
e3b78da8 15385 struct peer *peer = bucket->data;
825d9834 15386
47e12884 15387 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15388}
15389
2a0e69ae
DS
15390DEFUN (show_bgp_listeners,
15391 show_bgp_listeners_cmd,
15392 "show bgp listeners",
15393 SHOW_STR
15394 BGP_STR
15395 "Display Listen Sockets and who created them\n")
15396{
15397 bgp_dump_listener_info(vty);
15398
15399 return CMD_SUCCESS;
15400}
15401
825d9834
DS
15402DEFUN (show_bgp_peerhash,
15403 show_bgp_peerhash_cmd,
15404 "show bgp peerhash",
15405 SHOW_STR
15406 BGP_STR
15407 "Display information about the BGP peerhash\n")
15408{
15409 struct list *instances = bm->bgp;
15410 struct listnode *node;
15411 struct bgp *bgp;
15412
15413 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15414 vty_out(vty, "BGP: %s\n", bgp->name);
15415 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15416 vty);
15417 }
15418
15419 return CMD_SUCCESS;
15420}
15421
587ff0fd 15422/* also used for encap safi */
2b791107
DL
15423static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15424 afi_t afi, safi_t safi)
d62a17ae 15425{
9bcb3eef
DS
15426 struct bgp_dest *pdest;
15427 struct bgp_dest *dest;
d62a17ae 15428 struct bgp_table *table;
b54892e0
DS
15429 const struct prefix *p;
15430 const struct prefix_rd *prd;
d62a17ae 15431 struct bgp_static *bgp_static;
15432 mpls_label_t label;
d62a17ae 15433
15434 /* Network configuration. */
9bcb3eef
DS
15435 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15436 pdest = bgp_route_next(pdest)) {
15437 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15438 if (!table)
ea47320b 15439 continue;
d62a17ae 15440
9bcb3eef
DS
15441 for (dest = bgp_table_top(table); dest;
15442 dest = bgp_route_next(dest)) {
15443 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15444 if (bgp_static == NULL)
ea47320b 15445 continue;
d62a17ae 15446
9bcb3eef
DS
15447 p = bgp_dest_get_prefix(dest);
15448 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15449 pdest);
d62a17ae 15450
ea47320b 15451 /* "network" configuration display. */
ea47320b
DL
15452 label = decode_label(&bgp_static->label);
15453
c4f64ea9 15454 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15455 if (safi == SAFI_MPLS_VPN)
15456 vty_out(vty, " label %u", label);
15457
15458 if (bgp_static->rmap.name)
15459 vty_out(vty, " route-map %s",
15460 bgp_static->rmap.name);
e2a86ad9
DS
15461
15462 if (bgp_static->backdoor)
15463 vty_out(vty, " backdoor");
15464
ea47320b
DL
15465 vty_out(vty, "\n");
15466 }
15467 }
d62a17ae 15468}
15469
2b791107
DL
15470static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15471 afi_t afi, safi_t safi)
d62a17ae 15472{
9bcb3eef
DS
15473 struct bgp_dest *pdest;
15474 struct bgp_dest *dest;
d62a17ae 15475 struct bgp_table *table;
b54892e0
DS
15476 const struct prefix *p;
15477 const struct prefix_rd *prd;
d62a17ae 15478 struct bgp_static *bgp_static;
ff44f570 15479 char buf[PREFIX_STRLEN * 2];
d62a17ae 15480 char buf2[SU_ADDRSTRLEN];
5f933e1e 15481 char esi_buf[ESI_STR_LEN];
d62a17ae 15482
15483 /* Network configuration. */
9bcb3eef
DS
15484 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15485 pdest = bgp_route_next(pdest)) {
15486 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15487 if (!table)
ea47320b 15488 continue;
d62a17ae 15489
9bcb3eef
DS
15490 for (dest = bgp_table_top(table); dest;
15491 dest = bgp_route_next(dest)) {
15492 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15493 if (bgp_static == NULL)
ea47320b 15494 continue;
d62a17ae 15495
ea47320b 15496 char *macrouter = NULL;
d62a17ae 15497
ea47320b
DL
15498 if (bgp_static->router_mac)
15499 macrouter = prefix_mac2str(
15500 bgp_static->router_mac, NULL, 0);
15501 if (bgp_static->eth_s_id)
0a50c248
AK
15502 esi_to_str(bgp_static->eth_s_id,
15503 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15504 p = bgp_dest_get_prefix(dest);
15505 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15506
ea47320b 15507 /* "network" configuration display. */
197cb530
PG
15508 if (p->u.prefix_evpn.route_type == 5) {
15509 char local_buf[PREFIX_STRLEN];
07380148 15510
3714a385 15511 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15512 struct prefix_evpn *)p)
15513 ? AF_INET
15514 : AF_INET6;
3714a385 15515 inet_ntop(family,
07380148
DA
15516 &p->u.prefix_evpn.prefix_addr.ip.ip
15517 .addr,
15518 local_buf, sizeof(local_buf));
772270f3
QY
15519 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15520 p->u.prefix_evpn.prefix_addr
15521 .ip_prefix_length);
197cb530
PG
15522 } else {
15523 prefix2str(p, buf, sizeof(buf));
15524 }
ea47320b 15525
a4d82a8a
PZ
15526 if (bgp_static->gatewayIp.family == AF_INET
15527 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15528 inet_ntop(bgp_static->gatewayIp.family,
15529 &bgp_static->gatewayIp.u.prefix, buf2,
15530 sizeof(buf2));
ea47320b 15531 vty_out(vty,
c4f64ea9
DA
15532 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15533 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15534 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15535 macrouter);
15536
0a22ddfb 15537 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15538 }
15539 }
3da6fcd5
PG
15540}
15541
718e3744 15542/* Configuration of static route announcement and aggregate
15543 information. */
2b791107
DL
15544void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15545 safi_t safi)
d62a17ae 15546{
9bcb3eef 15547 struct bgp_dest *dest;
b54892e0 15548 const struct prefix *p;
d62a17ae 15549 struct bgp_static *bgp_static;
15550 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15551
2b791107
DL
15552 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15553 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15554 return;
15555 }
d62a17ae 15556
2b791107
DL
15557 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15558 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15559 return;
15560 }
d62a17ae 15561
15562 /* Network configuration. */
9bcb3eef
DS
15563 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15564 dest = bgp_route_next(dest)) {
15565 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15566 if (bgp_static == NULL)
ea47320b 15567 continue;
d62a17ae 15568
9bcb3eef 15569 p = bgp_dest_get_prefix(dest);
d62a17ae 15570
8228a9a7 15571 vty_out(vty, " network %pFX", p);
d62a17ae 15572
ea47320b
DL
15573 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15574 vty_out(vty, " label-index %u",
15575 bgp_static->label_index);
d62a17ae 15576
ea47320b
DL
15577 if (bgp_static->rmap.name)
15578 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15579
15580 if (bgp_static->backdoor)
15581 vty_out(vty, " backdoor");
718e3744 15582
ea47320b
DL
15583 vty_out(vty, "\n");
15584 }
15585
d62a17ae 15586 /* Aggregate-address configuration. */
9bcb3eef
DS
15587 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15588 dest = bgp_route_next(dest)) {
15589 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15590 if (bgp_aggregate == NULL)
ea47320b 15591 continue;
d62a17ae 15592
9bcb3eef 15593 p = bgp_dest_get_prefix(dest);
d62a17ae 15594
8228a9a7 15595 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15596
ea47320b
DL
15597 if (bgp_aggregate->as_set)
15598 vty_out(vty, " as-set");
d62a17ae 15599
ea47320b
DL
15600 if (bgp_aggregate->summary_only)
15601 vty_out(vty, " summary-only");
718e3744 15602
20894f50
DA
15603 if (bgp_aggregate->rmap.name)
15604 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15605
229757f1
DA
15606 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15607 vty_out(vty, " origin %s",
15608 bgp_origin2str(bgp_aggregate->origin));
15609
6aabb15d
RZ
15610 if (bgp_aggregate->match_med)
15611 vty_out(vty, " matching-MED-only");
15612
365ab2e7
RZ
15613 if (bgp_aggregate->suppress_map_name)
15614 vty_out(vty, " suppress-map %s",
15615 bgp_aggregate->suppress_map_name);
15616
ea47320b
DL
15617 vty_out(vty, "\n");
15618 }
d62a17ae 15619}
734b349e 15620
2b791107 15621void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15622 safi_t safi)
d62a17ae 15623{
9bcb3eef 15624 struct bgp_dest *dest;
d62a17ae 15625 struct bgp_distance *bdistance;
15626
15627 /* Distance configuration. */
15628 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15629 && bgp->distance_local[afi][safi]
15630 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15631 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15632 || bgp->distance_local[afi][safi]
15633 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15634 vty_out(vty, " distance bgp %d %d %d\n",
15635 bgp->distance_ebgp[afi][safi],
15636 bgp->distance_ibgp[afi][safi],
15637 bgp->distance_local[afi][safi]);
15638 }
734b349e 15639
9bcb3eef
DS
15640 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15641 dest = bgp_route_next(dest)) {
15642 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15643 if (bdistance != NULL)
56ca3b5b 15644 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15645 bdistance->distance, dest,
d62a17ae 15646 bdistance->access_list ? bdistance->access_list
15647 : "");
ca2e160d 15648 }
718e3744 15649}
15650
15651/* Allocate routing table structure and install commands. */
d62a17ae 15652void bgp_route_init(void)
15653{
15654 afi_t afi;
15655 safi_t safi;
15656
15657 /* Init BGP distance table. */
05c7a1cc 15658 FOREACH_AFI_SAFI (afi, safi)
960035b2 15659 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15660
15661 /* IPv4 BGP commands. */
15662 install_element(BGP_NODE, &bgp_table_map_cmd);
15663 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15664 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15665
554b3b10 15666 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15667
15668 /* IPv4 unicast configuration. */
15669 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15670 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15671 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15672
554b3b10 15673 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15674
15675 /* IPv4 multicast configuration. */
15676 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15677 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15678 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15679 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15680
15681 /* IPv4 labeled-unicast configuration. */
fb985e0c 15682 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15683 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15684
d62a17ae 15685 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15686 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15687 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15688 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15689 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15690 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15691 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15692 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15693
15694 install_element(VIEW_NODE,
15695 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15696 install_element(VIEW_NODE,
15697 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15698 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15699 install_element(VIEW_NODE,
15700 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15701#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15702 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15703#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15704 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15705 install_element(VIEW_NODE,
44c69747 15706 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15707
d62a17ae 15708 /* BGP dampening clear commands */
15709 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15710 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15711
d62a17ae 15712 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15713 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15714
15715 /* prefix count */
15716 install_element(ENABLE_NODE,
15717 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15718#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15719 install_element(ENABLE_NODE,
15720 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15721#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15722
d62a17ae 15723 /* New config IPv6 BGP commands. */
15724 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15725 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15726 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15727
554b3b10 15728 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15729
15730 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15731
fb985e0c
DA
15732 /* IPv6 labeled unicast address family. */
15733 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15734 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15735
d62a17ae 15736 install_element(BGP_NODE, &bgp_distance_cmd);
15737 install_element(BGP_NODE, &no_bgp_distance_cmd);
15738 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15739 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15740 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15741 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15742 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15743 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15744 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15745 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15746 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15747 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15748 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15749 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15750 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15751 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15752 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15753 install_element(BGP_IPV4M_NODE,
15754 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15755 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15756 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15757 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15758 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15759 install_element(BGP_IPV6_NODE,
15760 &ipv6_bgp_distance_source_access_list_cmd);
15761 install_element(BGP_IPV6_NODE,
15762 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15763 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15764 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15765 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15766 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15767 install_element(BGP_IPV6M_NODE,
15768 &ipv6_bgp_distance_source_access_list_cmd);
15769 install_element(BGP_IPV6M_NODE,
15770 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15771
ef5f4b23 15772 /* BGP dampening */
585f1adc
IR
15773 install_element(BGP_NODE, &bgp_damp_set_cmd);
15774 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15775 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15776 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15777 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15778 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15779 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15780 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15781 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15782 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15783 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15784 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15785 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15786 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15787
15788 /* Large Communities */
15789 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15790 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15791
15792 /* show bgp ipv4 flowspec detailed */
15793 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15794
2a0e69ae 15795 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15796 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15797}
15798
15799void bgp_route_finish(void)
15800{
15801 afi_t afi;
15802 safi_t safi;
15803
05c7a1cc
QY
15804 FOREACH_AFI_SAFI (afi, safi) {
15805 bgp_table_unlock(bgp_distance_table[afi][safi]);
15806 bgp_distance_table[afi][safi] = NULL;
15807 }
228da428 15808}