]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Add lttng tracepoints for peer_lock/peer_unlock
[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 */
8ccee4b8
DA
2089 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2090 if (!bgp_addpath_capable(pi, peer, afi, safi))
3dc339cd 2091 return false;
06370dac 2092
d62a17ae 2093 /* Aggregate-address suppress check. */
4056a5f6
RZ
2094 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2095 return false;
3f9c7369 2096
13b7e7f0
DS
2097 /*
2098 * If we are doing VRF 2 VRF leaking via the import
2099 * statement, we want to prevent the route going
2100 * off box as that the RT and RD created are localy
2101 * significant and globaly useless.
2102 */
40381db7
DS
2103 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2104 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2105 return false;
13b7e7f0 2106
d62a17ae 2107 /* If it's labeled safi, make sure the route has a valid label. */
2108 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2109 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2110 if (!bgp_is_valid_label(&label)) {
2111 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2112 zlog_debug("u%" PRIu64 ":s%" PRIu64
2113 " %pFX is filtered - no label (%p)",
d62a17ae 2114 subgrp->update_group->id, subgrp->id,
8228a9a7 2115 p, &label);
3dc339cd 2116 return false;
d62a17ae 2117 }
2118 }
cd1964ff 2119
d62a17ae 2120 /* Do not send back route to sender. */
2121 if (onlypeer && from == onlypeer) {
3dc339cd 2122 return false;
d62a17ae 2123 }
3f9c7369 2124
d62a17ae 2125 /* Do not send the default route in the BGP table if the neighbor is
2126 * configured for default-originate */
2127 if (CHECK_FLAG(peer->af_flags[afi][safi],
2128 PEER_FLAG_DEFAULT_ORIGINATE)) {
2129 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2130 return false;
d62a17ae 2131 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2132 return false;
d62a17ae 2133 }
4125bb67 2134
d62a17ae 2135 /* Transparency check. */
2136 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2137 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2138 transparent = 1;
2139 else
2140 transparent = 0;
2141
2142 /* If community is not disabled check the no-export and local. */
40381db7 2143 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2144 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2145 zlog_debug("%s: community filter check fail for %pFX",
2146 __func__, p);
3dc339cd 2147 return false;
d62a17ae 2148 }
3f9c7369 2149
d62a17ae 2150 /* If the attribute has originator-id and it is same as remote
2151 peer's id. */
40381db7
DS
2152 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2153 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2154 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2155 zlog_debug(
a9f3f4f5
DA
2156 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2157 onlypeer, p);
3dc339cd 2158 return false;
d62a17ae 2159 }
3f9c7369 2160
d62a17ae 2161 /* ORF prefix-list filter check */
2162 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2163 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2164 || CHECK_FLAG(peer->af_cap[afi][safi],
2165 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2166 if (peer->orf_plist[afi][safi]) {
2167 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2168 == PREFIX_DENY) {
2169 if (bgp_debug_update(NULL, p,
2170 subgrp->update_group, 0))
2171 zlog_debug(
a9f3f4f5
DA
2172 "%pBP [Update:SEND] %pFX is filtered via ORF",
2173 peer, p);
3dc339cd 2174 return false;
d62a17ae 2175 }
2176 }
2177
2178 /* Output filter check. */
40381db7 2179 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2180 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2181 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2182 p);
3dc339cd 2183 return false;
d62a17ae 2184 }
3f9c7369 2185
d62a17ae 2186 /* AS path loop check. */
2b31007c
RZ
2187 if (onlypeer && onlypeer->as_path_loop_detection
2188 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2189 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2190 zlog_debug(
a9f3f4f5
DA
2191 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2192 onlypeer, onlypeer->as);
3dc339cd 2193 return false;
d62a17ae 2194 }
3f9c7369 2195
d62a17ae 2196 /* If we're a CONFED we need to loop check the CONFED ID too */
2197 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
b0a8f709 2198 if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
d62a17ae 2199 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2200 zlog_debug(
a9f3f4f5
DA
2201 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2202 peer, bgp->confed_id);
3dc339cd 2203 return false;
d62a17ae 2204 }
3f9c7369 2205 }
3f9c7369 2206
d62a17ae 2207 /* Route-Reflect check. */
2208 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2209 reflect = 1;
2210 else
2211 reflect = 0;
2212
2213 /* IBGP reflection check. */
2214 if (reflect && !samepeer_safe) {
2215 /* A route from a Client peer. */
2216 if (CHECK_FLAG(from->af_flags[afi][safi],
2217 PEER_FLAG_REFLECTOR_CLIENT)) {
2218 /* Reflect to all the Non-Client peers and also to the
2219 Client peers other than the originator. Originator
2220 check
2221 is already done. So there is noting to do. */
2222 /* no bgp client-to-client reflection check. */
892fedb6
DA
2223 if (CHECK_FLAG(bgp->flags,
2224 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2225 if (CHECK_FLAG(peer->af_flags[afi][safi],
2226 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2227 return false;
d62a17ae 2228 } else {
2229 /* A route from a Non-client peer. Reflect to all other
2230 clients. */
2231 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2232 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2233 return false;
d62a17ae 2234 }
2235 }
3f9c7369 2236
51c3a7de
DA
2237 /* For modify attribute, copy it to temporary structure.
2238 * post_attr comes from BGP conditional advertisements, where
2239 * attributes are already processed by advertise-map route-map,
2240 * and this needs to be saved instead of overwriting from the
2241 * path attributes.
2242 */
2243 if (post_attr)
2244 *attr = *post_attr;
2245 else
2246 *attr = *piattr;
d62a17ae 2247
2248 /* If local-preference is not set. */
2249 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2250 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2251 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2252 attr->local_pref = bgp->default_local_pref;
3f9c7369 2253 }
3f9c7369 2254
d62a17ae 2255 /* If originator-id is not set and the route is to be reflected,
2256 set the originator id */
2257 if (reflect
2258 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2259 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2260 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2261 }
3f9c7369 2262
d62a17ae 2263 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2264 */
2265 if (peer->sort == BGP_PEER_EBGP
2266 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2267 if (from != bgp->peer_self && !transparent
2268 && !CHECK_FLAG(peer->af_flags[afi][safi],
2269 PEER_FLAG_MED_UNCHANGED))
2270 attr->flag &=
2271 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2272 }
3f9c7369 2273
d62a17ae 2274 /* Since the nexthop attribute can vary per peer, it is not explicitly
2275 * set
2276 * in announce check, only certain flags and length (or number of
2277 * nexthops
2278 * -- for IPv6/MP_REACH) are set here in order to guide the update
2279 * formation
2280 * code in setting the nexthop(s) on a per peer basis in
2281 * reformat_peer().
2282 * Typically, the source nexthop in the attribute is preserved but in
2283 * the
2284 * scenarios where we know it will always be overwritten, we reset the
2285 * nexthop to "0" in an attempt to achieve better Update packing. An
2286 * example of this is when a prefix from each of 2 IBGP peers needs to
2287 * be
2288 * announced to an EBGP peer (and they have the same attributes barring
2289 * their nexthop).
2290 */
2291 if (reflect)
2292 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2293
2294#define NEXTHOP_IS_V6 \
2295 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2296 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2297 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2298 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2299
2300 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2301 * if
2302 * the peer (group) is configured to receive link-local nexthop
2303 * unchanged
c728d027
DA
2304 * and it is available in the prefix OR we're not reflecting the route,
2305 * link-local nexthop address is valid and
d62a17ae 2306 * the peer (group) to whom we're going to announce is on a shared
2307 * network
2308 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2309 * By checking if nexthop LL address is valid we are sure that
2310 * we do not announce LL address as `::`.
d62a17ae 2311 */
2312 if (NEXTHOP_IS_V6) {
2313 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2314 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2315 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2316 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2317 || (!reflect && !transparent
c728d027
DA
2318 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2319 && peer->shared_network
d62a17ae 2320 && (from == bgp->peer_self
2321 || peer->sort == BGP_PEER_EBGP))) {
2322 attr->mp_nexthop_len =
2323 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2324 }
3f9c7369 2325
d62a17ae 2326 /* Clear off link-local nexthop in source, whenever it is not
2327 * needed to
2328 * ensure more prefixes share the same attribute for
2329 * announcement.
2330 */
2331 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2332 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2333 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2334 }
3f9c7369 2335
5a78f2bc
EB
2336 if (bgp_check_role_applicability(afi, safi) &&
2337 bgp_otc_egress(peer, attr))
d864dd9e
EB
2338 return false;
2339
d62a17ae 2340 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2341 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2342
0655090c
QY
2343 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2344 filter->advmap.aname &&
2345 route_map_lookup_by_name(filter->advmap.aname)) {
2346 struct bgp_path_info rmap_path = {0};
2347 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2348 struct attr dummy_attr = *attr;
2349
2350 /* Fill temp path_info */
2351 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2352 pi, peer, &dummy_attr);
2353
2354 struct route_map *amap =
2355 route_map_lookup_by_name(filter->advmap.aname);
2356
2357 ret = route_map_apply(amap, p, &rmap_path);
2358
2359 bgp_attr_flush(&dummy_attr);
2360
2361 /*
2362 * The conditional advertisement mode is Withdraw and this
2363 * prefix is a conditional prefix. Don't advertise it
2364 */
2365 if (ret == RMAP_PERMITMATCH)
2366 return false;
2367 }
2368
d62a17ae 2369 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2370 if (!post_attr &&
2371 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2372 struct bgp_path_info rmap_path = {0};
2373 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2374 struct attr dummy_attr = {0};
d62a17ae 2375
e34291b8 2376 /* Fill temp path_info */
9bcb3eef
DS
2377 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2378 pi, peer, attr);
16f7ce2b 2379
d62a17ae 2380 /* don't confuse inbound and outbound setting */
2381 RESET_FLAG(attr->rmap_change_flags);
2382
2383 /*
2384 * The route reflector is not allowed to modify the attributes
2385 * of the reflected IBGP routes unless explicitly allowed.
2386 */
2387 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2388 && !CHECK_FLAG(bgp->flags,
2389 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2390 dummy_attr = *attr;
40381db7 2391 rmap_path.attr = &dummy_attr;
d62a17ae 2392 }
3f9c7369 2393
d62a17ae 2394 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2395
4056a5f6 2396 if (bgp_path_suppressed(pi))
d62a17ae 2397 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2398 &rmap_path);
d62a17ae 2399 else
2400 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2401 &rmap_path);
d62a17ae 2402
7e7639f5 2403 bgp_attr_flush(&dummy_attr);
d62a17ae 2404 peer->rmap_type = 0;
2405
2406 if (ret == RMAP_DENYMATCH) {
778048bf 2407 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2408 zlog_debug(
a9f3f4f5
DA
2409 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2410 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2411 bgp_attr_flush(rmap_path.attr);
3dc339cd 2412 return false;
d62a17ae 2413 }
3f9c7369 2414 }
3f9c7369 2415
9dac9fc8
DA
2416 /* RFC 8212 to prevent route leaks.
2417 * This specification intends to improve this situation by requiring the
2418 * explicit configuration of both BGP Import and Export Policies for any
2419 * External BGP (EBGP) session such as customers, peers, or
2420 * confederation boundaries for all enabled address families. Through
2421 * codification of the aforementioned requirement, operators will
2422 * benefit from consistent behavior across different BGP
2423 * implementations.
2424 */
1d3fdccf 2425 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2426 if (!bgp_outbound_policy_exists(peer, filter)) {
2427 if (monotime_since(&bgp->ebgprequirespolicywarning,
2428 NULL) > FIFTEENMINUTE2USEC ||
2429 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2430 zlog_warn(
2431 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2432 monotime(&bgp->ebgprequirespolicywarning);
2433 }
3dc339cd 2434 return false;
b17826b7 2435 }
9dac9fc8 2436
fb29348a
DA
2437 /* draft-ietf-idr-deprecate-as-set-confed-set
2438 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2439 * Eventually, This document (if approved) updates RFC 4271
2440 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2441 * and obsoletes RFC 6472.
2442 */
7f972cd8 2443 if (peer->bgp->reject_as_sets)
fb29348a 2444 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2445 return false;
fb29348a 2446
8c4d4624 2447 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2448 * SoO extended community and validate against the configured
2449 * one. If they match, do not announce, to prevent routing
2450 * loops.
2451 */
2452 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2453 peer->soo[afi][safi]) {
2454 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2455 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2456
2457 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2458 ECOMMUNITY_SITE_ORIGIN) ||
2459 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2460 ECOMMUNITY_SITE_ORIGIN) ||
2461 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2462 ECOMMUNITY_SITE_ORIGIN)) &&
2463 ecommunity_include(ecomm, ecomm_soo)) {
2464 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2465 zlog_debug(
2466 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2467 peer, p, ecommunity_str(ecomm_soo));
2468 return false;
2469 }
2470 }
2471
33d022bc
DA
2472 /* Codification of AS 0 Processing */
2473 if (aspath_check_as_zero(attr->aspath))
e2369003 2474 return false;
33d022bc 2475
637e5ba4 2476 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2477 if (peer->sort == BGP_PEER_IBGP
2478 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2479 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2480 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2481 } else {
2482 bgp_attr_add_gshut_community(attr);
2483 }
2484 }
2485
1479ed2f
DA
2486 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2487 * Capability" to a neighbor MUST perform the following upon receiving
2488 * a route from that neighbor with the "LLGR_STALE" community, or upon
2489 * attaching the "LLGR_STALE" community itself per Section 4.2:
2490 *
2491 * The route SHOULD NOT be advertised to any neighbor from which the
2492 * Long-lived Graceful Restart Capability has not been received.
2493 */
9a706b42
DA
2494 if (bgp_attr_get_community(attr) &&
2495 community_include(bgp_attr_get_community(attr),
2496 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2497 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2498 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2499 return false;
2500
d62a17ae 2501 /* After route-map has been applied, we check to see if the nexthop to
2502 * be carried in the attribute (that is used for the announcement) can
2503 * be cleared off or not. We do this in all cases where we would be
2504 * setting the nexthop to "ourselves". For IPv6, we only need to
2505 * consider
2506 * the global nexthop here; the link-local nexthop would have been
2507 * cleared
2508 * already, and if not, it is required by the update formation code.
2509 * Also see earlier comments in this function.
2510 */
2511 /*
2512 * If route-map has performed some operation on the nexthop or the peer
2513 * configuration says to pass it unchanged, we cannot reset the nexthop
2514 * here, so only attempt to do it if these aren't true. Note that the
2515 * route-map handler itself might have cleared the nexthop, if for
2516 * example,
2517 * it is configured as 'peer-address'.
2518 */
2519 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2520 piattr->rmap_change_flags)
d62a17ae 2521 && !transparent
2522 && !CHECK_FLAG(peer->af_flags[afi][safi],
2523 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2524 /* We can reset the nexthop, if setting (or forcing) it to
2525 * 'self' */
2526 if (CHECK_FLAG(peer->af_flags[afi][safi],
2527 PEER_FLAG_NEXTHOP_SELF)
2528 || CHECK_FLAG(peer->af_flags[afi][safi],
2529 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2530 if (!reflect
2531 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2532 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer, afi, safi)
2535 ? AF_INET6
2536 : p->family),
2537 attr);
7b651a32 2538 nh_reset = true;
2539 }
d62a17ae 2540 } else if (peer->sort == BGP_PEER_EBGP) {
2541 /* Can also reset the nexthop if announcing to EBGP, but
2542 * only if
2543 * no peer in the subgroup is on a shared subnet.
2544 * Note: 3rd party nexthop currently implemented for
2545 * IPv4 only.
2546 */
737af885
BS
2547 if ((p->family == AF_INET) &&
2548 (!bgp_subgrp_multiaccess_check_v4(
2549 piattr->nexthop,
7b651a32 2550 subgrp, from))) {
d62a17ae 2551 subgroup_announce_reset_nhop(
2552 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2553 ? AF_INET6
2554 : p->family),
737af885 2555 attr);
7b651a32 2556 nh_reset = true;
2557 }
737af885
BS
2558
2559 if ((p->family == AF_INET6) &&
2560 (!bgp_subgrp_multiaccess_check_v6(
2561 piattr->mp_nexthop_global,
7b651a32 2562 subgrp, from))) {
737af885
BS
2563 subgroup_announce_reset_nhop(
2564 (peer_cap_enhe(peer, afi, safi)
2565 ? AF_INET6
2566 : p->family),
2567 attr);
7b651a32 2568 nh_reset = true;
2569 }
737af885
BS
2570
2571
2572
40381db7 2573 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2574 /*
2575 * This flag is used for leaked vpn-vrf routes
2576 */
2577 int family = p->family;
2578
2579 if (peer_cap_enhe(peer, afi, safi))
2580 family = AF_INET6;
2581
2582 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2583 zlog_debug(
6cf8a4bf
DA
2584 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2585 __func__, p, family2str(family));
960035b2 2586 subgroup_announce_reset_nhop(family, attr);
7b651a32 2587 nh_reset = true;
d62a17ae 2588 }
63696f1d 2589 }
960035b2 2590
63696f1d 2591 /* If IPv6/MP and nexthop does not have any override and happens
2592 * to
2593 * be a link-local address, reset it so that we don't pass along
2594 * the
2595 * source's link-local IPv6 address to recipients who may not be
2596 * on
2597 * the same interface.
2598 */
2599 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2600 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2601 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2602 nh_reset = true;
2603 }
d62a17ae 2604 }
3f9c7369 2605
7b27cf7b
DA
2606 /* If this is an iBGP, send Origin Validation State (OVS)
2607 * extended community (rfc8097).
2608 */
2609 if (peer->sort == BGP_PEER_IBGP) {
2610 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2611
2612 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2613
2614 if (rpki_state != RPKI_NOT_BEING_USED)
2615 bgp_attr_set_ecommunity(
2616 attr, ecommunity_add_origin_validation_state(
2617 rpki_state,
2618 bgp_attr_get_ecommunity(attr)));
2619 }
2620
7b651a32 2621 /*
2622 * When the next hop is set to ourselves, if all multipaths have
2623 * link-bandwidth announce the cumulative bandwidth as that makes
2624 * the most sense. However, don't modify if the link-bandwidth has
2625 * been explicitly set by user policy.
2626 */
2627 if (nh_reset &&
f7e1c681 2628 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2629 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2630 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2631 bgp_attr_set_ecommunity(
2632 attr,
2633 ecommunity_replace_linkbw(
2634 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2635 CHECK_FLAG(
2636 peer->flags,
2637 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2638
3dc339cd 2639 return true;
3f9c7369
DS
2640}
2641
cc9f21da 2642static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2643{
2644 struct afi_safi_info *info;
2645 afi_t afi;
2646 safi_t safi;
2647 struct bgp *bgp;
2648
2649 info = THREAD_ARG(thread);
2650 afi = info->afi;
2651 safi = info->safi;
2652 bgp = info->bgp;
2653
f009ff26 2654 bgp->gr_info[afi][safi].t_route_select = NULL;
f009ff26 2655 XFREE(MTYPE_TMP, info);
2656
2657 /* Best path selection */
cc9f21da 2658 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2659}
2660
9bcb3eef 2661void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2662 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2663 struct bgp_path_info_pair *result, afi_t afi,
2664 safi_t safi)
2665{
2666 struct bgp_path_info *new_select;
2667 struct bgp_path_info *old_select;
40381db7
DS
2668 struct bgp_path_info *pi;
2669 struct bgp_path_info *pi1;
2670 struct bgp_path_info *pi2;
2671 struct bgp_path_info *nextpi = NULL;
d62a17ae 2672 int paths_eq, do_mpath, debug;
2673 struct list mp_list;
2674 char pfx_buf[PREFIX2STR_BUFFER];
2675 char path_buf[PATH_ADDPATH_STR_BUFFER];
2676
2677 bgp_mp_list_init(&mp_list);
2678 do_mpath =
2679 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2680
9bcb3eef 2681 debug = bgp_debug_bestpath(dest);
d62a17ae 2682
2683 if (debug)
9bcb3eef 2684 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2685
9bcb3eef 2686 dest->reason = bgp_path_selection_none;
d62a17ae 2687 /* bgp deterministic-med */
2688 new_select = NULL;
892fedb6 2689 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2690
1defdda8 2691 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2692 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2693 pi1 = pi1->next)
9bcb3eef 2694 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2695 BGP_PATH_DMED_SELECTED);
d62a17ae 2696
9bcb3eef 2697 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2698 pi1 = pi1->next) {
40381db7 2699 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2700 continue;
40381db7 2701 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2702 continue;
ea8b2282 2703 if (pi1->peer != bgp->peer_self)
feb17238 2704 if (!peer_established(pi1->peer))
d62a17ae 2705 continue;
2706
40381db7
DS
2707 new_select = pi1;
2708 if (pi1->next) {
2709 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2710 if (CHECK_FLAG(pi2->flags,
1defdda8 2711 BGP_PATH_DMED_CHECK))
d62a17ae 2712 continue;
40381db7 2713 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2714 continue;
ea8b2282 2715 if (pi2->peer != bgp->peer_self
d62a17ae 2716 && !CHECK_FLAG(
ea8b2282
DS
2717 pi2->peer->sflags,
2718 PEER_STATUS_NSF_WAIT))
40381db7 2719 if (pi2->peer->status
d62a17ae 2720 != Established)
2721 continue;
2722
121e245d
DS
2723 if (!aspath_cmp_left(pi1->attr->aspath,
2724 pi2->attr->aspath)
2725 && !aspath_cmp_left_confed(
40381db7 2726 pi1->attr->aspath,
121e245d
DS
2727 pi2->attr->aspath))
2728 continue;
d62a17ae 2729
121e245d
DS
2730 if (bgp_path_info_cmp(
2731 bgp, pi2, new_select,
2732 &paths_eq, mpath_cfg, debug,
fdf81fa0 2733 pfx_buf, afi, safi,
9bcb3eef 2734 &dest->reason)) {
121e245d 2735 bgp_path_info_unset_flag(
9bcb3eef 2736 dest, new_select,
121e245d
DS
2737 BGP_PATH_DMED_SELECTED);
2738 new_select = pi2;
d62a17ae 2739 }
121e245d
DS
2740
2741 bgp_path_info_set_flag(
9bcb3eef 2742 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2743 }
2744 }
9bcb3eef 2745 bgp_path_info_set_flag(dest, new_select,
18ee8310 2746 BGP_PATH_DMED_CHECK);
9bcb3eef 2747 bgp_path_info_set_flag(dest, new_select,
18ee8310 2748 BGP_PATH_DMED_SELECTED);
d62a17ae 2749
2750 if (debug) {
18ee8310 2751 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2752 new_select, path_buf, sizeof(path_buf));
8228a9a7 2753 zlog_debug(
4378495a
DS
2754 "%pBD(%s): %s is the bestpath from AS %u",
2755 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2756 aspath_get_first_as(
2757 new_select->attr->aspath));
d62a17ae 2758 }
2759 }
2760 }
96450faf 2761
d62a17ae 2762 /* Check old selected route and new selected route. */
2763 old_select = NULL;
2764 new_select = NULL;
9bcb3eef 2765 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2766 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2767 enum bgp_path_selection_reason reason;
2768
40381db7
DS
2769 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2770 old_select = pi;
d62a17ae 2771
40381db7 2772 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2773 /* reap REMOVED routes, if needs be
2774 * selected route must stay for a while longer though
2775 */
40381db7
DS
2776 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2777 && (pi != old_select))
9bcb3eef 2778 bgp_path_info_reap(dest, pi);
d62a17ae 2779
ddb5b488 2780 if (debug)
40381db7
DS
2781 zlog_debug("%s: pi %p in holddown", __func__,
2782 pi);
ddb5b488 2783
d62a17ae 2784 continue;
2785 }
96450faf 2786
40381db7
DS
2787 if (pi->peer && pi->peer != bgp->peer_self
2788 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2789 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2790
2791 if (debug)
2792 zlog_debug(
40381db7
DS
2793 "%s: pi %p non self peer %s not estab state",
2794 __func__, pi, pi->peer->host);
ddb5b488 2795
d62a17ae 2796 continue;
ddb5b488 2797 }
9fbdd100 2798
892fedb6 2799 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2800 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2801 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2802 if (debug)
40381db7 2803 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2804 continue;
2805 }
9fbdd100 2806
9bcb3eef 2807 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2808
9bcb3eef 2809 reason = dest->reason;
40381db7 2810 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2811 debug, pfx_buf, afi, safi,
2812 &dest->reason)) {
19ea4cec
DS
2813 if (new_select == NULL &&
2814 reason != bgp_path_selection_none)
9bcb3eef 2815 dest->reason = reason;
40381db7 2816 new_select = pi;
d62a17ae 2817 }
2818 }
718e3744 2819
d62a17ae 2820 /* Now that we know which path is the bestpath see if any of the other
2821 * paths
2822 * qualify as multipaths
2823 */
2824 if (debug) {
2825 if (new_select)
7533cad7
QY
2826 bgp_path_info_path_with_addpath_rx_str(
2827 new_select, path_buf, sizeof(path_buf));
d62a17ae 2828 else
772270f3 2829 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2830 zlog_debug(
4378495a
DS
2831 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2832 dest, bgp->name_pretty, path_buf,
d62a17ae 2833 old_select ? old_select->peer->host : "NONE");
96450faf 2834 }
9fbdd100 2835
d62a17ae 2836 if (do_mpath && new_select) {
9bcb3eef 2837 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2838 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2839
2840 if (debug)
18ee8310 2841 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2842 pi, path_buf, sizeof(path_buf));
d62a17ae 2843
40381db7 2844 if (pi == new_select) {
d62a17ae 2845 if (debug)
2846 zlog_debug(
4378495a
DS
2847 "%pBD(%s): %s is the bestpath, add to the multipath list",
2848 dest, bgp->name_pretty,
2849 path_buf);
40381db7 2850 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2851 continue;
2852 }
2853
40381db7 2854 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2855 continue;
2856
40381db7
DS
2857 if (pi->peer && pi->peer != bgp->peer_self
2858 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2859 PEER_STATUS_NSF_WAIT))
feb17238 2860 if (!peer_established(pi->peer))
d62a17ae 2861 continue;
2862
40381db7 2863 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2864 if (debug)
2865 zlog_debug(
8228a9a7
DS
2866 "%pBD: %s has the same nexthop as the bestpath, skip it",
2867 dest, path_buf);
d62a17ae 2868 continue;
2869 }
2870
40381db7 2871 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2872 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2873 &dest->reason);
d62a17ae 2874
2875 if (paths_eq) {
2876 if (debug)
2877 zlog_debug(
8228a9a7
DS
2878 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2879 dest, path_buf);
40381db7 2880 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2881 }
2882 }
2883 }
fee0f4c6 2884
4378495a 2885 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2886 mpath_cfg);
2887 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2888 bgp_mp_list_clear(&mp_list);
96450faf 2889
9bcb3eef 2890 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2891
d62a17ae 2892 result->old = old_select;
2893 result->new = new_select;
96450faf 2894
d62a17ae 2895 return;
fee0f4c6 2896}
2897
3f9c7369
DS
2898/*
2899 * A new route/change in bestpath of an existing route. Evaluate the path
2900 * for advertisement to the subgroup.
2901 */
3dc339cd
DA
2902void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2903 struct bgp_path_info *selected,
9bcb3eef 2904 struct bgp_dest *dest,
3dc339cd 2905 uint32_t addpath_tx_id)
d62a17ae 2906{
b54892e0 2907 const struct prefix *p;
d62a17ae 2908 struct peer *onlypeer;
2909 struct attr attr;
2910 afi_t afi;
2911 safi_t safi;
a77e2f4b
S
2912 struct bgp *bgp;
2913 bool advertise;
adbac85e 2914
9bcb3eef 2915 p = bgp_dest_get_prefix(dest);
d62a17ae 2916 afi = SUBGRP_AFI(subgrp);
2917 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2918 bgp = SUBGRP_INST(subgrp);
d62a17ae 2919 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2920 : NULL);
2921
2dbe669b
DA
2922 if (BGP_DEBUG(update, UPDATE_OUT))
2923 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2924
d62a17ae 2925 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2926 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2927 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2928 return;
d62a17ae 2929
6006b807 2930 memset(&attr, 0, sizeof(attr));
d62a17ae 2931 /* It's initialized in bgp_announce_check() */
2932
a77e2f4b
S
2933 /* Announcement to the subgroup. If the route is filtered withdraw it.
2934 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2935 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2936 * route
d62a17ae 2937 */
a77e2f4b
S
2938 advertise = bgp_check_advertise(bgp, dest);
2939
d62a17ae 2940 if (selected) {
7f7940e6 2941 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2942 NULL)) {
a77e2f4b
S
2943 /* Route is selected, if the route is already installed
2944 * in FIB, then it is advertised
2945 */
be785e35
DS
2946 if (advertise) {
2947 if (!bgp_check_withdrawal(bgp, dest))
2948 bgp_adj_out_set_subgroup(
2949 dest, subgrp, &attr, selected);
2950 else
2951 bgp_adj_out_unset_subgroup(
2952 dest, subgrp, 1, addpath_tx_id);
2953 }
a77e2f4b 2954 } else
9bcb3eef 2955 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2956 addpath_tx_id);
d62a17ae 2957 }
2958
2959 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2960 else {
9bcb3eef 2961 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2962 }
200df115 2963}
fee0f4c6 2964
3064bf43 2965/*
e1072051 2966 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2967 * This is called at the end of route processing.
3064bf43 2968 */
9bcb3eef 2969void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2970{
40381db7 2971 struct bgp_path_info *pi;
3064bf43 2972
9bcb3eef 2973 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2974 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2975 continue;
40381db7
DS
2976 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2977 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2978 }
3064bf43 2979}
2980
2981/*
2982 * Has the route changed from the RIB's perspective? This is invoked only
2983 * if the route selection returns the same best route as earlier - to
2984 * determine if we need to update zebra or not.
2985 */
9bcb3eef 2986bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2987{
4b7e6066 2988 struct bgp_path_info *mpinfo;
d62a17ae 2989
2bb9eff4
DS
2990 /* If this is multipath, check all selected paths for any nexthop
2991 * change or attribute change. Some attribute changes (e.g., community)
2992 * aren't of relevance to the RIB, but we'll update zebra to ensure
2993 * we handle the case of BGP nexthop change. This is the behavior
2994 * when the best path has an attribute change anyway.
d62a17ae 2995 */
1defdda8 2996 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2997 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2998 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2999 return true;
d62a17ae 3000
2bb9eff4
DS
3001 /*
3002 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 3003 */
18ee8310
DS
3004 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
3005 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3006 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3007 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3008 return true;
d62a17ae 3009 }
3064bf43 3010
d62a17ae 3011 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3012 return false;
3064bf43 3013}
3014
d62a17ae 3015struct bgp_process_queue {
3016 struct bgp *bgp;
9bcb3eef 3017 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3018#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3019 unsigned int flags;
3020 unsigned int queued;
200df115 3021};
3022
3b0c17e1 3023static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3024 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3025 struct bgp_path_info *new_select,
3026 struct bgp_path_info *old_select)
3027{
9bcb3eef 3028 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3029
3030 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3031 return;
3032
3033 if (advertise_type5_routes(bgp, afi) && new_select
3034 && is_route_injectable_into_evpn(new_select)) {
3035
3036 /* apply the route-map */
3037 if (bgp->adv_cmd_rmap[afi][safi].map) {
3038 route_map_result_t ret;
3039 struct bgp_path_info rmap_path;
3040 struct bgp_path_info_extra rmap_path_extra;
3041 struct attr dummy_attr;
3042
3043 dummy_attr = *new_select->attr;
3044
3045 /* Fill temp path_info */
9bcb3eef 3046 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3047 new_select, new_select->peer,
3048 &dummy_attr);
3049
3050 RESET_FLAG(dummy_attr.rmap_change_flags);
3051
3052 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3053 p, &rmap_path);
3b0c17e1 3054
3055 if (ret == RMAP_DENYMATCH) {
3056 bgp_attr_flush(&dummy_attr);
3057 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3058 safi);
3059 } else
3060 bgp_evpn_advertise_type5_route(
3061 bgp, p, &dummy_attr, afi, safi);
3062 } else {
3063 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3064 afi, safi);
3065 }
3066 } else if (advertise_type5_routes(bgp, afi) && old_select
3067 && is_route_injectable_into_evpn(old_select))
3068 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3069}
3070
bb2ca692
MS
3071/*
3072 * Utility to determine whether a particular path_info should use
3073 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3074 * in a path where we basically _know_ this is a BGP-LU route.
3075 */
3076static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3077{
3078 /* Certain types get imp null; so do paths where the nexthop is
3079 * not labeled.
3080 */
3081 if (new_select->sub_type == BGP_ROUTE_STATIC
3082 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3083 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3084 return true;
3085 else if (new_select->extra == NULL ||
3086 !bgp_is_valid_label(&new_select->extra->label[0]))
3087 /* TODO -- should be configurable? */
3088 return true;
3089 else
3090 return false;
3091}
3092
3103e8d2
DS
3093/*
3094 * old_select = The old best path
3095 * new_select = the new best path
3096 *
3097 * if (!old_select && new_select)
3098 * We are sending new information on.
3099 *
3100 * if (old_select && new_select) {
3101 * if (new_select != old_select)
3102 * We have a new best path send a change
3103 * else
3104 * We've received a update with new attributes that needs
3105 * to be passed on.
3106 * }
3107 *
3108 * if (old_select && !new_select)
3109 * We have no eligible route that we can announce or the rn
3110 * is being removed.
3111 */
9bcb3eef 3112static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3113 afi_t afi, safi_t safi)
d62a17ae 3114{
4b7e6066
DS
3115 struct bgp_path_info *new_select;
3116 struct bgp_path_info *old_select;
3117 struct bgp_path_info_pair old_and_new;
ddb5b488 3118 int debug = 0;
d62a17ae 3119
892fedb6 3120 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3121 if (dest)
3122 debug = bgp_debug_bestpath(dest);
b54892e0 3123 if (debug)
f4c713ae 3124 zlog_debug(
56ca3b5b 3125 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3126 __func__, dest);
f4c713ae
LB
3127 return;
3128 }
d62a17ae 3129 /* Is it end of initial update? (after startup) */
9bcb3eef 3130 if (!dest) {
e36f61b5
DS
3131 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3132 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3133
3134 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3135 FOREACH_AFI_SAFI (afi, safi) {
3136 if (bgp_fibupd_safi(safi))
3137 bgp_zebra_announce_table(bgp, afi, safi);
3138 }
d62a17ae 3139 bgp->main_peers_update_hold = 0;
3140
3141 bgp_start_routeadv(bgp);
aac24838 3142 return;
d62a17ae 3143 }
cb1faec9 3144
9bcb3eef 3145 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3146
9bcb3eef 3147 debug = bgp_debug_bestpath(dest);
b54892e0 3148 if (debug)
4378495a
DS
3149 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3150 dest, bgp->name_pretty, afi2str(afi),
3151 safi2str(safi));
ddb5b488 3152
f009ff26 3153 /* The best path calculation for the route is deferred if
3154 * BGP_NODE_SELECT_DEFER is set
3155 */
9bcb3eef 3156 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3157 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3158 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3159 return;
3160 }
3161
d62a17ae 3162 /* Best path selection. */
9bcb3eef 3163 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3164 afi, safi);
3165 old_select = old_and_new.old;
3166 new_select = old_and_new.new;
3167
3168 /* Do we need to allocate or free labels?
3169 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3170 * necessary to do this upon changes to best path. Exceptions:
3171 * - label index has changed -> recalculate resulting label
3172 * - path_info sub_type changed -> switch to/from implicit-null
3173 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3174 */
318cac96 3175 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3176 if (new_select) {
3177 if (!old_select
3178 || bgp_label_index_differs(new_select, old_select)
57592a53 3179 || new_select->sub_type != old_select->sub_type
9bcb3eef 3180 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3181 /* Enforced penultimate hop popping:
3182 * implicit-null for local routes, aggregate
3183 * and redistributed routes
3184 */
bb2ca692 3185 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3186 if (CHECK_FLAG(
9bcb3eef 3187 dest->flags,
992dd67e
PR
3188 BGP_NODE_REGISTERED_FOR_LABEL)
3189 || CHECK_FLAG(
3190 dest->flags,
3191 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3192 bgp_unregister_for_label(dest);
67f67ba4
DA
3193 dest->local_label = mpls_lse_encode(
3194 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3195 1);
9bcb3eef 3196 bgp_set_valid_label(&dest->local_label);
d62a17ae 3197 } else
9bcb3eef
DS
3198 bgp_register_for_label(dest,
3199 new_select);
d62a17ae 3200 }
9bcb3eef 3201 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3202 BGP_NODE_REGISTERED_FOR_LABEL)
3203 || CHECK_FLAG(dest->flags,
3204 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3205 bgp_unregister_for_label(dest);
318cac96 3206 }
992dd67e
PR
3207 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3208 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3209 bgp_unregister_for_label(dest);
d62a17ae 3210 }
cd1964ff 3211
b54892e0 3212 if (debug)
ddb5b488 3213 zlog_debug(
4378495a
DS
3214 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3215 __func__, dest, bgp->name_pretty, afi2str(afi),
3216 safi2str(safi), old_select, new_select);
ddb5b488 3217
d62a17ae 3218 /* If best route remains the same and this is not due to user-initiated
3219 * clear, see exactly what needs to be done.
3220 */
d62a17ae 3221 if (old_select && old_select == new_select
9bcb3eef 3222 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3223 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3224 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3225 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3226#ifdef ENABLE_BGP_VNC
d62a17ae 3227 vnc_import_bgp_add_route(bgp, p, old_select);
3228 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3229#endif
bb744275 3230 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3231 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3232
be785e35
DS
3233 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3234 && new_select->sub_type == BGP_ROUTE_NORMAL)
3235 SET_FLAG(dest->flags,
3236 BGP_NODE_FIB_INSTALL_PENDING);
3237
ddb5b488
PZ
3238 if (new_select->type == ZEBRA_ROUTE_BGP
3239 && (new_select->sub_type == BGP_ROUTE_NORMAL
3240 || new_select->sub_type
3241 == BGP_ROUTE_IMPORTED))
3242
9bcb3eef 3243 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3244 bgp, afi, safi);
3245 }
d62a17ae 3246 }
d62a17ae 3247
3248 /* If there is a change of interest to peers, reannounce the
3249 * route. */
1defdda8 3250 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3251 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3252 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3253 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3254
3255 /* unicast routes must also be annouced to
3256 * labeled-unicast update-groups */
3257 if (safi == SAFI_UNICAST)
3258 group_announce_route(bgp, afi,
9bcb3eef 3259 SAFI_LABELED_UNICAST, dest,
d62a17ae 3260 new_select);
3261
1defdda8 3262 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3263 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3264 }
fee0f4c6 3265
3b0c17e1 3266 /* advertise/withdraw type-5 routes */
3267 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3268 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3269 bgp_process_evpn_route_injection(
9bcb3eef 3270 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3271
b1875e65 3272 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3273 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3274 bgp_zebra_clear_route_change_flags(dest);
3275 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3276 return;
d62a17ae 3277 }
8ad7271d 3278
d62a17ae 3279 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3280 */
9bcb3eef 3281 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3282
3283 /* bestpath has changed; bump version */
3284 if (old_select || new_select) {
9bcb3eef 3285 bgp_bump_version(dest);
d62a17ae 3286
3287 if (!bgp->t_rmap_def_originate_eval) {
3288 bgp_lock(bgp);
3289 thread_add_timer(
3290 bm->master,
3291 update_group_refresh_default_originate_route_map,
3292 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3293 &bgp->t_rmap_def_originate_eval);
3294 }
3295 }
3f9c7369 3296
d62a17ae 3297 if (old_select)
9bcb3eef 3298 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3299 if (new_select) {
ddb5b488
PZ
3300 if (debug)
3301 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3302 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3303 bgp_path_info_unset_flag(dest, new_select,
3304 BGP_PATH_ATTR_CHANGED);
1defdda8 3305 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3306 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3307 }
338b3424 3308
49e5a4a0 3309#ifdef ENABLE_BGP_VNC
d62a17ae 3310 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3311 if (old_select != new_select) {
3312 if (old_select) {
3313 vnc_import_bgp_exterior_del_route(bgp, p,
3314 old_select);
3315 vnc_import_bgp_del_route(bgp, p, old_select);
3316 }
3317 if (new_select) {
3318 vnc_import_bgp_exterior_add_route(bgp, p,
3319 new_select);
3320 vnc_import_bgp_add_route(bgp, p, new_select);
3321 }
3322 }
3323 }
65efcfce
LB
3324#endif
3325
9bcb3eef 3326 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3327
3328 /* unicast routes must also be annouced to labeled-unicast update-groups
3329 */
3330 if (safi == SAFI_UNICAST)
9bcb3eef 3331 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3332 new_select);
3333
3334 /* FIB update. */
3335 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3336 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3337
d62a17ae 3338 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3339 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3340 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3341 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3342
be785e35
DS
3343 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3344 SET_FLAG(dest->flags,
3345 BGP_NODE_FIB_INSTALL_PENDING);
3346
2b659f33
MK
3347 /* if this is an evpn imported type-5 prefix,
3348 * we need to withdraw the route first to clear
3349 * the nh neigh and the RMAC entry.
3350 */
3351 if (old_select &&
3352 is_route_parent_evpn(old_select))
3353 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3354
9bcb3eef 3355 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3356 } else {
d62a17ae 3357 /* Withdraw the route from the kernel. */
3358 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3359 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3360 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3361 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3362
568e10ca 3363 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3364 }
718e3744 3365 }
3064bf43 3366
9bcb3eef 3367 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3368 old_select);
5424b7ba 3369
d62a17ae 3370 /* Clear any route change flags. */
9bcb3eef 3371 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3372
18ee8310 3373 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3374 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3375 bgp_path_info_reap(dest, old_select);
d62a17ae 3376
9bcb3eef 3377 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3378 return;
718e3744 3379}
3380
f009ff26 3381/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3382void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3383{
9bcb3eef 3384 struct bgp_dest *dest;
f009ff26 3385 int cnt = 0;
3386 struct afi_safi_info *thread_info;
f009ff26 3387
56c226e7
DS
3388 if (bgp->gr_info[afi][safi].t_route_select) {
3389 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3390
3391 thread_info = THREAD_ARG(t);
3392 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3393 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3394 }
f009ff26 3395
3396 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3397 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3398 get_afi_safi_str(afi, safi, false),
26742171 3399 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3400 }
3401
3402 /* Process the route list */
6338d242 3403 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3404 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3405 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3406 dest = bgp_route_next(dest)) {
3407 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3408 continue;
3409
3410 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3411 bgp->gr_info[afi][safi].gr_deferred--;
3412 bgp_process_main_one(bgp, dest, afi, safi);
3413 cnt++;
067ea165
CB
3414 }
3415 /* If iteration stopped before the entire table was traversed then the
3416 * node needs to be unlocked.
3417 */
3418 if (dest) {
3419 bgp_dest_unlock_node(dest);
3420 dest = NULL;
f009ff26 3421 }
3422
9e3b51a7 3423 /* Send EOR message when all routes are processed */
6338d242 3424 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3425 bgp_send_delayed_eor(bgp);
8c48b3b6 3426 /* Send route processing complete message to RIB */
3427 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3428 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3429 return;
9e3b51a7 3430 }
f009ff26 3431
3432 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3433
3434 thread_info->afi = afi;
3435 thread_info->safi = safi;
3436 thread_info->bgp = bgp;
3437
3438 /* If there are more routes to be processed, start the
3439 * selection timer
3440 */
3441 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3442 BGP_ROUTE_SELECT_DELAY,
3443 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3444}
3445
aac24838 3446static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3447{
aac24838
JB
3448 struct bgp_process_queue *pqnode = data;
3449 struct bgp *bgp = pqnode->bgp;
d62a17ae 3450 struct bgp_table *table;
9bcb3eef 3451 struct bgp_dest *dest;
aac24838
JB
3452
3453 /* eoiu marker */
3454 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3455 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3456 /* should always have dedicated wq call */
3457 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3458 return WQ_SUCCESS;
3459 }
3460
ac021f40 3461 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3462 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3463 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3464 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3465 table = bgp_dest_table(dest);
3466 /* note, new DESTs may be added as part of processing */
3467 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3468
9bcb3eef 3469 bgp_dest_unlock_node(dest);
d62a17ae 3470 bgp_table_unlock(table);
3471 }
aac24838
JB
3472
3473 return WQ_SUCCESS;
3474}
3475
3476static void bgp_processq_del(struct work_queue *wq, void *data)
3477{
3478 struct bgp_process_queue *pqnode = data;
3479
3480 bgp_unlock(pqnode->bgp);
3481
3482 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3483}
3484
b6c386bb 3485void bgp_process_queue_init(struct bgp *bgp)
200df115 3486{
b6c386bb
DS
3487 if (!bgp->process_queue) {
3488 char name[BUFSIZ];
3489
3490 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3491 bgp->process_queue = work_queue_new(bm->master, name);
3492 }
3493
3494 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3495 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3496 bgp->process_queue->spec.max_retries = 0;
3497 bgp->process_queue->spec.hold = 50;
d62a17ae 3498 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3499 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3500}
3501
cfe8d15a 3502static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3503{
3504 struct bgp_process_queue *pqnode;
3505
a4d82a8a
PZ
3506 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3507 sizeof(struct bgp_process_queue));
aac24838
JB
3508
3509 /* unlocked in bgp_processq_del */
3510 pqnode->bgp = bgp_lock(bgp);
3511 STAILQ_INIT(&pqnode->pqueue);
3512
aac24838
JB
3513 return pqnode;
3514}
3515
9bcb3eef 3516void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3517{
aac24838 3518#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3519 struct work_queue *wq = bgp->process_queue;
d62a17ae 3520 struct bgp_process_queue *pqnode;
cfe8d15a 3521 int pqnode_reuse = 0;
495f0b13 3522
d62a17ae 3523 /* already scheduled for processing? */
9bcb3eef 3524 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3525 return;
2e02b9b2 3526
f009ff26 3527 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3528 * the workqueue
3529 */
9bcb3eef 3530 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3531 if (BGP_DEBUG(update, UPDATE_OUT))
3532 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3533 dest);
f009ff26 3534 return;
3535 }
3536
46aeabed
LS
3537 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3538 if (BGP_DEBUG(update, UPDATE_OUT))
3539 zlog_debug(
3540 "Soft reconfigure table in progress for route %p",
3541 dest);
3542 return;
3543 }
3544
aac24838 3545 if (wq == NULL)
d62a17ae 3546 return;
3547
aac24838 3548 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3549 limit only if is from the same BGP view and it's not an EOIU marker
3550 */
aac24838
JB
3551 if (work_queue_item_count(wq)) {
3552 struct work_queue_item *item = work_queue_last_item(wq);
3553 pqnode = item->data;
228da428 3554
a4d82a8a
PZ
3555 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3556 || pqnode->bgp != bgp
3557 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3558 pqnode = bgp_processq_alloc(bgp);
3559 else
3560 pqnode_reuse = 1;
aac24838 3561 } else
cfe8d15a 3562 pqnode = bgp_processq_alloc(bgp);
aac24838 3563 /* all unlocked in bgp_process_wq */
9bcb3eef 3564 bgp_table_lock(bgp_dest_table(dest));
aac24838 3565
9bcb3eef
DS
3566 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3567 bgp_dest_lock_node(dest);
aac24838 3568
60466a63 3569 /* can't be enqueued twice */
9bcb3eef
DS
3570 assert(STAILQ_NEXT(dest, pq) == NULL);
3571 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3572 pqnode->queued++;
3573
cfe8d15a
LB
3574 if (!pqnode_reuse)
3575 work_queue_add(wq, pqnode);
3576
d62a17ae 3577 return;
fee0f4c6 3578}
0a486e5f 3579
d62a17ae 3580void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3581{
d62a17ae 3582 struct bgp_process_queue *pqnode;
cb1faec9 3583
b6c386bb 3584 if (bgp->process_queue == NULL)
d62a17ae 3585 return;
2e02b9b2 3586
cfe8d15a 3587 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3588
aac24838 3589 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3590 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3591}
3592
cc9f21da 3593static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3594{
d62a17ae 3595 struct peer *peer;
0a486e5f 3596
d62a17ae 3597 peer = THREAD_ARG(thread);
3598 peer->t_pmax_restart = NULL;
0a486e5f 3599
d62a17ae 3600 if (bgp_debug_neighbor_events(peer))
3601 zlog_debug(
3602 "%s Maximum-prefix restart timer expired, restore peering",
3603 peer->host);
0a486e5f 3604
a9bafa95 3605 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3606 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3607}
3608
9cbd06e0
DA
3609static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3610 safi_t safi)
3611{
3612 uint32_t count = 0;
f41b0459 3613 bool filtered = false;
9cbd06e0
DA
3614 struct bgp_dest *dest;
3615 struct bgp_adj_in *ain;
40bb2ccf 3616 struct attr attr = {};
9cbd06e0
DA
3617 struct bgp_table *table = peer->bgp->rib[afi][safi];
3618
3619 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3620 for (ain = dest->adj_in; ain; ain = ain->next) {
3621 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3622
3623 attr = *ain->attr;
9cbd06e0
DA
3624
3625 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3626 == FILTER_DENY)
f41b0459
DA
3627 filtered = true;
3628
3629 if (bgp_input_modifier(
3630 peer, rn_p, &attr, afi, safi,
3631 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3632 NULL, 0, NULL)
3633 == RMAP_DENY)
3634 filtered = true;
3635
3636 if (filtered)
9cbd06e0 3637 count++;
f41b0459 3638
d498917e 3639 bgp_attr_flush(&attr);
9cbd06e0
DA
3640 }
3641 }
3642
3643 return count;
3644}
3645
3dc339cd
DA
3646bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3647 int always)
718e3744 3648{
d62a17ae 3649 iana_afi_t pkt_afi;
5c525538 3650 iana_safi_t pkt_safi;
9cbd06e0
DA
3651 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3652 PEER_FLAG_MAX_PREFIX_FORCE))
3653 ? bgp_filtered_routes_count(peer, afi, safi)
3654 + peer->pcount[afi][safi]
3655 : peer->pcount[afi][safi];
9cabb64b 3656
d62a17ae 3657 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3658 return false;
e0701b79 3659
9cbd06e0 3660 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3661 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3662 PEER_STATUS_PREFIX_LIMIT)
3663 && !always)
3dc339cd 3664 return false;
e0701b79 3665
d62a17ae 3666 zlog_info(
f70c91dc
DA
3667 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3668 get_afi_safi_str(afi, safi, false), peer, pcount,
3669 peer->pmax[afi][safi]);
d62a17ae 3670 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3671
3672 if (CHECK_FLAG(peer->af_flags[afi][safi],
3673 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3674 return false;
d62a17ae 3675
3676 /* Convert AFI, SAFI to values for packet. */
3677 pkt_afi = afi_int2iana(afi);
3678 pkt_safi = safi_int2iana(safi);
3679 {
d7c0a89a 3680 uint8_t ndata[7];
d62a17ae 3681
3682 ndata[0] = (pkt_afi >> 8);
3683 ndata[1] = pkt_afi;
3684 ndata[2] = pkt_safi;
3685 ndata[3] = (peer->pmax[afi][safi] >> 24);
3686 ndata[4] = (peer->pmax[afi][safi] >> 16);
3687 ndata[5] = (peer->pmax[afi][safi] >> 8);
3688 ndata[6] = (peer->pmax[afi][safi]);
3689
3690 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3691 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3692 BGP_NOTIFY_CEASE_MAX_PREFIX,
3693 ndata, 7);
3694 }
3695
3696 /* Dynamic peers will just close their connection. */
3697 if (peer_dynamic_neighbor(peer))
3dc339cd 3698 return true;
d62a17ae 3699
3700 /* restart timer start */
3701 if (peer->pmax_restart[afi][safi]) {
3702 peer->v_pmax_restart =
3703 peer->pmax_restart[afi][safi] * 60;
3704
3705 if (bgp_debug_neighbor_events(peer))
3706 zlog_debug(
f70c91dc
DA
3707 "%pBP Maximum-prefix restart timer started for %d secs",
3708 peer, peer->v_pmax_restart);
d62a17ae 3709
3710 BGP_TIMER_ON(peer->t_pmax_restart,
3711 bgp_maximum_prefix_restart_timer,
3712 peer->v_pmax_restart);
3713 }
3714
3dc339cd 3715 return true;
d62a17ae 3716 } else
3717 UNSET_FLAG(peer->af_sflags[afi][safi],
3718 PEER_STATUS_PREFIX_LIMIT);
3719
b1823b69
DS
3720 if (pcount
3721 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3722 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3723 PEER_STATUS_PREFIX_THRESHOLD)
3724 && !always)
3dc339cd 3725 return false;
d62a17ae 3726
3727 zlog_info(
f70c91dc
DA
3728 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3729 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3730 peer->pmax[afi][safi]);
d62a17ae 3731 SET_FLAG(peer->af_sflags[afi][safi],
3732 PEER_STATUS_PREFIX_THRESHOLD);
3733 } else
3734 UNSET_FLAG(peer->af_sflags[afi][safi],
3735 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3736 return false;
718e3744 3737}
3738
b40d939b 3739/* Unconditionally remove the route from the RIB, without taking
3740 * damping into consideration (eg, because the session went down)
3741 */
9bcb3eef 3742void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3743 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3744{
f009ff26 3745
3746 struct bgp *bgp = NULL;
3747 bool delete_route = false;
3748
9bcb3eef
DS
3749 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3750 safi);
d62a17ae 3751
f009ff26 3752 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3753 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3754
f009ff26 3755 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3756 * flag
3757 */
3758 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3759 delete_route = true;
9bcb3eef 3760 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3761 delete_route = true;
f009ff26 3762 if (delete_route) {
9bcb3eef
DS
3763 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3764 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3765 bgp = pi->peer->bgp;
26742171 3766 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3767 }
3768 }
3769 }
4a11bf2c 3770
9bcb3eef
DS
3771 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3772 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3773}
3774
9bcb3eef 3775static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3776 struct peer *peer, afi_t afi, safi_t safi,
3777 struct prefix_rd *prd)
3778{
9bcb3eef 3779 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3780
d62a17ae 3781 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3782 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3783 */
b4f7f45b
IR
3784 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3785 && peer->sort == BGP_PEER_EBGP)
3786 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3787 == BGP_DAMP_SUPPRESSED) {
3788 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3789 safi);
3790 return;
d62a17ae 3791 }
3792
49e5a4a0 3793#ifdef ENABLE_BGP_VNC
d62a17ae 3794 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3795 struct bgp_dest *pdest = NULL;
d62a17ae 3796 struct bgp_table *table = NULL;
3797
9bcb3eef
DS
3798 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3799 (struct prefix *)prd);
3800 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3801 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3802
3803 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3804 peer->bgp, prd, table, p, pi);
d62a17ae 3805 }
9bcb3eef 3806 bgp_dest_unlock_node(pdest);
d62a17ae 3807 }
3808 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3809 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3810
b54892e0
DS
3811 vnc_import_bgp_del_route(peer->bgp, p, pi);
3812 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3813 }
65efcfce 3814 }
d62a17ae 3815#endif
128ea8ab 3816
d62a17ae 3817 /* If this is an EVPN route, process for un-import. */
3818 if (safi == SAFI_EVPN)
b54892e0 3819 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3820
9bcb3eef 3821 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3822}
3823
4b7e6066
DS
3824struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3825 struct peer *peer, struct attr *attr,
9bcb3eef 3826 struct bgp_dest *dest)
fb018d25 3827{
4b7e6066 3828 struct bgp_path_info *new;
fb018d25 3829
d62a17ae 3830 /* Make new BGP info. */
4b7e6066 3831 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3832 new->type = type;
3833 new->instance = instance;
3834 new->sub_type = sub_type;
3835 new->peer = peer;
3836 new->attr = attr;
083ec940 3837 new->uptime = monotime(NULL);
9bcb3eef 3838 new->net = dest;
d62a17ae 3839 return new;
fb018d25
DS
3840}
3841
c265ee22 3842/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3843bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3844 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3845 struct bgp_dest *dest)
d62a17ae 3846{
2dbe3fa9 3847 bool ret = false;
b099a5c8
DA
3848 bool is_bgp_static_route =
3849 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3850 : false;
d62a17ae 3851
e8442016
DS
3852 /*
3853 * Only validated for unicast and multicast currently.
3854 * Also valid for EVPN where the nexthop is an IP address.
3855 * If we are a bgp static route being checked then there is
3856 * no need to check to see if the nexthop is martian as
3857 * that it should be ok.
3858 */
3859 if (is_bgp_static_route ||
3860 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3861 return false;
d62a17ae 3862
3863 /* If NEXT_HOP is present, validate it. */
3864 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3865 if (attr->nexthop.s_addr == INADDR_ANY ||
3866 !ipv4_unicast_valid(&attr->nexthop) ||
3867 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3868 return true;
d62a17ae 3869 }
c265ee22 3870
d62a17ae 3871 /* If MP_NEXTHOP is present, validate it. */
3872 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3873 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3874 * it is not an IPv6 link-local address.
0355b41d
DA
3875 *
3876 * If we receive an UPDATE with nexthop length set to 32 bytes
3877 * we shouldn't discard an UPDATE if it's set to (::).
3878 * The link-local (2st) is validated along the code path later.
d62a17ae 3879 */
3880 if (attr->mp_nexthop_len) {
3881 switch (attr->mp_nexthop_len) {
3882 case BGP_ATTR_NHLEN_IPV4:
3883 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3884 ret = (attr->mp_nexthop_global_in.s_addr ==
3885 INADDR_ANY ||
3886 !ipv4_unicast_valid(
3887 &attr->mp_nexthop_global_in) ||
3888 bgp_nexthop_self(bgp, afi, type, stype, attr,
3889 dest));
d62a17ae 3890 break;
3891
3892 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3893 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3894 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3895 &attr->mp_nexthop_global)
d62a17ae 3896 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3897 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3898 &attr->mp_nexthop_global)
3899 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3900 dest));
d62a17ae 3901 break;
0355b41d
DA
3902 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3903 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3904 || IN6_IS_ADDR_MULTICAST(
3905 &attr->mp_nexthop_global)
3906 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3907 dest));
0355b41d 3908 break;
d62a17ae 3909
3910 default:
3dc339cd 3911 ret = true;
d62a17ae 3912 break;
3913 }
3914 }
c265ee22 3915
d62a17ae 3916 return ret;
3917}
3918
aade37d7 3919static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3920{
3921 struct community *old;
3922 struct community *new;
3923 struct community *merge;
aade37d7 3924 struct community *no_export;
2721dd61 3925
9a706b42 3926 old = bgp_attr_get_community(attr);
aade37d7 3927 no_export = community_str2com("no-export");
2721dd61 3928
b4efa101
DA
3929 assert(no_export);
3930
2721dd61 3931 if (old) {
aade37d7 3932 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3933
3934 if (!old->refcnt)
3935 community_free(&old);
3936
3937 new = community_uniq_sort(merge);
3938 community_free(&merge);
3939 } else {
aade37d7 3940 new = community_dup(no_export);
2721dd61
DA
3941 }
3942
aade37d7 3943 community_free(&no_export);
2721dd61 3944
9a706b42 3945 bgp_attr_set_community(attr, new);
2721dd61
DA
3946}
3947
46dbf9d0
DA
3948static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3949 struct attr *attr, const struct prefix *prefix,
3950 int *sub_type)
3951{
3952 struct listnode *node, *nnode;
3953 struct bgp *bgp;
3954 bool accept_own_found = false;
3955
3956 if (safi != SAFI_MPLS_VPN)
3957 return false;
3958
3959 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3960 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3961 return false;
3962
3963 /* The route in question carries the ACCEPT_OWN community */
3964 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3965 struct community *comm = bgp_attr_get_community(attr);
3966
3967 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3968 accept_own_found = true;
3969 }
3970
3971 /* The route in question is targeted to one or more destination VRFs
3972 * on the router (as determined by inspecting the Route Target(s)).
3973 */
3974 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3975 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3976 continue;
3977
3978 if (accept_own_found &&
3979 ecommunity_include(
3980 bgp->vpn_policy[afi]
3981 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3982 bgp_attr_get_ecommunity(attr))) {
3983 if (bgp_debug_update(peer, prefix, NULL, 1))
3984 zlog_debug(
3985 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3986 peer, prefix);
3987
3988 /* Treat this route as imported, because it's leaked
3989 * already from another VRF, and we got an updated
3990 * version from route-reflector with ACCEPT_OWN
3991 * community.
3992 */
3993 *sub_type = BGP_ROUTE_IMPORTED;
3994
3995 return true;
3996 }
3997 }
3998
3999 return false;
4000}
4001
5a1ae2c2 4002int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4003 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4004 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4005 uint32_t num_labels, int soft_reconfig,
a4d82a8a 4006 struct bgp_route_evpn *evpn)
d62a17ae 4007{
4008 int ret;
4009 int aspath_loop_count = 0;
9bcb3eef 4010 struct bgp_dest *dest;
d62a17ae 4011 struct bgp *bgp;
4012 struct attr new_attr;
4013 struct attr *attr_new;
40381db7 4014 struct bgp_path_info *pi;
819e6767 4015 struct bgp_path_info *new = NULL;
4b7e6066 4016 struct bgp_path_info_extra *extra;
d62a17ae 4017 const char *reason;
4018 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4019 int connected = 0;
4020 int do_loop_check = 1;
4021 int has_valid_label = 0;
7c312383 4022 afi_t nh_afi;
9146341f 4023 bool force_evpn_import = false;
907707db 4024 safi_t orig_safi = safi;
a486300b 4025 bool leak_success = true;
b2ac1d0d 4026 int allowas_in = 0;
949b0f24 4027
c7bb4f00 4028 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4029 char pfxprint[PREFIX2STR_BUFFER];
4030
4031 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4032 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4033 afi, safi, attr);
6401252f
QY
4034 }
4035
49e5a4a0 4036#ifdef ENABLE_BGP_VNC
d62a17ae 4037 int vnc_implicit_withdraw = 0;
65efcfce 4038#endif
d62a17ae 4039 int same_attr = 0;
f8745525 4040 const struct prefix *bgp_nht_param_prefix;
718e3744 4041
907707db
MS
4042 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4043 if (orig_safi == SAFI_LABELED_UNICAST)
4044 safi = SAFI_UNICAST;
4045
6006b807 4046 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4047 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4048 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4049
d62a17ae 4050 bgp = peer->bgp;
9bcb3eef 4051 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4052 /* TODO: Check to see if we can get rid of "is_valid_label" */
4053 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4054 has_valid_label = (num_labels > 0) ? 1 : 0;
4055 else
4056 has_valid_label = bgp_is_valid_label(label);
718e3744 4057
28f66de2
MS
4058 if (has_valid_label)
4059 assert(label != NULL);
4060
66ff6089
AD
4061 /* Update overlay index of the attribute */
4062 if (afi == AFI_L2VPN && evpn)
4063 memcpy(&attr->evpn_overlay, evpn,
4064 sizeof(struct bgp_route_evpn));
4065
d62a17ae 4066 /* When peer's soft reconfiguration enabled. Record input packet in
4067 Adj-RIBs-In. */
4068 if (!soft_reconfig
4069 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4070 && peer != bgp->peer_self)
9bcb3eef 4071 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4072
b2ac1d0d
MS
4073 /* Update permitted loop count */
4074 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4075 allowas_in = peer->allowas_in[afi][safi];
4076
d62a17ae 4077 /* Check previously received route. */
9bcb3eef 4078 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4079 if (pi->peer == peer && pi->type == type
4080 && pi->sub_type == sub_type
4081 && pi->addpath_rx_id == addpath_id)
d62a17ae 4082 break;
4083
4084 /* AS path local-as loop check. */
4085 if (peer->change_local_as) {
b2ac1d0d
MS
4086 if (allowas_in)
4087 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4088 else if (!CHECK_FLAG(peer->flags,
4089 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4090 aspath_loop_count = 1;
4091
4092 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4093 > aspath_loop_count) {
b4d46cc9 4094 peer->stat_pfx_aspath_loop++;
692174a1 4095 reason = "as-path contains our own AS;";
d62a17ae 4096 goto filtered;
4097 }
718e3744 4098 }
718e3744 4099
d62a17ae 4100 /* If the peer is configured for "allowas-in origin" and the last ASN in
4101 * the
4102 * as-path is our ASN then we do not need to call aspath_loop_check
4103 */
4104 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4105 if (aspath_get_last_as(attr->aspath) == bgp->as)
4106 do_loop_check = 0;
4107
f8745525
PG
4108 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4109 bgp_nht_param_prefix = NULL;
4110 else
4111 bgp_nht_param_prefix = p;
4112
d62a17ae 4113 /* AS path loop check. */
4114 if (do_loop_check) {
b0a8f709
FD
4115 if (aspath_loop_check(attr->aspath, bgp->as) >
4116 peer->allowas_in[afi][safi]) {
b4d46cc9 4117 peer->stat_pfx_aspath_loop++;
d62a17ae 4118 reason = "as-path contains our own AS;";
4119 goto filtered;
4120 }
4121 }
aac9ef6c 4122
b0a8f709
FD
4123 /* If we're a CONFED we need to loop check the CONFED ID too */
4124 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4125 if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4126 peer->allowas_in[afi][safi]) {
4127 peer->stat_pfx_aspath_loop++;
4128 reason = "as-path contains our own confed AS;";
4129 goto filtered;
4130 }
4131
46dbf9d0
DA
4132 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4133 * enabled, then take care of that too.
4134 */
4135 bool accept_own = false;
4136
d62a17ae 4137 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4138 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4139 accept_own =
4140 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4141 if (!accept_own) {
4142 peer->stat_pfx_originator_loop++;
4143 reason = "originator is us;";
4144 goto filtered;
4145 }
d62a17ae 4146 }
718e3744 4147
d62a17ae 4148 /* Route reflector cluster ID check. */
4149 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4150 peer->stat_pfx_cluster_loop++;
d62a17ae 4151 reason = "reflected from the same cluster;";
4152 goto filtered;
4153 }
718e3744 4154
d62a17ae 4155 /* Apply incoming filter. */
907707db 4156 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4157 peer->stat_pfx_filter++;
d62a17ae 4158 reason = "filter;";
4159 goto filtered;
4160 }
718e3744 4161
a8b72dc6
DA
4162 /* RFC 8212 to prevent route leaks.
4163 * This specification intends to improve this situation by requiring the
4164 * explicit configuration of both BGP Import and Export Policies for any
4165 * External BGP (EBGP) session such as customers, peers, or
4166 * confederation boundaries for all enabled address families. Through
4167 * codification of the aforementioned requirement, operators will
4168 * benefit from consistent behavior across different BGP
4169 * implementations.
4170 */
1d3fdccf 4171 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4172 if (!bgp_inbound_policy_exists(peer,
4173 &peer->filter[afi][safi])) {
4174 reason = "inbound policy missing";
b17826b7
DS
4175 if (monotime_since(&bgp->ebgprequirespolicywarning,
4176 NULL) > FIFTEENMINUTE2USEC ||
4177 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4178 zlog_warn(
4179 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4180 monotime(&bgp->ebgprequirespolicywarning);
4181 }
a8b72dc6
DA
4182 goto filtered;
4183 }
4184
fb29348a
DA
4185 /* draft-ietf-idr-deprecate-as-set-confed-set
4186 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4187 * Eventually, This document (if approved) updates RFC 4271
4188 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4189 * and obsoletes RFC 6472.
4190 */
7f972cd8 4191 if (peer->bgp->reject_as_sets)
fb29348a
DA
4192 if (aspath_check_as_sets(attr->aspath)) {
4193 reason =
4194 "as-path contains AS_SET or AS_CONFED_SET type;";
4195 goto filtered;
4196 }
4197
6f4f49b2 4198 new_attr = *attr;
d62a17ae 4199
4200 /* Apply incoming route-map.
4201 * NB: new_attr may now contain newly allocated values from route-map
4202 * "set"
4203 * commands, so we need bgp_attr_flush in the error paths, until we
4204 * intern
4205 * the attr (which takes over the memory references) */
907707db 4206 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4207 num_labels, dest)
4208 == RMAP_DENY) {
b4d46cc9 4209 peer->stat_pfx_filter++;
d62a17ae 4210 reason = "route-map;";
4211 bgp_attr_flush(&new_attr);
4212 goto filtered;
4213 }
718e3744 4214
05864da7 4215 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4216 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4217 /* remove from RIB previous entry */
4218 bgp_zebra_withdraw(p, pi, bgp, safi);
4219 }
4220
7f323236
DW
4221 if (peer->sort == BGP_PEER_EBGP) {
4222
2721dd61
DA
4223 /* rfc7999:
4224 * A BGP speaker receiving an announcement tagged with the
4225 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4226 * NO_EXPORT community as defined in RFC1997, or a
4227 * similar community, to prevent propagation of the
4228 * prefix outside the local AS. The community to prevent
4229 * propagation SHOULD be chosen according to the operator's
4230 * routing policy.
4231 */
9a706b42
DA
4232 if (bgp_attr_get_community(&new_attr) &&
4233 community_include(bgp_attr_get_community(&new_attr),
4234 COMMUNITY_BLACKHOLE))
aade37d7 4235 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4236
a4d82a8a
PZ
4237 /* If we receive the graceful-shutdown community from an eBGP
4238 * peer we must lower local-preference */
9a706b42
DA
4239 if (bgp_attr_get_community(&new_attr) &&
4240 community_include(bgp_attr_get_community(&new_attr),
4241 COMMUNITY_GSHUT)) {
7f323236
DW
4242 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4243 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4244
4f770cf1
DA
4245 /* If graceful-shutdown is configured globally or
4246 * per neighbor, then add the GSHUT community to
4247 * all paths received from eBGP peers. */
4248 } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4249 CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
7f323236 4250 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4251 }
4252
d62a17ae 4253 /* next hop check. */
860ad3f9
DS
4254 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4255 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4256 &new_attr, dest)) {
b4d46cc9 4257 peer->stat_pfx_nh_invalid++;
d62a17ae 4258 reason = "martian or self next-hop;";
4259 bgp_attr_flush(&new_attr);
4260 goto filtered;
4261 }
718e3744 4262
5c14a191 4263 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4264 peer->stat_pfx_nh_invalid++;
4e802e66 4265 reason = "self mac;";
4dbf2038 4266 bgp_attr_flush(&new_attr);
4e802e66
DS
4267 goto filtered;
4268 }
4269
5a78f2bc
EB
4270 if (bgp_check_role_applicability(afi, safi) &&
4271 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4272 reason = "failing otc validation";
4273 bgp_attr_flush(&new_attr);
4274 goto filtered;
4275 }
a1b773e2
DS
4276 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4277 * condition :
4278 * Suppress fib is enabled
4279 * BGP_OPT_NO_FIB is not enabled
4280 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4281 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4282 */
4283 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4284 && (sub_type == BGP_ROUTE_NORMAL)
4285 && (!bgp_option_check(BGP_OPT_NO_FIB))
4286 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4287 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4288
01da2d26
DA
4289 /* If neighbor soo is configured, tag all incoming routes with
4290 * this SoO tag and then filter out advertisements in
4291 * subgroup_announce_check() if it matches the configured SoO
4292 * on the other peer.
4293 */
4294 if (peer->soo[afi][safi]) {
4295 struct ecommunity *old_ecomm =
4296 bgp_attr_get_ecommunity(&new_attr);
4297 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4298 struct ecommunity *new_ecomm;
4299
4300 if (old_ecomm) {
4301 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4302 ecomm_soo);
4303
4304 if (!old_ecomm->refcnt)
4305 ecommunity_free(&old_ecomm);
4306 } else {
4307 new_ecomm = ecommunity_dup(ecomm_soo);
4308 }
4309
4310 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4311 }
4312
4dbf2038 4313 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4314
d62a17ae 4315 /* If the update is implicit withdraw. */
40381db7 4316 if (pi) {
083ec940 4317 pi->uptime = monotime(NULL);
40381db7 4318 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4319
9bcb3eef 4320 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4321
d62a17ae 4322 /* Same attribute comes in. */
40381db7 4323 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4324 && same_attr
d62a17ae 4325 && (!has_valid_label
40381db7 4326 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4327 num_labels * sizeof(mpls_label_t))
66ff6089 4328 == 0)) {
b4f7f45b
IR
4329 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4330 BGP_CONFIG_DAMPENING)
d62a17ae 4331 && peer->sort == BGP_PEER_EBGP
40381db7 4332 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4333 if (bgp_debug_update(peer, p, NULL, 1)) {
4334 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4335 afi, safi, prd, p, label,
4336 num_labels, addpath_id ? 1 : 0,
66ff6089 4337 addpath_id, evpn, pfx_buf,
a4d82a8a 4338 sizeof(pfx_buf));
f70c91dc 4339 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4340 pfx_buf);
4341 }
4342
9bcb3eef 4343 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4344 != BGP_DAMP_SUPPRESSED) {
40381db7 4345 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4346 safi);
9bcb3eef 4347 bgp_process(bgp, dest, afi, safi);
d62a17ae 4348 }
4349 } else /* Duplicate - odd */
4350 {
4351 if (bgp_debug_update(peer, p, NULL, 1)) {
4352 if (!peer->rcvd_attr_printed) {
4353 zlog_debug(
f70c91dc
DA
4354 "%pBP rcvd UPDATE w/ attr: %s",
4355 peer,
d62a17ae 4356 peer->rcvd_attr_str);
4357 peer->rcvd_attr_printed = 1;
4358 }
4359
4360 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4361 afi, safi, prd, p, label,
4362 num_labels, addpath_id ? 1 : 0,
66ff6089 4363 addpath_id, evpn, pfx_buf,
a4d82a8a 4364 sizeof(pfx_buf));
d62a17ae 4365 zlog_debug(
f70c91dc
DA
4366 "%pBP rcvd %s...duplicate ignored",
4367 peer, pfx_buf);
d62a17ae 4368 }
4369
4370 /* graceful restart STALE flag unset. */
40381db7 4371 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4372 bgp_path_info_unset_flag(
9bcb3eef
DS
4373 dest, pi, BGP_PATH_STALE);
4374 bgp_dest_set_defer_flag(dest, false);
4375 bgp_process(bgp, dest, afi, safi);
d62a17ae 4376 }
4377 }
4378
9bcb3eef 4379 bgp_dest_unlock_node(dest);
d62a17ae 4380 bgp_attr_unintern(&attr_new);
4381
4382 return 0;
4383 }
718e3744 4384
d62a17ae 4385 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4386 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4387 if (bgp_debug_update(peer, p, NULL, 1)) {
4388 bgp_debug_rdpfxpath2str(
a4d82a8a 4389 afi, safi, prd, p, label, num_labels,
66ff6089 4390 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4391 pfx_buf, sizeof(pfx_buf));
d62a17ae 4392 zlog_debug(
f70c91dc
DA
4393 "%pBP rcvd %s, flapped quicker than processing",
4394 peer, pfx_buf);
d62a17ae 4395 }
4396
9bcb3eef 4397 bgp_path_info_restore(dest, pi);
9146341f 4398
4399 /*
4400 * If the BGP_PATH_REMOVED flag is set, then EVPN
4401 * routes would have been unimported already when a
4402 * prior BGP withdraw processing happened. Such routes
4403 * need to be imported again, so flag accordingly.
4404 */
4405 force_evpn_import = true;
d62a17ae 4406 }
718e3744 4407
d62a17ae 4408 /* Received Logging. */
4409 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4410 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4411 num_labels, addpath_id ? 1 : 0,
66ff6089 4412 addpath_id, evpn, pfx_buf,
a4d82a8a 4413 sizeof(pfx_buf));
f70c91dc 4414 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4415 }
718e3744 4416
d62a17ae 4417 /* graceful restart STALE flag unset. */
f009ff26 4418 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4419 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4420 bgp_dest_set_defer_flag(dest, false);
f009ff26 4421 }
d62a17ae 4422
4423 /* The attribute is changed. */
9bcb3eef 4424 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4425
4426 /* implicit withdraw, decrement aggregate and pcount here.
4427 * only if update is accepted, they'll increment below.
4428 */
40381db7 4429 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4430
4431 /* Update bgp route dampening information. */
b4f7f45b 4432 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4433 && peer->sort == BGP_PEER_EBGP) {
4434 /* This is implicit withdraw so we should update
b4f7f45b
IR
4435 dampening
4436 information. */
40381db7 4437 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4438 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4439 }
49e5a4a0 4440#ifdef ENABLE_BGP_VNC
d62a17ae 4441 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4442 struct bgp_dest *pdest = NULL;
d62a17ae 4443 struct bgp_table *table = NULL;
4444
9bcb3eef
DS
4445 pdest = bgp_node_get(bgp->rib[afi][safi],
4446 (struct prefix *)prd);
4447 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4448 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4449
4450 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4451 bgp, prd, table, p, pi);
d62a17ae 4452 }
9bcb3eef 4453 bgp_dest_unlock_node(pdest);
d62a17ae 4454 }
4455 if ((afi == AFI_IP || afi == AFI_IP6)
4456 && (safi == SAFI_UNICAST)) {
40381db7 4457 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4458 /*
4459 * Implicit withdraw case.
4460 */
4461 ++vnc_implicit_withdraw;
40381db7
DS
4462 vnc_import_bgp_del_route(bgp, p, pi);
4463 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4464 }
4465 }
65efcfce 4466#endif
128ea8ab 4467
d62a17ae 4468 /* Special handling for EVPN update of an existing route. If the
4469 * extended community attribute has changed, we need to
4470 * un-import
4471 * the route using its existing extended community. It will be
4472 * subsequently processed for import with the new extended
4473 * community.
4474 */
6f8c9c11
PR
4475 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4476 && !same_attr) {
40381db7 4477 if ((pi->attr->flag
d62a17ae 4478 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4479 && (attr_new->flag
4480 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4481 int cmp;
4482
b53e67a3
DA
4483 cmp = ecommunity_cmp(
4484 bgp_attr_get_ecommunity(pi->attr),
4485 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4486 if (!cmp) {
4487 if (bgp_debug_update(peer, p, NULL, 1))
4488 zlog_debug(
4489 "Change in EXT-COMM, existing %s new %s",
4490 ecommunity_str(
b53e67a3
DA
4491 bgp_attr_get_ecommunity(
4492 pi->attr)),
d62a17ae 4493 ecommunity_str(
b53e67a3
DA
4494 bgp_attr_get_ecommunity(
4495 attr_new)));
6f8c9c11
PR
4496 if (safi == SAFI_EVPN)
4497 bgp_evpn_unimport_route(
4498 bgp, afi, safi, p, pi);
4499 else /* SAFI_MPLS_VPN */
4500 vpn_leak_to_vrf_withdraw(bgp,
4501 pi);
d62a17ae 4502 }
4503 }
4504 }
718e3744 4505
d62a17ae 4506 /* Update to new attribute. */
40381db7
DS
4507 bgp_attr_unintern(&pi->attr);
4508 pi->attr = attr_new;
d62a17ae 4509
4510 /* Update MPLS label */
4511 if (has_valid_label) {
40381db7 4512 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4513 if (extra->label != label) {
4514 memcpy(&extra->label, label,
dbd587da 4515 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4516 extra->num_labels = num_labels;
4517 }
b57ba6d2
MK
4518 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4519 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4520 }
718e3744 4521
e496b420
HS
4522 /* Update SRv6 SID */
4523 if (attr->srv6_l3vpn) {
4524 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4525 if (sid_diff(&extra->sid[0].sid,
4526 &attr->srv6_l3vpn->sid)) {
4527 sid_copy(&extra->sid[0].sid,
e496b420
HS
4528 &attr->srv6_l3vpn->sid);
4529 extra->num_sids = 1;
cc8f05df 4530
16f3db2d
RS
4531 extra->sid[0].loc_block_len = 0;
4532 extra->sid[0].loc_node_len = 0;
4533 extra->sid[0].func_len = 0;
4534 extra->sid[0].arg_len = 0;
ea7cd161
RS
4535 extra->sid[0].transposition_len = 0;
4536 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4537
4538 if (attr->srv6_l3vpn->loc_block_len != 0) {
4539 extra->sid[0].loc_block_len =
4540 attr->srv6_l3vpn->loc_block_len;
4541 extra->sid[0].loc_node_len =
4542 attr->srv6_l3vpn->loc_node_len;
4543 extra->sid[0].func_len =
4544 attr->srv6_l3vpn->func_len;
4545 extra->sid[0].arg_len =
4546 attr->srv6_l3vpn->arg_len;
ea7cd161 4547 extra->sid[0].transposition_len =
cc8f05df 4548 attr->srv6_l3vpn
ea7cd161
RS
4549 ->transposition_len;
4550 extra->sid[0].transposition_offset =
cc8f05df 4551 attr->srv6_l3vpn
ea7cd161
RS
4552 ->transposition_offset;
4553 }
e496b420
HS
4554 }
4555 } else if (attr->srv6_vpn) {
4556 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4557 if (sid_diff(&extra->sid[0].sid,
4558 &attr->srv6_vpn->sid)) {
4559 sid_copy(&extra->sid[0].sid,
4560 &attr->srv6_vpn->sid);
e496b420
HS
4561 extra->num_sids = 1;
4562 }
4563 }
4564
49e5a4a0 4565#ifdef ENABLE_BGP_VNC
d62a17ae 4566 if ((afi == AFI_IP || afi == AFI_IP6)
4567 && (safi == SAFI_UNICAST)) {
4568 if (vnc_implicit_withdraw) {
4569 /*
4570 * Add back the route with its new attributes
4571 * (e.g., nexthop).
4572 * The route is still selected, until the route
4573 * selection
4574 * queued by bgp_process actually runs. We have
4575 * to make this
4576 * update to the VNC side immediately to avoid
4577 * racing against
4578 * configuration changes (e.g., route-map
4579 * changes) which
4580 * trigger re-importation of the entire RIB.
4581 */
40381db7
DS
4582 vnc_import_bgp_add_route(bgp, p, pi);
4583 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4584 }
4585 }
65efcfce
LB
4586#endif
4587
d62a17ae 4588 /* Update bgp route dampening information. */
b4f7f45b 4589 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4590 && peer->sort == BGP_PEER_EBGP) {
4591 /* Now we do normal update dampening. */
9bcb3eef 4592 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4593 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4594 bgp_dest_unlock_node(dest);
d62a17ae 4595 return 0;
4596 }
4597 }
128ea8ab 4598
d62a17ae 4599 /* Nexthop reachability check - for unicast and
4600 * labeled-unicast.. */
7c312383
AD
4601 if (((afi == AFI_IP || afi == AFI_IP6)
4602 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4603 || (safi == SAFI_EVPN &&
4604 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4605 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4606 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4607 && !CHECK_FLAG(peer->flags,
4608 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4609 && !CHECK_FLAG(bgp->flags,
4610 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4611 connected = 1;
4612 else
4613 connected = 0;
4614
960035b2
PZ
4615 struct bgp *bgp_nexthop = bgp;
4616
40381db7
DS
4617 if (pi->extra && pi->extra->bgp_orig)
4618 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4619
7c312383
AD
4620 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4621
4622 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4623 safi, pi, NULL, connected,
f8745525
PG
4624 bgp_nht_param_prefix) ||
4625 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4626 bgp_path_info_set_flag(dest, pi,
4627 BGP_PATH_VALID);
d62a17ae 4628 else {
4629 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4630 zlog_debug("%s(%pI4): NH unresolved",
4631 __func__,
4632 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4633 }
9bcb3eef 4634 bgp_path_info_unset_flag(dest, pi,
18ee8310 4635 BGP_PATH_VALID);
d62a17ae 4636 }
46dbf9d0
DA
4637 } else {
4638 if (accept_own)
4639 bgp_path_info_set_flag(dest, pi,
4640 BGP_PATH_ACCEPT_OWN);
4641
9bcb3eef 4642 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4643 }
d62a17ae 4644
49e5a4a0 4645#ifdef ENABLE_BGP_VNC
d62a17ae 4646 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4647 struct bgp_dest *pdest = NULL;
d62a17ae 4648 struct bgp_table *table = NULL;
4649
9bcb3eef
DS
4650 pdest = bgp_node_get(bgp->rib[afi][safi],
4651 (struct prefix *)prd);
4652 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4653 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4654
4655 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4656 bgp, prd, table, p, pi);
d62a17ae 4657 }
9bcb3eef 4658 bgp_dest_unlock_node(pdest);
d62a17ae 4659 }
4660#endif
718e3744 4661
d62a17ae 4662 /* If this is an EVPN route and some attribute has changed,
9146341f 4663 * or we are explicitly told to perform a route import, process
d62a17ae 4664 * route for import. If the extended community has changed, we
4665 * would
4666 * have done the un-import earlier and the import would result
4667 * in the
4668 * route getting injected into appropriate L2 VNIs. If it is
4669 * just
4670 * some other attribute change, the import will result in
4671 * updating
4672 * the attributes for the route in the VNI(s).
4673 */
9146341f 4674 if (safi == SAFI_EVPN &&
4675 (!same_attr || force_evpn_import) &&
7c312383 4676 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4677 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4678
4679 /* Process change. */
40381db7 4680 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4681
9bcb3eef
DS
4682 bgp_process(bgp, dest, afi, safi);
4683 bgp_dest_unlock_node(dest);
558d1fec 4684
ddb5b488
PZ
4685 if (SAFI_UNICAST == safi
4686 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4687 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4688
40381db7 4689 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4690 }
4691 if ((SAFI_MPLS_VPN == safi)
4692 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4693 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4694 }
4695
49e5a4a0 4696#ifdef ENABLE_BGP_VNC
d62a17ae 4697 if (SAFI_MPLS_VPN == safi) {
4698 mpls_label_t label_decoded = decode_label(label);
28070ee3 4699
d62a17ae 4700 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4701 type, sub_type, &label_decoded);
4702 }
4703 if (SAFI_ENCAP == safi) {
4704 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4705 type, sub_type, NULL);
4706 }
28070ee3 4707#endif
a486300b
PG
4708 if ((safi == SAFI_MPLS_VPN) &&
4709 !CHECK_FLAG(bgp->af_flags[afi][safi],
4710 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4711 !leak_success) {
4712 bgp_unlink_nexthop(pi);
4713 bgp_path_info_delete(dest, pi);
4714 }
d62a17ae 4715 return 0;
4716 } // End of implicit withdraw
718e3744 4717
d62a17ae 4718 /* Received Logging. */
4719 if (bgp_debug_update(peer, p, NULL, 1)) {
4720 if (!peer->rcvd_attr_printed) {
f70c91dc 4721 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4722 peer->rcvd_attr_str);
4723 peer->rcvd_attr_printed = 1;
4724 }
718e3744 4725
a4d82a8a 4726 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4727 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4728 pfx_buf, sizeof(pfx_buf));
f70c91dc 4729 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4730 }
718e3744 4731
d62a17ae 4732 /* Make new BGP info. */
9bcb3eef 4733 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4734
d62a17ae 4735 /* Update MPLS label */
4736 if (has_valid_label) {
18ee8310 4737 extra = bgp_path_info_extra_get(new);
8ba71050 4738 if (extra->label != label) {
dbd587da
QY
4739 memcpy(&extra->label, label,
4740 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4741 extra->num_labels = num_labels;
4742 }
b57ba6d2
MK
4743 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4744 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4745 }
718e3744 4746
e496b420
HS
4747 /* Update SRv6 SID */
4748 if (safi == SAFI_MPLS_VPN) {
4749 extra = bgp_path_info_extra_get(new);
4750 if (attr->srv6_l3vpn) {
16f3db2d 4751 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4752 extra->num_sids = 1;
cc8f05df 4753
16f3db2d
RS
4754 extra->sid[0].loc_block_len =
4755 attr->srv6_l3vpn->loc_block_len;
4756 extra->sid[0].loc_node_len =
4757 attr->srv6_l3vpn->loc_node_len;
4758 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4759 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4760 extra->sid[0].transposition_len =
4761 attr->srv6_l3vpn->transposition_len;
4762 extra->sid[0].transposition_offset =
4763 attr->srv6_l3vpn->transposition_offset;
e496b420 4764 } else if (attr->srv6_vpn) {
16f3db2d 4765 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4766 extra->num_sids = 1;
4767 }
4768 }
4769
d62a17ae 4770 /* Nexthop reachability check. */
7c312383
AD
4771 if (((afi == AFI_IP || afi == AFI_IP6)
4772 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4773 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4774 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4775 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4776 && !CHECK_FLAG(peer->flags,
4777 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4778 && !CHECK_FLAG(bgp->flags,
4779 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4780 connected = 1;
4781 else
4782 connected = 0;
4783
7c312383
AD
4784 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4785
4053e952 4786 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4787 connected, bgp_nht_param_prefix) ||
4788 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4789 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4790 else {
07380148
DA
4791 if (BGP_DEBUG(nht, NHT))
4792 zlog_debug("%s(%pI4): NH unresolved", __func__,
4793 &attr_new->nexthop);
9bcb3eef 4794 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4795 }
46dbf9d0
DA
4796 } else {
4797 if (accept_own)
4798 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4799
9bcb3eef 4800 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4801 }
a82478b9 4802
b381ed97
DA
4803 /* If maximum prefix count is configured and current prefix
4804 * count exeed it.
4805 */
4806 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4807 reason = "maximum-prefix overflow";
4808 bgp_attr_flush(&new_attr);
b381ed97
DA
4809 goto filtered;
4810 }
4811
d62a17ae 4812 /* Addpath ID */
4813 new->addpath_rx_id = addpath_id;
4814
4815 /* Increment prefix */
4816 bgp_aggregate_increment(bgp, p, new, afi, safi);
4817
4818 /* Register new BGP information. */
9bcb3eef 4819 bgp_path_info_add(dest, new);
d62a17ae 4820
4821 /* route_node_get lock */
9bcb3eef 4822 bgp_dest_unlock_node(dest);
558d1fec 4823
49e5a4a0 4824#ifdef ENABLE_BGP_VNC
d62a17ae 4825 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4826 struct bgp_dest *pdest = NULL;
d62a17ae 4827 struct bgp_table *table = NULL;
4828
9bcb3eef
DS
4829 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4830 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4831 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4832
4833 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4834 bgp, prd, table, p, new);
4835 }
9bcb3eef 4836 bgp_dest_unlock_node(pdest);
d62a17ae 4837 }
65efcfce
LB
4838#endif
4839
d62a17ae 4840 /* If this is an EVPN route, process for import. */
7c312383 4841 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4842 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4843
9bcb3eef 4844 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4845
d62a17ae 4846 /* Process change. */
9bcb3eef 4847 bgp_process(bgp, dest, afi, safi);
718e3744 4848
ddb5b488
PZ
4849 if (SAFI_UNICAST == safi
4850 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4851 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4852 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4853 }
4854 if ((SAFI_MPLS_VPN == safi)
4855 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4856 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4857 }
49e5a4a0 4858#ifdef ENABLE_BGP_VNC
d62a17ae 4859 if (SAFI_MPLS_VPN == safi) {
4860 mpls_label_t label_decoded = decode_label(label);
28070ee3 4861
d62a17ae 4862 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4863 sub_type, &label_decoded);
4864 }
4865 if (SAFI_ENCAP == safi) {
4866 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4867 sub_type, NULL);
4868 }
28070ee3 4869#endif
a486300b
PG
4870 if ((safi == SAFI_MPLS_VPN) &&
4871 !CHECK_FLAG(bgp->af_flags[afi][safi],
4872 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4873 !leak_success) {
4874 bgp_unlink_nexthop(new);
4875 bgp_path_info_delete(dest, new);
4876 }
28070ee3 4877
d62a17ae 4878 return 0;
718e3744 4879
d62a17ae 4880/* This BGP update is filtered. Log the reason then update BGP
4881 entry. */
4882filtered:
819e6767
DA
4883 if (new) {
4884 bgp_unlink_nexthop(new);
4885 bgp_path_info_delete(dest, new);
4886 bgp_path_info_extra_free(&new->extra);
4887 XFREE(MTYPE_BGP_ROUTE, new);
4888 }
4889
9bcb3eef 4890 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4891
d62a17ae 4892 if (bgp_debug_update(peer, p, NULL, 1)) {
4893 if (!peer->rcvd_attr_printed) {
f70c91dc 4894 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4895 peer->rcvd_attr_str);
4896 peer->rcvd_attr_printed = 1;
4897 }
718e3744 4898
a4d82a8a 4899 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4900 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4901 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4902 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4903 peer, pfx_buf, reason);
d62a17ae 4904 }
128ea8ab 4905
40381db7 4906 if (pi) {
d62a17ae 4907 /* If this is an EVPN route, un-import it as it is now filtered.
4908 */
4909 if (safi == SAFI_EVPN)
40381db7 4910 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4911
ddb5b488
PZ
4912 if (SAFI_UNICAST == safi
4913 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4914 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4915
40381db7 4916 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4917 }
4918 if ((SAFI_MPLS_VPN == safi)
4919 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4920
40381db7 4921 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4922 }
4923
9bcb3eef 4924 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4925 }
4926
9bcb3eef 4927 bgp_dest_unlock_node(dest);
558d1fec 4928
49e5a4a0 4929#ifdef ENABLE_BGP_VNC
d62a17ae 4930 /*
4931 * Filtered update is treated as an implicit withdrawal (see
4932 * bgp_rib_remove()
4933 * a few lines above)
4934 */
4935 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4936 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4937 0);
4938 }
97736e32
PZ
4939#endif
4940
d62a17ae 4941 return 0;
718e3744 4942}
4943
26a3ffd6 4944int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4945 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4946 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4947 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4948{
d62a17ae 4949 struct bgp *bgp;
4950 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4951 struct bgp_dest *dest;
40381db7 4952 struct bgp_path_info *pi;
718e3744 4953
49e5a4a0 4954#ifdef ENABLE_BGP_VNC
d62a17ae 4955 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4956 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4957 0);
4958 }
28070ee3
PZ
4959#endif
4960
d62a17ae 4961 bgp = peer->bgp;
4962
4963 /* Lookup node. */
9bcb3eef 4964 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4965
4966 /* If peer is soft reconfiguration enabled. Record input packet for
4967 * further calculation.
4968 *
4969 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4970 * routes that are filtered. This tanks out Quagga RS pretty badly due
4971 * to
4972 * the iteration over all RS clients.
4973 * Since we need to remove the entry from adj_in anyway, do that first
4974 * and
4975 * if there was no entry, we don't need to do anything more.
4976 */
4977 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4978 && peer != bgp->peer_self)
9bcb3eef 4979 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4980 peer->stat_pfx_dup_withdraw++;
4981
d62a17ae 4982 if (bgp_debug_update(peer, p, NULL, 1)) {
4983 bgp_debug_rdpfxpath2str(
a4d82a8a 4984 afi, safi, prd, p, label, num_labels,
6c995628
AD
4985 addpath_id ? 1 : 0, addpath_id, NULL,
4986 pfx_buf, sizeof(pfx_buf));
d62a17ae 4987 zlog_debug(
4988 "%s withdrawing route %s not in adj-in",
4989 peer->host, pfx_buf);
4990 }
9bcb3eef 4991 bgp_dest_unlock_node(dest);
d62a17ae 4992 return 0;
4993 }
cd808e74 4994
d62a17ae 4995 /* Lookup withdrawn route. */
9bcb3eef 4996 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4997 if (pi->peer == peer && pi->type == type
4998 && pi->sub_type == sub_type
4999 && pi->addpath_rx_id == addpath_id)
d62a17ae 5000 break;
5001
5002 /* Logging. */
5003 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5004 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5005 addpath_id ? 1 : 0, addpath_id, NULL,
5006 pfx_buf, sizeof(pfx_buf));
f70c91dc 5007 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 5008 pfx_buf);
5009 }
718e3744 5010
d62a17ae 5011 /* Withdraw specified route from routing table. */
40381db7 5012 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5013 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5014 if (SAFI_UNICAST == safi
5015 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5016 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5017 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5018 }
5019 if ((SAFI_MPLS_VPN == safi)
5020 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5021
40381db7 5022 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
5023 }
5024 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5025 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5026 addpath_id ? 1 : 0, addpath_id, NULL,
5027 pfx_buf, sizeof(pfx_buf));
d62a17ae 5028 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5029 }
718e3744 5030
d62a17ae 5031 /* Unlock bgp_node_get() lock. */
9bcb3eef 5032 bgp_dest_unlock_node(dest);
d62a17ae 5033
5034 return 0;
718e3744 5035}
6b0655a2 5036
d62a17ae 5037void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5038 int withdraw)
718e3744 5039{
d62a17ae 5040 struct update_subgroup *subgrp;
5041 subgrp = peer_subgroup(peer, afi, safi);
5042 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5043}
6182d65b 5044
718e3744 5045
3f9c7369
DS
5046/*
5047 * bgp_stop_announce_route_timer
5048 */
d62a17ae 5049void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5050{
d62a17ae 5051 if (!paf->t_announce_route)
5052 return;
5053
c3aaa89a 5054 THREAD_OFF(paf->t_announce_route);
718e3744 5055}
6b0655a2 5056
3f9c7369
DS
5057/*
5058 * bgp_announce_route_timer_expired
5059 *
5060 * Callback that is invoked when the route announcement timer for a
5061 * peer_af expires.
5062 */
cc9f21da 5063static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5064{
d62a17ae 5065 struct peer_af *paf;
5066 struct peer *peer;
558d1fec 5067
d62a17ae 5068 paf = THREAD_ARG(t);
5069 peer = paf->peer;
718e3744 5070
feb17238 5071 if (!peer_established(peer))
cc9f21da 5072 return;
3f9c7369 5073
d62a17ae 5074 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5075 return;
3f9c7369 5076
d62a17ae 5077 peer_af_announce_route(paf, 1);
c5aec50b
MK
5078
5079 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5080 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5081}
5082
3f9c7369
DS
5083/*
5084 * bgp_announce_route
5085 *
5086 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5087 *
5088 * if force is true we will force an update even if the update
5089 * limiting code is attempted to kick in.
3f9c7369 5090 */
e1a32ec1 5091void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5092{
5093 struct peer_af *paf;
5094 struct update_subgroup *subgrp;
5095
5096 paf = peer_af_find(peer, afi, safi);
5097 if (!paf)
5098 return;
5099 subgrp = PAF_SUBGRP(paf);
5100
5101 /*
5102 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5103 * or a refresh has already been triggered.
5104 */
5105 if (!subgrp || paf->t_announce_route)
5106 return;
5107
e1a32ec1
DS
5108 if (force)
5109 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5110
d62a17ae 5111 /*
5112 * Start a timer to stagger/delay the announce. This serves
5113 * two purposes - announcement can potentially be combined for
5114 * multiple peers and the announcement doesn't happen in the
5115 * vty context.
5116 */
5117 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5118 (subgrp->peer_count == 1)
5119 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5120 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5121 &paf->t_announce_route);
3f9c7369
DS
5122}
5123
5124/*
5125 * Announce routes from all AF tables to a peer.
5126 *
5127 * This should ONLY be called when there is a need to refresh the
5128 * routes to the peer based on a policy change for this peer alone
5129 * or a route refresh request received from the peer.
5130 * The operation will result in splitting the peer from its existing
5131 * subgroups and putting it in new subgroups.
5132 */
d62a17ae 5133void bgp_announce_route_all(struct peer *peer)
718e3744 5134{
d62a17ae 5135 afi_t afi;
5136 safi_t safi;
5137
05c7a1cc 5138 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5139 bgp_announce_route(peer, afi, safi, false);
718e3744 5140}
6b0655a2 5141
46aeabed
LS
5142/* Flag or unflag bgp_dest to determine whether it should be treated by
5143 * bgp_soft_reconfig_table_task.
5144 * Flag if flag is true. Unflag if flag is false.
5145 */
5146static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5147{
5148 struct bgp_dest *dest;
5149 struct bgp_adj_in *ain;
5150
5151 if (!table)
5152 return;
5153
5154 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5155 for (ain = dest->adj_in; ain; ain = ain->next) {
5156 if (ain->peer != NULL)
5157 break;
5158 }
5159 if (flag && ain != NULL && ain->peer != NULL)
5160 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5161 else
5162 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5163 }
5164}
5165
5166static int bgp_soft_reconfig_table_update(struct peer *peer,
5167 struct bgp_dest *dest,
5168 struct bgp_adj_in *ain, afi_t afi,
5169 safi_t safi, struct prefix_rd *prd)
5170{
5171 struct bgp_path_info *pi;
5172 uint32_t num_labels = 0;
5173 mpls_label_t *label_pnt = NULL;
5174 struct bgp_route_evpn evpn;
5175
5176 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5177 if (pi->peer == peer)
5178 break;
5179
5180 if (pi && pi->extra)
5181 num_labels = pi->extra->num_labels;
5182 if (num_labels)
5183 label_pnt = &pi->extra->label[0];
5184 if (pi)
5185 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5186 sizeof(evpn));
5187 else
5188 memset(&evpn, 0, sizeof(evpn));
5189
5190 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5191 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
5192 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
5193 &evpn);
5194}
5195
d62a17ae 5196static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5197 struct bgp_table *table,
5198 struct prefix_rd *prd)
718e3744 5199{
d62a17ae 5200 int ret;
9bcb3eef 5201 struct bgp_dest *dest;
d62a17ae 5202 struct bgp_adj_in *ain;
718e3744 5203
d62a17ae 5204 if (!table)
5205 table = peer->bgp->rib[afi][safi];
718e3744 5206
9bcb3eef
DS
5207 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5208 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5209 if (ain->peer != peer)
5210 continue;
8692c506 5211
46aeabed
LS
5212 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5213 afi, safi, prd);
ea47320b
DL
5214
5215 if (ret < 0) {
9bcb3eef 5216 bgp_dest_unlock_node(dest);
ea47320b 5217 return;
d62a17ae 5218 }
5219 }
718e3744 5220}
5221
46aeabed
LS
5222/* Do soft reconfig table per bgp table.
5223 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5224 * when BGP_NODE_SOFT_RECONFIG is set,
5225 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5226 * Schedule a new thread to continue the job.
5227 * Without splitting the full job into several part,
5228 * vtysh waits for the job to finish before responding to a BGP command
5229 */
cc9f21da 5230static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5231{
5232 uint32_t iter, max_iter;
5233 int ret;
5234 struct bgp_dest *dest;
5235 struct bgp_adj_in *ain;
5236 struct peer *peer;
5237 struct bgp_table *table;
5238 struct prefix_rd *prd;
5239 struct listnode *node, *nnode;
5240
5241 table = THREAD_ARG(thread);
5242 prd = NULL;
5243
5244 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5245 if (table->soft_reconfig_init) {
5246 /* first call of the function with a new srta structure.
5247 * Don't do any treatment this time on nodes
5248 * in order vtysh to respond quickly
5249 */
5250 max_iter = 0;
5251 }
5252
5253 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5254 dest = bgp_route_next(dest)) {
5255 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5256 continue;
5257
5258 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5259
5260 for (ain = dest->adj_in; ain; ain = ain->next) {
5261 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5262 nnode, peer)) {
5263 if (ain->peer != peer)
5264 continue;
5265
5266 ret = bgp_soft_reconfig_table_update(
5267 peer, dest, ain, table->afi,
5268 table->safi, prd);
5269 iter++;
5270
5271 if (ret < 0) {
5272 bgp_dest_unlock_node(dest);
5273 listnode_delete(
5274 table->soft_reconfig_peers,
5275 peer);
5276 bgp_announce_route(peer, table->afi,
e1a32ec1 5277 table->safi, false);
46aeabed
LS
5278 if (list_isempty(
5279 table->soft_reconfig_peers)) {
5280 list_delete(
5281 &table->soft_reconfig_peers);
5282 bgp_soft_reconfig_table_flag(
5283 table, false);
cc9f21da 5284 return;
46aeabed
LS
5285 }
5286 }
5287 }
5288 }
5289 }
5290
5291 /* we're either starting the initial iteration,
5292 * or we're going to continue an ongoing iteration
5293 */
5294 if (dest || table->soft_reconfig_init) {
5295 table->soft_reconfig_init = false;
5296 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5297 table, 0, &table->soft_reconfig_thread);
cc9f21da 5298 return;
46aeabed
LS
5299 }
5300 /* we're done, clean up the background iteration context info and
5301 schedule route annoucement
5302 */
5303 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5304 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5305 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5306 }
5307
5308 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5309}
5310
5311
5312/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5313 * and peer.
5314 * - bgp cannot be NULL
5315 * - if table and peer are NULL, cancel all threads within the bgp instance
5316 * - if table is NULL and peer is not,
5317 * remove peer in all threads within the bgp instance
5318 * - if peer is NULL, cancel all threads matching table within the bgp instance
5319 */
5320void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5321 const struct bgp_table *table,
5322 const struct peer *peer)
5323{
5324 struct peer *npeer;
5325 struct listnode *node, *nnode;
5326 int afi, safi;
5327 struct bgp_table *ntable;
5328
5329 if (!bgp)
5330 return;
5331
5332 FOREACH_AFI_SAFI (afi, safi) {
5333 ntable = bgp->rib[afi][safi];
5334 if (!ntable)
5335 continue;
5336 if (table && table != ntable)
5337 continue;
5338
5339 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5340 npeer)) {
5341 if (peer && peer != npeer)
5342 continue;
5343 listnode_delete(ntable->soft_reconfig_peers, npeer);
5344 }
5345
5346 if (!ntable->soft_reconfig_peers
5347 || !list_isempty(ntable->soft_reconfig_peers))
5348 continue;
5349
5350 list_delete(&ntable->soft_reconfig_peers);
5351 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5352 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5353 }
5354}
5355
89c73443
DS
5356/*
5357 * Returns false if the peer is not configured for soft reconfig in
5358 */
5359bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5360{
9bcb3eef 5361 struct bgp_dest *dest;
d62a17ae 5362 struct bgp_table *table;
46aeabed
LS
5363 struct listnode *node, *nnode;
5364 struct peer *npeer;
5365 struct peer_af *paf;
718e3744 5366
89c73443
DS
5367 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5368 return false;
718e3744 5369
d62a17ae 5370 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5371 && (safi != SAFI_EVPN)) {
5372 table = peer->bgp->rib[afi][safi];
5373 if (!table)
89c73443 5374 return true;
46aeabed
LS
5375
5376 table->soft_reconfig_init = true;
5377
5378 if (!table->soft_reconfig_peers)
5379 table->soft_reconfig_peers = list_new();
5380 npeer = NULL;
5381 /* add peer to the table soft_reconfig_peers if not already
5382 * there
5383 */
5384 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5385 npeer)) {
5386 if (peer == npeer)
5387 break;
5388 }
5389 if (peer != npeer)
5390 listnode_add(table->soft_reconfig_peers, peer);
5391
5392 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5393 * on table would start back at the beginning.
5394 */
5395 bgp_soft_reconfig_table_flag(table, true);
5396
5397 if (!table->soft_reconfig_thread)
5398 thread_add_event(bm->master,
5399 bgp_soft_reconfig_table_task, table, 0,
5400 &table->soft_reconfig_thread);
5401 /* Cancel bgp_announce_route_timer_expired threads.
5402 * bgp_announce_route_timer_expired threads have been scheduled
5403 * to announce routes as soon as the soft_reconfigure process
5404 * finishes.
5405 * In this case, soft_reconfigure is also scheduled by using
5406 * a thread but is planned after the
5407 * bgp_announce_route_timer_expired threads. It means that,
5408 * without cancelling the threads, the route announcement task
5409 * would run before the soft reconfiguration one. That would
5410 * useless and would block vtysh during several seconds. Route
5411 * announcements are rescheduled as soon as the soft_reconfigure
5412 * process finishes.
5413 */
5414 paf = peer_af_find(peer, afi, safi);
5415 if (paf)
5416 bgp_stop_announce_route_timer(paf);
5417 } else
9bcb3eef
DS
5418 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5419 dest = bgp_route_next(dest)) {
5420 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5421
b54892e0
DS
5422 if (table == NULL)
5423 continue;
8692c506 5424
9bcb3eef 5425 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5426 struct prefix_rd prd;
5427
5428 prd.family = AF_UNSPEC;
5429 prd.prefixlen = 64;
5430 memcpy(&prd.val, p->u.val, 8);
5431
5432 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5433 }
89c73443
DS
5434
5435 return true;
718e3744 5436}
6b0655a2 5437
228da428 5438
d62a17ae 5439struct bgp_clear_node_queue {
9bcb3eef 5440 struct bgp_dest *dest;
228da428
CC
5441};
5442
d62a17ae 5443static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5444{
d62a17ae 5445 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5446 struct bgp_dest *dest = cnq->dest;
d62a17ae 5447 struct peer *peer = wq->spec.data;
40381db7 5448 struct bgp_path_info *pi;
3103e8d2 5449 struct bgp *bgp;
9bcb3eef
DS
5450 afi_t afi = bgp_dest_table(dest)->afi;
5451 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5452
9bcb3eef 5453 assert(dest && peer);
3103e8d2 5454 bgp = peer->bgp;
d62a17ae 5455
5456 /* It is possible that we have multiple paths for a prefix from a peer
5457 * if that peer is using AddPath.
5458 */
9bcb3eef 5459 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5460 if (pi->peer != peer)
ea47320b
DL
5461 continue;
5462
5463 /* graceful restart STALE flag set. */
9af52ccf
DA
5464 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5465 && peer->nsf[afi][safi])
5466 || CHECK_FLAG(peer->af_sflags[afi][safi],
5467 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5468 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5469 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5470 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5471 else {
5472 /* If this is an EVPN route, process for
5473 * un-import. */
5474 if (safi == SAFI_EVPN)
9bcb3eef
DS
5475 bgp_evpn_unimport_route(
5476 bgp, afi, safi,
5477 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5478 /* Handle withdraw for VRF route-leaking and L3VPN */
5479 if (SAFI_UNICAST == safi
5480 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5481 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5482 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5483 bgp, pi);
960035b2 5484 }
3103e8d2 5485 if (SAFI_MPLS_VPN == safi &&
960035b2 5486 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5487 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5488 }
3103e8d2 5489
9bcb3eef 5490 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5491 }
ea47320b 5492 }
d62a17ae 5493 return WQ_SUCCESS;
200df115 5494}
5495
d62a17ae 5496static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5497{
d62a17ae 5498 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5499 struct bgp_dest *dest = cnq->dest;
5500 struct bgp_table *table = bgp_dest_table(dest);
228da428 5501
9bcb3eef 5502 bgp_dest_unlock_node(dest);
d62a17ae 5503 bgp_table_unlock(table);
5504 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5505}
5506
d62a17ae 5507static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5508{
d62a17ae 5509 struct peer *peer = wq->spec.data;
64e580a7 5510
d62a17ae 5511 /* Tickle FSM to start moving again */
5512 BGP_EVENT_ADD(peer, Clearing_Completed);
5513
5514 peer_unlock(peer); /* bgp_clear_route */
200df115 5515}
718e3744 5516
d62a17ae 5517static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5518{
d62a17ae 5519 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5520
5521 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5522#undef CLEAR_QUEUE_NAME_LEN
5523
0ce1ca80 5524 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5525 peer->clear_node_queue->spec.hold = 10;
5526 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5527 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5528 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5529 peer->clear_node_queue->spec.max_retries = 0;
5530
5531 /* we only 'lock' this peer reference when the queue is actually active
5532 */
5533 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5534}
5535
d62a17ae 5536static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5537 struct bgp_table *table)
65ca75e0 5538{
9bcb3eef 5539 struct bgp_dest *dest;
b6c386bb 5540 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5541
d62a17ae 5542 if (!table)
5543 table = peer->bgp->rib[afi][safi];
dc83d712 5544
d62a17ae 5545 /* If still no table => afi/safi isn't configured at all or smth. */
5546 if (!table)
5547 return;
dc83d712 5548
9bcb3eef 5549 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5550 struct bgp_path_info *pi, *next;
d62a17ae 5551 struct bgp_adj_in *ain;
5552 struct bgp_adj_in *ain_next;
5553
5554 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5555 * queued for every clearing peer, regardless of whether it is
5556 * relevant to the peer at hand.
5557 *
5558 * Overview: There are 3 different indices which need to be
5559 * scrubbed, potentially, when a peer is removed:
5560 *
5561 * 1 peer's routes visible via the RIB (ie accepted routes)
5562 * 2 peer's routes visible by the (optional) peer's adj-in index
5563 * 3 other routes visible by the peer's adj-out index
5564 *
5565 * 3 there is no hurry in scrubbing, once the struct peer is
5566 * removed from bgp->peer, we could just GC such deleted peer's
5567 * adj-outs at our leisure.
5568 *
5569 * 1 and 2 must be 'scrubbed' in some way, at least made
5570 * invisible via RIB index before peer session is allowed to be
5571 * brought back up. So one needs to know when such a 'search' is
5572 * complete.
5573 *
5574 * Ideally:
5575 *
5576 * - there'd be a single global queue or a single RIB walker
5577 * - rather than tracking which route_nodes still need to be
5578 * examined on a peer basis, we'd track which peers still
5579 * aren't cleared
5580 *
5581 * Given that our per-peer prefix-counts now should be reliable,
5582 * this may actually be achievable. It doesn't seem to be a huge
5583 * problem at this time,
5584 *
5585 * It is possible that we have multiple paths for a prefix from
5586 * a peer
5587 * if that peer is using AddPath.
5588 */
9bcb3eef 5589 ain = dest->adj_in;
d62a17ae 5590 while (ain) {
5591 ain_next = ain->next;
5592
6a840fd9 5593 if (ain->peer == peer)
9bcb3eef 5594 bgp_adj_in_remove(dest, ain);
d62a17ae 5595
5596 ain = ain_next;
5597 }
5598
9bcb3eef 5599 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5600 next = pi->next;
5601 if (pi->peer != peer)
d62a17ae 5602 continue;
5603
5604 if (force)
9bcb3eef 5605 bgp_path_info_reap(dest, pi);
d62a17ae 5606 else {
5607 struct bgp_clear_node_queue *cnq;
5608
5609 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5610 bgp_table_lock(bgp_dest_table(dest));
5611 bgp_dest_lock_node(dest);
d62a17ae 5612 cnq = XCALLOC(
5613 MTYPE_BGP_CLEAR_NODE_QUEUE,
5614 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5615 cnq->dest = dest;
d62a17ae 5616 work_queue_add(peer->clear_node_queue, cnq);
5617 break;
5618 }
5619 }
5620 }
5621 return;
5622}
5623
5624void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5625{
9bcb3eef 5626 struct bgp_dest *dest;
d62a17ae 5627 struct bgp_table *table;
5628
5629 if (peer->clear_node_queue == NULL)
5630 bgp_clear_node_queue_init(peer);
5631
5632 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5633 * Idle until it receives a Clearing_Completed event. This protects
5634 * against peers which flap faster than we can we clear, which could
5635 * lead to:
5636 *
5637 * a) race with routes from the new session being installed before
5638 * clear_route_node visits the node (to delete the route of that
5639 * peer)
5640 * b) resource exhaustion, clear_route_node likely leads to an entry
5641 * on the process_main queue. Fast-flapping could cause that queue
5642 * to grow and grow.
5643 */
5644
5645 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5646 * the unlock will happen upon work-queue completion; other wise, the
5647 * unlock happens at the end of this function.
5648 */
5649 if (!peer->clear_node_queue->thread)
5650 peer_lock(peer);
5651
5652 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5653 bgp_clear_route_table(peer, afi, safi, NULL);
5654 else
9bcb3eef
DS
5655 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5656 dest = bgp_route_next(dest)) {
5657 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5658 if (!table)
5659 continue;
5660
5661 bgp_clear_route_table(peer, afi, safi, table);
5662 }
d62a17ae 5663
5664 /* unlock if no nodes got added to the clear-node-queue. */
5665 if (!peer->clear_node_queue->thread)
5666 peer_unlock(peer);
718e3744 5667}
d62a17ae 5668
5669void bgp_clear_route_all(struct peer *peer)
718e3744 5670{
d62a17ae 5671 afi_t afi;
5672 safi_t safi;
718e3744 5673
05c7a1cc
QY
5674 FOREACH_AFI_SAFI (afi, safi)
5675 bgp_clear_route(peer, afi, safi);
65efcfce 5676
49e5a4a0 5677#ifdef ENABLE_BGP_VNC
d62a17ae 5678 rfapiProcessPeerDown(peer);
65efcfce 5679#endif
718e3744 5680}
5681
d62a17ae 5682void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5683{
d62a17ae 5684 struct bgp_table *table;
9bcb3eef 5685 struct bgp_dest *dest;
d62a17ae 5686 struct bgp_adj_in *ain;
5687 struct bgp_adj_in *ain_next;
718e3744 5688
d62a17ae 5689 table = peer->bgp->rib[afi][safi];
718e3744 5690
d62a17ae 5691 /* It is possible that we have multiple paths for a prefix from a peer
5692 * if that peer is using AddPath.
5693 */
9bcb3eef
DS
5694 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5695 ain = dest->adj_in;
43143c8f 5696
d62a17ae 5697 while (ain) {
5698 ain_next = ain->next;
43143c8f 5699
6a840fd9 5700 if (ain->peer == peer)
9bcb3eef 5701 bgp_adj_in_remove(dest, ain);
43143c8f 5702
d62a17ae 5703 ain = ain_next;
5704 }
5705 }
718e3744 5706}
93406d87 5707
1479ed2f
DA
5708/* If any of the routes from the peer have been marked with the NO_LLGR
5709 * community, either as sent by the peer, or as the result of a configured
5710 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5711 * operation of [RFC4271].
5712 */
d62a17ae 5713void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5714{
9bcb3eef 5715 struct bgp_dest *dest;
40381db7 5716 struct bgp_path_info *pi;
d62a17ae 5717 struct bgp_table *table;
5718
9af52ccf 5719 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5720 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5721 dest = bgp_route_next(dest)) {
5722 struct bgp_dest *rm;
d62a17ae 5723
5724 /* look for neighbor in tables */
9bcb3eef 5725 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5726 if (!table)
ea47320b
DL
5727 continue;
5728
5729 for (rm = bgp_table_top(table); rm;
5730 rm = bgp_route_next(rm))
9bcb3eef 5731 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5732 pi = pi->next) {
40381db7 5733 if (pi->peer != peer)
ea47320b 5734 continue;
1479ed2f
DA
5735 if (CHECK_FLAG(
5736 peer->af_sflags[afi][safi],
5737 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5738 bgp_attr_get_community(pi->attr) &&
1479ed2f 5739 !community_include(
9a706b42
DA
5740 bgp_attr_get_community(
5741 pi->attr),
1479ed2f 5742 COMMUNITY_NO_LLGR))
e3015d91 5743 continue;
40381db7 5744 if (!CHECK_FLAG(pi->flags,
1defdda8 5745 BGP_PATH_STALE))
e3015d91 5746 continue;
ea47320b 5747
641065d4
KM
5748 /*
5749 * If this is VRF leaked route
5750 * process for withdraw.
5751 */
5752 if (pi->sub_type ==
5753 BGP_ROUTE_IMPORTED &&
5754 peer->bgp->inst_type ==
5755 BGP_INSTANCE_TYPE_DEFAULT)
5756 vpn_leak_to_vrf_withdraw(
5757 peer->bgp, pi);
5758
40381db7 5759 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5760 break;
5761 }
d62a17ae 5762 }
5763 } else {
9bcb3eef
DS
5764 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5765 dest = bgp_route_next(dest))
5766 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5767 pi = pi->next) {
40381db7 5768 if (pi->peer != peer)
ea47320b 5769 continue;
1479ed2f
DA
5770 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5771 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5772 bgp_attr_get_community(pi->attr) &&
5773 !community_include(
5774 bgp_attr_get_community(pi->attr),
5775 COMMUNITY_NO_LLGR))
e3015d91 5776 continue;
40381db7 5777 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5778 continue;
641065d4
KM
5779 if (safi == SAFI_UNICAST &&
5780 (peer->bgp->inst_type ==
5781 BGP_INSTANCE_TYPE_VRF ||
5782 peer->bgp->inst_type ==
5783 BGP_INSTANCE_TYPE_DEFAULT))
5784 vpn_leak_from_vrf_withdraw(
5785 bgp_get_default(), peer->bgp,
5786 pi);
5787
9bcb3eef 5788 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5789 break;
5790 }
d62a17ae 5791 }
93406d87 5792}
6b0655a2 5793
9af52ccf
DA
5794void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5795{
5796 struct bgp_dest *dest, *ndest;
5797 struct bgp_path_info *pi;
5798 struct bgp_table *table;
5799
5800 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5801 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5802 dest = bgp_route_next(dest)) {
5803 table = bgp_dest_get_bgp_table_info(dest);
5804 if (!table)
5805 continue;
5806
5807 for (ndest = bgp_table_top(table); ndest;
5808 ndest = bgp_route_next(ndest)) {
5809 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5810 pi = pi->next) {
5811 if (pi->peer != peer)
5812 continue;
5813
5814 if ((CHECK_FLAG(
5815 peer->af_sflags[afi][safi],
5816 PEER_STATUS_ENHANCED_REFRESH))
5817 && !CHECK_FLAG(pi->flags,
5818 BGP_PATH_STALE)
5819 && !CHECK_FLAG(
5820 pi->flags,
5821 BGP_PATH_UNUSEABLE)) {
5822 if (bgp_debug_neighbor_events(
5823 peer))
5824 zlog_debug(
58e111f6
DA
5825 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5826 peer,
9af52ccf
DA
5827 afi2str(afi),
5828 safi2str(safi),
5829 bgp_dest_get_prefix(
5830 ndest));
5831
5832 bgp_path_info_set_flag(
5833 ndest, pi,
5834 BGP_PATH_STALE);
5835 }
5836 }
5837 }
5838 }
5839 } else {
5840 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5841 dest = bgp_route_next(dest)) {
5842 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5843 pi = pi->next) {
5844 if (pi->peer != peer)
5845 continue;
5846
5847 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5848 PEER_STATUS_ENHANCED_REFRESH))
5849 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5850 && !CHECK_FLAG(pi->flags,
5851 BGP_PATH_UNUSEABLE)) {
5852 if (bgp_debug_neighbor_events(peer))
5853 zlog_debug(
58e111f6
DA
5854 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5855 peer, afi2str(afi),
9af52ccf
DA
5856 safi2str(safi),
5857 bgp_dest_get_prefix(
5858 dest));
5859
5860 bgp_path_info_set_flag(dest, pi,
5861 BGP_PATH_STALE);
5862 }
5863 }
5864 }
5865 }
5866}
5867
3dc339cd 5868bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5869{
e0df4c04 5870 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5871 return true;
e0df4c04 5872
9dac9fc8
DA
5873 if (peer->sort == BGP_PEER_EBGP
5874 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5875 || FILTER_LIST_OUT_NAME(filter)
5876 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5877 return true;
5878 return false;
9dac9fc8
DA
5879}
5880
3dc339cd 5881bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5882{
e0df4c04 5883 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5884 return true;
e0df4c04 5885
9dac9fc8
DA
5886 if (peer->sort == BGP_PEER_EBGP
5887 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5888 || FILTER_LIST_IN_NAME(filter)
5889 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5890 return true;
5891 return false;
9dac9fc8
DA
5892}
5893
568e10ca 5894static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5895 safi_t safi)
bb86c601 5896{
9bcb3eef 5897 struct bgp_dest *dest;
40381db7 5898 struct bgp_path_info *pi;
4b7e6066 5899 struct bgp_path_info *next;
bb86c601 5900
9bcb3eef
DS
5901 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5902 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5903 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5904
40381db7 5905 next = pi->next;
1b7bb747
CS
5906
5907 /* Unimport EVPN routes from VRFs */
5908 if (safi == SAFI_EVPN)
5909 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5910 SAFI_EVPN, p, pi);
1b7bb747 5911
40381db7
DS
5912 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5913 && pi->type == ZEBRA_ROUTE_BGP
5914 && (pi->sub_type == BGP_ROUTE_NORMAL
5915 || pi->sub_type == BGP_ROUTE_AGGREGATE
5916 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5917
d62a17ae 5918 if (bgp_fibupd_safi(safi))
b54892e0 5919 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5920 }
9514b37d 5921
9bcb3eef 5922 bgp_path_info_reap(dest, pi);
d62a17ae 5923 }
bb86c601
LB
5924}
5925
718e3744 5926/* Delete all kernel routes. */
d62a17ae 5927void bgp_cleanup_routes(struct bgp *bgp)
5928{
5929 afi_t afi;
9bcb3eef 5930 struct bgp_dest *dest;
67009e22 5931 struct bgp_table *table;
d62a17ae 5932
5933 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5934 if (afi == AFI_L2VPN)
5935 continue;
568e10ca 5936 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5937 SAFI_UNICAST);
d62a17ae 5938 /*
5939 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5940 */
5941 if (afi != AFI_L2VPN) {
5942 safi_t safi;
5943 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5944 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5945 dest = bgp_route_next(dest)) {
5946 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5947 if (table != NULL) {
5948 bgp_cleanup_table(bgp, table, safi);
5949 bgp_table_finish(&table);
9bcb3eef
DS
5950 bgp_dest_set_bgp_table_info(dest, NULL);
5951 bgp_dest_unlock_node(dest);
d62a17ae 5952 }
5953 }
5954 safi = SAFI_ENCAP;
9bcb3eef
DS
5955 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5956 dest = bgp_route_next(dest)) {
5957 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5958 if (table != NULL) {
5959 bgp_cleanup_table(bgp, table, safi);
5960 bgp_table_finish(&table);
9bcb3eef
DS
5961 bgp_dest_set_bgp_table_info(dest, NULL);
5962 bgp_dest_unlock_node(dest);
d62a17ae 5963 }
5964 }
5965 }
5966 }
9bcb3eef
DS
5967 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5968 dest = bgp_route_next(dest)) {
5969 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5970 if (table != NULL) {
5971 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5972 bgp_table_finish(&table);
9bcb3eef
DS
5973 bgp_dest_set_bgp_table_info(dest, NULL);
5974 bgp_dest_unlock_node(dest);
d62a17ae 5975 }
bb86c601 5976 }
718e3744 5977}
5978
d62a17ae 5979void bgp_reset(void)
718e3744 5980{
d62a17ae 5981 vty_reset();
5982 bgp_zclient_reset();
5983 access_list_reset();
5984 prefix_list_reset();
718e3744 5985}
6b0655a2 5986
be92fc9f 5987bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5988{
d62a17ae 5989 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5990 && CHECK_FLAG(peer->af_cap[afi][safi],
5991 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5992}
5993
718e3744 5994/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5995 value. */
d62a17ae 5996int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5997 struct bgp_nlri *packet)
5998{
d7c0a89a
QY
5999 uint8_t *pnt;
6000 uint8_t *lim;
d62a17ae 6001 struct prefix p;
6002 int psize;
6003 int ret;
6004 afi_t afi;
6005 safi_t safi;
be92fc9f 6006 bool addpath_capable;
d7c0a89a 6007 uint32_t addpath_id;
d62a17ae 6008
d62a17ae 6009 pnt = packet->nlri;
6010 lim = pnt + packet->length;
6011 afi = packet->afi;
6012 safi = packet->safi;
6013 addpath_id = 0;
be92fc9f 6014 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 6015
6016 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6017 syntactic validity. If the field is syntactically incorrect,
6018 then the Error Subcode is set to Invalid Network Field. */
6019 for (; pnt < lim; pnt += psize) {
6020 /* Clear prefix structure. */
6006b807 6021 memset(&p, 0, sizeof(p));
d62a17ae 6022
be92fc9f 6023 if (addpath_capable) {
d62a17ae 6024
6025 /* When packet overflow occurs return immediately. */
761ed665 6026 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6027 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6028
a3a850a1 6029 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6030 addpath_id = ntohl(addpath_id);
d62a17ae 6031 pnt += BGP_ADDPATH_ID_LEN;
6032 }
718e3744 6033
d62a17ae 6034 /* Fetch prefix length. */
6035 p.prefixlen = *pnt++;
6036 /* afi/safi validity already verified by caller,
6037 * bgp_update_receive */
6038 p.family = afi2family(afi);
6039
6040 /* Prefix length check. */
6041 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6042 flog_err(
e50f7cfd 6043 EC_BGP_UPDATE_RCV,
14454c9f 6044 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6045 peer->host, p.prefixlen, packet->afi);
513386b5 6046 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6047 }
6b0655a2 6048
d62a17ae 6049 /* Packet size overflow check. */
6050 psize = PSIZE(p.prefixlen);
6051
6052 /* When packet overflow occur return immediately. */
6053 if (pnt + psize > lim) {
af4c2728 6054 flog_err(
e50f7cfd 6055 EC_BGP_UPDATE_RCV,
d62a17ae 6056 "%s [Error] Update packet error (prefix length %d overflows packet)",
6057 peer->host, p.prefixlen);
513386b5 6058 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6059 }
6060
6061 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6062 * prefix for the v4 and v6 afi's and unicast/multicast */
6063 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6064 flog_err(
e50f7cfd 6065 EC_BGP_UPDATE_RCV,
d62a17ae 6066 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6067 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6068 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6069 }
6070
6071 /* Fetch prefix from NLRI packet. */
a85297a7 6072 memcpy(p.u.val, pnt, psize);
d62a17ae 6073
6074 /* Check address. */
6075 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6076 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6077 /* From RFC4271 Section 6.3:
6078 *
6079 * If a prefix in the NLRI field is semantically
6080 * incorrect
6081 * (e.g., an unexpected multicast IP address),
6082 * an error SHOULD
6083 * be logged locally, and the prefix SHOULD be
6084 * ignored.
a4d82a8a 6085 */
af4c2728 6086 flog_err(
e50f7cfd 6087 EC_BGP_UPDATE_RCV,
23d0a753
DA
6088 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6089 peer->host, &p.u.prefix4);
d62a17ae 6090 continue;
6091 }
6092 }
6093
6094 /* Check address. */
6095 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6096 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6097 flog_err(
e50f7cfd 6098 EC_BGP_UPDATE_RCV,
c0d72166
DS
6099 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6100 peer->host, &p.u.prefix6);
d62a17ae 6101
6102 continue;
6103 }
6104 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6105 flog_err(
e50f7cfd 6106 EC_BGP_UPDATE_RCV,
c0d72166
DS
6107 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6108 peer->host, &p.u.prefix6);
d62a17ae 6109
6110 continue;
6111 }
6112 }
6113
6114 /* Normal process. */
6115 if (attr)
6116 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
6117 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 6118 NULL, NULL, 0, 0, NULL);
d62a17ae 6119 else
6120 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
6121 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
6122 BGP_ROUTE_NORMAL, NULL, NULL, 0,
6123 NULL);
d62a17ae 6124
513386b5
DA
6125 /* Do not send BGP notification twice when maximum-prefix count
6126 * overflow. */
6127 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6128 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6129
6130 /* Address family configuration mismatch. */
d62a17ae 6131 if (ret < 0)
513386b5 6132 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 6133 }
6134
6135 /* Packet length consistency check. */
6136 if (pnt != lim) {
af4c2728 6137 flog_err(
e50f7cfd 6138 EC_BGP_UPDATE_RCV,
d62a17ae 6139 "%s [Error] Update packet error (prefix length mismatch with total length)",
6140 peer->host);
513386b5 6141 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6142 }
6b0655a2 6143
513386b5 6144 return BGP_NLRI_PARSE_OK;
718e3744 6145}
6146
d62a17ae 6147static struct bgp_static *bgp_static_new(void)
718e3744 6148{
d62a17ae 6149 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6150}
6151
d62a17ae 6152static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6153{
0a22ddfb 6154 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6155 route_map_counter_decrement(bgp_static->rmap.map);
6156
0a22ddfb 6157 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6158 XFREE(MTYPE_BGP_STATIC, bgp_static);
6159}
6160
5f040085 6161void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6162 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6163{
9bcb3eef 6164 struct bgp_dest *dest;
40381db7 6165 struct bgp_path_info *pi;
4b7e6066 6166 struct bgp_path_info *new;
40381db7 6167 struct bgp_path_info rmap_path;
d62a17ae 6168 struct attr attr;
6169 struct attr *attr_new;
b68885f9 6170 route_map_result_t ret;
49e5a4a0 6171#ifdef ENABLE_BGP_VNC
d62a17ae 6172 int vnc_implicit_withdraw = 0;
65efcfce 6173#endif
fee0f4c6 6174
d62a17ae 6175 assert(bgp_static);
dd8103a9 6176
9bcb3eef 6177 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6178
0f05ea43 6179 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6180
d62a17ae 6181 attr.nexthop = bgp_static->igpnexthop;
6182 attr.med = bgp_static->igpmetric;
6183 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6184
7226bc40
TA
6185 if (afi == AFI_IP)
6186 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6187
97a52c82
DA
6188 if (bgp_static->igpmetric)
6189 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6190
d62a17ae 6191 if (bgp_static->atomic)
6192 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6193
d62a17ae 6194 /* Store label index, if required. */
6195 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6196 attr.label_index = bgp_static->label_index;
6197 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6198 }
718e3744 6199
d62a17ae 6200 /* Apply route-map. */
6201 if (bgp_static->rmap.name) {
6202 struct attr attr_tmp = attr;
80ced710 6203
6006b807 6204 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6205 rmap_path.peer = bgp->peer_self;
6206 rmap_path.attr = &attr_tmp;
fee0f4c6 6207
d62a17ae 6208 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6209
1782514f 6210 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6211
d62a17ae 6212 bgp->peer_self->rmap_type = 0;
718e3744 6213
d62a17ae 6214 if (ret == RMAP_DENYMATCH) {
6215 /* Free uninterned attribute. */
6216 bgp_attr_flush(&attr_tmp);
718e3744 6217
d62a17ae 6218 /* Unintern original. */
6219 aspath_unintern(&attr.aspath);
6220 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6221 bgp_dest_unlock_node(dest);
d62a17ae 6222 return;
6223 }
7f323236 6224
637e5ba4 6225 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6226 bgp_attr_add_gshut_community(&attr_tmp);
6227
d62a17ae 6228 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6229 } else {
6230
637e5ba4 6231 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6232 bgp_attr_add_gshut_community(&attr);
6233
d62a17ae 6234 attr_new = bgp_attr_intern(&attr);
7f323236 6235 }
718e3744 6236
9bcb3eef 6237 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6238 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6239 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6240 break;
6241
40381db7
DS
6242 if (pi) {
6243 if (attrhash_cmp(pi->attr, attr_new)
6244 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6245 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6246 bgp_dest_unlock_node(dest);
d62a17ae 6247 bgp_attr_unintern(&attr_new);
6248 aspath_unintern(&attr.aspath);
6249 return;
6250 } else {
6251 /* The attribute is changed. */
9bcb3eef 6252 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6253
6254 /* Rewrite BGP route information. */
40381db7 6255 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6256 bgp_path_info_restore(dest, pi);
d62a17ae 6257 else
40381db7 6258 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6259#ifdef ENABLE_BGP_VNC
d62a17ae 6260 if ((afi == AFI_IP || afi == AFI_IP6)
6261 && (safi == SAFI_UNICAST)) {
40381db7 6262 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6263 /*
6264 * Implicit withdraw case.
40381db7 6265 * We have to do this before pi is
d62a17ae 6266 * changed
6267 */
6268 ++vnc_implicit_withdraw;
40381db7 6269 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6270 vnc_import_bgp_exterior_del_route(
40381db7 6271 bgp, p, pi);
d62a17ae 6272 }
6273 }
65efcfce 6274#endif
40381db7
DS
6275 bgp_attr_unintern(&pi->attr);
6276 pi->attr = attr_new;
083ec940 6277 pi->uptime = monotime(NULL);
49e5a4a0 6278#ifdef ENABLE_BGP_VNC
d62a17ae 6279 if ((afi == AFI_IP || afi == AFI_IP6)
6280 && (safi == SAFI_UNICAST)) {
6281 if (vnc_implicit_withdraw) {
40381db7 6282 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6283 vnc_import_bgp_exterior_add_route(
40381db7 6284 bgp, p, pi);
d62a17ae 6285 }
6286 }
65efcfce 6287#endif
718e3744 6288
d62a17ae 6289 /* Nexthop reachability check. */
892fedb6 6290 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6291 && (safi == SAFI_UNICAST
6292 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6293
6294 struct bgp *bgp_nexthop = bgp;
6295
40381db7
DS
6296 if (pi->extra && pi->extra->bgp_orig)
6297 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6298
6299 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6300 afi, safi, pi, NULL,
654a5978 6301 0, p))
9bcb3eef 6302 bgp_path_info_set_flag(dest, pi,
18ee8310 6303 BGP_PATH_VALID);
d62a17ae 6304 else {
6305 if (BGP_DEBUG(nht, NHT)) {
6306 char buf1[INET6_ADDRSTRLEN];
6307 inet_ntop(p->family,
6308 &p->u.prefix, buf1,
07380148 6309 sizeof(buf1));
d62a17ae 6310 zlog_debug(
6311 "%s(%s): Route not in table, not advertising",
15569c58 6312 __func__, buf1);
d62a17ae 6313 }
18ee8310 6314 bgp_path_info_unset_flag(
9bcb3eef 6315 dest, pi, BGP_PATH_VALID);
d62a17ae 6316 }
6317 } else {
6318 /* Delete the NHT structure if any, if we're
6319 * toggling between
6320 * enabling/disabling import check. We
6321 * deregister the route
6322 * from NHT to avoid overloading NHT and the
6323 * process interaction
6324 */
40381db7 6325 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6326 bgp_path_info_set_flag(dest, pi,
6327 BGP_PATH_VALID);
d62a17ae 6328 }
6329 /* Process change. */
40381db7 6330 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6331 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6332
6333 if (SAFI_UNICAST == safi
6334 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6335 || bgp->inst_type
6336 == BGP_INSTANCE_TYPE_DEFAULT)) {
6337 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6338 pi);
ddb5b488
PZ
6339 }
6340
9bcb3eef 6341 bgp_dest_unlock_node(dest);
d62a17ae 6342 aspath_unintern(&attr.aspath);
6343 return;
6344 }
718e3744 6345 }
718e3744 6346
d62a17ae 6347 /* Make new BGP info. */
6348 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6349 attr_new, dest);
d62a17ae 6350 /* Nexthop reachability check. */
892fedb6 6351 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6352 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6353 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6354 p))
9bcb3eef 6355 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6356 else {
6357 if (BGP_DEBUG(nht, NHT)) {
6358 char buf1[INET6_ADDRSTRLEN];
07380148 6359
d62a17ae 6360 inet_ntop(p->family, &p->u.prefix, buf1,
07380148 6361 sizeof(buf1));
d62a17ae 6362 zlog_debug(
6363 "%s(%s): Route not in table, not advertising",
15569c58 6364 __func__, buf1);
d62a17ae 6365 }
9bcb3eef 6366 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6367 }
6368 } else {
6369 /* Delete the NHT structure if any, if we're toggling between
6370 * enabling/disabling import check. We deregister the route
6371 * from NHT to avoid overloading NHT and the process interaction
6372 */
6373 bgp_unlink_nexthop(new);
6374
9bcb3eef 6375 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6376 }
078430f6 6377
d62a17ae 6378 /* Aggregate address increment. */
6379 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6380
d62a17ae 6381 /* Register new BGP information. */
9bcb3eef 6382 bgp_path_info_add(dest, new);
718e3744 6383
d62a17ae 6384 /* route_node_get lock */
9bcb3eef 6385 bgp_dest_unlock_node(dest);
d62a17ae 6386
6387 /* Process change. */
9bcb3eef 6388 bgp_process(bgp, dest, afi, safi);
d62a17ae 6389
ddb5b488
PZ
6390 if (SAFI_UNICAST == safi
6391 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6392 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6393 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6394 }
6395
d62a17ae 6396 /* Unintern original. */
6397 aspath_unintern(&attr.aspath);
718e3744 6398}
6399
5f040085 6400void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6401 safi_t safi)
718e3744 6402{
9bcb3eef 6403 struct bgp_dest *dest;
40381db7 6404 struct bgp_path_info *pi;
718e3744 6405
9bcb3eef 6406 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6407
d62a17ae 6408 /* Check selected route and self inserted route. */
9bcb3eef 6409 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6410 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6411 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6412 break;
6413
6414 /* Withdraw static BGP route from routing table. */
40381db7 6415 if (pi) {
ddb5b488
PZ
6416 if (SAFI_UNICAST == safi
6417 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6418 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6419 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6420 }
40381db7
DS
6421 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6422 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6423 bgp_path_info_delete(dest, pi);
6424 bgp_process(bgp, dest, afi, safi);
d62a17ae 6425 }
718e3744 6426
d62a17ae 6427 /* Unlock bgp_node_lookup. */
9bcb3eef 6428 bgp_dest_unlock_node(dest);
718e3744 6429}
6430
137446f9
LB
6431/*
6432 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6433 */
5f040085 6434static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6435 afi_t afi, safi_t safi,
6436 struct prefix_rd *prd)
718e3744 6437{
9bcb3eef 6438 struct bgp_dest *dest;
40381db7 6439 struct bgp_path_info *pi;
718e3744 6440
9bcb3eef 6441 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6442
d62a17ae 6443 /* Check selected route and self inserted route. */
9bcb3eef 6444 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6445 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6446 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6447 break;
718e3744 6448
d62a17ae 6449 /* Withdraw static BGP route from routing table. */
40381db7 6450 if (pi) {
49e5a4a0 6451#ifdef ENABLE_BGP_VNC
d62a17ae 6452 rfapiProcessWithdraw(
40381db7 6453 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6454 1); /* Kill, since it is an administrative change */
65efcfce 6455#endif
ddb5b488
PZ
6456 if (SAFI_MPLS_VPN == safi
6457 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6458 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6459 }
40381db7 6460 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6461 bgp_path_info_delete(dest, pi);
6462 bgp_process(bgp, dest, afi, safi);
d62a17ae 6463 }
718e3744 6464
d62a17ae 6465 /* Unlock bgp_node_lookup. */
9bcb3eef 6466 bgp_dest_unlock_node(dest);
718e3744 6467}
6468
5f040085 6469static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6470 struct bgp_static *bgp_static, afi_t afi,
6471 safi_t safi)
137446f9 6472{
9bcb3eef 6473 struct bgp_dest *dest;
4b7e6066 6474 struct bgp_path_info *new;
d62a17ae 6475 struct attr *attr_new;
6476 struct attr attr = {0};
40381db7 6477 struct bgp_path_info *pi;
49e5a4a0 6478#ifdef ENABLE_BGP_VNC
d62a17ae 6479 mpls_label_t label = 0;
65efcfce 6480#endif
d7c0a89a 6481 uint32_t num_labels = 0;
137446f9 6482
d62a17ae 6483 assert(bgp_static);
137446f9 6484
b57ba6d2
MK
6485 if (bgp_static->label != MPLS_INVALID_LABEL)
6486 num_labels = 1;
9bcb3eef
DS
6487 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6488 &bgp_static->prd);
137446f9 6489
0f05ea43 6490 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6491
d62a17ae 6492 attr.nexthop = bgp_static->igpnexthop;
6493 attr.med = bgp_static->igpmetric;
6494 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6495
d62a17ae 6496 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6497 || (safi == SAFI_ENCAP)) {
6498 if (afi == AFI_IP) {
6499 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6500 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6501 }
6502 }
6503 if (afi == AFI_L2VPN) {
b04c1e99
IR
6504 if (bgp_static->gatewayIp.family == AF_INET) {
6505 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6506 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6507 &bgp_static->gatewayIp.u.prefix4,
6508 IPV4_MAX_BYTELEN);
b04c1e99
IR
6509 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6510 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6511 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6512 &bgp_static->gatewayIp.u.prefix6,
6513 IPV6_MAX_BYTELEN);
b04c1e99 6514 }
0a50c248 6515 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6516 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6517 struct bgp_encap_type_vxlan bet;
6006b807 6518 memset(&bet, 0, sizeof(bet));
3714a385 6519 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6520 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6521 }
6522 if (bgp_static->router_mac) {
6523 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6524 }
6525 }
6526 /* Apply route-map. */
6527 if (bgp_static->rmap.name) {
6528 struct attr attr_tmp = attr;
40381db7 6529 struct bgp_path_info rmap_path;
b68885f9 6530 route_map_result_t ret;
137446f9 6531
40381db7
DS
6532 rmap_path.peer = bgp->peer_self;
6533 rmap_path.attr = &attr_tmp;
137446f9 6534
d62a17ae 6535 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6536
1782514f 6537 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6538
d62a17ae 6539 bgp->peer_self->rmap_type = 0;
137446f9 6540
d62a17ae 6541 if (ret == RMAP_DENYMATCH) {
6542 /* Free uninterned attribute. */
6543 bgp_attr_flush(&attr_tmp);
137446f9 6544
d62a17ae 6545 /* Unintern original. */
6546 aspath_unintern(&attr.aspath);
6547 bgp_static_withdraw_safi(bgp, p, afi, safi,
6548 &bgp_static->prd);
bbc52106 6549 bgp_dest_unlock_node(dest);
d62a17ae 6550 return;
6551 }
137446f9 6552
d62a17ae 6553 attr_new = bgp_attr_intern(&attr_tmp);
6554 } else {
6555 attr_new = bgp_attr_intern(&attr);
6556 }
137446f9 6557
9bcb3eef 6558 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6559 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6560 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6561 break;
6562
40381db7 6563 if (pi) {
40381db7 6564 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6565 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6566 bgp_dest_unlock_node(dest);
d62a17ae 6567 bgp_attr_unintern(&attr_new);
6568 aspath_unintern(&attr.aspath);
6569 return;
6570 } else {
6571 /* The attribute is changed. */
9bcb3eef 6572 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6573
6574 /* Rewrite BGP route information. */
40381db7 6575 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6576 bgp_path_info_restore(dest, pi);
d62a17ae 6577 else
40381db7
DS
6578 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6579 bgp_attr_unintern(&pi->attr);
6580 pi->attr = attr_new;
083ec940 6581 pi->uptime = monotime(NULL);
49e5a4a0 6582#ifdef ENABLE_BGP_VNC
40381db7
DS
6583 if (pi->extra)
6584 label = decode_label(&pi->extra->label[0]);
65efcfce 6585#endif
137446f9 6586
d62a17ae 6587 /* Process change. */
40381db7 6588 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6589 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6590
6591 if (SAFI_MPLS_VPN == safi
6592 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6593 vpn_leak_to_vrf_update(bgp, pi,
6594 &bgp_static->prd);
ddb5b488 6595 }
49e5a4a0 6596#ifdef ENABLE_BGP_VNC
40381db7
DS
6597 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6598 pi->attr, afi, safi, pi->type,
6599 pi->sub_type, &label);
65efcfce 6600#endif
9bcb3eef 6601 bgp_dest_unlock_node(dest);
d62a17ae 6602 aspath_unintern(&attr.aspath);
6603 return;
6604 }
6605 }
137446f9
LB
6606
6607
d62a17ae 6608 /* Make new BGP info. */
6609 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6610 attr_new, dest);
1defdda8 6611 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6612 bgp_path_info_extra_get(new);
b57ba6d2
MK
6613 if (num_labels) {
6614 new->extra->label[0] = bgp_static->label;
6615 new->extra->num_labels = num_labels;
6616 }
49e5a4a0 6617#ifdef ENABLE_BGP_VNC
d62a17ae 6618 label = decode_label(&bgp_static->label);
65efcfce 6619#endif
137446f9 6620
d62a17ae 6621 /* Aggregate address increment. */
6622 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6623
d62a17ae 6624 /* Register new BGP information. */
9bcb3eef 6625 bgp_path_info_add(dest, new);
d62a17ae 6626 /* route_node_get lock */
9bcb3eef 6627 bgp_dest_unlock_node(dest);
137446f9 6628
d62a17ae 6629 /* Process change. */
9bcb3eef 6630 bgp_process(bgp, dest, afi, safi);
137446f9 6631
ddb5b488
PZ
6632 if (SAFI_MPLS_VPN == safi
6633 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6634 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6635 }
49e5a4a0 6636#ifdef ENABLE_BGP_VNC
d62a17ae 6637 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6638 safi, new->type, new->sub_type, &label);
65efcfce
LB
6639#endif
6640
d62a17ae 6641 /* Unintern original. */
6642 aspath_unintern(&attr.aspath);
137446f9
LB
6643}
6644
718e3744 6645/* Configure static BGP network. When user don't run zebra, static
6646 route should be installed as valid. */
585f1adc
IR
6647static int bgp_static_set(struct vty *vty, const char *negate,
6648 const char *ip_str, afi_t afi, safi_t safi,
6649 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6650{
585f1adc
IR
6651 VTY_DECLVAR_CONTEXT(bgp, bgp);
6652 int ret;
d62a17ae 6653 struct prefix p;
6654 struct bgp_static *bgp_static;
9bcb3eef 6655 struct bgp_dest *dest;
d7c0a89a 6656 uint8_t need_update = 0;
d62a17ae 6657
585f1adc
IR
6658 /* Convert IP prefix string to struct prefix. */
6659 ret = str2prefix(ip_str, &p);
6660 if (!ret) {
6661 vty_out(vty, "%% Malformed prefix\n");
6662 return CMD_WARNING_CONFIG_FAILED;
6663 }
6664 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6665 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6666 return CMD_WARNING_CONFIG_FAILED;
6667 }
6668
d62a17ae 6669 apply_mask(&p);
718e3744 6670
e2a86ad9 6671 if (negate) {
718e3744 6672
e2a86ad9 6673 /* Set BGP static route configuration. */
9bcb3eef 6674 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6675
9bcb3eef 6676 if (!dest) {
585f1adc
IR
6677 vty_out(vty, "%% Can't find static route specified\n");
6678 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6679 }
6680
9bcb3eef 6681 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6682
e2a86ad9
DS
6683 if ((label_index != BGP_INVALID_LABEL_INDEX)
6684 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6685 vty_out(vty,
6686 "%% label-index doesn't match static route\n");
70d9b134 6687 bgp_dest_unlock_node(dest);
585f1adc 6688 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6689 }
d62a17ae 6690
e2a86ad9
DS
6691 if ((rmap && bgp_static->rmap.name)
6692 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6693 vty_out(vty,
6694 "%% route-map name doesn't match static route\n");
70d9b134 6695 bgp_dest_unlock_node(dest);
585f1adc 6696 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6697 }
718e3744 6698
e2a86ad9
DS
6699 /* Update BGP RIB. */
6700 if (!bgp_static->backdoor)
6701 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6702
e2a86ad9
DS
6703 /* Clear configuration. */
6704 bgp_static_free(bgp_static);
9bcb3eef
DS
6705 bgp_dest_set_bgp_static_info(dest, NULL);
6706 bgp_dest_unlock_node(dest);
6707 bgp_dest_unlock_node(dest);
e2a86ad9 6708 } else {
718e3744 6709
e2a86ad9 6710 /* Set BGP static route configuration. */
9bcb3eef
DS
6711 dest = bgp_node_get(bgp->route[afi][safi], &p);
6712 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6713 if (bgp_static) {
e2a86ad9 6714 /* Configuration change. */
e2a86ad9
DS
6715 /* Label index cannot be changed. */
6716 if (bgp_static->label_index != label_index) {
585f1adc 6717 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6718 bgp_dest_unlock_node(dest);
585f1adc 6719 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6720 }
d62a17ae 6721
e2a86ad9 6722 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6723 if (bgp_static->valid
6724 && bgp_static->backdoor != backdoor)
e2a86ad9 6725 need_update = 1;
718e3744 6726
e2a86ad9 6727 bgp_static->backdoor = backdoor;
718e3744 6728
e2a86ad9 6729 if (rmap) {
0a22ddfb
QY
6730 XFREE(MTYPE_ROUTE_MAP_NAME,
6731 bgp_static->rmap.name);
b4897fa5 6732 route_map_counter_decrement(
6733 bgp_static->rmap.map);
e2a86ad9
DS
6734 bgp_static->rmap.name =
6735 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6736 bgp_static->rmap.map =
6737 route_map_lookup_by_name(rmap);
b4897fa5 6738 route_map_counter_increment(
6739 bgp_static->rmap.map);
e2a86ad9 6740 } else {
0a22ddfb
QY
6741 XFREE(MTYPE_ROUTE_MAP_NAME,
6742 bgp_static->rmap.name);
b4897fa5 6743 route_map_counter_decrement(
6744 bgp_static->rmap.map);
e2a86ad9
DS
6745 bgp_static->rmap.map = NULL;
6746 bgp_static->valid = 0;
6747 }
9bcb3eef 6748 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6749 } else {
6750 /* New configuration. */
6751 bgp_static = bgp_static_new();
6752 bgp_static->backdoor = backdoor;
6753 bgp_static->valid = 0;
6754 bgp_static->igpmetric = 0;
975a328e 6755 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6756 bgp_static->label_index = label_index;
718e3744 6757
e2a86ad9 6758 if (rmap) {
0a22ddfb
QY
6759 XFREE(MTYPE_ROUTE_MAP_NAME,
6760 bgp_static->rmap.name);
b4897fa5 6761 route_map_counter_decrement(
6762 bgp_static->rmap.map);
e2a86ad9
DS
6763 bgp_static->rmap.name =
6764 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6765 bgp_static->rmap.map =
6766 route_map_lookup_by_name(rmap);
b4897fa5 6767 route_map_counter_increment(
6768 bgp_static->rmap.map);
e2a86ad9 6769 }
9bcb3eef 6770 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6771 }
d62a17ae 6772
e2a86ad9
DS
6773 bgp_static->valid = 1;
6774 if (need_update)
6775 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6776
e2a86ad9
DS
6777 if (!bgp_static->backdoor)
6778 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6779 }
d62a17ae 6780
585f1adc 6781 return CMD_SUCCESS;
d62a17ae 6782}
6783
6784void bgp_static_add(struct bgp *bgp)
6785{
6786 afi_t afi;
6787 safi_t safi;
9bcb3eef
DS
6788 struct bgp_dest *dest;
6789 struct bgp_dest *rm;
d62a17ae 6790 struct bgp_table *table;
6791 struct bgp_static *bgp_static;
6792
47fc6261 6793 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6794 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6795 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6796 dest = bgp_route_next(dest)) {
6797 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6798 continue;
ea47320b 6799
05c7a1cc
QY
6800 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6801 || (safi == SAFI_EVPN)) {
9bcb3eef 6802 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6803
6804 for (rm = bgp_table_top(table); rm;
6805 rm = bgp_route_next(rm)) {
a78beeb5 6806 bgp_static =
9bcb3eef 6807 bgp_dest_get_bgp_static_info(
5a8ba9fc 6808 rm);
9bcb3eef
DS
6809 bgp_static_update_safi(
6810 bgp, bgp_dest_get_prefix(rm),
6811 bgp_static, afi, safi);
d62a17ae 6812 }
05c7a1cc 6813 } else {
5a8ba9fc 6814 bgp_static_update(
9bcb3eef
DS
6815 bgp, bgp_dest_get_prefix(dest),
6816 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6817 safi);
ea47320b 6818 }
05c7a1cc 6819 }
47fc6261 6820 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6821}
6822
718e3744 6823/* Called from bgp_delete(). Delete all static routes from the BGP
6824 instance. */
d62a17ae 6825void bgp_static_delete(struct bgp *bgp)
6826{
6827 afi_t afi;
6828 safi_t safi;
9bcb3eef
DS
6829 struct bgp_dest *dest;
6830 struct bgp_dest *rm;
d62a17ae 6831 struct bgp_table *table;
6832 struct bgp_static *bgp_static;
6833
05c7a1cc 6834 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6835 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6836 dest = bgp_route_next(dest)) {
6837 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6838 continue;
ea47320b 6839
05c7a1cc
QY
6840 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6841 || (safi == SAFI_EVPN)) {
9bcb3eef 6842 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6843
6844 for (rm = bgp_table_top(table); rm;
6845 rm = bgp_route_next(rm)) {
a78beeb5 6846 bgp_static =
9bcb3eef 6847 bgp_dest_get_bgp_static_info(
5a8ba9fc 6848 rm);
c7d14ba6
PG
6849 if (!bgp_static)
6850 continue;
6851
05c7a1cc 6852 bgp_static_withdraw_safi(
9bcb3eef 6853 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6854 AFI_IP, safi,
6855 (struct prefix_rd *)
9bcb3eef
DS
6856 bgp_dest_get_prefix(
6857 dest));
ea47320b 6858 bgp_static_free(bgp_static);
811c6797 6859 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6860 NULL);
811c6797 6861 bgp_dest_unlock_node(rm);
d62a17ae 6862 }
05c7a1cc 6863 } else {
9bcb3eef 6864 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6865 bgp_static_withdraw(bgp,
9bcb3eef 6866 bgp_dest_get_prefix(dest),
b54892e0 6867 afi, safi);
05c7a1cc 6868 bgp_static_free(bgp_static);
9bcb3eef
DS
6869 bgp_dest_set_bgp_static_info(dest, NULL);
6870 bgp_dest_unlock_node(dest);
ea47320b 6871 }
05c7a1cc 6872 }
d62a17ae 6873}
6874
6875void bgp_static_redo_import_check(struct bgp *bgp)
6876{
6877 afi_t afi;
6878 safi_t safi;
9bcb3eef
DS
6879 struct bgp_dest *dest;
6880 struct bgp_dest *rm;
d62a17ae 6881 struct bgp_table *table;
6882 struct bgp_static *bgp_static;
6883
6884 /* Use this flag to force reprocessing of the route */
892fedb6 6885 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6886 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6887 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6888 dest = bgp_route_next(dest)) {
6889 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6890 continue;
ea47320b 6891
05c7a1cc
QY
6892 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6893 || (safi == SAFI_EVPN)) {
9bcb3eef 6894 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6895
6896 for (rm = bgp_table_top(table); rm;
6897 rm = bgp_route_next(rm)) {
a78beeb5 6898 bgp_static =
9bcb3eef 6899 bgp_dest_get_bgp_static_info(
5a8ba9fc 6900 rm);
9bcb3eef
DS
6901 bgp_static_update_safi(
6902 bgp, bgp_dest_get_prefix(rm),
6903 bgp_static, afi, safi);
d62a17ae 6904 }
05c7a1cc 6905 } else {
9bcb3eef
DS
6906 bgp_static = bgp_dest_get_bgp_static_info(dest);
6907 bgp_static_update(bgp,
6908 bgp_dest_get_prefix(dest),
6909 bgp_static, afi, safi);
ea47320b 6910 }
05c7a1cc
QY
6911 }
6912 }
892fedb6 6913 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6914}
6915
6916static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6917 safi_t safi)
6918{
6919 struct bgp_table *table;
9bcb3eef 6920 struct bgp_dest *dest;
40381db7 6921 struct bgp_path_info *pi;
d62a17ae 6922
dfb6fd1d
NT
6923 /* Do not install the aggregate route if BGP is in the
6924 * process of termination.
6925 */
892fedb6
DA
6926 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6927 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6928 return;
6929
d62a17ae 6930 table = bgp->rib[afi][safi];
9bcb3eef
DS
6931 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6932 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6933 if (pi->peer == bgp->peer_self
6934 && ((pi->type == ZEBRA_ROUTE_BGP
6935 && pi->sub_type == BGP_ROUTE_STATIC)
6936 || (pi->type != ZEBRA_ROUTE_BGP
6937 && pi->sub_type
d62a17ae 6938 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6939 bgp_aggregate_decrement(
6940 bgp, bgp_dest_get_prefix(dest), pi, afi,
6941 safi);
40381db7 6942 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6943 bgp_path_info_delete(dest, pi);
6944 bgp_process(bgp, dest, afi, safi);
d62a17ae 6945 }
6946 }
6947 }
ad4cbda1 6948}
6949
6950/*
6951 * Purge all networks and redistributed routes from routing table.
6952 * Invoked upon the instance going down.
6953 */
d62a17ae 6954void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6955{
d62a17ae 6956 afi_t afi;
6957 safi_t safi;
ad4cbda1 6958
05c7a1cc
QY
6959 FOREACH_AFI_SAFI (afi, safi)
6960 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6961}
6962
137446f9
LB
6963/*
6964 * gpz 110624
6965 * Currently this is used to set static routes for VPN and ENCAP.
6966 * I think it can probably be factored with bgp_static_set.
6967 */
d62a17ae 6968int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6969 const char *ip_str, const char *rd_str,
6970 const char *label_str, const char *rmap_str,
6971 int evpn_type, const char *esi, const char *gwip,
6972 const char *ethtag, const char *routermac)
6973{
6974 VTY_DECLVAR_CONTEXT(bgp, bgp);
6975 int ret;
6976 struct prefix p;
6977 struct prefix_rd prd;
9bcb3eef
DS
6978 struct bgp_dest *pdest;
6979 struct bgp_dest *dest;
d62a17ae 6980 struct bgp_table *table;
6981 struct bgp_static *bgp_static;
6982 mpls_label_t label = MPLS_INVALID_LABEL;
6983 struct prefix gw_ip;
6984
6985 /* validate ip prefix */
6986 ret = str2prefix(ip_str, &p);
6987 if (!ret) {
6988 vty_out(vty, "%% Malformed prefix\n");
6989 return CMD_WARNING_CONFIG_FAILED;
6990 }
6991 apply_mask(&p);
6992 if ((afi == AFI_L2VPN)
6993 && (bgp_build_evpn_prefix(evpn_type,
6994 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6995 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6996 return CMD_WARNING_CONFIG_FAILED;
6997 }
718e3744 6998
d62a17ae 6999 ret = str2prefix_rd(rd_str, &prd);
7000 if (!ret) {
7001 vty_out(vty, "%% Malformed rd\n");
7002 return CMD_WARNING_CONFIG_FAILED;
7003 }
718e3744 7004
d62a17ae 7005 if (label_str) {
7006 unsigned long label_val;
7007 label_val = strtoul(label_str, NULL, 10);
7008 encode_label(label_val, &label);
7009 }
9bedbb1e 7010
d62a17ae 7011 if (safi == SAFI_EVPN) {
7012 if (esi && str2esi(esi, NULL) == 0) {
7013 vty_out(vty, "%% Malformed ESI\n");
7014 return CMD_WARNING_CONFIG_FAILED;
7015 }
7016 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7017 vty_out(vty, "%% Malformed Router MAC\n");
7018 return CMD_WARNING_CONFIG_FAILED;
7019 }
7020 if (gwip) {
6006b807 7021 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7022 ret = str2prefix(gwip, &gw_ip);
7023 if (!ret) {
7024 vty_out(vty, "%% Malformed GatewayIp\n");
7025 return CMD_WARNING_CONFIG_FAILED;
7026 }
7027 if ((gw_ip.family == AF_INET
3714a385 7028 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7029 (struct prefix_evpn *)&p))
7030 || (gw_ip.family == AF_INET6
3714a385 7031 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7032 (struct prefix_evpn *)&p))) {
7033 vty_out(vty,
7034 "%% GatewayIp family differs with IP prefix\n");
7035 return CMD_WARNING_CONFIG_FAILED;
7036 }
7037 }
7038 }
9bcb3eef
DS
7039 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7040 if (!bgp_dest_has_bgp_path_info_data(pdest))
7041 bgp_dest_set_bgp_table_info(pdest,
67009e22 7042 bgp_table_init(bgp, afi, safi));
9bcb3eef 7043 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7044
9bcb3eef 7045 dest = bgp_node_get(table, &p);
d62a17ae 7046
9bcb3eef 7047 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7048 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7049 bgp_dest_unlock_node(dest);
d62a17ae 7050 } else {
7051 /* New configuration. */
7052 bgp_static = bgp_static_new();
7053 bgp_static->backdoor = 0;
7054 bgp_static->valid = 0;
7055 bgp_static->igpmetric = 0;
975a328e 7056 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7057 bgp_static->label = label;
7058 bgp_static->prd = prd;
7059
7060 if (rmap_str) {
0a22ddfb 7061 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7062 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7063 bgp_static->rmap.name =
7064 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7065 bgp_static->rmap.map =
7066 route_map_lookup_by_name(rmap_str);
b4897fa5 7067 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7068 }
718e3744 7069
d62a17ae 7070 if (safi == SAFI_EVPN) {
7071 if (esi) {
7072 bgp_static->eth_s_id =
7073 XCALLOC(MTYPE_ATTR,
0a50c248 7074 sizeof(esi_t));
d62a17ae 7075 str2esi(esi, bgp_static->eth_s_id);
7076 }
7077 if (routermac) {
7078 bgp_static->router_mac =
28328ea9 7079 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7080 (void)prefix_str2mac(routermac,
7081 bgp_static->router_mac);
d62a17ae 7082 }
7083 if (gwip)
7084 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7085 }
9bcb3eef 7086 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7087
d62a17ae 7088 bgp_static->valid = 1;
7089 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7090 }
718e3744 7091
d62a17ae 7092 return CMD_SUCCESS;
718e3744 7093}
7094
7095/* Configure static BGP network. */
d62a17ae 7096int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7097 const char *ip_str, const char *rd_str,
7098 const char *label_str, int evpn_type, const char *esi,
7099 const char *gwip, const char *ethtag)
7100{
7101 VTY_DECLVAR_CONTEXT(bgp, bgp);
7102 int ret;
7103 struct prefix p;
7104 struct prefix_rd prd;
9bcb3eef
DS
7105 struct bgp_dest *pdest;
7106 struct bgp_dest *dest;
d62a17ae 7107 struct bgp_table *table;
7108 struct bgp_static *bgp_static;
7109 mpls_label_t label = MPLS_INVALID_LABEL;
7110
7111 /* Convert IP prefix string to struct prefix. */
7112 ret = str2prefix(ip_str, &p);
7113 if (!ret) {
7114 vty_out(vty, "%% Malformed prefix\n");
7115 return CMD_WARNING_CONFIG_FAILED;
7116 }
7117 apply_mask(&p);
7118 if ((afi == AFI_L2VPN)
7119 && (bgp_build_evpn_prefix(evpn_type,
7120 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7121 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7122 return CMD_WARNING_CONFIG_FAILED;
7123 }
7124 ret = str2prefix_rd(rd_str, &prd);
7125 if (!ret) {
7126 vty_out(vty, "%% Malformed rd\n");
7127 return CMD_WARNING_CONFIG_FAILED;
7128 }
718e3744 7129
d62a17ae 7130 if (label_str) {
7131 unsigned long label_val;
7132 label_val = strtoul(label_str, NULL, 10);
7133 encode_label(label_val, &label);
7134 }
718e3744 7135
9bcb3eef
DS
7136 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7137 if (!bgp_dest_has_bgp_path_info_data(pdest))
7138 bgp_dest_set_bgp_table_info(pdest,
67009e22 7139 bgp_table_init(bgp, afi, safi));
d62a17ae 7140 else
9bcb3eef
DS
7141 bgp_dest_unlock_node(pdest);
7142 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7143
9bcb3eef 7144 dest = bgp_node_lookup(table, &p);
6b0655a2 7145
9bcb3eef 7146 if (dest) {
d62a17ae 7147 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7148
9bcb3eef 7149 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7150 bgp_static_free(bgp_static);
9bcb3eef
DS
7151 bgp_dest_set_bgp_static_info(dest, NULL);
7152 bgp_dest_unlock_node(dest);
7153 bgp_dest_unlock_node(dest);
d62a17ae 7154 } else
7155 vty_out(vty, "%% Can't find the route\n");
7156
7157 return CMD_SUCCESS;
7158}
7159
7160static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7161 const char *rmap_name)
7162{
7163 VTY_DECLVAR_CONTEXT(bgp, bgp);
7164 struct bgp_rmap *rmap;
7165
7166 rmap = &bgp->table_map[afi][safi];
7167 if (rmap_name) {
0a22ddfb 7168 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7169 route_map_counter_decrement(rmap->map);
d62a17ae 7170 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7171 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7172 route_map_counter_increment(rmap->map);
d62a17ae 7173 } else {
0a22ddfb 7174 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7175 route_map_counter_decrement(rmap->map);
d62a17ae 7176 rmap->map = NULL;
7177 }
73ac8160 7178
d62a17ae 7179 if (bgp_fibupd_safi(safi))
7180 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7181
d62a17ae 7182 return CMD_SUCCESS;
73ac8160
DS
7183}
7184
d62a17ae 7185static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7186 const char *rmap_name)
73ac8160 7187{
d62a17ae 7188 VTY_DECLVAR_CONTEXT(bgp, bgp);
7189 struct bgp_rmap *rmap;
73ac8160 7190
d62a17ae 7191 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7192 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7193 route_map_counter_decrement(rmap->map);
d62a17ae 7194 rmap->map = NULL;
73ac8160 7195
d62a17ae 7196 if (bgp_fibupd_safi(safi))
7197 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7198
d62a17ae 7199 return CMD_SUCCESS;
73ac8160
DS
7200}
7201
2b791107 7202void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7203 safi_t safi)
73ac8160 7204{
d62a17ae 7205 if (bgp->table_map[afi][safi].name) {
d62a17ae 7206 vty_out(vty, " table-map %s\n",
7207 bgp->table_map[afi][safi].name);
7208 }
73ac8160
DS
7209}
7210
73ac8160
DS
7211DEFUN (bgp_table_map,
7212 bgp_table_map_cmd,
7213 "table-map WORD",
7214 "BGP table to RIB route download filter\n"
7215 "Name of the route map\n")
7216{
d62a17ae 7217 int idx_word = 1;
7218 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7219 argv[idx_word]->arg);
73ac8160
DS
7220}
7221DEFUN (no_bgp_table_map,
7222 no_bgp_table_map_cmd,
7223 "no table-map WORD",
3a2d747c 7224 NO_STR
73ac8160
DS
7225 "BGP table to RIB route download filter\n"
7226 "Name of the route map\n")
7227{
d62a17ae 7228 int idx_word = 2;
7229 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7230 argv[idx_word]->arg);
73ac8160
DS
7231}
7232
585f1adc
IR
7233DEFPY(bgp_network,
7234 bgp_network_cmd,
7235 "[no] network \
7236 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7237 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7238 backdoor$backdoor}]",
7239 NO_STR
7240 "Specify a network to announce via BGP\n"
7241 "IPv4 prefix\n"
7242 "Network number\n"
7243 "Network mask\n"
7244 "Network mask\n"
7245 "Route-map to modify the attributes\n"
7246 "Name of the route map\n"
7247 "Label index to associate with the prefix\n"
7248 "Label index value\n"
7249 "Specify a BGP backdoor route\n")
7250{
7251 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7252
7253 if (address_str) {
7254 int ret;
718e3744 7255
e2a86ad9 7256 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7257 addr_prefix_str,
7258 sizeof(addr_prefix_str));
e2a86ad9
DS
7259 if (!ret) {
7260 vty_out(vty, "%% Inconsistent address and mask\n");
7261 return CMD_WARNING_CONFIG_FAILED;
7262 }
d62a17ae 7263 }
718e3744 7264
585f1adc
IR
7265 return bgp_static_set(
7266 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7267 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7268 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7269}
7270
585f1adc
IR
7271DEFPY(ipv6_bgp_network,
7272 ipv6_bgp_network_cmd,
7273 "[no] network X:X::X:X/M$prefix \
70dd370f 7274 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7275 NO_STR
7276 "Specify a network to announce via BGP\n"
7277 "IPv6 prefix\n"
7278 "Route-map to modify the attributes\n"
7279 "Name of the route map\n"
7280 "Label index to associate with the prefix\n"
7281 "Label index value\n")
37a87b8f 7282{
585f1adc
IR
7283 return bgp_static_set(
7284 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7285 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7286}
7287
d62a17ae 7288static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7289{
d62a17ae 7290 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7291}
7292
d62a17ae 7293static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7294{
365ab2e7
RZ
7295 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7296 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7297 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7298 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7299 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7300}
718e3744 7301
365ab2e7
RZ
7302/**
7303 * Helper function to avoid repeated code: prepare variables for a
7304 * `route_map_apply` call.
7305 *
7306 * \returns `true` on route map match, otherwise `false`.
7307 */
7308static bool aggr_suppress_map_test(struct bgp *bgp,
7309 struct bgp_aggregate *aggregate,
7310 struct bgp_path_info *pi)
7311{
7312 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7313 route_map_result_t rmr = RMAP_DENYMATCH;
7314 struct bgp_path_info rmap_path = {};
7315 struct attr attr = {};
7316
7317 /* No route map entries created, just don't match. */
7318 if (aggregate->suppress_map == NULL)
7319 return false;
7320
7321 /* Call route map matching and return result. */
7322 attr.aspath = aspath_empty();
7323 rmap_path.peer = bgp->peer_self;
7324 rmap_path.attr = &attr;
7325
7326 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7327 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7328 bgp->peer_self->rmap_type = 0;
7329
7330 bgp_attr_flush(&attr);
afb254d7 7331 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7332
7333 return rmr == RMAP_PERMITMATCH;
7334}
7335
4056a5f6
RZ
7336/** Test whether the aggregation has suppressed this path or not. */
7337static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7338 struct bgp_path_info *pi)
7339{
7340 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7341 return false;
7342
7343 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7344}
7345
7346/**
7347 * Suppress this path and keep the reference.
7348 *
7349 * \returns `true` if needs processing otherwise `false`.
7350 */
7351static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7352 struct bgp_path_info *pi)
7353{
7354 struct bgp_path_info_extra *pie;
7355
7356 /* Path is already suppressed by this aggregation. */
7357 if (aggr_suppress_exists(aggregate, pi))
7358 return false;
7359
7360 pie = bgp_path_info_extra_get(pi);
7361
7362 /* This is the first suppression, allocate memory and list it. */
7363 if (pie->aggr_suppressors == NULL)
7364 pie->aggr_suppressors = list_new();
7365
7366 listnode_add(pie->aggr_suppressors, aggregate);
7367
7368 /* Only mark for processing if suppressed. */
7369 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7370 if (BGP_DEBUG(update, UPDATE_OUT))
7371 zlog_debug("aggregate-address suppressing: %pFX",
7372 bgp_dest_get_prefix(pi->net));
7373
4056a5f6
RZ
7374 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7375 return true;
7376 }
7377
7378 return false;
7379}
7380
7381/**
7382 * Unsuppress this path and remove the reference.
7383 *
7384 * \returns `true` if needs processing otherwise `false`.
7385 */
7386static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7387 struct bgp_path_info *pi)
7388{
7389 /* Path wasn't suppressed. */
7390 if (!aggr_suppress_exists(aggregate, pi))
7391 return false;
7392
7393 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7394
7395 /* Unsuppress and free extra memory if last item. */
7396 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7397 if (BGP_DEBUG(update, UPDATE_OUT))
7398 zlog_debug("aggregate-address unsuppressing: %pFX",
7399 bgp_dest_get_prefix(pi->net));
7400
4056a5f6
RZ
7401 list_delete(&pi->extra->aggr_suppressors);
7402 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7403 return true;
7404 }
7405
7406 return false;
7407}
7408
3dc339cd
DA
7409static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7410 struct aspath *aspath,
7411 struct community *comm,
7412 struct ecommunity *ecomm,
7413 struct lcommunity *lcomm)
eaaf8adb
DS
7414{
7415 static struct aspath *ae = NULL;
7416
7417 if (!ae)
7418 ae = aspath_empty();
7419
40381db7 7420 if (!pi)
3dc339cd 7421 return false;
eaaf8adb 7422
40381db7 7423 if (origin != pi->attr->origin)
3dc339cd 7424 return false;
eaaf8adb 7425
40381db7 7426 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7427 return false;
29f7d023 7428
9a706b42 7429 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7430 return false;
eaaf8adb 7431
b53e67a3 7432 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7433 return false;
eaaf8adb 7434
1bcf3a96 7435 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7436 return false;
dd18c5a9 7437
40381db7 7438 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7439 return false;
7ce8a8e0 7440
3dc339cd 7441 return true;
eaaf8adb
DS
7442}
7443
5f040085
DS
7444static void bgp_aggregate_install(
7445 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7446 uint8_t origin, struct aspath *aspath, struct community *community,
7447 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7448 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7449{
9bcb3eef 7450 struct bgp_dest *dest;
c701010e 7451 struct bgp_table *table;
6f94b685 7452 struct bgp_path_info *pi, *orig, *new;
20894f50 7453 struct attr *attr;
c701010e
DS
7454
7455 table = bgp->rib[afi][safi];
7456
9bcb3eef 7457 dest = bgp_node_get(table, p);
eaaf8adb 7458
9bcb3eef 7459 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7460 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7461 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7462 break;
7463
6aabb15d
RZ
7464 /*
7465 * If we have paths with different MEDs, then don't install
7466 * (or uninstall) the aggregate route.
7467 */
7468 if (aggregate->match_med && aggregate->med_mismatched)
7469 goto uninstall_aggregate_route;
7470
c701010e 7471 if (aggregate->count > 0) {
eaaf8adb
DS
7472 /*
7473 * If the aggregate information has not changed
7474 * no need to re-install it again.
7475 */
6f94b685 7476 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7477 ecommunity, lcommunity)) {
9bcb3eef 7478 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7479
7480 if (aspath)
7481 aspath_free(aspath);
7482 if (community)
3c1f53de 7483 community_free(&community);
3da2cc32
DS
7484 if (ecommunity)
7485 ecommunity_free(&ecommunity);
dd18c5a9
DS
7486 if (lcommunity)
7487 lcommunity_free(&lcommunity);
eaaf8adb
DS
7488
7489 return;
7490 }
7491
7492 /*
7493 * Mark the old as unusable
7494 */
40381db7 7495 if (pi)
9bcb3eef 7496 bgp_path_info_delete(dest, pi);
eaaf8adb 7497
20894f50
DA
7498 attr = bgp_attr_aggregate_intern(
7499 bgp, origin, aspath, community, ecommunity, lcommunity,
7500 aggregate, atomic_aggregate, p);
7501
7502 if (!attr) {
8c0044f3 7503 bgp_dest_unlock_node(dest);
20894f50 7504 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7505 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7506 zlog_debug("%s: %pFX null attribute", __func__,
7507 p);
20894f50
DA
7508 return;
7509 }
7510
3da2cc32 7511 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7512 bgp->peer_self, attr, dest);
20894f50 7513
1defdda8 7514 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7515
9bcb3eef
DS
7516 bgp_path_info_add(dest, new);
7517 bgp_process(bgp, dest, afi, safi);
c701010e 7518 } else {
6aabb15d 7519 uninstall_aggregate_route:
6f94b685 7520 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7521 if (pi->peer == bgp->peer_self
7522 && pi->type == ZEBRA_ROUTE_BGP
7523 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7524 break;
7525
7526 /* Withdraw static BGP route from routing table. */
40381db7 7527 if (pi) {
9bcb3eef
DS
7528 bgp_path_info_delete(dest, pi);
7529 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7530 }
7531 }
7532
9bcb3eef 7533 bgp_dest_unlock_node(dest);
c701010e
DS
7534}
7535
6aabb15d
RZ
7536/**
7537 * Check if the current path has different MED than other known paths.
7538 *
7539 * \returns `true` if the MED matched the others else `false`.
7540 */
7541static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7542 struct bgp *bgp, struct bgp_path_info *pi)
7543{
7544 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7545
7546 /* This is the first route being analyzed. */
7547 if (!aggregate->med_initialized) {
7548 aggregate->med_initialized = true;
7549 aggregate->med_mismatched = false;
7550 aggregate->med_matched_value = cur_med;
7551 } else {
7552 /* Check if routes with different MED showed up. */
7553 if (cur_med != aggregate->med_matched_value)
7554 aggregate->med_mismatched = true;
7555 }
7556
7557 return !aggregate->med_mismatched;
7558}
7559
7560/**
7561 * Initializes and tests all routes in the aggregate address path for MED
7562 * values.
7563 *
7564 * \returns `true` if all MEDs are the same otherwise `false`.
7565 */
7566static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7567 struct bgp *bgp, const struct prefix *p,
7568 afi_t afi, safi_t safi)
7569{
7570 struct bgp_table *table = bgp->rib[afi][safi];
7571 const struct prefix *dest_p;
7572 struct bgp_dest *dest, *top;
7573 struct bgp_path_info *pi;
7574 bool med_matched = true;
7575
7576 aggregate->med_initialized = false;
7577
7578 top = bgp_node_get(table, p);
7579 for (dest = bgp_node_get(table, p); dest;
7580 dest = bgp_route_next_until(dest, top)) {
7581 dest_p = bgp_dest_get_prefix(dest);
7582 if (dest_p->prefixlen <= p->prefixlen)
7583 continue;
7584
7585 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7586 if (BGP_PATH_HOLDDOWN(pi))
7587 continue;
7588 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7589 continue;
7590 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7591 med_matched = false;
7592 break;
7593 }
7594 }
7595 if (!med_matched)
7596 break;
7597 }
7598 bgp_dest_unlock_node(top);
7599
7600 return med_matched;
7601}
7602
7603/**
7604 * Toggles the route suppression status for this aggregate address
7605 * configuration.
7606 */
4056a5f6
RZ
7607void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7608 struct bgp *bgp, const struct prefix *p,
7609 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7610{
7611 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7612 const struct prefix *dest_p;
7613 struct bgp_dest *dest, *top;
7614 struct bgp_path_info *pi;
7615 bool toggle_suppression;
7616
7617 /* We've found a different MED we must revert any suppressed routes. */
7618 top = bgp_node_get(table, p);
7619 for (dest = bgp_node_get(table, p); dest;
7620 dest = bgp_route_next_until(dest, top)) {
7621 dest_p = bgp_dest_get_prefix(dest);
7622 if (dest_p->prefixlen <= p->prefixlen)
7623 continue;
7624
7625 toggle_suppression = false;
7626 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7627 if (BGP_PATH_HOLDDOWN(pi))
7628 continue;
7629 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7630 continue;
7631
6aabb15d
RZ
7632 /* We are toggling suppression back. */
7633 if (suppress) {
6aabb15d 7634 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7635 if (aggr_suppress_path(aggregate, pi))
7636 toggle_suppression = true;
6aabb15d
RZ
7637 continue;
7638 }
7639
6aabb15d 7640 /* Install route if there is no more suppression. */
4056a5f6 7641 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7642 toggle_suppression = true;
6aabb15d
RZ
7643 }
7644
7645 if (toggle_suppression)
7646 bgp_process(bgp, dest, afi, safi);
7647 }
7648 bgp_dest_unlock_node(top);
7649}
7650
7651/**
7652 * Aggregate address MED matching incremental test: this function is called
7653 * when the initial aggregation occurred and we are only testing a single
7654 * new path.
7655 *
7656 * In addition to testing and setting the MED validity it also installs back
7657 * suppressed routes (if summary is configured).
7658 *
7659 * Must not be called in `bgp_aggregate_route`.
7660 */
7661static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7662 struct bgp *bgp, const struct prefix *p,
7663 afi_t afi, safi_t safi,
f66624f5 7664 struct bgp_path_info *pi)
6aabb15d
RZ
7665{
7666 /* MED matching disabled. */
7667 if (!aggregate->match_med)
7668 return;
7669
f66624f5
DA
7670 /* Aggregation with different MED, recheck if we have got equal MEDs
7671 * now.
6aabb15d 7672 */
f66624f5
DA
7673 if (aggregate->med_mismatched &&
7674 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7675 aggregate->summary_only)
7676 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7677 true);
7678 else
6aabb15d
RZ
7679 bgp_aggregate_med_match(aggregate, bgp, pi);
7680
7681 /* No mismatches, just quit. */
7682 if (!aggregate->med_mismatched)
7683 return;
7684
7685 /* Route summarization is disabled. */
7686 if (!aggregate->summary_only)
7687 return;
7688
7689 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7690}
7691
b5d58c32 7692/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7693void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7694 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7695{
7696 struct bgp_table *table;
9bcb3eef
DS
7697 struct bgp_dest *top;
7698 struct bgp_dest *dest;
d7c0a89a 7699 uint8_t origin;
d62a17ae 7700 struct aspath *aspath = NULL;
d62a17ae 7701 struct community *community = NULL;
3da2cc32 7702 struct ecommunity *ecommunity = NULL;
dd18c5a9 7703 struct lcommunity *lcommunity = NULL;
40381db7 7704 struct bgp_path_info *pi;
d62a17ae 7705 unsigned long match = 0;
d7c0a89a 7706 uint8_t atomic_aggregate = 0;
d62a17ae 7707
9f822fa2
S
7708 /* If the bgp instance is being deleted or self peer is deleted
7709 * then do not create aggregate route
7710 */
892fedb6
DA
7711 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7712 || (bgp->peer_self == NULL))
9f822fa2
S
7713 return;
7714
6aabb15d
RZ
7715 /* Initialize and test routes for MED difference. */
7716 if (aggregate->match_med)
7717 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7718
4056a5f6
RZ
7719 /*
7720 * Reset aggregate count: we might've been called from route map
7721 * update so in that case we must retest all more specific routes.
7722 *
7723 * \see `bgp_route_map_process_update`.
7724 */
7725 aggregate->count = 0;
7726 aggregate->incomplete_origin_count = 0;
7727 aggregate->incomplete_origin_count = 0;
7728 aggregate->egp_origin_count = 0;
7729
d62a17ae 7730 /* ORIGIN attribute: If at least one route among routes that are
7731 aggregated has ORIGIN with the value INCOMPLETE, then the
7732 aggregated route must have the ORIGIN attribute with the value
7733 INCOMPLETE. Otherwise, if at least one route among routes that
7734 are aggregated has ORIGIN with the value EGP, then the aggregated
7735 route must have the origin attribute with the value EGP. In all
7736 other case the value of the ORIGIN attribute of the aggregated
7737 route is INTERNAL. */
7738 origin = BGP_ORIGIN_IGP;
718e3744 7739
d62a17ae 7740 table = bgp->rib[afi][safi];
718e3744 7741
d62a17ae 7742 top = bgp_node_get(table, p);
9bcb3eef
DS
7743 for (dest = bgp_node_get(table, p); dest;
7744 dest = bgp_route_next_until(dest, top)) {
7745 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7746
9bcb3eef 7747 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7748 continue;
d62a17ae 7749
a77e2f4b
S
7750 /* If suppress fib is enabled and route not installed
7751 * in FIB, skip the route
7752 */
7753 if (!bgp_check_advertise(bgp, dest))
7754 continue;
7755
c2ff8b3e 7756 match = 0;
d62a17ae 7757
9bcb3eef 7758 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7759 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7760 continue;
718e3744 7761
40381db7 7762 if (pi->attr->flag
c2ff8b3e
DS
7763 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7764 atomic_aggregate = 1;
d62a17ae 7765
40381db7 7766 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7767 continue;
d62a17ae 7768
f273fef1
DS
7769 /*
7770 * summary-only aggregate route suppress
7771 * aggregated route announcements.
6aabb15d
RZ
7772 *
7773 * MED matching:
7774 * Don't create summaries if MED didn't match
7775 * otherwise neither the specific routes and the
7776 * aggregation will be announced.
f273fef1 7777 */
6aabb15d
RZ
7778 if (aggregate->summary_only
7779 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7780 if (aggr_suppress_path(aggregate, pi))
7781 match++;
d62a17ae 7782 }
c2ff8b3e 7783
365ab2e7
RZ
7784 /*
7785 * Suppress more specific routes that match the route
7786 * map results.
7787 *
7788 * MED matching:
7789 * Don't suppress routes if MED matching is enabled and
7790 * it mismatched otherwise we might end up with no
7791 * routes for this path.
7792 */
7793 if (aggregate->suppress_map_name
7794 && AGGREGATE_MED_VALID(aggregate)
7795 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7796 if (aggr_suppress_path(aggregate, pi))
7797 match++;
d62a17ae 7798 }
c2ff8b3e
DS
7799
7800 aggregate->count++;
7801
f273fef1
DS
7802 /*
7803 * If at least one route among routes that are
7804 * aggregated has ORIGIN with the value INCOMPLETE,
7805 * then the aggregated route MUST have the ORIGIN
7806 * attribute with the value INCOMPLETE. Otherwise, if
7807 * at least one route among routes that are aggregated
7808 * has ORIGIN with the value EGP, then the aggregated
7809 * route MUST have the ORIGIN attribute with the value
7810 * EGP.
7811 */
fc968841
NT
7812 switch (pi->attr->origin) {
7813 case BGP_ORIGIN_INCOMPLETE:
7814 aggregate->incomplete_origin_count++;
7815 break;
7816 case BGP_ORIGIN_EGP:
7817 aggregate->egp_origin_count++;
7818 break;
7819 default:
7820 /*Do nothing.
7821 */
7822 break;
7823 }
c2ff8b3e
DS
7824
7825 if (!aggregate->as_set)
7826 continue;
7827
f273fef1
DS
7828 /*
7829 * as-set aggregate route generate origin, as path,
7830 * and community aggregation.
7831 */
fc968841
NT
7832 /* Compute aggregate route's as-path.
7833 */
ef51a7d8 7834 bgp_compute_aggregate_aspath_hash(aggregate,
7835 pi->attr->aspath);
c2ff8b3e 7836
fc968841
NT
7837 /* Compute aggregate route's community.
7838 */
9a706b42 7839 if (bgp_attr_get_community(pi->attr))
21fec674 7840 bgp_compute_aggregate_community_hash(
9a706b42
DA
7841 aggregate,
7842 bgp_attr_get_community(pi->attr));
dd18c5a9 7843
fc968841
NT
7844 /* Compute aggregate route's extended community.
7845 */
b53e67a3 7846 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7847 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7848 aggregate,
7849 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7850
7851 /* Compute aggregate route's large community.
7852 */
1bcf3a96 7853 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7854 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7855 aggregate,
7856 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7857 }
c2ff8b3e 7858 if (match)
9bcb3eef 7859 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7860 }
21fec674 7861 if (aggregate->as_set) {
ef51a7d8 7862 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7863 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7864 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7865 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7866 }
7867
f1eb1f05 7868
9bcb3eef 7869 bgp_dest_unlock_node(top);
718e3744 7870
718e3744 7871
fc968841
NT
7872 if (aggregate->incomplete_origin_count > 0)
7873 origin = BGP_ORIGIN_INCOMPLETE;
7874 else if (aggregate->egp_origin_count > 0)
7875 origin = BGP_ORIGIN_EGP;
d62a17ae 7876
229757f1
DA
7877 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7878 origin = aggregate->origin;
7879
fc968841
NT
7880 if (aggregate->as_set) {
7881 if (aggregate->aspath)
7882 /* Retrieve aggregate route's as-path.
7883 */
7884 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7885
fc968841
NT
7886 if (aggregate->community)
7887 /* Retrieve aggregate route's community.
7888 */
7889 community = community_dup(aggregate->community);
3da2cc32 7890
fc968841
NT
7891 if (aggregate->ecommunity)
7892 /* Retrieve aggregate route's ecommunity.
7893 */
7894 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7895
fc968841
NT
7896 if (aggregate->lcommunity)
7897 /* Retrieve aggregate route's lcommunity.
7898 */
7899 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7900 }
718e3744 7901
c701010e 7902 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7903 ecommunity, lcommunity, atomic_aggregate,
7904 aggregate);
718e3744 7905}
7906
5f040085
DS
7907void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7908 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7909{
7910 struct bgp_table *table;
9bcb3eef
DS
7911 struct bgp_dest *top;
7912 struct bgp_dest *dest;
40381db7 7913 struct bgp_path_info *pi;
3b7db173
DS
7914 unsigned long match;
7915
7916 table = bgp->rib[afi][safi];
7917
7918 /* If routes exists below this node, generate aggregate routes. */
7919 top = bgp_node_get(table, p);
9bcb3eef
DS
7920 for (dest = bgp_node_get(table, p); dest;
7921 dest = bgp_route_next_until(dest, top)) {
7922 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7923
9bcb3eef 7924 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7925 continue;
7926 match = 0;
7927
9bcb3eef 7928 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7929 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7930 continue;
7931
40381db7 7932 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7933 continue;
7934
92b175bd
RZ
7935 /*
7936 * This route is suppressed: attempt to unsuppress it.
7937 *
7938 * `aggr_unsuppress_path` will fail if this particular
7939 * aggregate route was not the suppressor.
7940 */
7941 if (pi->extra && pi->extra->aggr_suppressors &&
7942 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7943 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7944 match++;
3b7db173 7945 }
365ab2e7 7946
3b7db173 7947 aggregate->count--;
fc968841
NT
7948
7949 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7950 aggregate->incomplete_origin_count--;
7951 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7952 aggregate->egp_origin_count--;
7953
7954 if (aggregate->as_set) {
7955 /* Remove as-path from aggregate.
7956 */
ef51a7d8 7957 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7958 aggregate,
7959 pi->attr->aspath);
7960
9a706b42 7961 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7962 /* Remove community from aggregate.
7963 */
21fec674 7964 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7965 aggregate,
7966 bgp_attr_get_community(
7967 pi->attr));
fc968841 7968
b53e67a3 7969 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7970 /* Remove ecommunity from aggregate.
7971 */
4edd83f9 7972 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7973 aggregate,
7974 bgp_attr_get_ecommunity(
7975 pi->attr));
fc968841 7976
1bcf3a96 7977 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7978 /* Remove lcommunity from aggregate.
7979 */
f1eb1f05 7980 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7981 aggregate,
7982 bgp_attr_get_lcommunity(
7983 pi->attr));
fc968841 7984 }
3b7db173
DS
7985 }
7986
7987 /* If this node was suppressed, process the change. */
7988 if (match)
9bcb3eef 7989 bgp_process(bgp, dest, afi, safi);
3b7db173 7990 }
f1eb1f05 7991 if (aggregate->as_set) {
ef51a7d8 7992 aspath_free(aggregate->aspath);
7993 aggregate->aspath = NULL;
21fec674 7994 if (aggregate->community)
7995 community_free(&aggregate->community);
4edd83f9 7996 if (aggregate->ecommunity)
7997 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7998 if (aggregate->lcommunity)
7999 lcommunity_free(&aggregate->lcommunity);
8000 }
8001
9bcb3eef 8002 bgp_dest_unlock_node(top);
3b7db173 8003}
718e3744 8004
5f040085
DS
8005static void bgp_add_route_to_aggregate(struct bgp *bgp,
8006 const struct prefix *aggr_p,
fc968841
NT
8007 struct bgp_path_info *pinew, afi_t afi,
8008 safi_t safi,
8009 struct bgp_aggregate *aggregate)
8010{
8011 uint8_t origin;
8012 struct aspath *aspath = NULL;
8013 uint8_t atomic_aggregate = 0;
8014 struct community *community = NULL;
8015 struct ecommunity *ecommunity = NULL;
8016 struct lcommunity *lcommunity = NULL;
8017
a4559740 8018 /* If the bgp instance is being deleted or self peer is deleted
8019 * then do not create aggregate route
8020 */
8021 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8022 || (bgp->peer_self == NULL))
8023 return;
8024
fc968841
NT
8025 /* ORIGIN attribute: If at least one route among routes that are
8026 * aggregated has ORIGIN with the value INCOMPLETE, then the
8027 * aggregated route must have the ORIGIN attribute with the value
8028 * INCOMPLETE. Otherwise, if at least one route among routes that
8029 * are aggregated has ORIGIN with the value EGP, then the aggregated
8030 * route must have the origin attribute with the value EGP. In all
8031 * other case the value of the ORIGIN attribute of the aggregated
8032 * route is INTERNAL.
8033 */
8034 origin = BGP_ORIGIN_IGP;
8035
8036 aggregate->count++;
8037
6aabb15d
RZ
8038 /*
8039 * This must be called before `summary` check to avoid
8040 * "suppressing" twice.
8041 */
8042 if (aggregate->match_med)
8043 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8044 pinew);
6aabb15d
RZ
8045
8046 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8047 aggr_suppress_path(aggregate, pinew);
fc968841 8048
365ab2e7
RZ
8049 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8050 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8051 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8052
8053 switch (pinew->attr->origin) {
8054 case BGP_ORIGIN_INCOMPLETE:
8055 aggregate->incomplete_origin_count++;
8056 break;
8057 case BGP_ORIGIN_EGP:
8058 aggregate->egp_origin_count++;
8059 break;
8060 default:
8061 /* Do nothing.
8062 */
8063 break;
8064 }
8065
8066 if (aggregate->incomplete_origin_count > 0)
8067 origin = BGP_ORIGIN_INCOMPLETE;
8068 else if (aggregate->egp_origin_count > 0)
8069 origin = BGP_ORIGIN_EGP;
8070
229757f1
DA
8071 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8072 origin = aggregate->origin;
8073
fc968841
NT
8074 if (aggregate->as_set) {
8075 /* Compute aggregate route's as-path.
8076 */
8077 bgp_compute_aggregate_aspath(aggregate,
8078 pinew->attr->aspath);
8079
8080 /* Compute aggregate route's community.
8081 */
9a706b42 8082 if (bgp_attr_get_community(pinew->attr))
fc968841 8083 bgp_compute_aggregate_community(
9a706b42 8084 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8085
8086 /* Compute aggregate route's extended community.
8087 */
b53e67a3 8088 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8089 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8090 aggregate,
8091 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8092
8093 /* Compute aggregate route's large community.
8094 */
1bcf3a96 8095 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8096 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8097 aggregate,
8098 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8099
8100 /* Retrieve aggregate route's as-path.
8101 */
8102 if (aggregate->aspath)
8103 aspath = aspath_dup(aggregate->aspath);
8104
8105 /* Retrieve aggregate route's community.
8106 */
8107 if (aggregate->community)
8108 community = community_dup(aggregate->community);
8109
8110 /* Retrieve aggregate route's ecommunity.
8111 */
8112 if (aggregate->ecommunity)
8113 ecommunity = ecommunity_dup(aggregate->ecommunity);
8114
8115 /* Retrieve aggregate route's lcommunity.
8116 */
8117 if (aggregate->lcommunity)
8118 lcommunity = lcommunity_dup(aggregate->lcommunity);
8119 }
8120
8121 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8122 aspath, community, ecommunity,
8123 lcommunity, atomic_aggregate, aggregate);
8124}
8125
8126static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8127 safi_t safi,
8128 struct bgp_path_info *pi,
8129 struct bgp_aggregate *aggregate,
5f040085 8130 const struct prefix *aggr_p)
fc968841
NT
8131{
8132 uint8_t origin;
8133 struct aspath *aspath = NULL;
8134 uint8_t atomic_aggregate = 0;
8135 struct community *community = NULL;
8136 struct ecommunity *ecommunity = NULL;
8137 struct lcommunity *lcommunity = NULL;
8138 unsigned long match = 0;
8139
a4559740 8140 /* If the bgp instance is being deleted or self peer is deleted
8141 * then do not create aggregate route
8142 */
8143 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8144 || (bgp->peer_self == NULL))
8145 return;
8146
fc968841
NT
8147 if (BGP_PATH_HOLDDOWN(pi))
8148 return;
8149
8150 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8151 return;
8152
4056a5f6
RZ
8153 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8154 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8155 match++;
fc968841 8156
365ab2e7 8157 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8158 && aggr_suppress_map_test(bgp, aggregate, pi))
8159 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8160 match++;
fc968841 8161
6aabb15d 8162 /*
365ab2e7 8163 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8164 * "unsuppressing" twice.
8165 */
8166 if (aggregate->match_med)
f66624f5 8167 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8168
fc968841
NT
8169 if (aggregate->count > 0)
8170 aggregate->count--;
8171
8172 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8173 aggregate->incomplete_origin_count--;
8174 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8175 aggregate->egp_origin_count--;
8176
8177 if (aggregate->as_set) {
8178 /* Remove as-path from aggregate.
8179 */
8180 bgp_remove_aspath_from_aggregate(aggregate,
8181 pi->attr->aspath);
8182
9a706b42 8183 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8184 /* Remove community from aggregate.
8185 */
8186 bgp_remove_community_from_aggregate(
9a706b42 8187 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8188
b53e67a3 8189 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8190 /* Remove ecommunity from aggregate.
8191 */
8192 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8193 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8194
1bcf3a96 8195 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8196 /* Remove lcommunity from aggregate.
8197 */
8198 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8199 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8200 }
8201
8202 /* If this node was suppressed, process the change. */
8203 if (match)
8204 bgp_process(bgp, pi->net, afi, safi);
8205
8206 origin = BGP_ORIGIN_IGP;
8207 if (aggregate->incomplete_origin_count > 0)
8208 origin = BGP_ORIGIN_INCOMPLETE;
8209 else if (aggregate->egp_origin_count > 0)
8210 origin = BGP_ORIGIN_EGP;
8211
229757f1
DA
8212 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8213 origin = aggregate->origin;
8214
fc968841
NT
8215 if (aggregate->as_set) {
8216 /* Retrieve aggregate route's as-path.
8217 */
8218 if (aggregate->aspath)
8219 aspath = aspath_dup(aggregate->aspath);
8220
8221 /* Retrieve aggregate route's community.
8222 */
8223 if (aggregate->community)
8224 community = community_dup(aggregate->community);
8225
8226 /* Retrieve aggregate route's ecommunity.
8227 */
8228 if (aggregate->ecommunity)
8229 ecommunity = ecommunity_dup(aggregate->ecommunity);
8230
8231 /* Retrieve aggregate route's lcommunity.
8232 */
8233 if (aggregate->lcommunity)
8234 lcommunity = lcommunity_dup(aggregate->lcommunity);
8235 }
8236
8237 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8238 aspath, community, ecommunity,
8239 lcommunity, atomic_aggregate, aggregate);
8240}
8241
5a1ae2c2 8242void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8243 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8244{
9bcb3eef
DS
8245 struct bgp_dest *child;
8246 struct bgp_dest *dest;
d62a17ae 8247 struct bgp_aggregate *aggregate;
8248 struct bgp_table *table;
718e3744 8249
d62a17ae 8250 table = bgp->aggregate[afi][safi];
f018db83 8251
d62a17ae 8252 /* No aggregates configured. */
8253 if (bgp_table_top_nolock(table) == NULL)
8254 return;
f018db83 8255
d62a17ae 8256 if (p->prefixlen == 0)
8257 return;
718e3744 8258
40381db7 8259 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8260 return;
718e3744 8261
a77e2f4b
S
8262 /* If suppress fib is enabled and route not installed
8263 * in FIB, do not update the aggregate route
8264 */
8265 if (!bgp_check_advertise(bgp, pi->net))
8266 return;
8267
d62a17ae 8268 child = bgp_node_get(table, p);
718e3744 8269
d62a17ae 8270 /* Aggregate address configuration check. */
9bcb3eef
DS
8271 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8272 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8273
9bcb3eef
DS
8274 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8275 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8276 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8277 aggregate);
d62a17ae 8278 }
b1e62edd 8279 }
9bcb3eef 8280 bgp_dest_unlock_node(child);
718e3744 8281}
8282
5a1ae2c2 8283void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8284 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8285{
9bcb3eef
DS
8286 struct bgp_dest *child;
8287 struct bgp_dest *dest;
d62a17ae 8288 struct bgp_aggregate *aggregate;
8289 struct bgp_table *table;
718e3744 8290
d62a17ae 8291 table = bgp->aggregate[afi][safi];
718e3744 8292
d62a17ae 8293 /* No aggregates configured. */
8294 if (bgp_table_top_nolock(table) == NULL)
8295 return;
718e3744 8296
d62a17ae 8297 if (p->prefixlen == 0)
8298 return;
718e3744 8299
d62a17ae 8300 child = bgp_node_get(table, p);
718e3744 8301
d62a17ae 8302 /* Aggregate address configuration check. */
9bcb3eef
DS
8303 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8304 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8305
9bcb3eef
DS
8306 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8307 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8308 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8309 aggregate, dest_p);
d62a17ae 8310 }
b1e62edd 8311 }
9bcb3eef 8312 bgp_dest_unlock_node(child);
d62a17ae 8313}
718e3744 8314
718e3744 8315/* Aggregate route attribute. */
8316#define AGGREGATE_SUMMARY_ONLY 1
8317#define AGGREGATE_AS_SET 1
fb29348a 8318#define AGGREGATE_AS_UNSET 0
718e3744 8319
229757f1
DA
8320static const char *bgp_origin2str(uint8_t origin)
8321{
8322 switch (origin) {
8323 case BGP_ORIGIN_IGP:
8324 return "igp";
8325 case BGP_ORIGIN_EGP:
8326 return "egp";
8327 case BGP_ORIGIN_INCOMPLETE:
8328 return "incomplete";
8329 }
8330 return "n/a";
8331}
8332
fdeb5a81 8333static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8334{
8335 switch (v_state) {
fdeb5a81
DS
8336 case RPKI_NOT_BEING_USED:
8337 return "not used";
8338 case RPKI_VALID:
b5b99af8 8339 return "valid";
fdeb5a81 8340 case RPKI_NOTFOUND:
b5b99af8 8341 return "not found";
fdeb5a81 8342 case RPKI_INVALID:
b5b99af8 8343 return "invalid";
b5b99af8 8344 }
fdeb5a81
DS
8345
8346 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8347 return "ERROR";
8348}
8349
585f1adc
IR
8350static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8351 afi_t afi, safi_t safi)
718e3744 8352{
585f1adc
IR
8353 VTY_DECLVAR_CONTEXT(bgp, bgp);
8354 int ret;
8355 struct prefix p;
9bcb3eef 8356 struct bgp_dest *dest;
d62a17ae 8357 struct bgp_aggregate *aggregate;
718e3744 8358
585f1adc
IR
8359 /* Convert string to prefix structure. */
8360 ret = str2prefix(prefix_str, &p);
8361 if (!ret) {
8362 vty_out(vty, "Malformed prefix\n");
8363 return CMD_WARNING_CONFIG_FAILED;
8364 }
8365 apply_mask(&p);
a4559740 8366
d62a17ae 8367 /* Old configuration check. */
585f1adc 8368 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8369 if (!dest) {
585f1adc
IR
8370 vty_out(vty,
8371 "%% There is no aggregate-address configuration.\n");
8372 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8373 }
f6269b4f 8374
9bcb3eef 8375 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8376 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8377 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8378 NULL, NULL, 0, aggregate);
d62a17ae 8379
8380 /* Unlock aggregate address configuration. */
9bcb3eef 8381 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8382
8383 if (aggregate->community)
8384 community_free(&aggregate->community);
8385
8386 if (aggregate->community_hash) {
8387 /* Delete all communities in the hash.
8388 */
8389 hash_clean(aggregate->community_hash,
8390 bgp_aggr_community_remove);
8391 /* Free up the community_hash.
8392 */
8393 hash_free(aggregate->community_hash);
8394 }
8395
8396 if (aggregate->ecommunity)
8397 ecommunity_free(&aggregate->ecommunity);
8398
8399 if (aggregate->ecommunity_hash) {
8400 /* Delete all ecommunities in the hash.
8401 */
8402 hash_clean(aggregate->ecommunity_hash,
8403 bgp_aggr_ecommunity_remove);
8404 /* Free up the ecommunity_hash.
8405 */
8406 hash_free(aggregate->ecommunity_hash);
8407 }
8408
8409 if (aggregate->lcommunity)
8410 lcommunity_free(&aggregate->lcommunity);
8411
8412 if (aggregate->lcommunity_hash) {
8413 /* Delete all lcommunities in the hash.
8414 */
8415 hash_clean(aggregate->lcommunity_hash,
8416 bgp_aggr_lcommunity_remove);
8417 /* Free up the lcommunity_hash.
8418 */
8419 hash_free(aggregate->lcommunity_hash);
8420 }
8421
8422 if (aggregate->aspath)
8423 aspath_free(aggregate->aspath);
8424
8425 if (aggregate->aspath_hash) {
8426 /* Delete all as-paths in the hash.
8427 */
8428 hash_clean(aggregate->aspath_hash,
8429 bgp_aggr_aspath_remove);
8430 /* Free up the aspath_hash.
8431 */
8432 hash_free(aggregate->aspath_hash);
8433 }
8434
d62a17ae 8435 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8436 bgp_dest_unlock_node(dest);
8437 bgp_dest_unlock_node(dest);
d62a17ae 8438
585f1adc 8439 return CMD_SUCCESS;
d62a17ae 8440}
8441
585f1adc
IR
8442static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8443 safi_t safi, const char *rmap,
8444 uint8_t summary_only, uint8_t as_set,
8445 uint8_t origin, bool match_med,
8446 const char *suppress_map)
d62a17ae 8447{
585f1adc 8448 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8449 int ret;
585f1adc 8450 struct prefix p;
9bcb3eef 8451 struct bgp_dest *dest;
d62a17ae 8452 struct bgp_aggregate *aggregate;
fb29348a 8453 uint8_t as_set_new = as_set;
d62a17ae 8454
365ab2e7 8455 if (suppress_map && summary_only) {
585f1adc 8456 vty_out(vty,
365ab2e7 8457 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8458 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8459 }
8460
585f1adc
IR
8461 /* Convert string to prefix structure. */
8462 ret = str2prefix(prefix_str, &p);
8463 if (!ret) {
8464 vty_out(vty, "Malformed prefix\n");
8465 return CMD_WARNING_CONFIG_FAILED;
8466 }
8467 apply_mask(&p);
d62a17ae 8468
585f1adc
IR
8469 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8470 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8471 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8472 prefix_str);
8473 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8474 }
8475
d62a17ae 8476 /* Old configuration check. */
585f1adc 8477 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8478 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8479
20894f50 8480 if (aggregate) {
585f1adc 8481 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8482 /* try to remove the old entry */
585f1adc 8483 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8484 if (ret) {
585f1adc 8485 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8486 bgp_dest_unlock_node(dest);
585f1adc 8487 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8488 }
8489 }
718e3744 8490
d62a17ae 8491 /* Make aggregate address structure. */
8492 aggregate = bgp_aggregate_new();
8493 aggregate->summary_only = summary_only;
6aabb15d 8494 aggregate->match_med = match_med;
fb29348a
DA
8495
8496 /* Network operators MUST NOT locally generate any new
8497 * announcements containing AS_SET or AS_CONFED_SET. If they have
8498 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8499 * SHOULD withdraw those routes and re-announce routes for the
8500 * aggregate or component prefixes (i.e., the more-specific routes
8501 * subsumed by the previously aggregated route) without AS_SET
8502 * or AS_CONFED_SET in the updates.
8503 */
7f972cd8 8504 if (bgp->reject_as_sets) {
fb29348a
DA
8505 if (as_set == AGGREGATE_AS_SET) {
8506 as_set_new = AGGREGATE_AS_UNSET;
8507 zlog_warn(
63efca0e 8508 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8509 __func__);
585f1adc 8510 vty_out(vty,
fb29348a
DA
8511 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8512 }
8513 }
8514
8515 aggregate->as_set = as_set_new;
d62a17ae 8516 aggregate->safi = safi;
229757f1
DA
8517 /* Override ORIGIN attribute if defined.
8518 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8519 * to IGP which is not what rfc4271 says.
8520 * This enables the same behavior, optionally.
8521 */
8522 aggregate->origin = origin;
20894f50
DA
8523
8524 if (rmap) {
8525 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8526 route_map_counter_decrement(aggregate->rmap.map);
8527 aggregate->rmap.name =
8528 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8529 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8530 route_map_counter_increment(aggregate->rmap.map);
8531 }
365ab2e7
RZ
8532
8533 if (suppress_map) {
8534 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8535 route_map_counter_decrement(aggregate->suppress_map);
8536
8537 aggregate->suppress_map_name =
8538 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8539 aggregate->suppress_map =
8540 route_map_lookup_by_name(aggregate->suppress_map_name);
8541 route_map_counter_increment(aggregate->suppress_map);
8542 }
8543
9bcb3eef 8544 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8545
d62a17ae 8546 /* Aggregate address insert into BGP routing table. */
585f1adc 8547 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8548
585f1adc 8549 return CMD_SUCCESS;
718e3744 8550}
8551
585f1adc
IR
8552DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8553 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8554 "as-set$as_set_s"
8555 "|summary-only$summary_only"
cacba915 8556 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8557 "|origin <egp|igp|incomplete>$origin_s"
8558 "|matching-MED-only$match_med"
cacba915 8559 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8560 "}]",
8561 NO_STR
8562 "Configure BGP aggregate entries\n"
764402fe
DA
8563 "Aggregate prefix\n"
8564 "Aggregate address\n"
8565 "Aggregate mask\n"
585f1adc
IR
8566 "Generate AS set path information\n"
8567 "Filter more specific routes from updates\n"
8568 "Apply route map to aggregate network\n"
8569 "Route map name\n"
8570 "BGP origin code\n"
8571 "Remote EGP\n"
8572 "Local IGP\n"
8573 "Unknown heritage\n"
8574 "Only aggregate routes with matching MED\n"
8575 "Suppress the selected more specific routes\n"
8576 "Route map with the route selectors\n")
8577{
8578 const char *prefix_s = NULL;
554b3b10 8579 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8580 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8581 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8582 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8583
554b3b10 8584 if (addr_str) {
7533cad7
QY
8585 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8586 sizeof(prefix_buf))
554b3b10
RZ
8587 == 0) {
8588 vty_out(vty, "%% Inconsistent address and mask\n");
8589 return CMD_WARNING_CONFIG_FAILED;
8590 }
585f1adc
IR
8591 prefix_s = prefix_buf;
8592 } else
8593 prefix_s = prefix_str;
37a87b8f 8594
585f1adc
IR
8595 if (origin_s) {
8596 if (strcmp(origin_s, "egp") == 0)
8597 origin = BGP_ORIGIN_EGP;
8598 else if (strcmp(origin_s, "igp") == 0)
8599 origin = BGP_ORIGIN_IGP;
8600 else if (strcmp(origin_s, "incomplete") == 0)
8601 origin = BGP_ORIGIN_INCOMPLETE;
8602 }
90e21f35 8603
585f1adc
IR
8604 if (as_set_s)
8605 as_set = AGGREGATE_AS_SET;
554b3b10 8606
585f1adc 8607 /* Handle configuration removal, otherwise installation. */
554b3b10 8608 if (no)
585f1adc
IR
8609 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8610
8611 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8612 summary_only != NULL, as_set, origin,
8613 match_med != NULL, suppress_map);
8614}
8615
8616DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8617 "[no] aggregate-address X:X::X:X/M$prefix [{"
8618 "as-set$as_set_s"
8619 "|summary-only$summary_only"
cacba915 8620 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8621 "|origin <egp|igp|incomplete>$origin_s"
8622 "|matching-MED-only$match_med"
cacba915 8623 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8624 "}]",
8625 NO_STR
8626 "Configure BGP aggregate entries\n"
8627 "Aggregate prefix\n"
8628 "Generate AS set path information\n"
8629 "Filter more specific routes from updates\n"
8630 "Apply route map to aggregate network\n"
8631 "Route map name\n"
8632 "BGP origin code\n"
8633 "Remote EGP\n"
8634 "Local IGP\n"
8635 "Unknown heritage\n"
8636 "Only aggregate routes with matching MED\n"
8637 "Suppress the selected more specific routes\n"
8638 "Route map with the route selectors\n")
8639{
8640 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8641 int as_set = AGGREGATE_AS_UNSET;
8642
8643 if (origin_s) {
8644 if (strcmp(origin_s, "egp") == 0)
8645 origin = BGP_ORIGIN_EGP;
8646 else if (strcmp(origin_s, "igp") == 0)
8647 origin = BGP_ORIGIN_IGP;
8648 else if (strcmp(origin_s, "incomplete") == 0)
8649 origin = BGP_ORIGIN_INCOMPLETE;
8650 }
8651
8652 if (as_set_s)
8653 as_set = AGGREGATE_AS_SET;
8654
8655 /* Handle configuration removal, otherwise installation. */
554b3b10 8656 if (no)
585f1adc
IR
8657 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8658 SAFI_UNICAST);
554b3b10 8659
585f1adc
IR
8660 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8661 rmap_name, summary_only != NULL, as_set,
8662 origin, match_med != NULL, suppress_map);
718e3744 8663}
8664
718e3744 8665/* Redistribute route treatment. */
d62a17ae 8666void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8667 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8668 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8669 enum blackhole_type bhtype, uint32_t metric,
8670 uint8_t type, unsigned short instance,
8671 route_tag_t tag)
d62a17ae 8672{
4b7e6066 8673 struct bgp_path_info *new;
40381db7
DS
8674 struct bgp_path_info *bpi;
8675 struct bgp_path_info rmap_path;
9bcb3eef 8676 struct bgp_dest *bn;
d62a17ae 8677 struct attr attr;
8678 struct attr *new_attr;
8679 afi_t afi;
b68885f9 8680 route_map_result_t ret;
d62a17ae 8681 struct bgp_redist *red;
8682
8683 /* Make default attribute. */
0f05ea43 8684 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8685 /*
8686 * This must not be NULL to satisfy Coverity SA
8687 */
8688 assert(attr.aspath);
9de1f7ff 8689
a4d82a8a 8690 switch (nhtype) {
9de1f7ff 8691 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8692 switch (p->family) {
8693 case AF_INET:
8694 attr.nexthop.s_addr = INADDR_ANY;
8695 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8696 break;
8697 case AF_INET6:
8698 memset(&attr.mp_nexthop_global, 0,
8699 sizeof(attr.mp_nexthop_global));
8700 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8701 break;
8702 }
9de1f7ff
DS
8703 break;
8704 case NEXTHOP_TYPE_IPV4:
8705 case NEXTHOP_TYPE_IPV4_IFINDEX:
8706 attr.nexthop = nexthop->ipv4;
7226bc40 8707 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8708 break;
8709 case NEXTHOP_TYPE_IPV6:
8710 case NEXTHOP_TYPE_IPV6_IFINDEX:
8711 attr.mp_nexthop_global = nexthop->ipv6;
8712 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8713 break;
8714 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8715 switch (p->family) {
8716 case AF_INET:
9de1f7ff 8717 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8718 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8719 break;
8720 case AF_INET6:
9de1f7ff
DS
8721 memset(&attr.mp_nexthop_global, 0,
8722 sizeof(attr.mp_nexthop_global));
74489921 8723 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8724 break;
74489921 8725 }
0789eb69 8726 attr.bh_type = bhtype;
9de1f7ff 8727 break;
d62a17ae 8728 }
0789eb69 8729 attr.nh_type = nhtype;
74489921 8730 attr.nh_ifindex = ifindex;
f04a80a5 8731
d62a17ae 8732 attr.med = metric;
957f74c3 8733 attr.distance = distance;
d62a17ae 8734 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8735 attr.tag = tag;
718e3744 8736
97a52c82
DA
8737 if (metric)
8738 bgp_attr_set_aigp_metric(&attr, metric);
8739
d62a17ae 8740 afi = family2afi(p->family);
6aeb9e78 8741
d62a17ae 8742 red = bgp_redist_lookup(bgp, afi, type, instance);
8743 if (red) {
8744 struct attr attr_new;
718e3744 8745
d62a17ae 8746 /* Copy attribute for modification. */
6f4f49b2 8747 attr_new = attr;
718e3744 8748
97a52c82 8749 if (red->redist_metric_flag) {
d62a17ae 8750 attr_new.med = red->redist_metric;
97a52c82
DA
8751 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8752 }
718e3744 8753
d62a17ae 8754 /* Apply route-map. */
8755 if (red->rmap.name) {
6006b807 8756 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8757 rmap_path.peer = bgp->peer_self;
8758 rmap_path.attr = &attr_new;
718e3744 8759
d62a17ae 8760 SET_FLAG(bgp->peer_self->rmap_type,
8761 PEER_RMAP_TYPE_REDISTRIBUTE);
8762
1782514f 8763 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8764
8765 bgp->peer_self->rmap_type = 0;
8766
8767 if (ret == RMAP_DENYMATCH) {
8768 /* Free uninterned attribute. */
8769 bgp_attr_flush(&attr_new);
8770
8771 /* Unintern original. */
8772 aspath_unintern(&attr.aspath);
8773 bgp_redistribute_delete(bgp, p, type, instance);
8774 return;
8775 }
8776 }
8777
637e5ba4 8778 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8779 bgp_attr_add_gshut_community(&attr_new);
8780
d62a17ae 8781 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8782 SAFI_UNICAST, p, NULL);
8783
8784 new_attr = bgp_attr_intern(&attr_new);
8785
9bcb3eef 8786 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8787 if (bpi->peer == bgp->peer_self
8788 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8789 break;
8790
40381db7 8791 if (bpi) {
d62a17ae 8792 /* Ensure the (source route) type is updated. */
40381db7
DS
8793 bpi->type = type;
8794 if (attrhash_cmp(bpi->attr, new_attr)
8795 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8796 bgp_attr_unintern(&new_attr);
8797 aspath_unintern(&attr.aspath);
9bcb3eef 8798 bgp_dest_unlock_node(bn);
d62a17ae 8799 return;
8800 } else {
8801 /* The attribute is changed. */
40381db7 8802 bgp_path_info_set_flag(bn, bpi,
18ee8310 8803 BGP_PATH_ATTR_CHANGED);
d62a17ae 8804
8805 /* Rewrite BGP route information. */
40381db7
DS
8806 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8807 bgp_path_info_restore(bn, bpi);
d62a17ae 8808 else
40381db7
DS
8809 bgp_aggregate_decrement(
8810 bgp, p, bpi, afi, SAFI_UNICAST);
8811 bgp_attr_unintern(&bpi->attr);
8812 bpi->attr = new_attr;
083ec940 8813 bpi->uptime = monotime(NULL);
d62a17ae 8814
8815 /* Process change. */
40381db7 8816 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8817 SAFI_UNICAST);
8818 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8819 bgp_dest_unlock_node(bn);
d62a17ae 8820 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8821
8822 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8823 || (bgp->inst_type
8824 == BGP_INSTANCE_TYPE_DEFAULT)) {
8825
8826 vpn_leak_from_vrf_update(
40381db7 8827 bgp_get_default(), bgp, bpi);
ddb5b488 8828 }
d62a17ae 8829 return;
8830 }
8831 }
8832
8833 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8834 bgp->peer_self, new_attr, bn);
1defdda8 8835 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8836
8837 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8838 bgp_path_info_add(bn, new);
9bcb3eef 8839 bgp_dest_unlock_node(bn);
be785e35 8840 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8841 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8842
8843 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8844 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8845
8846 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8847 }
d62a17ae 8848 }
8849
8850 /* Unintern original. */
8851 aspath_unintern(&attr.aspath);
718e3744 8852}
8853
d7c0a89a
QY
8854void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8855 unsigned short instance)
718e3744 8856{
d62a17ae 8857 afi_t afi;
9bcb3eef 8858 struct bgp_dest *dest;
40381db7 8859 struct bgp_path_info *pi;
d62a17ae 8860 struct bgp_redist *red;
718e3744 8861
d62a17ae 8862 afi = family2afi(p->family);
718e3744 8863
d62a17ae 8864 red = bgp_redist_lookup(bgp, afi, type, instance);
8865 if (red) {
9bcb3eef
DS
8866 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8867 SAFI_UNICAST, p, NULL);
d62a17ae 8868
9bcb3eef 8869 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8870 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8871 break;
8872
40381db7 8873 if (pi) {
ddb5b488
PZ
8874 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8875 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8876
8877 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8878 bgp, pi);
ddb5b488 8879 }
40381db7 8880 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8881 bgp_path_info_delete(dest, pi);
8882 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8883 }
9bcb3eef 8884 bgp_dest_unlock_node(dest);
d62a17ae 8885 }
8886}
8887
8888/* Withdraw specified route type's route. */
8889void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8890 unsigned short instance)
d62a17ae 8891{
9bcb3eef 8892 struct bgp_dest *dest;
40381db7 8893 struct bgp_path_info *pi;
d62a17ae 8894 struct bgp_table *table;
8895
8896 table = bgp->rib[afi][SAFI_UNICAST];
8897
9bcb3eef
DS
8898 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8899 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8900 if (pi->peer == bgp->peer_self && pi->type == type
8901 && pi->instance == instance)
d62a17ae 8902 break;
8903
40381db7 8904 if (pi) {
ddb5b488
PZ
8905 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8906 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8907
8908 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8909 bgp, pi);
ddb5b488 8910 }
9bcb3eef 8911 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8912 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8913 bgp_path_info_delete(dest, pi);
8914 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8915 }
718e3744 8916 }
718e3744 8917}
6b0655a2 8918
718e3744 8919/* Static function to display route. */
7d3cae70
DA
8920static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8921 struct vty *vty, json_object *json, bool wide)
718e3744 8922{
be054588 8923 int len = 0;
07380148 8924 char buf[INET6_ADDRSTRLEN];
718e3744 8925
d62a17ae 8926 if (p->family == AF_INET) {
c6462ff4 8927 if (!json) {
8228a9a7 8928 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8929 } else {
8930 json_object_string_add(json, "prefix",
8931 inet_ntop(p->family,
8932 &p->u.prefix, buf,
07380148 8933 sizeof(buf)));
c6462ff4 8934 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8935 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8936 json_object_int_add(json, "version", dest->version);
c6462ff4 8937 }
d62a17ae 8938 } else if (p->family == AF_ETHERNET) {
8228a9a7 8939 len = vty_out(vty, "%pFX", p);
b03b8898 8940 } else if (p->family == AF_EVPN) {
57f7feb6 8941 if (!json)
2dbe669b 8942 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8943 else
60466a63 8944 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8945 } else if (p->family == AF_FLOWSPEC) {
8946 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8947 json ?
8948 NLRI_STRING_FORMAT_JSON_SIMPLE :
8949 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8950 } else {
c6462ff4 8951 if (!json)
8228a9a7 8952 len = vty_out(vty, "%pFX", p);
50e05855
AD
8953 else {
8954 json_object_string_add(json, "prefix",
07380148
DA
8955 inet_ntop(p->family,
8956 &p->u.prefix, buf,
8957 sizeof(buf)));
50e05855 8958 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8959 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8960 json_object_int_add(json, "version", dest->version);
37d4e0df 8961 }
9c92b5f7 8962 }
d62a17ae 8963
9c92b5f7 8964 if (!json) {
ae248832 8965 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8966 if (len < 1)
8967 vty_out(vty, "\n%*s", 20, " ");
8968 else
8969 vty_out(vty, "%*s", len, " ");
8970 }
718e3744 8971}
8972
d62a17ae 8973enum bgp_display_type {
8974 normal_list,
718e3744 8975};
8976
1d7260a1 8977const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8978{
8979 switch (reason) {
8980 case bgp_path_selection_none:
8981 return "Nothing to Select";
8982 case bgp_path_selection_first:
8983 return "First path received";
8984 case bgp_path_selection_evpn_sticky_mac:
8985 return "EVPN Sticky Mac";
8986 case bgp_path_selection_evpn_seq:
8987 return "EVPN sequence number";
8988 case bgp_path_selection_evpn_lower_ip:
8989 return "EVPN lower IP";
8990 case bgp_path_selection_evpn_local_path:
8991 return "EVPN local ES path";
8992 case bgp_path_selection_evpn_non_proxy:
8993 return "EVPN non proxy";
8994 case bgp_path_selection_weight:
8995 return "Weight";
8996 case bgp_path_selection_local_pref:
8997 return "Local Pref";
46dbf9d0
DA
8998 case bgp_path_selection_accept_own:
8999 return "Accept Own";
bbb46eb5
DA
9000 case bgp_path_selection_local_route:
9001 return "Local Route";
97a52c82
DA
9002 case bgp_path_selection_aigp:
9003 return "AIGP";
bbb46eb5
DA
9004 case bgp_path_selection_confed_as_path:
9005 return "Confederation based AS Path";
9006 case bgp_path_selection_as_path:
9007 return "AS Path";
9008 case bgp_path_selection_origin:
9009 return "Origin";
9010 case bgp_path_selection_med:
9011 return "MED";
9012 case bgp_path_selection_peer:
9013 return "Peer Type";
9014 case bgp_path_selection_confed:
9015 return "Confed Peer Type";
9016 case bgp_path_selection_igp_metric:
9017 return "IGP Metric";
9018 case bgp_path_selection_older:
9019 return "Older Path";
9020 case bgp_path_selection_router_id:
9021 return "Router ID";
9022 case bgp_path_selection_cluster_length:
bcab253c 9023 return "Cluster length";
bbb46eb5
DA
9024 case bgp_path_selection_stale:
9025 return "Path Staleness";
9026 case bgp_path_selection_local_configured:
9027 return "Locally configured route";
9028 case bgp_path_selection_neighbor_ip:
9029 return "Neighbor IP";
9030 case bgp_path_selection_default:
9031 return "Nothing left to compare";
9032 }
9033 return "Invalid (internal error)";
9034}
9035
18ee8310 9036/* Print the short form route status for a bgp_path_info */
4b7e6066 9037static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9038 struct bgp_path_info *path,
82c298be 9039 const struct prefix *p,
d62a17ae 9040 json_object *json_path)
718e3744 9041{
82c298be
DA
9042 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9043
d62a17ae 9044 if (json_path) {
b05a1c8b 9045
d62a17ae 9046 /* Route status display. */
9b6d8fcf 9047 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9048 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9049
9b6d8fcf 9050 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9051 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9052
4056a5f6 9053 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9054 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9055
9b6d8fcf
DS
9056 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9057 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9058 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9059
d62a17ae 9060 /* Selected */
9b6d8fcf 9061 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9062 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9063
9b6d8fcf 9064 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9065 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9066
bbb46eb5 9067 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9068 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9069 json_object_string_add(json_path, "selectionReason",
9070 bgp_path_selection_reason2str(
9071 path->net->reason));
9072 }
b05a1c8b 9073
9b6d8fcf 9074 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9075 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9076
d62a17ae 9077 /* Internal route. */
9b6d8fcf
DS
9078 if ((path->peer->as)
9079 && (path->peer->as == path->peer->local_as))
d62a17ae 9080 json_object_string_add(json_path, "pathFrom",
9081 "internal");
9082 else
9083 json_object_string_add(json_path, "pathFrom",
9084 "external");
b05a1c8b 9085
d62a17ae 9086 return;
9087 }
b05a1c8b 9088
82c298be
DA
9089 /* RPKI validation state */
9090 rpki_state =
9091 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9092
9093 if (rpki_state == RPKI_VALID)
9094 vty_out(vty, "V");
9095 else if (rpki_state == RPKI_INVALID)
9096 vty_out(vty, "I");
9097 else if (rpki_state == RPKI_NOTFOUND)
9098 vty_out(vty, "N");
eaeba5e8
WM
9099 else
9100 vty_out(vty, " ");
82c298be 9101
d62a17ae 9102 /* Route status display. */
9b6d8fcf 9103 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9104 vty_out(vty, "R");
9b6d8fcf 9105 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9106 vty_out(vty, "S");
4056a5f6 9107 else if (bgp_path_suppressed(path))
d62a17ae 9108 vty_out(vty, "s");
9b6d8fcf
DS
9109 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9110 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9111 vty_out(vty, "*");
9112 else
9113 vty_out(vty, " ");
9114
9115 /* Selected */
9b6d8fcf 9116 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9117 vty_out(vty, "h");
9b6d8fcf 9118 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9119 vty_out(vty, "d");
9b6d8fcf 9120 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9121 vty_out(vty, ">");
9b6d8fcf 9122 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9123 vty_out(vty, "=");
9124 else
9125 vty_out(vty, " ");
718e3744 9126
d62a17ae 9127 /* Internal route. */
9b6d8fcf
DS
9128 if (path->peer && (path->peer->as)
9129 && (path->peer->as == path->peer->local_as))
d62a17ae 9130 vty_out(vty, "i");
9131 else
9132 vty_out(vty, " ");
b40d939b 9133}
9134
2ba93fd6
DA
9135static char *bgp_nexthop_hostname(struct peer *peer,
9136 struct bgp_nexthop_cache *bnc)
25b5da8d 9137{
892fedb6 9138 if (peer->hostname
aef999a2 9139 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9140 return peer->hostname;
9141 return NULL;
9142}
9143
b40d939b 9144/* called from terminal list command */
bd494ec5 9145void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9146 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9147 json_object *json_paths, bool wide)
d62a17ae 9148{
aef999a2 9149 int len;
515c2602 9150 struct attr *attr = path->attr;
d62a17ae 9151 json_object *json_path = NULL;
9152 json_object *json_nexthops = NULL;
9153 json_object *json_nexthop_global = NULL;
9154 json_object *json_nexthop_ll = NULL;
6f214dd3 9155 json_object *json_ext_community = NULL;
9df8b37c 9156 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9157 bool nexthop_self =
9b6d8fcf 9158 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9159 bool nexthop_othervrf = false;
43089216 9160 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9161 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9162 char *nexthop_hostname =
9163 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9164 char esi_buf[ESI_STR_LEN];
d62a17ae 9165
9166 if (json_paths)
9167 json_path = json_object_new_object();
9168
9169 /* short status lead text */
82c298be 9170 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9171
9172 if (!json_paths) {
9173 /* print prefix and mask */
9174 if (!display)
7d3cae70 9175 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9176 else
ae248832 9177 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9178 } else {
7d3cae70 9179 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9180 }
47fc97cc 9181
9df8b37c
PZ
9182 /*
9183 * If vrf id of nexthop is different from that of prefix,
9184 * set up printable string to append
9185 */
9b6d8fcf 9186 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9187 const char *self = "";
9188
9189 if (nexthop_self)
9190 self = "<";
9191
9192 nexthop_othervrf = true;
9b6d8fcf 9193 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9194
9b6d8fcf 9195 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9196 snprintf(vrf_id_str, sizeof(vrf_id_str),
9197 "@%s%s", VRFID_NONE_STR, self);
9198 else
9199 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9200 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9201
9b6d8fcf
DS
9202 if (path->extra->bgp_orig->inst_type
9203 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9204
9b6d8fcf 9205 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9206 } else {
9207 const char *self = "";
9208
9209 if (nexthop_self)
9210 self = "<";
9211
9212 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9213 }
9214
445c2480
DS
9215 /*
9216 * For ENCAP and EVPN routes, nexthop address family is not
9217 * neccessarily the same as the prefix address family.
9218 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9219 * EVPN routes are also exchanged with a MP nexthop. Currently,
9220 * this
9221 * is only IPv4, the value will be present in either
9222 * attr->nexthop or
9223 * attr->mp_nexthop_global_in
9224 */
9225 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
445c2480
DS
9226 char nexthop[128];
9227 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9228
9229 switch (af) {
9230 case AF_INET:
07380148
DA
9231 snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9232 &attr->mp_nexthop_global_in);
445c2480
DS
9233 break;
9234 case AF_INET6:
07380148
DA
9235 snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9236 &attr->mp_nexthop_global);
445c2480
DS
9237 break;
9238 default:
772270f3 9239 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9240 break;
d62a17ae 9241 }
d62a17ae 9242
445c2480
DS
9243 if (json_paths) {
9244 json_nexthop_global = json_object_new_object();
9245
515c2602
DA
9246 json_object_string_add(json_nexthop_global, "ip",
9247 nexthop);
9248
939a97f4 9249 if (path->peer->hostname)
515c2602
DA
9250 json_object_string_add(json_nexthop_global,
9251 "hostname",
939a97f4 9252 path->peer->hostname);
515c2602
DA
9253
9254 json_object_string_add(json_nexthop_global, "afi",
9255 (af == AF_INET) ? "ipv4"
9256 : "ipv6");
445c2480
DS
9257 json_object_boolean_true_add(json_nexthop_global,
9258 "used");
aef999a2
DA
9259 } else {
9260 if (nexthop_hostname)
9261 len = vty_out(vty, "%s(%s)%s", nexthop,
9262 nexthop_hostname, vrf_id_str);
9263 else
9264 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9265
ae248832 9266 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9267 if (len < 1)
9268 vty_out(vty, "\n%*s", 36, " ");
9269 else
9270 vty_out(vty, "%*s", len, " ");
9271 }
445c2480
DS
9272 } else if (safi == SAFI_EVPN) {
9273 if (json_paths) {
9274 json_nexthop_global = json_object_new_object();
9275
c949c771 9276 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9277 "%pI4",
9278 &attr->mp_nexthop_global_in);
515c2602 9279
939a97f4 9280 if (path->peer->hostname)
515c2602
DA
9281 json_object_string_add(json_nexthop_global,
9282 "hostname",
939a97f4 9283 path->peer->hostname);
515c2602 9284
a4d82a8a
PZ
9285 json_object_string_add(json_nexthop_global, "afi",
9286 "ipv4");
445c2480
DS
9287 json_object_boolean_true_add(json_nexthop_global,
9288 "used");
aef999a2
DA
9289 } else {
9290 if (nexthop_hostname)
7226bc40
TA
9291 len = vty_out(vty, "%pI4(%s)%s",
9292 &attr->mp_nexthop_global_in,
aef999a2
DA
9293 nexthop_hostname, vrf_id_str);
9294 else
7226bc40
TA
9295 len = vty_out(vty, "%pI4%s",
9296 &attr->mp_nexthop_global_in,
aef999a2
DA
9297 vrf_id_str);
9298
ae248832 9299 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9300 if (len < 1)
9301 vty_out(vty, "\n%*s", 36, " ");
9302 else
9303 vty_out(vty, "%*s", len, " ");
9304 }
d33fc23b 9305 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9306 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9307 if (json_paths) {
9308 json_nexthop_global = json_object_new_object();
515c2602 9309
026b914a
PG
9310 json_object_string_add(json_nexthop_global,
9311 "afi", "ipv4");
c949c771
DA
9312 json_object_string_addf(json_nexthop_global,
9313 "ip", "%pI4",
9314 &attr->nexthop);
515c2602 9315
939a97f4 9316 if (path->peer->hostname)
515c2602
DA
9317 json_object_string_add(
9318 json_nexthop_global, "hostname",
939a97f4 9319 path->peer->hostname);
515c2602 9320
50e05855
AD
9321 json_object_boolean_true_add(
9322 json_nexthop_global,
026b914a
PG
9323 "used");
9324 } else {
aef999a2
DA
9325 if (nexthop_hostname)
9326 len = vty_out(vty, "%pI4(%s)%s",
9327 &attr->nexthop,
9328 nexthop_hostname,
9329 vrf_id_str);
9330 else
9331 len = vty_out(vty, "%pI4%s",
9332 &attr->nexthop,
9333 vrf_id_str);
9334
ae248832 9335 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9336 if (len < 1)
9337 vty_out(vty, "\n%*s", 36, " ");
9338 else
9339 vty_out(vty, "%*s", len, " ");
026b914a
PG
9340 }
9341 }
7226bc40 9342 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9343 if (json_paths) {
9344 json_nexthop_global = json_object_new_object();
d62a17ae 9345
c949c771
DA
9346 json_object_string_addf(json_nexthop_global, "ip",
9347 "%pI4", &attr->nexthop);
515c2602 9348
939a97f4 9349 if (path->peer->hostname)
515c2602
DA
9350 json_object_string_add(json_nexthop_global,
9351 "hostname",
939a97f4 9352 path->peer->hostname);
445c2480 9353
a4d82a8a
PZ
9354 json_object_string_add(json_nexthop_global, "afi",
9355 "ipv4");
445c2480
DS
9356 json_object_boolean_true_add(json_nexthop_global,
9357 "used");
9358 } else {
aef999a2
DA
9359 if (nexthop_hostname)
9360 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9361 nexthop_hostname, vrf_id_str);
9362 else
9363 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9364 vrf_id_str);
9df8b37c 9365
ae248832 9366 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9367 if (len < 1)
9368 vty_out(vty, "\n%*s", 36, " ");
9369 else
9370 vty_out(vty, "%*s", len, " ");
d62a17ae 9371 }
445c2480 9372 }
b05a1c8b 9373
445c2480 9374 /* IPv6 Next Hop */
7226bc40 9375 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9376 if (json_paths) {
9377 json_nexthop_global = json_object_new_object();
c949c771
DA
9378 json_object_string_addf(json_nexthop_global, "ip",
9379 "%pI6",
9380 &attr->mp_nexthop_global);
515c2602 9381
939a97f4 9382 if (path->peer->hostname)
515c2602
DA
9383 json_object_string_add(json_nexthop_global,
9384 "hostname",
939a97f4 9385 path->peer->hostname);
515c2602 9386
a4d82a8a
PZ
9387 json_object_string_add(json_nexthop_global, "afi",
9388 "ipv6");
9389 json_object_string_add(json_nexthop_global, "scope",
9390 "global");
445c2480
DS
9391
9392 /* We display both LL & GL if both have been
9393 * received */
0606039c
DA
9394 if ((attr->mp_nexthop_len
9395 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9396 || (path->peer->conf_if)) {
a4d82a8a 9397 json_nexthop_ll = json_object_new_object();
c949c771
DA
9398 json_object_string_addf(
9399 json_nexthop_ll, "ip", "%pI6",
9400 &attr->mp_nexthop_local);
515c2602 9401
939a97f4 9402 if (path->peer->hostname)
515c2602
DA
9403 json_object_string_add(
9404 json_nexthop_ll, "hostname",
939a97f4 9405 path->peer->hostname);
515c2602 9406
a4d82a8a
PZ
9407 json_object_string_add(json_nexthop_ll, "afi",
9408 "ipv6");
9409 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9410 "link-local");
d62a17ae 9411
a4d82a8a
PZ
9412 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9413 &attr->mp_nexthop_local)
445c2480
DS
9414 != 0)
9415 && !attr->mp_nexthop_prefer_global)
d62a17ae 9416 json_object_boolean_true_add(
a4d82a8a 9417 json_nexthop_ll, "used");
445c2480
DS
9418 else
9419 json_object_boolean_true_add(
a4d82a8a 9420 json_nexthop_global, "used");
445c2480
DS
9421 } else
9422 json_object_boolean_true_add(
9423 json_nexthop_global, "used");
9424 } else {
9425 /* Display LL if LL/Global both in table unless
9426 * prefer-global is set */
0606039c
DA
9427 if (((attr->mp_nexthop_len
9428 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9429 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9430 || (path->peer->conf_if)) {
9431 if (path->peer->conf_if) {
a4d82a8a 9432 len = vty_out(vty, "%s",
9b6d8fcf 9433 path->peer->conf_if);
ae248832
MK
9434 /* len of IPv6 addr + max len of def
9435 * ifname */
9436 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9437
9438 if (len < 1)
a4d82a8a 9439 vty_out(vty, "\n%*s", 36, " ");
445c2480 9440 else
a4d82a8a 9441 vty_out(vty, "%*s", len, " ");
d62a17ae 9442 } else {
aef999a2
DA
9443 if (nexthop_hostname)
9444 len = vty_out(
9445 vty, "%pI6(%s)%s",
9446 &attr->mp_nexthop_local,
9447 nexthop_hostname,
9448 vrf_id_str);
9449 else
9450 len = vty_out(
9451 vty, "%pI6%s",
9452 &attr->mp_nexthop_local,
9453 vrf_id_str);
9454
ae248832 9455 len = wide ? (41 - len) : (16 - len);
d62a17ae 9456
9457 if (len < 1)
a4d82a8a 9458 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9459 else
a4d82a8a 9460 vty_out(vty, "%*s", len, " ");
d62a17ae 9461 }
445c2480 9462 } else {
aef999a2
DA
9463 if (nexthop_hostname)
9464 len = vty_out(vty, "%pI6(%s)%s",
9465 &attr->mp_nexthop_global,
9466 nexthop_hostname,
9467 vrf_id_str);
9468 else
9469 len = vty_out(vty, "%pI6%s",
9470 &attr->mp_nexthop_global,
9471 vrf_id_str);
9472
ae248832 9473 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9474
9475 if (len < 1)
9476 vty_out(vty, "\n%*s", 36, " ");
9477 else
9478 vty_out(vty, "%*s", len, " ");
d62a17ae 9479 }
9480 }
445c2480 9481 }
718e3744 9482
445c2480
DS
9483 /* MED/Metric */
9484 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9485 if (json_paths)
50e05855 9486 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9487 else if (wide)
9488 vty_out(vty, "%7u", attr->med);
0fbac0b4 9489 else
445c2480 9490 vty_out(vty, "%10u", attr->med);
ae248832
MK
9491 else if (!json_paths) {
9492 if (wide)
9493 vty_out(vty, "%*s", 7, " ");
9494 else
9495 vty_out(vty, "%*s", 10, " ");
9496 }
d62a17ae 9497
445c2480
DS
9498 /* Local Pref */
9499 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9500 if (json_paths)
50e05855 9501 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9502 attr->local_pref);
9503 else
445c2480
DS
9504 vty_out(vty, "%7u", attr->local_pref);
9505 else if (!json_paths)
9506 vty_out(vty, " ");
d62a17ae 9507
445c2480
DS
9508 if (json_paths)
9509 json_object_int_add(json_path, "weight", attr->weight);
9510 else
9511 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9512
47e12884
DA
9513 if (json_paths)
9514 json_object_string_addf(json_path, "peerId", "%pSU",
9515 &path->peer->su);
b05a1c8b 9516
445c2480
DS
9517 /* Print aspath */
9518 if (attr->aspath) {
0fbac0b4 9519 if (json_paths)
50e05855 9520 json_object_string_add(json_path, "path",
0fbac0b4
DA
9521 attr->aspath->str);
9522 else
445c2480 9523 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9524 }
f1aa5d8a 9525
445c2480
DS
9526 /* Print origin */
9527 if (json_paths)
a4d82a8a
PZ
9528 json_object_string_add(json_path, "origin",
9529 bgp_origin_long_str[attr->origin]);
445c2480
DS
9530 else
9531 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9532
9df8b37c 9533 if (json_paths) {
d071f237 9534 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9535 json_object_string_add(json_path, "esi",
9536 esi_to_str(&attr->esi,
9537 esi_buf, sizeof(esi_buf)));
9538 }
6f214dd3
CS
9539 if (safi == SAFI_EVPN &&
9540 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9541 json_ext_community = json_object_new_object();
b53e67a3
DA
9542 json_object_string_add(
9543 json_ext_community, "string",
9544 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9545 json_object_object_add(json_path,
9546 "extendedCommunity",
9547 json_ext_community);
9548 }
9549
9df8b37c
PZ
9550 if (nexthop_self)
9551 json_object_boolean_true_add(json_path,
9552 "announceNexthopSelf");
9553 if (nexthop_othervrf) {
9554 json_object_string_add(json_path, "nhVrfName",
9555 nexthop_vrfname);
9556
9557 json_object_int_add(json_path, "nhVrfId",
9558 ((nexthop_vrfid == VRF_UNKNOWN)
9559 ? -1
9560 : (int)nexthop_vrfid));
9561 }
9562 }
9563
d62a17ae 9564 if (json_paths) {
9565 if (json_nexthop_global || json_nexthop_ll) {
9566 json_nexthops = json_object_new_array();
f1aa5d8a 9567
d62a17ae 9568 if (json_nexthop_global)
9569 json_object_array_add(json_nexthops,
9570 json_nexthop_global);
f1aa5d8a 9571
d62a17ae 9572 if (json_nexthop_ll)
9573 json_object_array_add(json_nexthops,
9574 json_nexthop_ll);
f1aa5d8a 9575
d62a17ae 9576 json_object_object_add(json_path, "nexthops",
9577 json_nexthops);
9578 }
9579
9580 json_object_array_add(json_paths, json_path);
9581 } else {
9582 vty_out(vty, "\n");
6f214dd3 9583
b5e140c8 9584 if (safi == SAFI_EVPN) {
d071f237 9585 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9586 /* XXX - add these params to the json out */
b5e140c8 9587 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9588 vty_out(vty, "ESI:%s",
9589 esi_to_str(&attr->esi, esi_buf,
9590 sizeof(esi_buf)));
60605cbc 9591
229587fb 9592 vty_out(vty, "\n");
b5e140c8
AK
9593 }
9594 if (attr->flag &
9595 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9596 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9597 vty_out(vty, "%s\n",
9598 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9599 }
6f214dd3
CS
9600 }
9601
49e5a4a0 9602#ifdef ENABLE_BGP_VNC
d62a17ae 9603 /* prints an additional line, indented, with VNC info, if
9604 * present */
9605 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9606 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9607#endif
d62a17ae 9608 }
9609}
718e3744 9610
9611/* called from terminal list command */
7d3cae70
DA
9612void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9613 const struct prefix *p, struct attr *attr, safi_t safi,
9614 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9615{
9616 json_object *json_status = NULL;
9617 json_object *json_net = NULL;
aef999a2 9618 int len;
d62a17ae 9619 char buff[BUFSIZ];
dc387b0f 9620
d62a17ae 9621 /* Route status display. */
9622 if (use_json) {
9623 json_status = json_object_new_object();
9624 json_net = json_object_new_object();
9625 } else {
146c574b 9626 vty_out(vty, " *");
d62a17ae 9627 vty_out(vty, ">");
9628 vty_out(vty, " ");
9629 }
718e3744 9630
d62a17ae 9631 /* print prefix and mask */
50e05855 9632 if (use_json) {
dc387b0f
LK
9633 if (safi == SAFI_EVPN)
9634 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9635 else if (p->family == AF_INET || p->family == AF_INET6) {
9636 json_object_string_add(
9637 json_net, "addrPrefix",
9638 inet_ntop(p->family, &p->u.prefix, buff,
9639 BUFSIZ));
9640 json_object_int_add(json_net, "prefixLen",
9641 p->prefixlen);
67d7e256 9642 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9643 }
50e05855 9644 } else
7d3cae70 9645 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9646
9647 /* Print attribute */
9648 if (attr) {
9649 if (use_json) {
7226bc40
TA
9650 if (p->family == AF_INET &&
9651 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9652 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9653 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9654 json_object_string_addf(
9655 json_net, "nextHop", "%pI4",
9656 &attr->mp_nexthop_global_in);
d62a17ae 9657 else
c949c771
DA
9658 json_object_string_addf(
9659 json_net, "nextHop", "%pI4",
9660 &attr->nexthop);
7226bc40
TA
9661 } else if (p->family == AF_INET6 ||
9662 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9663 json_object_string_addf(
9664 json_net, "nextHopGlobal", "%pI6",
9665 &attr->mp_nexthop_global);
7226bc40
TA
9666 } else if (p->family == AF_EVPN &&
9667 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9668 json_object_string_addf(
9669 json_net, "nextHop", "%pI4",
9670 &attr->mp_nexthop_global_in);
23d0a753 9671 }
d62a17ae 9672
9673 if (attr->flag
9674 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9675 json_object_int_add(json_net, "metric",
9676 attr->med);
9677
0fbac0b4 9678 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9679 json_object_int_add(json_net, "locPrf",
0fbac0b4 9680 attr->local_pref);
d62a17ae 9681
9682 json_object_int_add(json_net, "weight", attr->weight);
9683
9684 /* Print aspath */
0fbac0b4 9685 if (attr->aspath)
50e05855 9686 json_object_string_add(json_net, "path",
0fbac0b4 9687 attr->aspath->str);
d62a17ae 9688
9689 /* Print origin */
dd426a51
DA
9690#if CONFDATE > 20231208
9691CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9692#endif
d62a17ae 9693 json_object_string_add(json_net, "bgpOriginCode",
9694 bgp_origin_str[attr->origin]);
dd426a51
DA
9695 json_object_string_add(
9696 json_net, "origin",
9697 bgp_origin_long_str[attr->origin]);
d62a17ae 9698 } else {
7226bc40
TA
9699 if (p->family == AF_INET &&
9700 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9701 safi == SAFI_EVPN ||
9702 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9703 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9704 || safi == SAFI_EVPN)
23d0a753
DA
9705 vty_out(vty, "%-16pI4",
9706 &attr->mp_nexthop_global_in);
ae248832 9707 else if (wide)
23d0a753 9708 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9709 else
23d0a753 9710 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9711 } else if (p->family == AF_INET6 ||
9712 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
07380148
DA
9713 len = vty_out(vty, "%pI6",
9714 &attr->mp_nexthop_global);
ae248832 9715 len = wide ? (41 - len) : (16 - len);
d62a17ae 9716 if (len < 1)
9717 vty_out(vty, "\n%*s", 36, " ");
9718 else
9719 vty_out(vty, "%*s", len, " ");
9720 }
9721 if (attr->flag
9722 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9723 if (wide)
9724 vty_out(vty, "%7u", attr->med);
9725 else
9726 vty_out(vty, "%10u", attr->med);
9727 else if (wide)
9728 vty_out(vty, " ");
d62a17ae 9729 else
9730 vty_out(vty, " ");
718e3744 9731
d62a17ae 9732 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9733 vty_out(vty, "%7u", attr->local_pref);
9734 else
9735 vty_out(vty, " ");
9736
9737 vty_out(vty, "%7u ", attr->weight);
9738
9739 /* Print aspath */
9740 if (attr->aspath)
9741 aspath_print_vty(vty, "%s", attr->aspath, " ");
9742
9743 /* Print origin */
9744 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9745 }
9746 }
9747 if (use_json) {
4d65410c
DA
9748 struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9749
dd426a51
DA
9750#if CONFDATE > 20231208
9751CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9752#endif
d62a17ae 9753 json_object_boolean_true_add(json_status, "*");
9754 json_object_boolean_true_add(json_status, ">");
dd426a51
DA
9755 json_object_boolean_true_add(json_net, "valid");
9756 json_object_boolean_true_add(json_net, "best");
4d65410c 9757
dd426a51 9758 if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
4d65410c 9759 json_object_boolean_true_add(json_status, "=");
dd426a51
DA
9760 json_object_boolean_true_add(json_net, "multipath");
9761 }
d62a17ae 9762 json_object_object_add(json_net, "appliedStatusSymbols",
9763 json_status);
511211bf 9764 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9765 } else
9766 vty_out(vty, "\n");
9767}
9768
bd494ec5 9769void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9770 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9771 json_object *json)
9772{
9773 json_object *json_out = NULL;
9774 struct attr *attr;
9775 mpls_label_t label = MPLS_INVALID_LABEL;
9776
9b6d8fcf 9777 if (!path->extra)
d62a17ae 9778 return;
9779
9780 if (json)
9781 json_out = json_object_new_object();
9782
9783 /* short status lead text */
82c298be 9784 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9785
9786 /* print prefix and mask */
9787 if (json == NULL) {
9788 if (!display)
7d3cae70 9789 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9790 else
9791 vty_out(vty, "%*s", 17, " ");
9792 }
9793
9794 /* Print attribute */
9b6d8fcf 9795 attr = path->attr;
7226bc40
TA
9796 if (((p->family == AF_INET) &&
9797 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9798 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9799 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9800 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9801 || safi == SAFI_EVPN) {
9802 if (json)
c949c771
DA
9803 json_object_string_addf(
9804 json_out, "mpNexthopGlobalIn", "%pI4",
9805 &attr->mp_nexthop_global_in);
05864da7 9806 else
23d0a753
DA
9807 vty_out(vty, "%-16pI4",
9808 &attr->mp_nexthop_global_in);
05864da7
DS
9809 } else {
9810 if (json)
c949c771
DA
9811 json_object_string_addf(json_out, "nexthop",
9812 "%pI4", &attr->nexthop);
05864da7 9813 else
23d0a753 9814 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9815 }
7226bc40
TA
9816 } else if (((p->family == AF_INET6) &&
9817 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9818 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9819 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9820 char buf_a[512];
9821
9822 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9823 if (json)
c949c771
DA
9824 json_object_string_addf(
9825 json_out, "mpNexthopGlobalIn", "%pI6",
9826 &attr->mp_nexthop_global);
05864da7
DS
9827 else
9828 vty_out(vty, "%s",
9829 inet_ntop(AF_INET6,
9830 &attr->mp_nexthop_global,
9831 buf_a, sizeof(buf_a)));
9832 } else if (attr->mp_nexthop_len
9833 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9834 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9835 &attr->mp_nexthop_global,
9836 &attr->mp_nexthop_local);
9837 if (json)
9838 json_object_string_add(json_out,
9839 "mpNexthopGlobalLocal",
9840 buf_a);
9841 else
9842 vty_out(vty, "%s", buf_a);
d62a17ae 9843 }
9844 }
9845
9b6d8fcf 9846 label = decode_label(&path->extra->label[0]);
d62a17ae 9847
9848 if (bgp_is_valid_label(&label)) {
9849 if (json) {
9850 json_object_int_add(json_out, "notag", label);
9851 json_object_array_add(json, json_out);
9852 } else {
9853 vty_out(vty, "notag/%d", label);
9854 vty_out(vty, "\n");
9855 }
700ddfed
PG
9856 } else if (!json)
9857 vty_out(vty, "\n");
d62a17ae 9858}
718e3744 9859
bd494ec5 9860void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9861 struct bgp_path_info *path, int display,
d62a17ae 9862 json_object *json_paths)
718e3744 9863{
d62a17ae 9864 struct attr *attr;
d62a17ae 9865 json_object *json_path = NULL;
14f51eba
LK
9866 json_object *json_nexthop = NULL;
9867 json_object *json_overlay = NULL;
856ca177 9868
9b6d8fcf 9869 if (!path->extra)
d62a17ae 9870 return;
718e3744 9871
14f51eba
LK
9872 if (json_paths) {
9873 json_path = json_object_new_object();
9874 json_overlay = json_object_new_object();
9875 json_nexthop = json_object_new_object();
9876 }
9877
d62a17ae 9878 /* short status lead text */
82c298be 9879 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9880
d62a17ae 9881 /* print prefix and mask */
9882 if (!display)
7d3cae70 9883 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9884 else
9885 vty_out(vty, "%*s", 17, " ");
9886
9887 /* Print attribute */
9b6d8fcf 9888 attr = path->attr;
05864da7 9889 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9890
05864da7
DS
9891 switch (af) {
9892 case AF_INET:
05864da7 9893 if (!json_path) {
db66cf7c 9894 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9895 } else {
db66cf7c
DA
9896 json_object_string_addf(json_nexthop, "ip", "%pI4",
9897 &attr->mp_nexthop_global_in);
14f51eba 9898
05864da7 9899 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9900
05864da7
DS
9901 json_object_object_add(json_path, "nexthop",
9902 json_nexthop);
9903 }
9904 break;
9905 case AF_INET6:
05864da7 9906 if (!json_path) {
db66cf7c
DA
9907 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9908 &attr->mp_nexthop_local);
05864da7 9909 } else {
db66cf7c
DA
9910 json_object_string_addf(json_nexthop, "ipv6Global",
9911 "%pI6",
9912 &attr->mp_nexthop_global);
14f51eba 9913
db66cf7c
DA
9914 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9915 "%pI6",
9916 &attr->mp_nexthop_local);
14f51eba 9917
05864da7 9918 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9919
05864da7
DS
9920 json_object_object_add(json_path, "nexthop",
9921 json_nexthop);
9922 }
9923 break;
9924 default:
9925 if (!json_path) {
9926 vty_out(vty, "?");
9927 } else {
9928 json_object_string_add(json_nexthop, "Error",
9929 "Unsupported address-family");
77a2f8e5
DA
9930 json_object_string_add(json_nexthop, "error",
9931 "Unsupported address-family");
d62a17ae 9932 }
05864da7 9933 }
988258b4 9934
6c924775
DS
9935 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9936
05864da7 9937 if (!json_path)
db66cf7c 9938 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9939 else
db66cf7c 9940 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9941
b53e67a3 9942 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9943 char *mac = NULL;
9944 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9945 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9946 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9947
9948 if (routermac)
9949 mac = ecom_mac2str((char *)routermac->val);
9950 if (mac) {
9951 if (!json_path) {
c4efd0f4 9952 vty_out(vty, "/%s", mac);
05864da7
DS
9953 } else {
9954 json_object_string_add(json_overlay, "rmac",
9955 mac);
988258b4 9956 }
05864da7 9957 XFREE(MTYPE_TMP, mac);
988258b4 9958 }
05864da7 9959 }
718e3744 9960
05864da7
DS
9961 if (!json_path) {
9962 vty_out(vty, "\n");
9963 } else {
9964 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9965
05864da7 9966 json_object_array_add(json_paths, json_path);
14f51eba 9967 }
d62a17ae 9968}
718e3744 9969
d62a17ae 9970/* dampening route */
5f040085
DS
9971static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9972 struct bgp_path_info *path, int display,
9973 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9974 json_object *json_paths)
d62a17ae 9975{
e5be8c1d 9976 struct attr *attr = path->attr;
d62a17ae 9977 int len;
9978 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9979 json_object *json_path = NULL;
9980
9981 if (use_json)
9982 json_path = json_object_new_object();
d62a17ae 9983
9984 /* short status lead text */
e5be8c1d 9985 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9986
9987 /* print prefix and mask */
9988 if (!use_json) {
9989 if (!display)
7d3cae70 9990 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9991 else
9992 vty_out(vty, "%*s", 17, " ");
d62a17ae 9993
e5be8c1d
DA
9994 len = vty_out(vty, "%s", path->peer->host);
9995 len = 17 - len;
9996
9997 if (len < 1)
d62a17ae 9998 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9999 else
10000 vty_out(vty, "%*s", len, " ");
d62a17ae 10001
9b6d8fcf
DS
10002 vty_out(vty, "%s ",
10003 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10004 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 10005 use_json, NULL));
d62a17ae 10006
e5be8c1d 10007 if (attr->aspath)
05864da7 10008 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10009
05864da7
DS
10010 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10011
d62a17ae 10012 vty_out(vty, "\n");
e5be8c1d
DA
10013 } else {
10014 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
10015 safi, use_json, json_path);
10016
10017 if (attr->aspath)
10018 json_object_string_add(json_path, "asPath",
10019 attr->aspath->str);
10020
10021 json_object_string_add(json_path, "origin",
10022 bgp_origin_str[attr->origin]);
10023 json_object_string_add(json_path, "peerHost", path->peer->host);
10024
10025 json_object_array_add(json_paths, json_path);
10026 }
d62a17ae 10027}
718e3744 10028
d62a17ae 10029/* flap route */
5f040085
DS
10030static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10031 struct bgp_path_info *path, int display,
10032 afi_t afi, safi_t safi, bool use_json,
31258046 10033 json_object *json_paths)
784d3a42 10034{
31258046 10035 struct attr *attr = path->attr;
d62a17ae 10036 struct bgp_damp_info *bdi;
10037 char timebuf[BGP_UPTIME_LEN];
10038 int len;
31258046 10039 json_object *json_path = NULL;
784d3a42 10040
9b6d8fcf 10041 if (!path->extra)
d62a17ae 10042 return;
784d3a42 10043
31258046
DA
10044 if (use_json)
10045 json_path = json_object_new_object();
10046
9b6d8fcf 10047 bdi = path->extra->damp_info;
784d3a42 10048
d62a17ae 10049 /* short status lead text */
31258046 10050 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10051
d62a17ae 10052 if (!use_json) {
10053 if (!display)
7d3cae70 10054 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10055 else
10056 vty_out(vty, "%*s", 17, " ");
784d3a42 10057
31258046
DA
10058 len = vty_out(vty, "%s", path->peer->host);
10059 len = 16 - len;
10060 if (len < 1)
d62a17ae 10061 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10062 else
10063 vty_out(vty, "%*s", len, " ");
784d3a42 10064
31258046
DA
10065 len = vty_out(vty, "%d", bdi->flap);
10066 len = 5 - len;
10067 if (len < 1)
d62a17ae 10068 vty_out(vty, " ");
d62a17ae 10069 else
10070 vty_out(vty, "%*s", len, " ");
d62a17ae 10071
996c9314
LB
10072 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10073 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10074
31258046
DA
10075 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10076 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10077 vty_out(vty, "%s ",
9b6d8fcf 10078 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10079 BGP_UPTIME_LEN, afi,
31258046
DA
10080 safi, use_json, NULL));
10081 else
d62a17ae 10082 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10083
31258046 10084 if (attr->aspath)
05864da7 10085 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10086
05864da7
DS
10087 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10088
d62a17ae 10089 vty_out(vty, "\n");
31258046
DA
10090 } else {
10091 json_object_string_add(json_path, "peerHost", path->peer->host);
10092 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10093
10094 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10095 json_path);
10096
10097 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10098 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10099 bgp_damp_reuse_time_vty(vty, path, timebuf,
10100 BGP_UPTIME_LEN, afi, safi,
10101 use_json, json_path);
10102
10103 if (attr->aspath)
10104 json_object_string_add(json_path, "asPath",
10105 attr->aspath->str);
10106
10107 json_object_string_add(json_path, "origin",
10108 bgp_origin_str[attr->origin]);
10109
10110 json_object_array_add(json_paths, json_path);
10111 }
d62a17ae 10112}
10113
10114static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10115 int *first, const char *header,
10116 json_object *json_adv_to)
10117{
d62a17ae 10118 json_object *json_peer = NULL;
10119
10120 if (json_adv_to) {
10121 /* 'advertised-to' is a dictionary of peers we have advertised
10122 * this
10123 * prefix too. The key is the peer's IP or swpX, the value is
10124 * the
10125 * hostname if we know it and "" if not.
10126 */
10127 json_peer = json_object_new_object();
10128
10129 if (peer->hostname)
10130 json_object_string_add(json_peer, "hostname",
10131 peer->hostname);
10132
10133 if (peer->conf_if)
10134 json_object_object_add(json_adv_to, peer->conf_if,
10135 json_peer);
10136 else
47e12884
DA
10137 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10138 &peer->su);
d62a17ae 10139 } else {
10140 if (*first) {
10141 vty_out(vty, "%s", header);
10142 *first = 0;
10143 }
10144
10145 if (peer->hostname
892fedb6 10146 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10147 if (peer->conf_if)
10148 vty_out(vty, " %s(%s)", peer->hostname,
10149 peer->conf_if);
10150 else
47e12884
DA
10151 vty_out(vty, " %s(%pSU)", peer->hostname,
10152 &peer->su);
d62a17ae 10153 } else {
10154 if (peer->conf_if)
10155 vty_out(vty, " %s", peer->conf_if);
10156 else
47e12884 10157 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10158 }
10159 }
784d3a42
PG
10160}
10161
dcc68b5e
MS
10162static void route_vty_out_tx_ids(struct vty *vty,
10163 struct bgp_addpath_info_data *d)
10164{
10165 int i;
10166
10167 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10168 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10169 d->addpath_tx_id[i],
10170 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10171 }
10172}
10173
5e4d4c8a 10174static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10175 struct bgp_path_info *pi,
10176 struct attr *attr,
10177 json_object *json_path)
5e4d4c8a
AK
10178{
10179 char esi_buf[ESI_STR_LEN];
10180 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10181 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10182 ATTR_ES_PEER_ROUTER);
10183 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10184 ATTR_ES_PEER_ACTIVE);
10185 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10186 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10187 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10188 if (json_path) {
10189 json_object *json_es_info = NULL;
10190
10191 json_object_string_add(
10192 json_path, "esi",
10193 esi_buf);
10194 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10195 json_es_info = json_object_new_object();
10196 if (es_local)
10197 json_object_boolean_true_add(
10198 json_es_info, "localEs");
10199 if (peer_active)
10200 json_object_boolean_true_add(
10201 json_es_info, "peerActive");
10202 if (peer_proxy)
10203 json_object_boolean_true_add(
10204 json_es_info, "peerProxy");
10205 if (peer_router)
10206 json_object_boolean_true_add(
10207 json_es_info, "peerRouter");
10208 if (attr->mm_sync_seqnum)
10209 json_object_int_add(
10210 json_es_info, "peerSeq",
10211 attr->mm_sync_seqnum);
10212 json_object_object_add(
10213 json_path, "es_info",
10214 json_es_info);
10215 }
10216 } else {
10217 if (bgp_evpn_attr_is_sync(attr))
10218 vty_out(vty,
10219 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10220 esi_buf,
10221 es_local ? "local-es":"",
10222 peer_proxy ? "proxy " : "",
10223 peer_active ? "active ":"",
10224 peer_router ? "router ":"",
10225 attr->mm_sync_seqnum);
10226 else
10227 vty_out(vty, " ESI %s %s\n",
10228 esi_buf,
10229 es_local ? "local-es":"");
10230 }
10231}
10232
4933eaaf 10233void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10234 const struct prefix *p, struct bgp_path_info *path,
10235 afi_t afi, safi_t safi,
4027d19b
DS
10236 enum rpki_states rpki_curr_state,
10237 json_object *json_paths)
d62a17ae 10238{
10239 char buf[INET6_ADDRSTRLEN];
100290e4 10240 char tag_buf[30];
515c2602 10241 struct attr *attr = path->attr;
d62a17ae 10242 time_t tbuf;
10243 json_object *json_bestpath = NULL;
10244 json_object *json_cluster_list = NULL;
10245 json_object *json_cluster_list_list = NULL;
10246 json_object *json_ext_community = NULL;
10247 json_object *json_last_update = NULL;
7fd077aa 10248 json_object *json_pmsi = NULL;
d62a17ae 10249 json_object *json_nexthop_global = NULL;
10250 json_object *json_nexthop_ll = NULL;
10251 json_object *json_nexthops = NULL;
10252 json_object *json_path = NULL;
10253 json_object *json_peer = NULL;
10254 json_object *json_string = NULL;
10255 json_object *json_adv_to = NULL;
10256 int first = 0;
10257 struct listnode *node, *nnode;
10258 struct peer *peer;
be92fc9f 10259 bool addpath_capable;
d62a17ae 10260 int has_adj;
10261 unsigned int first_as;
1defdda8 10262 bool nexthop_self =
9b6d8fcf 10263 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10264 int i;
2ba93fd6
DA
10265 char *nexthop_hostname =
10266 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10267 uint32_t ttl = 0;
10268 uint32_t bos = 0;
10269 uint32_t exp = 0;
10270 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10271 tag_buf[0] = '\0';
f0cde006
LS
10272 struct bgp_path_info *bpi_ultimate =
10273 bgp_get_imported_bpi_ultimate(path);
d62a17ae 10274
10275 if (json_paths) {
10276 json_path = json_object_new_object();
10277 json_peer = json_object_new_object();
10278 json_nexthop_global = json_object_new_object();
10279 }
10280
8304dabf
AD
10281 if (safi == SAFI_EVPN) {
10282 if (!json_paths)
34c7f35f 10283 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10284 }
10285
44c69747 10286 if (path->extra) {
9b6d8fcf
DS
10287 if (path->extra && path->extra->num_labels) {
10288 bgp_evpn_label2str(path->extra->label,
10289 path->extra->num_labels, tag_buf,
a4d82a8a 10290 sizeof(tag_buf));
d62a17ae 10291 }
d7325ee7 10292 if (safi == SAFI_EVPN) {
44c69747 10293 if (!json_paths) {
44c69747
LK
10294 if (tag_buf[0] != '\0')
10295 vty_out(vty, " VNI %s", tag_buf);
44c69747 10296 } else {
77a2f8e5 10297 if (tag_buf[0]) {
44c69747
LK
10298 json_object_string_add(json_path, "VNI",
10299 tag_buf);
77a2f8e5
DA
10300 json_object_string_add(json_path, "vni",
10301 tag_buf);
10302 }
44c69747 10303 }
d7325ee7 10304 }
d62a17ae 10305 }
d62a17ae 10306
8304dabf
AD
10307 if (safi == SAFI_EVPN
10308 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10309 char gwip_buf[INET6_ADDRSTRLEN];
10310
860e740b
IR
10311 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10312 sizeof(gwip_buf));
8304dabf
AD
10313
10314 if (json_paths)
10315 json_object_string_add(json_path, "gatewayIP",
10316 gwip_buf);
10317 else
10318 vty_out(vty, " Gateway IP %s", gwip_buf);
10319 }
10320
2bf9780b 10321 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10322 vty_out(vty, "\n");
10323
100290e4
SW
10324
10325 if (path->extra && path->extra->parent && !json_paths) {
10326 struct bgp_path_info *parent_ri;
10327 struct bgp_dest *dest, *pdest;
10328
10329 parent_ri = (struct bgp_path_info *)path->extra->parent;
10330 dest = parent_ri->net;
10331 if (dest && dest->pdest) {
10332 pdest = dest->pdest;
10333 if (is_pi_family_evpn(parent_ri)) {
10334 vty_out(vty,
10335 " Imported from %pRD:%pFX, VNI %s",
10336 (struct prefix_rd *)bgp_dest_get_prefix(
10337 pdest),
10338 (struct prefix_evpn *)
10339 bgp_dest_get_prefix(dest),
10340 tag_buf);
6012963e 10341 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10342 vty_out(vty, ", L3NHG %s",
6012963e
SW
10343 CHECK_FLAG(
10344 attr->es_flags,
10345 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10346 ? "active"
10347 : "inactive");
10348 vty_out(vty, "\n");
10349
10350 } else
10351 vty_out(vty, " Imported from %pRD:%pFX\n",
10352 (struct prefix_rd *)bgp_dest_get_prefix(
10353 pdest),
10354 (struct prefix_evpn *)
10355 bgp_dest_get_prefix(dest));
10356 }
10357 }
10358
05864da7
DS
10359 /* Line1 display AS-path, Aggregator */
10360 if (attr->aspath) {
10361 if (json_paths) {
10362 if (!attr->aspath->json)
10363 aspath_str_update(attr->aspath, true);
10364 json_object_lock(attr->aspath->json);
10365 json_object_object_add(json_path, "aspath",
10366 attr->aspath->json);
10367 } else {
10368 if (attr->aspath->segments)
10369 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10370 else
05864da7 10371 vty_out(vty, " Local");
d62a17ae 10372 }
05864da7 10373 }
d62a17ae 10374
05864da7
DS
10375 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10376 if (json_paths)
10377 json_object_boolean_true_add(json_path, "removed");
10378 else
10379 vty_out(vty, ", (removed)");
10380 }
d62a17ae 10381
05864da7
DS
10382 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10383 if (json_paths)
10384 json_object_boolean_true_add(json_path, "stale");
10385 else
10386 vty_out(vty, ", (stale)");
10387 }
d62a17ae 10388
05864da7
DS
10389 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10390 if (json_paths) {
10391 json_object_int_add(json_path, "aggregatorAs",
10392 attr->aggregator_as);
c949c771
DA
10393 json_object_string_addf(json_path, "aggregatorId",
10394 "%pI4", &attr->aggregator_addr);
05864da7 10395 } else {
88d495a9
DA
10396 vty_out(vty, ", (aggregated by %u %pI4)",
10397 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10398 }
05864da7 10399 }
d62a17ae 10400
05864da7
DS
10401 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10402 PEER_FLAG_REFLECTOR_CLIENT)) {
10403 if (json_paths)
10404 json_object_boolean_true_add(json_path,
10405 "rxedFromRrClient");
10406 else
10407 vty_out(vty, ", (Received from a RR-client)");
10408 }
d62a17ae 10409
05864da7
DS
10410 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10411 PEER_FLAG_RSERVER_CLIENT)) {
10412 if (json_paths)
10413 json_object_boolean_true_add(json_path,
10414 "rxedFromRsClient");
10415 else
10416 vty_out(vty, ", (Received from a RS-client)");
10417 }
d62a17ae 10418
05864da7
DS
10419 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10420 if (json_paths)
10421 json_object_boolean_true_add(json_path,
10422 "dampeningHistoryEntry");
10423 else
10424 vty_out(vty, ", (history entry)");
10425 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10426 if (json_paths)
10427 json_object_boolean_true_add(json_path,
10428 "dampeningSuppressed");
10429 else
10430 vty_out(vty, ", (suppressed due to dampening)");
10431 }
d62a17ae 10432
05864da7
DS
10433 if (!json_paths)
10434 vty_out(vty, "\n");
d62a17ae 10435
05864da7
DS
10436 /* Line2 display Next-hop, Neighbor, Router-id */
10437 /* Display the nexthop */
b54892e0 10438
34c7f35f
SW
10439 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10440 p->family == AF_EVPN) &&
7226bc40
TA
10441 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10442 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10443 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10444 || safi == SAFI_EVPN) {
515c2602 10445 if (json_paths) {
c949c771
DA
10446 json_object_string_addf(
10447 json_nexthop_global, "ip", "%pI4",
10448 &attr->mp_nexthop_global_in);
515c2602 10449
939a97f4 10450 if (path->peer->hostname)
515c2602
DA
10451 json_object_string_add(
10452 json_nexthop_global, "hostname",
939a97f4 10453 path->peer->hostname);
aef999a2
DA
10454 } else {
10455 if (nexthop_hostname)
10456 vty_out(vty, " %pI4(%s)",
10457 &attr->mp_nexthop_global_in,
10458 nexthop_hostname);
10459 else
10460 vty_out(vty, " %pI4",
10461 &attr->mp_nexthop_global_in);
10462 }
d62a17ae 10463 } else {
515c2602 10464 if (json_paths) {
c949c771
DA
10465 json_object_string_addf(json_nexthop_global,
10466 "ip", "%pI4",
10467 &attr->nexthop);
515c2602 10468
939a97f4 10469 if (path->peer->hostname)
515c2602
DA
10470 json_object_string_add(
10471 json_nexthop_global, "hostname",
939a97f4 10472 path->peer->hostname);
aef999a2
DA
10473 } else {
10474 if (nexthop_hostname)
10475 vty_out(vty, " %pI4(%s)",
10476 &attr->nexthop,
10477 nexthop_hostname);
10478 else
10479 vty_out(vty, " %pI4",
10480 &attr->nexthop);
10481 }
d62a17ae 10482 }
10483
05864da7
DS
10484 if (json_paths)
10485 json_object_string_add(json_nexthop_global, "afi",
10486 "ipv4");
10487 } else {
10488 if (json_paths) {
c949c771
DA
10489 json_object_string_addf(json_nexthop_global, "ip",
10490 "%pI6",
10491 &attr->mp_nexthop_global);
515c2602 10492
939a97f4 10493 if (path->peer->hostname)
515c2602
DA
10494 json_object_string_add(json_nexthop_global,
10495 "hostname",
939a97f4 10496 path->peer->hostname);
515c2602 10497
05864da7
DS
10498 json_object_string_add(json_nexthop_global, "afi",
10499 "ipv6");
10500 json_object_string_add(json_nexthop_global, "scope",
10501 "global");
10502 } else {
aef999a2
DA
10503 if (nexthop_hostname)
10504 vty_out(vty, " %pI6(%s)",
10505 &attr->mp_nexthop_global,
10506 nexthop_hostname);
10507 else
10508 vty_out(vty, " %pI6",
10509 &attr->mp_nexthop_global);
d62a17ae 10510 }
05864da7 10511 }
d62a17ae 10512
05864da7 10513 /* Display the IGP cost or 'inaccessible' */
f0cde006 10514 if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10515 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10516
10517 if (json_paths) {
05864da7
DS
10518 json_object_boolean_false_add(json_nexthop_global,
10519 "accessible");
95ba22d5
DA
10520 json_object_boolean_add(json_nexthop_global,
10521 "importCheckEnabled", import);
10522 } else {
10523 vty_out(vty, " (inaccessible%s)",
10524 import ? ", import-check enabled" : "");
10525 }
05864da7 10526 } else {
f0cde006 10527 if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
d62a17ae 10528 if (json_paths)
f0cde006
LS
10529 json_object_int_add(
10530 json_nexthop_global, "metric",
10531 bpi_ultimate->extra->igpmetric);
d62a17ae 10532 else
05864da7 10533 vty_out(vty, " (metric %u)",
f0cde006 10534 bpi_ultimate->extra->igpmetric);
d62a17ae 10535 }
10536
05864da7 10537 /* IGP cost is 0, display this only for json */
d62a17ae 10538 else {
d62a17ae 10539 if (json_paths)
05864da7
DS
10540 json_object_int_add(json_nexthop_global,
10541 "metric", 0);
d62a17ae 10542 }
d62a17ae 10543
05864da7
DS
10544 if (json_paths)
10545 json_object_boolean_true_add(json_nexthop_global,
10546 "accessible");
10547 }
d62a17ae 10548
05864da7
DS
10549 /* Display peer "from" output */
10550 /* This path was originated locally */
10551 if (path->peer == bgp->peer_self) {
d62a17ae 10552
34c7f35f 10553 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10554 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10555 if (json_paths)
05864da7
DS
10556 json_object_string_add(json_peer, "peerId",
10557 "0.0.0.0");
d62a17ae 10558 else
05864da7
DS
10559 vty_out(vty, " from 0.0.0.0 ");
10560 } else {
d62a17ae 10561 if (json_paths)
05864da7
DS
10562 json_object_string_add(json_peer, "peerId",
10563 "::");
d62a17ae 10564 else
05864da7 10565 vty_out(vty, " from :: ");
d62a17ae 10566 }
d62a17ae 10567
4e9a9863 10568 if (json_paths)
c949c771
DA
10569 json_object_string_addf(json_peer, "routerId", "%pI4",
10570 &bgp->router_id);
4e9a9863 10571 else
23d0a753 10572 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10573 }
d62a17ae 10574
05864da7
DS
10575 /* We RXed this path from one of our peers */
10576 else {
10577
10578 if (json_paths) {
47e12884
DA
10579 json_object_string_addf(json_peer, "peerId", "%pSU",
10580 &path->peer->su);
c949c771
DA
10581 json_object_string_addf(json_peer, "routerId", "%pI4",
10582 &path->peer->remote_id);
05864da7
DS
10583
10584 if (path->peer->hostname)
10585 json_object_string_add(json_peer, "hostname",
10586 path->peer->hostname);
10587
10588 if (path->peer->domainname)
10589 json_object_string_add(json_peer, "domainname",
10590 path->peer->domainname);
10591
10592 if (path->peer->conf_if)
10593 json_object_string_add(json_peer, "interface",
10594 path->peer->conf_if);
10595 } else {
10596 if (path->peer->conf_if) {
10597 if (path->peer->hostname
892fedb6
DA
10598 && CHECK_FLAG(path->peer->bgp->flags,
10599 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10600 vty_out(vty, " from %s(%s)",
10601 path->peer->hostname,
10602 path->peer->conf_if);
d62a17ae 10603 else
05864da7 10604 vty_out(vty, " from %s",
9b6d8fcf 10605 path->peer->conf_if);
d62a17ae 10606 } else {
05864da7 10607 if (path->peer->hostname
892fedb6
DA
10608 && CHECK_FLAG(path->peer->bgp->flags,
10609 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10610 vty_out(vty, " from %s(%s)",
10611 path->peer->hostname,
10612 path->peer->host);
d62a17ae 10613 else
47e12884
DA
10614 vty_out(vty, " from %pSU",
10615 &path->peer->su);
d62a17ae 10616 }
d62a17ae 10617
05864da7 10618 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10619 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7 10620 else
07380148 10621 vty_out(vty, " (%pI4)", &path->peer->remote_id);
d62a17ae 10622 }
05864da7 10623 }
9df8b37c 10624
05864da7
DS
10625 /*
10626 * Note when vrfid of nexthop is different from that of prefix
10627 */
10628 if (path->extra && path->extra->bgp_orig) {
10629 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10630
05864da7
DS
10631 if (json_paths) {
10632 const char *vn;
9df8b37c 10633
05864da7
DS
10634 if (path->extra->bgp_orig->inst_type
10635 == BGP_INSTANCE_TYPE_DEFAULT)
10636 vn = VRF_DEFAULT_NAME;
10637 else
10638 vn = path->extra->bgp_orig->name;
9df8b37c 10639
05864da7 10640 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10641
05864da7
DS
10642 if (nexthop_vrfid == VRF_UNKNOWN) {
10643 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10644 } else {
05864da7
DS
10645 json_object_int_add(json_path, "nhVrfId",
10646 (int)nexthop_vrfid);
9df8b37c 10647 }
05864da7
DS
10648 } else {
10649 if (nexthop_vrfid == VRF_UNKNOWN)
10650 vty_out(vty, " vrf ?");
137147c6
DS
10651 else {
10652 struct vrf *vrf;
10653
10654 vrf = vrf_lookup_by_id(nexthop_vrfid);
10655 vty_out(vty, " vrf %s(%u)",
10656 VRF_LOGNAME(vrf), nexthop_vrfid);
10657 }
9df8b37c 10658 }
05864da7 10659 }
9df8b37c 10660
05864da7
DS
10661 if (nexthop_self) {
10662 if (json_paths) {
10663 json_object_boolean_true_add(json_path,
10664 "announceNexthopSelf");
10665 } else {
10666 vty_out(vty, " announce-nh-self");
9df8b37c 10667 }
05864da7 10668 }
9df8b37c 10669
05864da7
DS
10670 if (!json_paths)
10671 vty_out(vty, "\n");
d62a17ae 10672
05864da7
DS
10673 /* display the link-local nexthop */
10674 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10675 if (json_paths) {
10676 json_nexthop_ll = json_object_new_object();
c949c771
DA
10677 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10678 &attr->mp_nexthop_local);
515c2602 10679
939a97f4 10680 if (path->peer->hostname)
515c2602
DA
10681 json_object_string_add(json_nexthop_ll,
10682 "hostname",
939a97f4 10683 path->peer->hostname);
515c2602 10684
05864da7
DS
10685 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10686 json_object_string_add(json_nexthop_ll, "scope",
10687 "link-local");
d62a17ae 10688
05864da7
DS
10689 json_object_boolean_true_add(json_nexthop_ll,
10690 "accessible");
d62a17ae 10691
05864da7 10692 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10693 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10694 "used");
10695 else
10696 json_object_boolean_true_add(
10697 json_nexthop_global, "used");
10698 } else {
10699 vty_out(vty, " (%s) %s\n",
10700 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10701 buf, INET6_ADDRSTRLEN),
10702 attr->mp_nexthop_prefer_global
10703 ? "(prefer-global)"
10704 : "(used)");
d62a17ae 10705 }
05864da7
DS
10706 }
10707 /* If we do not have a link-local nexthop then we must flag the
10708 global as "used" */
10709 else {
10710 if (json_paths)
10711 json_object_boolean_true_add(json_nexthop_global,
10712 "used");
10713 }
d62a17ae 10714
b5e140c8 10715 if (safi == SAFI_EVPN &&
5e4d4c8a 10716 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10717 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10718 }
10719
05864da7
DS
10720 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10721 * Int/Ext/Local, Atomic, best */
10722 if (json_paths)
10723 json_object_string_add(json_path, "origin",
10724 bgp_origin_long_str[attr->origin]);
10725 else
10726 vty_out(vty, " Origin %s",
10727 bgp_origin_long_str[attr->origin]);
9df8b37c 10728
05864da7 10729 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10730 if (json_paths)
05864da7 10731 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10732 else
05864da7
DS
10733 vty_out(vty, ", metric %u", attr->med);
10734 }
9df8b37c 10735
05864da7
DS
10736 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10737 if (json_paths)
0fbac0b4 10738 json_object_int_add(json_path, "locPrf",
05864da7
DS
10739 attr->local_pref);
10740 else
10741 vty_out(vty, ", localpref %u", attr->local_pref);
10742 }
9df8b37c 10743
97a52c82
DA
10744 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10745 if (json_paths)
10746 json_object_int_add(json_path, "aigpMetric",
10747 bgp_attr_get_aigp_metric(attr));
10748 else
10749 vty_out(vty, ", aigp-metric %" PRIu64,
10750 bgp_attr_get_aigp_metric(attr));
10751 }
10752
05864da7
DS
10753 if (attr->weight != 0) {
10754 if (json_paths)
10755 json_object_int_add(json_path, "weight", attr->weight);
10756 else
10757 vty_out(vty, ", weight %u", attr->weight);
10758 }
9df8b37c 10759
05864da7
DS
10760 if (attr->tag != 0) {
10761 if (json_paths)
10762 json_object_int_add(json_path, "tag", attr->tag);
10763 else
10764 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10765 }
9df8b37c 10766
05864da7
DS
10767 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10768 if (json_paths)
10769 json_object_boolean_false_add(json_path, "valid");
10770 else
10771 vty_out(vty, ", invalid");
10772 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10773 if (json_paths)
10774 json_object_boolean_true_add(json_path, "valid");
10775 else
10776 vty_out(vty, ", valid");
10777 }
9df8b37c 10778
7d3cae70
DA
10779 if (json_paths)
10780 json_object_int_add(json_path, "version", bn->version);
10781
05864da7
DS
10782 if (path->peer != bgp->peer_self) {
10783 if (path->peer->as == path->peer->local_as) {
10784 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10785 if (json_paths)
10786 json_object_string_add(
10787 json_peer, "type",
10788 "confed-internal");
d62a17ae 10789 else
05864da7 10790 vty_out(vty, ", confed-internal");
d62a17ae 10791 } else {
05864da7
DS
10792 if (json_paths)
10793 json_object_string_add(
10794 json_peer, "type", "internal");
10795 else
10796 vty_out(vty, ", internal");
9df8b37c 10797 }
05864da7
DS
10798 } else {
10799 if (bgp_confederation_peers_check(bgp,
10800 path->peer->as)) {
10801 if (json_paths)
10802 json_object_string_add(
10803 json_peer, "type",
10804 "confed-external");
d62a17ae 10805 else
05864da7 10806 vty_out(vty, ", confed-external");
d62a17ae 10807 } else {
05864da7
DS
10808 if (json_paths)
10809 json_object_string_add(
10810 json_peer, "type", "external");
10811 else
10812 vty_out(vty, ", external");
d62a17ae 10813 }
10814 }
05864da7
DS
10815 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10816 if (json_paths) {
10817 json_object_boolean_true_add(json_path, "aggregated");
10818 json_object_boolean_true_add(json_path, "local");
10819 } else {
10820 vty_out(vty, ", aggregated, local");
10821 }
10822 } else if (path->type != ZEBRA_ROUTE_BGP) {
10823 if (json_paths)
10824 json_object_boolean_true_add(json_path, "sourced");
10825 else
10826 vty_out(vty, ", sourced");
10827 } else {
10828 if (json_paths) {
10829 json_object_boolean_true_add(json_path, "sourced");
10830 json_object_boolean_true_add(json_path, "local");
10831 } else {
10832 vty_out(vty, ", sourced, local");
d62a17ae 10833 }
05864da7 10834 }
718e3744 10835
05864da7 10836 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10837 if (json_paths)
05864da7
DS
10838 json_object_boolean_true_add(json_path,
10839 "atomicAggregate");
d62a17ae 10840 else
05864da7
DS
10841 vty_out(vty, ", atomic-aggregate");
10842 }
d62a17ae 10843
d864dd9e
EB
10844 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10845 if (json_paths)
10846 json_object_int_add(json_path, "otc", attr->otc);
10847 else
10848 vty_out(vty, ", otc %u", attr->otc);
10849 }
10850
05864da7
DS
10851 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10852 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10853 && bgp_path_info_mpath_count(path))) {
10854 if (json_paths)
10855 json_object_boolean_true_add(json_path, "multipath");
10856 else
10857 vty_out(vty, ", multipath");
10858 }
50e05855 10859
05864da7
DS
10860 // Mark the bestpath(s)
10861 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10862 first_as = aspath_get_first_as(attr->aspath);
718e3744 10863
05864da7
DS
10864 if (json_paths) {
10865 if (!json_bestpath)
10866 json_bestpath = json_object_new_object();
10867 json_object_int_add(json_bestpath, "bestpathFromAs",
10868 first_as);
10869 } else {
10870 if (first_as)
10871 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10872 else
05864da7 10873 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10874 }
05864da7 10875 }
718e3744 10876
05864da7
DS
10877 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10878 if (json_paths) {
10879 if (!json_bestpath)
10880 json_bestpath = json_object_new_object();
10881 json_object_boolean_true_add(json_bestpath, "overall");
10882 json_object_string_add(
10883 json_bestpath, "selectionReason",
10884 bgp_path_selection_reason2str(bn->reason));
10885 } else {
10886 vty_out(vty, ", best");
10887 vty_out(vty, " (%s)",
10888 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10889 }
05864da7 10890 }
718e3744 10891
4027d19b 10892 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10893 if (json_paths)
10894 json_object_string_add(
10895 json_path, "rpkiValidationState",
4027d19b 10896 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10897 else
1d327209 10898 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10899 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10900 }
10901
05864da7
DS
10902 if (json_bestpath)
10903 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10904
05864da7
DS
10905 if (!json_paths)
10906 vty_out(vty, "\n");
10907
10908 /* Line 4 display Community */
29e72930 10909 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10910 if (json_paths) {
9a706b42
DA
10911 if (!bgp_attr_get_community(attr)->json)
10912 community_str(bgp_attr_get_community(attr),
c0945b78 10913 true, true);
9a706b42
DA
10914 json_object_lock(bgp_attr_get_community(attr)->json);
10915 json_object_object_add(
10916 json_path, "community",
10917 bgp_attr_get_community(attr)->json);
05864da7
DS
10918 } else {
10919 vty_out(vty, " Community: %s\n",
9a706b42 10920 bgp_attr_get_community(attr)->str);
d62a17ae 10921 }
05864da7 10922 }
718e3744 10923
05864da7
DS
10924 /* Line 5 display Extended-community */
10925 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10926 if (json_paths) {
10927 json_ext_community = json_object_new_object();
b53e67a3
DA
10928 json_object_string_add(
10929 json_ext_community, "string",
10930 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10931 json_object_object_add(json_path, "extendedCommunity",
10932 json_ext_community);
d62a17ae 10933 } else {
05864da7 10934 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10935 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10936 }
05864da7 10937 }
718e3744 10938
05864da7
DS
10939 /* Line 6 display Large community */
10940 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10941 if (json_paths) {
1bcf3a96
DA
10942 if (!bgp_attr_get_lcommunity(attr)->json)
10943 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10944 true, true);
1bcf3a96
DA
10945 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10946 json_object_object_add(
10947 json_path, "largeCommunity",
10948 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10949 } else {
10950 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10951 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10952 }
05864da7 10953 }
718e3744 10954
05864da7
DS
10955 /* Line 7 display Originator, Cluster-id */
10956 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10957 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10958 char buf[BUFSIZ] = {0};
10959
05864da7 10960 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10961 if (json_paths)
c949c771
DA
10962 json_object_string_addf(json_path,
10963 "originatorId", "%pI4",
10964 &attr->originator_id);
d62a17ae 10965 else
23d0a753
DA
10966 vty_out(vty, " Originator: %pI4",
10967 &attr->originator_id);
d62a17ae 10968 }
856ca177 10969
05864da7 10970 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10971 struct cluster_list *cluster =
10972 bgp_attr_get_cluster(attr);
05864da7 10973 int i;
d62a17ae 10974
10975 if (json_paths) {
05864da7
DS
10976 json_cluster_list = json_object_new_object();
10977 json_cluster_list_list =
10978 json_object_new_array();
10979
779fee93 10980 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10981 json_string = json_object_new_string(
779fee93
DS
10982 inet_ntop(AF_INET,
10983 &cluster->list[i],
10984 buf, sizeof(buf)));
05864da7
DS
10985 json_object_array_add(
10986 json_cluster_list_list,
10987 json_string);
10988 }
718e3744 10989
05864da7
DS
10990 /*
10991 * struct cluster_list does not have
10992 * "str" variable like aspath and community
10993 * do. Add this someday if someone asks
10994 * for it.
10995 * json_object_string_add(json_cluster_list,
779fee93 10996 * "string", cluster->str);
05864da7
DS
10997 */
10998 json_object_object_add(json_cluster_list,
10999 "list",
11000 json_cluster_list_list);
11001 json_object_object_add(json_path, "clusterList",
11002 json_cluster_list);
0dc8ee70 11003 } else {
05864da7
DS
11004 vty_out(vty, ", Cluster list: ");
11005
779fee93 11006 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 11007 vty_out(vty, "%pI4 ",
779fee93 11008 &cluster->list[i]);
05864da7 11009 }
0dc8ee70 11010 }
d62a17ae 11011 }
718e3744 11012
d62a17ae 11013 if (!json_paths)
11014 vty_out(vty, "\n");
05864da7 11015 }
d62a17ae 11016
05864da7 11017 if (path->extra && path->extra->damp_info)
b4f7f45b 11018 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 11019
05864da7
DS
11020 /* Remote Label */
11021 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
11022 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
11023 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
11024 &bos);
d62a17ae 11025
05864da7
DS
11026 if (json_paths)
11027 json_object_int_add(json_path, "remoteLabel", label);
11028 else
11029 vty_out(vty, " Remote label: %d\n", label);
11030 }
d62a17ae 11031
e496b420
HS
11032 /* Remote SID */
11033 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
e496b420 11034 if (json_paths)
07380148
DA
11035 json_object_string_addf(json_path, "remoteSid", "%pI6",
11036 &path->extra->sid[0].sid);
e496b420 11037 else
07380148
DA
11038 vty_out(vty, " Remote SID: %pI6\n",
11039 &path->extra->sid[0].sid);
e496b420
HS
11040 }
11041
05864da7
DS
11042 /* Label Index */
11043 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11044 if (json_paths)
11045 json_object_int_add(json_path, "labelIndex",
11046 attr->label_index);
11047 else
11048 vty_out(vty, " Label Index: %d\n",
11049 attr->label_index);
11050 }
d62a17ae 11051
05864da7
DS
11052 /* Line 8 display Addpath IDs */
11053 if (path->addpath_rx_id
11054 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11055 if (json_paths) {
11056 json_object_int_add(json_path, "addpathRxId",
11057 path->addpath_rx_id);
d62a17ae 11058
05864da7
DS
11059 /* Keep backwards compatibility with the old API
11060 * by putting TX All's ID in the old field
11061 */
11062 json_object_int_add(
11063 json_path, "addpathTxId",
11064 path->tx_addpath
11065 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11066
05864da7
DS
11067 /* ... but create a specific field for each
11068 * strategy
11069 */
11070 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11071 json_object_int_add(
11072 json_path,
11073 bgp_addpath_names(i)->id_json_name,
11074 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11075 }
05864da7
DS
11076 } else {
11077 vty_out(vty, " AddPath ID: RX %u, ",
11078 path->addpath_rx_id);
d62a17ae 11079
05864da7 11080 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11081 }
05864da7 11082 }
520d5d76 11083
05864da7
DS
11084 /* If we used addpath to TX a non-bestpath we need to display
11085 * "Advertised to" on a path-by-path basis
11086 */
11087 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11088 first = 1;
dcc68b5e 11089
05864da7
DS
11090 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11091 addpath_capable =
11092 bgp_addpath_encode_tx(peer, afi, safi);
11093 has_adj = bgp_adj_out_lookup(
11094 peer, path->net,
11095 bgp_addpath_id_for_peer(peer, afi, safi,
11096 &path->tx_addpath));
11097
11098 if ((addpath_capable && has_adj)
11099 || (!addpath_capable && has_adj
11100 && CHECK_FLAG(path->flags,
11101 BGP_PATH_SELECTED))) {
11102 if (json_path && !json_adv_to)
11103 json_adv_to = json_object_new_object();
dcc68b5e 11104
05864da7
DS
11105 route_vty_out_advertised_to(
11106 vty, peer, &first,
11107 " Advertised to:", json_adv_to);
d62a17ae 11108 }
11109 }
718e3744 11110
05864da7
DS
11111 if (json_path) {
11112 if (json_adv_to) {
11113 json_object_object_add(
11114 json_path, "advertisedTo", json_adv_to);
d62a17ae 11115 }
05864da7
DS
11116 } else {
11117 if (!first) {
11118 vty_out(vty, "\n");
d62a17ae 11119 }
11120 }
05864da7 11121 }
b05a1c8b 11122
05864da7 11123 /* Line 9 display Uptime */
083ec940 11124 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11125 if (json_paths) {
11126 json_last_update = json_object_new_object();
11127 json_object_int_add(json_last_update, "epoch", tbuf);
11128 json_object_string_add(json_last_update, "string",
11129 ctime(&tbuf));
11130 json_object_object_add(json_path, "lastUpdate",
11131 json_last_update);
11132 } else
11133 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11134
05864da7
DS
11135 /* Line 10 display PMSI tunnel attribute, if present */
11136 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11137 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11138 bgp_attr_get_pmsi_tnl_type(attr),
11139 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11140
05864da7
DS
11141 if (json_paths) {
11142 json_pmsi = json_object_new_object();
11143 json_object_string_add(json_pmsi, "tunnelType", str);
11144 json_object_int_add(json_pmsi, "label",
11145 label2vni(&attr->label));
11146 json_object_object_add(json_path, "pmsi", json_pmsi);
11147 } else
11148 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11149 str, label2vni(&attr->label));
d62a17ae 11150 }
f1aa5d8a 11151
848e8cf6
DA
11152 if (path->peer->t_gr_restart &&
11153 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11154 unsigned long gr_remaining =
11155 thread_timer_remain_second(path->peer->t_gr_restart);
11156
11157 if (json_paths) {
11158 json_object_int_add(json_path,
11159 "gracefulRestartSecondsRemaining",
11160 gr_remaining);
11161 } else
11162 vty_out(vty,
11163 " Time until Graceful Restart stale route deleted: %lu\n",
11164 gr_remaining);
11165 }
11166
9a706b42
DA
11167 if (path->peer->t_llgr_stale[afi][safi] &&
11168 bgp_attr_get_community(attr) &&
11169 community_include(bgp_attr_get_community(attr),
11170 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11171 unsigned long llgr_remaining = thread_timer_remain_second(
11172 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11173
48ebba04
DA
11174 if (json_paths) {
11175 json_object_int_add(json_path, "llgrSecondsRemaining",
11176 llgr_remaining);
11177 } else
11178 vty_out(vty,
11179 " Time until Long-lived stale route deleted: %lu\n",
11180 llgr_remaining);
11181 }
11182
92269aa2
DS
11183 /* Output some debug about internal state of the dest flags */
11184 if (json_paths) {
11185 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11186 json_object_boolean_true_add(json_path, "processScheduled");
11187 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11188 json_object_boolean_true_add(json_path, "userCleared");
11189 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11190 json_object_boolean_true_add(json_path, "labelChanged");
11191 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11192 json_object_boolean_true_add(json_path, "registeredForLabel");
11193 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11194 json_object_boolean_true_add(json_path, "selectDefered");
11195 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11196 json_object_boolean_true_add(json_path, "fibInstalled");
11197 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11198 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11199
d62a17ae 11200 if (json_nexthop_global || json_nexthop_ll) {
11201 json_nexthops = json_object_new_array();
f1aa5d8a 11202
d62a17ae 11203 if (json_nexthop_global)
11204 json_object_array_add(json_nexthops,
11205 json_nexthop_global);
f1aa5d8a 11206
d62a17ae 11207 if (json_nexthop_ll)
11208 json_object_array_add(json_nexthops,
11209 json_nexthop_ll);
f1aa5d8a 11210
d62a17ae 11211 json_object_object_add(json_path, "nexthops",
11212 json_nexthops);
11213 }
11214
11215 json_object_object_add(json_path, "peer", json_peer);
11216 json_object_array_add(json_paths, json_path);
05864da7 11217 }
b366b518
BB
11218}
11219
96ade3ed 11220#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11221#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11222#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11223
a4d82a8a 11224static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11225 afi_t afi, safi_t safi, enum bgp_show_type type,
11226 bool use_json);
7f323236
DW
11227static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11228 const char *comstr, int exact, afi_t afi,
96c81f66 11229 safi_t safi, uint16_t show_flags);
d62a17ae 11230
1ae44dfc 11231static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11232 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11233 void *output_arg, const char *rd, int is_last,
96f3485c 11234 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11235 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11236 enum rpki_states rpki_target_state)
d62a17ae 11237{
40381db7 11238 struct bgp_path_info *pi;
9bcb3eef 11239 struct bgp_dest *dest;
2aad8c42
MS
11240 bool header = true;
11241 bool json_detail_header = false;
d62a17ae 11242 int display;
1ae44dfc
LB
11243 unsigned long output_count = 0;
11244 unsigned long total_count = 0;
d62a17ae 11245 struct prefix *p;
d62a17ae 11246 json_object *json_paths = NULL;
11247 int first = 1;
96f3485c
MK
11248 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11249 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11250 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11251
1ae44dfc 11252 if (output_cum && *output_cum != 0)
2aad8c42 11253 header = false;
1ae44dfc 11254
9386b588 11255 if (use_json && !*json_header_depth) {
96f3485c
MK
11256 if (all)
11257 *json_header_depth = 1;
11258 else {
11259 vty_out(vty, "{\n");
11260 *json_header_depth = 2;
11261 }
11262
d62a17ae 11263 vty_out(vty,
23d0a753
DA
11264 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11265 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11266 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11267 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11268 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11269 ? VRF_DEFAULT_NAME
11270 : bgp->name,
11271 table->version, &bgp->router_id,
01eced22 11272 bgp->default_local_pref, bgp->as);
9386b588 11273 if (rd) {
445c2480 11274 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11275 ++*json_header_depth;
11276 }
d62a17ae 11277 }
718e3744 11278
445c2480
DS
11279 if (use_json && rd) {
11280 vty_out(vty, " \"%s\" : { ", rd);
11281 }
11282
2aad8c42
MS
11283 /* Check for 'json detail', where we need header output once per dest */
11284 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11285 type != bgp_show_type_dampend_paths &&
11286 type != bgp_show_type_damp_neighbor &&
11287 type != bgp_show_type_flap_statistics &&
11288 type != bgp_show_type_flap_neighbor)
11289 json_detail_header = true;
11290
d62a17ae 11291 /* Start processing of routes. */
9bcb3eef
DS
11292 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11293 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11294 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11295 bool json_detail = json_detail_header;
b54892e0 11296
9bcb3eef 11297 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11298 if (pi == NULL)
98ce9a06 11299 continue;
d62a17ae 11300
98ce9a06 11301 display = 0;
98ce9a06
DS
11302 if (use_json)
11303 json_paths = json_object_new_array();
11304 else
11305 json_paths = NULL;
d62a17ae 11306
6f94b685 11307 for (; pi; pi = pi->next) {
9a706b42
DA
11308 struct community *picomm = NULL;
11309
11310 picomm = bgp_attr_get_community(pi->attr);
11311
98ce9a06 11312 total_count++;
1e2ce4f1 11313
7d3cae70
DA
11314 if (type == bgp_show_type_prefix_version) {
11315 uint32_t version =
11316 strtoul(output_arg, NULL, 10);
11317 if (dest->version < version)
11318 continue;
11319 }
11320
a70a28a5
DA
11321 if (type == bgp_show_type_community_alias) {
11322 char *alias = output_arg;
11323 char **communities;
11324 int num;
11325 bool found = false;
11326
9a706b42
DA
11327 if (picomm) {
11328 frrstr_split(picomm->str, " ",
11329 &communities, &num);
a70a28a5
DA
11330 for (int i = 0; i < num; i++) {
11331 const char *com2alias =
11332 bgp_community2alias(
11333 communities[i]);
cd9cc0e6
IR
11334 if (!found
11335 && strcmp(alias, com2alias)
11336 == 0)
a70a28a5 11337 found = true;
cd9cc0e6
IR
11338 XFREE(MTYPE_TMP,
11339 communities[i]);
a70a28a5 11340 }
cd9cc0e6 11341 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11342 }
11343
1bcf3a96
DA
11344 if (!found &&
11345 bgp_attr_get_lcommunity(pi->attr)) {
11346 frrstr_split(bgp_attr_get_lcommunity(
11347 pi->attr)
11348 ->str,
a70a28a5
DA
11349 " ", &communities, &num);
11350 for (int i = 0; i < num; i++) {
11351 const char *com2alias =
11352 bgp_community2alias(
11353 communities[i]);
cd9cc0e6
IR
11354 if (!found
11355 && strcmp(alias, com2alias)
11356 == 0)
a70a28a5 11357 found = true;
cd9cc0e6
IR
11358 XFREE(MTYPE_TMP,
11359 communities[i]);
a70a28a5 11360 }
cd9cc0e6 11361 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11362 }
11363
11364 if (!found)
11365 continue;
11366 }
11367
1e2ce4f1
DS
11368 if (type == bgp_show_type_rpki) {
11369 if (dest_p->family == AF_INET
11370 || dest_p->family == AF_INET6)
4027d19b 11371 rpki_curr_state = hook_call(
1e2ce4f1
DS
11372 bgp_rpki_prefix_status,
11373 pi->peer, pi->attr, dest_p);
4027d19b
DS
11374 if (rpki_target_state != RPKI_NOT_BEING_USED
11375 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11376 continue;
11377 }
11378
98ce9a06
DS
11379 if (type == bgp_show_type_flap_statistics
11380 || type == bgp_show_type_flap_neighbor
11381 || type == bgp_show_type_dampend_paths
11382 || type == bgp_show_type_damp_neighbor) {
40381db7 11383 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11384 continue;
11385 }
11386 if (type == bgp_show_type_regexp) {
11387 regex_t *regex = output_arg;
d62a17ae 11388
40381db7 11389 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11390 == REG_NOMATCH)
11391 continue;
11392 }
11393 if (type == bgp_show_type_prefix_list) {
11394 struct prefix_list *plist = output_arg;
d62a17ae 11395
9bcb3eef 11396 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11397 != PREFIX_PERMIT)
11398 continue;
11399 }
ed126382
DA
11400 if (type == bgp_show_type_access_list) {
11401 struct access_list *alist = output_arg;
11402
11403 if (access_list_apply(alist, dest_p) !=
11404 FILTER_PERMIT)
11405 continue;
11406 }
98ce9a06
DS
11407 if (type == bgp_show_type_filter_list) {
11408 struct as_list *as_list = output_arg;
d62a17ae 11409
40381db7 11410 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11411 != AS_FILTER_PERMIT)
11412 continue;
11413 }
11414 if (type == bgp_show_type_route_map) {
11415 struct route_map *rmap = output_arg;
9b6d8fcf 11416 struct bgp_path_info path;
636632c3
DA
11417 struct bgp_path_info_extra extra;
11418 struct attr dummy_attr = {};
b68885f9 11419 route_map_result_t ret;
d62a17ae 11420
6f4f49b2 11421 dummy_attr = *pi->attr;
d62a17ae 11422
636632c3
DA
11423 prep_for_rmap_apply(&path, &extra, dest, pi,
11424 pi->peer, &dummy_attr);
d62a17ae 11425
1782514f 11426 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11427 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11428 if (ret == RMAP_DENYMATCH)
11429 continue;
11430 }
11431 if (type == bgp_show_type_neighbor
11432 || type == bgp_show_type_flap_neighbor
11433 || type == bgp_show_type_damp_neighbor) {
11434 union sockunion *su = output_arg;
11435
40381db7
DS
11436 if (pi->peer == NULL
11437 || pi->peer->su_remote == NULL
11438 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11439 continue;
11440 }
11441 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11442 uint32_t destination;
d62a17ae 11443
9bcb3eef 11444 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11445 if (IN_CLASSC(destination)
9bcb3eef 11446 && dest_p->prefixlen == 24)
98ce9a06
DS
11447 continue;
11448 if (IN_CLASSB(destination)
9bcb3eef 11449 && dest_p->prefixlen == 16)
98ce9a06
DS
11450 continue;
11451 if (IN_CLASSA(destination)
9bcb3eef 11452 && dest_p->prefixlen == 8)
98ce9a06
DS
11453 continue;
11454 }
11455 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11456 p = output_arg;
9bcb3eef 11457 if (!prefix_match(p, dest_p))
98ce9a06
DS
11458 continue;
11459 }
11460 if (type == bgp_show_type_community_all) {
9a706b42 11461 if (!picomm)
98ce9a06
DS
11462 continue;
11463 }
11464 if (type == bgp_show_type_community) {
11465 struct community *com = output_arg;
d62a17ae 11466
9a706b42 11467 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11468 continue;
11469 }
11470 if (type == bgp_show_type_community_exact) {
11471 struct community *com = output_arg;
d62a17ae 11472
9a706b42 11473 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11474 continue;
11475 }
11476 if (type == bgp_show_type_community_list) {
11477 struct community_list *list = output_arg;
d62a17ae 11478
9a706b42 11479 if (!community_list_match(picomm, list))
98ce9a06
DS
11480 continue;
11481 }
a4d82a8a 11482 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11483 struct community_list *list = output_arg;
d62a17ae 11484
9a706b42 11485 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11486 continue;
11487 }
11488 if (type == bgp_show_type_lcommunity) {
11489 struct lcommunity *lcom = output_arg;
d62a17ae 11490
1bcf3a96
DA
11491 if (!bgp_attr_get_lcommunity(pi->attr) ||
11492 !lcommunity_match(
11493 bgp_attr_get_lcommunity(pi->attr),
11494 lcom))
98ce9a06
DS
11495 continue;
11496 }
36a206db 11497
11498 if (type == bgp_show_type_lcommunity_exact) {
11499 struct lcommunity *lcom = output_arg;
11500
1bcf3a96
DA
11501 if (!bgp_attr_get_lcommunity(pi->attr) ||
11502 !lcommunity_cmp(
11503 bgp_attr_get_lcommunity(pi->attr),
11504 lcom))
36a206db 11505 continue;
11506 }
98ce9a06
DS
11507 if (type == bgp_show_type_lcommunity_list) {
11508 struct community_list *list = output_arg;
d62a17ae 11509
1bcf3a96
DA
11510 if (!lcommunity_list_match(
11511 bgp_attr_get_lcommunity(pi->attr),
11512 list))
98ce9a06
DS
11513 continue;
11514 }
36a206db 11515 if (type
11516 == bgp_show_type_lcommunity_list_exact) {
11517 struct community_list *list = output_arg;
11518
11519 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11520 bgp_attr_get_lcommunity(pi->attr),
11521 list))
36a206db 11522 continue;
11523 }
98ce9a06 11524 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11525 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11526 continue;
11527 }
11528 if (type == bgp_show_type_dampend_paths
11529 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11530 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11531 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11532 continue;
11533 }
11534
11535 if (!use_json && header) {
23d0a753
DA
11536 vty_out(vty,
11537 "BGP table version is %" PRIu64
11538 ", local router ID is %pI4, vrf id ",
11539 table->version, &bgp->router_id);
9df8b37c
PZ
11540 if (bgp->vrf_id == VRF_UNKNOWN)
11541 vty_out(vty, "%s", VRFID_NONE_STR);
11542 else
11543 vty_out(vty, "%u", bgp->vrf_id);
11544 vty_out(vty, "\n");
01eced22
AD
11545 vty_out(vty, "Default local pref %u, ",
11546 bgp->default_local_pref);
11547 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11548 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11549 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11550 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11551 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11552 if (type == bgp_show_type_dampend_paths
11553 || type == bgp_show_type_damp_neighbor)
98ce9a06 11554 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11555 else if (type == bgp_show_type_flap_statistics
11556 || type == bgp_show_type_flap_neighbor)
98ce9a06 11557 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11558 else
ae248832
MK
11559 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11560 : BGP_SHOW_HEADER));
2aad8c42
MS
11561 header = false;
11562
11563 } else if (json_detail && json_paths != NULL) {
11564 const struct prefix_rd *prd;
11565 json_object *jtemp;
11566
11567 /* Use common detail header, for most types;
11568 * need a json 'object'.
11569 */
11570
11571 jtemp = json_object_new_object();
11572 prd = bgp_rd_from_dest(dest, safi);
11573
11574 route_vty_out_detail_header(
34c7f35f
SW
11575 vty, bgp, dest,
11576 bgp_dest_get_prefix(dest), prd,
11577 table->afi, safi, jtemp);
2aad8c42
MS
11578
11579 json_object_array_add(json_paths, jtemp);
11580
11581 json_detail = false;
d62a17ae 11582 }
2aad8c42 11583
98ce9a06
DS
11584 if (rd != NULL && !display && !output_count) {
11585 if (!use_json)
11586 vty_out(vty,
11587 "Route Distinguisher: %s\n",
11588 rd);
d62a17ae 11589 }
98ce9a06
DS
11590 if (type == bgp_show_type_dampend_paths
11591 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11592 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11593 AFI_IP, safi, use_json,
11594 json_paths);
98ce9a06
DS
11595 else if (type == bgp_show_type_flap_statistics
11596 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11597 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11598 AFI_IP, safi, use_json,
11599 json_paths);
f280c93b
DA
11600 else {
11601 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11602 route_vty_out_detail(
34c7f35f
SW
11603 vty, bgp, dest,
11604 bgp_dest_get_prefix(dest), pi,
f280c93b
DA
11605 family2afi(dest_p->family),
11606 safi, RPKI_NOT_BEING_USED,
11607 json_paths);
11608 else
11609 route_vty_out(vty, dest_p, pi, display,
11610 safi, json_paths, wide);
11611 }
98ce9a06 11612 display++;
d62a17ae 11613 }
11614
98ce9a06
DS
11615 if (display) {
11616 output_count++;
11617 if (!use_json)
11618 continue;
11619
625d2931 11620 /* encode prefix */
9bcb3eef 11621 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11622 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11623
1840384b 11624
b54892e0
DS
11625 bgp_fs_nlri_get_string(
11626 (unsigned char *)
9bcb3eef
DS
11627 dest_p->u.prefix_flowspec.ptr,
11628 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11629 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11630 family2afi(dest_p->u
11631 .prefix_flowspec.family));
625d2931 11632 if (first)
b54892e0 11633 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11634 dest_p->u.prefix_flowspec
b54892e0 11635 .prefixlen);
625d2931 11636 else
b54892e0 11637 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11638 dest_p->u.prefix_flowspec
b54892e0 11639 .prefixlen);
625d2931 11640 } else {
625d2931 11641 if (first)
1b78780b 11642 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11643 else
1b78780b 11644 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11645 }
3757f964 11646 vty_json(vty, json_paths);
449feb8e 11647 json_paths = NULL;
98ce9a06 11648 first = 0;
1f83ed02
DS
11649 } else
11650 json_object_free(json_paths);
98ce9a06
DS
11651 }
11652
1ae44dfc
LB
11653 if (output_cum) {
11654 output_count += *output_cum;
11655 *output_cum = output_count;
11656 }
11657 if (total_cum) {
11658 total_count += *total_cum;
11659 *total_cum = total_count;
11660 }
d62a17ae 11661 if (use_json) {
9386b588 11662 if (rd) {
a4d82a8a 11663 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11664 }
11665 if (is_last) {
a4d82a8a
PZ
11666 unsigned long i;
11667 for (i = 0; i < *json_header_depth; ++i)
11668 vty_out(vty, " } ");
96f3485c
MK
11669 if (!all)
11670 vty_out(vty, "\n");
9386b588 11671 }
d62a17ae 11672 } else {
1ae44dfc
LB
11673 if (is_last) {
11674 /* No route is displayed */
11675 if (output_count == 0) {
11676 if (type == bgp_show_type_normal)
11677 vty_out(vty,
11678 "No BGP prefixes displayed, %ld exist\n",
11679 total_count);
11680 } else
d62a17ae 11681 vty_out(vty,
1ae44dfc
LB
11682 "\nDisplayed %ld routes and %ld total paths\n",
11683 output_count, total_count);
11684 }
d62a17ae 11685 }
718e3744 11686
d62a17ae 11687 return CMD_SUCCESS;
718e3744 11688}
11689
1ae44dfc
LB
11690int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11691 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11692 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11693{
9bcb3eef 11694 struct bgp_dest *dest, *next;
1ae44dfc
LB
11695 unsigned long output_cum = 0;
11696 unsigned long total_cum = 0;
9386b588 11697 unsigned long json_header_depth = 0;
67009e22 11698 struct bgp_table *itable;
0136788c 11699 bool show_msg;
96c81f66 11700 uint16_t show_flags = 0;
0136788c
LB
11701
11702 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11703
96f3485c
MK
11704 if (use_json)
11705 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11706
9bcb3eef
DS
11707 for (dest = bgp_table_top(table); dest; dest = next) {
11708 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11709
9bcb3eef
DS
11710 next = bgp_route_next(dest);
11711 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11712 continue;
67009e22 11713
9bcb3eef 11714 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11715 if (itable != NULL) {
1ae44dfc 11716 struct prefix_rd prd;
06b9f471 11717 char rd[RD_ADDRSTRLEN];
1ae44dfc 11718
9bcb3eef 11719 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11720 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11721 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11722 rd, next == NULL, &output_cum,
11723 &total_cum, &json_header_depth,
1e2ce4f1 11724 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11725 if (next == NULL)
11726 show_msg = false;
1ae44dfc
LB
11727 }
11728 }
0136788c
LB
11729 if (show_msg) {
11730 if (output_cum == 0)
11731 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11732 total_cum);
11733 else
11734 vty_out(vty,
11735 "\nDisplayed %ld routes and %ld total paths\n",
11736 output_cum, total_cum);
0224b329
DA
11737 } else {
11738 if (use_json && output_cum == 0)
11739 vty_out(vty, "{}\n");
0136788c 11740 }
1ae44dfc
LB
11741 return CMD_SUCCESS;
11742}
2aad8c42 11743
d62a17ae 11744static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11745 enum bgp_show_type type, void *output_arg,
96c81f66 11746 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11747{
d62a17ae 11748 struct bgp_table *table;
9386b588 11749 unsigned long json_header_depth = 0;
96f3485c 11750 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11751
d62a17ae 11752 if (bgp == NULL) {
11753 bgp = bgp_get_default();
11754 }
fee0f4c6 11755
d62a17ae 11756 if (bgp == NULL) {
11757 if (!use_json)
11758 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11759 else
11760 vty_out(vty, "{}\n");
d62a17ae 11761 return CMD_WARNING;
11762 }
4dd6177e 11763
cd8c2a27
MS
11764 /* Labeled-unicast routes live in the unicast table. */
11765 if (safi == SAFI_LABELED_UNICAST)
11766 safi = SAFI_UNICAST;
11767
1ae44dfc 11768 table = bgp->rib[afi][safi];
d62a17ae 11769 /* use MPLS and ENCAP specific shows until they are merged */
11770 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11771 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11772 output_arg, use_json);
d62a17ae 11773 }
dba3c1d3
PG
11774
11775 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11776 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11777 output_arg, use_json,
11778 1, NULL, NULL);
11779 }
fee0f4c6 11780
96f3485c 11781 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11782 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11783 rpki_target_state);
fee0f4c6 11784}
11785
d62a17ae 11786static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11787 safi_t safi, uint16_t show_flags)
f186de26 11788{
d62a17ae 11789 struct listnode *node, *nnode;
11790 struct bgp *bgp;
11791 int is_first = 1;
9f049418 11792 bool route_output = false;
96f3485c 11793 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11794
d62a17ae 11795 if (use_json)
11796 vty_out(vty, "{\n");
9f689658 11797
d62a17ae 11798 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11799 route_output = true;
d62a17ae 11800 if (use_json) {
11801 if (!is_first)
11802 vty_out(vty, ",\n");
11803 else
11804 is_first = 0;
11805
11806 vty_out(vty, "\"%s\":",
11807 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11808 ? VRF_DEFAULT_NAME
d62a17ae 11809 : bgp->name);
11810 } else {
11811 vty_out(vty, "\nInstance %s:\n",
11812 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11813 ? VRF_DEFAULT_NAME
d62a17ae 11814 : bgp->name);
11815 }
11816 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11817 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11818 }
9f689658 11819
d62a17ae 11820 if (use_json)
11821 vty_out(vty, "}\n");
9f049418
DS
11822 else if (!route_output)
11823 vty_out(vty, "%% BGP instance not found\n");
f186de26 11824}
11825
718e3744 11826/* Header of detailed BGP route information */
d62a17ae 11827void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11828 struct bgp_dest *dest, const struct prefix *p,
11829 const struct prefix_rd *prd, afi_t afi,
11830 safi_t safi, json_object *json)
d62a17ae 11831{
40381db7 11832 struct bgp_path_info *pi;
d62a17ae 11833 struct peer *peer;
11834 struct listnode *node, *nnode;
06b9f471 11835 char buf1[RD_ADDRSTRLEN];
d62a17ae 11836 int count = 0;
11837 int best = 0;
11838 int suppress = 0;
c5f1e1b2
C
11839 int accept_own = 0;
11840 int route_filter_translated_v4 = 0;
11841 int route_filter_v4 = 0;
11842 int route_filter_translated_v6 = 0;
11843 int route_filter_v6 = 0;
11844 int llgr_stale = 0;
11845 int no_llgr = 0;
11846 int accept_own_nexthop = 0;
11847 int blackhole = 0;
d62a17ae 11848 int no_export = 0;
11849 int no_advertise = 0;
11850 int local_as = 0;
c5f1e1b2 11851 int no_peer = 0;
d62a17ae 11852 int first = 1;
11853 int has_valid_label = 0;
11854 mpls_label_t label = 0;
11855 json_object *json_adv_to = NULL;
67f67ba4
DA
11856 uint32_t ttl = 0;
11857 uint32_t bos = 0;
11858 uint32_t exp = 0;
9bedbb1e 11859
67f67ba4 11860 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11861
67f67ba4 11862 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11863
44c69747 11864 if (safi == SAFI_EVPN) {
44c69747 11865 if (!json) {
2dbe669b 11866 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11867 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11868 : "",
2dbe669b 11869 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11870 } else {
11871 json_object_string_add(json, "rd",
11872 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11873 "");
11874 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11875 }
11876 } else {
11877 if (!json) {
9119ef3a
DA
11878 vty_out(vty,
11879 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11880 "\n",
d62a17ae 11881 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11882 ? prefix_rd2str(prd, buf1,
11883 sizeof(buf1))
11884 : ""),
9119ef3a
DA
11885 safi == SAFI_MPLS_VPN ? ":" : "", p,
11886 dest->version);
cd1964ff 11887
9119ef3a 11888 } else {
67d7e256 11889 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11890 json_object_int_add(json, "version", dest->version);
11891
11892 }
44c69747
LK
11893 }
11894
11895 if (has_valid_label) {
11896 if (json)
11897 json_object_int_add(json, "localLabel", label);
11898 else
d62a17ae 11899 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11900 }
11901
11902 if (!json)
d62a17ae 11903 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11904 vty_out(vty, "not allocated\n");
718e3744 11905
9bcb3eef 11906 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11907 struct community *picomm = NULL;
11908
11909 picomm = bgp_attr_get_community(pi->attr);
11910
d62a17ae 11911 count++;
40381db7 11912 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11913 best = count;
4056a5f6 11914 if (bgp_path_suppressed(pi))
d62a17ae 11915 suppress = 1;
cee9c031 11916
9a706b42 11917 if (!picomm)
cee9c031
QY
11918 continue;
11919
11920 no_advertise += community_include(
9a706b42
DA
11921 picomm, COMMUNITY_NO_ADVERTISE);
11922 no_export +=
11923 community_include(picomm, COMMUNITY_NO_EXPORT);
11924 local_as +=
11925 community_include(picomm, COMMUNITY_LOCAL_AS);
11926 accept_own +=
11927 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11928 route_filter_translated_v4 += community_include(
9a706b42 11929 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11930 route_filter_translated_v6 += community_include(
9a706b42 11931 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11932 route_filter_v4 += community_include(
9a706b42 11933 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11934 route_filter_v6 += community_include(
9a706b42
DA
11935 picomm, COMMUNITY_ROUTE_FILTER_v6);
11936 llgr_stale +=
11937 community_include(picomm, COMMUNITY_LLGR_STALE);
11938 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11939 accept_own_nexthop += community_include(
11940 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11941 blackhole +=
11942 community_include(picomm, COMMUNITY_BLACKHOLE);
11943 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11944 }
718e3744 11945 }
718e3744 11946
d62a17ae 11947 if (!json) {
11948 vty_out(vty, "Paths: (%d available", count);
11949 if (best) {
11950 vty_out(vty, ", best #%d", best);
b84060bb
PG
11951 if (safi == SAFI_UNICAST) {
11952 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11953 vty_out(vty, ", table %s",
11954 VRF_DEFAULT_NAME);
11955 else
11956 vty_out(vty, ", vrf %s",
11957 bgp->name);
11958 }
d62a17ae 11959 } else
11960 vty_out(vty, ", no best path");
11961
c5f1e1b2
C
11962 if (accept_own)
11963 vty_out(vty,
11964 ", accept own local route exported and imported in different VRF");
11965 else if (route_filter_translated_v4)
11966 vty_out(vty,
11967 ", mark translated RTs for VPNv4 route filtering");
11968 else if (route_filter_v4)
11969 vty_out(vty,
11970 ", attach RT as-is for VPNv4 route filtering");
11971 else if (route_filter_translated_v6)
11972 vty_out(vty,
11973 ", mark translated RTs for VPNv6 route filtering");
11974 else if (route_filter_v6)
11975 vty_out(vty,
11976 ", attach RT as-is for VPNv6 route filtering");
11977 else if (llgr_stale)
11978 vty_out(vty,
1479ed2f 11979 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11980 else if (no_llgr)
11981 vty_out(vty,
11982 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11983 else if (accept_own_nexthop)
11984 vty_out(vty,
11985 ", accept local nexthop");
11986 else if (blackhole)
11987 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11988 else if (no_export)
11989 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11990 else if (no_advertise)
11991 vty_out(vty, ", not advertised to any peer");
d62a17ae 11992 else if (local_as)
11993 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11994 else if (no_peer)
11995 vty_out(vty,
11996 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11997
11998 if (suppress)
11999 vty_out(vty,
12000 ", Advertisements suppressed by an aggregate.");
12001 vty_out(vty, ")\n");
12002 }
718e3744 12003
d62a17ae 12004 /* If we are not using addpath then we can display Advertised to and
12005 * that will
12006 * show what peers we advertised the bestpath to. If we are using
12007 * addpath
12008 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 12009 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 12010 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 12011 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 12012 if (json && !json_adv_to)
12013 json_adv_to = json_object_new_object();
12014
12015 route_vty_out_advertised_to(
12016 vty, peer, &first,
12017 " Advertised to non peer-group peers:\n ",
12018 json_adv_to);
12019 }
12020 }
12021
12022 if (json) {
12023 if (json_adv_to) {
12024 json_object_object_add(json, "advertisedTo",
12025 json_adv_to);
12026 }
12027 } else {
12028 if (first)
12029 vty_out(vty, " Not advertised to any peer");
12030 vty_out(vty, "\n");
12031 }
12032 }
718e3744 12033}
12034
edfee30d 12035static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12036 struct bgp_dest *bgp_node, struct vty *vty,
12037 struct bgp *bgp, afi_t afi, safi_t safi,
12038 json_object *json, enum bgp_path_type pathtype,
4027d19b 12039 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12040{
12041 struct bgp_path_info *pi;
12042 int header = 1;
44c69747
LK
12043 json_object *json_header = NULL;
12044 json_object *json_paths = NULL;
4933eaaf 12045 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12046
9bcb3eef 12047 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12048 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12049
12050 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12051 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12052 pi->peer, pi->attr, p);
4933eaaf 12053
4027d19b
DS
12054 if (rpki_target_state != RPKI_NOT_BEING_USED
12055 && rpki_curr_state != rpki_target_state)
4933eaaf 12056 continue;
44c69747
LK
12057
12058 if (json && !json_paths) {
12059 /* Instantiate json_paths only if path is valid */
12060 json_paths = json_object_new_array();
c4f64ea9 12061 if (pfx_rd)
44c69747 12062 json_header = json_object_new_object();
c4f64ea9 12063 else
44c69747
LK
12064 json_header = json;
12065 }
12066
12067 if (header) {
12068 route_vty_out_detail_header(
34c7f35f
SW
12069 vty, bgp, bgp_node,
12070 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12071 safi, json_header);
44c69747
LK
12072 header = 0;
12073 }
12074 (*display)++;
12075
12076 if (pathtype == BGP_PATH_SHOW_ALL
12077 || (pathtype == BGP_PATH_SHOW_BESTPATH
12078 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12079 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12080 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12081 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12082 route_vty_out_detail(vty, bgp, bgp_node,
12083 bgp_dest_get_prefix(bgp_node), pi,
12084 AFI_IP, safi, rpki_curr_state,
12085 json_paths);
44c69747
LK
12086 }
12087
12088 if (json && json_paths) {
12089 json_object_object_add(json_header, "paths", json_paths);
12090
12091 if (pfx_rd)
c4f64ea9
DA
12092 json_object_object_addf(json, json_header, "%pRD",
12093 pfx_rd);
44c69747
LK
12094 }
12095}
12096
2aad8c42
MS
12097/*
12098 * Return rd based on safi
12099 */
46dbf9d0
DA
12100const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12101 safi_t safi)
2aad8c42
MS
12102{
12103 switch (safi) {
12104 case SAFI_MPLS_VPN:
12105 case SAFI_ENCAP:
12106 case SAFI_EVPN:
12107 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12108 default:
12109 return NULL;
2aad8c42
MS
12110 }
12111}
12112
718e3744 12113/* Display specified route of BGP table. */
d62a17ae 12114static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12115 struct bgp_table *rib, const char *ip_str,
12116 afi_t afi, safi_t safi,
4027d19b 12117 enum rpki_states rpki_target_state,
d62a17ae 12118 struct prefix_rd *prd, int prefix_check,
9f049418 12119 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12120{
12121 int ret;
d62a17ae 12122 int display = 0;
12123 struct prefix match;
9bcb3eef
DS
12124 struct bgp_dest *dest;
12125 struct bgp_dest *rm;
d62a17ae 12126 struct bgp_table *table;
12127 json_object *json = NULL;
12128 json_object *json_paths = NULL;
12129
12130 /* Check IP address argument. */
12131 ret = str2prefix(ip_str, &match);
12132 if (!ret) {
12133 vty_out(vty, "address is malformed\n");
12134 return CMD_WARNING;
12135 }
718e3744 12136
d62a17ae 12137 match.family = afi2family(afi);
b05a1c8b 12138
44c69747 12139 if (use_json)
d62a17ae 12140 json = json_object_new_object();
718e3744 12141
44c69747 12142 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12143 for (dest = bgp_table_top(rib); dest;
12144 dest = bgp_route_next(dest)) {
12145 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12146
9bcb3eef 12147 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12148 continue;
9bcb3eef 12149 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12150 if (!table)
ea47320b 12151 continue;
d62a17ae 12152
4953391b
DA
12153 rm = bgp_node_match(table, &match);
12154 if (rm == NULL)
ea47320b 12155 continue;
d62a17ae 12156
9bcb3eef 12157 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12158 if (prefix_check
b54892e0 12159 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12160 bgp_dest_unlock_node(rm);
ea47320b
DL
12161 continue;
12162 }
d62a17ae 12163
9bcb3eef 12164 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12165 bgp, afi, safi, json, pathtype,
4027d19b 12166 &display, rpki_target_state);
44c69747 12167
9bcb3eef 12168 bgp_dest_unlock_node(rm);
44c69747
LK
12169 }
12170 } else if (safi == SAFI_EVPN) {
9bcb3eef 12171 struct bgp_dest *longest_pfx;
cded3b72 12172 bool is_exact_pfxlen_match = false;
44c69747 12173
9bcb3eef
DS
12174 for (dest = bgp_table_top(rib); dest;
12175 dest = bgp_route_next(dest)) {
12176 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12177
9bcb3eef 12178 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12179 continue;
9bcb3eef 12180 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12181 if (!table)
12182 continue;
12183
12184 longest_pfx = NULL;
cded3b72 12185 is_exact_pfxlen_match = false;
44c69747
LK
12186 /*
12187 * Search through all the prefixes for a match. The
12188 * pfx's are enumerated in ascending order of pfxlens.
12189 * So, the last pfx match is the longest match. Set
12190 * is_exact_pfxlen_match when we get exact pfxlen match
12191 */
12192 for (rm = bgp_table_top(table); rm;
12193 rm = bgp_route_next(rm)) {
b54892e0 12194 const struct prefix *rm_p =
9bcb3eef 12195 bgp_dest_get_prefix(rm);
44c69747
LK
12196 /*
12197 * Get prefixlen of the ip-prefix within type5
12198 * evpn route
12199 */
b54892e0
DS
12200 if (evpn_type5_prefix_match(rm_p, &match)
12201 && rm->info) {
44c69747
LK
12202 longest_pfx = rm;
12203 int type5_pfxlen =
b54892e0
DS
12204 bgp_evpn_get_type5_prefixlen(
12205 rm_p);
44c69747 12206 if (type5_pfxlen == match.prefixlen) {
cded3b72 12207 is_exact_pfxlen_match = true;
9bcb3eef 12208 bgp_dest_unlock_node(rm);
44c69747
LK
12209 break;
12210 }
d62a17ae 12211 }
12212 }
ea47320b 12213
44c69747
LK
12214 if (!longest_pfx)
12215 continue;
12216
12217 if (prefix_check && !is_exact_pfxlen_match)
12218 continue;
12219
12220 rm = longest_pfx;
9bcb3eef 12221 bgp_dest_lock_node(rm);
44c69747 12222
9bcb3eef 12223 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12224 bgp, afi, safi, json, pathtype,
4027d19b 12225 &display, rpki_target_state);
44c69747 12226
9bcb3eef 12227 bgp_dest_unlock_node(rm);
d62a17ae 12228 }
98a9dbc7 12229 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12230 if (use_json)
12231 json_paths = json_object_new_array();
12232
63a0b7a9
PG
12233 display = bgp_flowspec_display_match_per_ip(afi, rib,
12234 &match, prefix_check,
12235 vty,
12236 use_json,
12237 json_paths);
d5f20468
SP
12238 if (use_json) {
12239 if (display)
12240 json_object_object_add(json, "paths",
12241 json_paths);
12242 else
12243 json_object_free(json_paths);
12244 }
d62a17ae 12245 } else {
4953391b
DA
12246 dest = bgp_node_match(rib, &match);
12247 if (dest != NULL) {
9bcb3eef 12248 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12249 if (!prefix_check
9bcb3eef
DS
12250 || dest_p->prefixlen == match.prefixlen) {
12251 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12252 safi, json, pathtype,
4027d19b 12253 &display, rpki_target_state);
d62a17ae 12254 }
12255
9bcb3eef 12256 bgp_dest_unlock_node(dest);
d62a17ae 12257 }
12258 }
e5eee9af 12259
d62a17ae 12260 if (use_json) {
75eeda93 12261 vty_json(vty, json);
d62a17ae 12262 } else {
12263 if (!display) {
12264 vty_out(vty, "%% Network not in table\n");
12265 return CMD_WARNING;
12266 }
12267 }
b05a1c8b 12268
d62a17ae 12269 return CMD_SUCCESS;
718e3744 12270}
12271
fee0f4c6 12272/* Display specified route of Main RIB */
d62a17ae 12273static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12274 afi_t afi, safi_t safi, struct prefix_rd *prd,
12275 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12276 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12277{
9b86009a 12278 if (!bgp) {
d62a17ae 12279 bgp = bgp_get_default();
9b86009a
RW
12280 if (!bgp) {
12281 if (!use_json)
12282 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12283 else
12284 vty_out(vty, "{}\n");
9b86009a
RW
12285 return CMD_WARNING;
12286 }
12287 }
d62a17ae 12288
12289 /* labeled-unicast routes live in the unicast table */
12290 if (safi == SAFI_LABELED_UNICAST)
12291 safi = SAFI_UNICAST;
12292
12293 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12294 afi, safi, rpki_target_state, prd,
8aa22bbb 12295 prefix_check, pathtype, use_json);
d62a17ae 12296}
12297
12298static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12299 struct cmd_token **argv, bool exact, afi_t afi,
12300 safi_t safi, bool uj)
d62a17ae 12301{
12302 struct lcommunity *lcom;
12303 struct buffer *b;
12304 int i;
12305 char *str;
12306 int first = 0;
96c81f66 12307 uint16_t show_flags = 0;
4f28b2b5 12308 int ret;
96f3485c
MK
12309
12310 if (uj)
12311 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12312
12313 b = buffer_new(1024);
12314 for (i = 0; i < argc; i++) {
12315 if (first)
12316 buffer_putc(b, ' ');
12317 else {
12318 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12319 first = 1;
12320 buffer_putstr(b, argv[i]->arg);
12321 }
12322 }
12323 }
12324 buffer_putc(b, '\0');
57d187bc 12325
d62a17ae 12326 str = buffer_getstr(b);
12327 buffer_free(b);
57d187bc 12328
d62a17ae 12329 lcom = lcommunity_str2com(str);
12330 XFREE(MTYPE_TMP, str);
12331 if (!lcom) {
12332 vty_out(vty, "%% Large-community malformed\n");
12333 return CMD_WARNING;
12334 }
57d187bc 12335
4f28b2b5 12336 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12337 (exact ? bgp_show_type_lcommunity_exact
12338 : bgp_show_type_lcommunity),
12339 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12340
12341 lcommunity_free(&lcom);
12342 return ret;
57d187bc
JS
12343}
12344
d62a17ae 12345static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12346 const char *lcom, bool exact, afi_t afi,
12347 safi_t safi, bool uj)
57d187bc 12348{
d62a17ae 12349 struct community_list *list;
96c81f66 12350 uint16_t show_flags = 0;
96f3485c
MK
12351
12352 if (uj)
12353 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12354
57d187bc 12355
e237b0d2 12356 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12357 LARGE_COMMUNITY_LIST_MASTER);
12358 if (list == NULL) {
12359 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12360 lcom);
12361 return CMD_WARNING;
12362 }
57d187bc 12363
36a206db 12364 return bgp_show(vty, bgp, afi, safi,
12365 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12366 : bgp_show_type_lcommunity_list),
1e2ce4f1 12367 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12368}
12369
52951b63
DS
12370DEFUN (show_ip_bgp_large_community_list,
12371 show_ip_bgp_large_community_list_cmd,
77a3a95e 12372 "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
12373 SHOW_STR
12374 IP_STR
12375 BGP_STR
12376 BGP_INSTANCE_HELP_STR
9bedbb1e 12377 BGP_AFI_HELP_STR
4dd6177e 12378 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12379 "Display routes matching the large-community-list\n"
12380 "large-community-list number\n"
12381 "large-community-list name\n"
36a206db 12382 "Exact match of the large-communities\n"
52951b63
DS
12383 JSON_STR)
12384{
d62a17ae 12385 afi_t afi = AFI_IP6;
12386 safi_t safi = SAFI_UNICAST;
12387 int idx = 0;
36a206db 12388 bool exact_match = 0;
4d678463 12389 struct bgp *bgp = NULL;
9f049418 12390 bool uj = use_json(argc, argv);
d62a17ae 12391
ef3364f0
DA
12392 if (uj)
12393 argc--;
4d678463 12394
ef3364f0
DA
12395 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12396 &bgp, uj);
12397 if (!idx)
12398 return CMD_WARNING;
d62a17ae 12399
12400 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12401
12402 const char *clist_number_or_name = argv[++idx]->arg;
12403
12404 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12405 exact_match = 1;
12406
12407 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12408 exact_match, afi, safi, uj);
52951b63
DS
12409}
12410DEFUN (show_ip_bgp_large_community,
12411 show_ip_bgp_large_community_cmd,
36a206db 12412 "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
12413 SHOW_STR
12414 IP_STR
12415 BGP_STR
12416 BGP_INSTANCE_HELP_STR
9bedbb1e 12417 BGP_AFI_HELP_STR
4dd6177e 12418 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12419 "Display routes matching the large-communities\n"
12420 "List of large-community numbers\n"
36a206db 12421 "Exact match of the large-communities\n"
52951b63
DS
12422 JSON_STR)
12423{
d62a17ae 12424 afi_t afi = AFI_IP6;
12425 safi_t safi = SAFI_UNICAST;
12426 int idx = 0;
36a206db 12427 bool exact_match = 0;
4d678463 12428 struct bgp *bgp = NULL;
9f049418 12429 bool uj = use_json(argc, argv);
96c81f66 12430 uint16_t show_flags = 0;
d62a17ae 12431
96f3485c
MK
12432 if (uj) {
12433 argc--;
12434 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12435 }
4d678463 12436
96f3485c
MK
12437 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12438 &bgp, uj);
12439 if (!idx)
12440 return CMD_WARNING;
d62a17ae 12441
36a206db 12442 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12443 if (argv_find(argv, argc, "exact-match", &idx)) {
12444 argc--;
36a206db 12445 exact_match = 1;
1857760c 12446 }
36a206db 12447 return bgp_show_lcommunity(vty, bgp, argc, argv,
12448 exact_match, afi, safi, uj);
12449 } else
d62a17ae 12450 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12451 bgp_show_type_lcommunity_all, NULL, show_flags,
12452 RPKI_NOT_BEING_USED);
52951b63
DS
12453}
12454
71f1613a
DA
12455static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12456 safi_t safi, struct json_object *json_array);
d62a17ae 12457static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12458 safi_t safi, struct json_object *json);
e01ca200 12459
7b2ff250 12460
9ab0cf58
PG
12461DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12462 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12463 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12464 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12465{
12466 bool uj = use_json(argc, argv);
12467 struct bgp *bgp = NULL;
ec76a1d1
DA
12468 safi_t safi = SAFI_UNICAST;
12469 afi_t afi = AFI_IP6;
4265b261 12470 int idx = 0;
6c9d22e2
PG
12471 struct json_object *json_all = NULL;
12472 struct json_object *json_afi_safi = NULL;
4265b261
PG
12473
12474 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12475 &bgp, false);
71f1613a 12476 if (!idx)
4265b261 12477 return CMD_WARNING;
6c9d22e2 12478
4265b261 12479 if (uj)
6c9d22e2 12480 json_all = json_object_new_object();
4265b261 12481
9ab0cf58
PG
12482 FOREACH_AFI_SAFI (afi, safi) {
12483 /*
12484 * So limit output to those afi/safi pairs that
12485 * actually have something interesting in them
12486 */
12487 if (strmatch(get_afi_safi_str(afi, safi, true),
12488 "Unknown")) {
12489 continue;
12490 }
12491 if (uj) {
12492 json_afi_safi = json_object_new_array();
12493 json_object_object_add(
12494 json_all,
12495 get_afi_safi_str(afi, safi, true),
12496 json_afi_safi);
12497 } else {
12498 json_afi_safi = NULL;
6c9d22e2 12499 }
9ab0cf58
PG
12500
12501 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12502 }
6c9d22e2 12503
3757f964
DA
12504 if (uj)
12505 vty_json(vty, json_all);
6c9d22e2 12506
4265b261
PG
12507 return CMD_SUCCESS;
12508}
12509
7b2ff250 12510/* BGP route print out function without JSON */
14718643
PG
12511DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12512 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12513 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12514 SHOW_STR
12515 IP_STR
12516 BGP_STR
12517 BGP_INSTANCE_HELP_STR
12518 L2VPN_HELP_STR
12519 EVPN_HELP_STR
12520 "BGP RIB advertisement statistics\n"
12521 JSON_STR)
12522{
ec76a1d1
DA
12523 afi_t afi = AFI_IP6;
12524 safi_t safi = SAFI_UNICAST;
14718643
PG
12525 struct bgp *bgp = NULL;
12526 int idx = 0, ret;
12527 bool uj = use_json(argc, argv);
12528 struct json_object *json_afi_safi = NULL, *json = NULL;
12529
12530 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12531 &bgp, false);
12532 if (!idx)
12533 return CMD_WARNING;
12534
12535 if (uj)
12536 json_afi_safi = json_object_new_array();
12537 else
12538 json_afi_safi = NULL;
12539
12540 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12541
12542 if (uj) {
12543 json = json_object_new_object();
12544 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12545 json_afi_safi);
3757f964 12546 vty_json(vty, json);
14718643
PG
12547 }
12548 return ret;
12549}
12550
893cccd0 12551/* BGP route print out function without JSON */
9ab0cf58
PG
12552DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12553 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12554 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12555 "]]\
893cccd0 12556 statistics [json]",
9ab0cf58
PG
12557 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12558 BGP_SAFI_WITH_LABEL_HELP_STR
12559 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12560{
ec76a1d1
DA
12561 afi_t afi = AFI_IP6;
12562 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12563 struct bgp *bgp = NULL;
12564 int idx = 0, ret;
12565 bool uj = use_json(argc, argv);
6c9d22e2 12566 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12567
12568 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12569 &bgp, false);
12570 if (!idx)
12571 return CMD_WARNING;
6c9d22e2 12572
893cccd0 12573 if (uj)
6c9d22e2
PG
12574 json_afi_safi = json_object_new_array();
12575 else
12576 json_afi_safi = NULL;
12577
12578 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12579
12580 if (uj) {
12581 json = json_object_new_object();
12582 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12583 json_afi_safi);
3757f964 12584 vty_json(vty, json);
893cccd0
PG
12585 }
12586 return ret;
893cccd0 12587}
7b2ff250 12588
fe0f234d 12589DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12590 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12591 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12592 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12593 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12594 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12595 "Display the entries for all address families\n"
9ab0cf58
PG
12596 "Display detailed information about dampening\n"
12597 "Display detail of configured dampening parameters\n"
fe0f234d 12598 JSON_STR)
718e3744 12599{
d62a17ae 12600 afi_t afi = AFI_IP6;
12601 safi_t safi = SAFI_UNICAST;
d62a17ae 12602 struct bgp *bgp = NULL;
12603 int idx = 0;
96c81f66 12604 uint16_t show_flags = 0;
fe0f234d
RW
12605 bool uj = use_json(argc, argv);
12606
12607 if (uj) {
12608 argc--;
12609 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12610 }
96f3485c
MK
12611
12612 /* [<ipv4|ipv6> [all]] */
12613 if (all) {
12614 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12615 if (argv_find(argv, argc, "ipv4", &idx))
12616 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12617
12618 if (argv_find(argv, argc, "ipv6", &idx))
12619 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12620 }
d62a17ae 12621
12622 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12623 &bgp, false);
d62a17ae 12624 if (!idx)
12625 return CMD_WARNING;
12626
fe0f234d 12627 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12628}
12629
fe0f234d
RW
12630/* BGP route print out function */
12631DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12632 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12633 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12634 "]]\
96f3485c 12635 [all$all]\
cf4898bc
QY
12636 [cidr-only\
12637 |dampening <flap-statistics|dampened-paths>\
12638 |community [AA:NN|local-AS|no-advertise|no-export\
12639 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12640 |accept-own|accept-own-nexthop|route-filter-v6\
12641 |route-filter-v4|route-filter-translated-v6\
12642 |route-filter-translated-v4] [exact-match]\
70799983 12643 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12644 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12645 |prefix-list WORD\
ed126382 12646 |access-list ACCESSLIST_NAME\
70dd370f 12647 |route-map RMAP_NAME\
1e2ce4f1 12648 |rpki <invalid|valid|notfound>\
7d3cae70 12649 |version (1-4294967295)\
b4ad2fae 12650 |alias ALIAS_NAME\
39c3c736
RW
12651 |A.B.C.D/M longer-prefixes\
12652 |X:X::X:X/M longer-prefixes\
70cd87ca 12653 |optimal-route-reflection [WORD$orr_group_name]\
f280c93b 12654 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12655 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12656 BGP_SAFI_WITH_LABEL_HELP_STR
12657 "Display the entries for all address families\n"
12658 "Display only routes with non-natural netmasks\n"
12659 "Display detailed information about dampening\n"
12660 "Display flap statistics of routes\n"
12661 "Display paths suppressed due to dampening\n"
12662 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12663 "Do not send outside local AS (well-known community)\n"
12664 "Do not advertise to any peer (well-known community)\n"
12665 "Do not export to next AS (well-known community)\n"
12666 "Graceful shutdown (well-known community)\n"
12667 "Do not export to any peer (well-known community)\n"
12668 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12669 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12670 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12671 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12672 "Should accept VPN route with local nexthop (well-known community)\n"
12673 "RT VPNv6 route filtering (well-known community)\n"
12674 "RT VPNv4 route filtering (well-known community)\n"
12675 "RT translated VPNv6 route filtering (well-known community)\n"
12676 "RT translated VPNv4 route filtering (well-known community)\n"
12677 "Exact match of the communities\n"
70799983
RW
12678 "Community-list number\n"
12679 "Community-list name\n"
12680 "Display routes matching the community-list\n"
12681 "Exact match of the communities\n"
a7129347
RW
12682 "Display routes conforming to the filter-list\n"
12683 "Regular expression access list name\n"
6deaf579
RW
12684 "Display routes conforming to the prefix-list\n"
12685 "Prefix-list name\n"
ed126382
DA
12686 "Display routes conforming to the access-list\n"
12687 "Access-list name\n"
bf1a944a
RW
12688 "Display routes matching the route-map\n"
12689 "A route-map to match on\n"
a70a28a5
DA
12690 "RPKI route types\n"
12691 "A valid path as determined by rpki\n"
12692 "A invalid path as determined by rpki\n"
12693 "A path that has no rpki data\n"
12694 "Display prefixes with matching version numbers\n"
12695 "Version number and above\n"
12696 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12697 "BGP community alias\n"
12698 "IPv4 prefix\n"
12699 "Display route and more specific routes\n"
12700 "IPv6 prefix\n"
12701 "Display route and more specific routes\n"
70cd87ca
MK
12702 "Display Optimal Route Reflection RR Clients\n"
12703 "ORR Group name\n"
39c3c736 12704 JSON_STR
a70a28a5
DA
12705 "Display detailed version of JSON output\n"
12706 "Increase table width for longer prefixes\n")
7b2ff250
DW
12707{
12708 afi_t afi = AFI_IP6;
12709 safi_t safi = SAFI_UNICAST;
12710 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12711 void *output_arg = NULL;
7b2ff250
DW
12712 struct bgp *bgp = NULL;
12713 int idx = 0;
d0086e8e 12714 int exact_match = 0;
96f3485c
MK
12715 char *community = NULL;
12716 bool first = true;
96c81f66 12717 uint16_t show_flags = 0;
4027d19b 12718 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12719 struct prefix p;
70cd87ca 12720 bool orr_group = false;
96f3485c
MK
12721
12722 if (uj) {
9f049418 12723 argc--;
96f3485c
MK
12724 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12725 }
12726
f280c93b
DA
12727 if (detail)
12728 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12729
96f3485c
MK
12730 /* [<ipv4|ipv6> [all]] */
12731 if (all) {
12732 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12733
12734 if (argv_find(argv, argc, "ipv4", &idx))
12735 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12736
12737 if (argv_find(argv, argc, "ipv6", &idx))
12738 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12739 }
12740
12741 if (wide)
12742 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12743
12744 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12745 &bgp, uj);
7b2ff250
DW
12746 if (!idx)
12747 return CMD_WARNING;
12748
7b2ff250 12749 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12750 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12751
12752 if (argv_find(argv, argc, "dampening", &idx)) {
12753 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12754 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12755 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12756 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12757 }
12758
12759 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12760 char *maybecomm = NULL;
d0086e8e 12761
79bc257a
RW
12762 if (idx + 1 < argc) {
12763 if (argv[idx + 1]->type == VARIABLE_TKN)
12764 maybecomm = argv[idx + 1]->arg;
12765 else
12766 maybecomm = argv[idx + 1]->text;
12767 }
12768
cf4898bc
QY
12769 if (maybecomm && !strmatch(maybecomm, "json")
12770 && !strmatch(maybecomm, "exact-match"))
12771 community = maybecomm;
d0086e8e 12772
cf4898bc
QY
12773 if (argv_find(argv, argc, "exact-match", &idx))
12774 exact_match = 1;
d0086e8e 12775
96f3485c
MK
12776 if (!community)
12777 sh_type = bgp_show_type_community_all;
12778 }
12779
70799983
RW
12780 if (argv_find(argv, argc, "community-list", &idx)) {
12781 const char *clist_number_or_name = argv[++idx]->arg;
12782 struct community_list *list;
12783
12784 if (argv_find(argv, argc, "exact-match", &idx))
12785 exact_match = 1;
12786
12787 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12788 COMMUNITY_LIST_MASTER);
12789 if (list == NULL) {
606d49a4 12790 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12791 clist_number_or_name);
12792 return CMD_WARNING;
12793 }
12794
12795 if (exact_match)
12796 sh_type = bgp_show_type_community_list_exact;
12797 else
12798 sh_type = bgp_show_type_community_list;
12799 output_arg = list;
12800 }
12801
a7129347
RW
12802 if (argv_find(argv, argc, "filter-list", &idx)) {
12803 const char *filter = argv[++idx]->arg;
12804 struct as_list *as_list;
12805
12806 as_list = as_list_lookup(filter);
12807 if (as_list == NULL) {
606d49a4 12808 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12809 filter);
12810 return CMD_WARNING;
12811 }
12812
12813 sh_type = bgp_show_type_filter_list;
12814 output_arg = as_list;
12815 }
12816
6deaf579
RW
12817 if (argv_find(argv, argc, "prefix-list", &idx)) {
12818 const char *prefix_list_str = argv[++idx]->arg;
12819 struct prefix_list *plist;
12820
12821 plist = prefix_list_lookup(afi, prefix_list_str);
12822 if (plist == NULL) {
606d49a4 12823 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12824 prefix_list_str);
12825 return CMD_WARNING;
12826 }
12827
12828 sh_type = bgp_show_type_prefix_list;
12829 output_arg = plist;
12830 }
12831
ed126382
DA
12832 if (argv_find(argv, argc, "access-list", &idx)) {
12833 const char *access_list_str = argv[++idx]->arg;
12834 struct access_list *alist;
12835
12836 alist = access_list_lookup(afi, access_list_str);
12837 if (!alist) {
606d49a4 12838 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12839 access_list_str);
12840 return CMD_WARNING;
12841 }
12842
12843 sh_type = bgp_show_type_access_list;
12844 output_arg = alist;
12845 }
12846
bf1a944a
RW
12847 if (argv_find(argv, argc, "route-map", &idx)) {
12848 const char *rmap_str = argv[++idx]->arg;
12849 struct route_map *rmap;
12850
12851 rmap = route_map_lookup_by_name(rmap_str);
12852 if (!rmap) {
606d49a4 12853 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12854 return CMD_WARNING;
12855 }
12856
12857 sh_type = bgp_show_type_route_map;
12858 output_arg = rmap;
12859 }
12860
1e2ce4f1
DS
12861 if (argv_find(argv, argc, "rpki", &idx)) {
12862 sh_type = bgp_show_type_rpki;
12863 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12864 rpki_target_state = RPKI_VALID;
1e2ce4f1 12865 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12866 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12867 }
12868
7d3cae70
DA
12869 /* Display prefixes with matching version numbers */
12870 if (argv_find(argv, argc, "version", &idx)) {
12871 sh_type = bgp_show_type_prefix_version;
2391833e 12872 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12873 }
12874
a70a28a5
DA
12875 /* Display prefixes with matching BGP community alias */
12876 if (argv_find(argv, argc, "alias", &idx)) {
12877 sh_type = bgp_show_type_community_alias;
2391833e 12878 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12879 }
12880
39c3c736
RW
12881 /* prefix-longer */
12882 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12883 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12884 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12885
12886 if (!str2prefix(prefix_str, &p)) {
12887 vty_out(vty, "%% Malformed Prefix\n");
12888 return CMD_WARNING;
12889 }
12890
12891 sh_type = bgp_show_type_prefix_longer;
12892 output_arg = &p;
a70a28a5
DA
12893 }
12894
70cd87ca
MK
12895 if (argv_find(argv, argc, "optimal-route-reflection", &idx))
12896 orr_group = true;
12897
96f3485c
MK
12898 if (!all) {
12899 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12900 if (community)
12901 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12902 exact_match, afi, safi,
12903 show_flags);
70cd87ca
MK
12904 else if (orr_group)
12905 return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
12906 show_flags);
2391833e 12907 else
a70a28a5 12908 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12909 output_arg, show_flags,
a70a28a5 12910 rpki_target_state);
96f3485c 12911 } else {
fa5ac378
DA
12912 struct listnode *node;
12913 struct bgp *abgp;
96f3485c
MK
12914 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12915 * AFI_IP6 */
12916
12917 if (uj)
12918 vty_out(vty, "{\n");
12919
12920 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12921 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12922 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12923 ? AFI_IP
12924 : AFI_IP6;
fa5ac378
DA
12925 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12926 FOREACH_SAFI (safi) {
12927 if (!bgp_afi_safi_peer_exists(abgp, afi,
12928 safi))
12929 continue;
96f3485c 12930
fa5ac378
DA
12931 if (uj) {
12932 if (first)
12933 first = false;
12934 else
12935 vty_out(vty, ",\n");
12936 vty_out(vty, "\"%s\":{\n",
12937 get_afi_safi_str(afi,
12938 safi,
12939 true));
12940 } else
12941 vty_out(vty,
12942 "\nFor address family: %s\n",
12943 get_afi_safi_str(
12944 afi, safi,
12945 false));
12946
12947 if (community)
12948 bgp_show_community(
12949 vty, abgp, community,
12950 exact_match, afi, safi,
12951 show_flags);
70cd87ca
MK
12952 else if (orr_group)
12953 bgp_show_orr(vty, bgp, afi,
12954 safi,
12955 orr_group_name,
12956 show_flags);
96f3485c 12957 else
fa5ac378
DA
12958 bgp_show(vty, abgp, afi, safi,
12959 sh_type, output_arg,
12960 show_flags,
12961 rpki_target_state);
12962 if (uj)
12963 vty_out(vty, "}\n");
12964 }
96f3485c
MK
12965 }
12966 } else {
12967 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12968 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12969 FOREACH_AFI_SAFI (afi, safi) {
12970 if (!bgp_afi_safi_peer_exists(abgp, afi,
12971 safi))
12972 continue;
96f3485c 12973
fa5ac378
DA
12974 if (uj) {
12975 if (first)
12976 first = false;
12977 else
12978 vty_out(vty, ",\n");
12979
12980 vty_out(vty, "\"%s\":{\n",
12981 get_afi_safi_str(afi,
12982 safi,
12983 true));
12984 } else
12985 vty_out(vty,
12986 "\nFor address family: %s\n",
12987 get_afi_safi_str(
12988 afi, safi,
12989 false));
12990
12991 if (community)
12992 bgp_show_community(
12993 vty, abgp, community,
12994 exact_match, afi, safi,
12995 show_flags);
70cd87ca
MK
12996 else if (orr_group)
12997 bgp_show_orr(vty, bgp, afi,
12998 safi,
12999 orr_group_name,
13000 show_flags);
96f3485c 13001 else
fa5ac378
DA
13002 bgp_show(vty, abgp, afi, safi,
13003 sh_type, output_arg,
13004 show_flags,
13005 rpki_target_state);
13006 if (uj)
13007 vty_out(vty, "}\n");
13008 }
96f3485c
MK
13009 }
13010 }
13011 if (uj)
13012 vty_out(vty, "}\n");
13013 }
13014 return CMD_SUCCESS;
a636c635 13015}
47fc97cc 13016
718e3744 13017DEFUN (show_ip_bgp_route,
13018 show_ip_bgp_route_cmd,
8aa22bbb 13019 "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 13020 SHOW_STR
13021 IP_STR
13022 BGP_STR
a636c635 13023 BGP_INSTANCE_HELP_STR
4f280b15 13024 BGP_AFI_HELP_STR
4dd6177e 13025 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13026 "Network in the BGP routing table to display\n"
0c7b1b01 13027 "IPv4 prefix\n"
8c3deaae 13028 "Network in the BGP routing table to display\n"
0c7b1b01 13029 "IPv6 prefix\n"
4092b06c 13030 "Display only the bestpath\n"
b05a1c8b 13031 "Display only multipaths\n"
8aa22bbb
DS
13032 "Display only paths that match the specified rpki state\n"
13033 "A valid path as determined by rpki\n"
13034 "A invalid path as determined by rpki\n"
13035 "A path that has no rpki data\n"
9973d184 13036 JSON_STR)
4092b06c 13037{
d62a17ae 13038 int prefix_check = 0;
ae19d7dd 13039
d62a17ae 13040 afi_t afi = AFI_IP6;
13041 safi_t safi = SAFI_UNICAST;
13042 char *prefix = NULL;
13043 struct bgp *bgp = NULL;
13044 enum bgp_path_type path_type;
9f049418 13045 bool uj = use_json(argc, argv);
b05a1c8b 13046
d62a17ae 13047 int idx = 0;
ae19d7dd 13048
d62a17ae 13049 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13050 &bgp, uj);
d62a17ae 13051 if (!idx)
13052 return CMD_WARNING;
c41247f5 13053
d62a17ae 13054 if (!bgp) {
13055 vty_out(vty,
13056 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13057 return CMD_WARNING;
13058 }
a636c635 13059
d62a17ae 13060 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13061 if (argv_find(argv, argc, "A.B.C.D", &idx)
13062 || argv_find(argv, argc, "X:X::X:X", &idx))
13063 prefix_check = 0;
13064 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13065 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13066 prefix_check = 1;
13067
13068 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13069 && afi != AFI_IP6) {
13070 vty_out(vty,
13071 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13072 return CMD_WARNING;
13073 }
13074 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13075 && afi != AFI_IP) {
13076 vty_out(vty,
13077 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13078 return CMD_WARNING;
13079 }
13080
13081 prefix = argv[idx]->arg;
13082
13083 /* [<bestpath|multipath>] */
13084 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13085 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13086 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13087 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13088 else
360660c6 13089 path_type = BGP_PATH_SHOW_ALL;
a636c635 13090
d62a17ae 13091 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13092 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13093}
13094
8c3deaae
QY
13095DEFUN (show_ip_bgp_regexp,
13096 show_ip_bgp_regexp_cmd,
3e5b31b3 13097 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13098 SHOW_STR
13099 IP_STR
13100 BGP_STR
b00b230a 13101 BGP_INSTANCE_HELP_STR
4f280b15 13102 BGP_AFI_HELP_STR
4dd6177e 13103 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13104 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13105 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13106 JSON_STR)
8c3deaae 13107{
d62a17ae 13108 afi_t afi = AFI_IP6;
13109 safi_t safi = SAFI_UNICAST;
13110 struct bgp *bgp = NULL;
3e5b31b3
DA
13111 bool uj = use_json(argc, argv);
13112 char *regstr = NULL;
8c3deaae 13113
d62a17ae 13114 int idx = 0;
13115 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13116 &bgp, false);
d62a17ae 13117 if (!idx)
13118 return CMD_WARNING;
8c3deaae 13119
d62a17ae 13120 // get index of regex
3e5b31b3
DA
13121 if (argv_find(argv, argc, "REGEX", &idx))
13122 regstr = argv[idx]->arg;
8c3deaae 13123
5f71d11c 13124 assert(regstr);
3e5b31b3
DA
13125 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13126 bgp_show_type_regexp, uj);
8c3deaae
QY
13127}
13128
ae248832 13129DEFPY (show_ip_bgp_instance_all,
a636c635 13130 show_ip_bgp_instance_all_cmd,
ae248832 13131 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13132 SHOW_STR
a636c635 13133 IP_STR
4092b06c 13134 BGP_STR
a636c635 13135 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13136 BGP_AFI_HELP_STR
4dd6177e 13137 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13138 JSON_STR
13139 "Increase table width for longer prefixes\n")
4092b06c 13140{
54d05dea 13141 afi_t afi = AFI_IP6;
d62a17ae 13142 safi_t safi = SAFI_UNICAST;
13143 struct bgp *bgp = NULL;
d62a17ae 13144 int idx = 0;
96c81f66 13145 uint16_t show_flags = 0;
ae19d7dd 13146
96f3485c 13147 if (uj) {
d62a17ae 13148 argc--;
96f3485c
MK
13149 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13150 }
13151
13152 if (wide)
13153 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13154
9f049418
DS
13155 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13156 &bgp, uj);
13157 if (!idx)
13158 return CMD_WARNING;
13159
96f3485c 13160 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13161 return CMD_SUCCESS;
e3e29b32
LB
13162}
13163
a4d82a8a 13164static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13165 afi_t afi, safi_t safi, enum bgp_show_type type,
13166 bool use_json)
718e3744 13167{
d62a17ae 13168 regex_t *regex;
13169 int rc;
96c81f66 13170 uint16_t show_flags = 0;
96f3485c
MK
13171
13172 if (use_json)
13173 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13174
c3900853 13175 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13176 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13177 regstr);
13178 return CMD_WARNING_CONFIG_FAILED;
13179 }
13180
d62a17ae 13181 regex = bgp_regcomp(regstr);
13182 if (!regex) {
13183 vty_out(vty, "Can't compile regexp %s\n", regstr);
13184 return CMD_WARNING;
13185 }
a636c635 13186
1e2ce4f1
DS
13187 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13188 RPKI_NOT_BEING_USED);
d62a17ae 13189 bgp_regex_free(regex);
13190 return rc;
e3e29b32
LB
13191}
13192
7f323236
DW
13193static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13194 const char *comstr, int exact, afi_t afi,
96c81f66 13195 safi_t safi, uint16_t show_flags)
d62a17ae 13196{
13197 struct community *com;
d62a17ae 13198 int ret = 0;
13199
7f323236 13200 com = community_str2com(comstr);
d62a17ae 13201 if (!com) {
7f323236 13202 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13203 return CMD_WARNING;
13204 }
13205
13206 ret = bgp_show(vty, bgp, afi, safi,
13207 (exact ? bgp_show_type_community_exact
13208 : bgp_show_type_community),
1e2ce4f1 13209 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13210 community_free(&com);
46c3ce83 13211
d62a17ae 13212 return ret;
718e3744 13213}
13214
d62a17ae 13215enum bgp_stats {
13216 BGP_STATS_MAXBITLEN = 0,
13217 BGP_STATS_RIB,
13218 BGP_STATS_PREFIXES,
13219 BGP_STATS_TOTPLEN,
13220 BGP_STATS_UNAGGREGATEABLE,
13221 BGP_STATS_MAX_AGGREGATEABLE,
13222 BGP_STATS_AGGREGATES,
13223 BGP_STATS_SPACE,
13224 BGP_STATS_ASPATH_COUNT,
13225 BGP_STATS_ASPATH_MAXHOPS,
13226 BGP_STATS_ASPATH_TOTHOPS,
13227 BGP_STATS_ASPATH_MAXSIZE,
13228 BGP_STATS_ASPATH_TOTSIZE,
13229 BGP_STATS_ASN_HIGHEST,
13230 BGP_STATS_MAX,
a636c635 13231};
2815e61f 13232
9ab0cf58 13233#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13234#define TABLE_STATS_IDX_JSON 1
13235
13236static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13237 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13238 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13239 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13240 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13241 "unaggregateablePrefixes"},
13242 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13243 "maximumAggregateablePrefixes"},
13244 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13245 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13246 [BGP_STATS_SPACE] = {"Address space advertised",
13247 "addressSpaceAdvertised"},
9ab0cf58
PG
13248 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13249 "advertisementsWithPaths"},
13250 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13251 "longestAsPath"},
13252 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13253 "largestAsPath"},
13254 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13255 "averageAsPathLengthHops"},
13256 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13257 "averageAsPathSizeBytes"},
13258 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13259 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13260};
2815e61f 13261
d62a17ae 13262struct bgp_table_stats {
13263 struct bgp_table *table;
13264 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13265
13266 unsigned long long
13267 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13268 1];
13269
8d0ab76d 13270 double total_space;
ff7924f6
PJ
13271};
13272
9bcb3eef 13273static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13274 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13275{
9bcb3eef 13276 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13277 struct bgp_path_info *pi;
b54892e0 13278 const struct prefix *rn_p;
d62a17ae 13279
9bcb3eef 13280 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13281 return;
d62a17ae 13282
9bcb3eef 13283 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13284 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13285 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13286
0747643e 13287 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13288 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13289 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13290 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13291
9bcb3eef 13292 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13293 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13294 /* announced address space */
13295 if (space)
b54892e0 13296 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13297 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13298 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13299
9c14ec72 13300
9bcb3eef 13301 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13302 ts->counts[BGP_STATS_RIB]++;
13303
05864da7
DS
13304 if (CHECK_FLAG(pi->attr->flag,
13305 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13306 ts->counts[BGP_STATS_AGGREGATES]++;
13307
13308 /* as-path stats */
05864da7 13309 if (pi->attr->aspath) {
9c14ec72
RW
13310 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13311 unsigned int size = aspath_size(pi->attr->aspath);
13312 as_t highest = aspath_highest(pi->attr->aspath);
13313
13314 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13315
13316 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13317 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13318
13319 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13320 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13321
13322 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13323 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13324 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13325 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13326 }
13327 }
13328}
13329
cc9f21da 13330static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13331{
9bcb3eef
DS
13332 struct bgp_dest *dest, *ndest;
13333 struct bgp_dest *top;
9c14ec72
RW
13334 struct bgp_table_stats *ts = THREAD_ARG(t);
13335 unsigned int space = 0;
13336
13337 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13338 return;
9c14ec72
RW
13339
13340 switch (ts->table->afi) {
13341 case AFI_IP:
13342 space = IPV4_MAX_BITLEN;
13343 break;
13344 case AFI_IP6:
13345 space = IPV6_MAX_BITLEN;
13346 break;
3ba7b4af
TA
13347 case AFI_L2VPN:
13348 space = EVPN_ROUTE_PREFIXLEN;
13349 break;
9c14ec72 13350 default:
cc9f21da 13351 return;
9c14ec72
RW
13352 }
13353
13354 ts->counts[BGP_STATS_MAXBITLEN] = space;
13355
9bcb3eef 13356 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13357 if (ts->table->safi == SAFI_MPLS_VPN
13358 || ts->table->safi == SAFI_ENCAP
13359 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13360 struct bgp_table *table;
13361
9bcb3eef 13362 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13363 if (!table)
13364 continue;
13365
13366 top = bgp_table_top(table);
9bcb3eef
DS
13367 for (ndest = bgp_table_top(table); ndest;
13368 ndest = bgp_route_next(ndest))
13369 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13370 } else {
9bcb3eef 13371 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13372 }
13373 }
2815e61f 13374}
ff7924f6 13375
71f1613a
DA
13376static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13377 struct json_object *json_array)
13378{
13379 struct listnode *node, *nnode;
13380 struct bgp *bgp;
13381
13382 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13383 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13384}
13385
13386static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13387 safi_t safi, struct json_object *json_array)
2815e61f 13388{
d62a17ae 13389 struct bgp_table_stats ts;
13390 unsigned int i;
893cccd0
PG
13391 int ret = CMD_SUCCESS;
13392 char temp_buf[20];
6c9d22e2 13393 struct json_object *json = NULL;
0747643e
AQ
13394 uint32_t bitlen = 0;
13395 struct json_object *json_bitlen;
6c9d22e2
PG
13396
13397 if (json_array)
13398 json = json_object_new_object();
019386c2 13399
d62a17ae 13400 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13401 char warning_msg[50];
13402
13403 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13404 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13405 safi);
6c9d22e2
PG
13406
13407 if (!json)
893cccd0
PG
13408 vty_out(vty, "%s\n", warning_msg);
13409 else
9ab0cf58 13410 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13411
893cccd0
PG
13412 ret = CMD_WARNING;
13413 goto end_table_stats;
d62a17ae 13414 }
019386c2 13415
893cccd0 13416 if (!json)
5290ceab
DA
13417 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13418 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13419 else
13420 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13421
d62a17ae 13422 /* labeled-unicast routes live in the unicast table */
13423 if (safi == SAFI_LABELED_UNICAST)
13424 safi = SAFI_UNICAST;
019386c2 13425
d62a17ae 13426 memset(&ts, 0, sizeof(ts));
13427 ts.table = bgp->rib[afi][safi];
13428 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13429
d62a17ae 13430 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13431 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13432 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13433 continue;
13434
13435 switch (i) {
d62a17ae 13436 case BGP_STATS_ASPATH_TOTHOPS:
13437 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13438 if (!json) {
9ab0cf58
PG
13439 snprintf(
13440 temp_buf, sizeof(temp_buf), "%12.2f",
13441 ts.counts[i]
13442 ? (float)ts.counts[i]
13443 / (float)ts.counts
13444 [BGP_STATS_ASPATH_COUNT]
13445 : 0);
893cccd0 13446 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13447 table_stats_strs[i]
13448 [TABLE_STATS_IDX_VTY],
893cccd0 13449 temp_buf);
9ab0cf58
PG
13450 } else {
13451 json_object_double_add(
13452 json,
13453 table_stats_strs[i]
13454 [TABLE_STATS_IDX_JSON],
13455 ts.counts[i]
13456 ? (double)ts.counts[i]
13457 / (double)ts.counts
d62a17ae 13458 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13459 : 0);
13460 }
d62a17ae 13461 break;
13462 case BGP_STATS_TOTPLEN:
6c9d22e2 13463 if (!json) {
9ab0cf58
PG
13464 snprintf(
13465 temp_buf, sizeof(temp_buf), "%12.2f",
13466 ts.counts[i]
13467 ? (float)ts.counts[i]
13468 / (float)ts.counts
13469 [BGP_STATS_PREFIXES]
13470 : 0);
893cccd0 13471 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13472 table_stats_strs[i]
13473 [TABLE_STATS_IDX_VTY],
893cccd0 13474 temp_buf);
9ab0cf58
PG
13475 } else {
13476 json_object_double_add(
13477 json,
13478 table_stats_strs[i]
13479 [TABLE_STATS_IDX_JSON],
13480 ts.counts[i]
13481 ? (double)ts.counts[i]
13482 / (double)ts.counts
d62a17ae 13483 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13484 : 0);
13485 }
d62a17ae 13486 break;
13487 case BGP_STATS_SPACE:
6c9d22e2
PG
13488 if (!json) {
13489 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13490 ts.total_space);
893cccd0 13491 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13492 table_stats_strs[i]
13493 [TABLE_STATS_IDX_VTY],
893cccd0 13494 temp_buf);
9ab0cf58
PG
13495 } else {
13496 json_object_double_add(
13497 json,
13498 table_stats_strs[i]
13499 [TABLE_STATS_IDX_JSON],
13500 (double)ts.total_space);
13501 }
8d0ab76d 13502 if (afi == AFI_IP6) {
6c9d22e2
PG
13503 if (!json) {
13504 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13505 "%12g",
13506 ts.total_space
13507 * pow(2.0, -128 + 32));
6c9d22e2
PG
13508 vty_out(vty, "%30s: %s\n",
13509 "/32 equivalent %s\n",
13510 temp_buf);
9ab0cf58
PG
13511 } else {
13512 json_object_double_add(
13513 json, "/32equivalent",
13514 (double)(ts.total_space
13515 * pow(2.0,
13516 -128 + 32)));
13517 }
6c9d22e2
PG
13518 if (!json) {
13519 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13520 "%12g",
13521 ts.total_space
13522 * pow(2.0, -128 + 48));
6c9d22e2
PG
13523 vty_out(vty, "%30s: %s\n",
13524 "/48 equivalent %s\n",
13525 temp_buf);
9ab0cf58
PG
13526 } else {
13527 json_object_double_add(
13528 json, "/48equivalent",
13529 (double)(ts.total_space
13530 * pow(2.0,
13531 -128 + 48)));
13532 }
8d0ab76d 13533 } else {
6c9d22e2
PG
13534 if (!json) {
13535 snprintf(temp_buf, sizeof(temp_buf),
13536 "%12.2f",
9ab0cf58
PG
13537 ts.total_space * 100.
13538 * pow(2.0, -32));
6c9d22e2 13539 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13540 "% announced ", temp_buf);
13541 } else {
13542 json_object_double_add(
13543 json, "%announced",
13544 (double)(ts.total_space * 100.
13545 * pow(2.0, -32)));
13546 }
6c9d22e2
PG
13547 if (!json) {
13548 snprintf(temp_buf, sizeof(temp_buf),
13549 "%12.2f",
9ab0cf58
PG
13550 ts.total_space
13551 * pow(2.0, -32 + 8));
6c9d22e2
PG
13552 vty_out(vty, "%30s: %s\n",
13553 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13554 } else {
13555 json_object_double_add(
13556 json, "/8equivalent",
13557 (double)(ts.total_space
13558 * pow(2.0, -32 + 8)));
13559 }
6c9d22e2
PG
13560 if (!json) {
13561 snprintf(temp_buf, sizeof(temp_buf),
13562 "%12.2f",
9ab0cf58
PG
13563 ts.total_space
13564 * pow(2.0, -32 + 24));
6c9d22e2 13565 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13566 "/24 equivalent ", temp_buf);
13567 } else {
13568 json_object_double_add(
13569 json, "/24equivalent",
13570 (double)(ts.total_space
13571 * pow(2.0, -32 + 24)));
13572 }
8d0ab76d 13573 }
d62a17ae 13574 break;
13575 default:
6c9d22e2
PG
13576 if (!json) {
13577 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13578 ts.counts[i]);
893cccd0 13579 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13580 table_stats_strs[i]
13581 [TABLE_STATS_IDX_VTY],
13582 temp_buf);
13583 } else {
13584 json_object_int_add(
13585 json,
13586 table_stats_strs[i]
13587 [TABLE_STATS_IDX_JSON],
13588 ts.counts[i]);
13589 }
d62a17ae 13590 }
893cccd0
PG
13591 if (!json)
13592 vty_out(vty, "\n");
d62a17ae 13593 }
0747643e
AQ
13594
13595 switch (afi) {
13596 case AFI_IP:
13597 bitlen = IPV4_MAX_BITLEN;
13598 break;
13599 case AFI_IP6:
13600 bitlen = IPV6_MAX_BITLEN;
13601 break;
13602 case AFI_L2VPN:
13603 bitlen = EVPN_ROUTE_PREFIXLEN;
13604 break;
13605 default:
13606 break;
13607 }
13608
13609 if (json) {
13610 json_bitlen = json_object_new_array();
13611
13612 for (i = 0; i <= bitlen; i++) {
13613 struct json_object *ind_bit = json_object_new_object();
13614
13615 if (!ts.prefix_len_count[i])
13616 continue;
13617
13618 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13619 json_object_int_add(ind_bit, temp_buf,
13620 ts.prefix_len_count[i]);
13621 json_object_array_add(json_bitlen, ind_bit);
13622 }
13623 json_object_object_add(json, "prefixLength", json_bitlen);
13624 }
13625
9ab0cf58 13626end_table_stats:
6c9d22e2
PG
13627 if (json)
13628 json_object_array_add(json_array, json);
893cccd0 13629 return ret;
d62a17ae 13630}
13631
71f1613a
DA
13632static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13633 safi_t safi, struct json_object *json_array)
13634{
13635 if (!bgp) {
13636 bgp_table_stats_all(vty, afi, safi, json_array);
13637 return CMD_SUCCESS;
13638 }
13639
13640 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13641}
13642
d62a17ae 13643enum bgp_pcounts {
13644 PCOUNT_ADJ_IN = 0,
13645 PCOUNT_DAMPED,
13646 PCOUNT_REMOVED,
13647 PCOUNT_HISTORY,
13648 PCOUNT_STALE,
13649 PCOUNT_VALID,
13650 PCOUNT_ALL,
13651 PCOUNT_COUNTED,
7e3d9632 13652 PCOUNT_BPATH_SELECTED,
d62a17ae 13653 PCOUNT_PFCNT, /* the figure we display to users */
13654 PCOUNT_MAX,
a636c635 13655};
718e3744 13656
2b64873d 13657static const char *const pcount_strs[] = {
9d303b37
DL
13658 [PCOUNT_ADJ_IN] = "Adj-in",
13659 [PCOUNT_DAMPED] = "Damped",
13660 [PCOUNT_REMOVED] = "Removed",
13661 [PCOUNT_HISTORY] = "History",
13662 [PCOUNT_STALE] = "Stale",
13663 [PCOUNT_VALID] = "Valid",
13664 [PCOUNT_ALL] = "All RIB",
13665 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13666 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13667 [PCOUNT_PFCNT] = "Useable",
13668 [PCOUNT_MAX] = NULL,
a636c635 13669};
718e3744 13670
d62a17ae 13671struct peer_pcounts {
13672 unsigned int count[PCOUNT_MAX];
13673 const struct peer *peer;
13674 const struct bgp_table *table;
54317cba 13675 safi_t safi;
a636c635 13676};
47fc97cc 13677
9bcb3eef 13678static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13679{
54317cba
JW
13680 const struct bgp_adj_in *ain;
13681 const struct bgp_path_info *pi;
d62a17ae 13682 const struct peer *peer = pc->peer;
13683
54317cba
JW
13684 for (ain = rn->adj_in; ain; ain = ain->next)
13685 if (ain->peer == peer)
13686 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13687
9bcb3eef 13688 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13689
54317cba
JW
13690 if (pi->peer != peer)
13691 continue;
d62a17ae 13692
54317cba 13693 pc->count[PCOUNT_ALL]++;
d62a17ae 13694
54317cba
JW
13695 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13696 pc->count[PCOUNT_DAMPED]++;
13697 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13698 pc->count[PCOUNT_HISTORY]++;
13699 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13700 pc->count[PCOUNT_REMOVED]++;
13701 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13702 pc->count[PCOUNT_STALE]++;
13703 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13704 pc->count[PCOUNT_VALID]++;
13705 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13706 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13707 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13708 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13709
13710 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13711 pc->count[PCOUNT_COUNTED]++;
13712 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13713 flog_err(
13714 EC_LIB_DEVELOPMENT,
13715 "Attempting to count but flags say it is unusable");
13716 } else {
40381db7 13717 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13718 flog_err(
13719 EC_LIB_DEVELOPMENT,
13720 "Not counted but flags say we should");
d62a17ae 13721 }
13722 }
54317cba
JW
13723}
13724
cc9f21da 13725static void bgp_peer_count_walker(struct thread *t)
54317cba 13726{
9bcb3eef 13727 struct bgp_dest *rn, *rm;
54317cba
JW
13728 const struct bgp_table *table;
13729 struct peer_pcounts *pc = THREAD_ARG(t);
13730
13731 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13732 || pc->safi == SAFI_EVPN) {
13733 /* Special handling for 2-level routing tables. */
13734 for (rn = bgp_table_top(pc->table); rn;
13735 rn = bgp_route_next(rn)) {
9bcb3eef 13736 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13737 if (table != NULL)
13738 for (rm = bgp_table_top(table); rm;
13739 rm = bgp_route_next(rm))
13740 bgp_peer_count_proc(rm, pc);
13741 }
13742 } else
13743 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13744 bgp_peer_count_proc(rn, pc);
718e3744 13745}
13746
d62a17ae 13747static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13748 safi_t safi, bool use_json)
856ca177 13749{
d62a17ae 13750 struct peer_pcounts pcounts = {.peer = peer};
13751 unsigned int i;
13752 json_object *json = NULL;
13753 json_object *json_loop = NULL;
856ca177 13754
d62a17ae 13755 if (use_json) {
13756 json = json_object_new_object();
13757 json_loop = json_object_new_object();
13758 }
718e3744 13759
d62a17ae 13760 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13761 || !peer->bgp->rib[afi][safi]) {
13762 if (use_json) {
13763 json_object_string_add(
13764 json, "warning",
13765 "No such neighbor or address family");
13766 vty_out(vty, "%s\n", json_object_to_json_string(json));
13767 json_object_free(json);
d5f20468 13768 json_object_free(json_loop);
d62a17ae 13769 } else
13770 vty_out(vty, "%% No such neighbor or address family\n");
13771
13772 return CMD_WARNING;
13773 }
2a71e9ce 13774
d62a17ae 13775 memset(&pcounts, 0, sizeof(pcounts));
13776 pcounts.peer = peer;
13777 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13778 pcounts.safi = safi;
d62a17ae 13779
13780 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13781 * stats for the thread-walk (i.e. ensure this can't be blamed on
13782 * on just vty_read()).
13783 */
d62a17ae 13784 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13785
13786 if (use_json) {
13787 json_object_string_add(json, "prefixCountsFor", peer->host);
13788 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13789 get_afi_safi_str(afi, safi, true));
d62a17ae 13790 json_object_int_add(json, "pfxCounter",
13791 peer->pcount[afi][safi]);
13792
13793 for (i = 0; i < PCOUNT_MAX; i++)
13794 json_object_int_add(json_loop, pcount_strs[i],
13795 pcounts.count[i]);
13796
13797 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13798
13799 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13800 json_object_string_add(json, "pfxctDriftFor",
13801 peer->host);
13802 json_object_string_add(
13803 json, "recommended",
13804 "Please report this bug, with the above command output");
13805 }
75eeda93 13806 vty_json(vty, json);
d62a17ae 13807 } else {
13808
13809 if (peer->hostname
892fedb6 13810 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13811 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13812 peer->hostname, peer->host,
5cb5f4d0 13813 get_afi_safi_str(afi, safi, false));
d62a17ae 13814 } else {
13815 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13816 get_afi_safi_str(afi, safi, false));
d62a17ae 13817 }
13818
6cde4b45 13819 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13820 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13821
13822 for (i = 0; i < PCOUNT_MAX; i++)
13823 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13824 pcounts.count[i]);
13825
13826 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13827 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13828 vty_out(vty,
13829 "Please report this bug, with the above command output\n");
13830 }
13831 }
13832
13833 return CMD_SUCCESS;
718e3744 13834}
13835
a636c635
DW
13836DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13837 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13838 "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 13839 SHOW_STR
13840 IP_STR
13841 BGP_STR
8386ac43 13842 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13843 BGP_AFI_HELP_STR
13844 BGP_SAFI_HELP_STR
0b16f239
DS
13845 "Detailed information on TCP and BGP neighbor connections\n"
13846 "Neighbor to display information about\n"
13847 "Neighbor to display information about\n"
91d37724 13848 "Neighbor on BGP configured interface\n"
a636c635 13849 "Display detailed prefix count information\n"
9973d184 13850 JSON_STR)
0b16f239 13851{
d62a17ae 13852 afi_t afi = AFI_IP6;
13853 safi_t safi = SAFI_UNICAST;
13854 struct peer *peer;
13855 int idx = 0;
13856 struct bgp *bgp = NULL;
9f049418
DS
13857 bool uj = use_json(argc, argv);
13858
13859 if (uj)
13860 argc--;
856ca177 13861
d62a17ae 13862 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13863 &bgp, uj);
d62a17ae 13864 if (!idx)
13865 return CMD_WARNING;
0b16f239 13866
d62a17ae 13867 argv_find(argv, argc, "neighbors", &idx);
13868 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13869 if (!peer)
13870 return CMD_WARNING;
bb46e94f 13871
29c8d9da 13872 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13873}
0b16f239 13874
d6902373
PG
13875#ifdef KEEP_OLD_VPN_COMMANDS
13876DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13877 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13878 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13879 SHOW_STR
13880 IP_STR
13881 BGP_STR
d6902373 13882 BGP_VPNVX_HELP_STR
91d37724 13883 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13884 "Detailed information on TCP and BGP neighbor connections\n"
13885 "Neighbor to display information about\n"
13886 "Neighbor to display information about\n"
91d37724 13887 "Neighbor on BGP configured interface\n"
a636c635 13888 "Display detailed prefix count information\n"
9973d184 13889 JSON_STR)
a636c635 13890{
d62a17ae 13891 int idx_peer = 6;
13892 struct peer *peer;
9f049418 13893 bool uj = use_json(argc, argv);
a636c635 13894
d62a17ae 13895 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13896 if (!peer)
13897 return CMD_WARNING;
13898
13899 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13900}
13901
d6902373
PG
13902DEFUN (show_ip_bgp_vpn_all_route_prefix,
13903 show_ip_bgp_vpn_all_route_prefix_cmd,
13904 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13905 SHOW_STR
13906 IP_STR
13907 BGP_STR
d6902373 13908 BGP_VPNVX_HELP_STR
91d37724
QY
13909 "Display information about all VPNv4 NLRIs\n"
13910 "Network in the BGP routing table to display\n"
3a2d747c 13911 "Network in the BGP routing table to display\n"
9973d184 13912 JSON_STR)
91d37724 13913{
d62a17ae 13914 int idx = 0;
13915 char *network = NULL;
13916 struct bgp *bgp = bgp_get_default();
13917 if (!bgp) {
13918 vty_out(vty, "Can't find default instance\n");
13919 return CMD_WARNING;
13920 }
87e34b58 13921
d62a17ae 13922 if (argv_find(argv, argc, "A.B.C.D", &idx))
13923 network = argv[idx]->arg;
13924 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13925 network = argv[idx]->arg;
13926 else {
13927 vty_out(vty, "Unable to figure out Network\n");
13928 return CMD_WARNING;
13929 }
87e34b58 13930
d62a17ae 13931 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13932 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13933 use_json(argc, argv));
91d37724 13934}
d6902373 13935#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13936
44c69747
LK
13937DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13938 show_bgp_l2vpn_evpn_route_prefix_cmd,
13939 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13940 SHOW_STR
4c63a661
PG
13941 BGP_STR
13942 L2VPN_HELP_STR
13943 EVPN_HELP_STR
44c69747
LK
13944 "Network in the BGP routing table to display\n"
13945 "Network in the BGP routing table to display\n"
4c63a661
PG
13946 "Network in the BGP routing table to display\n"
13947 "Network in the BGP routing table to display\n"
13948 JSON_STR)
13949{
d62a17ae 13950 int idx = 0;
13951 char *network = NULL;
44c69747 13952 int prefix_check = 0;
a636c635 13953
44c69747
LK
13954 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13955 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13956 network = argv[idx]->arg;
44c69747 13957 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13958 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13959 network = argv[idx]->arg;
44c69747
LK
13960 prefix_check = 1;
13961 } else {
d62a17ae 13962 vty_out(vty, "Unable to figure out Network\n");
13963 return CMD_WARNING;
13964 }
44c69747
LK
13965 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13966 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13967 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13968}
13969
114fc229 13970static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13971 struct bgp_table *table, int *header1,
13972 int *header2, json_object *json,
13973 json_object *json_scode,
13974 json_object *json_ocode, bool wide)
13975{
13976 uint64_t version = table ? table->version : 0;
13977
13978 if (*header1) {
13979 if (json) {
13980 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13981 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13982 "%pI4", &peer->bgp->router_id);
2f9bc755 13983 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13984 peer->bgp->default_local_pref);
13985 json_object_int_add(json, "localAS",
13986 peer->change_local_as
13987 ? peer->change_local_as
13988 : peer->local_as);
2f9bc755
DS
13989 json_object_object_add(json, "bgpStatusCodes",
13990 json_scode);
13991 json_object_object_add(json, "bgpOriginCodes",
13992 json_ocode);
13993 } else {
13994 vty_out(vty,
23d0a753
DA
13995 "BGP table version is %" PRIu64
13996 ", local router ID is %pI4, vrf id ",
114fc229
DA
13997 version, &peer->bgp->router_id);
13998 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13999 vty_out(vty, "%s", VRFID_NONE_STR);
14000 else
114fc229 14001 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
14002 vty_out(vty, "\n");
14003 vty_out(vty, "Default local pref %u, ",
114fc229
DA
14004 peer->bgp->default_local_pref);
14005 vty_out(vty, "local AS %u\n",
14006 peer->change_local_as ? peer->change_local_as
14007 : peer->local_as);
2f9bc755
DS
14008 vty_out(vty, BGP_SHOW_SCODE_HEADER);
14009 vty_out(vty, BGP_SHOW_NCODE_HEADER);
14010 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14011 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
14012 }
14013 *header1 = 0;
14014 }
14015 if (*header2) {
14016 if (!json)
14017 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14018 : BGP_SHOW_HEADER));
14019 *header2 = 0;
14020 }
14021}
14022
d9478df0
TA
14023static void
14024show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14025 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14026 const char *rmap_name, json_object *json, json_object *json_ar,
14027 json_object *json_scode, json_object *json_ocode,
96c81f66 14028 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 14029 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 14030{
d62a17ae 14031 struct bgp_adj_in *ain;
14032 struct bgp_adj_out *adj;
9bcb3eef 14033 struct bgp_dest *dest;
d62a17ae 14034 struct bgp *bgp;
d62a17ae 14035 struct attr attr;
14036 int ret;
14037 struct update_subgroup *subgrp;
d62a17ae 14038 struct peer_af *paf;
f99def61 14039 bool route_filtered;
96f3485c
MK
14040 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14041 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14042 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14043 || (safi == SAFI_EVPN))
14044 ? true
14045 : false;
a636c635 14046
d62a17ae 14047 bgp = peer->bgp;
a636c635 14048
d62a17ae 14049 subgrp = peer_subgroup(peer, afi, safi);
14050
6392aaa6 14051 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14052 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14053 if (use_json) {
14054 json_object_int_add(json, "bgpTableVersion",
14055 table->version);
c949c771
DA
14056 json_object_string_addf(json, "bgpLocalRouterId",
14057 "%pI4", &bgp->router_id);
01eced22
AD
14058 json_object_int_add(json, "defaultLocPrf",
14059 bgp->default_local_pref);
114fc229
DA
14060 json_object_int_add(json, "localAS",
14061 peer->change_local_as
14062 ? peer->change_local_as
14063 : peer->local_as);
d62a17ae 14064 json_object_object_add(json, "bgpStatusCodes",
14065 json_scode);
14066 json_object_object_add(json, "bgpOriginCodes",
14067 json_ocode);
07d0c4ed
DA
14068 json_object_string_add(
14069 json, "bgpOriginatingDefaultNetwork",
14070 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14071 } else {
23d0a753
DA
14072 vty_out(vty,
14073 "BGP table version is %" PRIu64
14074 ", local router ID is %pI4, vrf id ",
14075 table->version, &bgp->router_id);
9df8b37c
PZ
14076 if (bgp->vrf_id == VRF_UNKNOWN)
14077 vty_out(vty, "%s", VRFID_NONE_STR);
14078 else
14079 vty_out(vty, "%u", bgp->vrf_id);
14080 vty_out(vty, "\n");
01eced22
AD
14081 vty_out(vty, "Default local pref %u, ",
14082 bgp->default_local_pref);
114fc229
DA
14083 vty_out(vty, "local AS %u\n",
14084 peer->change_local_as ? peer->change_local_as
14085 : peer->local_as);
d62a17ae 14086 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 14087 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 14088 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14089 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 14090
07d0c4ed
DA
14091 vty_out(vty, "Originating default network %s\n\n",
14092 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14093 }
65565c9a 14094 (*output_count)++;
d9478df0 14095 *header1 = 0;
d62a17ae 14096 }
a636c635 14097
9bcb3eef 14098 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14099 if (type == bgp_show_adj_route_received
14100 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14101 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14102 if (ain->peer != peer)
ea47320b 14103 continue;
6392aaa6 14104
114fc229 14105 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
14106 header2, json, json_scode,
14107 json_ocode, wide);
14108
14109 if ((safi == SAFI_MPLS_VPN)
14110 || (safi == SAFI_ENCAP)
14111 || (safi == SAFI_EVPN)) {
14112 if (use_json)
14113 json_object_string_add(
14114 json_ar, "rd", rd_str);
14115 else if (show_rd && rd_str) {
14116 vty_out(vty,
14117 "Route Distinguisher: %s\n",
14118 rd_str);
14119 show_rd = false;
14120 }
14121 }
6392aaa6 14122
6f4f49b2 14123 attr = *ain->attr;
f99def61
AD
14124 route_filtered = false;
14125
14126 /* Filter prefix using distribute list,
14127 * filter list or prefix list
14128 */
b54892e0 14129 const struct prefix *rn_p =
9bcb3eef 14130 bgp_dest_get_prefix(dest);
b54892e0
DS
14131 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14132 safi))
14133 == FILTER_DENY)
f99def61
AD
14134 route_filtered = true;
14135
14136 /* Filter prefix using route-map */
b54892e0
DS
14137 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14138 safi, rmap_name, NULL,
14139 0, NULL);
6392aaa6 14140
13c8e163
AD
14141 if (type == bgp_show_adj_route_filtered &&
14142 !route_filtered && ret != RMAP_DENY) {
d498917e 14143 bgp_attr_flush(&attr);
6392aaa6 14144 continue;
d62a17ae 14145 }
6392aaa6 14146
d9478df0
TA
14147 if (type == bgp_show_adj_route_received
14148 && (route_filtered || ret == RMAP_DENY))
14149 (*filtered_count)++;
6392aaa6 14150
7d3cae70 14151 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 14152 use_json, json_ar, wide);
d498917e 14153 bgp_attr_flush(&attr);
d9478df0 14154 (*output_count)++;
d62a17ae 14155 }
6392aaa6 14156 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14157 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14158 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14159 if (paf->peer != peer || !adj->attr)
924c3f6a 14160 continue;
d62a17ae 14161
114fc229 14162 show_adj_route_header(vty, peer, table,
d9478df0
TA
14163 header1, header2,
14164 json, json_scode,
14165 json_ocode, wide);
d62a17ae 14166
b54892e0 14167 const struct prefix *rn_p =
9bcb3eef 14168 bgp_dest_get_prefix(dest);
b54892e0 14169
6f4f49b2 14170 attr = *adj->attr;
b755861b 14171 ret = bgp_output_modifier(
b54892e0 14172 peer, rn_p, &attr, afi, safi,
b755861b 14173 rmap_name);
f46d8e1e 14174
b755861b 14175 if (ret != RMAP_DENY) {
d9478df0
TA
14176 if ((safi == SAFI_MPLS_VPN)
14177 || (safi == SAFI_ENCAP)
14178 || (safi == SAFI_EVPN)) {
14179 if (use_json)
14180 json_object_string_add(
14181 json_ar,
14182 "rd",
14183 rd_str);
14184 else if (show_rd
14185 && rd_str) {
14186 vty_out(vty,
14187 "Route Distinguisher: %s\n",
14188 rd_str);
14189 show_rd = false;
14190 }
14191 }
b54892e0 14192 route_vty_out_tmp(
7d3cae70
DA
14193 vty, dest, rn_p, &attr,
14194 safi, use_json, json_ar,
ae248832 14195 wide);
d9478df0 14196 (*output_count)++;
b755861b 14197 } else {
d9478df0 14198 (*filtered_count)++;
a2addae8 14199 }
b755861b 14200
d498917e 14201 bgp_attr_flush(&attr);
924c3f6a 14202 }
f20ce998
DS
14203 } else if (type == bgp_show_adj_route_bestpath) {
14204 struct bgp_path_info *pi;
14205
114fc229
DA
14206 show_adj_route_header(vty, peer, table, header1,
14207 header2, json, json_scode,
14208 json_ocode, wide);
f20ce998
DS
14209
14210 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14211 pi = pi->next) {
14212 if (pi->peer != peer)
14213 continue;
14214
14215 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14216 continue;
14217
7d3cae70 14218 route_vty_out_tmp(vty, dest,
f20ce998
DS
14219 bgp_dest_get_prefix(dest),
14220 pi->attr, safi, use_json,
14221 json_ar, wide);
d9478df0 14222 (*output_count)++;
f20ce998 14223 }
d62a17ae 14224 }
14225 }
a636c635 14226}
2a71e9ce 14227
d62a17ae 14228static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14229 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14230 const char *rmap_name, uint16_t show_flags)
0b16f239 14231{
d9478df0
TA
14232 struct bgp *bgp;
14233 struct bgp_table *table;
d62a17ae 14234 json_object *json = NULL;
d9478df0
TA
14235 json_object *json_scode = NULL;
14236 json_object *json_ocode = NULL;
14237 json_object *json_ar = NULL;
96f3485c 14238 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14239
d9478df0
TA
14240 /* Init BGP headers here so they're only displayed once
14241 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14242 */
14243 int header1 = 1;
14244 int header2 = 1;
14245
14246 /*
14247 * Initialize variables for each RD
14248 * All prefixes under an RD is aggregated within "json_routes"
14249 */
14250 char rd_str[BUFSIZ] = {0};
14251 json_object *json_routes = NULL;
14252
14253
14254 /* For 2-tier tables, prefix counts need to be
14255 * maintained across multiple runs of show_adj_route()
14256 */
14257 unsigned long output_count_per_rd;
14258 unsigned long filtered_count_per_rd;
14259 unsigned long output_count = 0;
14260 unsigned long filtered_count = 0;
14261
14262 if (use_json) {
d62a17ae 14263 json = json_object_new_object();
d9478df0
TA
14264 json_ar = json_object_new_object();
14265 json_scode = json_object_new_object();
14266 json_ocode = json_object_new_object();
dd426a51
DA
14267#if CONFDATE > 20231208
14268CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14269#endif
d9478df0
TA
14270 json_object_string_add(json_scode, "suppressed", "s");
14271 json_object_string_add(json_scode, "damped", "d");
14272 json_object_string_add(json_scode, "history", "h");
14273 json_object_string_add(json_scode, "valid", "*");
14274 json_object_string_add(json_scode, "best", ">");
14275 json_object_string_add(json_scode, "multipath", "=");
14276 json_object_string_add(json_scode, "internal", "i");
14277 json_object_string_add(json_scode, "ribFailure", "r");
14278 json_object_string_add(json_scode, "stale", "S");
14279 json_object_string_add(json_scode, "removed", "R");
14280
dd426a51
DA
14281#if CONFDATE > 20231208
14282CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14283#endif
d9478df0
TA
14284 json_object_string_add(json_ocode, "igp", "i");
14285 json_object_string_add(json_ocode, "egp", "e");
14286 json_object_string_add(json_ocode, "incomplete", "?");
14287 }
0b16f239 14288
d62a17ae 14289 if (!peer || !peer->afc[afi][safi]) {
14290 if (use_json) {
14291 json_object_string_add(
14292 json, "warning",
14293 "No such neighbor or address family");
14294 vty_out(vty, "%s\n", json_object_to_json_string(json));
14295 json_object_free(json);
690c3134
MW
14296 json_object_free(json_ar);
14297 json_object_free(json_scode);
14298 json_object_free(json_ocode);
d62a17ae 14299 } else
14300 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14301
d62a17ae 14302 return CMD_WARNING;
14303 }
14304
6392aaa6
PM
14305 if ((type == bgp_show_adj_route_received
14306 || type == bgp_show_adj_route_filtered)
d62a17ae 14307 && !CHECK_FLAG(peer->af_flags[afi][safi],
14308 PEER_FLAG_SOFT_RECONFIG)) {
14309 if (use_json) {
14310 json_object_string_add(
14311 json, "warning",
14312 "Inbound soft reconfiguration not enabled");
14313 vty_out(vty, "%s\n", json_object_to_json_string(json));
14314 json_object_free(json);
690c3134
MW
14315 json_object_free(json_ar);
14316 json_object_free(json_scode);
14317 json_object_free(json_ocode);
d62a17ae 14318 } else
14319 vty_out(vty,
14320 "%% Inbound soft reconfiguration not enabled\n");
14321
14322 return CMD_WARNING;
14323 }
0b16f239 14324
d9478df0
TA
14325 bgp = peer->bgp;
14326
14327 /* labeled-unicast routes live in the unicast table */
14328 if (safi == SAFI_LABELED_UNICAST)
14329 table = bgp->rib[afi][SAFI_UNICAST];
14330 else
14331 table = bgp->rib[afi][safi];
14332
14333 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14334 || (safi == SAFI_EVPN)) {
14335
14336 struct bgp_dest *dest;
14337
14338 for (dest = bgp_table_top(table); dest;
14339 dest = bgp_route_next(dest)) {
14340 table = bgp_dest_get_bgp_table_info(dest);
14341 if (!table)
14342 continue;
14343
14344 output_count_per_rd = 0;
14345 filtered_count_per_rd = 0;
14346
14347 if (use_json)
14348 json_routes = json_object_new_object();
14349
14350 const struct prefix_rd *prd;
14351 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14352 dest);
14353
14354 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14355
14356 show_adj_route(vty, peer, table, afi, safi, type,
14357 rmap_name, json, json_routes, json_scode,
14358 json_ocode, show_flags, &header1,
14359 &header2, rd_str, &output_count_per_rd,
14360 &filtered_count_per_rd);
14361
14362 /* Don't include an empty RD in the output! */
14363 if (json_routes && (output_count_per_rd > 0))
14364 json_object_object_add(json_ar, rd_str,
14365 json_routes);
14366
14367 output_count += output_count_per_rd;
14368 filtered_count += filtered_count_per_rd;
14369 }
14370 } else
14371 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14372 json, json_ar, json_scode, json_ocode,
14373 show_flags, &header1, &header2, rd_str,
14374 &output_count, &filtered_count);
14375
14376 if (use_json) {
c1984955
TA
14377 if (type == bgp_show_adj_route_advertised)
14378 json_object_object_add(json, "advertisedRoutes",
14379 json_ar);
14380 else
14381 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14382 json_object_int_add(json, "totalPrefixCounter", output_count);
14383 json_object_int_add(json, "filteredPrefixCounter",
14384 filtered_count);
14385
690c3134
MW
14386 /*
14387 * These fields only give up ownership to `json` when `header1`
14388 * is used (set to zero). See code in `show_adj_route` and
14389 * `show_adj_route_header`.
14390 */
14391 if (header1 == 1) {
d9478df0
TA
14392 json_object_free(json_scode);
14393 json_object_free(json_ocode);
14394 }
14395
75eeda93 14396 vty_json(vty, json);
d9478df0
TA
14397 } else if (output_count > 0) {
14398 if (filtered_count > 0)
14399 vty_out(vty,
14400 "\nTotal number of prefixes %ld (%ld filtered)\n",
14401 output_count, filtered_count);
14402 else
14403 vty_out(vty, "\nTotal number of prefixes %ld\n",
14404 output_count);
14405 }
0b16f239 14406
d62a17ae 14407 return CMD_SUCCESS;
a636c635 14408}
50ef26d4 14409
f20ce998
DS
14410DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14411 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14412 "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]",
14413 SHOW_STR
14414 IP_STR
14415 BGP_STR
14416 BGP_INSTANCE_HELP_STR
14417 BGP_AFI_HELP_STR
14418 BGP_SAFI_WITH_LABEL_HELP_STR
14419 "Detailed information on TCP and BGP neighbor connections\n"
14420 "Neighbor to display information about\n"
14421 "Neighbor to display information about\n"
14422 "Neighbor on BGP configured interface\n"
14423 "Display the routes selected by best path\n"
14424 JSON_STR
14425 "Increase table width for longer prefixes\n")
14426{
14427 afi_t afi = AFI_IP6;
14428 safi_t safi = SAFI_UNICAST;
14429 char *rmap_name = NULL;
14430 char *peerstr = NULL;
14431 struct bgp *bgp = NULL;
14432 struct peer *peer;
14433 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14434 int idx = 0;
96c81f66 14435 uint16_t show_flags = 0;
96f3485c
MK
14436
14437 if (uj)
14438 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14439
14440 if (wide)
14441 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14442
14443 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14444 &bgp, uj);
14445
14446 if (!idx)
14447 return CMD_WARNING;
14448
14449 argv_find(argv, argc, "neighbors", &idx);
14450 peerstr = argv[++idx]->arg;
14451
14452 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14453 if (!peer)
14454 return CMD_WARNING;
14455
96f3485c
MK
14456 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14457 show_flags);
f20ce998
DS
14458}
14459
ae248832 14460DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14461 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14462 "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 14463 SHOW_STR
14464 IP_STR
14465 BGP_STR
a636c635 14466 BGP_INSTANCE_HELP_STR
7395a2c9 14467 BGP_AFI_HELP_STR
4dd6177e 14468 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14469 "Display the entries for all address families\n"
718e3744 14470 "Detailed information on TCP and BGP neighbor connections\n"
14471 "Neighbor to display information about\n"
14472 "Neighbor to display information about\n"
91d37724 14473 "Neighbor on BGP configured interface\n"
a636c635 14474 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14475 "Display the received routes from neighbor\n"
14476 "Display the filtered routes received from neighbor\n"
a636c635
DW
14477 "Route-map to modify the attributes\n"
14478 "Name of the route map\n"
ae248832
MK
14479 JSON_STR
14480 "Increase table width for longer prefixes\n")
718e3744 14481{
d62a17ae 14482 afi_t afi = AFI_IP6;
14483 safi_t safi = SAFI_UNICAST;
d62a17ae 14484 char *peerstr = NULL;
d62a17ae 14485 struct bgp *bgp = NULL;
14486 struct peer *peer;
6392aaa6 14487 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14488 int idx = 0;
96f3485c 14489 bool first = true;
96c81f66 14490 uint16_t show_flags = 0;
75ce3b14
DA
14491 struct listnode *node;
14492 struct bgp *abgp;
6392aaa6 14493
96f3485c 14494 if (uj) {
d62a17ae 14495 argc--;
96f3485c
MK
14496 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14497 }
14498
14499 if (all) {
14500 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14501 if (argv_find(argv, argc, "ipv4", &idx))
14502 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14503
14504 if (argv_find(argv, argc, "ipv6", &idx))
14505 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14506 }
14507
14508 if (wide)
14509 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14510
9f049418
DS
14511 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14512 &bgp, uj);
14513 if (!idx)
14514 return CMD_WARNING;
14515
d62a17ae 14516 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14517 argv_find(argv, argc, "neighbors", &idx);
14518 peerstr = argv[++idx]->arg;
8c3deaae 14519
d62a17ae 14520 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14521 if (!peer)
14522 return CMD_WARNING;
856ca177 14523
d62a17ae 14524 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14525 type = bgp_show_adj_route_advertised;
14526 else if (argv_find(argv, argc, "received-routes", &idx))
14527 type = bgp_show_adj_route_received;
14528 else if (argv_find(argv, argc, "filtered-routes", &idx))
14529 type = bgp_show_adj_route_filtered;
14530
96f3485c 14531 if (!all)
70dd370f 14532 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14533 show_flags);
14534 if (uj)
14535 vty_out(vty, "{\n");
14536
14537 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14538 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14539 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14540 : AFI_IP6;
75ce3b14
DA
14541 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14542 FOREACH_SAFI (safi) {
14543 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14544 continue;
96f3485c 14545
75ce3b14
DA
14546 if (uj) {
14547 if (first)
14548 first = false;
14549 else
14550 vty_out(vty, ",\n");
14551 vty_out(vty, "\"%s\":",
14552 get_afi_safi_str(afi, safi,
14553 true));
14554 } else
14555 vty_out(vty,
14556 "\nFor address family: %s\n",
14557 get_afi_safi_str(afi, safi,
14558 false));
96f3485c 14559
75ce3b14 14560 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14561 route_map, show_flags);
75ce3b14 14562 }
96f3485c
MK
14563 }
14564 } else {
75ce3b14
DA
14565 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14566 FOREACH_AFI_SAFI (afi, safi) {
14567 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14568 continue;
96f3485c 14569
75ce3b14
DA
14570 if (uj) {
14571 if (first)
14572 first = false;
14573 else
14574 vty_out(vty, ",\n");
14575 vty_out(vty, "\"%s\":",
14576 get_afi_safi_str(afi, safi,
14577 true));
14578 } else
14579 vty_out(vty,
14580 "\nFor address family: %s\n",
14581 get_afi_safi_str(afi, safi,
14582 false));
96f3485c 14583
75ce3b14 14584 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14585 route_map, show_flags);
75ce3b14 14586 }
96f3485c
MK
14587 }
14588 }
14589 if (uj)
14590 vty_out(vty, "}\n");
14591
14592 return CMD_SUCCESS;
95cbbd2a
ML
14593}
14594
718e3744 14595DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14596 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14597 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14598 SHOW_STR
14599 IP_STR
14600 BGP_STR
d3120452 14601 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14602 BGP_AF_STR
14603 BGP_AF_STR
14604 BGP_AF_MODIFIER_STR
718e3744 14605 "Detailed information on TCP and BGP neighbor connections\n"
14606 "Neighbor to display information about\n"
14607 "Neighbor to display information about\n"
91d37724 14608 "Neighbor on BGP configured interface\n"
718e3744 14609 "Display information received from a BGP neighbor\n"
856ca177 14610 "Display the prefixlist filter\n"
9973d184 14611 JSON_STR)
718e3744 14612{
d62a17ae 14613 afi_t afi = AFI_IP6;
14614 safi_t safi = SAFI_UNICAST;
14615 char *peerstr = NULL;
d62a17ae 14616 char name[BUFSIZ];
d62a17ae 14617 struct peer *peer;
d3120452 14618 int count;
d62a17ae 14619 int idx = 0;
d3120452
IR
14620 struct bgp *bgp = NULL;
14621 bool uj = use_json(argc, argv);
14622
14623 if (uj)
14624 argc--;
14625
14626 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14627 &bgp, uj);
14628 if (!idx)
14629 return CMD_WARNING;
d62a17ae 14630
d62a17ae 14631 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14632 argv_find(argv, argc, "neighbors", &idx);
14633 peerstr = argv[++idx]->arg;
14634
d3120452
IR
14635 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14636 if (!peer)
14637 return CMD_WARNING;
718e3744 14638
4ced1a2c 14639 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14640 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14641 if (count) {
14642 if (!uj)
14643 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14644 get_afi_safi_str(afi, safi, false));
d62a17ae 14645 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14646 } else {
14647 if (uj)
14648 vty_out(vty, "{}\n");
14649 else
14650 vty_out(vty, "No functional output\n");
14651 }
718e3744 14652
d62a17ae 14653 return CMD_SUCCESS;
14654}
14655
14656static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14657 afi_t afi, safi_t safi,
9f049418 14658 enum bgp_show_type type, bool use_json)
d62a17ae 14659{
96c81f66 14660 uint16_t show_flags = 0;
96f3485c
MK
14661
14662 if (use_json)
14663 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14664
d62a17ae 14665 if (!peer || !peer->afc[afi][safi]) {
14666 if (use_json) {
14667 json_object *json_no = NULL;
14668 json_no = json_object_new_object();
14669 json_object_string_add(
14670 json_no, "warning",
14671 "No such neighbor or address family");
14672 vty_out(vty, "%s\n",
14673 json_object_to_json_string(json_no));
14674 json_object_free(json_no);
14675 } else
14676 vty_out(vty, "%% No such neighbor or address family\n");
14677 return CMD_WARNING;
14678 }
47fc97cc 14679
7daf25a3
TA
14680 /* labeled-unicast routes live in the unicast table */
14681 if (safi == SAFI_LABELED_UNICAST)
14682 safi = SAFI_UNICAST;
14683
1e2ce4f1
DS
14684 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14685 RPKI_NOT_BEING_USED);
718e3744 14686}
14687
dba3c1d3
PG
14688DEFUN (show_ip_bgp_flowspec_routes_detailed,
14689 show_ip_bgp_flowspec_routes_detailed_cmd,
14690 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14691 SHOW_STR
14692 IP_STR
14693 BGP_STR
14694 BGP_INSTANCE_HELP_STR
14695 BGP_AFI_HELP_STR
14696 "SAFI Flowspec\n"
14697 "Detailed information on flowspec entries\n"
14698 JSON_STR)
14699{
458c1475 14700 afi_t afi = AFI_IP6;
dba3c1d3
PG
14701 safi_t safi = SAFI_UNICAST;
14702 struct bgp *bgp = NULL;
14703 int idx = 0;
9f049418 14704 bool uj = use_json(argc, argv);
5be6fa9b 14705 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14706
96f3485c 14707 if (uj) {
9f049418 14708 argc--;
96f3485c
MK
14709 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14710 }
dba3c1d3
PG
14711
14712 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14713 &bgp, uj);
dba3c1d3
PG
14714 if (!idx)
14715 return CMD_WARNING;
14716
96f3485c 14717 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14718 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14719}
14720
718e3744 14721DEFUN (show_ip_bgp_neighbor_routes,
14722 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14723 "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 14724 SHOW_STR
14725 IP_STR
14726 BGP_STR
8386ac43 14727 BGP_INSTANCE_HELP_STR
4f280b15 14728 BGP_AFI_HELP_STR
4dd6177e 14729 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14730 "Detailed information on TCP and BGP neighbor connections\n"
14731 "Neighbor to display information about\n"
14732 "Neighbor to display information about\n"
91d37724 14733 "Neighbor on BGP configured interface\n"
2525cf39 14734 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14735 "Display the dampened routes received from neighbor\n"
14736 "Display routes learned from neighbor\n"
9973d184 14737 JSON_STR)
718e3744 14738{
d62a17ae 14739 char *peerstr = NULL;
14740 struct bgp *bgp = NULL;
14741 afi_t afi = AFI_IP6;
14742 safi_t safi = SAFI_UNICAST;
14743 struct peer *peer;
14744 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14745 int idx = 0;
9f049418
DS
14746 bool uj = use_json(argc, argv);
14747
14748 if (uj)
14749 argc--;
bb46e94f 14750
d62a17ae 14751 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14752 &bgp, uj);
d62a17ae 14753 if (!idx)
14754 return CMD_WARNING;
c493f2d8 14755
d62a17ae 14756 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14757 argv_find(argv, argc, "neighbors", &idx);
14758 peerstr = argv[++idx]->arg;
8c3deaae 14759
d62a17ae 14760 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14761 if (!peer)
d62a17ae 14762 return CMD_WARNING;
bb46e94f 14763
d62a17ae 14764 if (argv_find(argv, argc, "flap-statistics", &idx))
14765 sh_type = bgp_show_type_flap_neighbor;
14766 else if (argv_find(argv, argc, "dampened-routes", &idx))
14767 sh_type = bgp_show_type_damp_neighbor;
14768 else if (argv_find(argv, argc, "routes", &idx))
14769 sh_type = bgp_show_type_neighbor;
2525cf39 14770
d62a17ae 14771 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14772}
6b0655a2 14773
734b349e 14774struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14775
d62a17ae 14776struct bgp_distance {
14777 /* Distance value for the IP source prefix. */
d7c0a89a 14778 uint8_t distance;
718e3744 14779
d62a17ae 14780 /* Name of the access-list to be matched. */
14781 char *access_list;
718e3744 14782};
14783
4f280b15
LB
14784DEFUN (show_bgp_afi_vpn_rd_route,
14785 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14786 "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
14787 SHOW_STR
14788 BGP_STR
14789 BGP_AFI_HELP_STR
00e6edb9 14790 BGP_AF_MODIFIER_STR
4f280b15
LB
14791 "Display information for a route distinguisher\n"
14792 "Route Distinguisher\n"
a111dd97 14793 "All Route Distinguishers\n"
7395a2c9
DS
14794 "Network in the BGP routing table to display\n"
14795 "Network in the BGP routing table to display\n"
14796 JSON_STR)
4f280b15 14797{
d62a17ae 14798 int ret;
14799 struct prefix_rd prd;
14800 afi_t afi = AFI_MAX;
14801 int idx = 0;
4f280b15 14802
ff6566f3
DS
14803 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14804 vty_out(vty, "%% Malformed Address Family\n");
14805 return CMD_WARNING;
14806 }
14807
a111dd97
TA
14808 if (!strcmp(argv[5]->arg, "all"))
14809 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14810 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14811 RPKI_NOT_BEING_USED,
14812 use_json(argc, argv));
14813
d62a17ae 14814 ret = str2prefix_rd(argv[5]->arg, &prd);
14815 if (!ret) {
14816 vty_out(vty, "%% Malformed Route Distinguisher\n");
14817 return CMD_WARNING;
14818 }
ff6566f3 14819
d62a17ae 14820 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14821 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14822 use_json(argc, argv));
4f280b15
LB
14823}
14824
d62a17ae 14825static struct bgp_distance *bgp_distance_new(void)
718e3744 14826{
d62a17ae 14827 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14828}
14829
d62a17ae 14830static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14831{
d62a17ae 14832 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14833}
14834
585f1adc
IR
14835static int bgp_distance_set(struct vty *vty, const char *distance_str,
14836 const char *ip_str, const char *access_list_str)
718e3744 14837{
d62a17ae 14838 int ret;
585f1adc
IR
14839 afi_t afi;
14840 safi_t safi;
d62a17ae 14841 struct prefix p;
585f1adc 14842 uint8_t distance;
9bcb3eef 14843 struct bgp_dest *dest;
d62a17ae 14844 struct bgp_distance *bdistance;
718e3744 14845
585f1adc
IR
14846 afi = bgp_node_afi(vty);
14847 safi = bgp_node_safi(vty);
14848
d62a17ae 14849 ret = str2prefix(ip_str, &p);
14850 if (ret == 0) {
585f1adc 14851 vty_out(vty, "Malformed prefix\n");
d62a17ae 14852 return CMD_WARNING_CONFIG_FAILED;
14853 }
718e3744 14854
585f1adc
IR
14855 distance = atoi(distance_str);
14856
d62a17ae 14857 /* Get BGP distance node. */
9bcb3eef
DS
14858 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14859 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14860 if (bdistance)
9bcb3eef 14861 bgp_dest_unlock_node(dest);
ca2e160d 14862 else {
d62a17ae 14863 bdistance = bgp_distance_new();
9bcb3eef 14864 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14865 }
718e3744 14866
d62a17ae 14867 /* Set distance value. */
14868 bdistance->distance = distance;
718e3744 14869
d62a17ae 14870 /* Reset access-list configuration. */
e1b36e13 14871 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14872 if (access_list_str)
14873 bdistance->access_list =
14874 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14875
d62a17ae 14876 return CMD_SUCCESS;
718e3744 14877}
14878
585f1adc
IR
14879static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14880 const char *ip_str, const char *access_list_str)
718e3744 14881{
d62a17ae 14882 int ret;
585f1adc
IR
14883 afi_t afi;
14884 safi_t safi;
d62a17ae 14885 struct prefix p;
585f1adc 14886 int distance;
9bcb3eef 14887 struct bgp_dest *dest;
d62a17ae 14888 struct bgp_distance *bdistance;
718e3744 14889
585f1adc
IR
14890 afi = bgp_node_afi(vty);
14891 safi = bgp_node_safi(vty);
14892
d62a17ae 14893 ret = str2prefix(ip_str, &p);
14894 if (ret == 0) {
585f1adc 14895 vty_out(vty, "Malformed prefix\n");
d62a17ae 14896 return CMD_WARNING_CONFIG_FAILED;
14897 }
718e3744 14898
9bcb3eef
DS
14899 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14900 if (!dest) {
585f1adc 14901 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14902 return CMD_WARNING_CONFIG_FAILED;
14903 }
718e3744 14904
9bcb3eef 14905 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14906 distance = atoi(distance_str);
1f9a9fff 14907
d62a17ae 14908 if (bdistance->distance != distance) {
585f1adc 14909 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14910 bgp_dest_unlock_node(dest);
d62a17ae 14911 return CMD_WARNING_CONFIG_FAILED;
14912 }
718e3744 14913
0a22ddfb 14914 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14915 bgp_distance_free(bdistance);
718e3744 14916
9bcb3eef
DS
14917 bgp_dest_set_bgp_path_info(dest, NULL);
14918 bgp_dest_unlock_node(dest);
14919 bgp_dest_unlock_node(dest);
718e3744 14920
d62a17ae 14921 return CMD_SUCCESS;
718e3744 14922}
14923
718e3744 14924/* Apply BGP information to distance method. */
b8685f9b 14925uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14926 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14927{
9bcb3eef 14928 struct bgp_dest *dest;
801bb996 14929 struct prefix q = {0};
d62a17ae 14930 struct peer *peer;
14931 struct bgp_distance *bdistance;
14932 struct access_list *alist;
14933 struct bgp_static *bgp_static;
14934
14935 if (!bgp)
14936 return 0;
14937
40381db7 14938 peer = pinfo->peer;
d62a17ae 14939
7b7d48e5
DS
14940 if (pinfo->attr->distance)
14941 return pinfo->attr->distance;
14942
801bb996
CS
14943 /* Check source address.
14944 * Note: for aggregate route, peer can have unspec af type.
14945 */
14946 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14947 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14948 return 0;
14949
9bcb3eef
DS
14950 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14951 if (dest) {
14952 bdistance = bgp_dest_get_bgp_distance_info(dest);
14953 bgp_dest_unlock_node(dest);
d62a17ae 14954
14955 if (bdistance->access_list) {
14956 alist = access_list_lookup(afi, bdistance->access_list);
14957 if (alist
14958 && access_list_apply(alist, p) == FILTER_PERMIT)
14959 return bdistance->distance;
14960 } else
14961 return bdistance->distance;
718e3744 14962 }
718e3744 14963
d62a17ae 14964 /* Backdoor check. */
9bcb3eef
DS
14965 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14966 if (dest) {
14967 bgp_static = bgp_dest_get_bgp_static_info(dest);
14968 bgp_dest_unlock_node(dest);
718e3744 14969
d62a17ae 14970 if (bgp_static->backdoor) {
14971 if (bgp->distance_local[afi][safi])
14972 return bgp->distance_local[afi][safi];
14973 else
14974 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14975 }
718e3744 14976 }
718e3744 14977
d62a17ae 14978 if (peer->sort == BGP_PEER_EBGP) {
14979 if (bgp->distance_ebgp[afi][safi])
14980 return bgp->distance_ebgp[afi][safi];
14981 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14982 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14983 if (bgp->distance_ibgp[afi][safi])
14984 return bgp->distance_ibgp[afi][safi];
14985 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14986 } else {
14987 if (bgp->distance_local[afi][safi])
14988 return bgp->distance_local[afi][safi];
14989 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14990 }
718e3744 14991}
14992
a612fb77
DA
14993/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14994 * we should tell ZEBRA update the routes for a specific
14995 * AFI/SAFI to reflect changes in RIB.
14996 */
585f1adc
IR
14997static void bgp_announce_routes_distance_update(struct bgp *bgp,
14998 afi_t update_afi,
14999 safi_t update_safi)
a612fb77
DA
15000{
15001 afi_t afi;
15002 safi_t safi;
15003
15004 FOREACH_AFI_SAFI (afi, safi) {
15005 if (!bgp_fibupd_safi(safi))
15006 continue;
15007
8b54bc30
DA
15008 if (afi != update_afi && safi != update_safi)
15009 continue;
15010
15011 if (BGP_DEBUG(zebra, ZEBRA))
15012 zlog_debug(
15013 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15014 __func__, afi, safi);
15015 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
15016 }
15017}
15018
585f1adc
IR
15019DEFUN (bgp_distance,
15020 bgp_distance_cmd,
15021 "distance bgp (1-255) (1-255) (1-255)",
15022 "Define an administrative distance\n"
15023 "BGP distance\n"
15024 "Distance for routes external to the AS\n"
15025 "Distance for routes internal to the AS\n"
15026 "Distance for local routes\n")
718e3744 15027{
585f1adc 15028 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15029 int idx_number = 2;
15030 int idx_number_2 = 3;
15031 int idx_number_3 = 4;
585f1adc
IR
15032 int distance_ebgp = atoi(argv[idx_number]->arg);
15033 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15034 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15035 afi_t afi;
15036 safi_t safi;
718e3744 15037
d62a17ae 15038 afi = bgp_node_afi(vty);
15039 safi = bgp_node_safi(vty);
718e3744 15040
585f1adc
IR
15041 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15042 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15043 || bgp->distance_local[afi][safi] != distance_local) {
15044 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15045 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15046 bgp->distance_local[afi][safi] = distance_local;
15047 bgp_announce_routes_distance_update(bgp, afi, safi);
15048 }
15049 return CMD_SUCCESS;
15050}
37a87b8f 15051
585f1adc
IR
15052DEFUN (no_bgp_distance,
15053 no_bgp_distance_cmd,
15054 "no distance bgp [(1-255) (1-255) (1-255)]",
15055 NO_STR
15056 "Define an administrative distance\n"
15057 "BGP distance\n"
15058 "Distance for routes external to the AS\n"
15059 "Distance for routes internal to the AS\n"
15060 "Distance for local routes\n")
718e3744 15061{
585f1adc 15062 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15063 afi_t afi;
15064 safi_t safi;
37a87b8f
CS
15065
15066 afi = bgp_node_afi(vty);
15067 safi = bgp_node_safi(vty);
15068
585f1adc
IR
15069 if (bgp->distance_ebgp[afi][safi] != 0
15070 || bgp->distance_ibgp[afi][safi] != 0
15071 || bgp->distance_local[afi][safi] != 0) {
15072 bgp->distance_ebgp[afi][safi] = 0;
15073 bgp->distance_ibgp[afi][safi] = 0;
15074 bgp->distance_local[afi][safi] = 0;
15075 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15076 }
585f1adc
IR
15077 return CMD_SUCCESS;
15078}
37a87b8f 15079
37a87b8f 15080
585f1adc
IR
15081DEFUN (bgp_distance_source,
15082 bgp_distance_source_cmd,
15083 "distance (1-255) A.B.C.D/M",
15084 "Define an administrative distance\n"
15085 "Administrative distance\n"
15086 "IP source prefix\n")
15087{
15088 int idx_number = 1;
15089 int idx_ipv4_prefixlen = 2;
15090 bgp_distance_set(vty, argv[idx_number]->arg,
15091 argv[idx_ipv4_prefixlen]->arg, NULL);
15092 return CMD_SUCCESS;
734b349e
MZ
15093}
15094
585f1adc
IR
15095DEFUN (no_bgp_distance_source,
15096 no_bgp_distance_source_cmd,
15097 "no distance (1-255) A.B.C.D/M",
15098 NO_STR
15099 "Define an administrative distance\n"
15100 "Administrative distance\n"
15101 "IP source prefix\n")
37a87b8f 15102{
585f1adc
IR
15103 int idx_number = 2;
15104 int idx_ipv4_prefixlen = 3;
15105 bgp_distance_unset(vty, argv[idx_number]->arg,
15106 argv[idx_ipv4_prefixlen]->arg, NULL);
15107 return CMD_SUCCESS;
37a87b8f
CS
15108}
15109
585f1adc
IR
15110DEFUN (bgp_distance_source_access_list,
15111 bgp_distance_source_access_list_cmd,
15112 "distance (1-255) A.B.C.D/M WORD",
15113 "Define an administrative distance\n"
15114 "Administrative distance\n"
15115 "IP source prefix\n"
15116 "Access list name\n")
37a87b8f 15117{
585f1adc
IR
15118 int idx_number = 1;
15119 int idx_ipv4_prefixlen = 2;
15120 int idx_word = 3;
15121 bgp_distance_set(vty, argv[idx_number]->arg,
15122 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15123 return CMD_SUCCESS;
15124}
718e3744 15125
585f1adc
IR
15126DEFUN (no_bgp_distance_source_access_list,
15127 no_bgp_distance_source_access_list_cmd,
15128 "no distance (1-255) A.B.C.D/M WORD",
15129 NO_STR
15130 "Define an administrative distance\n"
15131 "Administrative distance\n"
15132 "IP source prefix\n"
15133 "Access list name\n")
15134{
15135 int idx_number = 2;
15136 int idx_ipv4_prefixlen = 3;
15137 int idx_word = 4;
15138 bgp_distance_unset(vty, argv[idx_number]->arg,
15139 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15140 return CMD_SUCCESS;
15141}
37a87b8f 15142
585f1adc
IR
15143DEFUN (ipv6_bgp_distance_source,
15144 ipv6_bgp_distance_source_cmd,
15145 "distance (1-255) X:X::X:X/M",
15146 "Define an administrative distance\n"
15147 "Administrative distance\n"
15148 "IP source prefix\n")
15149{
15150 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15151 return CMD_SUCCESS;
15152}
7ebe9748 15153
585f1adc
IR
15154DEFUN (no_ipv6_bgp_distance_source,
15155 no_ipv6_bgp_distance_source_cmd,
15156 "no distance (1-255) X:X::X:X/M",
15157 NO_STR
15158 "Define an administrative distance\n"
15159 "Administrative distance\n"
15160 "IP source prefix\n")
15161{
15162 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15163 return CMD_SUCCESS;
15164}
37a87b8f 15165
585f1adc
IR
15166DEFUN (ipv6_bgp_distance_source_access_list,
15167 ipv6_bgp_distance_source_access_list_cmd,
15168 "distance (1-255) X:X::X:X/M WORD",
15169 "Define an administrative distance\n"
15170 "Administrative distance\n"
15171 "IP source prefix\n"
15172 "Access list name\n")
15173{
15174 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15175 return CMD_SUCCESS;
718e3744 15176}
15177
585f1adc
IR
15178DEFUN (no_ipv6_bgp_distance_source_access_list,
15179 no_ipv6_bgp_distance_source_access_list_cmd,
15180 "no distance (1-255) X:X::X:X/M WORD",
15181 NO_STR
15182 "Define an administrative distance\n"
15183 "Administrative distance\n"
15184 "IP source prefix\n"
15185 "Access list name\n")
718e3744 15186{
585f1adc
IR
15187 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15188 return CMD_SUCCESS;
15189}
37a87b8f 15190
585f1adc
IR
15191DEFUN (bgp_damp_set,
15192 bgp_damp_set_cmd,
a30fec23 15193 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15194 "BGP Specific commands\n"
15195 "Enable route-flap dampening\n"
15196 "Half-life time for the penalty\n"
15197 "Value to start reusing a route\n"
15198 "Value to start suppressing a route\n"
15199 "Maximum duration to suppress a stable route\n")
15200{
15201 VTY_DECLVAR_CONTEXT(bgp, bgp);
15202 int idx_half_life = 2;
15203 int idx_reuse = 3;
15204 int idx_suppress = 4;
15205 int idx_max_suppress = 5;
37a87b8f
CS
15206 int half = DEFAULT_HALF_LIFE * 60;
15207 int reuse = DEFAULT_REUSE;
15208 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15209 int max = 4 * half;
15210
15211 if (argc == 6) {
15212 half = atoi(argv[idx_half_life]->arg) * 60;
15213 reuse = atoi(argv[idx_reuse]->arg);
15214 suppress = atoi(argv[idx_suppress]->arg);
15215 max = atoi(argv[idx_max_suppress]->arg) * 60;
15216 } else if (argc == 3) {
15217 half = atoi(argv[idx_half_life]->arg) * 60;
15218 max = 4 * half;
15219 }
15220
15221 /*
15222 * These can't be 0 but our SA doesn't understand the
15223 * way our cli is constructed
15224 */
15225 assert(reuse);
15226 assert(half);
15227 if (suppress < reuse) {
15228 vty_out(vty,
15229 "Suppress value cannot be less than reuse value \n");
15230 return 0;
15231 }
15232
15233 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15234 reuse, suppress, max);
15235}
15236
15237DEFUN (bgp_damp_unset,
15238 bgp_damp_unset_cmd,
a30fec23 15239 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15240 NO_STR
15241 "BGP Specific commands\n"
15242 "Enable route-flap dampening\n"
15243 "Half-life time for the penalty\n"
15244 "Value to start reusing a route\n"
15245 "Value to start suppressing a route\n"
15246 "Maximum duration to suppress a stable route\n")
15247{
15248 VTY_DECLVAR_CONTEXT(bgp, bgp);
15249 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15250}
15251
718e3744 15252/* Display specified route of BGP table. */
d62a17ae 15253static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15254 const char *ip_str, afi_t afi, safi_t safi,
15255 struct prefix_rd *prd, int prefix_check)
15256{
15257 int ret;
15258 struct prefix match;
9bcb3eef
DS
15259 struct bgp_dest *dest;
15260 struct bgp_dest *rm;
40381db7
DS
15261 struct bgp_path_info *pi;
15262 struct bgp_path_info *pi_temp;
d62a17ae 15263 struct bgp *bgp;
15264 struct bgp_table *table;
15265
15266 /* BGP structure lookup. */
15267 if (view_name) {
15268 bgp = bgp_lookup_by_name(view_name);
15269 if (bgp == NULL) {
15270 vty_out(vty, "%% Can't find BGP instance %s\n",
15271 view_name);
15272 return CMD_WARNING;
15273 }
15274 } else {
15275 bgp = bgp_get_default();
15276 if (bgp == NULL) {
15277 vty_out(vty, "%% No BGP process is configured\n");
15278 return CMD_WARNING;
15279 }
718e3744 15280 }
718e3744 15281
d62a17ae 15282 /* Check IP address argument. */
15283 ret = str2prefix(ip_str, &match);
15284 if (!ret) {
15285 vty_out(vty, "%% address is malformed\n");
15286 return CMD_WARNING;
15287 }
718e3744 15288
d62a17ae 15289 match.family = afi2family(afi);
15290
15291 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15292 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15293 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15294 dest = bgp_route_next(dest)) {
15295 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15296
9bcb3eef 15297 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15298 continue;
9bcb3eef 15299 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15300 if (!table)
ea47320b 15301 continue;
4953391b
DA
15302 rm = bgp_node_match(table, &match);
15303 if (rm == NULL)
ea47320b 15304 continue;
d62a17ae 15305
9bcb3eef 15306 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15307
ea47320b 15308 if (!prefix_check
b54892e0 15309 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15310 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15311 while (pi) {
15312 if (pi->extra && pi->extra->damp_info) {
15313 pi_temp = pi->next;
ea47320b 15314 bgp_damp_info_free(
19971c9a 15315 pi->extra->damp_info,
5c8846f6 15316 1, afi, safi);
40381db7 15317 pi = pi_temp;
ea47320b 15318 } else
40381db7 15319 pi = pi->next;
d62a17ae 15320 }
ea47320b
DL
15321 }
15322
9bcb3eef 15323 bgp_dest_unlock_node(rm);
d62a17ae 15324 }
15325 } else {
4953391b
DA
15326 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15327 if (dest != NULL) {
9bcb3eef 15328 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15329
d62a17ae 15330 if (!prefix_check
9bcb3eef
DS
15331 || dest_p->prefixlen == match.prefixlen) {
15332 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15333 while (pi) {
15334 if (pi->extra && pi->extra->damp_info) {
15335 pi_temp = pi->next;
d62a17ae 15336 bgp_damp_info_free(
19971c9a 15337 pi->extra->damp_info,
5c8846f6 15338 1, afi, safi);
40381db7 15339 pi = pi_temp;
d62a17ae 15340 } else
40381db7 15341 pi = pi->next;
d62a17ae 15342 }
15343 }
15344
9bcb3eef 15345 bgp_dest_unlock_node(dest);
d62a17ae 15346 }
15347 }
718e3744 15348
d62a17ae 15349 return CMD_SUCCESS;
718e3744 15350}
15351
15352DEFUN (clear_ip_bgp_dampening,
15353 clear_ip_bgp_dampening_cmd,
15354 "clear ip bgp dampening",
15355 CLEAR_STR
15356 IP_STR
15357 BGP_STR
15358 "Clear route flap dampening information\n")
15359{
b4f7f45b 15360 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15361 return CMD_SUCCESS;
718e3744 15362}
15363
15364DEFUN (clear_ip_bgp_dampening_prefix,
15365 clear_ip_bgp_dampening_prefix_cmd,
15366 "clear ip bgp dampening A.B.C.D/M",
15367 CLEAR_STR
15368 IP_STR
15369 BGP_STR
15370 "Clear route flap dampening information\n"
0c7b1b01 15371 "IPv4 prefix\n")
718e3744 15372{
d62a17ae 15373 int idx_ipv4_prefixlen = 4;
15374 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15375 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15376}
15377
15378DEFUN (clear_ip_bgp_dampening_address,
15379 clear_ip_bgp_dampening_address_cmd,
15380 "clear ip bgp dampening A.B.C.D",
15381 CLEAR_STR
15382 IP_STR
15383 BGP_STR
15384 "Clear route flap dampening information\n"
15385 "Network to clear damping information\n")
15386{
d62a17ae 15387 int idx_ipv4 = 4;
15388 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15389 SAFI_UNICAST, NULL, 0);
718e3744 15390}
15391
15392DEFUN (clear_ip_bgp_dampening_address_mask,
15393 clear_ip_bgp_dampening_address_mask_cmd,
15394 "clear ip bgp dampening A.B.C.D A.B.C.D",
15395 CLEAR_STR
15396 IP_STR
15397 BGP_STR
15398 "Clear route flap dampening information\n"
15399 "Network to clear damping information\n"
15400 "Network mask\n")
15401{
d62a17ae 15402 int idx_ipv4 = 4;
15403 int idx_ipv4_2 = 5;
15404 int ret;
15405 char prefix_str[BUFSIZ];
718e3744 15406
d62a17ae 15407 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15408 prefix_str, sizeof(prefix_str));
d62a17ae 15409 if (!ret) {
15410 vty_out(vty, "%% Inconsistent address and mask\n");
15411 return CMD_WARNING;
15412 }
718e3744 15413
d62a17ae 15414 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15415 NULL, 0);
718e3744 15416}
6b0655a2 15417
e3b78da8 15418static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15419{
15420 struct vty *vty = arg;
e3b78da8 15421 struct peer *peer = bucket->data;
825d9834 15422
47e12884 15423 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15424}
15425
2a0e69ae
DS
15426DEFUN (show_bgp_listeners,
15427 show_bgp_listeners_cmd,
15428 "show bgp listeners",
15429 SHOW_STR
15430 BGP_STR
15431 "Display Listen Sockets and who created them\n")
15432{
15433 bgp_dump_listener_info(vty);
15434
15435 return CMD_SUCCESS;
15436}
15437
825d9834
DS
15438DEFUN (show_bgp_peerhash,
15439 show_bgp_peerhash_cmd,
15440 "show bgp peerhash",
15441 SHOW_STR
15442 BGP_STR
15443 "Display information about the BGP peerhash\n")
15444{
15445 struct list *instances = bm->bgp;
15446 struct listnode *node;
15447 struct bgp *bgp;
15448
15449 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15450 vty_out(vty, "BGP: %s\n", bgp->name);
15451 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15452 vty);
15453 }
15454
15455 return CMD_SUCCESS;
15456}
15457
587ff0fd 15458/* also used for encap safi */
2b791107
DL
15459static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15460 afi_t afi, safi_t safi)
d62a17ae 15461{
9bcb3eef
DS
15462 struct bgp_dest *pdest;
15463 struct bgp_dest *dest;
d62a17ae 15464 struct bgp_table *table;
b54892e0
DS
15465 const struct prefix *p;
15466 const struct prefix_rd *prd;
d62a17ae 15467 struct bgp_static *bgp_static;
15468 mpls_label_t label;
d62a17ae 15469
15470 /* Network configuration. */
9bcb3eef
DS
15471 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15472 pdest = bgp_route_next(pdest)) {
15473 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15474 if (!table)
ea47320b 15475 continue;
d62a17ae 15476
9bcb3eef
DS
15477 for (dest = bgp_table_top(table); dest;
15478 dest = bgp_route_next(dest)) {
15479 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15480 if (bgp_static == NULL)
ea47320b 15481 continue;
d62a17ae 15482
9bcb3eef
DS
15483 p = bgp_dest_get_prefix(dest);
15484 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15485 pdest);
d62a17ae 15486
ea47320b 15487 /* "network" configuration display. */
ea47320b
DL
15488 label = decode_label(&bgp_static->label);
15489
c4f64ea9 15490 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15491 if (safi == SAFI_MPLS_VPN)
15492 vty_out(vty, " label %u", label);
15493
15494 if (bgp_static->rmap.name)
15495 vty_out(vty, " route-map %s",
15496 bgp_static->rmap.name);
e2a86ad9
DS
15497
15498 if (bgp_static->backdoor)
15499 vty_out(vty, " backdoor");
15500
ea47320b
DL
15501 vty_out(vty, "\n");
15502 }
15503 }
d62a17ae 15504}
15505
2b791107
DL
15506static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15507 afi_t afi, safi_t safi)
d62a17ae 15508{
9bcb3eef
DS
15509 struct bgp_dest *pdest;
15510 struct bgp_dest *dest;
d62a17ae 15511 struct bgp_table *table;
b54892e0
DS
15512 const struct prefix *p;
15513 const struct prefix_rd *prd;
d62a17ae 15514 struct bgp_static *bgp_static;
ff44f570 15515 char buf[PREFIX_STRLEN * 2];
d62a17ae 15516 char buf2[SU_ADDRSTRLEN];
5f933e1e 15517 char esi_buf[ESI_STR_LEN];
d62a17ae 15518
15519 /* Network configuration. */
9bcb3eef
DS
15520 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15521 pdest = bgp_route_next(pdest)) {
15522 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15523 if (!table)
ea47320b 15524 continue;
d62a17ae 15525
9bcb3eef
DS
15526 for (dest = bgp_table_top(table); dest;
15527 dest = bgp_route_next(dest)) {
15528 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15529 if (bgp_static == NULL)
ea47320b 15530 continue;
d62a17ae 15531
ea47320b 15532 char *macrouter = NULL;
d62a17ae 15533
ea47320b
DL
15534 if (bgp_static->router_mac)
15535 macrouter = prefix_mac2str(
15536 bgp_static->router_mac, NULL, 0);
15537 if (bgp_static->eth_s_id)
0a50c248
AK
15538 esi_to_str(bgp_static->eth_s_id,
15539 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15540 p = bgp_dest_get_prefix(dest);
15541 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15542
ea47320b 15543 /* "network" configuration display. */
197cb530
PG
15544 if (p->u.prefix_evpn.route_type == 5) {
15545 char local_buf[PREFIX_STRLEN];
07380148 15546
3714a385 15547 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15548 struct prefix_evpn *)p)
15549 ? AF_INET
15550 : AF_INET6;
3714a385 15551 inet_ntop(family,
07380148
DA
15552 &p->u.prefix_evpn.prefix_addr.ip.ip
15553 .addr,
15554 local_buf, sizeof(local_buf));
772270f3
QY
15555 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15556 p->u.prefix_evpn.prefix_addr
15557 .ip_prefix_length);
197cb530
PG
15558 } else {
15559 prefix2str(p, buf, sizeof(buf));
15560 }
ea47320b 15561
a4d82a8a
PZ
15562 if (bgp_static->gatewayIp.family == AF_INET
15563 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15564 inet_ntop(bgp_static->gatewayIp.family,
15565 &bgp_static->gatewayIp.u.prefix, buf2,
15566 sizeof(buf2));
ea47320b 15567 vty_out(vty,
c4f64ea9
DA
15568 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15569 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15570 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15571 macrouter);
15572
0a22ddfb 15573 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15574 }
15575 }
3da6fcd5
PG
15576}
15577
718e3744 15578/* Configuration of static route announcement and aggregate
15579 information. */
2b791107
DL
15580void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15581 safi_t safi)
d62a17ae 15582{
9bcb3eef 15583 struct bgp_dest *dest;
b54892e0 15584 const struct prefix *p;
d62a17ae 15585 struct bgp_static *bgp_static;
15586 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15587
2b791107
DL
15588 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15589 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15590 return;
15591 }
d62a17ae 15592
2b791107
DL
15593 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15594 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15595 return;
15596 }
d62a17ae 15597
15598 /* Network configuration. */
9bcb3eef
DS
15599 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15600 dest = bgp_route_next(dest)) {
15601 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15602 if (bgp_static == NULL)
ea47320b 15603 continue;
d62a17ae 15604
9bcb3eef 15605 p = bgp_dest_get_prefix(dest);
d62a17ae 15606
8228a9a7 15607 vty_out(vty, " network %pFX", p);
d62a17ae 15608
ea47320b
DL
15609 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15610 vty_out(vty, " label-index %u",
15611 bgp_static->label_index);
d62a17ae 15612
ea47320b
DL
15613 if (bgp_static->rmap.name)
15614 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15615
15616 if (bgp_static->backdoor)
15617 vty_out(vty, " backdoor");
718e3744 15618
ea47320b
DL
15619 vty_out(vty, "\n");
15620 }
15621
d62a17ae 15622 /* Aggregate-address configuration. */
9bcb3eef
DS
15623 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15624 dest = bgp_route_next(dest)) {
15625 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15626 if (bgp_aggregate == NULL)
ea47320b 15627 continue;
d62a17ae 15628
9bcb3eef 15629 p = bgp_dest_get_prefix(dest);
d62a17ae 15630
8228a9a7 15631 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15632
ea47320b
DL
15633 if (bgp_aggregate->as_set)
15634 vty_out(vty, " as-set");
d62a17ae 15635
ea47320b
DL
15636 if (bgp_aggregate->summary_only)
15637 vty_out(vty, " summary-only");
718e3744 15638
20894f50
DA
15639 if (bgp_aggregate->rmap.name)
15640 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15641
229757f1
DA
15642 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15643 vty_out(vty, " origin %s",
15644 bgp_origin2str(bgp_aggregate->origin));
15645
6aabb15d
RZ
15646 if (bgp_aggregate->match_med)
15647 vty_out(vty, " matching-MED-only");
15648
365ab2e7
RZ
15649 if (bgp_aggregate->suppress_map_name)
15650 vty_out(vty, " suppress-map %s",
15651 bgp_aggregate->suppress_map_name);
15652
ea47320b
DL
15653 vty_out(vty, "\n");
15654 }
d62a17ae 15655}
734b349e 15656
2b791107 15657void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15658 safi_t safi)
d62a17ae 15659{
9bcb3eef 15660 struct bgp_dest *dest;
d62a17ae 15661 struct bgp_distance *bdistance;
15662
15663 /* Distance configuration. */
15664 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15665 && bgp->distance_local[afi][safi]
15666 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15667 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15668 || bgp->distance_local[afi][safi]
15669 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15670 vty_out(vty, " distance bgp %d %d %d\n",
15671 bgp->distance_ebgp[afi][safi],
15672 bgp->distance_ibgp[afi][safi],
15673 bgp->distance_local[afi][safi]);
15674 }
734b349e 15675
9bcb3eef
DS
15676 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15677 dest = bgp_route_next(dest)) {
15678 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15679 if (bdistance != NULL)
56ca3b5b 15680 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15681 bdistance->distance, dest,
d62a17ae 15682 bdistance->access_list ? bdistance->access_list
15683 : "");
ca2e160d 15684 }
718e3744 15685}
15686
15687/* Allocate routing table structure and install commands. */
d62a17ae 15688void bgp_route_init(void)
15689{
15690 afi_t afi;
15691 safi_t safi;
15692
15693 /* Init BGP distance table. */
05c7a1cc 15694 FOREACH_AFI_SAFI (afi, safi)
960035b2 15695 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15696
15697 /* IPv4 BGP commands. */
15698 install_element(BGP_NODE, &bgp_table_map_cmd);
15699 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15700 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15701
554b3b10 15702 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15703
15704 /* IPv4 unicast configuration. */
15705 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15706 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15707 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15708
554b3b10 15709 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15710
15711 /* IPv4 multicast configuration. */
15712 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15713 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15714 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15715 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15716
15717 /* IPv4 labeled-unicast configuration. */
fb985e0c 15718 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15719 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15720
d62a17ae 15721 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15722 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15723 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15724 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15725 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15726 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15727 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15728 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15729
15730 install_element(VIEW_NODE,
15731 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15732 install_element(VIEW_NODE,
15733 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15734 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15735 install_element(VIEW_NODE,
15736 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15737#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15738 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15739#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15740 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15741 install_element(VIEW_NODE,
44c69747 15742 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15743
d62a17ae 15744 /* BGP dampening clear commands */
15745 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15746 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15747
d62a17ae 15748 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15749 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15750
15751 /* prefix count */
15752 install_element(ENABLE_NODE,
15753 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15754#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15755 install_element(ENABLE_NODE,
15756 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15757#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15758
d62a17ae 15759 /* New config IPv6 BGP commands. */
15760 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15761 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15762 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15763
554b3b10 15764 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15765
15766 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15767
fb985e0c
DA
15768 /* IPv6 labeled unicast address family. */
15769 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15770 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15771
d62a17ae 15772 install_element(BGP_NODE, &bgp_distance_cmd);
15773 install_element(BGP_NODE, &no_bgp_distance_cmd);
15774 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15775 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15776 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15777 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15778 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15779 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15780 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15781 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15782 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15783 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15784 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15785 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15786 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15787 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15788 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15789 install_element(BGP_IPV4M_NODE,
15790 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15791 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15792 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15793 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15794 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15795 install_element(BGP_IPV6_NODE,
15796 &ipv6_bgp_distance_source_access_list_cmd);
15797 install_element(BGP_IPV6_NODE,
15798 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15799 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15800 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15801 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15802 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15803 install_element(BGP_IPV6M_NODE,
15804 &ipv6_bgp_distance_source_access_list_cmd);
15805 install_element(BGP_IPV6M_NODE,
15806 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15807
ef5f4b23 15808 /* BGP dampening */
585f1adc
IR
15809 install_element(BGP_NODE, &bgp_damp_set_cmd);
15810 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15811 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15812 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15813 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15814 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15815 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15816 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15817 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15818 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15819 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15820 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15821 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15822 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15823
15824 /* Large Communities */
15825 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15826 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15827
15828 /* show bgp ipv4 flowspec detailed */
15829 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15830
2a0e69ae 15831 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15832 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15833}
15834
15835void bgp_route_finish(void)
15836{
15837 afi_t afi;
15838 safi_t safi;
15839
05c7a1cc
QY
15840 FOREACH_AFI_SAFI (afi, safi) {
15841 bgp_table_unlock(bgp_distance_table[afi][safi]);
15842 bgp_distance_table[afi][safi] = NULL;
15843 }
228da428 15844}