]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Figure out rpki validation state earlier
[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"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
fdeb5a81 74#include "bgpd/bgp_rpki.h"
718e3744 75
49e5a4a0 76#ifdef ENABLE_BGP_VNC
f8b6f499
LB
77#include "bgpd/rfapi/rfapi_backend.h"
78#include "bgpd/rfapi/vnc_import_bgp.h"
79#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 80#endif
aee875b5
PG
81#include "bgpd/bgp_encap_types.h"
82#include "bgpd/bgp_encap_tlv.h"
684a7227 83#include "bgpd/bgp_evpn.h"
0a50c248 84#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 85#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 86#include "bgpd/bgp_flowspec.h"
98a9dbc7 87#include "bgpd/bgp_flowspec_util.h"
45918cfb 88#include "bgpd/bgp_pbr.h"
37a87b8f
CS
89#include "northbound.h"
90#include "northbound_cli.h"
91#include "bgpd/bgp_nb.h"
65efcfce 92
e2a86ad9
DS
93#ifndef VTYSH_EXTRACT_PL
94#include "bgpd/bgp_route_clippy.c"
95#endif
aee875b5 96
7fd28dd2
PR
97DEFINE_HOOK(bgp_snmp_update_stats,
98 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 99 (rn, pi, added));
7fd28dd2 100
b5b99af8
DS
101DEFINE_HOOK(bgp_rpki_prefix_status,
102 (struct peer *peer, struct attr *attr,
103 const struct prefix *prefix),
8451921b 104 (peer, attr, prefix));
b5b99af8 105
718e3744 106/* Extern from bgp_dump.c */
dde72586
SH
107extern const char *bgp_origin_str[];
108extern const char *bgp_origin_long_str[];
3742de8d 109
b7d08f5a 110/* PMSI strings. */
111#define PMSI_TNLTYPE_STR_NO_INFO "No info"
112#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
113static const struct message bgp_pmsi_tnltype_str[] = {
114 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
115 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
116 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
117 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
118 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
119 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
120 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
121 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 122 {0}
123};
b7d08f5a 124
9df8b37c
PZ
125#define VRFID_NONE_STR "-"
126
4a11bf2c 127DEFINE_HOOK(bgp_process,
9bcb3eef
DS
128 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
129 struct peer *peer, bool withdraw),
8451921b 130 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 131
4056a5f6
RZ
132/** Test if path is suppressed. */
133static bool bgp_path_suppressed(struct bgp_path_info *pi)
134{
135 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
136 return false;
137
138 return listcount(pi->extra->aggr_suppressors) > 0;
139}
4a11bf2c 140
9bcb3eef 141struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 142 safi_t safi, const struct prefix *p,
d62a17ae 143 struct prefix_rd *prd)
144{
9bcb3eef
DS
145 struct bgp_dest *dest;
146 struct bgp_dest *pdest = NULL;
d62a17ae 147
148 assert(table);
d62a17ae 149
150 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
151 || (safi == SAFI_EVPN)) {
9bcb3eef 152 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 153
9bcb3eef
DS
154 if (!bgp_dest_has_bgp_path_info_data(pdest))
155 bgp_dest_set_bgp_table_info(
156 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 157 else
9bcb3eef
DS
158 bgp_dest_unlock_node(pdest);
159 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 160 }
718e3744 161
9bcb3eef 162 dest = bgp_node_get(table, p);
718e3744 163
d62a17ae 164 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165 || (safi == SAFI_EVPN))
9bcb3eef 166 dest->pdest = pdest;
718e3744 167
9bcb3eef 168 return dest;
718e3744 169}
6b0655a2 170
9bcb3eef 171struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 172 safi_t safi, const struct prefix *p,
d62a17ae 173 struct prefix_rd *prd)
128ea8ab 174{
9bcb3eef
DS
175 struct bgp_dest *dest;
176 struct bgp_dest *pdest = NULL;
128ea8ab 177
d62a17ae 178 if (!table)
179 return NULL;
128ea8ab 180
d62a17ae 181 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
182 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
183 pdest = bgp_node_lookup(table, (struct prefix *)prd);
184 if (!pdest)
d62a17ae 185 return NULL;
128ea8ab 186
9bcb3eef
DS
187 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
188 bgp_dest_unlock_node(pdest);
d62a17ae 189 return NULL;
190 }
128ea8ab 191
9bcb3eef 192 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 193 }
128ea8ab 194
9bcb3eef 195 dest = bgp_node_lookup(table, p);
128ea8ab 196
9bcb3eef 197 return dest;
128ea8ab 198}
199
18ee8310
DS
200/* Allocate bgp_path_info_extra */
201static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 202{
4b7e6066
DS
203 struct bgp_path_info_extra *new;
204 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
205 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
206 new->label[0] = MPLS_INVALID_LABEL;
207 new->num_labels = 0;
3e3708cb
PG
208 new->bgp_fs_pbr = NULL;
209 new->bgp_fs_iprule = NULL;
d62a17ae 210 return new;
fb982c25
PJ
211}
212
a2e219fe 213void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 214{
4b7e6066 215 struct bgp_path_info_extra *e;
d62a17ae 216
c93a3b77
DS
217 if (!extra || !*extra)
218 return;
d62a17ae 219
c93a3b77 220 e = *extra;
d62a17ae 221
c93a3b77
DS
222 e->damp_info = NULL;
223 if (e->parent) {
40381db7 224 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 225
40381db7 226 if (bpi->net) {
0e70e6c8
DL
227 /* FIXME: since multiple e may have the same e->parent
228 * and e->parent->net is holding a refcount for each
229 * of them, we need to do some fudging here.
230 *
40381db7
DS
231 * WARNING: if bpi->net->lock drops to 0, bpi may be
232 * freed as well (because bpi->net was holding the
233 * last reference to bpi) => write after free!
0e70e6c8
DL
234 */
235 unsigned refcount;
236
40381db7 237 bpi = bgp_path_info_lock(bpi);
c10e14e9 238 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 239 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 240 if (!refcount)
40381db7
DS
241 bpi->net = NULL;
242 bgp_path_info_unlock(bpi);
0e70e6c8 243 }
18ee8310 244 bgp_path_info_unlock(e->parent);
c93a3b77 245 e->parent = NULL;
d62a17ae 246 }
c93a3b77
DS
247
248 if (e->bgp_orig)
249 bgp_unlock(e->bgp_orig);
c26edcda 250
ff3bf9a4
DS
251 if (e->aggr_suppressors)
252 list_delete(&e->aggr_suppressors);
253
60605cbc
AK
254 if (e->mh_info)
255 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 256
ce3c0614
PG
257 if ((*extra)->bgp_fs_iprule)
258 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 259 if ((*extra)->bgp_fs_pbr)
6a154c88 260 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 261 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
262}
263
18ee8310
DS
264/* Get bgp_path_info extra information for the given bgp_path_info, lazy
265 * allocated if required.
fb982c25 266 */
40381db7 267struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 268{
40381db7
DS
269 if (!pi->extra)
270 pi->extra = bgp_path_info_extra_new();
271 return pi->extra;
fb982c25
PJ
272}
273
718e3744 274/* Free bgp route information. */
9b6d8fcf 275static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 276{
05864da7 277 bgp_attr_unintern(&path->attr);
fb018d25 278
9b6d8fcf
DS
279 bgp_unlink_nexthop(path);
280 bgp_path_info_extra_free(&path->extra);
281 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
282 if (path->net)
283 bgp_addpath_free_info_data(&path->tx_addpath,
284 &path->net->tx_addpath);
718e3744 285
9b6d8fcf 286 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 287
9b6d8fcf 288 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 289}
290
9b6d8fcf 291struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 292{
9b6d8fcf
DS
293 path->lock++;
294 return path;
200df115 295}
296
9b6d8fcf 297struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 298{
9b6d8fcf
DS
299 assert(path && path->lock > 0);
300 path->lock--;
d62a17ae 301
9b6d8fcf 302 if (path->lock == 0) {
200df115 303#if 0
304 zlog_debug ("%s: unlocked and freeing", __func__);
305 zlog_backtrace (LOG_DEBUG);
306#endif
9b6d8fcf 307 bgp_path_info_free(path);
d62a17ae 308 return NULL;
309 }
200df115 310
311#if 0
9b6d8fcf 312 if (path->lock == 1)
200df115 313 {
314 zlog_debug ("%s: unlocked to 1", __func__);
315 zlog_backtrace (LOG_DEBUG);
316 }
317#endif
d62a17ae 318
9b6d8fcf 319 return path;
200df115 320}
321
f009ff26 322/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 323static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 324{
325 struct peer *peer;
326 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 327 bool set_flag = false;
f009ff26 328 struct bgp *bgp = NULL;
329 struct bgp_table *table = NULL;
330 afi_t afi = 0;
331 safi_t safi = 0;
f009ff26 332
333 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
334 * then the route selection is deferred
335 */
9bcb3eef 336 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 337 return 0;
338
9bcb3eef 339 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 340 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 341 zlog_debug(
56ca3b5b
DL
342 "Route %pBD is in workqueue and being processed, not deferred.",
343 dest);
b54892e0 344
5f9c1aa2 345 return 0;
346 }
347
9bcb3eef 348 table = bgp_dest_table(dest);
f009ff26 349 if (table) {
350 bgp = table->bgp;
351 afi = table->afi;
352 safi = table->safi;
353 }
354
9bcb3eef 355 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 356 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
357 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
358 continue;
359
360 /* Route selection is deferred if there is a stale path which
361 * which indicates peer is in restart mode
362 */
36235319
QY
363 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
364 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 365 set_flag = true;
f009ff26 366 } else {
367 /* If the peer is graceful restart capable and peer is
368 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
369 */
370 peer = old_pi->peer;
36235319
QY
371 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
372 && BGP_PEER_RESTARTING_MODE(peer)
373 && (old_pi
374 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 375 set_flag = true;
f009ff26 376 }
377 }
378 if (set_flag)
379 break;
380 }
381
382 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
383 * is active
384 */
2ba1fe69 385 if (set_flag && table) {
f009ff26 386 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
387 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
388 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 389 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 390 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
391 zlog_debug("DEFER route %pBD, dest %p", dest,
392 dest);
f009ff26 393 return 0;
394 }
395 }
396 return -1;
397}
398
9bcb3eef 399void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 400{
4b7e6066 401 struct bgp_path_info *top;
718e3744 402
9bcb3eef 403 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 404
6f94b685 405 pi->next = top;
40381db7 406 pi->prev = NULL;
d62a17ae 407 if (top)
40381db7 408 top->prev = pi;
9bcb3eef 409 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 410
40381db7 411 bgp_path_info_lock(pi);
9bcb3eef 412 bgp_dest_lock_node(dest);
40381db7 413 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 414 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 415 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 416}
417
d62a17ae 418/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 419 completion callback *only* */
9bcb3eef 420void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 421{
40381db7
DS
422 if (pi->next)
423 pi->next->prev = pi->prev;
424 if (pi->prev)
425 pi->prev->next = pi->next;
d62a17ae 426 else
9bcb3eef 427 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 428
40381db7
DS
429 bgp_path_info_mpath_dequeue(pi);
430 bgp_path_info_unlock(pi);
7fd28dd2 431 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 432 bgp_dest_unlock_node(dest);
718e3744 433}
434
9bcb3eef 435void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 436{
9bcb3eef 437 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 438 /* set of previous already took care of pcount */
40381db7 439 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 440}
441
18ee8310 442/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
443 called when a route is deleted and then quickly re-added before the
444 deletion has been processed */
9bcb3eef 445void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 446{
9bcb3eef 447 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 448 /* unset of previous already took care of pcount */
40381db7 449 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
450}
451
d62a17ae 452/* Adjust pcount as required */
9bcb3eef 453static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 454{
d62a17ae 455 struct bgp_table *table;
67174041 456
9bcb3eef 457 assert(dest && bgp_dest_table(dest));
40381db7 458 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 459
9bcb3eef 460 table = bgp_dest_table(dest);
67174041 461
40381db7 462 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 463 return;
464
40381db7
DS
465 if (!BGP_PATH_COUNTABLE(pi)
466 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 467
40381db7 468 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 469
470 /* slight hack, but more robust against errors. */
40381db7
DS
471 if (pi->peer->pcount[table->afi][table->safi])
472 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 473 else
450971aa 474 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 475 "Asked to decrement 0 prefix count for peer");
40381db7
DS
476 } else if (BGP_PATH_COUNTABLE(pi)
477 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
478 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
479 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 480 }
1a392d46
PJ
481}
482
40381db7
DS
483static int bgp_label_index_differs(struct bgp_path_info *pi1,
484 struct bgp_path_info *pi2)
28d58fd7 485{
40381db7 486 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 487}
1a392d46 488
18ee8310 489/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
490 * This is here primarily to keep prefix-count in check.
491 */
9bcb3eef 492void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 493 uint32_t flag)
1a392d46 494{
40381db7 495 SET_FLAG(pi->flags, flag);
d62a17ae 496
497 /* early bath if we know it's not a flag that changes countability state
498 */
499 if (!CHECK_FLAG(flag,
1defdda8 500 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 501 return;
502
9bcb3eef 503 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
504}
505
9bcb3eef 506void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 507 uint32_t flag)
1a392d46 508{
40381db7 509 UNSET_FLAG(pi->flags, flag);
d62a17ae 510
511 /* early bath if we know it's not a flag that changes countability state
512 */
513 if (!CHECK_FLAG(flag,
1defdda8 514 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 515 return;
516
9bcb3eef 517 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
518}
519
718e3744 520/* Get MED value. If MED value is missing and "bgp bestpath
521 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 522static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 523{
524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
525 return attr->med;
526 else {
892fedb6 527 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 528 return BGP_MED_MAX;
529 else
530 return 0;
531 }
718e3744 532}
533
7533cad7
QY
534void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
535 size_t buf_len)
2ec1e66f 536{
40381db7 537 if (pi->addpath_rx_id)
7533cad7
QY
538 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
539 pi->peer->host, pi->addpath_rx_id);
d62a17ae 540 else
7533cad7 541 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 542}
9fbdd100 543
d62a17ae 544/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
545 */
18ee8310
DS
546static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
547 struct bgp_path_info *exist, int *paths_eq,
548 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
549 char *pfx_buf, afi_t afi, safi_t safi,
550 enum bgp_path_selection_reason *reason)
d62a17ae 551{
552 struct attr *newattr, *existattr;
553 bgp_peer_sort_t new_sort;
554 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
555 uint32_t new_pref;
556 uint32_t exist_pref;
557 uint32_t new_med;
558 uint32_t exist_med;
559 uint32_t new_weight;
560 uint32_t exist_weight;
d62a17ae 561 uint32_t newm, existm;
562 struct in_addr new_id;
563 struct in_addr exist_id;
564 int new_cluster;
565 int exist_cluster;
566 int internal_as_route;
567 int confed_as_route;
04d14c8b 568 int ret = 0;
d62a17ae 569 char new_buf[PATH_ADDPATH_STR_BUFFER];
570 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
571 uint32_t new_mm_seq;
572 uint32_t exist_mm_seq;
6d8c603a 573 int nh_cmp;
d071f237
AK
574 esi_t *exist_esi;
575 esi_t *new_esi;
576 bool same_esi;
577 bool old_proxy;
578 bool new_proxy;
33c6e933 579 bool new_origin, exist_origin;
d62a17ae 580
581 *paths_eq = 0;
582
583 /* 0. Null check. */
584 if (new == NULL) {
fdf81fa0 585 *reason = bgp_path_selection_none;
d62a17ae 586 if (debug)
587 zlog_debug("%s: new is NULL", pfx_buf);
588 return 0;
589 }
2ec1e66f 590
d62a17ae 591 if (debug)
7533cad7
QY
592 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
593 sizeof(new_buf));
718e3744 594
d62a17ae 595 if (exist == NULL) {
fdf81fa0 596 *reason = bgp_path_selection_first;
d62a17ae 597 if (debug)
598 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
599 new_buf);
600 return 1;
601 }
2ec1e66f 602
d62a17ae 603 if (debug) {
7533cad7
QY
604 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
605 sizeof(exist_buf));
d62a17ae 606 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
607 pfx_buf, new_buf, new->flags, exist_buf,
608 exist->flags);
609 }
8ff56318 610
d62a17ae 611 newattr = new->attr;
612 existattr = exist->attr;
613
614 /* For EVPN routes, we cannot just go by local vs remote, we have to
615 * look at the MAC mobility sequence number, if present.
616 */
617 if (safi == SAFI_EVPN) {
618 /* This is an error condition described in RFC 7432 Section
619 * 15.2. The RFC
620 * states that in this scenario "the PE MUST alert the operator"
621 * but it
622 * does not state what other action to take. In order to provide
623 * some
624 * consistency in this scenario we are going to prefer the path
625 * with the
626 * sticky flag.
627 */
628 if (newattr->sticky != existattr->sticky) {
629 if (!debug) {
9bcb3eef
DS
630 prefix2str(
631 bgp_dest_get_prefix(new->net), pfx_buf,
632 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310 633 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
634 new, new_buf, sizeof(new_buf));
635 bgp_path_info_path_with_addpath_rx_str(
636 exist, exist_buf, sizeof(exist_buf));
d62a17ae 637 }
638
639 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 640 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
641 if (debug)
642 zlog_debug(
643 "%s: %s wins over %s due to sticky MAC flag",
644 pfx_buf, new_buf, exist_buf);
d62a17ae 645 return 1;
646 }
647
648 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 649 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
650 if (debug)
651 zlog_debug(
652 "%s: %s loses to %s due to sticky MAC flag",
653 pfx_buf, new_buf, exist_buf);
d62a17ae 654 return 0;
655 }
656 }
128ea8ab 657
d071f237
AK
658 new_esi = bgp_evpn_attr_get_esi(newattr);
659 exist_esi = bgp_evpn_attr_get_esi(existattr);
660 if (bgp_evpn_is_esi_valid(new_esi) &&
661 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
662 same_esi = true;
663 } else {
664 same_esi = false;
665 }
666
667 /* If both paths have the same non-zero ES and
668 * one path is local it wins.
669 * PS: Note the local path wins even if the remote
670 * has the higher MM seq. The local path's
671 * MM seq will be fixed up to match the highest
672 * rem seq, subsequently.
673 */
674 if (same_esi) {
675 char esi_buf[ESI_STR_LEN];
676
677 if (bgp_evpn_is_path_local(bgp, new)) {
678 *reason = bgp_path_selection_evpn_local_path;
679 if (debug)
680 zlog_debug(
681 "%s: %s wins over %s as ES %s is same and local",
682 pfx_buf, new_buf, exist_buf,
683 esi_to_str(new_esi, esi_buf,
684 sizeof(esi_buf)));
685 return 1;
686 }
687 if (bgp_evpn_is_path_local(bgp, exist)) {
688 *reason = bgp_path_selection_evpn_local_path;
689 if (debug)
690 zlog_debug(
691 "%s: %s loses to %s as ES %s is same and local",
692 pfx_buf, new_buf, exist_buf,
693 esi_to_str(new_esi, esi_buf,
694 sizeof(esi_buf)));
695 return 0;
696 }
697 }
698
d62a17ae 699 new_mm_seq = mac_mobility_seqnum(newattr);
700 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 701
d62a17ae 702 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 703 *reason = bgp_path_selection_evpn_seq;
d62a17ae 704 if (debug)
705 zlog_debug(
706 "%s: %s wins over %s due to MM seq %u > %u",
707 pfx_buf, new_buf, exist_buf, new_mm_seq,
708 exist_mm_seq);
709 return 1;
710 }
8ff56318 711
d62a17ae 712 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 713 *reason = bgp_path_selection_evpn_seq;
d62a17ae 714 if (debug)
715 zlog_debug(
716 "%s: %s loses to %s due to MM seq %u < %u",
717 pfx_buf, new_buf, exist_buf, new_mm_seq,
718 exist_mm_seq);
719 return 0;
720 }
6d8c603a 721
d071f237
AK
722 /* if the sequence numbers and ESI are the same and one path
723 * is non-proxy it wins (over proxy)
724 */
725 new_proxy = bgp_evpn_attr_is_proxy(newattr);
726 old_proxy = bgp_evpn_attr_is_proxy(existattr);
727 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
728 old_proxy != new_proxy) {
729 if (!new_proxy) {
730 *reason = bgp_path_selection_evpn_non_proxy;
731 if (debug)
732 zlog_debug(
733 "%s: %s wins over %s, same seq/es and non-proxy",
734 pfx_buf, new_buf, exist_buf);
735 return 1;
736 }
737
738 *reason = bgp_path_selection_evpn_non_proxy;
739 if (debug)
740 zlog_debug(
741 "%s: %s loses to %s, same seq/es and non-proxy",
742 pfx_buf, new_buf, exist_buf);
743 return 0;
744 }
745
6d8c603a
AK
746 /*
747 * if sequence numbers are the same path with the lowest IP
748 * wins
749 */
750 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
751 if (nh_cmp < 0) {
fdf81fa0 752 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
753 if (debug)
754 zlog_debug(
23d0a753 755 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 756 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 757 &new->attr->nexthop);
6d8c603a
AK
758 return 1;
759 }
760 if (nh_cmp > 0) {
fdf81fa0 761 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
762 if (debug)
763 zlog_debug(
23d0a753 764 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 765 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 766 &new->attr->nexthop);
6d8c603a
AK
767 return 0;
768 }
d62a17ae 769 }
9fbdd100 770
d62a17ae 771 /* 1. Weight check. */
d62a17ae 772 new_weight = newattr->weight;
773 exist_weight = existattr->weight;
8ff56318 774
d62a17ae 775 if (new_weight > exist_weight) {
fdf81fa0 776 *reason = bgp_path_selection_weight;
d62a17ae 777 if (debug)
778 zlog_debug("%s: %s wins over %s due to weight %d > %d",
779 pfx_buf, new_buf, exist_buf, new_weight,
780 exist_weight);
781 return 1;
782 }
718e3744 783
d62a17ae 784 if (new_weight < exist_weight) {
fdf81fa0 785 *reason = bgp_path_selection_weight;
d62a17ae 786 if (debug)
787 zlog_debug("%s: %s loses to %s due to weight %d < %d",
788 pfx_buf, new_buf, exist_buf, new_weight,
789 exist_weight);
790 return 0;
791 }
9fbdd100 792
d62a17ae 793 /* 2. Local preference check. */
794 new_pref = exist_pref = bgp->default_local_pref;
795
796 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
797 new_pref = newattr->local_pref;
798 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
799 exist_pref = existattr->local_pref;
800
801 if (new_pref > exist_pref) {
fdf81fa0 802 *reason = bgp_path_selection_local_pref;
d62a17ae 803 if (debug)
804 zlog_debug(
805 "%s: %s wins over %s due to localpref %d > %d",
806 pfx_buf, new_buf, exist_buf, new_pref,
807 exist_pref);
808 return 1;
809 }
718e3744 810
d62a17ae 811 if (new_pref < exist_pref) {
fdf81fa0 812 *reason = bgp_path_selection_local_pref;
d62a17ae 813 if (debug)
814 zlog_debug(
815 "%s: %s loses to %s due to localpref %d < %d",
816 pfx_buf, new_buf, exist_buf, new_pref,
817 exist_pref);
818 return 0;
819 }
9fbdd100 820
d62a17ae 821 /* 3. Local route check. We prefer:
822 * - BGP_ROUTE_STATIC
823 * - BGP_ROUTE_AGGREGATE
824 * - BGP_ROUTE_REDISTRIBUTE
825 */
33c6e933
DS
826 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
827 new->sub_type == BGP_ROUTE_IMPORTED);
828 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
829 exist->sub_type == BGP_ROUTE_IMPORTED);
830
831 if (new_origin && !exist_origin) {
fdf81fa0 832 *reason = bgp_path_selection_local_route;
d62a17ae 833 if (debug)
834 zlog_debug(
835 "%s: %s wins over %s due to preferred BGP_ROUTE type",
836 pfx_buf, new_buf, exist_buf);
837 return 1;
838 }
718e3744 839
33c6e933 840 if (!new_origin && exist_origin) {
fdf81fa0 841 *reason = bgp_path_selection_local_route;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s loses to %s due to preferred BGP_ROUTE type",
845 pfx_buf, new_buf, exist_buf);
846 return 0;
6811845b 847 }
718e3744 848
d62a17ae 849 /* 4. AS path length check. */
892fedb6 850 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 851 int exist_hops = aspath_count_hops(existattr->aspath);
852 int exist_confeds = aspath_count_confeds(existattr->aspath);
853
892fedb6 854 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 855 int aspath_hops;
856
857 aspath_hops = aspath_count_hops(newattr->aspath);
858 aspath_hops += aspath_count_confeds(newattr->aspath);
859
860 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 861 *reason = bgp_path_selection_confed_as_path;
d62a17ae 862 if (debug)
863 zlog_debug(
864 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
865 pfx_buf, new_buf, exist_buf,
866 aspath_hops,
867 (exist_hops + exist_confeds));
868 return 1;
869 }
870
871 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 872 *reason = bgp_path_selection_confed_as_path;
d62a17ae 873 if (debug)
874 zlog_debug(
875 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
876 pfx_buf, new_buf, exist_buf,
877 aspath_hops,
878 (exist_hops + exist_confeds));
879 return 0;
880 }
881 } else {
882 int newhops = aspath_count_hops(newattr->aspath);
883
884 if (newhops < exist_hops) {
fdf81fa0 885 *reason = bgp_path_selection_as_path;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to aspath hopcount %d < %d",
889 pfx_buf, new_buf, exist_buf,
890 newhops, exist_hops);
891 return 1;
892 }
893
894 if (newhops > exist_hops) {
fdf81fa0 895 *reason = bgp_path_selection_as_path;
d62a17ae 896 if (debug)
897 zlog_debug(
898 "%s: %s loses to %s due to aspath hopcount %d > %d",
899 pfx_buf, new_buf, exist_buf,
900 newhops, exist_hops);
901 return 0;
902 }
903 }
904 }
9fbdd100 905
d62a17ae 906 /* 5. Origin check. */
907 if (newattr->origin < existattr->origin) {
fdf81fa0 908 *reason = bgp_path_selection_origin;
d62a17ae 909 if (debug)
910 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
911 pfx_buf, new_buf, exist_buf,
912 bgp_origin_long_str[newattr->origin],
913 bgp_origin_long_str[existattr->origin]);
914 return 1;
915 }
718e3744 916
d62a17ae 917 if (newattr->origin > existattr->origin) {
fdf81fa0 918 *reason = bgp_path_selection_origin;
d62a17ae 919 if (debug)
920 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
921 pfx_buf, new_buf, exist_buf,
922 bgp_origin_long_str[newattr->origin],
923 bgp_origin_long_str[existattr->origin]);
924 return 0;
925 }
718e3744 926
d62a17ae 927 /* 6. MED check. */
928 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
929 && aspath_count_hops(existattr->aspath) == 0);
930 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
931 && aspath_count_confeds(existattr->aspath) > 0
932 && aspath_count_hops(newattr->aspath) == 0
933 && aspath_count_hops(existattr->aspath) == 0);
934
892fedb6
DA
935 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
936 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 937 || aspath_cmp_left(newattr->aspath, existattr->aspath)
938 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
939 || internal_as_route) {
940 new_med = bgp_med_value(new->attr, bgp);
941 exist_med = bgp_med_value(exist->attr, bgp);
942
943 if (new_med < exist_med) {
fdf81fa0 944 *reason = bgp_path_selection_med;
d62a17ae 945 if (debug)
946 zlog_debug(
947 "%s: %s wins over %s due to MED %d < %d",
948 pfx_buf, new_buf, exist_buf, new_med,
949 exist_med);
950 return 1;
951 }
8ff56318 952
d62a17ae 953 if (new_med > exist_med) {
fdf81fa0 954 *reason = bgp_path_selection_med;
d62a17ae 955 if (debug)
956 zlog_debug(
957 "%s: %s loses to %s due to MED %d > %d",
958 pfx_buf, new_buf, exist_buf, new_med,
959 exist_med);
960 return 0;
961 }
962 }
9fbdd100 963
d62a17ae 964 /* 7. Peer type check. */
965 new_sort = new->peer->sort;
966 exist_sort = exist->peer->sort;
967
968 if (new_sort == BGP_PEER_EBGP
969 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 970 *reason = bgp_path_selection_peer;
d62a17ae 971 if (debug)
972 zlog_debug(
973 "%s: %s wins over %s due to eBGP peer > iBGP peer",
974 pfx_buf, new_buf, exist_buf);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (exist_sort == BGP_PEER_EBGP
979 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 980 *reason = bgp_path_selection_peer;
d62a17ae 981 if (debug)
982 zlog_debug(
983 "%s: %s loses to %s due to iBGP peer < eBGP peer",
984 pfx_buf, new_buf, exist_buf);
985 return 0;
986 }
8ff56318 987
d62a17ae 988 /* 8. IGP metric check. */
989 newm = existm = 0;
8ff56318 990
d62a17ae 991 if (new->extra)
992 newm = new->extra->igpmetric;
993 if (exist->extra)
994 existm = exist->extra->igpmetric;
9fbdd100 995
d62a17ae 996 if (newm < existm) {
997 if (debug)
998 zlog_debug(
d588b995 999 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1000 pfx_buf, new_buf, exist_buf, newm, existm);
1001 ret = 1;
1002 }
718e3744 1003
d62a17ae 1004 if (newm > existm) {
1005 if (debug)
1006 zlog_debug(
d588b995 1007 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1008 pfx_buf, new_buf, exist_buf, newm, existm);
1009 ret = 0;
5e242b0d 1010 }
5e242b0d 1011
d62a17ae 1012 /* 9. Same IGP metric. Compare the cluster list length as
1013 representative of IGP hops metric. Rewrite the metric value
1014 pair (newm, existm) with the cluster list length. Prefer the
1015 path with smaller cluster list length. */
1016 if (newm == existm) {
bf0d28dc
DS
1017 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1018 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1019 && (mpath_cfg == NULL
1020 || CHECK_FLAG(
1021 mpath_cfg->ibgp_flags,
1022 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1023 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1024 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1025
1026 if (newm < existm) {
1027 if (debug)
1028 zlog_debug(
d588b995 1029 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1030 pfx_buf, new_buf, exist_buf,
1031 newm, existm);
1032 ret = 1;
1033 }
1034
1035 if (newm > existm) {
1036 if (debug)
1037 zlog_debug(
d588b995 1038 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1039 pfx_buf, new_buf, exist_buf,
1040 newm, existm);
1041 ret = 0;
1042 }
1043 }
1044 }
31a4638f 1045
d62a17ae 1046 /* 10. confed-external vs. confed-internal */
1047 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1048 if (new_sort == BGP_PEER_CONFED
1049 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1050 *reason = bgp_path_selection_confed;
d62a17ae 1051 if (debug)
1052 zlog_debug(
1053 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1054 pfx_buf, new_buf, exist_buf);
1055 return 1;
1056 }
718e3744 1057
d62a17ae 1058 if (exist_sort == BGP_PEER_CONFED
1059 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1060 *reason = bgp_path_selection_confed;
d62a17ae 1061 if (debug)
1062 zlog_debug(
1063 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1064 pfx_buf, new_buf, exist_buf);
1065 return 0;
1066 }
1067 }
718e3744 1068
d62a17ae 1069 /* 11. Maximum path check. */
1070 if (newm == existm) {
1071 /* If one path has a label but the other does not, do not treat
1072 * them as equals for multipath
1073 */
a4d82a8a 1074 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1075 != (exist->extra
b57ba6d2 1076 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1077 if (debug)
1078 zlog_debug(
1079 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1080 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1081 } else if (CHECK_FLAG(bgp->flags,
1082 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1083
1084 /*
1085 * For the two paths, all comparison steps till IGP
1086 * metric
1087 * have succeeded - including AS_PATH hop count. Since
1088 * 'bgp
1089 * bestpath as-path multipath-relax' knob is on, we
1090 * don't need
1091 * an exact match of AS_PATH. Thus, mark the paths are
1092 * equal.
1093 * That will trigger both these paths to get into the
1094 * multipath
1095 * array.
1096 */
1097 *paths_eq = 1;
1098
1099 if (debug)
1100 zlog_debug(
1101 "%s: %s and %s are equal via multipath-relax",
1102 pfx_buf, new_buf, exist_buf);
1103 } else if (new->peer->sort == BGP_PEER_IBGP) {
1104 if (aspath_cmp(new->attr->aspath,
1105 exist->attr->aspath)) {
1106 *paths_eq = 1;
1107
1108 if (debug)
1109 zlog_debug(
1110 "%s: %s and %s are equal via matching aspaths",
1111 pfx_buf, new_buf, exist_buf);
1112 }
1113 } else if (new->peer->as == exist->peer->as) {
1114 *paths_eq = 1;
1115
1116 if (debug)
1117 zlog_debug(
1118 "%s: %s and %s are equal via same remote-as",
1119 pfx_buf, new_buf, exist_buf);
1120 }
1121 } else {
1122 /*
1123 * TODO: If unequal cost ibgp multipath is enabled we can
1124 * mark the paths as equal here instead of returning
1125 */
1126 if (debug) {
1127 if (ret == 1)
1128 zlog_debug(
1129 "%s: %s wins over %s after IGP metric comparison",
1130 pfx_buf, new_buf, exist_buf);
1131 else
1132 zlog_debug(
1133 "%s: %s loses to %s after IGP metric comparison",
1134 pfx_buf, new_buf, exist_buf);
1135 }
fdf81fa0 1136 *reason = bgp_path_selection_igp_metric;
d62a17ae 1137 return ret;
1138 }
718e3744 1139
d62a17ae 1140 /* 12. If both paths are external, prefer the path that was received
1141 first (the oldest one). This step minimizes route-flap, since a
1142 newer path won't displace an older one, even if it was the
1143 preferred route based on the additional decision criteria below. */
892fedb6 1144 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1145 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1146 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1147 *reason = bgp_path_selection_older;
d62a17ae 1148 if (debug)
1149 zlog_debug(
1150 "%s: %s wins over %s due to oldest external",
1151 pfx_buf, new_buf, exist_buf);
1152 return 1;
1153 }
9fbdd100 1154
1defdda8 1155 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1156 *reason = bgp_path_selection_older;
d62a17ae 1157 if (debug)
1158 zlog_debug(
1159 "%s: %s loses to %s due to oldest external",
1160 pfx_buf, new_buf, exist_buf);
1161 return 0;
1162 }
1163 }
718e3744 1164
d62a17ae 1165 /* 13. Router-ID comparision. */
1166 /* If one of the paths is "stale", the corresponding peer router-id will
1167 * be 0 and would always win over the other path. If originator id is
1168 * used for the comparision, it will decide which path is better.
1169 */
1170 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1171 new_id.s_addr = newattr->originator_id.s_addr;
1172 else
1173 new_id.s_addr = new->peer->remote_id.s_addr;
1174 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1175 exist_id.s_addr = existattr->originator_id.s_addr;
1176 else
1177 exist_id.s_addr = exist->peer->remote_id.s_addr;
1178
1179 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1180 *reason = bgp_path_selection_router_id;
d62a17ae 1181 if (debug)
1182 zlog_debug(
1183 "%s: %s wins over %s due to Router-ID comparison",
1184 pfx_buf, new_buf, exist_buf);
1185 return 1;
1186 }
718e3744 1187
d62a17ae 1188 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1189 *reason = bgp_path_selection_router_id;
d62a17ae 1190 if (debug)
1191 zlog_debug(
1192 "%s: %s loses to %s due to Router-ID comparison",
1193 pfx_buf, new_buf, exist_buf);
1194 return 0;
1195 }
9fbdd100 1196
d62a17ae 1197 /* 14. Cluster length comparision. */
1198 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1199 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1200
1201 if (new_cluster < exist_cluster) {
fdf81fa0 1202 *reason = bgp_path_selection_cluster_length;
d62a17ae 1203 if (debug)
1204 zlog_debug(
1205 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1206 pfx_buf, new_buf, exist_buf, new_cluster,
1207 exist_cluster);
1208 return 1;
1209 }
718e3744 1210
d62a17ae 1211 if (new_cluster > exist_cluster) {
fdf81fa0 1212 *reason = bgp_path_selection_cluster_length;
d62a17ae 1213 if (debug)
1214 zlog_debug(
1215 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1216 pfx_buf, new_buf, exist_buf, new_cluster,
1217 exist_cluster);
1218 return 0;
1219 }
9fbdd100 1220
d62a17ae 1221 /* 15. Neighbor address comparision. */
1222 /* Do this only if neither path is "stale" as stale paths do not have
1223 * valid peer information (as the connection may or may not be up).
1224 */
1defdda8 1225 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1226 *reason = bgp_path_selection_stale;
d62a17ae 1227 if (debug)
1228 zlog_debug(
1229 "%s: %s wins over %s due to latter path being STALE",
1230 pfx_buf, new_buf, exist_buf);
1231 return 1;
1232 }
0de5153c 1233
1defdda8 1234 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1235 *reason = bgp_path_selection_stale;
d62a17ae 1236 if (debug)
1237 zlog_debug(
1238 "%s: %s loses to %s due to former path being STALE",
1239 pfx_buf, new_buf, exist_buf);
1240 return 0;
1241 }
718e3744 1242
d62a17ae 1243 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1244 if (new->peer->su_remote == NULL) {
1245 *reason = bgp_path_selection_local_configured;
d62a17ae 1246 return 0;
fdf81fa0
DS
1247 }
1248 if (exist->peer->su_remote == NULL) {
1249 *reason = bgp_path_selection_local_configured;
d62a17ae 1250 return 1;
fdf81fa0 1251 }
9fbdd100 1252
d62a17ae 1253 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1254
1255 if (ret == 1) {
fdf81fa0 1256 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1257 if (debug)
1258 zlog_debug(
1259 "%s: %s loses to %s due to Neighor IP comparison",
1260 pfx_buf, new_buf, exist_buf);
1261 return 0;
1262 }
1263
1264 if (ret == -1) {
fdf81fa0 1265 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1266 if (debug)
1267 zlog_debug(
1268 "%s: %s wins over %s due to Neighor IP comparison",
1269 pfx_buf, new_buf, exist_buf);
1270 return 1;
1271 }
9fbdd100 1272
fdf81fa0 1273 *reason = bgp_path_selection_default;
d62a17ae 1274 if (debug)
1275 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1276 pfx_buf, new_buf, exist_buf);
718e3744 1277
d62a17ae 1278 return 1;
718e3744 1279}
1280
d071f237
AK
1281
1282int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1283 struct bgp_path_info *exist, int *paths_eq)
1284{
1285 enum bgp_path_selection_reason reason;
1286 char pfx_buf[PREFIX2STR_BUFFER];
1287
1288 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1289 AFI_L2VPN, SAFI_EVPN, &reason);
1290}
1291
65efcfce
LB
1292/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1293 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1294 * multipath is enabled
65efcfce 1295 * This version is compatible with */
18ee8310
DS
1296int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1297 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1298 afi_t afi, safi_t safi,
1299 enum bgp_path_selection_reason *reason)
d62a17ae 1300{
1301 int paths_eq;
1302 int ret;
18ee8310 1303 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1304 afi, safi, reason);
d62a17ae 1305
1306 if (paths_eq)
1307 ret = 0;
1308 else {
1309 if (ret == 1)
1310 ret = -1;
1311 else
1312 ret = 1;
1313 }
1314 return ret;
65efcfce
LB
1315}
1316
5a1ae2c2
DS
1317static enum filter_type bgp_input_filter(struct peer *peer,
1318 const struct prefix *p,
d62a17ae 1319 struct attr *attr, afi_t afi,
1320 safi_t safi)
718e3744 1321{
d62a17ae 1322 struct bgp_filter *filter;
6401252f 1323 enum filter_type ret = FILTER_PERMIT;
718e3744 1324
d62a17ae 1325 filter = &peer->filter[afi][safi];
718e3744 1326
d62a17ae 1327#define FILTER_EXIST_WARN(F, f, filter) \
1328 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1329 zlog_debug("%s: Could not find configured input %s-list %s!", \
1330 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1331
1332 if (DISTRIBUTE_IN_NAME(filter)) {
1333 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1334
6401252f
QY
1335 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1336 == FILTER_DENY) {
1337 ret = FILTER_DENY;
1338 goto done;
1339 }
d62a17ae 1340 }
1341
1342 if (PREFIX_LIST_IN_NAME(filter)) {
1343 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1344
6401252f
QY
1345 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1346 == PREFIX_DENY) {
1347 ret = FILTER_DENY;
1348 goto done;
1349 }
d62a17ae 1350 }
1351
1352 if (FILTER_LIST_IN_NAME(filter)) {
1353 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1354
1355 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1356 == AS_FILTER_DENY) {
1357 ret = FILTER_DENY;
1358 goto done;
1359 }
d62a17ae 1360 }
1361
6401252f 1362done:
c7bb4f00 1363 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1364 char pfxprint[PREFIX2STR_BUFFER];
1365
1366 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1367 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1368 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1369 }
1370
1371 return ret;
650f76c2 1372#undef FILTER_EXIST_WARN
718e3744 1373}
1374
b8685f9b
DS
1375static enum filter_type bgp_output_filter(struct peer *peer,
1376 const struct prefix *p,
d62a17ae 1377 struct attr *attr, afi_t afi,
1378 safi_t safi)
718e3744 1379{
d62a17ae 1380 struct bgp_filter *filter;
6401252f 1381 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1382
1383 filter = &peer->filter[afi][safi];
1384
1385#define FILTER_EXIST_WARN(F, f, filter) \
1386 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1387 zlog_debug("%s: Could not find configured output %s-list %s!", \
1388 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1389
d62a17ae 1390 if (DISTRIBUTE_OUT_NAME(filter)) {
1391 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1392
6401252f
QY
1393 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1394 == FILTER_DENY) {
1395 ret = FILTER_DENY;
1396 goto done;
1397 }
d62a17ae 1398 }
1399
1400 if (PREFIX_LIST_OUT_NAME(filter)) {
1401 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1402
d62a17ae 1403 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1404 == PREFIX_DENY) {
1405 ret = FILTER_DENY;
1406 goto done;
1407 }
d62a17ae 1408 }
718e3744 1409
d62a17ae 1410 if (FILTER_LIST_OUT_NAME(filter)) {
1411 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1412
d62a17ae 1413 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1414 == AS_FILTER_DENY) {
1415 ret = FILTER_DENY;
1416 goto done;
1417 }
1418 }
1419
c7bb4f00 1420 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1421 char pfxprint[PREFIX2STR_BUFFER];
1422
1423 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1424 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1425 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1426 }
718e3744 1427
6401252f
QY
1428done:
1429 return ret;
650f76c2 1430#undef FILTER_EXIST_WARN
718e3744 1431}
1432
1433/* If community attribute includes no_export then return 1. */
3dc339cd 1434static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1435{
1436 if (attr->community) {
1437 /* NO_ADVERTISE check. */
1438 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1439 return true;
d62a17ae 1440
1441 /* NO_EXPORT check. */
1442 if (peer->sort == BGP_PEER_EBGP
1443 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1444 return true;
d62a17ae 1445
1446 /* NO_EXPORT_SUBCONFED check. */
1447 if (peer->sort == BGP_PEER_EBGP
1448 || peer->sort == BGP_PEER_CONFED)
1449 if (community_include(attr->community,
1450 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1451 return true;
d62a17ae 1452 }
3dc339cd 1453 return false;
718e3744 1454}
1455
1456/* Route reflection loop check. */
3dc339cd 1457static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1458{
d62a17ae 1459 struct in_addr cluster_id;
779fee93 1460 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1461
779fee93 1462 if (cluster) {
d62a17ae 1463 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1464 cluster_id = peer->bgp->cluster_id;
1465 else
1466 cluster_id = peer->bgp->router_id;
1467
779fee93 1468 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1469 return true;
d62a17ae 1470 }
3dc339cd 1471 return false;
718e3744 1472}
6b0655a2 1473
5a1ae2c2 1474static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1475 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1476 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1477 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1478{
d62a17ae 1479 struct bgp_filter *filter;
82b692c0
LK
1480 struct bgp_path_info rmap_path = { 0 };
1481 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1482 route_map_result_t ret;
1483 struct route_map *rmap = NULL;
718e3744 1484
d62a17ae 1485 filter = &peer->filter[afi][safi];
718e3744 1486
d62a17ae 1487 /* Apply default weight value. */
1488 if (peer->weight[afi][safi])
1489 attr->weight = peer->weight[afi][safi];
718e3744 1490
d62a17ae 1491 if (rmap_name) {
1492 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1493
d62a17ae 1494 if (rmap == NULL)
1495 return RMAP_DENY;
1496 } else {
1497 if (ROUTE_MAP_IN_NAME(filter)) {
1498 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1499
d62a17ae 1500 if (rmap == NULL)
1501 return RMAP_DENY;
1502 }
1503 }
0b16f239 1504
d62a17ae 1505 /* Route map apply. */
1506 if (rmap) {
40381db7 1507 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1508 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1509 rmap_path.peer = peer;
1510 rmap_path.attr = attr;
82b692c0 1511 rmap_path.extra = &extra;
9bcb3eef 1512 rmap_path.net = dest;
196c6b09 1513
82b692c0
LK
1514 extra.num_labels = num_labels;
1515 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1516 memcpy(extra.label, label,
1517 num_labels * sizeof(mpls_label_t));
718e3744 1518
d62a17ae 1519 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1520
d62a17ae 1521 /* Apply BGP route map to the attribute. */
1782514f 1522 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1523
d62a17ae 1524 peer->rmap_type = 0;
0b16f239 1525
1f2263be 1526 if (ret == RMAP_DENYMATCH)
d62a17ae 1527 return RMAP_DENY;
0b16f239 1528 }
d62a17ae 1529 return RMAP_PERMIT;
0b16f239
DS
1530}
1531
5f040085 1532static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1533 struct attr *attr, afi_t afi, safi_t safi,
1534 const char *rmap_name)
0b16f239 1535{
40381db7 1536 struct bgp_path_info rmap_path;
d62a17ae 1537 route_map_result_t ret;
1538 struct route_map *rmap = NULL;
d7c0a89a 1539 uint8_t rmap_type;
0b16f239 1540
b787157a
DS
1541 /*
1542 * So if we get to this point and have no rmap_name
1543 * we want to just show the output as it currently
1544 * exists.
1545 */
1546 if (!rmap_name)
1547 return RMAP_PERMIT;
0b16f239 1548
d62a17ae 1549 /* Apply default weight value. */
1550 if (peer->weight[afi][safi])
1551 attr->weight = peer->weight[afi][safi];
0b16f239 1552
b787157a 1553 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1554
b787157a
DS
1555 /*
1556 * If we have a route map name and we do not find
1557 * the routemap that means we have an implicit
1558 * deny.
1559 */
1560 if (rmap == NULL)
1561 return RMAP_DENY;
0b16f239 1562
40381db7 1563 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1564 /* Route map apply. */
b787157a 1565 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1566 rmap_path.peer = peer;
1567 rmap_path.attr = attr;
0b16f239 1568
0f672529 1569 rmap_type = peer->rmap_type;
b787157a 1570 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1571
b787157a 1572 /* Apply BGP route map to the attribute. */
1782514f 1573 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1574
0f672529 1575 peer->rmap_type = rmap_type;
b787157a
DS
1576
1577 if (ret == RMAP_DENYMATCH)
1578 /*
1579 * caller has multiple error paths with bgp_attr_flush()
1580 */
1581 return RMAP_DENY;
ac41b2a2 1582
d62a17ae 1583 return RMAP_PERMIT;
718e3744 1584}
6b0655a2 1585
5000f21c 1586/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1587static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1588 struct peer *peer, struct attr *attr)
1589{
1590 if (peer->sort == BGP_PEER_EBGP
1591 && (peer_af_flag_check(peer, afi, safi,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1593 || peer_af_flag_check(peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1595 || peer_af_flag_check(peer, afi, safi,
1596 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1597 || peer_af_flag_check(peer, afi, safi,
1598 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1599 // Take action on the entire aspath
1600 if (peer_af_flag_check(peer, afi, safi,
1601 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1602 || peer_af_flag_check(peer, afi, safi,
1603 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1604 if (peer_af_flag_check(
1605 peer, afi, safi,
1606 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1607 attr->aspath = aspath_replace_private_asns(
bf26b80e 1608 attr->aspath, bgp->as, peer->as);
d62a17ae 1609
1610 // The entire aspath consists of private ASNs so create
1611 // an empty aspath
1612 else if (aspath_private_as_check(attr->aspath))
1613 attr->aspath = aspath_empty_get();
1614
1615 // There are some public and some private ASNs, remove
1616 // the private ASNs
1617 else
1618 attr->aspath = aspath_remove_private_asns(
bf26b80e 1619 attr->aspath, peer->as);
d62a17ae 1620 }
1621
1622 // 'all' was not specified so the entire aspath must be private
1623 // ASNs
1624 // for us to do anything
1625 else if (aspath_private_as_check(attr->aspath)) {
1626 if (peer_af_flag_check(
1627 peer, afi, safi,
1628 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1629 attr->aspath = aspath_replace_private_asns(
bf26b80e 1630 attr->aspath, bgp->as, peer->as);
d62a17ae 1631 else
1632 attr->aspath = aspath_empty_get();
1633 }
1634 }
5000f21c
DS
1635}
1636
c7122e14 1637/* If this is an EBGP peer with as-override */
d62a17ae 1638static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1639 struct peer *peer, struct attr *attr)
1640{
1641 if (peer->sort == BGP_PEER_EBGP
1642 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1643 if (aspath_single_asn_check(attr->aspath, peer->as))
1644 attr->aspath = aspath_replace_specific_asn(
1645 attr->aspath, peer->as, bgp->as);
1646 }
1647}
1648
7f323236
DW
1649void bgp_attr_add_gshut_community(struct attr *attr)
1650{
1651 struct community *old;
1652 struct community *new;
1653 struct community *merge;
1654 struct community *gshut;
1655
1656 old = attr->community;
1657 gshut = community_str2com("graceful-shutdown");
1658
990f4f91 1659 assert(gshut);
1660
7f323236
DW
1661 if (old) {
1662 merge = community_merge(community_dup(old), gshut);
1663
a4d82a8a 1664 if (old->refcnt == 0)
3c1f53de 1665 community_free(&old);
7f323236
DW
1666
1667 new = community_uniq_sort(merge);
3c1f53de 1668 community_free(&merge);
7f323236
DW
1669 } else {
1670 new = community_dup(gshut);
1671 }
1672
3c1f53de 1673 community_free(&gshut);
7f323236
DW
1674 attr->community = new;
1675 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1676
1677 /* When we add the graceful-shutdown community we must also
1678 * lower the local-preference */
1679 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1680 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1681}
1682
1683
e73c112e
MK
1684/* Notify BGP Conditional advertisement scanner process. */
1685void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1686{
1687 struct peer *temp_peer;
1688 struct peer *peer = SUBGRP_PEER(subgrp);
1689 struct listnode *temp_node, *temp_nnode = NULL;
1690 afi_t afi = SUBGRP_AFI(subgrp);
1691 safi_t safi = SUBGRP_SAFI(subgrp);
1692 struct bgp *bgp = SUBGRP_INST(subgrp);
1693 struct bgp_filter *filter = &peer->filter[afi][safi];
1694
1695 if (!ADVERTISE_MAP_NAME(filter))
1696 return;
1697
1698 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1699 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1700 continue;
1701
1702 if (peer != temp_peer)
1703 continue;
1704
1705 temp_peer->advmap_table_change = true;
1706 break;
1707 }
1708}
1709
1710
f2ee6d5c 1711void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1712{
960035b2 1713 if (family == AF_INET) {
975a328e
DA
1714 attr->nexthop.s_addr = INADDR_ANY;
1715 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1716 }
d62a17ae 1717 if (family == AF_INET6)
1718 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1719 if (family == AF_EVPN)
1720 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1721}
1722
9bcb3eef 1723bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1724 struct update_subgroup *subgrp,
7f7940e6
MK
1725 const struct prefix *p, struct attr *attr,
1726 bool skip_rmap_check)
d62a17ae 1727{
1728 struct bgp_filter *filter;
1729 struct peer *from;
1730 struct peer *peer;
1731 struct peer *onlypeer;
1732 struct bgp *bgp;
40381db7 1733 struct attr *piattr;
b68885f9 1734 route_map_result_t ret;
d62a17ae 1735 int transparent;
1736 int reflect;
1737 afi_t afi;
1738 safi_t safi;
1739 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1740 bool nh_reset = false;
1741 uint64_t cum_bw;
d62a17ae 1742
1743 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1744 return false;
d62a17ae 1745
1746 afi = SUBGRP_AFI(subgrp);
1747 safi = SUBGRP_SAFI(subgrp);
1748 peer = SUBGRP_PEER(subgrp);
1749 onlypeer = NULL;
1750 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1751 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1752
40381db7 1753 from = pi->peer;
d62a17ae 1754 filter = &peer->filter[afi][safi];
1755 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1756 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1757 : pi->attr;
3f9c7369 1758
49e5a4a0 1759#ifdef ENABLE_BGP_VNC
d62a17ae 1760 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1761 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1762 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1763
1764 /*
1765 * direct and direct_ext type routes originate internally even
1766 * though they can have peer pointers that reference other
1767 * systems
1768 */
8228a9a7
DS
1769 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1770 __func__, p);
d62a17ae 1771 samepeer_safe = 1;
1772 }
65efcfce
LB
1773#endif
1774
ddb5b488
PZ
1775 if (((afi == AFI_IP) || (afi == AFI_IP6))
1776 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1777 && (pi->type == ZEBRA_ROUTE_BGP)
1778 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1779
1780 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1781
1782 samepeer_safe = 1;
1783 }
1784
d62a17ae 1785 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1786 * pi is valid */
1787 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1788 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1789 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1790 return false;
d62a17ae 1791 }
adbac85e 1792
d62a17ae 1793 /* If this is not the bestpath then check to see if there is an enabled
1794 * addpath
1795 * feature that requires us to advertise it */
40381db7 1796 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1797 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1798 return false;
d62a17ae 1799 }
1800 }
06370dac 1801
d62a17ae 1802 /* Aggregate-address suppress check. */
4056a5f6
RZ
1803 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1804 return false;
3f9c7369 1805
13b7e7f0
DS
1806 /*
1807 * If we are doing VRF 2 VRF leaking via the import
1808 * statement, we want to prevent the route going
1809 * off box as that the RT and RD created are localy
1810 * significant and globaly useless.
1811 */
40381db7
DS
1812 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1813 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1814 return false;
13b7e7f0 1815
d62a17ae 1816 /* If it's labeled safi, make sure the route has a valid label. */
1817 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1818 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1819 if (!bgp_is_valid_label(&label)) {
1820 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1821 zlog_debug("u%" PRIu64 ":s%" PRIu64
1822 " %pFX is filtered - no label (%p)",
d62a17ae 1823 subgrp->update_group->id, subgrp->id,
8228a9a7 1824 p, &label);
3dc339cd 1825 return false;
d62a17ae 1826 }
1827 }
cd1964ff 1828
d62a17ae 1829 /* Do not send back route to sender. */
1830 if (onlypeer && from == onlypeer) {
3dc339cd 1831 return false;
d62a17ae 1832 }
3f9c7369 1833
d62a17ae 1834 /* Do not send the default route in the BGP table if the neighbor is
1835 * configured for default-originate */
1836 if (CHECK_FLAG(peer->af_flags[afi][safi],
1837 PEER_FLAG_DEFAULT_ORIGINATE)) {
1838 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1839 return false;
d62a17ae 1840 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1841 return false;
d62a17ae 1842 }
4125bb67 1843
d62a17ae 1844 /* Transparency check. */
1845 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1846 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1847 transparent = 1;
1848 else
1849 transparent = 0;
1850
1851 /* If community is not disabled check the no-export and local. */
40381db7 1852 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1853 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1854 zlog_debug("%s: community filter check fail for %pFX",
1855 __func__, p);
3dc339cd 1856 return false;
d62a17ae 1857 }
3f9c7369 1858
d62a17ae 1859 /* If the attribute has originator-id and it is same as remote
1860 peer's id. */
40381db7
DS
1861 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1862 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1863 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1864 zlog_debug(
8228a9a7
DS
1865 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1866 onlypeer->host, p);
3dc339cd 1867 return false;
d62a17ae 1868 }
3f9c7369 1869
d62a17ae 1870 /* ORF prefix-list filter check */
1871 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1872 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1873 || CHECK_FLAG(peer->af_cap[afi][safi],
1874 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1875 if (peer->orf_plist[afi][safi]) {
1876 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1877 == PREFIX_DENY) {
1878 if (bgp_debug_update(NULL, p,
1879 subgrp->update_group, 0))
1880 zlog_debug(
8228a9a7
DS
1881 "%s [Update:SEND] %pFX is filtered via ORF",
1882 peer->host, p);
3dc339cd 1883 return false;
d62a17ae 1884 }
1885 }
1886
1887 /* Output filter check. */
40381db7 1888 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1889 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1890 zlog_debug("%s [Update:SEND] %pFX is filtered",
1891 peer->host, p);
3dc339cd 1892 return false;
d62a17ae 1893 }
3f9c7369 1894
d62a17ae 1895 /* AS path loop check. */
2b31007c
RZ
1896 if (onlypeer && onlypeer->as_path_loop_detection
1897 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1898 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1899 zlog_debug(
3efd0893 1900 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1901 onlypeer->host, onlypeer->as);
3dc339cd 1902 return false;
d62a17ae 1903 }
3f9c7369 1904
d62a17ae 1905 /* If we're a CONFED we need to loop check the CONFED ID too */
1906 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1907 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1908 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1909 zlog_debug(
3efd0893 1910 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1911 peer->host, bgp->confed_id);
3dc339cd 1912 return false;
d62a17ae 1913 }
3f9c7369 1914 }
3f9c7369 1915
d62a17ae 1916 /* Route-Reflect check. */
1917 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1918 reflect = 1;
1919 else
1920 reflect = 0;
1921
1922 /* IBGP reflection check. */
1923 if (reflect && !samepeer_safe) {
1924 /* A route from a Client peer. */
1925 if (CHECK_FLAG(from->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT)) {
1927 /* Reflect to all the Non-Client peers and also to the
1928 Client peers other than the originator. Originator
1929 check
1930 is already done. So there is noting to do. */
1931 /* no bgp client-to-client reflection check. */
892fedb6
DA
1932 if (CHECK_FLAG(bgp->flags,
1933 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1934 if (CHECK_FLAG(peer->af_flags[afi][safi],
1935 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1936 return false;
d62a17ae 1937 } else {
1938 /* A route from a Non-client peer. Reflect to all other
1939 clients. */
1940 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1941 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1942 return false;
d62a17ae 1943 }
1944 }
3f9c7369 1945
d62a17ae 1946 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1947 *attr = *piattr;
d62a17ae 1948
1949 /* If local-preference is not set. */
1950 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1951 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1952 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1953 attr->local_pref = bgp->default_local_pref;
3f9c7369 1954 }
3f9c7369 1955
d62a17ae 1956 /* If originator-id is not set and the route is to be reflected,
1957 set the originator id */
1958 if (reflect
1959 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1960 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1961 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1962 }
3f9c7369 1963
d62a17ae 1964 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1965 */
1966 if (peer->sort == BGP_PEER_EBGP
1967 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1968 if (from != bgp->peer_self && !transparent
1969 && !CHECK_FLAG(peer->af_flags[afi][safi],
1970 PEER_FLAG_MED_UNCHANGED))
1971 attr->flag &=
1972 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1973 }
3f9c7369 1974
d62a17ae 1975 /* Since the nexthop attribute can vary per peer, it is not explicitly
1976 * set
1977 * in announce check, only certain flags and length (or number of
1978 * nexthops
1979 * -- for IPv6/MP_REACH) are set here in order to guide the update
1980 * formation
1981 * code in setting the nexthop(s) on a per peer basis in
1982 * reformat_peer().
1983 * Typically, the source nexthop in the attribute is preserved but in
1984 * the
1985 * scenarios where we know it will always be overwritten, we reset the
1986 * nexthop to "0" in an attempt to achieve better Update packing. An
1987 * example of this is when a prefix from each of 2 IBGP peers needs to
1988 * be
1989 * announced to an EBGP peer (and they have the same attributes barring
1990 * their nexthop).
1991 */
1992 if (reflect)
1993 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1994
1995#define NEXTHOP_IS_V6 \
1996 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1997 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1998 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1999 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2000
2001 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2002 * if
2003 * the peer (group) is configured to receive link-local nexthop
2004 * unchanged
c728d027
DA
2005 * and it is available in the prefix OR we're not reflecting the route,
2006 * link-local nexthop address is valid and
d62a17ae 2007 * the peer (group) to whom we're going to announce is on a shared
2008 * network
2009 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2010 * By checking if nexthop LL address is valid we are sure that
2011 * we do not announce LL address as `::`.
d62a17ae 2012 */
2013 if (NEXTHOP_IS_V6) {
2014 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2015 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2016 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2017 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2018 || (!reflect
2019 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2020 && peer->shared_network
d62a17ae 2021 && (from == bgp->peer_self
2022 || peer->sort == BGP_PEER_EBGP))) {
2023 attr->mp_nexthop_len =
2024 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2025 }
3f9c7369 2026
d62a17ae 2027 /* Clear off link-local nexthop in source, whenever it is not
2028 * needed to
2029 * ensure more prefixes share the same attribute for
2030 * announcement.
2031 */
2032 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2033 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2034 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2035 }
3f9c7369 2036
d62a17ae 2037 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2038 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2039
2040 /* Route map & unsuppress-map apply. */
7f7940e6 2041 if (!skip_rmap_check
e73c112e 2042 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2043 struct bgp_path_info rmap_path = {0};
2044 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2045 struct attr dummy_attr = {0};
d62a17ae 2046
e34291b8 2047 /* Fill temp path_info */
9bcb3eef
DS
2048 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2049 pi, peer, attr);
16f7ce2b 2050
d62a17ae 2051 /* don't confuse inbound and outbound setting */
2052 RESET_FLAG(attr->rmap_change_flags);
2053
2054 /*
2055 * The route reflector is not allowed to modify the attributes
2056 * of the reflected IBGP routes unless explicitly allowed.
2057 */
2058 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2059 && !CHECK_FLAG(bgp->flags,
2060 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2061 dummy_attr = *attr;
40381db7 2062 rmap_path.attr = &dummy_attr;
d62a17ae 2063 }
3f9c7369 2064
d62a17ae 2065 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2066
4056a5f6 2067 if (bgp_path_suppressed(pi))
d62a17ae 2068 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2069 &rmap_path);
d62a17ae 2070 else
2071 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2072 &rmap_path);
d62a17ae 2073
2074 peer->rmap_type = 0;
2075
2076 if (ret == RMAP_DENYMATCH) {
778048bf 2077 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2078 zlog_debug(
2079 "%s [Update:SEND] %pFX is filtered by route-map",
2080 peer->host, p);
778048bf 2081
d62a17ae 2082 bgp_attr_flush(attr);
3dc339cd 2083 return false;
d62a17ae 2084 }
3f9c7369 2085 }
3f9c7369 2086
9dac9fc8
DA
2087 /* RFC 8212 to prevent route leaks.
2088 * This specification intends to improve this situation by requiring the
2089 * explicit configuration of both BGP Import and Export Policies for any
2090 * External BGP (EBGP) session such as customers, peers, or
2091 * confederation boundaries for all enabled address families. Through
2092 * codification of the aforementioned requirement, operators will
2093 * benefit from consistent behavior across different BGP
2094 * implementations.
2095 */
1d3fdccf 2096 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2097 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2098 return false;
9dac9fc8 2099
fb29348a
DA
2100 /* draft-ietf-idr-deprecate-as-set-confed-set
2101 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2102 * Eventually, This document (if approved) updates RFC 4271
2103 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2104 * and obsoletes RFC 6472.
2105 */
7f972cd8 2106 if (peer->bgp->reject_as_sets)
fb29348a 2107 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2108 return false;
fb29348a 2109
33d022bc
DA
2110 /* Codification of AS 0 Processing */
2111 if (aspath_check_as_zero(attr->aspath))
e2369003 2112 return false;
33d022bc 2113
637e5ba4 2114 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2115 if (peer->sort == BGP_PEER_IBGP
2116 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2117 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2118 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2119 } else {
2120 bgp_attr_add_gshut_community(attr);
2121 }
2122 }
2123
d62a17ae 2124 /* After route-map has been applied, we check to see if the nexthop to
2125 * be carried in the attribute (that is used for the announcement) can
2126 * be cleared off or not. We do this in all cases where we would be
2127 * setting the nexthop to "ourselves". For IPv6, we only need to
2128 * consider
2129 * the global nexthop here; the link-local nexthop would have been
2130 * cleared
2131 * already, and if not, it is required by the update formation code.
2132 * Also see earlier comments in this function.
2133 */
2134 /*
2135 * If route-map has performed some operation on the nexthop or the peer
2136 * configuration says to pass it unchanged, we cannot reset the nexthop
2137 * here, so only attempt to do it if these aren't true. Note that the
2138 * route-map handler itself might have cleared the nexthop, if for
2139 * example,
2140 * it is configured as 'peer-address'.
2141 */
2142 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2143 piattr->rmap_change_flags)
d62a17ae 2144 && !transparent
2145 && !CHECK_FLAG(peer->af_flags[afi][safi],
2146 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2147 /* We can reset the nexthop, if setting (or forcing) it to
2148 * 'self' */
2149 if (CHECK_FLAG(peer->af_flags[afi][safi],
2150 PEER_FLAG_NEXTHOP_SELF)
2151 || CHECK_FLAG(peer->af_flags[afi][safi],
2152 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2153 if (!reflect
2154 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2155 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2156 subgroup_announce_reset_nhop(
2157 (peer_cap_enhe(peer, afi, safi)
2158 ? AF_INET6
2159 : p->family),
2160 attr);
7b651a32 2161 nh_reset = true;
2162 }
d62a17ae 2163 } else if (peer->sort == BGP_PEER_EBGP) {
2164 /* Can also reset the nexthop if announcing to EBGP, but
2165 * only if
2166 * no peer in the subgroup is on a shared subnet.
2167 * Note: 3rd party nexthop currently implemented for
2168 * IPv4 only.
2169 */
737af885
BS
2170 if ((p->family == AF_INET) &&
2171 (!bgp_subgrp_multiaccess_check_v4(
2172 piattr->nexthop,
7b651a32 2173 subgrp, from))) {
d62a17ae 2174 subgroup_announce_reset_nhop(
2175 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2176 ? AF_INET6
2177 : p->family),
737af885 2178 attr);
7b651a32 2179 nh_reset = true;
2180 }
737af885
BS
2181
2182 if ((p->family == AF_INET6) &&
2183 (!bgp_subgrp_multiaccess_check_v6(
2184 piattr->mp_nexthop_global,
7b651a32 2185 subgrp, from))) {
737af885
BS
2186 subgroup_announce_reset_nhop(
2187 (peer_cap_enhe(peer, afi, safi)
2188 ? AF_INET6
2189 : p->family),
2190 attr);
7b651a32 2191 nh_reset = true;
2192 }
737af885
BS
2193
2194
2195
40381db7 2196 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2197 /*
2198 * This flag is used for leaked vpn-vrf routes
2199 */
2200 int family = p->family;
2201
2202 if (peer_cap_enhe(peer, afi, safi))
2203 family = AF_INET6;
2204
2205 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2206 zlog_debug(
1defdda8 2207 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2208 __func__, family2str(family));
2209 subgroup_announce_reset_nhop(family, attr);
7b651a32 2210 nh_reset = true;
d62a17ae 2211 }
63696f1d 2212 }
960035b2 2213
63696f1d 2214 /* If IPv6/MP and nexthop does not have any override and happens
2215 * to
2216 * be a link-local address, reset it so that we don't pass along
2217 * the
2218 * source's link-local IPv6 address to recipients who may not be
2219 * on
2220 * the same interface.
2221 */
2222 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2223 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2224 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2225 nh_reset = true;
2226 }
d62a17ae 2227 }
3f9c7369 2228
7b651a32 2229 /*
2230 * When the next hop is set to ourselves, if all multipaths have
2231 * link-bandwidth announce the cumulative bandwidth as that makes
2232 * the most sense. However, don't modify if the link-bandwidth has
2233 * been explicitly set by user policy.
2234 */
2235 if (nh_reset &&
f7e1c681 2236 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2237 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2238 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2239 attr->ecommunity = ecommunity_replace_linkbw(
2240 bgp->as, attr->ecommunity, cum_bw);
2241
3dc339cd 2242 return true;
3f9c7369
DS
2243}
2244
f009ff26 2245static int bgp_route_select_timer_expire(struct thread *thread)
2246{
2247 struct afi_safi_info *info;
2248 afi_t afi;
2249 safi_t safi;
2250 struct bgp *bgp;
2251
2252 info = THREAD_ARG(thread);
2253 afi = info->afi;
2254 safi = info->safi;
2255 bgp = info->bgp;
2256
2257 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2258 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2259 safi);
f009ff26 2260
2261 bgp->gr_info[afi][safi].t_route_select = NULL;
2262
2263 XFREE(MTYPE_TMP, info);
2264
2265 /* Best path selection */
2266 return bgp_best_path_select_defer(bgp, afi, safi);
2267}
2268
9bcb3eef 2269void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2270 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2271 struct bgp_path_info_pair *result, afi_t afi,
2272 safi_t safi)
2273{
2274 struct bgp_path_info *new_select;
2275 struct bgp_path_info *old_select;
40381db7
DS
2276 struct bgp_path_info *pi;
2277 struct bgp_path_info *pi1;
2278 struct bgp_path_info *pi2;
2279 struct bgp_path_info *nextpi = NULL;
d62a17ae 2280 int paths_eq, do_mpath, debug;
2281 struct list mp_list;
2282 char pfx_buf[PREFIX2STR_BUFFER];
2283 char path_buf[PATH_ADDPATH_STR_BUFFER];
2284
2285 bgp_mp_list_init(&mp_list);
2286 do_mpath =
2287 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2288
9bcb3eef 2289 debug = bgp_debug_bestpath(dest);
d62a17ae 2290
2291 if (debug)
9bcb3eef 2292 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2293
9bcb3eef 2294 dest->reason = bgp_path_selection_none;
d62a17ae 2295 /* bgp deterministic-med */
2296 new_select = NULL;
892fedb6 2297 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2298
1defdda8 2299 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2300 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2301 pi1 = pi1->next)
9bcb3eef 2302 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2303 BGP_PATH_DMED_SELECTED);
d62a17ae 2304
9bcb3eef 2305 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2306 pi1 = pi1->next) {
40381db7 2307 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2308 continue;
40381db7 2309 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2310 continue;
ea8b2282 2311 if (pi1->peer != bgp->peer_self)
40381db7 2312 if (pi1->peer->status != Established)
d62a17ae 2313 continue;
2314
40381db7
DS
2315 new_select = pi1;
2316 if (pi1->next) {
2317 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2318 if (CHECK_FLAG(pi2->flags,
1defdda8 2319 BGP_PATH_DMED_CHECK))
d62a17ae 2320 continue;
40381db7 2321 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2322 continue;
ea8b2282 2323 if (pi2->peer != bgp->peer_self
d62a17ae 2324 && !CHECK_FLAG(
ea8b2282
DS
2325 pi2->peer->sflags,
2326 PEER_STATUS_NSF_WAIT))
40381db7 2327 if (pi2->peer->status
d62a17ae 2328 != Established)
2329 continue;
2330
121e245d
DS
2331 if (!aspath_cmp_left(pi1->attr->aspath,
2332 pi2->attr->aspath)
2333 && !aspath_cmp_left_confed(
40381db7 2334 pi1->attr->aspath,
121e245d
DS
2335 pi2->attr->aspath))
2336 continue;
d62a17ae 2337
121e245d
DS
2338 if (bgp_path_info_cmp(
2339 bgp, pi2, new_select,
2340 &paths_eq, mpath_cfg, debug,
fdf81fa0 2341 pfx_buf, afi, safi,
9bcb3eef 2342 &dest->reason)) {
121e245d 2343 bgp_path_info_unset_flag(
9bcb3eef 2344 dest, new_select,
121e245d
DS
2345 BGP_PATH_DMED_SELECTED);
2346 new_select = pi2;
d62a17ae 2347 }
121e245d
DS
2348
2349 bgp_path_info_set_flag(
9bcb3eef 2350 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2351 }
2352 }
9bcb3eef 2353 bgp_path_info_set_flag(dest, new_select,
18ee8310 2354 BGP_PATH_DMED_CHECK);
9bcb3eef 2355 bgp_path_info_set_flag(dest, new_select,
18ee8310 2356 BGP_PATH_DMED_SELECTED);
d62a17ae 2357
2358 if (debug) {
18ee8310 2359 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2360 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2361 zlog_debug(
2362 "%pBD: %s is the bestpath from AS %u",
2363 dest, path_buf,
2364 aspath_get_first_as(
2365 new_select->attr->aspath));
d62a17ae 2366 }
2367 }
2368 }
96450faf 2369
d62a17ae 2370 /* Check old selected route and new selected route. */
2371 old_select = NULL;
2372 new_select = NULL;
9bcb3eef 2373 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2374 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2375 enum bgp_path_selection_reason reason;
2376
40381db7
DS
2377 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2378 old_select = pi;
d62a17ae 2379
40381db7 2380 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2381 /* reap REMOVED routes, if needs be
2382 * selected route must stay for a while longer though
2383 */
40381db7
DS
2384 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2385 && (pi != old_select))
9bcb3eef 2386 bgp_path_info_reap(dest, pi);
d62a17ae 2387
ddb5b488 2388 if (debug)
40381db7
DS
2389 zlog_debug("%s: pi %p in holddown", __func__,
2390 pi);
ddb5b488 2391
d62a17ae 2392 continue;
2393 }
96450faf 2394
40381db7
DS
2395 if (pi->peer && pi->peer != bgp->peer_self
2396 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2397 if (pi->peer->status != Established) {
ddb5b488
PZ
2398
2399 if (debug)
2400 zlog_debug(
40381db7
DS
2401 "%s: pi %p non self peer %s not estab state",
2402 __func__, pi, pi->peer->host);
ddb5b488 2403
d62a17ae 2404 continue;
ddb5b488 2405 }
9fbdd100 2406
892fedb6 2407 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2408 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2409 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2410 if (debug)
40381db7 2411 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2412 continue;
2413 }
9fbdd100 2414
9bcb3eef 2415 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2416
9bcb3eef 2417 reason = dest->reason;
40381db7 2418 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2419 debug, pfx_buf, afi, safi,
2420 &dest->reason)) {
19ea4cec
DS
2421 if (new_select == NULL &&
2422 reason != bgp_path_selection_none)
9bcb3eef 2423 dest->reason = reason;
40381db7 2424 new_select = pi;
d62a17ae 2425 }
2426 }
718e3744 2427
d62a17ae 2428 /* Now that we know which path is the bestpath see if any of the other
2429 * paths
2430 * qualify as multipaths
2431 */
2432 if (debug) {
2433 if (new_select)
7533cad7
QY
2434 bgp_path_info_path_with_addpath_rx_str(
2435 new_select, path_buf, sizeof(path_buf));
d62a17ae 2436 else
772270f3 2437 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2438 zlog_debug(
8228a9a7
DS
2439 "%pBD: After path selection, newbest is %s oldbest was %s",
2440 dest, path_buf,
d62a17ae 2441 old_select ? old_select->peer->host : "NONE");
96450faf 2442 }
9fbdd100 2443
d62a17ae 2444 if (do_mpath && new_select) {
9bcb3eef 2445 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2446 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2447
2448 if (debug)
18ee8310 2449 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2450 pi, path_buf, sizeof(path_buf));
d62a17ae 2451
40381db7 2452 if (pi == new_select) {
d62a17ae 2453 if (debug)
2454 zlog_debug(
8228a9a7
DS
2455 "%pBD: %s is the bestpath, add to the multipath list",
2456 dest, path_buf);
40381db7 2457 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2458 continue;
2459 }
2460
40381db7 2461 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2462 continue;
2463
40381db7
DS
2464 if (pi->peer && pi->peer != bgp->peer_self
2465 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2466 PEER_STATUS_NSF_WAIT))
40381db7 2467 if (pi->peer->status != Established)
d62a17ae 2468 continue;
2469
40381db7 2470 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2471 if (debug)
2472 zlog_debug(
8228a9a7
DS
2473 "%pBD: %s has the same nexthop as the bestpath, skip it",
2474 dest, path_buf);
d62a17ae 2475 continue;
2476 }
2477
40381db7 2478 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2479 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2480 &dest->reason);
d62a17ae 2481
2482 if (paths_eq) {
2483 if (debug)
2484 zlog_debug(
8228a9a7
DS
2485 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2486 dest, path_buf);
40381db7 2487 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2488 }
2489 }
2490 }
fee0f4c6 2491
9bcb3eef 2492 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2493 mpath_cfg);
2494 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2495 bgp_mp_list_clear(&mp_list);
96450faf 2496
9bcb3eef 2497 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2498
d62a17ae 2499 result->old = old_select;
2500 result->new = new_select;
96450faf 2501
d62a17ae 2502 return;
fee0f4c6 2503}
2504
3f9c7369
DS
2505/*
2506 * A new route/change in bestpath of an existing route. Evaluate the path
2507 * for advertisement to the subgroup.
2508 */
3dc339cd
DA
2509void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2510 struct bgp_path_info *selected,
9bcb3eef 2511 struct bgp_dest *dest,
3dc339cd 2512 uint32_t addpath_tx_id)
d62a17ae 2513{
b54892e0 2514 const struct prefix *p;
d62a17ae 2515 struct peer *onlypeer;
2516 struct attr attr;
2517 afi_t afi;
2518 safi_t safi;
a77e2f4b
S
2519 struct bgp *bgp;
2520 bool advertise;
adbac85e 2521
9bcb3eef 2522 p = bgp_dest_get_prefix(dest);
d62a17ae 2523 afi = SUBGRP_AFI(subgrp);
2524 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2525 bgp = SUBGRP_INST(subgrp);
d62a17ae 2526 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2527 : NULL);
2528
2dbe669b
DA
2529 if (BGP_DEBUG(update, UPDATE_OUT))
2530 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2531
d62a17ae 2532 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2533 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2534 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2535 return;
d62a17ae 2536
2537 memset(&attr, 0, sizeof(struct attr));
2538 /* It's initialized in bgp_announce_check() */
2539
a77e2f4b
S
2540 /* Announcement to the subgroup. If the route is filtered withdraw it.
2541 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2542 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2543 * route
d62a17ae 2544 */
a77e2f4b
S
2545 advertise = bgp_check_advertise(bgp, dest);
2546
d62a17ae 2547 if (selected) {
7f7940e6 2548 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2549 false)) {
2550 /* Route is selected, if the route is already installed
2551 * in FIB, then it is advertised
2552 */
2553 if (advertise)
2554 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2555 selected);
2556 } else
9bcb3eef 2557 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2558 addpath_tx_id);
d62a17ae 2559 }
2560
2561 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2562 else {
9bcb3eef 2563 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2564 }
200df115 2565}
fee0f4c6 2566
3064bf43 2567/*
e1072051 2568 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2569 * This is called at the end of route processing.
3064bf43 2570 */
9bcb3eef 2571void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2572{
40381db7 2573 struct bgp_path_info *pi;
3064bf43 2574
9bcb3eef 2575 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2576 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2577 continue;
40381db7
DS
2578 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2579 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2580 }
3064bf43 2581}
2582
2583/*
2584 * Has the route changed from the RIB's perspective? This is invoked only
2585 * if the route selection returns the same best route as earlier - to
2586 * determine if we need to update zebra or not.
2587 */
9bcb3eef 2588bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2589{
4b7e6066 2590 struct bgp_path_info *mpinfo;
d62a17ae 2591
2bb9eff4
DS
2592 /* If this is multipath, check all selected paths for any nexthop
2593 * change or attribute change. Some attribute changes (e.g., community)
2594 * aren't of relevance to the RIB, but we'll update zebra to ensure
2595 * we handle the case of BGP nexthop change. This is the behavior
2596 * when the best path has an attribute change anyway.
d62a17ae 2597 */
1defdda8 2598 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2599 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2600 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2601 return true;
d62a17ae 2602
2bb9eff4
DS
2603 /*
2604 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2605 */
18ee8310
DS
2606 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2607 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2608 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2609 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2610 return true;
d62a17ae 2611 }
3064bf43 2612
d62a17ae 2613 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2614 return false;
3064bf43 2615}
2616
d62a17ae 2617struct bgp_process_queue {
2618 struct bgp *bgp;
9bcb3eef 2619 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2620#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2621 unsigned int flags;
2622 unsigned int queued;
200df115 2623};
2624
3b0c17e1 2625static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2626 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2627 struct bgp_path_info *new_select,
2628 struct bgp_path_info *old_select)
2629{
9bcb3eef 2630 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2631
2632 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2633 return;
2634
2635 if (advertise_type5_routes(bgp, afi) && new_select
2636 && is_route_injectable_into_evpn(new_select)) {
2637
2638 /* apply the route-map */
2639 if (bgp->adv_cmd_rmap[afi][safi].map) {
2640 route_map_result_t ret;
2641 struct bgp_path_info rmap_path;
2642 struct bgp_path_info_extra rmap_path_extra;
2643 struct attr dummy_attr;
2644
2645 dummy_attr = *new_select->attr;
2646
2647 /* Fill temp path_info */
9bcb3eef 2648 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2649 new_select, new_select->peer,
2650 &dummy_attr);
2651
2652 RESET_FLAG(dummy_attr.rmap_change_flags);
2653
2654 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2655 p, &rmap_path);
3b0c17e1 2656
2657 if (ret == RMAP_DENYMATCH) {
2658 bgp_attr_flush(&dummy_attr);
2659 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2660 safi);
2661 } else
2662 bgp_evpn_advertise_type5_route(
2663 bgp, p, &dummy_attr, afi, safi);
2664 } else {
2665 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2666 afi, safi);
2667 }
2668 } else if (advertise_type5_routes(bgp, afi) && old_select
2669 && is_route_injectable_into_evpn(old_select))
2670 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2671}
2672
3103e8d2
DS
2673/*
2674 * old_select = The old best path
2675 * new_select = the new best path
2676 *
2677 * if (!old_select && new_select)
2678 * We are sending new information on.
2679 *
2680 * if (old_select && new_select) {
2681 * if (new_select != old_select)
2682 * We have a new best path send a change
2683 * else
2684 * We've received a update with new attributes that needs
2685 * to be passed on.
2686 * }
2687 *
2688 * if (old_select && !new_select)
2689 * We have no eligible route that we can announce or the rn
2690 * is being removed.
2691 */
9bcb3eef 2692static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2693 afi_t afi, safi_t safi)
d62a17ae 2694{
4b7e6066
DS
2695 struct bgp_path_info *new_select;
2696 struct bgp_path_info *old_select;
2697 struct bgp_path_info_pair old_and_new;
ddb5b488 2698 int debug = 0;
d62a17ae 2699
892fedb6 2700 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2701 if (dest)
2702 debug = bgp_debug_bestpath(dest);
b54892e0 2703 if (debug)
f4c713ae 2704 zlog_debug(
56ca3b5b 2705 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2706 __func__, dest);
f4c713ae
LB
2707 return;
2708 }
d62a17ae 2709 /* Is it end of initial update? (after startup) */
9bcb3eef 2710 if (!dest) {
d62a17ae 2711 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2712 sizeof(bgp->update_delay_zebra_resume_time));
2713
2714 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2715 FOREACH_AFI_SAFI (afi, safi) {
2716 if (bgp_fibupd_safi(safi))
2717 bgp_zebra_announce_table(bgp, afi, safi);
2718 }
d62a17ae 2719 bgp->main_peers_update_hold = 0;
2720
2721 bgp_start_routeadv(bgp);
aac24838 2722 return;
d62a17ae 2723 }
cb1faec9 2724
9bcb3eef 2725 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2726
9bcb3eef 2727 debug = bgp_debug_bestpath(dest);
b54892e0 2728 if (debug)
56ca3b5b 2729 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2730 afi2str(afi), safi2str(safi));
ddb5b488 2731
f009ff26 2732 /* The best path calculation for the route is deferred if
2733 * BGP_NODE_SELECT_DEFER is set
2734 */
9bcb3eef 2735 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2736 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2737 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2738 return;
2739 }
2740
d62a17ae 2741 /* Best path selection. */
9bcb3eef 2742 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2743 afi, safi);
2744 old_select = old_and_new.old;
2745 new_select = old_and_new.new;
2746
2747 /* Do we need to allocate or free labels?
2748 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2749 * necessary to do this upon changes to best path. Exceptions:
2750 * - label index has changed -> recalculate resulting label
2751 * - path_info sub_type changed -> switch to/from implicit-null
2752 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2753 */
318cac96 2754 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2755 if (new_select) {
2756 if (!old_select
2757 || bgp_label_index_differs(new_select, old_select)
57592a53 2758 || new_select->sub_type != old_select->sub_type
9bcb3eef 2759 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2760 /* Enforced penultimate hop popping:
2761 * implicit-null for local routes, aggregate
2762 * and redistributed routes
2763 */
d62a17ae 2764 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2765 || new_select->sub_type
2766 == BGP_ROUTE_AGGREGATE
2767 || new_select->sub_type
2768 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2769 if (CHECK_FLAG(
9bcb3eef 2770 dest->flags,
992dd67e
PR
2771 BGP_NODE_REGISTERED_FOR_LABEL)
2772 || CHECK_FLAG(
2773 dest->flags,
2774 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2775 bgp_unregister_for_label(dest);
70e98a7f 2776 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2777 &dest->local_label);
2778 bgp_set_valid_label(&dest->local_label);
d62a17ae 2779 } else
9bcb3eef
DS
2780 bgp_register_for_label(dest,
2781 new_select);
d62a17ae 2782 }
9bcb3eef 2783 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2784 BGP_NODE_REGISTERED_FOR_LABEL)
2785 || CHECK_FLAG(dest->flags,
2786 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2787 bgp_unregister_for_label(dest);
318cac96 2788 }
992dd67e
PR
2789 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2790 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2791 bgp_unregister_for_label(dest);
d62a17ae 2792 }
cd1964ff 2793
b54892e0 2794 if (debug)
ddb5b488 2795 zlog_debug(
56ca3b5b 2796 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2797 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2798 old_select, new_select);
ddb5b488 2799
d62a17ae 2800 /* If best route remains the same and this is not due to user-initiated
2801 * clear, see exactly what needs to be done.
2802 */
d62a17ae 2803 if (old_select && old_select == new_select
9bcb3eef 2804 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2805 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2806 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2807 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2808#ifdef ENABLE_BGP_VNC
d62a17ae 2809 vnc_import_bgp_add_route(bgp, p, old_select);
2810 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2811#endif
bb744275 2812 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2813 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2814
2815 if (new_select->type == ZEBRA_ROUTE_BGP
2816 && (new_select->sub_type == BGP_ROUTE_NORMAL
2817 || new_select->sub_type
2818 == BGP_ROUTE_IMPORTED))
2819
9bcb3eef 2820 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2821 bgp, afi, safi);
2822 }
d62a17ae 2823 }
d62a17ae 2824
2825 /* If there is a change of interest to peers, reannounce the
2826 * route. */
1defdda8 2827 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2828 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2829 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2830 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2831
2832 /* unicast routes must also be annouced to
2833 * labeled-unicast update-groups */
2834 if (safi == SAFI_UNICAST)
2835 group_announce_route(bgp, afi,
9bcb3eef 2836 SAFI_LABELED_UNICAST, dest,
d62a17ae 2837 new_select);
2838
1defdda8 2839 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2840 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2841 }
fee0f4c6 2842
3b0c17e1 2843 /* advertise/withdraw type-5 routes */
2844 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2845 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2846 bgp_process_evpn_route_injection(
9bcb3eef 2847 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2848
b1875e65 2849 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2850 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2851 bgp_zebra_clear_route_change_flags(dest);
2852 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2853 return;
d62a17ae 2854 }
8ad7271d 2855
d62a17ae 2856 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2857 */
9bcb3eef 2858 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2859
2860 /* bestpath has changed; bump version */
2861 if (old_select || new_select) {
9bcb3eef 2862 bgp_bump_version(dest);
d62a17ae 2863
2864 if (!bgp->t_rmap_def_originate_eval) {
2865 bgp_lock(bgp);
2866 thread_add_timer(
2867 bm->master,
2868 update_group_refresh_default_originate_route_map,
2869 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2870 &bgp->t_rmap_def_originate_eval);
2871 }
2872 }
3f9c7369 2873
d62a17ae 2874 if (old_select)
9bcb3eef 2875 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2876 if (new_select) {
ddb5b488
PZ
2877 if (debug)
2878 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2879 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2880 bgp_path_info_unset_flag(dest, new_select,
2881 BGP_PATH_ATTR_CHANGED);
1defdda8 2882 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2883 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2884 }
338b3424 2885
49e5a4a0 2886#ifdef ENABLE_BGP_VNC
d62a17ae 2887 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2888 if (old_select != new_select) {
2889 if (old_select) {
2890 vnc_import_bgp_exterior_del_route(bgp, p,
2891 old_select);
2892 vnc_import_bgp_del_route(bgp, p, old_select);
2893 }
2894 if (new_select) {
2895 vnc_import_bgp_exterior_add_route(bgp, p,
2896 new_select);
2897 vnc_import_bgp_add_route(bgp, p, new_select);
2898 }
2899 }
2900 }
65efcfce
LB
2901#endif
2902
9bcb3eef 2903 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2904
2905 /* unicast routes must also be annouced to labeled-unicast update-groups
2906 */
2907 if (safi == SAFI_UNICAST)
9bcb3eef 2908 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2909 new_select);
2910
2911 /* FIB update. */
2912 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2913 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2914 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2915 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2916 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2917 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2918
2919 /* if this is an evpn imported type-5 prefix,
2920 * we need to withdraw the route first to clear
2921 * the nh neigh and the RMAC entry.
2922 */
2923 if (old_select &&
2924 is_route_parent_evpn(old_select))
2925 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2926
9bcb3eef 2927 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2928 } else {
d62a17ae 2929 /* Withdraw the route from the kernel. */
2930 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2931 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2932 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2933 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2934
568e10ca 2935 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2936 }
718e3744 2937 }
3064bf43 2938
9bcb3eef 2939 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2940 old_select);
5424b7ba 2941
d62a17ae 2942 /* Clear any route change flags. */
9bcb3eef 2943 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2944
18ee8310 2945 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2946 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2947 bgp_path_info_reap(dest, old_select);
d62a17ae 2948
9bcb3eef 2949 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2950 return;
718e3744 2951}
2952
f009ff26 2953/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2954int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2955{
9bcb3eef 2956 struct bgp_dest *dest;
f009ff26 2957 int cnt = 0;
2958 struct afi_safi_info *thread_info;
f009ff26 2959
56c226e7
DS
2960 if (bgp->gr_info[afi][safi].t_route_select) {
2961 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2962
2963 thread_info = THREAD_ARG(t);
2964 XFREE(MTYPE_TMP, thread_info);
f009ff26 2965 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2966 }
f009ff26 2967
2968 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2969 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2970 get_afi_safi_str(afi, safi, false),
26742171 2971 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2972 }
2973
2974 /* Process the route list */
6338d242
DS
2975 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2976 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2977 dest = bgp_route_next(dest)) {
2978 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2979 continue;
2980
2981 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2982 bgp->gr_info[afi][safi].gr_deferred--;
2983 bgp_process_main_one(bgp, dest, afi, safi);
2984 cnt++;
2985 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2986 bgp_dest_unlock_node(dest);
2987 break;
f009ff26 2988 }
f009ff26 2989 }
2990
9e3b51a7 2991 /* Send EOR message when all routes are processed */
6338d242 2992 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2993 bgp_send_delayed_eor(bgp);
8c48b3b6 2994 /* Send route processing complete message to RIB */
2995 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2996 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2997 return 0;
9e3b51a7 2998 }
f009ff26 2999
3000 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3001
3002 thread_info->afi = afi;
3003 thread_info->safi = safi;
3004 thread_info->bgp = bgp;
3005
3006 /* If there are more routes to be processed, start the
3007 * selection timer
3008 */
3009 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3010 BGP_ROUTE_SELECT_DELAY,
3011 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3012 return 0;
3013}
3014
aac24838 3015static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3016{
aac24838
JB
3017 struct bgp_process_queue *pqnode = data;
3018 struct bgp *bgp = pqnode->bgp;
d62a17ae 3019 struct bgp_table *table;
9bcb3eef 3020 struct bgp_dest *dest;
aac24838
JB
3021
3022 /* eoiu marker */
3023 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3024 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3025 /* should always have dedicated wq call */
3026 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3027 return WQ_SUCCESS;
3028 }
3029
ac021f40 3030 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3031 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3032 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3033 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3034 table = bgp_dest_table(dest);
3035 /* note, new DESTs may be added as part of processing */
3036 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3037
9bcb3eef 3038 bgp_dest_unlock_node(dest);
d62a17ae 3039 bgp_table_unlock(table);
3040 }
aac24838
JB
3041
3042 return WQ_SUCCESS;
3043}
3044
3045static void bgp_processq_del(struct work_queue *wq, void *data)
3046{
3047 struct bgp_process_queue *pqnode = data;
3048
3049 bgp_unlock(pqnode->bgp);
3050
3051 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3052}
3053
b6c386bb 3054void bgp_process_queue_init(struct bgp *bgp)
200df115 3055{
b6c386bb
DS
3056 if (!bgp->process_queue) {
3057 char name[BUFSIZ];
3058
3059 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3060 bgp->process_queue = work_queue_new(bm->master, name);
3061 }
3062
3063 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3064 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3065 bgp->process_queue->spec.max_retries = 0;
3066 bgp->process_queue->spec.hold = 50;
d62a17ae 3067 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3068 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3069}
3070
cfe8d15a 3071static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3072{
3073 struct bgp_process_queue *pqnode;
3074
a4d82a8a
PZ
3075 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3076 sizeof(struct bgp_process_queue));
aac24838
JB
3077
3078 /* unlocked in bgp_processq_del */
3079 pqnode->bgp = bgp_lock(bgp);
3080 STAILQ_INIT(&pqnode->pqueue);
3081
aac24838
JB
3082 return pqnode;
3083}
3084
9bcb3eef 3085void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3086{
aac24838 3087#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3088 struct work_queue *wq = bgp->process_queue;
d62a17ae 3089 struct bgp_process_queue *pqnode;
cfe8d15a 3090 int pqnode_reuse = 0;
495f0b13 3091
d62a17ae 3092 /* already scheduled for processing? */
9bcb3eef 3093 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3094 return;
2e02b9b2 3095
f009ff26 3096 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3097 * the workqueue
3098 */
9bcb3eef 3099 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3100 if (BGP_DEBUG(update, UPDATE_OUT))
3101 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3102 dest);
f009ff26 3103 return;
3104 }
3105
aac24838 3106 if (wq == NULL)
d62a17ae 3107 return;
3108
aac24838 3109 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3110 limit only if is from the same BGP view and it's not an EOIU marker
3111 */
aac24838
JB
3112 if (work_queue_item_count(wq)) {
3113 struct work_queue_item *item = work_queue_last_item(wq);
3114 pqnode = item->data;
228da428 3115
a4d82a8a
PZ
3116 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3117 || pqnode->bgp != bgp
3118 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3119 pqnode = bgp_processq_alloc(bgp);
3120 else
3121 pqnode_reuse = 1;
aac24838 3122 } else
cfe8d15a 3123 pqnode = bgp_processq_alloc(bgp);
aac24838 3124 /* all unlocked in bgp_process_wq */
9bcb3eef 3125 bgp_table_lock(bgp_dest_table(dest));
aac24838 3126
9bcb3eef
DS
3127 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3128 bgp_dest_lock_node(dest);
aac24838 3129
60466a63 3130 /* can't be enqueued twice */
9bcb3eef
DS
3131 assert(STAILQ_NEXT(dest, pq) == NULL);
3132 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3133 pqnode->queued++;
3134
cfe8d15a
LB
3135 if (!pqnode_reuse)
3136 work_queue_add(wq, pqnode);
3137
d62a17ae 3138 return;
fee0f4c6 3139}
0a486e5f 3140
d62a17ae 3141void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3142{
d62a17ae 3143 struct bgp_process_queue *pqnode;
cb1faec9 3144
b6c386bb 3145 if (bgp->process_queue == NULL)
d62a17ae 3146 return;
2e02b9b2 3147
cfe8d15a 3148 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3149
aac24838 3150 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3151 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3152}
3153
d62a17ae 3154static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3155{
d62a17ae 3156 struct peer *peer;
0a486e5f 3157
d62a17ae 3158 peer = THREAD_ARG(thread);
3159 peer->t_pmax_restart = NULL;
0a486e5f 3160
d62a17ae 3161 if (bgp_debug_neighbor_events(peer))
3162 zlog_debug(
3163 "%s Maximum-prefix restart timer expired, restore peering",
3164 peer->host);
0a486e5f 3165
a9bafa95 3166 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3167 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3168
d62a17ae 3169 return 0;
0a486e5f 3170}
3171
9cbd06e0
DA
3172static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3173 safi_t safi)
3174{
3175 uint32_t count = 0;
f41b0459 3176 bool filtered = false;
9cbd06e0
DA
3177 struct bgp_dest *dest;
3178 struct bgp_adj_in *ain;
40bb2ccf 3179 struct attr attr = {};
9cbd06e0
DA
3180 struct bgp_table *table = peer->bgp->rib[afi][safi];
3181
3182 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3183 for (ain = dest->adj_in; ain; ain = ain->next) {
3184 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3185
3186 attr = *ain->attr;
9cbd06e0
DA
3187
3188 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3189 == FILTER_DENY)
f41b0459
DA
3190 filtered = true;
3191
3192 if (bgp_input_modifier(
3193 peer, rn_p, &attr, afi, safi,
3194 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3195 NULL, 0, NULL)
3196 == RMAP_DENY)
3197 filtered = true;
3198
3199 if (filtered)
9cbd06e0 3200 count++;
f41b0459
DA
3201
3202 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3203 }
3204 }
3205
3206 return count;
3207}
3208
3dc339cd
DA
3209bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3210 int always)
718e3744 3211{
d62a17ae 3212 iana_afi_t pkt_afi;
5c525538 3213 iana_safi_t pkt_safi;
9cbd06e0
DA
3214 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3215 PEER_FLAG_MAX_PREFIX_FORCE))
3216 ? bgp_filtered_routes_count(peer, afi, safi)
3217 + peer->pcount[afi][safi]
3218 : peer->pcount[afi][safi];
9cabb64b 3219
d62a17ae 3220 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3221 return false;
e0701b79 3222
9cbd06e0 3223 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3224 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3225 PEER_STATUS_PREFIX_LIMIT)
3226 && !always)
3dc339cd 3227 return false;
e0701b79 3228
d62a17ae 3229 zlog_info(
6cde4b45 3230 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3231 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3232 peer->pmax[afi][safi]);
d62a17ae 3233 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3234
3235 if (CHECK_FLAG(peer->af_flags[afi][safi],
3236 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3237 return false;
d62a17ae 3238
3239 /* Convert AFI, SAFI to values for packet. */
3240 pkt_afi = afi_int2iana(afi);
3241 pkt_safi = safi_int2iana(safi);
3242 {
d7c0a89a 3243 uint8_t ndata[7];
d62a17ae 3244
3245 ndata[0] = (pkt_afi >> 8);
3246 ndata[1] = pkt_afi;
3247 ndata[2] = pkt_safi;
3248 ndata[3] = (peer->pmax[afi][safi] >> 24);
3249 ndata[4] = (peer->pmax[afi][safi] >> 16);
3250 ndata[5] = (peer->pmax[afi][safi] >> 8);
3251 ndata[6] = (peer->pmax[afi][safi]);
3252
3253 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3254 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3255 BGP_NOTIFY_CEASE_MAX_PREFIX,
3256 ndata, 7);
3257 }
3258
3259 /* Dynamic peers will just close their connection. */
3260 if (peer_dynamic_neighbor(peer))
3dc339cd 3261 return true;
d62a17ae 3262
3263 /* restart timer start */
3264 if (peer->pmax_restart[afi][safi]) {
3265 peer->v_pmax_restart =
3266 peer->pmax_restart[afi][safi] * 60;
3267
3268 if (bgp_debug_neighbor_events(peer))
3269 zlog_debug(
3270 "%s Maximum-prefix restart timer started for %d secs",
3271 peer->host, peer->v_pmax_restart);
3272
3273 BGP_TIMER_ON(peer->t_pmax_restart,
3274 bgp_maximum_prefix_restart_timer,
3275 peer->v_pmax_restart);
3276 }
3277
3dc339cd 3278 return true;
d62a17ae 3279 } else
3280 UNSET_FLAG(peer->af_sflags[afi][safi],
3281 PEER_STATUS_PREFIX_LIMIT);
3282
b1823b69
DS
3283 if (pcount
3284 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3285 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3286 PEER_STATUS_PREFIX_THRESHOLD)
3287 && !always)
3dc339cd 3288 return false;
d62a17ae 3289
3290 zlog_info(
6cde4b45 3291 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3292 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3293 peer->pmax[afi][safi]);
d62a17ae 3294 SET_FLAG(peer->af_sflags[afi][safi],
3295 PEER_STATUS_PREFIX_THRESHOLD);
3296 } else
3297 UNSET_FLAG(peer->af_sflags[afi][safi],
3298 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3299 return false;
718e3744 3300}
3301
b40d939b 3302/* Unconditionally remove the route from the RIB, without taking
3303 * damping into consideration (eg, because the session went down)
3304 */
9bcb3eef 3305void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3306 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3307{
f009ff26 3308
3309 struct bgp *bgp = NULL;
3310 bool delete_route = false;
3311
9bcb3eef
DS
3312 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3313 safi);
d62a17ae 3314
f009ff26 3315 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3316 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3317
f009ff26 3318 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3319 * flag
3320 */
3321 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3322 delete_route = true;
9bcb3eef 3323 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3324 delete_route = true;
f009ff26 3325 if (delete_route) {
9bcb3eef
DS
3326 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3327 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3328 bgp = pi->peer->bgp;
26742171 3329 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3330 }
3331 }
3332 }
4a11bf2c 3333
9bcb3eef
DS
3334 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3335 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3336}
3337
9bcb3eef 3338static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3339 struct peer *peer, afi_t afi, safi_t safi,
3340 struct prefix_rd *prd)
3341{
9bcb3eef 3342 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3343
d62a17ae 3344 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3345 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3346 */
40ec3340
DS
3347 if (peer->sort == BGP_PEER_EBGP) {
3348 if (get_active_bdc_from_pi(pi, afi, safi)) {
3349 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3350 == BGP_DAMP_SUPPRESSED) {
3351 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3352 safi);
3353 return;
3354 }
d62a17ae 3355 }
40ec3340 3356 }
d62a17ae 3357
49e5a4a0 3358#ifdef ENABLE_BGP_VNC
d62a17ae 3359 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3360 struct bgp_dest *pdest = NULL;
d62a17ae 3361 struct bgp_table *table = NULL;
3362
9bcb3eef
DS
3363 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3364 (struct prefix *)prd);
3365 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3366 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3367
3368 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3369 peer->bgp, prd, table, p, pi);
d62a17ae 3370 }
9bcb3eef 3371 bgp_dest_unlock_node(pdest);
d62a17ae 3372 }
3373 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3374 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3375
b54892e0
DS
3376 vnc_import_bgp_del_route(peer->bgp, p, pi);
3377 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3378 }
65efcfce 3379 }
d62a17ae 3380#endif
128ea8ab 3381
d62a17ae 3382 /* If this is an EVPN route, process for un-import. */
3383 if (safi == SAFI_EVPN)
b54892e0 3384 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3385
9bcb3eef 3386 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3387}
3388
4b7e6066
DS
3389struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3390 struct peer *peer, struct attr *attr,
9bcb3eef 3391 struct bgp_dest *dest)
fb018d25 3392{
4b7e6066 3393 struct bgp_path_info *new;
fb018d25 3394
d62a17ae 3395 /* Make new BGP info. */
4b7e6066 3396 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3397 new->type = type;
3398 new->instance = instance;
3399 new->sub_type = sub_type;
3400 new->peer = peer;
3401 new->attr = attr;
3402 new->uptime = bgp_clock();
9bcb3eef 3403 new->net = dest;
d62a17ae 3404 return new;
fb018d25
DS
3405}
3406
d62a17ae 3407static void overlay_index_update(struct attr *attr,
d62a17ae 3408 union gw_addr *gw_ip)
684a7227 3409{
d62a17ae 3410 if (!attr)
3411 return;
d62a17ae 3412 if (gw_ip == NULL) {
6c924775
DS
3413 struct bgp_route_evpn eo;
3414
3415 memset(&eo, 0, sizeof(eo));
3416 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3417 } else {
6c924775
DS
3418 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3419
3420 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3421 }
684a7227
PG
3422}
3423
40381db7 3424static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3425 union gw_addr *gw_ip)
3426{
6c924775
DS
3427 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3428 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3429 union {
0a50c248 3430 esi_t esi;
11ebf4ed
DS
3431 union gw_addr ip;
3432 } temp;
d62a17ae 3433
3434 if (afi != AFI_L2VPN)
3435 return true;
11ebf4ed 3436
6c924775 3437 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3438
3439 if (gw_ip == NULL) {
3440 memset(&temp, 0, sizeof(temp));
40381db7 3441 path_gw_ip_remote = &temp.ip;
11ebf4ed 3442 } else
40381db7 3443 path_gw_ip_remote = gw_ip;
11ebf4ed 3444
6c924775 3445 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3446}
3447
c265ee22 3448/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3449bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3450 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3451 struct bgp_dest *dest)
d62a17ae 3452{
2dbe3fa9 3453 bool ret = false;
b099a5c8
DA
3454 bool is_bgp_static_route =
3455 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3456 : false;
d62a17ae 3457
e8442016
DS
3458 /*
3459 * Only validated for unicast and multicast currently.
3460 * Also valid for EVPN where the nexthop is an IP address.
3461 * If we are a bgp static route being checked then there is
3462 * no need to check to see if the nexthop is martian as
3463 * that it should be ok.
3464 */
3465 if (is_bgp_static_route ||
3466 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3467 return false;
d62a17ae 3468
3469 /* If NEXT_HOP is present, validate it. */
3470 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3471 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3472 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3473 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3474 return true;
d62a17ae 3475 }
c265ee22 3476
d62a17ae 3477 /* If MP_NEXTHOP is present, validate it. */
3478 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3479 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3480 * it is not an IPv6 link-local address.
0355b41d
DA
3481 *
3482 * If we receive an UPDATE with nexthop length set to 32 bytes
3483 * we shouldn't discard an UPDATE if it's set to (::).
3484 * The link-local (2st) is validated along the code path later.
d62a17ae 3485 */
3486 if (attr->mp_nexthop_len) {
3487 switch (attr->mp_nexthop_len) {
3488 case BGP_ATTR_NHLEN_IPV4:
3489 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3490 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3491 || IPV4_CLASS_DE(
3492 ntohl(attr->mp_nexthop_global_in.s_addr))
3493 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3494 dest));
d62a17ae 3495 break;
3496
3497 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3498 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3499 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3500 &attr->mp_nexthop_global)
d62a17ae 3501 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3502 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3503 &attr->mp_nexthop_global)
3504 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3505 dest));
d62a17ae 3506 break;
0355b41d
DA
3507 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3508 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3509 || IN6_IS_ADDR_MULTICAST(
3510 &attr->mp_nexthop_global)
3511 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3512 dest));
0355b41d 3513 break;
d62a17ae 3514
3515 default:
3dc339cd 3516 ret = true;
d62a17ae 3517 break;
3518 }
3519 }
c265ee22 3520
d62a17ae 3521 return ret;
3522}
3523
aade37d7 3524static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3525{
3526 struct community *old;
3527 struct community *new;
3528 struct community *merge;
aade37d7 3529 struct community *no_export;
2721dd61
DA
3530
3531 old = attr->community;
aade37d7 3532 no_export = community_str2com("no-export");
2721dd61 3533
b4efa101
DA
3534 assert(no_export);
3535
2721dd61 3536 if (old) {
aade37d7 3537 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3538
3539 if (!old->refcnt)
3540 community_free(&old);
3541
3542 new = community_uniq_sort(merge);
3543 community_free(&merge);
3544 } else {
aade37d7 3545 new = community_dup(no_export);
2721dd61
DA
3546 }
3547
aade37d7 3548 community_free(&no_export);
2721dd61
DA
3549
3550 attr->community = new;
3551 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3552}
3553
5a1ae2c2 3554int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3555 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3556 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3557 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3558 struct bgp_route_evpn *evpn)
d62a17ae 3559{
3560 int ret;
3561 int aspath_loop_count = 0;
9bcb3eef 3562 struct bgp_dest *dest;
d62a17ae 3563 struct bgp *bgp;
3564 struct attr new_attr;
3565 struct attr *attr_new;
40381db7 3566 struct bgp_path_info *pi;
4b7e6066
DS
3567 struct bgp_path_info *new;
3568 struct bgp_path_info_extra *extra;
d62a17ae 3569 const char *reason;
3570 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3571 int connected = 0;
3572 int do_loop_check = 1;
3573 int has_valid_label = 0;
7c312383 3574 afi_t nh_afi;
949b0f24 3575 uint8_t pi_type = 0;
3576 uint8_t pi_sub_type = 0;
3577
c7bb4f00 3578 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3579 char pfxprint[PREFIX2STR_BUFFER];
3580
3581 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3582 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3583 afi, safi, attr);
6401252f
QY
3584 }
3585
49e5a4a0 3586#ifdef ENABLE_BGP_VNC
d62a17ae 3587 int vnc_implicit_withdraw = 0;
65efcfce 3588#endif
d62a17ae 3589 int same_attr = 0;
718e3744 3590
d62a17ae 3591 memset(&new_attr, 0, sizeof(struct attr));
3592 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3593 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3594
d62a17ae 3595 bgp = peer->bgp;
9bcb3eef 3596 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3597 /* TODO: Check to see if we can get rid of "is_valid_label" */
3598 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3599 has_valid_label = (num_labels > 0) ? 1 : 0;
3600 else
3601 has_valid_label = bgp_is_valid_label(label);
718e3744 3602
28f66de2
MS
3603 if (has_valid_label)
3604 assert(label != NULL);
3605
d62a17ae 3606 /* When peer's soft reconfiguration enabled. Record input packet in
3607 Adj-RIBs-In. */
3608 if (!soft_reconfig
3609 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3610 && peer != bgp->peer_self)
9bcb3eef 3611 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3612
3613 /* Check previously received route. */
9bcb3eef 3614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3615 if (pi->peer == peer && pi->type == type
3616 && pi->sub_type == sub_type
3617 && pi->addpath_rx_id == addpath_id)
d62a17ae 3618 break;
3619
3620 /* AS path local-as loop check. */
3621 if (peer->change_local_as) {
c4368918
DW
3622 if (peer->allowas_in[afi][safi])
3623 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3624 else if (!CHECK_FLAG(peer->flags,
3625 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3626 aspath_loop_count = 1;
3627
3628 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3629 > aspath_loop_count) {
b4d46cc9 3630 peer->stat_pfx_aspath_loop++;
9bcb3eef 3631 reason = "as-path contains our own AS A;";
d62a17ae 3632 goto filtered;
3633 }
718e3744 3634 }
718e3744 3635
d62a17ae 3636 /* If the peer is configured for "allowas-in origin" and the last ASN in
3637 * the
3638 * as-path is our ASN then we do not need to call aspath_loop_check
3639 */
3640 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3641 if (aspath_get_last_as(attr->aspath) == bgp->as)
3642 do_loop_check = 0;
3643
3644 /* AS path loop check. */
3645 if (do_loop_check) {
3646 if (aspath_loop_check(attr->aspath, bgp->as)
3647 > peer->allowas_in[afi][safi]
3648 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3649 && aspath_loop_check(attr->aspath, bgp->confed_id)
3650 > peer->allowas_in[afi][safi])) {
b4d46cc9 3651 peer->stat_pfx_aspath_loop++;
d62a17ae 3652 reason = "as-path contains our own AS;";
3653 goto filtered;
3654 }
3655 }
aac9ef6c 3656
d62a17ae 3657 /* Route reflector originator ID check. */
3658 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3659 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3660 peer->stat_pfx_originator_loop++;
d62a17ae 3661 reason = "originator is us;";
3662 goto filtered;
3663 }
718e3744 3664
d62a17ae 3665 /* Route reflector cluster ID check. */
3666 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3667 peer->stat_pfx_cluster_loop++;
d62a17ae 3668 reason = "reflected from the same cluster;";
3669 goto filtered;
3670 }
718e3744 3671
d62a17ae 3672 /* Apply incoming filter. */
3673 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3674 peer->stat_pfx_filter++;
d62a17ae 3675 reason = "filter;";
3676 goto filtered;
3677 }
718e3744 3678
a8b72dc6
DA
3679 /* RFC 8212 to prevent route leaks.
3680 * This specification intends to improve this situation by requiring the
3681 * explicit configuration of both BGP Import and Export Policies for any
3682 * External BGP (EBGP) session such as customers, peers, or
3683 * confederation boundaries for all enabled address families. Through
3684 * codification of the aforementioned requirement, operators will
3685 * benefit from consistent behavior across different BGP
3686 * implementations.
3687 */
1d3fdccf 3688 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3689 if (!bgp_inbound_policy_exists(peer,
3690 &peer->filter[afi][safi])) {
3691 reason = "inbound policy missing";
3692 goto filtered;
3693 }
3694
fb29348a
DA
3695 /* draft-ietf-idr-deprecate-as-set-confed-set
3696 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3697 * Eventually, This document (if approved) updates RFC 4271
3698 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3699 * and obsoletes RFC 6472.
3700 */
7f972cd8 3701 if (peer->bgp->reject_as_sets)
fb29348a
DA
3702 if (aspath_check_as_sets(attr->aspath)) {
3703 reason =
3704 "as-path contains AS_SET or AS_CONFED_SET type;";
3705 goto filtered;
3706 }
3707
6f4f49b2 3708 new_attr = *attr;
d62a17ae 3709
3710 /* Apply incoming route-map.
3711 * NB: new_attr may now contain newly allocated values from route-map
3712 * "set"
3713 * commands, so we need bgp_attr_flush in the error paths, until we
3714 * intern
3715 * the attr (which takes over the memory references) */
9bcb3eef
DS
3716 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3717 num_labels, dest)
3718 == RMAP_DENY) {
b4d46cc9 3719 peer->stat_pfx_filter++;
d62a17ae 3720 reason = "route-map;";
3721 bgp_attr_flush(&new_attr);
3722 goto filtered;
3723 }
718e3744 3724
05864da7 3725 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3726 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3727 /* remove from RIB previous entry */
3728 bgp_zebra_withdraw(p, pi, bgp, safi);
3729 }
3730
7f323236
DW
3731 if (peer->sort == BGP_PEER_EBGP) {
3732
2721dd61
DA
3733 /* rfc7999:
3734 * A BGP speaker receiving an announcement tagged with the
3735 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3736 * NO_EXPORT community as defined in RFC1997, or a
3737 * similar community, to prevent propagation of the
3738 * prefix outside the local AS. The community to prevent
3739 * propagation SHOULD be chosen according to the operator's
3740 * routing policy.
3741 */
3742 if (new_attr.community
3743 && community_include(new_attr.community,
3744 COMMUNITY_BLACKHOLE))
aade37d7 3745 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3746
a4d82a8a
PZ
3747 /* If we receive the graceful-shutdown community from an eBGP
3748 * peer we must lower local-preference */
3749 if (new_attr.community
3750 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3751 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3752 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3753
a4d82a8a
PZ
3754 /* If graceful-shutdown is configured then add the GSHUT
3755 * community to all paths received from eBGP peers */
637e5ba4 3756 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3757 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3758 }
3759
949b0f24 3760 if (pi) {
3761 pi_type = pi->type;
3762 pi_sub_type = pi->sub_type;
3763 }
3764
d62a17ae 3765 /* next hop check. */
a4d82a8a 3766 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3767 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3768 &new_attr, dest)) {
b4d46cc9 3769 peer->stat_pfx_nh_invalid++;
d62a17ae 3770 reason = "martian or self next-hop;";
3771 bgp_attr_flush(&new_attr);
3772 goto filtered;
3773 }
718e3744 3774
5c14a191 3775 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3776 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3777 reason = "self mac;";
3778 goto filtered;
3779 }
3780
1e9be514
QY
3781 /* Update Overlay Index */
3782 if (afi == AFI_L2VPN) {
3783 overlay_index_update(&new_attr,
3784 evpn == NULL ? NULL : &evpn->gw_ip);
3785 }
3786
a1b773e2
DS
3787 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3788 * condition :
3789 * Suppress fib is enabled
3790 * BGP_OPT_NO_FIB is not enabled
3791 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3792 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3793 */
3794 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3795 && (sub_type == BGP_ROUTE_NORMAL)
3796 && (!bgp_option_check(BGP_OPT_NO_FIB))
3797 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3798 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3799
d62a17ae 3800 attr_new = bgp_attr_intern(&new_attr);
3801
9cbd06e0
DA
3802 /* If maximum prefix count is configured and current prefix
3803 * count exeed it.
3804 */
3805 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3806 return -1;
3807
d62a17ae 3808 /* If the update is implicit withdraw. */
40381db7
DS
3809 if (pi) {
3810 pi->uptime = bgp_clock();
3811 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3812
9bcb3eef 3813 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3814
d62a17ae 3815 /* Same attribute comes in. */
40381db7 3816 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3817 && same_attr
d62a17ae 3818 && (!has_valid_label
40381db7 3819 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3820 num_labels * sizeof(mpls_label_t))
d62a17ae 3821 == 0)
3822 && (overlay_index_equal(
0a50c248 3823 afi, pi,
d62a17ae 3824 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3825 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3826 && peer->sort == BGP_PEER_EBGP
40381db7 3827 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3828 if (bgp_debug_update(peer, p, NULL, 1)) {
3829 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3830 afi, safi, prd, p, label,
3831 num_labels, addpath_id ? 1 : 0,
3832 addpath_id, pfx_buf,
3833 sizeof(pfx_buf));
d62a17ae 3834 zlog_debug("%s rcvd %s", peer->host,
3835 pfx_buf);
3836 }
3837
9bcb3eef 3838 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3839 != BGP_DAMP_SUPPRESSED) {
40381db7 3840 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3841 safi);
9bcb3eef 3842 bgp_process(bgp, dest, afi, safi);
d62a17ae 3843 }
3844 } else /* Duplicate - odd */
3845 {
3846 if (bgp_debug_update(peer, p, NULL, 1)) {
3847 if (!peer->rcvd_attr_printed) {
3848 zlog_debug(
3849 "%s rcvd UPDATE w/ attr: %s",
3850 peer->host,
3851 peer->rcvd_attr_str);
3852 peer->rcvd_attr_printed = 1;
3853 }
3854
3855 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3856 afi, safi, prd, p, label,
3857 num_labels, addpath_id ? 1 : 0,
3858 addpath_id, pfx_buf,
3859 sizeof(pfx_buf));
d62a17ae 3860 zlog_debug(
3861 "%s rcvd %s...duplicate ignored",
3862 peer->host, pfx_buf);
3863 }
3864
3865 /* graceful restart STALE flag unset. */
40381db7 3866 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3867 bgp_path_info_unset_flag(
9bcb3eef
DS
3868 dest, pi, BGP_PATH_STALE);
3869 bgp_dest_set_defer_flag(dest, false);
3870 bgp_process(bgp, dest, afi, safi);
d62a17ae 3871 }
3872 }
3873
9bcb3eef 3874 bgp_dest_unlock_node(dest);
d62a17ae 3875 bgp_attr_unintern(&attr_new);
3876
3877 return 0;
3878 }
718e3744 3879
d62a17ae 3880 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3881 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3882 if (bgp_debug_update(peer, p, NULL, 1)) {
3883 bgp_debug_rdpfxpath2str(
a4d82a8a 3884 afi, safi, prd, p, label, num_labels,
d62a17ae 3885 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3886 sizeof(pfx_buf));
3887 zlog_debug(
3888 "%s rcvd %s, flapped quicker than processing",
3889 peer->host, pfx_buf);
3890 }
3891
9bcb3eef 3892 bgp_path_info_restore(dest, pi);
d62a17ae 3893 }
718e3744 3894
d62a17ae 3895 /* Received Logging. */
3896 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3897 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3898 num_labels, addpath_id ? 1 : 0,
3899 addpath_id, pfx_buf,
3900 sizeof(pfx_buf));
d62a17ae 3901 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3902 }
718e3744 3903
d62a17ae 3904 /* graceful restart STALE flag unset. */
f009ff26 3905 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3906 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3907 bgp_dest_set_defer_flag(dest, false);
f009ff26 3908 }
d62a17ae 3909
3910 /* The attribute is changed. */
9bcb3eef 3911 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3912
3913 /* implicit withdraw, decrement aggregate and pcount here.
3914 * only if update is accepted, they'll increment below.
3915 */
40381db7 3916 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3917
3918 /* Update bgp route dampening information. */
40ec3340 3919 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3920 && peer->sort == BGP_PEER_EBGP) {
3921 /* This is implicit withdraw so we should update
40ec3340
DS
3922 * dampening information.
3923 */
40381db7 3924 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3925 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3926 }
49e5a4a0 3927#ifdef ENABLE_BGP_VNC
d62a17ae 3928 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3929 struct bgp_dest *pdest = NULL;
d62a17ae 3930 struct bgp_table *table = NULL;
3931
9bcb3eef
DS
3932 pdest = bgp_node_get(bgp->rib[afi][safi],
3933 (struct prefix *)prd);
3934 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3935 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3936
3937 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3938 bgp, prd, table, p, pi);
d62a17ae 3939 }
9bcb3eef 3940 bgp_dest_unlock_node(pdest);
d62a17ae 3941 }
3942 if ((afi == AFI_IP || afi == AFI_IP6)
3943 && (safi == SAFI_UNICAST)) {
40381db7 3944 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3945 /*
3946 * Implicit withdraw case.
3947 */
3948 ++vnc_implicit_withdraw;
40381db7
DS
3949 vnc_import_bgp_del_route(bgp, p, pi);
3950 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3951 }
3952 }
65efcfce 3953#endif
128ea8ab 3954
d62a17ae 3955 /* Special handling for EVPN update of an existing route. If the
3956 * extended community attribute has changed, we need to
3957 * un-import
3958 * the route using its existing extended community. It will be
3959 * subsequently processed for import with the new extended
3960 * community.
3961 */
6f8c9c11
PR
3962 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3963 && !same_attr) {
40381db7 3964 if ((pi->attr->flag
d62a17ae 3965 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3966 && (attr_new->flag
3967 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3968 int cmp;
3969
40381db7 3970 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3971 attr_new->ecommunity);
3972 if (!cmp) {
3973 if (bgp_debug_update(peer, p, NULL, 1))
3974 zlog_debug(
3975 "Change in EXT-COMM, existing %s new %s",
3976 ecommunity_str(
40381db7 3977 pi->attr->ecommunity),
d62a17ae 3978 ecommunity_str(
3979 attr_new->ecommunity));
6f8c9c11
PR
3980 if (safi == SAFI_EVPN)
3981 bgp_evpn_unimport_route(
3982 bgp, afi, safi, p, pi);
3983 else /* SAFI_MPLS_VPN */
3984 vpn_leak_to_vrf_withdraw(bgp,
3985 pi);
d62a17ae 3986 }
3987 }
3988 }
718e3744 3989
d62a17ae 3990 /* Update to new attribute. */
40381db7
DS
3991 bgp_attr_unintern(&pi->attr);
3992 pi->attr = attr_new;
d62a17ae 3993
3994 /* Update MPLS label */
3995 if (has_valid_label) {
40381db7 3996 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3997 if (extra->label != label) {
3998 memcpy(&extra->label, label,
dbd587da 3999 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4000 extra->num_labels = num_labels;
4001 }
b57ba6d2
MK
4002 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4003 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4004 }
718e3744 4005
e496b420
HS
4006 /* Update SRv6 SID */
4007 if (attr->srv6_l3vpn) {
4008 extra = bgp_path_info_extra_get(pi);
4009 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4010 sid_copy(&extra->sid[0],
4011 &attr->srv6_l3vpn->sid);
4012 extra->num_sids = 1;
4013 }
4014 } else if (attr->srv6_vpn) {
4015 extra = bgp_path_info_extra_get(pi);
4016 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4017 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4018 extra->num_sids = 1;
4019 }
4020 }
4021
49e5a4a0 4022#ifdef ENABLE_BGP_VNC
d62a17ae 4023 if ((afi == AFI_IP || afi == AFI_IP6)
4024 && (safi == SAFI_UNICAST)) {
4025 if (vnc_implicit_withdraw) {
4026 /*
4027 * Add back the route with its new attributes
4028 * (e.g., nexthop).
4029 * The route is still selected, until the route
4030 * selection
4031 * queued by bgp_process actually runs. We have
4032 * to make this
4033 * update to the VNC side immediately to avoid
4034 * racing against
4035 * configuration changes (e.g., route-map
4036 * changes) which
4037 * trigger re-importation of the entire RIB.
4038 */
40381db7
DS
4039 vnc_import_bgp_add_route(bgp, p, pi);
4040 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4041 }
4042 }
65efcfce
LB
4043#endif
4044
d62a17ae 4045 /* Update bgp route dampening information. */
40ec3340 4046 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4047 && peer->sort == BGP_PEER_EBGP) {
4048 /* Now we do normal update dampening. */
9bcb3eef 4049 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4050 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4051 bgp_dest_unlock_node(dest);
d62a17ae 4052 return 0;
4053 }
4054 }
128ea8ab 4055
d62a17ae 4056 /* Nexthop reachability check - for unicast and
4057 * labeled-unicast.. */
7c312383
AD
4058 if (((afi == AFI_IP || afi == AFI_IP6)
4059 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4060 || (safi == SAFI_EVPN &&
4061 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4062 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4063 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4064 && !CHECK_FLAG(peer->flags,
4065 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4066 && !CHECK_FLAG(bgp->flags,
4067 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4068 connected = 1;
4069 else
4070 connected = 0;
4071
960035b2
PZ
4072 struct bgp *bgp_nexthop = bgp;
4073
40381db7
DS
4074 if (pi->extra && pi->extra->bgp_orig)
4075 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4076
7c312383
AD
4077 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4078
4079 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4080 safi, pi, NULL, connected)
a4d82a8a 4081 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4082 bgp_path_info_set_flag(dest, pi,
4083 BGP_PATH_VALID);
d62a17ae 4084 else {
4085 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4086 zlog_debug("%s(%pI4): NH unresolved",
4087 __func__,
4088 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4089 }
9bcb3eef 4090 bgp_path_info_unset_flag(dest, pi,
18ee8310 4091 BGP_PATH_VALID);
d62a17ae 4092 }
4093 } else
9bcb3eef 4094 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4095
49e5a4a0 4096#ifdef ENABLE_BGP_VNC
d62a17ae 4097 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4098 struct bgp_dest *pdest = NULL;
d62a17ae 4099 struct bgp_table *table = NULL;
4100
9bcb3eef
DS
4101 pdest = bgp_node_get(bgp->rib[afi][safi],
4102 (struct prefix *)prd);
4103 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4104 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4105
4106 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4107 bgp, prd, table, p, pi);
d62a17ae 4108 }
9bcb3eef 4109 bgp_dest_unlock_node(pdest);
d62a17ae 4110 }
4111#endif
718e3744 4112
d62a17ae 4113 /* If this is an EVPN route and some attribute has changed,
4114 * process
4115 * route for import. If the extended community has changed, we
4116 * would
4117 * have done the un-import earlier and the import would result
4118 * in the
4119 * route getting injected into appropriate L2 VNIs. If it is
4120 * just
4121 * some other attribute change, the import will result in
4122 * updating
4123 * the attributes for the route in the VNI(s).
4124 */
7c312383
AD
4125 if (safi == SAFI_EVPN && !same_attr &&
4126 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4127 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4128
4129 /* Process change. */
40381db7 4130 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4131
9bcb3eef
DS
4132 bgp_process(bgp, dest, afi, safi);
4133 bgp_dest_unlock_node(dest);
558d1fec 4134
ddb5b488
PZ
4135 if (SAFI_UNICAST == safi
4136 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4137 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4138
40381db7 4139 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4140 }
4141 if ((SAFI_MPLS_VPN == safi)
4142 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4143
40381db7 4144 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4145 }
4146
49e5a4a0 4147#ifdef ENABLE_BGP_VNC
d62a17ae 4148 if (SAFI_MPLS_VPN == safi) {
4149 mpls_label_t label_decoded = decode_label(label);
28070ee3 4150
d62a17ae 4151 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4152 type, sub_type, &label_decoded);
4153 }
4154 if (SAFI_ENCAP == safi) {
4155 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4156 type, sub_type, NULL);
4157 }
28070ee3
PZ
4158#endif
4159
d62a17ae 4160 return 0;
4161 } // End of implicit withdraw
718e3744 4162
d62a17ae 4163 /* Received Logging. */
4164 if (bgp_debug_update(peer, p, NULL, 1)) {
4165 if (!peer->rcvd_attr_printed) {
4166 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4167 peer->rcvd_attr_str);
4168 peer->rcvd_attr_printed = 1;
4169 }
718e3744 4170
a4d82a8a 4171 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4172 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4173 sizeof(pfx_buf));
4174 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4175 }
718e3744 4176
d62a17ae 4177 /* Make new BGP info. */
9bcb3eef 4178 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4179
d62a17ae 4180 /* Update MPLS label */
4181 if (has_valid_label) {
18ee8310 4182 extra = bgp_path_info_extra_get(new);
8ba71050 4183 if (extra->label != label) {
dbd587da
QY
4184 memcpy(&extra->label, label,
4185 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4186 extra->num_labels = num_labels;
4187 }
b57ba6d2
MK
4188 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4189 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4190 }
718e3744 4191
e496b420
HS
4192 /* Update SRv6 SID */
4193 if (safi == SAFI_MPLS_VPN) {
4194 extra = bgp_path_info_extra_get(new);
4195 if (attr->srv6_l3vpn) {
4196 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4197 extra->num_sids = 1;
4198 } else if (attr->srv6_vpn) {
4199 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4200 extra->num_sids = 1;
4201 }
4202 }
4203
d62a17ae 4204 /* Update Overlay Index */
4205 if (afi == AFI_L2VPN) {
4206 overlay_index_update(new->attr,
d62a17ae 4207 evpn == NULL ? NULL : &evpn->gw_ip);
4208 }
4209 /* Nexthop reachability check. */
7c312383
AD
4210 if (((afi == AFI_IP || afi == AFI_IP6)
4211 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4212 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4213 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4214 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4215 && !CHECK_FLAG(peer->flags,
4216 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4217 && !CHECK_FLAG(bgp->flags,
4218 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4219 connected = 1;
4220 else
4221 connected = 0;
4222
7c312383
AD
4223 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4224
4053e952 4225 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4226 connected)
a4d82a8a 4227 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4228 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4229 else {
4230 if (BGP_DEBUG(nht, NHT)) {
4231 char buf1[INET6_ADDRSTRLEN];
4232 inet_ntop(AF_INET,
4233 (const void *)&attr_new->nexthop,
4234 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4235 zlog_debug("%s(%s): NH unresolved", __func__,
4236 buf1);
d62a17ae 4237 }
9bcb3eef 4238 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4239 }
4240 } else
9bcb3eef 4241 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4242
d62a17ae 4243 /* Addpath ID */
4244 new->addpath_rx_id = addpath_id;
4245
4246 /* Increment prefix */
4247 bgp_aggregate_increment(bgp, p, new, afi, safi);
4248
4249 /* Register new BGP information. */
9bcb3eef 4250 bgp_path_info_add(dest, new);
d62a17ae 4251
4252 /* route_node_get lock */
9bcb3eef 4253 bgp_dest_unlock_node(dest);
558d1fec 4254
49e5a4a0 4255#ifdef ENABLE_BGP_VNC
d62a17ae 4256 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4257 struct bgp_dest *pdest = NULL;
d62a17ae 4258 struct bgp_table *table = NULL;
4259
9bcb3eef
DS
4260 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4261 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4262 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4263
4264 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4265 bgp, prd, table, p, new);
4266 }
9bcb3eef 4267 bgp_dest_unlock_node(pdest);
d62a17ae 4268 }
65efcfce
LB
4269#endif
4270
d62a17ae 4271 /* If this is an EVPN route, process for import. */
7c312383 4272 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4273 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4274
9bcb3eef 4275 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4276
d62a17ae 4277 /* Process change. */
9bcb3eef 4278 bgp_process(bgp, dest, afi, safi);
718e3744 4279
ddb5b488
PZ
4280 if (SAFI_UNICAST == safi
4281 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4282 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4283 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4284 }
4285 if ((SAFI_MPLS_VPN == safi)
4286 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4287
4288 vpn_leak_to_vrf_update(bgp, new);
4289 }
49e5a4a0 4290#ifdef ENABLE_BGP_VNC
d62a17ae 4291 if (SAFI_MPLS_VPN == safi) {
4292 mpls_label_t label_decoded = decode_label(label);
28070ee3 4293
d62a17ae 4294 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4295 sub_type, &label_decoded);
4296 }
4297 if (SAFI_ENCAP == safi) {
4298 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4299 sub_type, NULL);
4300 }
28070ee3
PZ
4301#endif
4302
d62a17ae 4303 return 0;
718e3744 4304
d62a17ae 4305/* This BGP update is filtered. Log the reason then update BGP
4306 entry. */
4307filtered:
9bcb3eef 4308 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4309
d62a17ae 4310 if (bgp_debug_update(peer, p, NULL, 1)) {
4311 if (!peer->rcvd_attr_printed) {
4312 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4313 peer->rcvd_attr_str);
4314 peer->rcvd_attr_printed = 1;
4315 }
718e3744 4316
a4d82a8a 4317 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4318 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4319 sizeof(pfx_buf));
4320 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4321 peer->host, pfx_buf, reason);
4322 }
128ea8ab 4323
40381db7 4324 if (pi) {
d62a17ae 4325 /* If this is an EVPN route, un-import it as it is now filtered.
4326 */
4327 if (safi == SAFI_EVPN)
40381db7 4328 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4329
ddb5b488
PZ
4330 if (SAFI_UNICAST == safi
4331 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4332 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4333
40381db7 4334 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4335 }
4336 if ((SAFI_MPLS_VPN == safi)
4337 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4338
40381db7 4339 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4340 }
4341
9bcb3eef 4342 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4343 }
4344
9bcb3eef 4345 bgp_dest_unlock_node(dest);
558d1fec 4346
49e5a4a0 4347#ifdef ENABLE_BGP_VNC
d62a17ae 4348 /*
4349 * Filtered update is treated as an implicit withdrawal (see
4350 * bgp_rib_remove()
4351 * a few lines above)
4352 */
4353 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4354 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4355 0);
4356 }
97736e32
PZ
4357#endif
4358
d62a17ae 4359 return 0;
718e3744 4360}
4361
26a3ffd6 4362int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4363 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4364 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4365 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4366{
d62a17ae 4367 struct bgp *bgp;
4368 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4369 struct bgp_dest *dest;
40381db7 4370 struct bgp_path_info *pi;
718e3744 4371
49e5a4a0 4372#ifdef ENABLE_BGP_VNC
d62a17ae 4373 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4374 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4375 0);
4376 }
28070ee3
PZ
4377#endif
4378
d62a17ae 4379 bgp = peer->bgp;
4380
4381 /* Lookup node. */
9bcb3eef 4382 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4383
4384 /* If peer is soft reconfiguration enabled. Record input packet for
4385 * further calculation.
4386 *
4387 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4388 * routes that are filtered. This tanks out Quagga RS pretty badly due
4389 * to
4390 * the iteration over all RS clients.
4391 * Since we need to remove the entry from adj_in anyway, do that first
4392 * and
4393 * if there was no entry, we don't need to do anything more.
4394 */
4395 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4396 && peer != bgp->peer_self)
9bcb3eef 4397 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4398 peer->stat_pfx_dup_withdraw++;
4399
d62a17ae 4400 if (bgp_debug_update(peer, p, NULL, 1)) {
4401 bgp_debug_rdpfxpath2str(
a4d82a8a 4402 afi, safi, prd, p, label, num_labels,
d62a17ae 4403 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4404 sizeof(pfx_buf));
4405 zlog_debug(
4406 "%s withdrawing route %s not in adj-in",
4407 peer->host, pfx_buf);
4408 }
9bcb3eef 4409 bgp_dest_unlock_node(dest);
d62a17ae 4410 return 0;
4411 }
cd808e74 4412
d62a17ae 4413 /* Lookup withdrawn route. */
9bcb3eef 4414 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4415 if (pi->peer == peer && pi->type == type
4416 && pi->sub_type == sub_type
4417 && pi->addpath_rx_id == addpath_id)
d62a17ae 4418 break;
4419
4420 /* Logging. */
4421 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4422 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4423 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4424 sizeof(pfx_buf));
4425 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4426 pfx_buf);
4427 }
718e3744 4428
d62a17ae 4429 /* Withdraw specified route from routing table. */
40381db7 4430 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4431 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4432 if (SAFI_UNICAST == safi
4433 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4434 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4435 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4436 }
4437 if ((SAFI_MPLS_VPN == safi)
4438 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4439
40381db7 4440 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4441 }
4442 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4443 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4444 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4445 sizeof(pfx_buf));
4446 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4447 }
718e3744 4448
d62a17ae 4449 /* Unlock bgp_node_get() lock. */
9bcb3eef 4450 bgp_dest_unlock_node(dest);
d62a17ae 4451
4452 return 0;
718e3744 4453}
6b0655a2 4454
d62a17ae 4455void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4456 int withdraw)
718e3744 4457{
d62a17ae 4458 struct update_subgroup *subgrp;
4459 subgrp = peer_subgroup(peer, afi, safi);
4460 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4461}
6182d65b 4462
718e3744 4463
3f9c7369
DS
4464/*
4465 * bgp_stop_announce_route_timer
4466 */
d62a17ae 4467void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4468{
d62a17ae 4469 if (!paf->t_announce_route)
4470 return;
4471
50478845 4472 thread_cancel(&paf->t_announce_route);
718e3744 4473}
6b0655a2 4474
3f9c7369
DS
4475/*
4476 * bgp_announce_route_timer_expired
4477 *
4478 * Callback that is invoked when the route announcement timer for a
4479 * peer_af expires.
4480 */
d62a17ae 4481static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4482{
d62a17ae 4483 struct peer_af *paf;
4484 struct peer *peer;
558d1fec 4485
d62a17ae 4486 paf = THREAD_ARG(t);
4487 peer = paf->peer;
718e3744 4488
d62a17ae 4489 if (peer->status != Established)
4490 return 0;
3f9c7369 4491
d62a17ae 4492 if (!peer->afc_nego[paf->afi][paf->safi])
4493 return 0;
3f9c7369 4494
d62a17ae 4495 peer_af_announce_route(paf, 1);
c5aec50b
MK
4496
4497 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4498 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4499
d62a17ae 4500 return 0;
718e3744 4501}
4502
3f9c7369
DS
4503/*
4504 * bgp_announce_route
4505 *
4506 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4507 */
d62a17ae 4508void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4509{
4510 struct peer_af *paf;
4511 struct update_subgroup *subgrp;
4512
4513 paf = peer_af_find(peer, afi, safi);
4514 if (!paf)
4515 return;
4516 subgrp = PAF_SUBGRP(paf);
4517
4518 /*
4519 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4520 * or a refresh has already been triggered.
4521 */
4522 if (!subgrp || paf->t_announce_route)
4523 return;
4524
4525 /*
4526 * Start a timer to stagger/delay the announce. This serves
4527 * two purposes - announcement can potentially be combined for
4528 * multiple peers and the announcement doesn't happen in the
4529 * vty context.
4530 */
4531 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4532 (subgrp->peer_count == 1)
4533 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4534 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4535 &paf->t_announce_route);
3f9c7369
DS
4536}
4537
4538/*
4539 * Announce routes from all AF tables to a peer.
4540 *
4541 * This should ONLY be called when there is a need to refresh the
4542 * routes to the peer based on a policy change for this peer alone
4543 * or a route refresh request received from the peer.
4544 * The operation will result in splitting the peer from its existing
4545 * subgroups and putting it in new subgroups.
4546 */
d62a17ae 4547void bgp_announce_route_all(struct peer *peer)
718e3744 4548{
d62a17ae 4549 afi_t afi;
4550 safi_t safi;
4551
05c7a1cc
QY
4552 FOREACH_AFI_SAFI (afi, safi)
4553 bgp_announce_route(peer, afi, safi);
718e3744 4554}
6b0655a2 4555
d62a17ae 4556static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4557 struct bgp_table *table,
4558 struct prefix_rd *prd)
718e3744 4559{
d62a17ae 4560 int ret;
9bcb3eef 4561 struct bgp_dest *dest;
d62a17ae 4562 struct bgp_adj_in *ain;
718e3744 4563
d62a17ae 4564 if (!table)
4565 table = peer->bgp->rib[afi][safi];
718e3744 4566
9bcb3eef
DS
4567 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4568 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4569 if (ain->peer != peer)
4570 continue;
8692c506 4571
d7d15889 4572 struct bgp_path_info *pi;
d7c0a89a 4573 uint32_t num_labels = 0;
b57ba6d2 4574 mpls_label_t *label_pnt = NULL;
8cb687c2 4575 struct bgp_route_evpn evpn;
b57ba6d2 4576
9bcb3eef 4577 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4578 pi = pi->next)
4579 if (pi->peer == peer)
4580 break;
4581
40381db7
DS
4582 if (pi && pi->extra)
4583 num_labels = pi->extra->num_labels;
b57ba6d2 4584 if (num_labels)
40381db7 4585 label_pnt = &pi->extra->label[0];
8cb687c2 4586 if (pi)
6c924775
DS
4587 memcpy(&evpn,
4588 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4589 sizeof(evpn));
4590 else
4591 memset(&evpn, 0, sizeof(evpn));
8692c506 4592
9bcb3eef
DS
4593 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4594 ain->addpath_rx_id, ain->attr, afi,
4595 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4596 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4597 num_labels, 1, &evpn);
ea47320b
DL
4598
4599 if (ret < 0) {
9bcb3eef 4600 bgp_dest_unlock_node(dest);
ea47320b 4601 return;
d62a17ae 4602 }
4603 }
718e3744 4604}
4605
d62a17ae 4606void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4607{
9bcb3eef 4608 struct bgp_dest *dest;
d62a17ae 4609 struct bgp_table *table;
718e3744 4610
d62a17ae 4611 if (peer->status != Established)
4612 return;
718e3744 4613
d62a17ae 4614 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4615 && (safi != SAFI_EVPN))
4616 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4617 else
9bcb3eef
DS
4618 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4619 dest = bgp_route_next(dest)) {
4620 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4621
b54892e0
DS
4622 if (table == NULL)
4623 continue;
8692c506 4624
9bcb3eef 4625 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4626 struct prefix_rd prd;
4627
4628 prd.family = AF_UNSPEC;
4629 prd.prefixlen = 64;
4630 memcpy(&prd.val, p->u.val, 8);
4631
4632 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4633 }
718e3744 4634}
6b0655a2 4635
228da428 4636
d62a17ae 4637struct bgp_clear_node_queue {
9bcb3eef 4638 struct bgp_dest *dest;
228da428
CC
4639};
4640
d62a17ae 4641static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4642{
d62a17ae 4643 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4644 struct bgp_dest *dest = cnq->dest;
d62a17ae 4645 struct peer *peer = wq->spec.data;
40381db7 4646 struct bgp_path_info *pi;
3103e8d2 4647 struct bgp *bgp;
9bcb3eef
DS
4648 afi_t afi = bgp_dest_table(dest)->afi;
4649 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4650
9bcb3eef 4651 assert(dest && peer);
3103e8d2 4652 bgp = peer->bgp;
d62a17ae 4653
4654 /* It is possible that we have multiple paths for a prefix from a peer
4655 * if that peer is using AddPath.
4656 */
9bcb3eef 4657 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4658 if (pi->peer != peer)
ea47320b
DL
4659 continue;
4660
4661 /* graceful restart STALE flag set. */
9af52ccf
DA
4662 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4663 && peer->nsf[afi][safi])
4664 || CHECK_FLAG(peer->af_sflags[afi][safi],
4665 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4666 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4667 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4668 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4669 else {
4670 /* If this is an EVPN route, process for
4671 * un-import. */
4672 if (safi == SAFI_EVPN)
9bcb3eef
DS
4673 bgp_evpn_unimport_route(
4674 bgp, afi, safi,
4675 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4676 /* Handle withdraw for VRF route-leaking and L3VPN */
4677 if (SAFI_UNICAST == safi
4678 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4679 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4680 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4681 bgp, pi);
960035b2 4682 }
3103e8d2 4683 if (SAFI_MPLS_VPN == safi &&
960035b2 4684 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4685 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4686 }
3103e8d2 4687
9bcb3eef 4688 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4689 }
ea47320b 4690 }
d62a17ae 4691 return WQ_SUCCESS;
200df115 4692}
4693
d62a17ae 4694static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4695{
d62a17ae 4696 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4697 struct bgp_dest *dest = cnq->dest;
4698 struct bgp_table *table = bgp_dest_table(dest);
228da428 4699
9bcb3eef 4700 bgp_dest_unlock_node(dest);
d62a17ae 4701 bgp_table_unlock(table);
4702 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4703}
4704
d62a17ae 4705static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4706{
d62a17ae 4707 struct peer *peer = wq->spec.data;
64e580a7 4708
d62a17ae 4709 /* Tickle FSM to start moving again */
4710 BGP_EVENT_ADD(peer, Clearing_Completed);
4711
4712 peer_unlock(peer); /* bgp_clear_route */
200df115 4713}
718e3744 4714
d62a17ae 4715static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4716{
d62a17ae 4717 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4718
4719 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4720#undef CLEAR_QUEUE_NAME_LEN
4721
0ce1ca80 4722 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4723 peer->clear_node_queue->spec.hold = 10;
4724 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4725 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4726 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4727 peer->clear_node_queue->spec.max_retries = 0;
4728
4729 /* we only 'lock' this peer reference when the queue is actually active
4730 */
4731 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4732}
4733
d62a17ae 4734static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4735 struct bgp_table *table)
65ca75e0 4736{
9bcb3eef 4737 struct bgp_dest *dest;
b6c386bb 4738 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4739
d62a17ae 4740 if (!table)
4741 table = peer->bgp->rib[afi][safi];
dc83d712 4742
d62a17ae 4743 /* If still no table => afi/safi isn't configured at all or smth. */
4744 if (!table)
4745 return;
dc83d712 4746
9bcb3eef 4747 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4748 struct bgp_path_info *pi, *next;
d62a17ae 4749 struct bgp_adj_in *ain;
4750 struct bgp_adj_in *ain_next;
4751
4752 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4753 * queued for every clearing peer, regardless of whether it is
4754 * relevant to the peer at hand.
4755 *
4756 * Overview: There are 3 different indices which need to be
4757 * scrubbed, potentially, when a peer is removed:
4758 *
4759 * 1 peer's routes visible via the RIB (ie accepted routes)
4760 * 2 peer's routes visible by the (optional) peer's adj-in index
4761 * 3 other routes visible by the peer's adj-out index
4762 *
4763 * 3 there is no hurry in scrubbing, once the struct peer is
4764 * removed from bgp->peer, we could just GC such deleted peer's
4765 * adj-outs at our leisure.
4766 *
4767 * 1 and 2 must be 'scrubbed' in some way, at least made
4768 * invisible via RIB index before peer session is allowed to be
4769 * brought back up. So one needs to know when such a 'search' is
4770 * complete.
4771 *
4772 * Ideally:
4773 *
4774 * - there'd be a single global queue or a single RIB walker
4775 * - rather than tracking which route_nodes still need to be
4776 * examined on a peer basis, we'd track which peers still
4777 * aren't cleared
4778 *
4779 * Given that our per-peer prefix-counts now should be reliable,
4780 * this may actually be achievable. It doesn't seem to be a huge
4781 * problem at this time,
4782 *
4783 * It is possible that we have multiple paths for a prefix from
4784 * a peer
4785 * if that peer is using AddPath.
4786 */
9bcb3eef 4787 ain = dest->adj_in;
d62a17ae 4788 while (ain) {
4789 ain_next = ain->next;
4790
4791 if (ain->peer == peer) {
9bcb3eef
DS
4792 bgp_adj_in_remove(dest, ain);
4793 bgp_dest_unlock_node(dest);
d62a17ae 4794 }
4795
4796 ain = ain_next;
4797 }
4798
9bcb3eef 4799 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4800 next = pi->next;
4801 if (pi->peer != peer)
d62a17ae 4802 continue;
4803
4804 if (force)
9bcb3eef 4805 bgp_path_info_reap(dest, pi);
d62a17ae 4806 else {
4807 struct bgp_clear_node_queue *cnq;
4808
4809 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4810 bgp_table_lock(bgp_dest_table(dest));
4811 bgp_dest_lock_node(dest);
d62a17ae 4812 cnq = XCALLOC(
4813 MTYPE_BGP_CLEAR_NODE_QUEUE,
4814 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4815 cnq->dest = dest;
d62a17ae 4816 work_queue_add(peer->clear_node_queue, cnq);
4817 break;
4818 }
4819 }
4820 }
4821 return;
4822}
4823
4824void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4825{
9bcb3eef 4826 struct bgp_dest *dest;
d62a17ae 4827 struct bgp_table *table;
4828
4829 if (peer->clear_node_queue == NULL)
4830 bgp_clear_node_queue_init(peer);
4831
4832 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4833 * Idle until it receives a Clearing_Completed event. This protects
4834 * against peers which flap faster than we can we clear, which could
4835 * lead to:
4836 *
4837 * a) race with routes from the new session being installed before
4838 * clear_route_node visits the node (to delete the route of that
4839 * peer)
4840 * b) resource exhaustion, clear_route_node likely leads to an entry
4841 * on the process_main queue. Fast-flapping could cause that queue
4842 * to grow and grow.
4843 */
4844
4845 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4846 * the unlock will happen upon work-queue completion; other wise, the
4847 * unlock happens at the end of this function.
4848 */
4849 if (!peer->clear_node_queue->thread)
4850 peer_lock(peer);
4851
4852 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4853 bgp_clear_route_table(peer, afi, safi, NULL);
4854 else
9bcb3eef
DS
4855 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4856 dest = bgp_route_next(dest)) {
4857 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4858 if (!table)
4859 continue;
4860
4861 bgp_clear_route_table(peer, afi, safi, table);
4862 }
d62a17ae 4863
4864 /* unlock if no nodes got added to the clear-node-queue. */
4865 if (!peer->clear_node_queue->thread)
4866 peer_unlock(peer);
718e3744 4867}
d62a17ae 4868
4869void bgp_clear_route_all(struct peer *peer)
718e3744 4870{
d62a17ae 4871 afi_t afi;
4872 safi_t safi;
718e3744 4873
05c7a1cc
QY
4874 FOREACH_AFI_SAFI (afi, safi)
4875 bgp_clear_route(peer, afi, safi);
65efcfce 4876
49e5a4a0 4877#ifdef ENABLE_BGP_VNC
d62a17ae 4878 rfapiProcessPeerDown(peer);
65efcfce 4879#endif
718e3744 4880}
4881
d62a17ae 4882void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4883{
d62a17ae 4884 struct bgp_table *table;
9bcb3eef 4885 struct bgp_dest *dest;
d62a17ae 4886 struct bgp_adj_in *ain;
4887 struct bgp_adj_in *ain_next;
718e3744 4888
d62a17ae 4889 table = peer->bgp->rib[afi][safi];
718e3744 4890
d62a17ae 4891 /* It is possible that we have multiple paths for a prefix from a peer
4892 * if that peer is using AddPath.
4893 */
9bcb3eef
DS
4894 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4895 ain = dest->adj_in;
43143c8f 4896
d62a17ae 4897 while (ain) {
4898 ain_next = ain->next;
43143c8f 4899
d62a17ae 4900 if (ain->peer == peer) {
9bcb3eef
DS
4901 bgp_adj_in_remove(dest, ain);
4902 bgp_dest_unlock_node(dest);
d62a17ae 4903 }
43143c8f 4904
d62a17ae 4905 ain = ain_next;
4906 }
4907 }
718e3744 4908}
93406d87 4909
d62a17ae 4910void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4911{
9bcb3eef 4912 struct bgp_dest *dest;
40381db7 4913 struct bgp_path_info *pi;
d62a17ae 4914 struct bgp_table *table;
4915
9af52ccf 4916 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4917 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4918 dest = bgp_route_next(dest)) {
4919 struct bgp_dest *rm;
d62a17ae 4920
4921 /* look for neighbor in tables */
9bcb3eef 4922 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4923 if (!table)
ea47320b
DL
4924 continue;
4925
4926 for (rm = bgp_table_top(table); rm;
4927 rm = bgp_route_next(rm))
9bcb3eef 4928 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4929 pi = pi->next) {
40381db7 4930 if (pi->peer != peer)
ea47320b 4931 continue;
40381db7 4932 if (!CHECK_FLAG(pi->flags,
1defdda8 4933 BGP_PATH_STALE))
ea47320b
DL
4934 break;
4935
40381db7 4936 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4937 break;
4938 }
d62a17ae 4939 }
4940 } else {
9bcb3eef
DS
4941 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4942 dest = bgp_route_next(dest))
4943 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4944 pi = pi->next) {
40381db7 4945 if (pi->peer != peer)
ea47320b 4946 continue;
40381db7 4947 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4948 break;
9bcb3eef 4949 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4950 break;
4951 }
d62a17ae 4952 }
93406d87 4953}
6b0655a2 4954
9af52ccf
DA
4955void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4956{
4957 struct bgp_dest *dest, *ndest;
4958 struct bgp_path_info *pi;
4959 struct bgp_table *table;
4960
4961 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4962 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4963 dest = bgp_route_next(dest)) {
4964 table = bgp_dest_get_bgp_table_info(dest);
4965 if (!table)
4966 continue;
4967
4968 for (ndest = bgp_table_top(table); ndest;
4969 ndest = bgp_route_next(ndest)) {
4970 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4971 pi = pi->next) {
4972 if (pi->peer != peer)
4973 continue;
4974
4975 if ((CHECK_FLAG(
4976 peer->af_sflags[afi][safi],
4977 PEER_STATUS_ENHANCED_REFRESH))
4978 && !CHECK_FLAG(pi->flags,
4979 BGP_PATH_STALE)
4980 && !CHECK_FLAG(
4981 pi->flags,
4982 BGP_PATH_UNUSEABLE)) {
4983 if (bgp_debug_neighbor_events(
4984 peer))
4985 zlog_debug(
4986 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4987 peer->host,
4988 afi2str(afi),
4989 safi2str(safi),
4990 bgp_dest_get_prefix(
4991 ndest));
4992
4993 bgp_path_info_set_flag(
4994 ndest, pi,
4995 BGP_PATH_STALE);
4996 }
4997 }
4998 }
4999 }
5000 } else {
5001 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5002 dest = bgp_route_next(dest)) {
5003 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5004 pi = pi->next) {
5005 if (pi->peer != peer)
5006 continue;
5007
5008 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5009 PEER_STATUS_ENHANCED_REFRESH))
5010 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5011 && !CHECK_FLAG(pi->flags,
5012 BGP_PATH_UNUSEABLE)) {
5013 if (bgp_debug_neighbor_events(peer))
5014 zlog_debug(
5015 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5016 peer->host,
5017 afi2str(afi),
5018 safi2str(safi),
5019 bgp_dest_get_prefix(
5020 dest));
5021
5022 bgp_path_info_set_flag(dest, pi,
5023 BGP_PATH_STALE);
5024 }
5025 }
5026 }
5027 }
5028}
5029
3dc339cd 5030bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5031{
e0df4c04 5032 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5033 return true;
e0df4c04 5034
9dac9fc8
DA
5035 if (peer->sort == BGP_PEER_EBGP
5036 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5037 || FILTER_LIST_OUT_NAME(filter)
5038 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5039 return true;
5040 return false;
9dac9fc8
DA
5041}
5042
3dc339cd 5043bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5044{
e0df4c04 5045 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5046 return true;
e0df4c04 5047
9dac9fc8
DA
5048 if (peer->sort == BGP_PEER_EBGP
5049 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5050 || FILTER_LIST_IN_NAME(filter)
5051 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5052 return true;
5053 return false;
9dac9fc8
DA
5054}
5055
568e10ca 5056static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5057 safi_t safi)
bb86c601 5058{
9bcb3eef 5059 struct bgp_dest *dest;
40381db7 5060 struct bgp_path_info *pi;
4b7e6066 5061 struct bgp_path_info *next;
bb86c601 5062
9bcb3eef
DS
5063 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5064 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5065 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5066
40381db7 5067 next = pi->next;
1b7bb747
CS
5068
5069 /* Unimport EVPN routes from VRFs */
5070 if (safi == SAFI_EVPN)
5071 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5072 SAFI_EVPN, p, pi);
1b7bb747 5073
40381db7
DS
5074 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5075 && pi->type == ZEBRA_ROUTE_BGP
5076 && (pi->sub_type == BGP_ROUTE_NORMAL
5077 || pi->sub_type == BGP_ROUTE_AGGREGATE
5078 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5079
d62a17ae 5080 if (bgp_fibupd_safi(safi))
b54892e0 5081 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5082 }
9514b37d 5083
9bcb3eef 5084 bgp_path_info_reap(dest, pi);
d62a17ae 5085 }
bb86c601
LB
5086}
5087
718e3744 5088/* Delete all kernel routes. */
d62a17ae 5089void bgp_cleanup_routes(struct bgp *bgp)
5090{
5091 afi_t afi;
9bcb3eef 5092 struct bgp_dest *dest;
67009e22 5093 struct bgp_table *table;
d62a17ae 5094
5095 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5096 if (afi == AFI_L2VPN)
5097 continue;
568e10ca 5098 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5099 SAFI_UNICAST);
d62a17ae 5100 /*
5101 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5102 */
5103 if (afi != AFI_L2VPN) {
5104 safi_t safi;
5105 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5106 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5107 dest = bgp_route_next(dest)) {
5108 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5109 if (table != NULL) {
5110 bgp_cleanup_table(bgp, table, safi);
5111 bgp_table_finish(&table);
9bcb3eef
DS
5112 bgp_dest_set_bgp_table_info(dest, NULL);
5113 bgp_dest_unlock_node(dest);
d62a17ae 5114 }
5115 }
5116 safi = SAFI_ENCAP;
9bcb3eef
DS
5117 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5118 dest = bgp_route_next(dest)) {
5119 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5120 if (table != NULL) {
5121 bgp_cleanup_table(bgp, table, safi);
5122 bgp_table_finish(&table);
9bcb3eef
DS
5123 bgp_dest_set_bgp_table_info(dest, NULL);
5124 bgp_dest_unlock_node(dest);
d62a17ae 5125 }
5126 }
5127 }
5128 }
9bcb3eef
DS
5129 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5130 dest = bgp_route_next(dest)) {
5131 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5132 if (table != NULL) {
5133 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5134 bgp_table_finish(&table);
9bcb3eef
DS
5135 bgp_dest_set_bgp_table_info(dest, NULL);
5136 bgp_dest_unlock_node(dest);
d62a17ae 5137 }
bb86c601 5138 }
718e3744 5139}
5140
d62a17ae 5141void bgp_reset(void)
718e3744 5142{
d62a17ae 5143 vty_reset();
5144 bgp_zclient_reset();
5145 access_list_reset();
5146 prefix_list_reset();
718e3744 5147}
6b0655a2 5148
d62a17ae 5149static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5150{
d62a17ae 5151 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5152 && CHECK_FLAG(peer->af_cap[afi][safi],
5153 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5154}
5155
718e3744 5156/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5157 value. */
d62a17ae 5158int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5159 struct bgp_nlri *packet)
5160{
d7c0a89a
QY
5161 uint8_t *pnt;
5162 uint8_t *lim;
d62a17ae 5163 struct prefix p;
5164 int psize;
5165 int ret;
5166 afi_t afi;
5167 safi_t safi;
5168 int addpath_encoded;
d7c0a89a 5169 uint32_t addpath_id;
d62a17ae 5170
d62a17ae 5171 pnt = packet->nlri;
5172 lim = pnt + packet->length;
5173 afi = packet->afi;
5174 safi = packet->safi;
5175 addpath_id = 0;
5176 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5177
5178 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5179 syntactic validity. If the field is syntactically incorrect,
5180 then the Error Subcode is set to Invalid Network Field. */
5181 for (; pnt < lim; pnt += psize) {
5182 /* Clear prefix structure. */
5183 memset(&p, 0, sizeof(struct prefix));
5184
5185 if (addpath_encoded) {
5186
5187 /* When packet overflow occurs return immediately. */
761ed665 5188 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5189 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5190
a3a850a1 5191 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5192 addpath_id = ntohl(addpath_id);
d62a17ae 5193 pnt += BGP_ADDPATH_ID_LEN;
5194 }
718e3744 5195
d62a17ae 5196 /* Fetch prefix length. */
5197 p.prefixlen = *pnt++;
5198 /* afi/safi validity already verified by caller,
5199 * bgp_update_receive */
5200 p.family = afi2family(afi);
5201
5202 /* Prefix length check. */
5203 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5204 flog_err(
e50f7cfd 5205 EC_BGP_UPDATE_RCV,
14454c9f 5206 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5207 peer->host, p.prefixlen, packet->afi);
513386b5 5208 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5209 }
6b0655a2 5210
d62a17ae 5211 /* Packet size overflow check. */
5212 psize = PSIZE(p.prefixlen);
5213
5214 /* When packet overflow occur return immediately. */
5215 if (pnt + psize > lim) {
af4c2728 5216 flog_err(
e50f7cfd 5217 EC_BGP_UPDATE_RCV,
d62a17ae 5218 "%s [Error] Update packet error (prefix length %d overflows packet)",
5219 peer->host, p.prefixlen);
513386b5 5220 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5221 }
5222
5223 /* Defensive coding, double-check the psize fits in a struct
5224 * prefix */
5225 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5226 flog_err(
e50f7cfd 5227 EC_BGP_UPDATE_RCV,
d62a17ae 5228 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5229 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5230 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5231 }
5232
5233 /* Fetch prefix from NLRI packet. */
a85297a7 5234 memcpy(p.u.val, pnt, psize);
d62a17ae 5235
5236 /* Check address. */
5237 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5238 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5239 /* From RFC4271 Section 6.3:
5240 *
5241 * If a prefix in the NLRI field is semantically
5242 * incorrect
5243 * (e.g., an unexpected multicast IP address),
5244 * an error SHOULD
5245 * be logged locally, and the prefix SHOULD be
5246 * ignored.
a4d82a8a 5247 */
af4c2728 5248 flog_err(
e50f7cfd 5249 EC_BGP_UPDATE_RCV,
23d0a753
DA
5250 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5251 peer->host, &p.u.prefix4);
d62a17ae 5252 continue;
5253 }
5254 }
5255
5256 /* Check address. */
5257 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5258 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5259 flog_err(
e50f7cfd 5260 EC_BGP_UPDATE_RCV,
c0d72166
DS
5261 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5262 peer->host, &p.u.prefix6);
d62a17ae 5263
5264 continue;
5265 }
5266 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5267 flog_err(
e50f7cfd 5268 EC_BGP_UPDATE_RCV,
c0d72166
DS
5269 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5270 peer->host, &p.u.prefix6);
d62a17ae 5271
5272 continue;
5273 }
5274 }
5275
5276 /* Normal process. */
5277 if (attr)
5278 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5279 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5280 NULL, NULL, 0, 0, NULL);
d62a17ae 5281 else
5282 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5283 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5284 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5285 NULL);
d62a17ae 5286
513386b5
DA
5287 /* Do not send BGP notification twice when maximum-prefix count
5288 * overflow. */
5289 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5290 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5291
5292 /* Address family configuration mismatch. */
d62a17ae 5293 if (ret < 0)
513386b5 5294 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5295 }
5296
5297 /* Packet length consistency check. */
5298 if (pnt != lim) {
af4c2728 5299 flog_err(
e50f7cfd 5300 EC_BGP_UPDATE_RCV,
d62a17ae 5301 "%s [Error] Update packet error (prefix length mismatch with total length)",
5302 peer->host);
513386b5 5303 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5304 }
6b0655a2 5305
513386b5 5306 return BGP_NLRI_PARSE_OK;
718e3744 5307}
5308
d62a17ae 5309static struct bgp_static *bgp_static_new(void)
718e3744 5310{
d62a17ae 5311 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5312}
5313
d62a17ae 5314static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5315{
0a22ddfb 5316 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5317 route_map_counter_decrement(bgp_static->rmap.map);
5318
0a22ddfb 5319 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5320 XFREE(MTYPE_BGP_STATIC, bgp_static);
5321}
5322
5f040085 5323void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5324 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5325{
9bcb3eef 5326 struct bgp_dest *dest;
40381db7 5327 struct bgp_path_info *pi;
4b7e6066 5328 struct bgp_path_info *new;
40381db7 5329 struct bgp_path_info rmap_path;
d62a17ae 5330 struct attr attr;
5331 struct attr *attr_new;
b68885f9 5332 route_map_result_t ret;
49e5a4a0 5333#ifdef ENABLE_BGP_VNC
d62a17ae 5334 int vnc_implicit_withdraw = 0;
65efcfce 5335#endif
fee0f4c6 5336
d62a17ae 5337 assert(bgp_static);
dd8103a9 5338
9bcb3eef 5339 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5340
d62a17ae 5341 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5342
d62a17ae 5343 attr.nexthop = bgp_static->igpnexthop;
5344 attr.med = bgp_static->igpmetric;
5345 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5346
d62a17ae 5347 if (bgp_static->atomic)
5348 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5349
d62a17ae 5350 /* Store label index, if required. */
5351 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5352 attr.label_index = bgp_static->label_index;
5353 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5354 }
718e3744 5355
d62a17ae 5356 /* Apply route-map. */
5357 if (bgp_static->rmap.name) {
5358 struct attr attr_tmp = attr;
80ced710 5359
40381db7
DS
5360 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5361 rmap_path.peer = bgp->peer_self;
5362 rmap_path.attr = &attr_tmp;
fee0f4c6 5363
d62a17ae 5364 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5365
1782514f 5366 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5367
d62a17ae 5368 bgp->peer_self->rmap_type = 0;
718e3744 5369
d62a17ae 5370 if (ret == RMAP_DENYMATCH) {
5371 /* Free uninterned attribute. */
5372 bgp_attr_flush(&attr_tmp);
718e3744 5373
d62a17ae 5374 /* Unintern original. */
5375 aspath_unintern(&attr.aspath);
5376 bgp_static_withdraw(bgp, p, afi, safi);
5377 return;
5378 }
7f323236 5379
637e5ba4 5380 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5381 bgp_attr_add_gshut_community(&attr_tmp);
5382
d62a17ae 5383 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5384 } else {
5385
637e5ba4 5386 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5387 bgp_attr_add_gshut_community(&attr);
5388
d62a17ae 5389 attr_new = bgp_attr_intern(&attr);
7f323236 5390 }
718e3744 5391
9bcb3eef 5392 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5393 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5394 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5395 break;
5396
40381db7
DS
5397 if (pi) {
5398 if (attrhash_cmp(pi->attr, attr_new)
5399 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5400 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5401 bgp_dest_unlock_node(dest);
d62a17ae 5402 bgp_attr_unintern(&attr_new);
5403 aspath_unintern(&attr.aspath);
5404 return;
5405 } else {
5406 /* The attribute is changed. */
9bcb3eef 5407 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5408
5409 /* Rewrite BGP route information. */
40381db7 5410 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5411 bgp_path_info_restore(dest, pi);
d62a17ae 5412 else
40381db7 5413 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5414#ifdef ENABLE_BGP_VNC
d62a17ae 5415 if ((afi == AFI_IP || afi == AFI_IP6)
5416 && (safi == SAFI_UNICAST)) {
40381db7 5417 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5418 /*
5419 * Implicit withdraw case.
40381db7 5420 * We have to do this before pi is
d62a17ae 5421 * changed
5422 */
5423 ++vnc_implicit_withdraw;
40381db7 5424 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5425 vnc_import_bgp_exterior_del_route(
40381db7 5426 bgp, p, pi);
d62a17ae 5427 }
5428 }
65efcfce 5429#endif
40381db7
DS
5430 bgp_attr_unintern(&pi->attr);
5431 pi->attr = attr_new;
5432 pi->uptime = bgp_clock();
49e5a4a0 5433#ifdef ENABLE_BGP_VNC
d62a17ae 5434 if ((afi == AFI_IP || afi == AFI_IP6)
5435 && (safi == SAFI_UNICAST)) {
5436 if (vnc_implicit_withdraw) {
40381db7 5437 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5438 vnc_import_bgp_exterior_add_route(
40381db7 5439 bgp, p, pi);
d62a17ae 5440 }
5441 }
65efcfce 5442#endif
718e3744 5443
d62a17ae 5444 /* Nexthop reachability check. */
892fedb6 5445 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5446 && (safi == SAFI_UNICAST
5447 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5448
5449 struct bgp *bgp_nexthop = bgp;
5450
40381db7
DS
5451 if (pi->extra && pi->extra->bgp_orig)
5452 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5453
5454 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5455 afi, safi, pi, NULL,
5456 0))
9bcb3eef 5457 bgp_path_info_set_flag(dest, pi,
18ee8310 5458 BGP_PATH_VALID);
d62a17ae 5459 else {
5460 if (BGP_DEBUG(nht, NHT)) {
5461 char buf1[INET6_ADDRSTRLEN];
5462 inet_ntop(p->family,
5463 &p->u.prefix, buf1,
5464 INET6_ADDRSTRLEN);
5465 zlog_debug(
5466 "%s(%s): Route not in table, not advertising",
15569c58 5467 __func__, buf1);
d62a17ae 5468 }
18ee8310 5469 bgp_path_info_unset_flag(
9bcb3eef 5470 dest, pi, BGP_PATH_VALID);
d62a17ae 5471 }
5472 } else {
5473 /* Delete the NHT structure if any, if we're
5474 * toggling between
5475 * enabling/disabling import check. We
5476 * deregister the route
5477 * from NHT to avoid overloading NHT and the
5478 * process interaction
5479 */
40381db7 5480 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5481 bgp_path_info_set_flag(dest, pi,
5482 BGP_PATH_VALID);
d62a17ae 5483 }
5484 /* Process change. */
40381db7 5485 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5486 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5487
5488 if (SAFI_UNICAST == safi
5489 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5490 || bgp->inst_type
5491 == BGP_INSTANCE_TYPE_DEFAULT)) {
5492 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5493 pi);
ddb5b488
PZ
5494 }
5495
9bcb3eef 5496 bgp_dest_unlock_node(dest);
d62a17ae 5497 aspath_unintern(&attr.aspath);
5498 return;
5499 }
718e3744 5500 }
718e3744 5501
d62a17ae 5502 /* Make new BGP info. */
5503 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5504 attr_new, dest);
d62a17ae 5505 /* Nexthop reachability check. */
892fedb6 5506 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5507 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5508 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5509 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5510 else {
5511 if (BGP_DEBUG(nht, NHT)) {
5512 char buf1[INET6_ADDRSTRLEN];
5513 inet_ntop(p->family, &p->u.prefix, buf1,
5514 INET6_ADDRSTRLEN);
5515 zlog_debug(
5516 "%s(%s): Route not in table, not advertising",
15569c58 5517 __func__, buf1);
d62a17ae 5518 }
9bcb3eef 5519 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5520 }
5521 } else {
5522 /* Delete the NHT structure if any, if we're toggling between
5523 * enabling/disabling import check. We deregister the route
5524 * from NHT to avoid overloading NHT and the process interaction
5525 */
5526 bgp_unlink_nexthop(new);
5527
9bcb3eef 5528 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5529 }
078430f6 5530
d62a17ae 5531 /* Aggregate address increment. */
5532 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5533
d62a17ae 5534 /* Register new BGP information. */
9bcb3eef 5535 bgp_path_info_add(dest, new);
718e3744 5536
d62a17ae 5537 /* route_node_get lock */
9bcb3eef 5538 bgp_dest_unlock_node(dest);
d62a17ae 5539
5540 /* Process change. */
9bcb3eef 5541 bgp_process(bgp, dest, afi, safi);
d62a17ae 5542
ddb5b488
PZ
5543 if (SAFI_UNICAST == safi
5544 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5545 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5546 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5547 }
5548
d62a17ae 5549 /* Unintern original. */
5550 aspath_unintern(&attr.aspath);
718e3744 5551}
5552
5f040085 5553void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5554 safi_t safi)
718e3744 5555{
9bcb3eef 5556 struct bgp_dest *dest;
40381db7 5557 struct bgp_path_info *pi;
718e3744 5558
9bcb3eef 5559 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5560
d62a17ae 5561 /* Check selected route and self inserted route. */
9bcb3eef 5562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5563 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5564 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5565 break;
5566
5567 /* Withdraw static BGP route from routing table. */
40381db7 5568 if (pi) {
ddb5b488
PZ
5569 if (SAFI_UNICAST == safi
5570 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5571 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5572 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5573 }
40381db7
DS
5574 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5575 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5576 bgp_path_info_delete(dest, pi);
5577 bgp_process(bgp, dest, afi, safi);
d62a17ae 5578 }
718e3744 5579
d62a17ae 5580 /* Unlock bgp_node_lookup. */
9bcb3eef 5581 bgp_dest_unlock_node(dest);
718e3744 5582}
5583
137446f9
LB
5584/*
5585 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5586 */
5f040085 5587static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5588 afi_t afi, safi_t safi,
5589 struct prefix_rd *prd)
718e3744 5590{
9bcb3eef 5591 struct bgp_dest *dest;
40381db7 5592 struct bgp_path_info *pi;
718e3744 5593
9bcb3eef 5594 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5595
d62a17ae 5596 /* Check selected route and self inserted route. */
9bcb3eef 5597 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5598 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5599 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5600 break;
718e3744 5601
d62a17ae 5602 /* Withdraw static BGP route from routing table. */
40381db7 5603 if (pi) {
49e5a4a0 5604#ifdef ENABLE_BGP_VNC
d62a17ae 5605 rfapiProcessWithdraw(
40381db7 5606 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5607 1); /* Kill, since it is an administrative change */
65efcfce 5608#endif
ddb5b488
PZ
5609 if (SAFI_MPLS_VPN == safi
5610 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5611 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5612 }
40381db7 5613 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5614 bgp_path_info_delete(dest, pi);
5615 bgp_process(bgp, dest, afi, safi);
d62a17ae 5616 }
718e3744 5617
d62a17ae 5618 /* Unlock bgp_node_lookup. */
9bcb3eef 5619 bgp_dest_unlock_node(dest);
718e3744 5620}
5621
5f040085 5622static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5623 struct bgp_static *bgp_static, afi_t afi,
5624 safi_t safi)
137446f9 5625{
9bcb3eef 5626 struct bgp_dest *dest;
4b7e6066 5627 struct bgp_path_info *new;
d62a17ae 5628 struct attr *attr_new;
5629 struct attr attr = {0};
40381db7 5630 struct bgp_path_info *pi;
49e5a4a0 5631#ifdef ENABLE_BGP_VNC
d62a17ae 5632 mpls_label_t label = 0;
65efcfce 5633#endif
d7c0a89a 5634 uint32_t num_labels = 0;
d62a17ae 5635 union gw_addr add;
137446f9 5636
d62a17ae 5637 assert(bgp_static);
137446f9 5638
b57ba6d2
MK
5639 if (bgp_static->label != MPLS_INVALID_LABEL)
5640 num_labels = 1;
9bcb3eef
DS
5641 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5642 &bgp_static->prd);
137446f9 5643
d62a17ae 5644 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5645
d62a17ae 5646 attr.nexthop = bgp_static->igpnexthop;
5647 attr.med = bgp_static->igpmetric;
5648 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5649
d62a17ae 5650 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5651 || (safi == SAFI_ENCAP)) {
5652 if (afi == AFI_IP) {
5653 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5654 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5655 }
5656 }
5657 if (afi == AFI_L2VPN) {
5658 if (bgp_static->gatewayIp.family == AF_INET)
5659 add.ipv4.s_addr =
5660 bgp_static->gatewayIp.u.prefix4.s_addr;
5661 else if (bgp_static->gatewayIp.family == AF_INET6)
5662 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5663 sizeof(struct in6_addr));
0a50c248 5664 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5665 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5666 struct bgp_encap_type_vxlan bet;
5667 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5668 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5669 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5670 }
5671 if (bgp_static->router_mac) {
5672 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5673 }
5674 }
5675 /* Apply route-map. */
5676 if (bgp_static->rmap.name) {
5677 struct attr attr_tmp = attr;
40381db7 5678 struct bgp_path_info rmap_path;
b68885f9 5679 route_map_result_t ret;
137446f9 5680
40381db7
DS
5681 rmap_path.peer = bgp->peer_self;
5682 rmap_path.attr = &attr_tmp;
137446f9 5683
d62a17ae 5684 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5685
1782514f 5686 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5687
d62a17ae 5688 bgp->peer_self->rmap_type = 0;
137446f9 5689
d62a17ae 5690 if (ret == RMAP_DENYMATCH) {
5691 /* Free uninterned attribute. */
5692 bgp_attr_flush(&attr_tmp);
137446f9 5693
d62a17ae 5694 /* Unintern original. */
5695 aspath_unintern(&attr.aspath);
5696 bgp_static_withdraw_safi(bgp, p, afi, safi,
5697 &bgp_static->prd);
5698 return;
5699 }
137446f9 5700
d62a17ae 5701 attr_new = bgp_attr_intern(&attr_tmp);
5702 } else {
5703 attr_new = bgp_attr_intern(&attr);
5704 }
137446f9 5705
9bcb3eef 5706 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5707 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5708 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5709 break;
5710
40381db7 5711 if (pi) {
d62a17ae 5712 memset(&add, 0, sizeof(union gw_addr));
40381db7 5713 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5714 && overlay_index_equal(afi, pi, &add)
40381db7 5715 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5716 bgp_dest_unlock_node(dest);
d62a17ae 5717 bgp_attr_unintern(&attr_new);
5718 aspath_unintern(&attr.aspath);
5719 return;
5720 } else {
5721 /* The attribute is changed. */
9bcb3eef 5722 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5723
5724 /* Rewrite BGP route information. */
40381db7 5725 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5726 bgp_path_info_restore(dest, pi);
d62a17ae 5727 else
40381db7
DS
5728 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5729 bgp_attr_unintern(&pi->attr);
5730 pi->attr = attr_new;
5731 pi->uptime = bgp_clock();
49e5a4a0 5732#ifdef ENABLE_BGP_VNC
40381db7
DS
5733 if (pi->extra)
5734 label = decode_label(&pi->extra->label[0]);
65efcfce 5735#endif
137446f9 5736
d62a17ae 5737 /* Process change. */
40381db7 5738 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5739 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5740
5741 if (SAFI_MPLS_VPN == safi
5742 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5743 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5744 }
49e5a4a0 5745#ifdef ENABLE_BGP_VNC
40381db7
DS
5746 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5747 pi->attr, afi, safi, pi->type,
5748 pi->sub_type, &label);
65efcfce 5749#endif
9bcb3eef 5750 bgp_dest_unlock_node(dest);
d62a17ae 5751 aspath_unintern(&attr.aspath);
5752 return;
5753 }
5754 }
137446f9
LB
5755
5756
d62a17ae 5757 /* Make new BGP info. */
5758 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5759 attr_new, dest);
1defdda8 5760 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5761 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5762 if (num_labels) {
5763 new->extra->label[0] = bgp_static->label;
5764 new->extra->num_labels = num_labels;
5765 }
49e5a4a0 5766#ifdef ENABLE_BGP_VNC
d62a17ae 5767 label = decode_label(&bgp_static->label);
65efcfce 5768#endif
137446f9 5769
d62a17ae 5770 /* Aggregate address increment. */
5771 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5772
d62a17ae 5773 /* Register new BGP information. */
9bcb3eef 5774 bgp_path_info_add(dest, new);
d62a17ae 5775 /* route_node_get lock */
9bcb3eef 5776 bgp_dest_unlock_node(dest);
137446f9 5777
d62a17ae 5778 /* Process change. */
9bcb3eef 5779 bgp_process(bgp, dest, afi, safi);
137446f9 5780
ddb5b488
PZ
5781 if (SAFI_MPLS_VPN == safi
5782 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5783 vpn_leak_to_vrf_update(bgp, new);
5784 }
49e5a4a0 5785#ifdef ENABLE_BGP_VNC
d62a17ae 5786 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5787 safi, new->type, new->sub_type, &label);
65efcfce
LB
5788#endif
5789
d62a17ae 5790 /* Unintern original. */
5791 aspath_unintern(&attr.aspath);
137446f9
LB
5792}
5793
718e3744 5794/* Configure static BGP network. When user don't run zebra, static
5795 route should be installed as valid. */
37a87b8f
CS
5796int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5797 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5798 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5799{
d62a17ae 5800 struct prefix p;
5801 struct bgp_static *bgp_static;
9bcb3eef 5802 struct bgp_dest *dest;
d7c0a89a 5803 uint8_t need_update = 0;
d62a17ae 5804
37a87b8f 5805 prefix_copy(&p, pfx);
d62a17ae 5806 apply_mask(&p);
718e3744 5807
e2a86ad9 5808 if (negate) {
718e3744 5809
e2a86ad9 5810 /* Set BGP static route configuration. */
9bcb3eef 5811 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5812
9bcb3eef 5813 if (!dest) {
37a87b8f
CS
5814 snprintf(errmsg, errmsg_len,
5815 "Can't find static route specified\n");
5816 return -1;
d62a17ae 5817 }
5818
9bcb3eef 5819 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5820
e2a86ad9
DS
5821 if ((label_index != BGP_INVALID_LABEL_INDEX)
5822 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5823 snprintf(errmsg, errmsg_len,
5824 "label-index doesn't match static route\n");
5825 return -1;
d62a17ae 5826 }
d62a17ae 5827
e2a86ad9
DS
5828 if ((rmap && bgp_static->rmap.name)
5829 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5830 snprintf(errmsg, errmsg_len,
5831 "route-map name doesn't match static route\n");
5832 return -1;
d62a17ae 5833 }
718e3744 5834
e2a86ad9
DS
5835 /* Update BGP RIB. */
5836 if (!bgp_static->backdoor)
5837 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5838
e2a86ad9
DS
5839 /* Clear configuration. */
5840 bgp_static_free(bgp_static);
9bcb3eef
DS
5841 bgp_dest_set_bgp_static_info(dest, NULL);
5842 bgp_dest_unlock_node(dest);
5843 bgp_dest_unlock_node(dest);
e2a86ad9 5844 } else {
718e3744 5845
e2a86ad9 5846 /* Set BGP static route configuration. */
9bcb3eef
DS
5847 dest = bgp_node_get(bgp->route[afi][safi], &p);
5848 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5849 if (bgp_static) {
e2a86ad9 5850 /* Configuration change. */
e2a86ad9
DS
5851 /* Label index cannot be changed. */
5852 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5853 snprintf(errmsg, errmsg_len,
5854 "cannot change label-index\n");
5855 return -1;
e2a86ad9 5856 }
d62a17ae 5857
e2a86ad9 5858 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5859 if (bgp_static->valid
5860 && bgp_static->backdoor != backdoor)
e2a86ad9 5861 need_update = 1;
718e3744 5862
e2a86ad9 5863 bgp_static->backdoor = backdoor;
718e3744 5864
e2a86ad9 5865 if (rmap) {
0a22ddfb
QY
5866 XFREE(MTYPE_ROUTE_MAP_NAME,
5867 bgp_static->rmap.name);
b4897fa5 5868 route_map_counter_decrement(
5869 bgp_static->rmap.map);
e2a86ad9
DS
5870 bgp_static->rmap.name =
5871 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5872 bgp_static->rmap.map =
5873 route_map_lookup_by_name(rmap);
b4897fa5 5874 route_map_counter_increment(
5875 bgp_static->rmap.map);
e2a86ad9 5876 } else {
0a22ddfb
QY
5877 XFREE(MTYPE_ROUTE_MAP_NAME,
5878 bgp_static->rmap.name);
b4897fa5 5879 route_map_counter_decrement(
5880 bgp_static->rmap.map);
e2a86ad9
DS
5881 bgp_static->rmap.map = NULL;
5882 bgp_static->valid = 0;
5883 }
9bcb3eef 5884 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5885 } else {
5886 /* New configuration. */
5887 bgp_static = bgp_static_new();
5888 bgp_static->backdoor = backdoor;
5889 bgp_static->valid = 0;
5890 bgp_static->igpmetric = 0;
975a328e 5891 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5892 bgp_static->label_index = label_index;
718e3744 5893
e2a86ad9 5894 if (rmap) {
0a22ddfb
QY
5895 XFREE(MTYPE_ROUTE_MAP_NAME,
5896 bgp_static->rmap.name);
b4897fa5 5897 route_map_counter_decrement(
5898 bgp_static->rmap.map);
e2a86ad9
DS
5899 bgp_static->rmap.name =
5900 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5901 bgp_static->rmap.map =
5902 route_map_lookup_by_name(rmap);
b4897fa5 5903 route_map_counter_increment(
5904 bgp_static->rmap.map);
e2a86ad9 5905 }
9bcb3eef 5906 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5907 }
d62a17ae 5908
e2a86ad9
DS
5909 bgp_static->valid = 1;
5910 if (need_update)
5911 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5912
e2a86ad9
DS
5913 if (!bgp_static->backdoor)
5914 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5915 }
d62a17ae 5916
37a87b8f 5917 return 0;
d62a17ae 5918}
5919
5920void bgp_static_add(struct bgp *bgp)
5921{
5922 afi_t afi;
5923 safi_t safi;
9bcb3eef
DS
5924 struct bgp_dest *dest;
5925 struct bgp_dest *rm;
d62a17ae 5926 struct bgp_table *table;
5927 struct bgp_static *bgp_static;
5928
05c7a1cc 5929 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5930 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5931 dest = bgp_route_next(dest)) {
5932 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5933 continue;
ea47320b 5934
05c7a1cc
QY
5935 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5936 || (safi == SAFI_EVPN)) {
9bcb3eef 5937 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5938
5939 for (rm = bgp_table_top(table); rm;
5940 rm = bgp_route_next(rm)) {
a78beeb5 5941 bgp_static =
9bcb3eef 5942 bgp_dest_get_bgp_static_info(
5a8ba9fc 5943 rm);
9bcb3eef
DS
5944 bgp_static_update_safi(
5945 bgp, bgp_dest_get_prefix(rm),
5946 bgp_static, afi, safi);
d62a17ae 5947 }
05c7a1cc 5948 } else {
5a8ba9fc 5949 bgp_static_update(
9bcb3eef
DS
5950 bgp, bgp_dest_get_prefix(dest),
5951 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5952 safi);
ea47320b 5953 }
05c7a1cc 5954 }
6aeb9e78
DS
5955}
5956
718e3744 5957/* Called from bgp_delete(). Delete all static routes from the BGP
5958 instance. */
d62a17ae 5959void bgp_static_delete(struct bgp *bgp)
5960{
5961 afi_t afi;
5962 safi_t safi;
9bcb3eef
DS
5963 struct bgp_dest *dest;
5964 struct bgp_dest *rm;
d62a17ae 5965 struct bgp_table *table;
5966 struct bgp_static *bgp_static;
5967
05c7a1cc 5968 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5969 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5970 dest = bgp_route_next(dest)) {
5971 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5972 continue;
ea47320b 5973
05c7a1cc
QY
5974 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5975 || (safi == SAFI_EVPN)) {
9bcb3eef 5976 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5977
5978 for (rm = bgp_table_top(table); rm;
5979 rm = bgp_route_next(rm)) {
a78beeb5 5980 bgp_static =
9bcb3eef 5981 bgp_dest_get_bgp_static_info(
5a8ba9fc 5982 rm);
c7d14ba6
PG
5983 if (!bgp_static)
5984 continue;
5985
05c7a1cc 5986 bgp_static_withdraw_safi(
9bcb3eef 5987 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5988 AFI_IP, safi,
5989 (struct prefix_rd *)
9bcb3eef
DS
5990 bgp_dest_get_prefix(
5991 dest));
ea47320b 5992 bgp_static_free(bgp_static);
811c6797 5993 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5994 NULL);
811c6797 5995 bgp_dest_unlock_node(rm);
d62a17ae 5996 }
05c7a1cc 5997 } else {
9bcb3eef 5998 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5999 bgp_static_withdraw(bgp,
9bcb3eef 6000 bgp_dest_get_prefix(dest),
b54892e0 6001 afi, safi);
05c7a1cc 6002 bgp_static_free(bgp_static);
9bcb3eef
DS
6003 bgp_dest_set_bgp_static_info(dest, NULL);
6004 bgp_dest_unlock_node(dest);
ea47320b 6005 }
05c7a1cc 6006 }
d62a17ae 6007}
6008
6009void bgp_static_redo_import_check(struct bgp *bgp)
6010{
6011 afi_t afi;
6012 safi_t safi;
9bcb3eef
DS
6013 struct bgp_dest *dest;
6014 struct bgp_dest *rm;
d62a17ae 6015 struct bgp_table *table;
6016 struct bgp_static *bgp_static;
6017
6018 /* Use this flag to force reprocessing of the route */
892fedb6 6019 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6020 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6021 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6022 dest = bgp_route_next(dest)) {
6023 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6024 continue;
ea47320b 6025
05c7a1cc
QY
6026 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6027 || (safi == SAFI_EVPN)) {
9bcb3eef 6028 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6029
6030 for (rm = bgp_table_top(table); rm;
6031 rm = bgp_route_next(rm)) {
a78beeb5 6032 bgp_static =
9bcb3eef 6033 bgp_dest_get_bgp_static_info(
5a8ba9fc 6034 rm);
9bcb3eef
DS
6035 bgp_static_update_safi(
6036 bgp, bgp_dest_get_prefix(rm),
6037 bgp_static, afi, safi);
d62a17ae 6038 }
05c7a1cc 6039 } else {
9bcb3eef
DS
6040 bgp_static = bgp_dest_get_bgp_static_info(dest);
6041 bgp_static_update(bgp,
6042 bgp_dest_get_prefix(dest),
6043 bgp_static, afi, safi);
ea47320b 6044 }
05c7a1cc
QY
6045 }
6046 }
892fedb6 6047 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6048}
6049
6050static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6051 safi_t safi)
6052{
6053 struct bgp_table *table;
9bcb3eef 6054 struct bgp_dest *dest;
40381db7 6055 struct bgp_path_info *pi;
d62a17ae 6056
dfb6fd1d
NT
6057 /* Do not install the aggregate route if BGP is in the
6058 * process of termination.
6059 */
892fedb6
DA
6060 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6061 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6062 return;
6063
d62a17ae 6064 table = bgp->rib[afi][safi];
9bcb3eef
DS
6065 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6066 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6067 if (pi->peer == bgp->peer_self
6068 && ((pi->type == ZEBRA_ROUTE_BGP
6069 && pi->sub_type == BGP_ROUTE_STATIC)
6070 || (pi->type != ZEBRA_ROUTE_BGP
6071 && pi->sub_type
d62a17ae 6072 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6073 bgp_aggregate_decrement(
6074 bgp, bgp_dest_get_prefix(dest), pi, afi,
6075 safi);
40381db7 6076 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6077 bgp_path_info_delete(dest, pi);
6078 bgp_process(bgp, dest, afi, safi);
d62a17ae 6079 }
6080 }
6081 }
ad4cbda1 6082}
6083
6084/*
6085 * Purge all networks and redistributed routes from routing table.
6086 * Invoked upon the instance going down.
6087 */
d62a17ae 6088void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6089{
d62a17ae 6090 afi_t afi;
6091 safi_t safi;
ad4cbda1 6092
05c7a1cc
QY
6093 FOREACH_AFI_SAFI (afi, safi)
6094 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6095}
6096
137446f9
LB
6097/*
6098 * gpz 110624
6099 * Currently this is used to set static routes for VPN and ENCAP.
6100 * I think it can probably be factored with bgp_static_set.
6101 */
d62a17ae 6102int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6103 const char *ip_str, const char *rd_str,
6104 const char *label_str, const char *rmap_str,
6105 int evpn_type, const char *esi, const char *gwip,
6106 const char *ethtag, const char *routermac)
6107{
6108 VTY_DECLVAR_CONTEXT(bgp, bgp);
6109 int ret;
6110 struct prefix p;
6111 struct prefix_rd prd;
9bcb3eef
DS
6112 struct bgp_dest *pdest;
6113 struct bgp_dest *dest;
d62a17ae 6114 struct bgp_table *table;
6115 struct bgp_static *bgp_static;
6116 mpls_label_t label = MPLS_INVALID_LABEL;
6117 struct prefix gw_ip;
6118
6119 /* validate ip prefix */
6120 ret = str2prefix(ip_str, &p);
6121 if (!ret) {
6122 vty_out(vty, "%% Malformed prefix\n");
6123 return CMD_WARNING_CONFIG_FAILED;
6124 }
6125 apply_mask(&p);
6126 if ((afi == AFI_L2VPN)
6127 && (bgp_build_evpn_prefix(evpn_type,
6128 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6129 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6130 return CMD_WARNING_CONFIG_FAILED;
6131 }
718e3744 6132
d62a17ae 6133 ret = str2prefix_rd(rd_str, &prd);
6134 if (!ret) {
6135 vty_out(vty, "%% Malformed rd\n");
6136 return CMD_WARNING_CONFIG_FAILED;
6137 }
718e3744 6138
d62a17ae 6139 if (label_str) {
6140 unsigned long label_val;
6141 label_val = strtoul(label_str, NULL, 10);
6142 encode_label(label_val, &label);
6143 }
9bedbb1e 6144
d62a17ae 6145 if (safi == SAFI_EVPN) {
6146 if (esi && str2esi(esi, NULL) == 0) {
6147 vty_out(vty, "%% Malformed ESI\n");
6148 return CMD_WARNING_CONFIG_FAILED;
6149 }
6150 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6151 vty_out(vty, "%% Malformed Router MAC\n");
6152 return CMD_WARNING_CONFIG_FAILED;
6153 }
6154 if (gwip) {
6155 memset(&gw_ip, 0, sizeof(struct prefix));
6156 ret = str2prefix(gwip, &gw_ip);
6157 if (!ret) {
6158 vty_out(vty, "%% Malformed GatewayIp\n");
6159 return CMD_WARNING_CONFIG_FAILED;
6160 }
6161 if ((gw_ip.family == AF_INET
3714a385 6162 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6163 (struct prefix_evpn *)&p))
6164 || (gw_ip.family == AF_INET6
3714a385 6165 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6166 (struct prefix_evpn *)&p))) {
6167 vty_out(vty,
6168 "%% GatewayIp family differs with IP prefix\n");
6169 return CMD_WARNING_CONFIG_FAILED;
6170 }
6171 }
6172 }
9bcb3eef
DS
6173 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6174 if (!bgp_dest_has_bgp_path_info_data(pdest))
6175 bgp_dest_set_bgp_table_info(pdest,
67009e22 6176 bgp_table_init(bgp, afi, safi));
9bcb3eef 6177 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6178
9bcb3eef 6179 dest = bgp_node_get(table, &p);
d62a17ae 6180
9bcb3eef 6181 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6182 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6183 bgp_dest_unlock_node(dest);
d62a17ae 6184 } else {
6185 /* New configuration. */
6186 bgp_static = bgp_static_new();
6187 bgp_static->backdoor = 0;
6188 bgp_static->valid = 0;
6189 bgp_static->igpmetric = 0;
975a328e 6190 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6191 bgp_static->label = label;
6192 bgp_static->prd = prd;
6193
6194 if (rmap_str) {
0a22ddfb 6195 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6196 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6197 bgp_static->rmap.name =
6198 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6199 bgp_static->rmap.map =
6200 route_map_lookup_by_name(rmap_str);
b4897fa5 6201 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6202 }
718e3744 6203
d62a17ae 6204 if (safi == SAFI_EVPN) {
6205 if (esi) {
6206 bgp_static->eth_s_id =
6207 XCALLOC(MTYPE_ATTR,
0a50c248 6208 sizeof(esi_t));
d62a17ae 6209 str2esi(esi, bgp_static->eth_s_id);
6210 }
6211 if (routermac) {
6212 bgp_static->router_mac =
28328ea9 6213 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6214 (void)prefix_str2mac(routermac,
6215 bgp_static->router_mac);
d62a17ae 6216 }
6217 if (gwip)
6218 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6219 }
9bcb3eef 6220 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6221
d62a17ae 6222 bgp_static->valid = 1;
6223 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6224 }
718e3744 6225
d62a17ae 6226 return CMD_SUCCESS;
718e3744 6227}
6228
6229/* Configure static BGP network. */
d62a17ae 6230int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6231 const char *ip_str, const char *rd_str,
6232 const char *label_str, int evpn_type, const char *esi,
6233 const char *gwip, const char *ethtag)
6234{
6235 VTY_DECLVAR_CONTEXT(bgp, bgp);
6236 int ret;
6237 struct prefix p;
6238 struct prefix_rd prd;
9bcb3eef
DS
6239 struct bgp_dest *pdest;
6240 struct bgp_dest *dest;
d62a17ae 6241 struct bgp_table *table;
6242 struct bgp_static *bgp_static;
6243 mpls_label_t label = MPLS_INVALID_LABEL;
6244
6245 /* Convert IP prefix string to struct prefix. */
6246 ret = str2prefix(ip_str, &p);
6247 if (!ret) {
6248 vty_out(vty, "%% Malformed prefix\n");
6249 return CMD_WARNING_CONFIG_FAILED;
6250 }
6251 apply_mask(&p);
6252 if ((afi == AFI_L2VPN)
6253 && (bgp_build_evpn_prefix(evpn_type,
6254 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6255 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6256 return CMD_WARNING_CONFIG_FAILED;
6257 }
6258 ret = str2prefix_rd(rd_str, &prd);
6259 if (!ret) {
6260 vty_out(vty, "%% Malformed rd\n");
6261 return CMD_WARNING_CONFIG_FAILED;
6262 }
718e3744 6263
d62a17ae 6264 if (label_str) {
6265 unsigned long label_val;
6266 label_val = strtoul(label_str, NULL, 10);
6267 encode_label(label_val, &label);
6268 }
718e3744 6269
9bcb3eef
DS
6270 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6271 if (!bgp_dest_has_bgp_path_info_data(pdest))
6272 bgp_dest_set_bgp_table_info(pdest,
67009e22 6273 bgp_table_init(bgp, afi, safi));
d62a17ae 6274 else
9bcb3eef
DS
6275 bgp_dest_unlock_node(pdest);
6276 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6277
9bcb3eef 6278 dest = bgp_node_lookup(table, &p);
6b0655a2 6279
9bcb3eef 6280 if (dest) {
d62a17ae 6281 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6282
9bcb3eef 6283 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6284 bgp_static_free(bgp_static);
9bcb3eef
DS
6285 bgp_dest_set_bgp_static_info(dest, NULL);
6286 bgp_dest_unlock_node(dest);
6287 bgp_dest_unlock_node(dest);
d62a17ae 6288 } else
6289 vty_out(vty, "%% Can't find the route\n");
6290
6291 return CMD_SUCCESS;
6292}
6293
6294static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6295 const char *rmap_name)
6296{
6297 VTY_DECLVAR_CONTEXT(bgp, bgp);
6298 struct bgp_rmap *rmap;
6299
6300 rmap = &bgp->table_map[afi][safi];
6301 if (rmap_name) {
0a22ddfb 6302 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6303 route_map_counter_decrement(rmap->map);
d62a17ae 6304 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6305 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6306 route_map_counter_increment(rmap->map);
d62a17ae 6307 } else {
0a22ddfb 6308 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6309 route_map_counter_decrement(rmap->map);
d62a17ae 6310 rmap->map = NULL;
6311 }
73ac8160 6312
d62a17ae 6313 if (bgp_fibupd_safi(safi))
6314 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6315
d62a17ae 6316 return CMD_SUCCESS;
73ac8160
DS
6317}
6318
d62a17ae 6319static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6320 const char *rmap_name)
73ac8160 6321{
d62a17ae 6322 VTY_DECLVAR_CONTEXT(bgp, bgp);
6323 struct bgp_rmap *rmap;
73ac8160 6324
d62a17ae 6325 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6326 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6327 route_map_counter_decrement(rmap->map);
d62a17ae 6328 rmap->map = NULL;
73ac8160 6329
d62a17ae 6330 if (bgp_fibupd_safi(safi))
6331 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6332
d62a17ae 6333 return CMD_SUCCESS;
73ac8160
DS
6334}
6335
2b791107 6336void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6337 safi_t safi)
73ac8160 6338{
d62a17ae 6339 if (bgp->table_map[afi][safi].name) {
d62a17ae 6340 vty_out(vty, " table-map %s\n",
6341 bgp->table_map[afi][safi].name);
6342 }
73ac8160
DS
6343}
6344
73ac8160
DS
6345DEFUN (bgp_table_map,
6346 bgp_table_map_cmd,
6347 "table-map WORD",
6348 "BGP table to RIB route download filter\n"
6349 "Name of the route map\n")
6350{
d62a17ae 6351 int idx_word = 1;
6352 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6353 argv[idx_word]->arg);
73ac8160
DS
6354}
6355DEFUN (no_bgp_table_map,
6356 no_bgp_table_map_cmd,
6357 "no table-map WORD",
3a2d747c 6358 NO_STR
73ac8160
DS
6359 "BGP table to RIB route download filter\n"
6360 "Name of the route map\n")
6361{
d62a17ae 6362 int idx_word = 2;
6363 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6364 argv[idx_word]->arg);
73ac8160
DS
6365}
6366
37a87b8f
CS
6367DEFPY_YANG (bgp_network, bgp_network_cmd,
6368 "[no] network \
6369 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6370 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6371 backdoor$backdoor}]",
6372 NO_STR
6373 "Specify a network to announce via BGP\n"
6374 "IPv4 prefix\n"
6375 "Network number\n"
6376 "Network mask\n"
6377 "Network mask\n"
6378 "Route-map to modify the attributes\n"
6379 "Name of the route map\n"
6380 "Label index to associate with the prefix\n"
6381 "Label index value\n"
6382 "Specify a BGP backdoor route\n")
6383{
6384 char addr_prefix_str[PREFIX_STRLEN];
6385 char base_xpath[XPATH_MAXLEN];
6386 afi_t afi;
6387 safi_t safi;
e2a86ad9
DS
6388
6389 if (address_str) {
6390 int ret;
718e3744 6391
e2a86ad9 6392 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6393 addr_prefix_str,
6394 sizeof(addr_prefix_str));
e2a86ad9
DS
6395 if (!ret) {
6396 vty_out(vty, "%% Inconsistent address and mask\n");
6397 return CMD_WARNING_CONFIG_FAILED;
6398 }
d62a17ae 6399 }
718e3744 6400
37a87b8f
CS
6401 afi = bgp_node_afi(vty);
6402 safi = bgp_node_safi(vty);
6403
6404 if (no) {
6405 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6406 } else {
6407 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6408
6409 if (map_name)
6410 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6411 NB_OP_CREATE, map_name);
6412 else
6413 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6414 NB_OP_DESTROY, NULL);
6415
6416 if (label_index_str)
6417 nb_cli_enqueue_change(vty, "./label-index",
6418 NB_OP_MODIFY, label_index_str);
6419
6420 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6421 backdoor ? "true" : "false");
6422 }
6423
6424 snprintf(
6425 base_xpath, sizeof(base_xpath),
6426 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6427 yang_afi_safi_value2identity(afi, safi),
6428 bgp_afi_safi_get_container_str(afi, safi),
6429 address_str ? addr_prefix_str : prefix_str);
6430
6431 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6432}
6433
37a87b8f
CS
6434DEFPY_YANG (ipv6_bgp_network,
6435 ipv6_bgp_network_cmd,
6436 "[no] network X:X::X:X/M$prefix \
6437 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6438 NO_STR
6439 "Specify a network to announce via BGP\n"
6440 "IPv6 prefix\n"
6441 "Route-map to modify the attributes\n"
6442 "Name of the route map\n"
6443 "Label index to associate with the prefix\n"
6444 "Label index value\n")
6445{
6446 char base_xpath[XPATH_MAXLEN];
6447 afi_t afi;
6448 safi_t safi;
6449
6450 afi = bgp_node_afi(vty);
6451 safi = bgp_node_safi(vty);
6452
6453 if (no) {
6454 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6455 } else {
6456 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6457
6458 if (map_name)
6459 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6460 NB_OP_MODIFY, map_name);
6461 else
6462 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6463 NB_OP_DESTROY, NULL);
6464
6465 if (label_index_str)
6466 nb_cli_enqueue_change(vty, "./label-index",
6467 NB_OP_MODIFY, label_index_str);
6468 }
6469
6470 snprintf(
6471 base_xpath, sizeof(base_xpath),
6472 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6473 yang_afi_safi_value2identity(afi, safi),
6474 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6475
6476 return nb_cli_apply_changes(vty, base_xpath);
6477}
6478
6479void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6480 struct lyd_node *dnode,
6481 bool show_defaults)
718e3744 6482{
37a87b8f
CS
6483 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6484
6485 if (yang_dnode_exists(dnode, "./label-index"))
6486 vty_out(vty, " label-index %s",
6487 yang_dnode_get_string(dnode, "./label-index"));
6488
6489 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6490 vty_out(vty, " route-map %s",
6491 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6492
6493 if (yang_dnode_get_bool(dnode, "./backdoor"))
6494 vty_out(vty, " backdoor");
6495
6496 vty_out(vty, "\n");
1b6d5c7e
VV
6497}
6498
d62a17ae 6499static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6500{
d62a17ae 6501 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6502}
6503
d62a17ae 6504static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6505{
365ab2e7
RZ
6506 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6507 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6508 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6509 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6510 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6511}
718e3744 6512
365ab2e7
RZ
6513/**
6514 * Helper function to avoid repeated code: prepare variables for a
6515 * `route_map_apply` call.
6516 *
6517 * \returns `true` on route map match, otherwise `false`.
6518 */
6519static bool aggr_suppress_map_test(struct bgp *bgp,
6520 struct bgp_aggregate *aggregate,
6521 struct bgp_path_info *pi)
6522{
6523 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6524 route_map_result_t rmr = RMAP_DENYMATCH;
6525 struct bgp_path_info rmap_path = {};
6526 struct attr attr = {};
6527
6528 /* No route map entries created, just don't match. */
6529 if (aggregate->suppress_map == NULL)
6530 return false;
6531
6532 /* Call route map matching and return result. */
6533 attr.aspath = aspath_empty();
6534 rmap_path.peer = bgp->peer_self;
6535 rmap_path.attr = &attr;
6536
6537 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6538 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6539 bgp->peer_self->rmap_type = 0;
6540
6541 bgp_attr_flush(&attr);
6542
6543 return rmr == RMAP_PERMITMATCH;
6544}
6545
4056a5f6
RZ
6546/** Test whether the aggregation has suppressed this path or not. */
6547static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6548 struct bgp_path_info *pi)
6549{
6550 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6551 return false;
6552
6553 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6554}
6555
6556/**
6557 * Suppress this path and keep the reference.
6558 *
6559 * \returns `true` if needs processing otherwise `false`.
6560 */
6561static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6562 struct bgp_path_info *pi)
6563{
6564 struct bgp_path_info_extra *pie;
6565
6566 /* Path is already suppressed by this aggregation. */
6567 if (aggr_suppress_exists(aggregate, pi))
6568 return false;
6569
6570 pie = bgp_path_info_extra_get(pi);
6571
6572 /* This is the first suppression, allocate memory and list it. */
6573 if (pie->aggr_suppressors == NULL)
6574 pie->aggr_suppressors = list_new();
6575
6576 listnode_add(pie->aggr_suppressors, aggregate);
6577
6578 /* Only mark for processing if suppressed. */
6579 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6580 if (BGP_DEBUG(update, UPDATE_OUT))
6581 zlog_debug("aggregate-address suppressing: %pFX",
6582 bgp_dest_get_prefix(pi->net));
6583
4056a5f6
RZ
6584 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6585 return true;
6586 }
6587
6588 return false;
6589}
6590
6591/**
6592 * Unsuppress this path and remove the reference.
6593 *
6594 * \returns `true` if needs processing otherwise `false`.
6595 */
6596static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6597 struct bgp_path_info *pi)
6598{
6599 /* Path wasn't suppressed. */
6600 if (!aggr_suppress_exists(aggregate, pi))
6601 return false;
6602
6603 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6604
6605 /* Unsuppress and free extra memory if last item. */
6606 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6607 if (BGP_DEBUG(update, UPDATE_OUT))
6608 zlog_debug("aggregate-address unsuppressing: %pFX",
6609 bgp_dest_get_prefix(pi->net));
6610
4056a5f6
RZ
6611 list_delete(&pi->extra->aggr_suppressors);
6612 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6613 return true;
6614 }
6615
6616 return false;
6617}
6618
3dc339cd
DA
6619static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6620 struct aspath *aspath,
6621 struct community *comm,
6622 struct ecommunity *ecomm,
6623 struct lcommunity *lcomm)
eaaf8adb
DS
6624{
6625 static struct aspath *ae = NULL;
6626
6627 if (!ae)
6628 ae = aspath_empty();
6629
40381db7 6630 if (!pi)
3dc339cd 6631 return false;
eaaf8adb 6632
40381db7 6633 if (origin != pi->attr->origin)
3dc339cd 6634 return false;
eaaf8adb 6635
40381db7 6636 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6637 return false;
29f7d023 6638
40381db7 6639 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6640 return false;
eaaf8adb 6641
3da2cc32 6642 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6643 return false;
eaaf8adb 6644
dd18c5a9 6645 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6646 return false;
dd18c5a9 6647
40381db7 6648 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6649 return false;
7ce8a8e0 6650
3dc339cd 6651 return true;
eaaf8adb
DS
6652}
6653
5f040085
DS
6654static void bgp_aggregate_install(
6655 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6656 uint8_t origin, struct aspath *aspath, struct community *community,
6657 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6658 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6659{
9bcb3eef 6660 struct bgp_dest *dest;
c701010e 6661 struct bgp_table *table;
6f94b685 6662 struct bgp_path_info *pi, *orig, *new;
20894f50 6663 struct attr *attr;
c701010e
DS
6664
6665 table = bgp->rib[afi][safi];
6666
9bcb3eef 6667 dest = bgp_node_get(table, p);
eaaf8adb 6668
9bcb3eef 6669 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6670 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6671 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6672 break;
6673
6aabb15d
RZ
6674 /*
6675 * If we have paths with different MEDs, then don't install
6676 * (or uninstall) the aggregate route.
6677 */
6678 if (aggregate->match_med && aggregate->med_mismatched)
6679 goto uninstall_aggregate_route;
6680
c701010e 6681 if (aggregate->count > 0) {
eaaf8adb
DS
6682 /*
6683 * If the aggregate information has not changed
6684 * no need to re-install it again.
6685 */
6f94b685 6686 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6687 ecommunity, lcommunity)) {
9bcb3eef 6688 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6689
6690 if (aspath)
6691 aspath_free(aspath);
6692 if (community)
3c1f53de 6693 community_free(&community);
3da2cc32
DS
6694 if (ecommunity)
6695 ecommunity_free(&ecommunity);
dd18c5a9
DS
6696 if (lcommunity)
6697 lcommunity_free(&lcommunity);
eaaf8adb
DS
6698
6699 return;
6700 }
6701
6702 /*
6703 * Mark the old as unusable
6704 */
40381db7 6705 if (pi)
9bcb3eef 6706 bgp_path_info_delete(dest, pi);
eaaf8adb 6707
20894f50
DA
6708 attr = bgp_attr_aggregate_intern(
6709 bgp, origin, aspath, community, ecommunity, lcommunity,
6710 aggregate, atomic_aggregate, p);
6711
6712 if (!attr) {
6713 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6714 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6715 zlog_debug("%s: %pFX null attribute", __func__,
6716 p);
20894f50
DA
6717 return;
6718 }
6719
3da2cc32 6720 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6721 bgp->peer_self, attr, dest);
20894f50 6722
1defdda8 6723 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6724
9bcb3eef
DS
6725 bgp_path_info_add(dest, new);
6726 bgp_process(bgp, dest, afi, safi);
c701010e 6727 } else {
6aabb15d 6728 uninstall_aggregate_route:
6f94b685 6729 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6730 if (pi->peer == bgp->peer_self
6731 && pi->type == ZEBRA_ROUTE_BGP
6732 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6733 break;
6734
6735 /* Withdraw static BGP route from routing table. */
40381db7 6736 if (pi) {
9bcb3eef
DS
6737 bgp_path_info_delete(dest, pi);
6738 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6739 }
6740 }
6741
9bcb3eef 6742 bgp_dest_unlock_node(dest);
c701010e
DS
6743}
6744
6aabb15d
RZ
6745/**
6746 * Check if the current path has different MED than other known paths.
6747 *
6748 * \returns `true` if the MED matched the others else `false`.
6749 */
6750static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6751 struct bgp *bgp, struct bgp_path_info *pi)
6752{
6753 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6754
6755 /* This is the first route being analyzed. */
6756 if (!aggregate->med_initialized) {
6757 aggregate->med_initialized = true;
6758 aggregate->med_mismatched = false;
6759 aggregate->med_matched_value = cur_med;
6760 } else {
6761 /* Check if routes with different MED showed up. */
6762 if (cur_med != aggregate->med_matched_value)
6763 aggregate->med_mismatched = true;
6764 }
6765
6766 return !aggregate->med_mismatched;
6767}
6768
6769/**
6770 * Initializes and tests all routes in the aggregate address path for MED
6771 * values.
6772 *
6773 * \returns `true` if all MEDs are the same otherwise `false`.
6774 */
6775static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6776 struct bgp *bgp, const struct prefix *p,
6777 afi_t afi, safi_t safi)
6778{
6779 struct bgp_table *table = bgp->rib[afi][safi];
6780 const struct prefix *dest_p;
6781 struct bgp_dest *dest, *top;
6782 struct bgp_path_info *pi;
6783 bool med_matched = true;
6784
6785 aggregate->med_initialized = false;
6786
6787 top = bgp_node_get(table, p);
6788 for (dest = bgp_node_get(table, p); dest;
6789 dest = bgp_route_next_until(dest, top)) {
6790 dest_p = bgp_dest_get_prefix(dest);
6791 if (dest_p->prefixlen <= p->prefixlen)
6792 continue;
6793
6794 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6795 if (BGP_PATH_HOLDDOWN(pi))
6796 continue;
6797 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6798 continue;
6799 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6800 med_matched = false;
6801 break;
6802 }
6803 }
6804 if (!med_matched)
6805 break;
6806 }
6807 bgp_dest_unlock_node(top);
6808
6809 return med_matched;
6810}
6811
6812/**
6813 * Toggles the route suppression status for this aggregate address
6814 * configuration.
6815 */
4056a5f6
RZ
6816void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6817 struct bgp *bgp, const struct prefix *p,
6818 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6819{
6820 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6821 const struct prefix *dest_p;
6822 struct bgp_dest *dest, *top;
6823 struct bgp_path_info *pi;
6824 bool toggle_suppression;
6825
6826 /* We've found a different MED we must revert any suppressed routes. */
6827 top = bgp_node_get(table, p);
6828 for (dest = bgp_node_get(table, p); dest;
6829 dest = bgp_route_next_until(dest, top)) {
6830 dest_p = bgp_dest_get_prefix(dest);
6831 if (dest_p->prefixlen <= p->prefixlen)
6832 continue;
6833
6834 toggle_suppression = false;
6835 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6836 if (BGP_PATH_HOLDDOWN(pi))
6837 continue;
6838 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6839 continue;
6840
6aabb15d
RZ
6841 /* We are toggling suppression back. */
6842 if (suppress) {
6aabb15d 6843 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6844 if (aggr_suppress_path(aggregate, pi))
6845 toggle_suppression = true;
6aabb15d
RZ
6846 continue;
6847 }
6848
6aabb15d 6849 /* Install route if there is no more suppression. */
4056a5f6 6850 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6851 toggle_suppression = true;
6aabb15d
RZ
6852 }
6853
6854 if (toggle_suppression)
6855 bgp_process(bgp, dest, afi, safi);
6856 }
6857 bgp_dest_unlock_node(top);
6858}
6859
6860/**
6861 * Aggregate address MED matching incremental test: this function is called
6862 * when the initial aggregation occurred and we are only testing a single
6863 * new path.
6864 *
6865 * In addition to testing and setting the MED validity it also installs back
6866 * suppressed routes (if summary is configured).
6867 *
6868 * Must not be called in `bgp_aggregate_route`.
6869 */
6870static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6871 struct bgp *bgp, const struct prefix *p,
6872 afi_t afi, safi_t safi,
6873 struct bgp_path_info *pi, bool is_adding)
6874{
6875 /* MED matching disabled. */
6876 if (!aggregate->match_med)
6877 return;
6878
6879 /* Aggregation with different MED, nothing to do. */
6880 if (aggregate->med_mismatched)
6881 return;
6882
6883 /*
6884 * Test the current entry:
6885 *
6886 * is_adding == true: if the new entry doesn't match then we must
6887 * install all suppressed routes.
6888 *
6889 * is_adding == false: if the entry being removed was the last
6890 * unmatching entry then we can suppress all routes.
6891 */
6892 if (!is_adding) {
6893 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6894 && aggregate->summary_only)
6895 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6896 safi, true);
6897 } else
6898 bgp_aggregate_med_match(aggregate, bgp, pi);
6899
6900 /* No mismatches, just quit. */
6901 if (!aggregate->med_mismatched)
6902 return;
6903
6904 /* Route summarization is disabled. */
6905 if (!aggregate->summary_only)
6906 return;
6907
6908 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6909}
6910
b5d58c32 6911/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6912void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6913 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6914{
6915 struct bgp_table *table;
9bcb3eef
DS
6916 struct bgp_dest *top;
6917 struct bgp_dest *dest;
d7c0a89a 6918 uint8_t origin;
d62a17ae 6919 struct aspath *aspath = NULL;
d62a17ae 6920 struct community *community = NULL;
3da2cc32 6921 struct ecommunity *ecommunity = NULL;
dd18c5a9 6922 struct lcommunity *lcommunity = NULL;
40381db7 6923 struct bgp_path_info *pi;
d62a17ae 6924 unsigned long match = 0;
d7c0a89a 6925 uint8_t atomic_aggregate = 0;
d62a17ae 6926
9f822fa2
S
6927 /* If the bgp instance is being deleted or self peer is deleted
6928 * then do not create aggregate route
6929 */
892fedb6
DA
6930 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6931 || (bgp->peer_self == NULL))
9f822fa2
S
6932 return;
6933
6aabb15d
RZ
6934 /* Initialize and test routes for MED difference. */
6935 if (aggregate->match_med)
6936 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6937
4056a5f6
RZ
6938 /*
6939 * Reset aggregate count: we might've been called from route map
6940 * update so in that case we must retest all more specific routes.
6941 *
6942 * \see `bgp_route_map_process_update`.
6943 */
6944 aggregate->count = 0;
6945 aggregate->incomplete_origin_count = 0;
6946 aggregate->incomplete_origin_count = 0;
6947 aggregate->egp_origin_count = 0;
6948
d62a17ae 6949 /* ORIGIN attribute: If at least one route among routes that are
6950 aggregated has ORIGIN with the value INCOMPLETE, then the
6951 aggregated route must have the ORIGIN attribute with the value
6952 INCOMPLETE. Otherwise, if at least one route among routes that
6953 are aggregated has ORIGIN with the value EGP, then the aggregated
6954 route must have the origin attribute with the value EGP. In all
6955 other case the value of the ORIGIN attribute of the aggregated
6956 route is INTERNAL. */
6957 origin = BGP_ORIGIN_IGP;
718e3744 6958
d62a17ae 6959 table = bgp->rib[afi][safi];
718e3744 6960
d62a17ae 6961 top = bgp_node_get(table, p);
9bcb3eef
DS
6962 for (dest = bgp_node_get(table, p); dest;
6963 dest = bgp_route_next_until(dest, top)) {
6964 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6965
9bcb3eef 6966 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6967 continue;
d62a17ae 6968
a77e2f4b
S
6969 /* If suppress fib is enabled and route not installed
6970 * in FIB, skip the route
6971 */
6972 if (!bgp_check_advertise(bgp, dest))
6973 continue;
6974
c2ff8b3e 6975 match = 0;
d62a17ae 6976
9bcb3eef 6977 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6978 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6979 continue;
718e3744 6980
40381db7 6981 if (pi->attr->flag
c2ff8b3e
DS
6982 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6983 atomic_aggregate = 1;
d62a17ae 6984
40381db7 6985 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6986 continue;
d62a17ae 6987
f273fef1
DS
6988 /*
6989 * summary-only aggregate route suppress
6990 * aggregated route announcements.
6aabb15d
RZ
6991 *
6992 * MED matching:
6993 * Don't create summaries if MED didn't match
6994 * otherwise neither the specific routes and the
6995 * aggregation will be announced.
f273fef1 6996 */
6aabb15d
RZ
6997 if (aggregate->summary_only
6998 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6999 if (aggr_suppress_path(aggregate, pi))
7000 match++;
d62a17ae 7001 }
c2ff8b3e 7002
365ab2e7
RZ
7003 /*
7004 * Suppress more specific routes that match the route
7005 * map results.
7006 *
7007 * MED matching:
7008 * Don't suppress routes if MED matching is enabled and
7009 * it mismatched otherwise we might end up with no
7010 * routes for this path.
7011 */
7012 if (aggregate->suppress_map_name
7013 && AGGREGATE_MED_VALID(aggregate)
7014 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7015 if (aggr_suppress_path(aggregate, pi))
7016 match++;
d62a17ae 7017 }
c2ff8b3e
DS
7018
7019 aggregate->count++;
7020
f273fef1
DS
7021 /*
7022 * If at least one route among routes that are
7023 * aggregated has ORIGIN with the value INCOMPLETE,
7024 * then the aggregated route MUST have the ORIGIN
7025 * attribute with the value INCOMPLETE. Otherwise, if
7026 * at least one route among routes that are aggregated
7027 * has ORIGIN with the value EGP, then the aggregated
7028 * route MUST have the ORIGIN attribute with the value
7029 * EGP.
7030 */
fc968841
NT
7031 switch (pi->attr->origin) {
7032 case BGP_ORIGIN_INCOMPLETE:
7033 aggregate->incomplete_origin_count++;
7034 break;
7035 case BGP_ORIGIN_EGP:
7036 aggregate->egp_origin_count++;
7037 break;
7038 default:
7039 /*Do nothing.
7040 */
7041 break;
7042 }
c2ff8b3e
DS
7043
7044 if (!aggregate->as_set)
7045 continue;
7046
f273fef1
DS
7047 /*
7048 * as-set aggregate route generate origin, as path,
7049 * and community aggregation.
7050 */
fc968841
NT
7051 /* Compute aggregate route's as-path.
7052 */
ef51a7d8 7053 bgp_compute_aggregate_aspath_hash(aggregate,
7054 pi->attr->aspath);
c2ff8b3e 7055
fc968841
NT
7056 /* Compute aggregate route's community.
7057 */
7058 if (pi->attr->community)
21fec674 7059 bgp_compute_aggregate_community_hash(
fc968841
NT
7060 aggregate,
7061 pi->attr->community);
dd18c5a9 7062
fc968841
NT
7063 /* Compute aggregate route's extended community.
7064 */
7065 if (pi->attr->ecommunity)
4edd83f9 7066 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7067 aggregate,
7068 pi->attr->ecommunity);
7069
7070 /* Compute aggregate route's large community.
7071 */
7072 if (pi->attr->lcommunity)
f1eb1f05 7073 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7074 aggregate,
7075 pi->attr->lcommunity);
d62a17ae 7076 }
c2ff8b3e 7077 if (match)
9bcb3eef 7078 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7079 }
21fec674 7080 if (aggregate->as_set) {
ef51a7d8 7081 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7082 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7083 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7084 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7085 }
7086
f1eb1f05 7087
9bcb3eef 7088 bgp_dest_unlock_node(top);
718e3744 7089
718e3744 7090
fc968841
NT
7091 if (aggregate->incomplete_origin_count > 0)
7092 origin = BGP_ORIGIN_INCOMPLETE;
7093 else if (aggregate->egp_origin_count > 0)
7094 origin = BGP_ORIGIN_EGP;
d62a17ae 7095
229757f1
DA
7096 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7097 origin = aggregate->origin;
7098
fc968841
NT
7099 if (aggregate->as_set) {
7100 if (aggregate->aspath)
7101 /* Retrieve aggregate route's as-path.
7102 */
7103 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7104
fc968841
NT
7105 if (aggregate->community)
7106 /* Retrieve aggregate route's community.
7107 */
7108 community = community_dup(aggregate->community);
3da2cc32 7109
fc968841
NT
7110 if (aggregate->ecommunity)
7111 /* Retrieve aggregate route's ecommunity.
7112 */
7113 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7114
fc968841
NT
7115 if (aggregate->lcommunity)
7116 /* Retrieve aggregate route's lcommunity.
7117 */
7118 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7119 }
718e3744 7120
c701010e 7121 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7122 ecommunity, lcommunity, atomic_aggregate,
7123 aggregate);
718e3744 7124}
7125
5f040085
DS
7126void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7127 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7128{
7129 struct bgp_table *table;
9bcb3eef
DS
7130 struct bgp_dest *top;
7131 struct bgp_dest *dest;
40381db7 7132 struct bgp_path_info *pi;
3b7db173
DS
7133 unsigned long match;
7134
7135 table = bgp->rib[afi][safi];
7136
7137 /* If routes exists below this node, generate aggregate routes. */
7138 top = bgp_node_get(table, p);
9bcb3eef
DS
7139 for (dest = bgp_node_get(table, p); dest;
7140 dest = bgp_route_next_until(dest, top)) {
7141 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7142
9bcb3eef 7143 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7144 continue;
7145 match = 0;
7146
9bcb3eef 7147 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7148 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7149 continue;
7150
40381db7 7151 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7152 continue;
7153
6aabb15d
RZ
7154 if (aggregate->summary_only && pi->extra
7155 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7156 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7157 match++;
3b7db173 7158 }
3b7db173 7159
365ab2e7
RZ
7160 if (aggregate->suppress_map_name
7161 && AGGREGATE_MED_VALID(aggregate)
7162 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7163 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7164 match++;
3b7db173 7165 }
365ab2e7 7166
3b7db173 7167 aggregate->count--;
fc968841
NT
7168
7169 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7170 aggregate->incomplete_origin_count--;
7171 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7172 aggregate->egp_origin_count--;
7173
7174 if (aggregate->as_set) {
7175 /* Remove as-path from aggregate.
7176 */
ef51a7d8 7177 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7178 aggregate,
7179 pi->attr->aspath);
7180
7181 if (pi->attr->community)
7182 /* Remove community from aggregate.
7183 */
21fec674 7184 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7185 aggregate,
7186 pi->attr->community);
7187
7188 if (pi->attr->ecommunity)
7189 /* Remove ecommunity from aggregate.
7190 */
4edd83f9 7191 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7192 aggregate,
7193 pi->attr->ecommunity);
7194
7195 if (pi->attr->lcommunity)
7196 /* Remove lcommunity from aggregate.
7197 */
f1eb1f05 7198 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7199 aggregate,
7200 pi->attr->lcommunity);
7201 }
3b7db173
DS
7202 }
7203
7204 /* If this node was suppressed, process the change. */
7205 if (match)
9bcb3eef 7206 bgp_process(bgp, dest, afi, safi);
3b7db173 7207 }
f1eb1f05 7208 if (aggregate->as_set) {
ef51a7d8 7209 aspath_free(aggregate->aspath);
7210 aggregate->aspath = NULL;
21fec674 7211 if (aggregate->community)
7212 community_free(&aggregate->community);
4edd83f9 7213 if (aggregate->ecommunity)
7214 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7215 if (aggregate->lcommunity)
7216 lcommunity_free(&aggregate->lcommunity);
7217 }
7218
9bcb3eef 7219 bgp_dest_unlock_node(top);
3b7db173 7220}
718e3744 7221
5f040085
DS
7222static void bgp_add_route_to_aggregate(struct bgp *bgp,
7223 const struct prefix *aggr_p,
fc968841
NT
7224 struct bgp_path_info *pinew, afi_t afi,
7225 safi_t safi,
7226 struct bgp_aggregate *aggregate)
7227{
7228 uint8_t origin;
7229 struct aspath *aspath = NULL;
7230 uint8_t atomic_aggregate = 0;
7231 struct community *community = NULL;
7232 struct ecommunity *ecommunity = NULL;
7233 struct lcommunity *lcommunity = NULL;
7234
a4559740 7235 /* If the bgp instance is being deleted or self peer is deleted
7236 * then do not create aggregate route
7237 */
7238 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7239 || (bgp->peer_self == NULL))
7240 return;
7241
fc968841
NT
7242 /* ORIGIN attribute: If at least one route among routes that are
7243 * aggregated has ORIGIN with the value INCOMPLETE, then the
7244 * aggregated route must have the ORIGIN attribute with the value
7245 * INCOMPLETE. Otherwise, if at least one route among routes that
7246 * are aggregated has ORIGIN with the value EGP, then the aggregated
7247 * route must have the origin attribute with the value EGP. In all
7248 * other case the value of the ORIGIN attribute of the aggregated
7249 * route is INTERNAL.
7250 */
7251 origin = BGP_ORIGIN_IGP;
7252
7253 aggregate->count++;
7254
6aabb15d
RZ
7255 /*
7256 * This must be called before `summary` check to avoid
7257 * "suppressing" twice.
7258 */
7259 if (aggregate->match_med)
7260 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7261 pinew, true);
7262
7263 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7264 aggr_suppress_path(aggregate, pinew);
fc968841 7265
365ab2e7
RZ
7266 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7267 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7268 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7269
7270 switch (pinew->attr->origin) {
7271 case BGP_ORIGIN_INCOMPLETE:
7272 aggregate->incomplete_origin_count++;
7273 break;
7274 case BGP_ORIGIN_EGP:
7275 aggregate->egp_origin_count++;
7276 break;
7277 default:
7278 /* Do nothing.
7279 */
7280 break;
7281 }
7282
7283 if (aggregate->incomplete_origin_count > 0)
7284 origin = BGP_ORIGIN_INCOMPLETE;
7285 else if (aggregate->egp_origin_count > 0)
7286 origin = BGP_ORIGIN_EGP;
7287
229757f1
DA
7288 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7289 origin = aggregate->origin;
7290
fc968841
NT
7291 if (aggregate->as_set) {
7292 /* Compute aggregate route's as-path.
7293 */
7294 bgp_compute_aggregate_aspath(aggregate,
7295 pinew->attr->aspath);
7296
7297 /* Compute aggregate route's community.
7298 */
7299 if (pinew->attr->community)
7300 bgp_compute_aggregate_community(
7301 aggregate,
7302 pinew->attr->community);
7303
7304 /* Compute aggregate route's extended community.
7305 */
7306 if (pinew->attr->ecommunity)
7307 bgp_compute_aggregate_ecommunity(
7308 aggregate,
7309 pinew->attr->ecommunity);
7310
7311 /* Compute aggregate route's large community.
7312 */
7313 if (pinew->attr->lcommunity)
7314 bgp_compute_aggregate_lcommunity(
7315 aggregate,
7316 pinew->attr->lcommunity);
7317
7318 /* Retrieve aggregate route's as-path.
7319 */
7320 if (aggregate->aspath)
7321 aspath = aspath_dup(aggregate->aspath);
7322
7323 /* Retrieve aggregate route's community.
7324 */
7325 if (aggregate->community)
7326 community = community_dup(aggregate->community);
7327
7328 /* Retrieve aggregate route's ecommunity.
7329 */
7330 if (aggregate->ecommunity)
7331 ecommunity = ecommunity_dup(aggregate->ecommunity);
7332
7333 /* Retrieve aggregate route's lcommunity.
7334 */
7335 if (aggregate->lcommunity)
7336 lcommunity = lcommunity_dup(aggregate->lcommunity);
7337 }
7338
7339 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7340 aspath, community, ecommunity,
7341 lcommunity, atomic_aggregate, aggregate);
7342}
7343
7344static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7345 safi_t safi,
7346 struct bgp_path_info *pi,
7347 struct bgp_aggregate *aggregate,
5f040085 7348 const struct prefix *aggr_p)
fc968841
NT
7349{
7350 uint8_t origin;
7351 struct aspath *aspath = NULL;
7352 uint8_t atomic_aggregate = 0;
7353 struct community *community = NULL;
7354 struct ecommunity *ecommunity = NULL;
7355 struct lcommunity *lcommunity = NULL;
7356 unsigned long match = 0;
7357
a4559740 7358 /* If the bgp instance is being deleted or self peer is deleted
7359 * then do not create aggregate route
7360 */
7361 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7362 || (bgp->peer_self == NULL))
7363 return;
7364
fc968841
NT
7365 if (BGP_PATH_HOLDDOWN(pi))
7366 return;
7367
7368 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7369 return;
7370
4056a5f6
RZ
7371 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7372 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7373 match++;
fc968841 7374
365ab2e7 7375 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7376 && aggr_suppress_map_test(bgp, aggregate, pi))
7377 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7378 match++;
fc968841 7379
6aabb15d 7380 /*
365ab2e7 7381 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7382 * "unsuppressing" twice.
7383 */
7384 if (aggregate->match_med)
7385 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7386 true);
7387
fc968841
NT
7388 if (aggregate->count > 0)
7389 aggregate->count--;
7390
7391 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7392 aggregate->incomplete_origin_count--;
7393 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7394 aggregate->egp_origin_count--;
7395
7396 if (aggregate->as_set) {
7397 /* Remove as-path from aggregate.
7398 */
7399 bgp_remove_aspath_from_aggregate(aggregate,
7400 pi->attr->aspath);
7401
7402 if (pi->attr->community)
7403 /* Remove community from aggregate.
7404 */
7405 bgp_remove_community_from_aggregate(
7406 aggregate,
7407 pi->attr->community);
7408
7409 if (pi->attr->ecommunity)
7410 /* Remove ecommunity from aggregate.
7411 */
7412 bgp_remove_ecommunity_from_aggregate(
7413 aggregate,
7414 pi->attr->ecommunity);
7415
7416 if (pi->attr->lcommunity)
7417 /* Remove lcommunity from aggregate.
7418 */
7419 bgp_remove_lcommunity_from_aggregate(
7420 aggregate,
7421 pi->attr->lcommunity);
7422 }
7423
7424 /* If this node was suppressed, process the change. */
7425 if (match)
7426 bgp_process(bgp, pi->net, afi, safi);
7427
7428 origin = BGP_ORIGIN_IGP;
7429 if (aggregate->incomplete_origin_count > 0)
7430 origin = BGP_ORIGIN_INCOMPLETE;
7431 else if (aggregate->egp_origin_count > 0)
7432 origin = BGP_ORIGIN_EGP;
7433
229757f1
DA
7434 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7435 origin = aggregate->origin;
7436
fc968841
NT
7437 if (aggregate->as_set) {
7438 /* Retrieve aggregate route's as-path.
7439 */
7440 if (aggregate->aspath)
7441 aspath = aspath_dup(aggregate->aspath);
7442
7443 /* Retrieve aggregate route's community.
7444 */
7445 if (aggregate->community)
7446 community = community_dup(aggregate->community);
7447
7448 /* Retrieve aggregate route's ecommunity.
7449 */
7450 if (aggregate->ecommunity)
7451 ecommunity = ecommunity_dup(aggregate->ecommunity);
7452
7453 /* Retrieve aggregate route's lcommunity.
7454 */
7455 if (aggregate->lcommunity)
7456 lcommunity = lcommunity_dup(aggregate->lcommunity);
7457 }
7458
7459 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7460 aspath, community, ecommunity,
7461 lcommunity, atomic_aggregate, aggregate);
7462}
7463
5a1ae2c2 7464void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7465 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7466{
9bcb3eef
DS
7467 struct bgp_dest *child;
7468 struct bgp_dest *dest;
d62a17ae 7469 struct bgp_aggregate *aggregate;
7470 struct bgp_table *table;
718e3744 7471
d62a17ae 7472 table = bgp->aggregate[afi][safi];
f018db83 7473
d62a17ae 7474 /* No aggregates configured. */
7475 if (bgp_table_top_nolock(table) == NULL)
7476 return;
f018db83 7477
d62a17ae 7478 if (p->prefixlen == 0)
7479 return;
718e3744 7480
40381db7 7481 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7482 return;
718e3744 7483
a77e2f4b
S
7484 /* If suppress fib is enabled and route not installed
7485 * in FIB, do not update the aggregate route
7486 */
7487 if (!bgp_check_advertise(bgp, pi->net))
7488 return;
7489
d62a17ae 7490 child = bgp_node_get(table, p);
718e3744 7491
d62a17ae 7492 /* Aggregate address configuration check. */
9bcb3eef
DS
7493 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7494 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7495
9bcb3eef
DS
7496 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7497 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7498 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7499 aggregate);
d62a17ae 7500 }
b1e62edd 7501 }
9bcb3eef 7502 bgp_dest_unlock_node(child);
718e3744 7503}
7504
5a1ae2c2 7505void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7506 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7507{
9bcb3eef
DS
7508 struct bgp_dest *child;
7509 struct bgp_dest *dest;
d62a17ae 7510 struct bgp_aggregate *aggregate;
7511 struct bgp_table *table;
718e3744 7512
d62a17ae 7513 table = bgp->aggregate[afi][safi];
718e3744 7514
d62a17ae 7515 /* No aggregates configured. */
7516 if (bgp_table_top_nolock(table) == NULL)
7517 return;
718e3744 7518
d62a17ae 7519 if (p->prefixlen == 0)
7520 return;
718e3744 7521
d62a17ae 7522 child = bgp_node_get(table, p);
718e3744 7523
d62a17ae 7524 /* Aggregate address configuration check. */
9bcb3eef
DS
7525 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7526 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7527
9bcb3eef
DS
7528 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7529 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7530 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7531 aggregate, dest_p);
d62a17ae 7532 }
b1e62edd 7533 }
9bcb3eef 7534 bgp_dest_unlock_node(child);
d62a17ae 7535}
718e3744 7536
718e3744 7537/* Aggregate route attribute. */
7538#define AGGREGATE_SUMMARY_ONLY 1
7539#define AGGREGATE_AS_SET 1
fb29348a 7540#define AGGREGATE_AS_UNSET 0
718e3744 7541
229757f1
DA
7542static const char *bgp_origin2str(uint8_t origin)
7543{
7544 switch (origin) {
7545 case BGP_ORIGIN_IGP:
7546 return "igp";
7547 case BGP_ORIGIN_EGP:
7548 return "egp";
7549 case BGP_ORIGIN_INCOMPLETE:
7550 return "incomplete";
7551 }
7552 return "n/a";
7553}
7554
fdeb5a81 7555static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7556{
7557 switch (v_state) {
fdeb5a81
DS
7558 case RPKI_NOT_BEING_USED:
7559 return "not used";
7560 case RPKI_VALID:
b5b99af8 7561 return "valid";
fdeb5a81 7562 case RPKI_NOTFOUND:
b5b99af8 7563 return "not found";
fdeb5a81 7564 case RPKI_INVALID:
b5b99af8 7565 return "invalid";
b5b99af8 7566 }
fdeb5a81
DS
7567
7568 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7569 return "ERROR";
7570}
7571
37a87b8f
CS
7572int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7573 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7574{
9bcb3eef 7575 struct bgp_dest *dest;
d62a17ae 7576 struct bgp_aggregate *aggregate;
718e3744 7577
a4559740 7578 /* If the bgp instance is being deleted or self peer is deleted
7579 * then do not create aggregate route
7580 */
7581 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7582 || (bgp->peer_self == NULL))
7583 return 0;
7584
37a87b8f 7585 apply_mask(prefix);
d62a17ae 7586 /* Old configuration check. */
37a87b8f 7587 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7588 if (!dest) {
37a87b8f
CS
7589 snprintf(errmsg, errmsg_len,
7590 "There is no aggregate-address configuration.\n");
7591 return -1;
d62a17ae 7592 }
f6269b4f 7593
9bcb3eef 7594 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7595 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7596 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7597 0, aggregate);
d62a17ae 7598
7599 /* Unlock aggregate address configuration. */
9bcb3eef 7600 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7601
7602 if (aggregate->community)
7603 community_free(&aggregate->community);
7604
7605 if (aggregate->community_hash) {
7606 /* Delete all communities in the hash.
7607 */
7608 hash_clean(aggregate->community_hash,
7609 bgp_aggr_community_remove);
7610 /* Free up the community_hash.
7611 */
7612 hash_free(aggregate->community_hash);
7613 }
7614
7615 if (aggregate->ecommunity)
7616 ecommunity_free(&aggregate->ecommunity);
7617
7618 if (aggregate->ecommunity_hash) {
7619 /* Delete all ecommunities in the hash.
7620 */
7621 hash_clean(aggregate->ecommunity_hash,
7622 bgp_aggr_ecommunity_remove);
7623 /* Free up the ecommunity_hash.
7624 */
7625 hash_free(aggregate->ecommunity_hash);
7626 }
7627
7628 if (aggregate->lcommunity)
7629 lcommunity_free(&aggregate->lcommunity);
7630
7631 if (aggregate->lcommunity_hash) {
7632 /* Delete all lcommunities in the hash.
7633 */
7634 hash_clean(aggregate->lcommunity_hash,
7635 bgp_aggr_lcommunity_remove);
7636 /* Free up the lcommunity_hash.
7637 */
7638 hash_free(aggregate->lcommunity_hash);
7639 }
7640
7641 if (aggregate->aspath)
7642 aspath_free(aggregate->aspath);
7643
7644 if (aggregate->aspath_hash) {
7645 /* Delete all as-paths in the hash.
7646 */
7647 hash_clean(aggregate->aspath_hash,
7648 bgp_aggr_aspath_remove);
7649 /* Free up the aspath_hash.
7650 */
7651 hash_free(aggregate->aspath_hash);
7652 }
7653
d62a17ae 7654 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7655 bgp_dest_unlock_node(dest);
7656 bgp_dest_unlock_node(dest);
d62a17ae 7657
37a87b8f 7658 return 0;
d62a17ae 7659}
7660
37a87b8f
CS
7661int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7662 safi_t safi, const char *rmap, uint8_t summary_only,
7663 uint8_t as_set, uint8_t origin, bool match_med,
7664 const char *suppress_map,
7665 char *errmsg, size_t errmsg_len)
d62a17ae 7666{
d62a17ae 7667 int ret;
9bcb3eef 7668 struct bgp_dest *dest;
d62a17ae 7669 struct bgp_aggregate *aggregate;
fb29348a 7670 uint8_t as_set_new = as_set;
37a87b8f 7671 char buf[PREFIX2STR_BUFFER];
d62a17ae 7672
365ab2e7 7673 if (suppress_map && summary_only) {
37a87b8f 7674 snprintf(errmsg, errmsg_len,
365ab2e7 7675 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7676 return -1;
365ab2e7
RZ
7677 }
7678
37a87b8f 7679 apply_mask(prefix);
d62a17ae 7680
37a87b8f
CS
7681 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7682 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7683 snprintf(
7684 errmsg, errmsg_len,
7685 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7686 prefix2str(prefix, buf, PREFIX_STRLEN));
7687 return -1;
3624ac81
DS
7688 }
7689
d62a17ae 7690 /* Old configuration check. */
37a87b8f 7691 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7692 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7693
20894f50 7694 if (aggregate) {
37a87b8f
CS
7695 snprintf(errmsg, errmsg_len,
7696 "There is already same aggregate network.\n");
d62a17ae 7697 /* try to remove the old entry */
37a87b8f
CS
7698 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7699 errmsg_len);
d62a17ae 7700 if (ret) {
37a87b8f
CS
7701 snprintf(errmsg, errmsg_len,
7702 "Error deleting aggregate.\n");
9bcb3eef 7703 bgp_dest_unlock_node(dest);
37a87b8f 7704 return -1;
d62a17ae 7705 }
7706 }
718e3744 7707
d62a17ae 7708 /* Make aggregate address structure. */
7709 aggregate = bgp_aggregate_new();
7710 aggregate->summary_only = summary_only;
6aabb15d 7711 aggregate->match_med = match_med;
fb29348a
DA
7712
7713 /* Network operators MUST NOT locally generate any new
7714 * announcements containing AS_SET or AS_CONFED_SET. If they have
7715 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7716 * SHOULD withdraw those routes and re-announce routes for the
7717 * aggregate or component prefixes (i.e., the more-specific routes
7718 * subsumed by the previously aggregated route) without AS_SET
7719 * or AS_CONFED_SET in the updates.
7720 */
7f972cd8 7721 if (bgp->reject_as_sets) {
fb29348a
DA
7722 if (as_set == AGGREGATE_AS_SET) {
7723 as_set_new = AGGREGATE_AS_UNSET;
7724 zlog_warn(
63efca0e 7725 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7726 __func__);
37a87b8f
CS
7727 snprintf(
7728 errmsg, errmsg_len,
fb29348a
DA
7729 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7730 }
7731 }
7732
7733 aggregate->as_set = as_set_new;
d62a17ae 7734 aggregate->safi = safi;
229757f1
DA
7735 /* Override ORIGIN attribute if defined.
7736 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7737 * to IGP which is not what rfc4271 says.
7738 * This enables the same behavior, optionally.
7739 */
7740 aggregate->origin = origin;
20894f50
DA
7741
7742 if (rmap) {
7743 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7744 route_map_counter_decrement(aggregate->rmap.map);
7745 aggregate->rmap.name =
7746 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7747 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7748 route_map_counter_increment(aggregate->rmap.map);
7749 }
365ab2e7
RZ
7750
7751 if (suppress_map) {
7752 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7753 route_map_counter_decrement(aggregate->suppress_map);
7754
7755 aggregate->suppress_map_name =
7756 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7757 aggregate->suppress_map =
7758 route_map_lookup_by_name(aggregate->suppress_map_name);
7759 route_map_counter_increment(aggregate->suppress_map);
7760 }
7761
9bcb3eef 7762 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7763
d62a17ae 7764 /* Aggregate address insert into BGP routing table. */
37a87b8f 7765 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7766
37a87b8f 7767 return 0;
718e3744 7768}
7769
37a87b8f
CS
7770DEFPY_YANG(
7771 aggregate_addressv4, aggregate_addressv4_cmd,
7772 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7773 "as-set$as_set_s"
7774 "|summary-only$summary_only"
7775 "|route-map WORD$rmap_name"
7776 "|origin <egp|igp|incomplete>$origin_s"
7777 "|matching-MED-only$match_med"
90e21f35 7778 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7779 "}",
7780 NO_STR
7781 "Configure BGP aggregate entries\n"
7782 "Aggregate prefix\n"
7783 "Aggregate address\n"
7784 "Aggregate mask\n"
7785 "Generate AS set path information\n"
7786 "Filter more specific routes from updates\n"
7787 "Apply route map to aggregate network\n"
7788 "Route map name\n"
7789 "BGP origin code\n"
7790 "Remote EGP\n"
7791 "Local IGP\n"
7792 "Unknown heritage\n"
7793 "Only aggregate routes with matching MED\n"
90e21f35
CS
7794 "Suppress the selected more specific routes\n"
7795 "Route map with the route selectors\n")
37a87b8f
CS
7796{
7797 char base_xpath[XPATH_MAXLEN];
554b3b10 7798 safi_t safi = bgp_node_safi(vty);
554b3b10 7799 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7800
554b3b10 7801 if (addr_str) {
7533cad7
QY
7802 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7803 sizeof(prefix_buf))
554b3b10
RZ
7804 == 0) {
7805 vty_out(vty, "%% Inconsistent address and mask\n");
7806 return CMD_WARNING_CONFIG_FAILED;
7807 }
37a87b8f
CS
7808 } else {
7809 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7810 }
7811
37a87b8f
CS
7812 if (!no && origin_s)
7813 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7814
7815 if (!no && as_set_s)
7816 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7817 else
7818 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7819
7820 if (!no && summary_only)
7821 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7822 "true");
7823 else
7824 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7825 "false");
7826
fa423774
CS
7827 if (!no && match_med)
7828 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7829 else
7830 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7831 "false");
7832
37a87b8f
CS
7833 if (rmap_name)
7834 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7835 rmap_name);
7836 else
7837 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7838 NB_OP_DESTROY, NULL);
7839
90e21f35
CS
7840 if (suppress_map)
7841 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7842 suppress_map);
7843 else
7844 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7845 NULL);
7846
37a87b8f
CS
7847 snprintf(
7848 base_xpath, sizeof(base_xpath),
7849 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7850 yang_afi_safi_value2identity(AFI_IP, safi),
7851 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7852
554b3b10 7853 if (no)
37a87b8f
CS
7854 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7855 else
7856 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7857
7858 return nb_cli_apply_changes(vty, base_xpath);
7859}
7860
7861DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7862 "[no] aggregate-address X:X::X:X/M$prefix {"
7863 "as-set$as_set_s"
7864 "|summary-only$summary_only"
7865 "|route-map WORD$rmap_name"
7866 "|origin <egp|igp|incomplete>$origin_s"
7867 "|matching-MED-only$match_med"
90e21f35 7868 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7869 "}",
7870 NO_STR
7871 "Configure BGP aggregate entries\n"
7872 "Aggregate prefix\n"
7873 "Generate AS set path information\n"
7874 "Filter more specific routes from updates\n"
7875 "Apply route map to aggregate network\n"
7876 "Route map name\n"
7877 "BGP origin code\n"
7878 "Remote EGP\n"
7879 "Local IGP\n"
7880 "Unknown heritage\n"
7881 "Only aggregate routes with matching MED\n"
7882 "Suppress the selected more specific routes\n"
90e21f35 7883 "Route map with the route selectors\n")
37a87b8f
CS
7884{
7885 char base_xpath[XPATH_MAXLEN];
7886 safi_t safi = bgp_node_safi(vty);
7887
7888 if (!no && origin_s)
7889 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7890
7891 if (!no && as_set_s)
7892 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7893 else
7894 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7895
7896 if (!no && summary_only)
7897 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7898 "true");
7899 else
7900 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7901 "false");
7902
fa423774
CS
7903 if (!no && match_med)
7904 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7905 else
7906 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7907 "false");
7908
37a87b8f
CS
7909 if (rmap_name)
7910 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7911 rmap_name);
7912
90e21f35
CS
7913 if (suppress_map)
7914 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7915 suppress_map);
7916 else
7917 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7918 NULL);
7919
37a87b8f
CS
7920 snprintf(
7921 base_xpath, sizeof(base_xpath),
7922 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7923 yang_afi_safi_value2identity(AFI_IP6, safi),
7924 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7925
554b3b10 7926 if (no)
37a87b8f
CS
7927 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7928 else
7929 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7930
37a87b8f
CS
7931 return nb_cli_apply_changes(vty, base_xpath);
7932}
7933
7934void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7935 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7936{
7937 uint8_t origin;
7938
7939 vty_out(vty, " aggregate-address %s",
7940 yang_dnode_get_string(dnode, "./prefix"));
7941
7942 if (yang_dnode_get_bool(dnode, "./as-set"))
7943 vty_out(vty, " as-set");
7944
7945 if (yang_dnode_get_bool(dnode, "./summary-only"))
7946 vty_out(vty, " summary-only");
7947
7948 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7949 vty_out(vty, " route-map %s",
7950 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7951
7952 origin = yang_dnode_get_enum(dnode, "./origin");
7953 if (origin != BGP_ORIGIN_UNSPECIFIED)
7954 vty_out(vty, " origin %s", bgp_origin2str(origin));
7955
fa423774
CS
7956 if (yang_dnode_get_bool(dnode, "./match-med"))
7957 vty_out(vty, " matching-MED-only");
7958
37a87b8f 7959 vty_out(vty, "\n");
718e3744 7960}
7961
718e3744 7962/* Redistribute route treatment. */
d62a17ae 7963void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7964 const union g_addr *nexthop, ifindex_t ifindex,
7965 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7966 uint8_t type, unsigned short instance,
7967 route_tag_t tag)
d62a17ae 7968{
4b7e6066 7969 struct bgp_path_info *new;
40381db7
DS
7970 struct bgp_path_info *bpi;
7971 struct bgp_path_info rmap_path;
9bcb3eef 7972 struct bgp_dest *bn;
d62a17ae 7973 struct attr attr;
7974 struct attr *new_attr;
7975 afi_t afi;
b68885f9 7976 route_map_result_t ret;
d62a17ae 7977 struct bgp_redist *red;
7978
7979 /* Make default attribute. */
7980 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7981 /*
7982 * This must not be NULL to satisfy Coverity SA
7983 */
7984 assert(attr.aspath);
9de1f7ff 7985
a4d82a8a 7986 switch (nhtype) {
9de1f7ff
DS
7987 case NEXTHOP_TYPE_IFINDEX:
7988 break;
7989 case NEXTHOP_TYPE_IPV4:
7990 case NEXTHOP_TYPE_IPV4_IFINDEX:
7991 attr.nexthop = nexthop->ipv4;
7992 break;
7993 case NEXTHOP_TYPE_IPV6:
7994 case NEXTHOP_TYPE_IPV6_IFINDEX:
7995 attr.mp_nexthop_global = nexthop->ipv6;
7996 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7997 break;
7998 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7999 switch (p->family) {
8000 case AF_INET:
9de1f7ff 8001 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8002 break;
8003 case AF_INET6:
9de1f7ff
DS
8004 memset(&attr.mp_nexthop_global, 0,
8005 sizeof(attr.mp_nexthop_global));
74489921 8006 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8007 break;
74489921 8008 }
9de1f7ff 8009 break;
d62a17ae 8010 }
74489921 8011 attr.nh_ifindex = ifindex;
f04a80a5 8012
d62a17ae 8013 attr.med = metric;
8014 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8015 attr.tag = tag;
718e3744 8016
d62a17ae 8017 afi = family2afi(p->family);
6aeb9e78 8018
d62a17ae 8019 red = bgp_redist_lookup(bgp, afi, type, instance);
8020 if (red) {
8021 struct attr attr_new;
718e3744 8022
d62a17ae 8023 /* Copy attribute for modification. */
6f4f49b2 8024 attr_new = attr;
718e3744 8025
d62a17ae 8026 if (red->redist_metric_flag)
8027 attr_new.med = red->redist_metric;
718e3744 8028
d62a17ae 8029 /* Apply route-map. */
8030 if (red->rmap.name) {
40381db7
DS
8031 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8032 rmap_path.peer = bgp->peer_self;
8033 rmap_path.attr = &attr_new;
718e3744 8034
d62a17ae 8035 SET_FLAG(bgp->peer_self->rmap_type,
8036 PEER_RMAP_TYPE_REDISTRIBUTE);
8037
1782514f 8038 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8039
8040 bgp->peer_self->rmap_type = 0;
8041
8042 if (ret == RMAP_DENYMATCH) {
8043 /* Free uninterned attribute. */
8044 bgp_attr_flush(&attr_new);
8045
8046 /* Unintern original. */
8047 aspath_unintern(&attr.aspath);
8048 bgp_redistribute_delete(bgp, p, type, instance);
8049 return;
8050 }
8051 }
8052
637e5ba4 8053 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8054 bgp_attr_add_gshut_community(&attr_new);
8055
d62a17ae 8056 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8057 SAFI_UNICAST, p, NULL);
8058
8059 new_attr = bgp_attr_intern(&attr_new);
8060
9bcb3eef 8061 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8062 if (bpi->peer == bgp->peer_self
8063 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8064 break;
8065
40381db7 8066 if (bpi) {
d62a17ae 8067 /* Ensure the (source route) type is updated. */
40381db7
DS
8068 bpi->type = type;
8069 if (attrhash_cmp(bpi->attr, new_attr)
8070 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8071 bgp_attr_unintern(&new_attr);
8072 aspath_unintern(&attr.aspath);
9bcb3eef 8073 bgp_dest_unlock_node(bn);
d62a17ae 8074 return;
8075 } else {
8076 /* The attribute is changed. */
40381db7 8077 bgp_path_info_set_flag(bn, bpi,
18ee8310 8078 BGP_PATH_ATTR_CHANGED);
d62a17ae 8079
8080 /* Rewrite BGP route information. */
40381db7
DS
8081 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8082 bgp_path_info_restore(bn, bpi);
d62a17ae 8083 else
40381db7
DS
8084 bgp_aggregate_decrement(
8085 bgp, p, bpi, afi, SAFI_UNICAST);
8086 bgp_attr_unintern(&bpi->attr);
8087 bpi->attr = new_attr;
8088 bpi->uptime = bgp_clock();
d62a17ae 8089
8090 /* Process change. */
40381db7 8091 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8092 SAFI_UNICAST);
8093 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8094 bgp_dest_unlock_node(bn);
d62a17ae 8095 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8096
8097 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8098 || (bgp->inst_type
8099 == BGP_INSTANCE_TYPE_DEFAULT)) {
8100
8101 vpn_leak_from_vrf_update(
40381db7 8102 bgp_get_default(), bgp, bpi);
ddb5b488 8103 }
d62a17ae 8104 return;
8105 }
8106 }
8107
8108 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8109 bgp->peer_self, new_attr, bn);
1defdda8 8110 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8111
8112 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8113 bgp_path_info_add(bn, new);
9bcb3eef 8114 bgp_dest_unlock_node(bn);
d62a17ae 8115 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8116
8117 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8118 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8119
8120 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8121 }
d62a17ae 8122 }
8123
8124 /* Unintern original. */
8125 aspath_unintern(&attr.aspath);
718e3744 8126}
8127
d7c0a89a
QY
8128void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8129 unsigned short instance)
718e3744 8130{
d62a17ae 8131 afi_t afi;
9bcb3eef 8132 struct bgp_dest *dest;
40381db7 8133 struct bgp_path_info *pi;
d62a17ae 8134 struct bgp_redist *red;
718e3744 8135
d62a17ae 8136 afi = family2afi(p->family);
718e3744 8137
d62a17ae 8138 red = bgp_redist_lookup(bgp, afi, type, instance);
8139 if (red) {
9bcb3eef
DS
8140 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8141 SAFI_UNICAST, p, NULL);
d62a17ae 8142
9bcb3eef 8143 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8144 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8145 break;
8146
40381db7 8147 if (pi) {
ddb5b488
PZ
8148 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8149 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8150
8151 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8152 bgp, pi);
ddb5b488 8153 }
40381db7 8154 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8155 bgp_path_info_delete(dest, pi);
8156 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8157 }
9bcb3eef 8158 bgp_dest_unlock_node(dest);
d62a17ae 8159 }
8160}
8161
8162/* Withdraw specified route type's route. */
8163void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8164 unsigned short instance)
d62a17ae 8165{
9bcb3eef 8166 struct bgp_dest *dest;
40381db7 8167 struct bgp_path_info *pi;
d62a17ae 8168 struct bgp_table *table;
8169
8170 table = bgp->rib[afi][SAFI_UNICAST];
8171
9bcb3eef
DS
8172 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8173 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8174 if (pi->peer == bgp->peer_self && pi->type == type
8175 && pi->instance == instance)
d62a17ae 8176 break;
8177
40381db7 8178 if (pi) {
ddb5b488
PZ
8179 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8180 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8181
8182 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8183 bgp, pi);
ddb5b488 8184 }
9bcb3eef 8185 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8186 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8187 bgp_path_info_delete(dest, pi);
8188 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8189 }
718e3744 8190 }
718e3744 8191}
6b0655a2 8192
718e3744 8193/* Static function to display route. */
bd494ec5 8194static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8195 json_object *json, bool wide)
718e3744 8196{
be054588 8197 int len = 0;
d62a17ae 8198 char buf[BUFSIZ];
50e05855 8199 char buf2[BUFSIZ];
718e3744 8200
d62a17ae 8201 if (p->family == AF_INET) {
c6462ff4 8202 if (!json) {
8228a9a7 8203 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8204 } else {
8205 json_object_string_add(json, "prefix",
8206 inet_ntop(p->family,
8207 &p->u.prefix, buf,
8208 BUFSIZ));
8209 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8210 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8211 json_object_string_add(json, "network", buf2);
c6462ff4 8212 }
d62a17ae 8213 } else if (p->family == AF_ETHERNET) {
8228a9a7 8214 len = vty_out(vty, "%pFX", p);
b03b8898 8215 } else if (p->family == AF_EVPN) {
57f7feb6 8216 if (!json)
2dbe669b 8217 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8218 else
60466a63 8219 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8220 } else if (p->family == AF_FLOWSPEC) {
8221 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8222 json ?
8223 NLRI_STRING_FORMAT_JSON_SIMPLE :
8224 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8225 } else {
c6462ff4 8226 if (!json)
8228a9a7 8227 len = vty_out(vty, "%pFX", p);
50e05855
AD
8228 else {
8229 json_object_string_add(json, "prefix",
8230 inet_ntop(p->family,
8231 &p->u.prefix, buf,
8232 BUFSIZ));
8233 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8234 prefix2str(p, buf2, PREFIX_STRLEN);
8235 json_object_string_add(json, "network", buf2);
8236 }
9c92b5f7 8237 }
d62a17ae 8238
9c92b5f7 8239 if (!json) {
ae248832 8240 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8241 if (len < 1)
8242 vty_out(vty, "\n%*s", 20, " ");
8243 else
8244 vty_out(vty, "%*s", len, " ");
8245 }
718e3744 8246}
8247
d62a17ae 8248enum bgp_display_type {
8249 normal_list,
718e3744 8250};
8251
bbb46eb5
DA
8252static const char *
8253bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8254{
8255 switch (reason) {
8256 case bgp_path_selection_none:
8257 return "Nothing to Select";
8258 case bgp_path_selection_first:
8259 return "First path received";
8260 case bgp_path_selection_evpn_sticky_mac:
8261 return "EVPN Sticky Mac";
8262 case bgp_path_selection_evpn_seq:
8263 return "EVPN sequence number";
8264 case bgp_path_selection_evpn_lower_ip:
8265 return "EVPN lower IP";
8266 case bgp_path_selection_evpn_local_path:
8267 return "EVPN local ES path";
8268 case bgp_path_selection_evpn_non_proxy:
8269 return "EVPN non proxy";
8270 case bgp_path_selection_weight:
8271 return "Weight";
8272 case bgp_path_selection_local_pref:
8273 return "Local Pref";
8274 case bgp_path_selection_local_route:
8275 return "Local Route";
8276 case bgp_path_selection_confed_as_path:
8277 return "Confederation based AS Path";
8278 case bgp_path_selection_as_path:
8279 return "AS Path";
8280 case bgp_path_selection_origin:
8281 return "Origin";
8282 case bgp_path_selection_med:
8283 return "MED";
8284 case bgp_path_selection_peer:
8285 return "Peer Type";
8286 case bgp_path_selection_confed:
8287 return "Confed Peer Type";
8288 case bgp_path_selection_igp_metric:
8289 return "IGP Metric";
8290 case bgp_path_selection_older:
8291 return "Older Path";
8292 case bgp_path_selection_router_id:
8293 return "Router ID";
8294 case bgp_path_selection_cluster_length:
bcab253c 8295 return "Cluster length";
bbb46eb5
DA
8296 case bgp_path_selection_stale:
8297 return "Path Staleness";
8298 case bgp_path_selection_local_configured:
8299 return "Locally configured route";
8300 case bgp_path_selection_neighbor_ip:
8301 return "Neighbor IP";
8302 case bgp_path_selection_default:
8303 return "Nothing left to compare";
8304 }
8305 return "Invalid (internal error)";
8306}
8307
18ee8310 8308/* Print the short form route status for a bgp_path_info */
4b7e6066 8309static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8310 struct bgp_path_info *path,
d62a17ae 8311 json_object *json_path)
718e3744 8312{
d62a17ae 8313 if (json_path) {
b05a1c8b 8314
d62a17ae 8315 /* Route status display. */
9b6d8fcf 8316 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8317 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8318
9b6d8fcf 8319 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8320 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8321
4056a5f6 8322 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8323 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8324
9b6d8fcf
DS
8325 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8326 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8327 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8328
d62a17ae 8329 /* Selected */
9b6d8fcf 8330 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8331 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8332
9b6d8fcf 8333 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8334 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8335
bbb46eb5 8336 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8337 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8338 json_object_string_add(json_path, "selectionReason",
8339 bgp_path_selection_reason2str(
8340 path->net->reason));
8341 }
b05a1c8b 8342
9b6d8fcf 8343 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8344 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8345
d62a17ae 8346 /* Internal route. */
9b6d8fcf
DS
8347 if ((path->peer->as)
8348 && (path->peer->as == path->peer->local_as))
d62a17ae 8349 json_object_string_add(json_path, "pathFrom",
8350 "internal");
8351 else
8352 json_object_string_add(json_path, "pathFrom",
8353 "external");
b05a1c8b 8354
d62a17ae 8355 return;
8356 }
b05a1c8b 8357
d62a17ae 8358 /* Route status display. */
9b6d8fcf 8359 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8360 vty_out(vty, "R");
9b6d8fcf 8361 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8362 vty_out(vty, "S");
4056a5f6 8363 else if (bgp_path_suppressed(path))
d62a17ae 8364 vty_out(vty, "s");
9b6d8fcf
DS
8365 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8366 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8367 vty_out(vty, "*");
8368 else
8369 vty_out(vty, " ");
8370
8371 /* Selected */
9b6d8fcf 8372 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8373 vty_out(vty, "h");
9b6d8fcf 8374 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8375 vty_out(vty, "d");
9b6d8fcf 8376 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8377 vty_out(vty, ">");
9b6d8fcf 8378 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8379 vty_out(vty, "=");
8380 else
8381 vty_out(vty, " ");
718e3744 8382
d62a17ae 8383 /* Internal route. */
9b6d8fcf
DS
8384 if (path->peer && (path->peer->as)
8385 && (path->peer->as == path->peer->local_as))
d62a17ae 8386 vty_out(vty, "i");
8387 else
8388 vty_out(vty, " ");
b40d939b 8389}
8390
2ba93fd6
DA
8391static char *bgp_nexthop_hostname(struct peer *peer,
8392 struct bgp_nexthop_cache *bnc)
25b5da8d 8393{
892fedb6 8394 if (peer->hostname
aef999a2 8395 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8396 return peer->hostname;
8397 return NULL;
8398}
8399
b40d939b 8400/* called from terminal list command */
bd494ec5 8401void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8402 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8403 json_object *json_paths, bool wide)
d62a17ae 8404{
aef999a2 8405 int len;
515c2602 8406 struct attr *attr = path->attr;
d62a17ae 8407 json_object *json_path = NULL;
8408 json_object *json_nexthops = NULL;
8409 json_object *json_nexthop_global = NULL;
8410 json_object *json_nexthop_ll = NULL;
6f214dd3 8411 json_object *json_ext_community = NULL;
9df8b37c 8412 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8413 bool nexthop_self =
9b6d8fcf 8414 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8415 bool nexthop_othervrf = false;
43089216 8416 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8417 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8418 char *nexthop_hostname =
8419 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8420 char esi_buf[ESI_STR_LEN];
d62a17ae 8421
8422 if (json_paths)
8423 json_path = json_object_new_object();
8424
8425 /* short status lead text */
9b6d8fcf 8426 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8427
8428 if (!json_paths) {
8429 /* print prefix and mask */
8430 if (!display)
ae248832 8431 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8432 else
ae248832 8433 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8434 } else {
ae248832 8435 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8436 }
47fc97cc 8437
9df8b37c
PZ
8438 /*
8439 * If vrf id of nexthop is different from that of prefix,
8440 * set up printable string to append
8441 */
9b6d8fcf 8442 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8443 const char *self = "";
8444
8445 if (nexthop_self)
8446 self = "<";
8447
8448 nexthop_othervrf = true;
9b6d8fcf 8449 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8450
9b6d8fcf 8451 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8452 snprintf(vrf_id_str, sizeof(vrf_id_str),
8453 "@%s%s", VRFID_NONE_STR, self);
8454 else
8455 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8456 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8457
9b6d8fcf
DS
8458 if (path->extra->bgp_orig->inst_type
8459 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8460
9b6d8fcf 8461 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8462 } else {
8463 const char *self = "";
8464
8465 if (nexthop_self)
8466 self = "<";
8467
8468 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8469 }
8470
445c2480
DS
8471 /*
8472 * For ENCAP and EVPN routes, nexthop address family is not
8473 * neccessarily the same as the prefix address family.
8474 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8475 * EVPN routes are also exchanged with a MP nexthop. Currently,
8476 * this
8477 * is only IPv4, the value will be present in either
8478 * attr->nexthop or
8479 * attr->mp_nexthop_global_in
8480 */
8481 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8482 char buf[BUFSIZ];
8483 char nexthop[128];
8484 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8485
8486 switch (af) {
8487 case AF_INET:
772270f3
QY
8488 snprintf(nexthop, sizeof(nexthop), "%s",
8489 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8490 BUFSIZ));
445c2480
DS
8491 break;
8492 case AF_INET6:
772270f3
QY
8493 snprintf(nexthop, sizeof(nexthop), "%s",
8494 inet_ntop(af, &attr->mp_nexthop_global, buf,
8495 BUFSIZ));
445c2480
DS
8496 break;
8497 default:
772270f3 8498 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8499 break;
d62a17ae 8500 }
d62a17ae 8501
445c2480
DS
8502 if (json_paths) {
8503 json_nexthop_global = json_object_new_object();
8504
515c2602
DA
8505 json_object_string_add(json_nexthop_global, "ip",
8506 nexthop);
8507
939a97f4 8508 if (path->peer->hostname)
515c2602
DA
8509 json_object_string_add(json_nexthop_global,
8510 "hostname",
939a97f4 8511 path->peer->hostname);
515c2602
DA
8512
8513 json_object_string_add(json_nexthop_global, "afi",
8514 (af == AF_INET) ? "ipv4"
8515 : "ipv6");
445c2480
DS
8516 json_object_boolean_true_add(json_nexthop_global,
8517 "used");
aef999a2
DA
8518 } else {
8519 if (nexthop_hostname)
8520 len = vty_out(vty, "%s(%s)%s", nexthop,
8521 nexthop_hostname, vrf_id_str);
8522 else
8523 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8524
ae248832 8525 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8526 if (len < 1)
8527 vty_out(vty, "\n%*s", 36, " ");
8528 else
8529 vty_out(vty, "%*s", len, " ");
8530 }
445c2480
DS
8531 } else if (safi == SAFI_EVPN) {
8532 if (json_paths) {
23d0a753
DA
8533 char buf[BUFSIZ] = {0};
8534
445c2480
DS
8535 json_nexthop_global = json_object_new_object();
8536
515c2602 8537 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8538 inet_ntop(AF_INET,
8539 &attr->nexthop, buf,
8540 sizeof(buf)));
515c2602 8541
939a97f4 8542 if (path->peer->hostname)
515c2602
DA
8543 json_object_string_add(json_nexthop_global,
8544 "hostname",
939a97f4 8545 path->peer->hostname);
515c2602 8546
a4d82a8a
PZ
8547 json_object_string_add(json_nexthop_global, "afi",
8548 "ipv4");
445c2480
DS
8549 json_object_boolean_true_add(json_nexthop_global,
8550 "used");
aef999a2
DA
8551 } else {
8552 if (nexthop_hostname)
8553 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8554 nexthop_hostname, vrf_id_str);
8555 else
8556 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8557 vrf_id_str);
8558
ae248832 8559 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8560 if (len < 1)
8561 vty_out(vty, "\n%*s", 36, " ");
8562 else
8563 vty_out(vty, "%*s", len, " ");
8564 }
d33fc23b 8565 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8566 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8567 if (json_paths) {
23d0a753
DA
8568 char buf[BUFSIZ] = {0};
8569
026b914a 8570 json_nexthop_global = json_object_new_object();
515c2602 8571
026b914a
PG
8572 json_object_string_add(json_nexthop_global,
8573 "afi", "ipv4");
515c2602
DA
8574 json_object_string_add(
8575 json_nexthop_global, "ip",
23d0a753
DA
8576 inet_ntop(AF_INET, &attr->nexthop, buf,
8577 sizeof(buf)));
515c2602 8578
939a97f4 8579 if (path->peer->hostname)
515c2602
DA
8580 json_object_string_add(
8581 json_nexthop_global, "hostname",
939a97f4 8582 path->peer->hostname);
515c2602 8583
50e05855
AD
8584 json_object_boolean_true_add(
8585 json_nexthop_global,
026b914a
PG
8586 "used");
8587 } else {
aef999a2
DA
8588 if (nexthop_hostname)
8589 len = vty_out(vty, "%pI4(%s)%s",
8590 &attr->nexthop,
8591 nexthop_hostname,
8592 vrf_id_str);
8593 else
8594 len = vty_out(vty, "%pI4%s",
8595 &attr->nexthop,
8596 vrf_id_str);
8597
ae248832 8598 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8599 if (len < 1)
8600 vty_out(vty, "\n%*s", 36, " ");
8601 else
8602 vty_out(vty, "%*s", len, " ");
026b914a
PG
8603 }
8604 }
d33fc23b 8605 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8606 if (json_paths) {
23d0a753
DA
8607 char buf[BUFSIZ] = {0};
8608
445c2480 8609 json_nexthop_global = json_object_new_object();
d62a17ae 8610
515c2602 8611 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8612 inet_ntop(AF_INET,
8613 &attr->nexthop, buf,
8614 sizeof(buf)));
515c2602 8615
939a97f4 8616 if (path->peer->hostname)
515c2602
DA
8617 json_object_string_add(json_nexthop_global,
8618 "hostname",
939a97f4 8619 path->peer->hostname);
445c2480 8620
a4d82a8a
PZ
8621 json_object_string_add(json_nexthop_global, "afi",
8622 "ipv4");
445c2480
DS
8623 json_object_boolean_true_add(json_nexthop_global,
8624 "used");
8625 } else {
aef999a2
DA
8626 if (nexthop_hostname)
8627 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8628 nexthop_hostname, vrf_id_str);
8629 else
8630 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8631 vrf_id_str);
9df8b37c 8632
ae248832 8633 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8634 if (len < 1)
8635 vty_out(vty, "\n%*s", 36, " ");
8636 else
8637 vty_out(vty, "%*s", len, " ");
d62a17ae 8638 }
445c2480 8639 }
b05a1c8b 8640
445c2480 8641 /* IPv6 Next Hop */
a4d82a8a 8642 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8643 char buf[BUFSIZ];
d62a17ae 8644
445c2480
DS
8645 if (json_paths) {
8646 json_nexthop_global = json_object_new_object();
a4d82a8a 8647 json_object_string_add(
515c2602
DA
8648 json_nexthop_global, "ip",
8649 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8650 buf, BUFSIZ));
8651
939a97f4 8652 if (path->peer->hostname)
515c2602
DA
8653 json_object_string_add(json_nexthop_global,
8654 "hostname",
939a97f4 8655 path->peer->hostname);
515c2602 8656
a4d82a8a
PZ
8657 json_object_string_add(json_nexthop_global, "afi",
8658 "ipv6");
8659 json_object_string_add(json_nexthop_global, "scope",
8660 "global");
445c2480
DS
8661
8662 /* We display both LL & GL if both have been
8663 * received */
0606039c
DA
8664 if ((attr->mp_nexthop_len
8665 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8666 || (path->peer->conf_if)) {
a4d82a8a 8667 json_nexthop_ll = json_object_new_object();
d62a17ae 8668 json_object_string_add(
515c2602
DA
8669 json_nexthop_ll, "ip",
8670 inet_ntop(AF_INET6,
8671 &attr->mp_nexthop_local, buf,
8672 BUFSIZ));
8673
939a97f4 8674 if (path->peer->hostname)
515c2602
DA
8675 json_object_string_add(
8676 json_nexthop_ll, "hostname",
939a97f4 8677 path->peer->hostname);
515c2602 8678
a4d82a8a
PZ
8679 json_object_string_add(json_nexthop_ll, "afi",
8680 "ipv6");
8681 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8682 "link-local");
d62a17ae 8683
a4d82a8a
PZ
8684 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8685 &attr->mp_nexthop_local)
445c2480
DS
8686 != 0)
8687 && !attr->mp_nexthop_prefer_global)
d62a17ae 8688 json_object_boolean_true_add(
a4d82a8a 8689 json_nexthop_ll, "used");
445c2480
DS
8690 else
8691 json_object_boolean_true_add(
a4d82a8a 8692 json_nexthop_global, "used");
445c2480
DS
8693 } else
8694 json_object_boolean_true_add(
8695 json_nexthop_global, "used");
8696 } else {
8697 /* Display LL if LL/Global both in table unless
8698 * prefer-global is set */
0606039c
DA
8699 if (((attr->mp_nexthop_len
8700 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8701 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8702 || (path->peer->conf_if)) {
8703 if (path->peer->conf_if) {
a4d82a8a 8704 len = vty_out(vty, "%s",
9b6d8fcf 8705 path->peer->conf_if);
ae248832
MK
8706 /* len of IPv6 addr + max len of def
8707 * ifname */
8708 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8709
8710 if (len < 1)
a4d82a8a 8711 vty_out(vty, "\n%*s", 36, " ");
445c2480 8712 else
a4d82a8a 8713 vty_out(vty, "%*s", len, " ");
d62a17ae 8714 } else {
aef999a2
DA
8715 if (nexthop_hostname)
8716 len = vty_out(
8717 vty, "%pI6(%s)%s",
8718 &attr->mp_nexthop_local,
8719 nexthop_hostname,
8720 vrf_id_str);
8721 else
8722 len = vty_out(
8723 vty, "%pI6%s",
8724 &attr->mp_nexthop_local,
8725 vrf_id_str);
8726
ae248832 8727 len = wide ? (41 - len) : (16 - len);
d62a17ae 8728
8729 if (len < 1)
a4d82a8a 8730 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8731 else
a4d82a8a 8732 vty_out(vty, "%*s", len, " ");
d62a17ae 8733 }
445c2480 8734 } else {
aef999a2
DA
8735 if (nexthop_hostname)
8736 len = vty_out(vty, "%pI6(%s)%s",
8737 &attr->mp_nexthop_global,
8738 nexthop_hostname,
8739 vrf_id_str);
8740 else
8741 len = vty_out(vty, "%pI6%s",
8742 &attr->mp_nexthop_global,
8743 vrf_id_str);
8744
ae248832 8745 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8746
8747 if (len < 1)
8748 vty_out(vty, "\n%*s", 36, " ");
8749 else
8750 vty_out(vty, "%*s", len, " ");
d62a17ae 8751 }
8752 }
445c2480 8753 }
718e3744 8754
445c2480
DS
8755 /* MED/Metric */
8756 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8757 if (json_paths)
50e05855 8758 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8759 else if (wide)
8760 vty_out(vty, "%7u", attr->med);
0fbac0b4 8761 else
445c2480 8762 vty_out(vty, "%10u", attr->med);
ae248832
MK
8763 else if (!json_paths) {
8764 if (wide)
8765 vty_out(vty, "%*s", 7, " ");
8766 else
8767 vty_out(vty, "%*s", 10, " ");
8768 }
d62a17ae 8769
445c2480
DS
8770 /* Local Pref */
8771 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8772 if (json_paths)
50e05855 8773 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8774 attr->local_pref);
8775 else
445c2480
DS
8776 vty_out(vty, "%7u", attr->local_pref);
8777 else if (!json_paths)
8778 vty_out(vty, " ");
d62a17ae 8779
445c2480
DS
8780 if (json_paths)
8781 json_object_int_add(json_path, "weight", attr->weight);
8782 else
8783 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8784
445c2480
DS
8785 if (json_paths) {
8786 char buf[BUFSIZ];
a4d82a8a
PZ
8787 json_object_string_add(
8788 json_path, "peerId",
9b6d8fcf 8789 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8790 }
b05a1c8b 8791
445c2480
DS
8792 /* Print aspath */
8793 if (attr->aspath) {
0fbac0b4 8794 if (json_paths)
50e05855 8795 json_object_string_add(json_path, "path",
0fbac0b4
DA
8796 attr->aspath->str);
8797 else
445c2480 8798 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8799 }
f1aa5d8a 8800
445c2480
DS
8801 /* Print origin */
8802 if (json_paths)
a4d82a8a
PZ
8803 json_object_string_add(json_path, "origin",
8804 bgp_origin_long_str[attr->origin]);
445c2480
DS
8805 else
8806 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8807
9df8b37c 8808 if (json_paths) {
d071f237 8809 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8810 json_object_string_add(json_path, "esi",
8811 esi_to_str(&attr->esi,
8812 esi_buf, sizeof(esi_buf)));
8813 }
6f214dd3
CS
8814 if (safi == SAFI_EVPN &&
8815 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8816 json_ext_community = json_object_new_object();
8817 json_object_string_add(json_ext_community,
8818 "string",
8819 attr->ecommunity->str);
8820 json_object_object_add(json_path,
8821 "extendedCommunity",
8822 json_ext_community);
8823 }
8824
9df8b37c
PZ
8825 if (nexthop_self)
8826 json_object_boolean_true_add(json_path,
8827 "announceNexthopSelf");
8828 if (nexthop_othervrf) {
8829 json_object_string_add(json_path, "nhVrfName",
8830 nexthop_vrfname);
8831
8832 json_object_int_add(json_path, "nhVrfId",
8833 ((nexthop_vrfid == VRF_UNKNOWN)
8834 ? -1
8835 : (int)nexthop_vrfid));
8836 }
8837 }
8838
d62a17ae 8839 if (json_paths) {
8840 if (json_nexthop_global || json_nexthop_ll) {
8841 json_nexthops = json_object_new_array();
f1aa5d8a 8842
d62a17ae 8843 if (json_nexthop_global)
8844 json_object_array_add(json_nexthops,
8845 json_nexthop_global);
f1aa5d8a 8846
d62a17ae 8847 if (json_nexthop_ll)
8848 json_object_array_add(json_nexthops,
8849 json_nexthop_ll);
f1aa5d8a 8850
d62a17ae 8851 json_object_object_add(json_path, "nexthops",
8852 json_nexthops);
8853 }
8854
8855 json_object_array_add(json_paths, json_path);
8856 } else {
8857 vty_out(vty, "\n");
6f214dd3 8858
b5e140c8 8859 if (safi == SAFI_EVPN) {
229587fb
AK
8860 struct bgp_path_es_info *path_es_info = NULL;
8861
d071f237 8862 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8863 /* XXX - add these params to the json out */
b5e140c8 8864 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8865 vty_out(vty, "ESI:%s",
8866 esi_to_str(&attr->esi, esi_buf,
8867 sizeof(esi_buf)));
60605cbc
AK
8868
8869 if (path->extra && path->extra->mh_info)
8870 path_es_info =
8871 path->extra->mh_info->es_info;
8872
229587fb
AK
8873 if (path_es_info && path_es_info->es)
8874 vty_out(vty, " VNI: %u",
8875 path_es_info->vni);
8876 vty_out(vty, "\n");
b5e140c8
AK
8877 }
8878 if (attr->flag &
8879 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8880 vty_out(vty, "%*s", 20, " ");
8881 vty_out(vty, "%s\n", attr->ecommunity->str);
8882 }
6f214dd3
CS
8883 }
8884
49e5a4a0 8885#ifdef ENABLE_BGP_VNC
d62a17ae 8886 /* prints an additional line, indented, with VNC info, if
8887 * present */
8888 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8889 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8890#endif
d62a17ae 8891 }
8892}
718e3744 8893
8894/* called from terminal list command */
5f040085
DS
8895void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8896 struct attr *attr, safi_t safi, bool use_json,
ae248832 8897 json_object *json_ar, bool wide)
d62a17ae 8898{
8899 json_object *json_status = NULL;
8900 json_object *json_net = NULL;
aef999a2 8901 int len;
d62a17ae 8902 char buff[BUFSIZ];
dc387b0f 8903
d62a17ae 8904 /* Route status display. */
8905 if (use_json) {
8906 json_status = json_object_new_object();
8907 json_net = json_object_new_object();
8908 } else {
8909 vty_out(vty, "*");
8910 vty_out(vty, ">");
8911 vty_out(vty, " ");
8912 }
718e3744 8913
d62a17ae 8914 /* print prefix and mask */
50e05855 8915 if (use_json) {
dc387b0f
LK
8916 if (safi == SAFI_EVPN)
8917 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8918 else if (p->family == AF_INET || p->family == AF_INET6) {
8919 json_object_string_add(
8920 json_net, "addrPrefix",
8921 inet_ntop(p->family, &p->u.prefix, buff,
8922 BUFSIZ));
8923 json_object_int_add(json_net, "prefixLen",
8924 p->prefixlen);
8925 prefix2str(p, buff, PREFIX_STRLEN);
8926 json_object_string_add(json_net, "network", buff);
8927 }
50e05855 8928 } else
ae248832 8929 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8930
8931 /* Print attribute */
8932 if (attr) {
8933 if (use_json) {
23d0a753
DA
8934 char buf[BUFSIZ] = {0};
8935
d62a17ae 8936 if (p->family == AF_INET
8937 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8938 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8939 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8940 json_object_string_add(
8941 json_net, "nextHop",
23d0a753
DA
8942 inet_ntop(
8943 AF_INET,
8944 &attr->mp_nexthop_global_in,
8945 buf, sizeof(buf)));
d62a17ae 8946 else
8947 json_object_string_add(
8948 json_net, "nextHop",
23d0a753
DA
8949 inet_ntop(AF_INET,
8950 &attr->nexthop, buf,
8951 sizeof(buf)));
d62a17ae 8952 } else if (p->family == AF_INET6
8953 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8954 char buf[BUFSIZ];
8955
8956 json_object_string_add(
aa0a10fc 8957 json_net, "nextHopGlobal",
d62a17ae 8958 inet_ntop(AF_INET6,
8959 &attr->mp_nexthop_global, buf,
8960 BUFSIZ));
23d0a753
DA
8961 } else if (p->family == AF_EVPN
8962 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8963 char buf[BUFSIZ] = {0};
8964
8965 json_object_string_add(
8966 json_net, "nextHop",
8967 inet_ntop(AF_INET,
8968 &attr->mp_nexthop_global_in,
8969 buf, sizeof(buf)));
8970 }
d62a17ae 8971
8972 if (attr->flag
8973 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8974 json_object_int_add(json_net, "metric",
8975 attr->med);
8976
0fbac0b4 8977 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8978 json_object_int_add(json_net, "locPrf",
0fbac0b4 8979 attr->local_pref);
d62a17ae 8980
8981 json_object_int_add(json_net, "weight", attr->weight);
8982
8983 /* Print aspath */
0fbac0b4 8984 if (attr->aspath)
50e05855 8985 json_object_string_add(json_net, "path",
0fbac0b4 8986 attr->aspath->str);
d62a17ae 8987
8988 /* Print origin */
8989 json_object_string_add(json_net, "bgpOriginCode",
8990 bgp_origin_str[attr->origin]);
8991 } else {
8992 if (p->family == AF_INET
8993 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8994 || safi == SAFI_EVPN
8995 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8996 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8997 || safi == SAFI_EVPN)
23d0a753
DA
8998 vty_out(vty, "%-16pI4",
8999 &attr->mp_nexthop_global_in);
ae248832 9000 else if (wide)
23d0a753 9001 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9002 else
23d0a753 9003 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9004 } else if (p->family == AF_INET6
9005 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9006 char buf[BUFSIZ];
9007
9008 len = vty_out(
9009 vty, "%s",
9010 inet_ntop(AF_INET6,
9011 &attr->mp_nexthop_global, buf,
9012 BUFSIZ));
ae248832 9013 len = wide ? (41 - len) : (16 - len);
d62a17ae 9014 if (len < 1)
9015 vty_out(vty, "\n%*s", 36, " ");
9016 else
9017 vty_out(vty, "%*s", len, " ");
9018 }
9019 if (attr->flag
9020 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9021 if (wide)
9022 vty_out(vty, "%7u", attr->med);
9023 else
9024 vty_out(vty, "%10u", attr->med);
9025 else if (wide)
9026 vty_out(vty, " ");
d62a17ae 9027 else
9028 vty_out(vty, " ");
718e3744 9029
d62a17ae 9030 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9031 vty_out(vty, "%7u", attr->local_pref);
9032 else
9033 vty_out(vty, " ");
9034
9035 vty_out(vty, "%7u ", attr->weight);
9036
9037 /* Print aspath */
9038 if (attr->aspath)
9039 aspath_print_vty(vty, "%s", attr->aspath, " ");
9040
9041 /* Print origin */
9042 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9043 }
9044 }
9045 if (use_json) {
9046 json_object_boolean_true_add(json_status, "*");
9047 json_object_boolean_true_add(json_status, ">");
9048 json_object_object_add(json_net, "appliedStatusSymbols",
9049 json_status);
1608ff77 9050
dc387b0f
LK
9051 prefix2str(p, buff, PREFIX_STRLEN);
9052 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9053 } else
9054 vty_out(vty, "\n");
9055}
9056
bd494ec5 9057void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9058 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9059 json_object *json)
9060{
9061 json_object *json_out = NULL;
9062 struct attr *attr;
9063 mpls_label_t label = MPLS_INVALID_LABEL;
9064
9b6d8fcf 9065 if (!path->extra)
d62a17ae 9066 return;
9067
9068 if (json)
9069 json_out = json_object_new_object();
9070
9071 /* short status lead text */
9b6d8fcf 9072 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9073
9074 /* print prefix and mask */
9075 if (json == NULL) {
9076 if (!display)
ae248832 9077 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9078 else
9079 vty_out(vty, "%*s", 17, " ");
9080 }
9081
9082 /* Print attribute */
9b6d8fcf 9083 attr = path->attr;
05864da7
DS
9084 if (((p->family == AF_INET)
9085 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9086 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9087 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9088 char buf[BUFSIZ] = {0};
9089
05864da7
DS
9090 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9091 || safi == SAFI_EVPN) {
9092 if (json)
9093 json_object_string_add(
9094 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9095 inet_ntop(AF_INET,
9096 &attr->mp_nexthop_global_in,
9097 buf, sizeof(buf)));
05864da7 9098 else
23d0a753
DA
9099 vty_out(vty, "%-16pI4",
9100 &attr->mp_nexthop_global_in);
05864da7
DS
9101 } else {
9102 if (json)
9103 json_object_string_add(
9104 json_out, "nexthop",
23d0a753
DA
9105 inet_ntop(AF_INET, &attr->nexthop, buf,
9106 sizeof(buf)));
05864da7 9107 else
23d0a753 9108 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9109 }
9110 } else if (((p->family == AF_INET6)
9111 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9112 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9113 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9114 char buf_a[512];
9115
9116 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9117 if (json)
9118 json_object_string_add(
9119 json_out, "mpNexthopGlobalIn",
9120 inet_ntop(AF_INET6,
9121 &attr->mp_nexthop_global,
9122 buf_a, sizeof(buf_a)));
9123 else
9124 vty_out(vty, "%s",
9125 inet_ntop(AF_INET6,
9126 &attr->mp_nexthop_global,
9127 buf_a, sizeof(buf_a)));
9128 } else if (attr->mp_nexthop_len
9129 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9130 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9131 &attr->mp_nexthop_global,
9132 &attr->mp_nexthop_local);
9133 if (json)
9134 json_object_string_add(json_out,
9135 "mpNexthopGlobalLocal",
9136 buf_a);
9137 else
9138 vty_out(vty, "%s", buf_a);
d62a17ae 9139 }
9140 }
9141
9b6d8fcf 9142 label = decode_label(&path->extra->label[0]);
d62a17ae 9143
9144 if (bgp_is_valid_label(&label)) {
9145 if (json) {
9146 json_object_int_add(json_out, "notag", label);
9147 json_object_array_add(json, json_out);
9148 } else {
9149 vty_out(vty, "notag/%d", label);
9150 vty_out(vty, "\n");
9151 }
9152 }
9153}
718e3744 9154
bd494ec5 9155void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9156 struct bgp_path_info *path, int display,
d62a17ae 9157 json_object *json_paths)
718e3744 9158{
d62a17ae 9159 struct attr *attr;
14f51eba 9160 char buf[BUFSIZ] = {0};
d62a17ae 9161 json_object *json_path = NULL;
14f51eba
LK
9162 json_object *json_nexthop = NULL;
9163 json_object *json_overlay = NULL;
856ca177 9164
9b6d8fcf 9165 if (!path->extra)
d62a17ae 9166 return;
718e3744 9167
14f51eba
LK
9168 if (json_paths) {
9169 json_path = json_object_new_object();
9170 json_overlay = json_object_new_object();
9171 json_nexthop = json_object_new_object();
9172 }
9173
d62a17ae 9174 /* short status lead text */
9b6d8fcf 9175 route_vty_short_status_out(vty, path, json_path);
856ca177 9176
d62a17ae 9177 /* print prefix and mask */
9178 if (!display)
ae248832 9179 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9180 else
9181 vty_out(vty, "%*s", 17, " ");
9182
9183 /* Print attribute */
9b6d8fcf 9184 attr = path->attr;
05864da7
DS
9185 char buf1[BUFSIZ];
9186 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9187
05864da7
DS
9188 switch (af) {
9189 case AF_INET:
9190 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9191 if (!json_path) {
9192 vty_out(vty, "%-16s", buf);
9193 } else {
9194 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9195
05864da7 9196 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9197
05864da7
DS
9198 json_object_object_add(json_path, "nexthop",
9199 json_nexthop);
9200 }
9201 break;
9202 case AF_INET6:
9203 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9204 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9205 if (!json_path) {
9206 vty_out(vty, "%s(%s)", buf, buf1);
9207 } else {
9208 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9209
05864da7
DS
9210 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9211 buf1);
14f51eba 9212
05864da7 9213 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9214
05864da7
DS
9215 json_object_object_add(json_path, "nexthop",
9216 json_nexthop);
9217 }
9218 break;
9219 default:
9220 if (!json_path) {
9221 vty_out(vty, "?");
9222 } else {
9223 json_object_string_add(json_nexthop, "Error",
9224 "Unsupported address-family");
d62a17ae 9225 }
05864da7 9226 }
988258b4 9227
6c924775
DS
9228 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9229
9230 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9231 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9232 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9233 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9234
05864da7
DS
9235 if (!json_path)
9236 vty_out(vty, "/%s", buf);
9237 else
9238 json_object_string_add(json_overlay, "gw", buf);
9239
9240 if (attr->ecommunity) {
9241 char *mac = NULL;
9242 struct ecommunity_val *routermac = ecommunity_lookup(
9243 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9244 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9245
9246 if (routermac)
9247 mac = ecom_mac2str((char *)routermac->val);
9248 if (mac) {
9249 if (!json_path) {
c4efd0f4 9250 vty_out(vty, "/%s", mac);
05864da7
DS
9251 } else {
9252 json_object_string_add(json_overlay, "rmac",
9253 mac);
988258b4 9254 }
05864da7 9255 XFREE(MTYPE_TMP, mac);
988258b4 9256 }
05864da7 9257 }
718e3744 9258
05864da7
DS
9259 if (!json_path) {
9260 vty_out(vty, "\n");
9261 } else {
9262 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9263
05864da7 9264 json_object_array_add(json_paths, json_path);
14f51eba 9265 }
d62a17ae 9266}
718e3744 9267
d62a17ae 9268/* dampening route */
5f040085
DS
9269static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9270 struct bgp_path_info *path, int display,
9271 afi_t afi, safi_t safi, bool use_json,
9272 json_object *json)
d62a17ae 9273{
9274 struct attr *attr;
9275 int len;
9276 char timebuf[BGP_UPTIME_LEN];
9277
9278 /* short status lead text */
9b6d8fcf 9279 route_vty_short_status_out(vty, path, json);
d62a17ae 9280
9281 /* print prefix and mask */
9282 if (!use_json) {
9283 if (!display)
ae248832 9284 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9285 else
9286 vty_out(vty, "%*s", 17, " ");
9287 }
9288
9b6d8fcf 9289 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9290 len = 17 - len;
9291 if (len < 1) {
9292 if (!use_json)
9293 vty_out(vty, "\n%*s", 34, " ");
9294 } else {
9295 if (use_json)
9296 json_object_int_add(json, "peerHost", len);
9297 else
9298 vty_out(vty, "%*s", len, " ");
9299 }
9300
9301 if (use_json)
a935f597
DA
9302 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9303 safi, use_json, json);
d62a17ae 9304 else
9b6d8fcf
DS
9305 vty_out(vty, "%s ",
9306 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9307 BGP_UPTIME_LEN, afi, safi,
9308 use_json, json));
d62a17ae 9309
9310 /* Print attribute */
9b6d8fcf 9311 attr = path->attr;
d62a17ae 9312
05864da7
DS
9313 /* Print aspath */
9314 if (attr->aspath) {
d62a17ae 9315 if (use_json)
05864da7
DS
9316 json_object_string_add(json, "asPath",
9317 attr->aspath->str);
d62a17ae 9318 else
05864da7 9319 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9320 }
05864da7
DS
9321
9322 /* Print origin */
9323 if (use_json)
9324 json_object_string_add(json, "origin",
9325 bgp_origin_str[attr->origin]);
9326 else
9327 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9328
d62a17ae 9329 if (!use_json)
9330 vty_out(vty, "\n");
9331}
718e3744 9332
d62a17ae 9333/* flap route */
5f040085
DS
9334static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9335 struct bgp_path_info *path, int display,
9336 afi_t afi, safi_t safi, bool use_json,
9337 json_object *json)
784d3a42 9338{
d62a17ae 9339 struct attr *attr;
9340 struct bgp_damp_info *bdi;
9341 char timebuf[BGP_UPTIME_LEN];
9342 int len;
784d3a42 9343
9b6d8fcf 9344 if (!path->extra)
d62a17ae 9345 return;
784d3a42 9346
9b6d8fcf 9347 bdi = path->extra->damp_info;
784d3a42 9348
d62a17ae 9349 /* short status lead text */
9b6d8fcf 9350 route_vty_short_status_out(vty, path, json);
784d3a42 9351
d62a17ae 9352 /* print prefix and mask */
9353 if (!use_json) {
9354 if (!display)
ae248832 9355 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9356 else
9357 vty_out(vty, "%*s", 17, " ");
9358 }
784d3a42 9359
9b6d8fcf 9360 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9361 len = 16 - len;
9362 if (len < 1) {
9363 if (!use_json)
9364 vty_out(vty, "\n%*s", 33, " ");
9365 } else {
9366 if (use_json)
9367 json_object_int_add(json, "peerHost", len);
9368 else
9369 vty_out(vty, "%*s", len, " ");
9370 }
784d3a42 9371
d62a17ae 9372 len = vty_out(vty, "%d", bdi->flap);
9373 len = 5 - len;
9374 if (len < 1) {
9375 if (!use_json)
9376 vty_out(vty, " ");
9377 } else {
9378 if (use_json)
9379 json_object_int_add(json, "bdiFlap", len);
9380 else
9381 vty_out(vty, "%*s", len, " ");
9382 }
9383
9384 if (use_json)
9385 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9386 json);
9387 else
996c9314
LB
9388 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9389 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9390
9b6d8fcf
DS
9391 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9392 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9393 if (use_json)
9b6d8fcf 9394 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9395 BGP_UPTIME_LEN, afi, safi,
9396 use_json, json);
d62a17ae 9397 else
9398 vty_out(vty, "%s ",
9b6d8fcf 9399 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9400 BGP_UPTIME_LEN, afi,
9401 safi, use_json, json));
d62a17ae 9402 } else {
9403 if (!use_json)
9404 vty_out(vty, "%*s ", 8, " ");
9405 }
9406
9407 /* Print attribute */
9b6d8fcf 9408 attr = path->attr;
d62a17ae 9409
05864da7
DS
9410 /* Print aspath */
9411 if (attr->aspath) {
d62a17ae 9412 if (use_json)
05864da7
DS
9413 json_object_string_add(json, "asPath",
9414 attr->aspath->str);
d62a17ae 9415 else
05864da7 9416 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9417 }
05864da7
DS
9418
9419 /* Print origin */
9420 if (use_json)
9421 json_object_string_add(json, "origin",
9422 bgp_origin_str[attr->origin]);
9423 else
9424 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9425
d62a17ae 9426 if (!use_json)
9427 vty_out(vty, "\n");
9428}
9429
9430static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9431 int *first, const char *header,
9432 json_object *json_adv_to)
9433{
9434 char buf1[INET6_ADDRSTRLEN];
9435 json_object *json_peer = NULL;
9436
9437 if (json_adv_to) {
9438 /* 'advertised-to' is a dictionary of peers we have advertised
9439 * this
9440 * prefix too. The key is the peer's IP or swpX, the value is
9441 * the
9442 * hostname if we know it and "" if not.
9443 */
9444 json_peer = json_object_new_object();
9445
9446 if (peer->hostname)
9447 json_object_string_add(json_peer, "hostname",
9448 peer->hostname);
9449
9450 if (peer->conf_if)
9451 json_object_object_add(json_adv_to, peer->conf_if,
9452 json_peer);
9453 else
9454 json_object_object_add(
9455 json_adv_to,
9456 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9457 json_peer);
9458 } else {
9459 if (*first) {
9460 vty_out(vty, "%s", header);
9461 *first = 0;
9462 }
9463
9464 if (peer->hostname
892fedb6 9465 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9466 if (peer->conf_if)
9467 vty_out(vty, " %s(%s)", peer->hostname,
9468 peer->conf_if);
9469 else
9470 vty_out(vty, " %s(%s)", peer->hostname,
9471 sockunion2str(&peer->su, buf1,
9472 SU_ADDRSTRLEN));
9473 } else {
9474 if (peer->conf_if)
9475 vty_out(vty, " %s", peer->conf_if);
9476 else
9477 vty_out(vty, " %s",
9478 sockunion2str(&peer->su, buf1,
9479 SU_ADDRSTRLEN));
9480 }
9481 }
784d3a42
PG
9482}
9483
dcc68b5e
MS
9484static void route_vty_out_tx_ids(struct vty *vty,
9485 struct bgp_addpath_info_data *d)
9486{
9487 int i;
9488
9489 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9490 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9491 d->addpath_tx_id[i],
9492 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9493 }
9494}
9495
5e4d4c8a 9496static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9497 struct bgp_path_info *pi,
9498 struct attr *attr,
9499 json_object *json_path)
5e4d4c8a
AK
9500{
9501 char esi_buf[ESI_STR_LEN];
9502 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9503 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9504 ATTR_ES_PEER_ROUTER);
9505 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9506 ATTR_ES_PEER_ACTIVE);
9507 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9508 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9509 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9510 if (json_path) {
9511 json_object *json_es_info = NULL;
9512
9513 json_object_string_add(
9514 json_path, "esi",
9515 esi_buf);
9516 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9517 json_es_info = json_object_new_object();
9518 if (es_local)
9519 json_object_boolean_true_add(
9520 json_es_info, "localEs");
9521 if (peer_active)
9522 json_object_boolean_true_add(
9523 json_es_info, "peerActive");
9524 if (peer_proxy)
9525 json_object_boolean_true_add(
9526 json_es_info, "peerProxy");
9527 if (peer_router)
9528 json_object_boolean_true_add(
9529 json_es_info, "peerRouter");
9530 if (attr->mm_sync_seqnum)
9531 json_object_int_add(
9532 json_es_info, "peerSeq",
9533 attr->mm_sync_seqnum);
9534 json_object_object_add(
9535 json_path, "es_info",
9536 json_es_info);
9537 }
9538 } else {
9539 if (bgp_evpn_attr_is_sync(attr))
9540 vty_out(vty,
9541 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9542 esi_buf,
9543 es_local ? "local-es":"",
9544 peer_proxy ? "proxy " : "",
9545 peer_active ? "active ":"",
9546 peer_router ? "router ":"",
9547 attr->mm_sync_seqnum);
9548 else
9549 vty_out(vty, " ESI %s %s\n",
9550 esi_buf,
9551 es_local ? "local-es":"");
9552 }
9553}
9554
4933eaaf
DS
9555void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9556 struct bgp_path_info *path, afi_t afi, safi_t safi,
9557 enum rpki_states curr_state, json_object *json_paths)
d62a17ae 9558{
9559 char buf[INET6_ADDRSTRLEN];
9560 char buf1[BUFSIZ];
515c2602 9561 struct attr *attr = path->attr;
d62a17ae 9562 int sockunion_vty_out(struct vty *, union sockunion *);
9563 time_t tbuf;
9564 json_object *json_bestpath = NULL;
9565 json_object *json_cluster_list = NULL;
9566 json_object *json_cluster_list_list = NULL;
9567 json_object *json_ext_community = NULL;
9568 json_object *json_last_update = NULL;
7fd077aa 9569 json_object *json_pmsi = NULL;
d62a17ae 9570 json_object *json_nexthop_global = NULL;
9571 json_object *json_nexthop_ll = NULL;
9572 json_object *json_nexthops = NULL;
9573 json_object *json_path = NULL;
9574 json_object *json_peer = NULL;
9575 json_object *json_string = NULL;
9576 json_object *json_adv_to = NULL;
9577 int first = 0;
9578 struct listnode *node, *nnode;
9579 struct peer *peer;
9580 int addpath_capable;
9581 int has_adj;
9582 unsigned int first_as;
1defdda8 9583 bool nexthop_self =
9b6d8fcf 9584 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9585 int i;
2ba93fd6
DA
9586 char *nexthop_hostname =
9587 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9588
9589 if (json_paths) {
9590 json_path = json_object_new_object();
9591 json_peer = json_object_new_object();
9592 json_nexthop_global = json_object_new_object();
9593 }
9594
44c69747 9595 if (path->extra) {
b57ba6d2 9596 char tag_buf[30];
d62a17ae 9597
d62a17ae 9598 tag_buf[0] = '\0';
9b6d8fcf
DS
9599 if (path->extra && path->extra->num_labels) {
9600 bgp_evpn_label2str(path->extra->label,
9601 path->extra->num_labels, tag_buf,
a4d82a8a 9602 sizeof(tag_buf));
d62a17ae 9603 }
d7325ee7 9604 if (safi == SAFI_EVPN) {
44c69747 9605 if (!json_paths) {
2dbe669b
DA
9606 vty_out(vty, " Route %pFX",
9607 (struct prefix_evpn *)
9608 bgp_dest_get_prefix(bn));
44c69747
LK
9609 if (tag_buf[0] != '\0')
9610 vty_out(vty, " VNI %s", tag_buf);
9611 vty_out(vty, "\n");
9612 } else {
9613 if (tag_buf[0])
9614 json_object_string_add(json_path, "VNI",
9615 tag_buf);
9616 }
d7325ee7
DD
9617 }
9618
44c69747 9619 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9620 struct bgp_path_info *parent_ri;
9bcb3eef 9621 struct bgp_dest *dest, *pdest;
d62a17ae 9622
9b6d8fcf 9623 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9624 dest = parent_ri->net;
9625 if (dest && dest->pdest) {
9626 pdest = dest->pdest;
9627 prefix_rd2str(
9628 (struct prefix_rd *)bgp_dest_get_prefix(
9629 pdest),
9630 buf1, sizeof(buf1));
d7325ee7 9631 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9632 vty_out(vty,
58bff4d1 9633 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9634 buf1,
9635 (struct prefix_evpn *)
9636 bgp_dest_get_prefix(
9637 dest),
9638 tag_buf);
58bff4d1
AK
9639 if (attr->es_flags & ATTR_ES_L3_NHG)
9640 vty_out(vty, ", L3NHG %s",
9641 (attr->es_flags
9642 & ATTR_ES_L3_NHG_ACTIVE)
9643 ? "active"
9644 : "inactive");
9645 vty_out(vty, "\n");
9646
d7325ee7 9647 } else
2dbe669b
DA
9648 vty_out(vty,
9649 " Imported from %s:%pFX\n",
9650 buf1,
9651 (struct prefix_evpn *)
9652 bgp_dest_get_prefix(
9653 dest));
d62a17ae 9654 }
9655 }
9656 }
d62a17ae 9657
05864da7
DS
9658 /* Line1 display AS-path, Aggregator */
9659 if (attr->aspath) {
9660 if (json_paths) {
9661 if (!attr->aspath->json)
9662 aspath_str_update(attr->aspath, true);
9663 json_object_lock(attr->aspath->json);
9664 json_object_object_add(json_path, "aspath",
9665 attr->aspath->json);
9666 } else {
9667 if (attr->aspath->segments)
9668 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9669 else
05864da7 9670 vty_out(vty, " Local");
d62a17ae 9671 }
05864da7 9672 }
d62a17ae 9673
05864da7
DS
9674 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9675 if (json_paths)
9676 json_object_boolean_true_add(json_path, "removed");
9677 else
9678 vty_out(vty, ", (removed)");
9679 }
d62a17ae 9680
05864da7
DS
9681 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9682 if (json_paths)
9683 json_object_boolean_true_add(json_path, "stale");
9684 else
9685 vty_out(vty, ", (stale)");
9686 }
d62a17ae 9687
05864da7
DS
9688 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9689 if (json_paths) {
23d0a753
DA
9690 char buf[BUFSIZ] = {0};
9691
05864da7
DS
9692 json_object_int_add(json_path, "aggregatorAs",
9693 attr->aggregator_as);
23d0a753
DA
9694 json_object_string_add(json_path, "aggregatorId",
9695 inet_ntop(AF_INET,
9696 &attr->aggregator_addr,
9697 buf, sizeof(buf)));
05864da7 9698 } else {
88d495a9
DA
9699 vty_out(vty, ", (aggregated by %u %pI4)",
9700 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9701 }
05864da7 9702 }
d62a17ae 9703
05864da7
DS
9704 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9705 PEER_FLAG_REFLECTOR_CLIENT)) {
9706 if (json_paths)
9707 json_object_boolean_true_add(json_path,
9708 "rxedFromRrClient");
9709 else
9710 vty_out(vty, ", (Received from a RR-client)");
9711 }
d62a17ae 9712
05864da7
DS
9713 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9714 PEER_FLAG_RSERVER_CLIENT)) {
9715 if (json_paths)
9716 json_object_boolean_true_add(json_path,
9717 "rxedFromRsClient");
9718 else
9719 vty_out(vty, ", (Received from a RS-client)");
9720 }
d62a17ae 9721
05864da7
DS
9722 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9723 if (json_paths)
9724 json_object_boolean_true_add(json_path,
9725 "dampeningHistoryEntry");
9726 else
9727 vty_out(vty, ", (history entry)");
9728 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9729 if (json_paths)
9730 json_object_boolean_true_add(json_path,
9731 "dampeningSuppressed");
9732 else
9733 vty_out(vty, ", (suppressed due to dampening)");
9734 }
d62a17ae 9735
05864da7
DS
9736 if (!json_paths)
9737 vty_out(vty, "\n");
d62a17ae 9738
05864da7
DS
9739 /* Line2 display Next-hop, Neighbor, Router-id */
9740 /* Display the nexthop */
9bcb3eef 9741 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9742
9743 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9744 || bn_p->family == AF_EVPN)
05864da7
DS
9745 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9746 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9747 char buf[BUFSIZ] = {0};
9748
05864da7
DS
9749 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9750 || safi == SAFI_EVPN) {
515c2602 9751 if (json_paths) {
d62a17ae 9752 json_object_string_add(
515c2602 9753 json_nexthop_global, "ip",
23d0a753
DA
9754 inet_ntop(AF_INET,
9755 &attr->mp_nexthop_global_in,
9756 buf, sizeof(buf)));
515c2602 9757
939a97f4 9758 if (path->peer->hostname)
515c2602
DA
9759 json_object_string_add(
9760 json_nexthop_global, "hostname",
939a97f4 9761 path->peer->hostname);
aef999a2
DA
9762 } else {
9763 if (nexthop_hostname)
9764 vty_out(vty, " %pI4(%s)",
9765 &attr->mp_nexthop_global_in,
9766 nexthop_hostname);
9767 else
9768 vty_out(vty, " %pI4",
9769 &attr->mp_nexthop_global_in);
9770 }
d62a17ae 9771 } else {
515c2602 9772 if (json_paths) {
05864da7 9773 json_object_string_add(
515c2602 9774 json_nexthop_global, "ip",
23d0a753
DA
9775 inet_ntop(AF_INET, &attr->nexthop, buf,
9776 sizeof(buf)));
515c2602 9777
939a97f4 9778 if (path->peer->hostname)
515c2602
DA
9779 json_object_string_add(
9780 json_nexthop_global, "hostname",
939a97f4 9781 path->peer->hostname);
aef999a2
DA
9782 } else {
9783 if (nexthop_hostname)
9784 vty_out(vty, " %pI4(%s)",
9785 &attr->nexthop,
9786 nexthop_hostname);
9787 else
9788 vty_out(vty, " %pI4",
9789 &attr->nexthop);
9790 }
d62a17ae 9791 }
9792
05864da7
DS
9793 if (json_paths)
9794 json_object_string_add(json_nexthop_global, "afi",
9795 "ipv4");
9796 } else {
9797 if (json_paths) {
9798 json_object_string_add(
515c2602
DA
9799 json_nexthop_global, "ip",
9800 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9801 buf, INET6_ADDRSTRLEN));
9802
939a97f4 9803 if (path->peer->hostname)
515c2602
DA
9804 json_object_string_add(json_nexthop_global,
9805 "hostname",
939a97f4 9806 path->peer->hostname);
515c2602 9807
05864da7
DS
9808 json_object_string_add(json_nexthop_global, "afi",
9809 "ipv6");
9810 json_object_string_add(json_nexthop_global, "scope",
9811 "global");
9812 } else {
aef999a2
DA
9813 if (nexthop_hostname)
9814 vty_out(vty, " %pI6(%s)",
9815 &attr->mp_nexthop_global,
9816 nexthop_hostname);
9817 else
9818 vty_out(vty, " %pI6",
9819 &attr->mp_nexthop_global);
d62a17ae 9820 }
05864da7 9821 }
d62a17ae 9822
05864da7
DS
9823 /* Display the IGP cost or 'inaccessible' */
9824 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9825 if (json_paths)
9826 json_object_boolean_false_add(json_nexthop_global,
9827 "accessible");
9828 else
9829 vty_out(vty, " (inaccessible)");
9830 } else {
9831 if (path->extra && path->extra->igpmetric) {
d62a17ae 9832 if (json_paths)
05864da7
DS
9833 json_object_int_add(json_nexthop_global,
9834 "metric",
9835 path->extra->igpmetric);
d62a17ae 9836 else
05864da7
DS
9837 vty_out(vty, " (metric %u)",
9838 path->extra->igpmetric);
d62a17ae 9839 }
9840
05864da7 9841 /* IGP cost is 0, display this only for json */
d62a17ae 9842 else {
d62a17ae 9843 if (json_paths)
05864da7
DS
9844 json_object_int_add(json_nexthop_global,
9845 "metric", 0);
d62a17ae 9846 }
d62a17ae 9847
05864da7
DS
9848 if (json_paths)
9849 json_object_boolean_true_add(json_nexthop_global,
9850 "accessible");
9851 }
d62a17ae 9852
05864da7
DS
9853 /* Display peer "from" output */
9854 /* This path was originated locally */
9855 if (path->peer == bgp->peer_self) {
d62a17ae 9856
05864da7 9857 if (safi == SAFI_EVPN
b54892e0 9858 || (bn_p->family == AF_INET
05864da7 9859 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9860 if (json_paths)
05864da7
DS
9861 json_object_string_add(json_peer, "peerId",
9862 "0.0.0.0");
d62a17ae 9863 else
05864da7
DS
9864 vty_out(vty, " from 0.0.0.0 ");
9865 } else {
d62a17ae 9866 if (json_paths)
05864da7
DS
9867 json_object_string_add(json_peer, "peerId",
9868 "::");
d62a17ae 9869 else
05864da7 9870 vty_out(vty, " from :: ");
d62a17ae 9871 }
d62a17ae 9872
23d0a753
DA
9873 if (json_paths) {
9874 char buf[BUFSIZ] = {0};
9875
05864da7 9876 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9877 inet_ntop(AF_INET,
9878 &bgp->router_id, buf,
9879 sizeof(buf)));
9880 } else {
9881 vty_out(vty, "(%pI4)", &bgp->router_id);
9882 }
05864da7 9883 }
d62a17ae 9884
05864da7
DS
9885 /* We RXed this path from one of our peers */
9886 else {
9887
9888 if (json_paths) {
9889 json_object_string_add(json_peer, "peerId",
9890 sockunion2str(&path->peer->su,
9891 buf,
9892 SU_ADDRSTRLEN));
9893 json_object_string_add(json_peer, "routerId",
9894 inet_ntop(AF_INET,
9895 &path->peer->remote_id,
9896 buf1, sizeof(buf1)));
9897
9898 if (path->peer->hostname)
9899 json_object_string_add(json_peer, "hostname",
9900 path->peer->hostname);
9901
9902 if (path->peer->domainname)
9903 json_object_string_add(json_peer, "domainname",
9904 path->peer->domainname);
9905
9906 if (path->peer->conf_if)
9907 json_object_string_add(json_peer, "interface",
9908 path->peer->conf_if);
9909 } else {
9910 if (path->peer->conf_if) {
9911 if (path->peer->hostname
892fedb6
DA
9912 && CHECK_FLAG(path->peer->bgp->flags,
9913 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9914 vty_out(vty, " from %s(%s)",
9915 path->peer->hostname,
9916 path->peer->conf_if);
d62a17ae 9917 else
05864da7 9918 vty_out(vty, " from %s",
9b6d8fcf 9919 path->peer->conf_if);
d62a17ae 9920 } else {
05864da7 9921 if (path->peer->hostname
892fedb6
DA
9922 && CHECK_FLAG(path->peer->bgp->flags,
9923 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9924 vty_out(vty, " from %s(%s)",
9925 path->peer->hostname,
9926 path->peer->host);
d62a17ae 9927 else
05864da7
DS
9928 vty_out(vty, " from %s",
9929 sockunion2str(&path->peer->su,
9930 buf,
9931 SU_ADDRSTRLEN));
d62a17ae 9932 }
d62a17ae 9933
05864da7 9934 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9935 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9936 else
9937 vty_out(vty, " (%s)",
9938 inet_ntop(AF_INET,
9939 &path->peer->remote_id, buf1,
9940 sizeof(buf1)));
d62a17ae 9941 }
05864da7 9942 }
9df8b37c 9943
05864da7
DS
9944 /*
9945 * Note when vrfid of nexthop is different from that of prefix
9946 */
9947 if (path->extra && path->extra->bgp_orig) {
9948 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9949
05864da7
DS
9950 if (json_paths) {
9951 const char *vn;
9df8b37c 9952
05864da7
DS
9953 if (path->extra->bgp_orig->inst_type
9954 == BGP_INSTANCE_TYPE_DEFAULT)
9955 vn = VRF_DEFAULT_NAME;
9956 else
9957 vn = path->extra->bgp_orig->name;
9df8b37c 9958
05864da7 9959 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9960
05864da7
DS
9961 if (nexthop_vrfid == VRF_UNKNOWN) {
9962 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9963 } else {
05864da7
DS
9964 json_object_int_add(json_path, "nhVrfId",
9965 (int)nexthop_vrfid);
9df8b37c 9966 }
05864da7
DS
9967 } else {
9968 if (nexthop_vrfid == VRF_UNKNOWN)
9969 vty_out(vty, " vrf ?");
137147c6
DS
9970 else {
9971 struct vrf *vrf;
9972
9973 vrf = vrf_lookup_by_id(nexthop_vrfid);
9974 vty_out(vty, " vrf %s(%u)",
9975 VRF_LOGNAME(vrf), nexthop_vrfid);
9976 }
9df8b37c 9977 }
05864da7 9978 }
9df8b37c 9979
05864da7
DS
9980 if (nexthop_self) {
9981 if (json_paths) {
9982 json_object_boolean_true_add(json_path,
9983 "announceNexthopSelf");
9984 } else {
9985 vty_out(vty, " announce-nh-self");
9df8b37c 9986 }
05864da7 9987 }
9df8b37c 9988
05864da7
DS
9989 if (!json_paths)
9990 vty_out(vty, "\n");
d62a17ae 9991
05864da7
DS
9992 /* display the link-local nexthop */
9993 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9994 if (json_paths) {
9995 json_nexthop_ll = json_object_new_object();
9996 json_object_string_add(
515c2602
DA
9997 json_nexthop_ll, "ip",
9998 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9999 buf, INET6_ADDRSTRLEN));
10000
939a97f4 10001 if (path->peer->hostname)
515c2602
DA
10002 json_object_string_add(json_nexthop_ll,
10003 "hostname",
939a97f4 10004 path->peer->hostname);
515c2602 10005
05864da7
DS
10006 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10007 json_object_string_add(json_nexthop_ll, "scope",
10008 "link-local");
d62a17ae 10009
05864da7
DS
10010 json_object_boolean_true_add(json_nexthop_ll,
10011 "accessible");
d62a17ae 10012
05864da7 10013 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10014 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10015 "used");
10016 else
10017 json_object_boolean_true_add(
10018 json_nexthop_global, "used");
10019 } else {
10020 vty_out(vty, " (%s) %s\n",
10021 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10022 buf, INET6_ADDRSTRLEN),
10023 attr->mp_nexthop_prefer_global
10024 ? "(prefer-global)"
10025 : "(used)");
d62a17ae 10026 }
05864da7
DS
10027 }
10028 /* If we do not have a link-local nexthop then we must flag the
10029 global as "used" */
10030 else {
10031 if (json_paths)
10032 json_object_boolean_true_add(json_nexthop_global,
10033 "used");
10034 }
d62a17ae 10035
b5e140c8 10036 if (safi == SAFI_EVPN &&
5e4d4c8a 10037 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10038 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10039 }
10040
05864da7
DS
10041 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10042 * Int/Ext/Local, Atomic, best */
10043 if (json_paths)
10044 json_object_string_add(json_path, "origin",
10045 bgp_origin_long_str[attr->origin]);
10046 else
10047 vty_out(vty, " Origin %s",
10048 bgp_origin_long_str[attr->origin]);
9df8b37c 10049
05864da7 10050 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10051 if (json_paths)
05864da7 10052 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10053 else
05864da7
DS
10054 vty_out(vty, ", metric %u", attr->med);
10055 }
9df8b37c 10056
05864da7
DS
10057 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10058 if (json_paths)
0fbac0b4 10059 json_object_int_add(json_path, "locPrf",
05864da7
DS
10060 attr->local_pref);
10061 else
10062 vty_out(vty, ", localpref %u", attr->local_pref);
10063 }
9df8b37c 10064
05864da7
DS
10065 if (attr->weight != 0) {
10066 if (json_paths)
10067 json_object_int_add(json_path, "weight", attr->weight);
10068 else
10069 vty_out(vty, ", weight %u", attr->weight);
10070 }
9df8b37c 10071
05864da7
DS
10072 if (attr->tag != 0) {
10073 if (json_paths)
10074 json_object_int_add(json_path, "tag", attr->tag);
10075 else
10076 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10077 }
9df8b37c 10078
05864da7
DS
10079 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10080 if (json_paths)
10081 json_object_boolean_false_add(json_path, "valid");
10082 else
10083 vty_out(vty, ", invalid");
10084 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10085 if (json_paths)
10086 json_object_boolean_true_add(json_path, "valid");
10087 else
10088 vty_out(vty, ", valid");
10089 }
9df8b37c 10090
05864da7
DS
10091 if (path->peer != bgp->peer_self) {
10092 if (path->peer->as == path->peer->local_as) {
10093 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10094 if (json_paths)
10095 json_object_string_add(
10096 json_peer, "type",
10097 "confed-internal");
d62a17ae 10098 else
05864da7 10099 vty_out(vty, ", confed-internal");
d62a17ae 10100 } else {
05864da7
DS
10101 if (json_paths)
10102 json_object_string_add(
10103 json_peer, "type", "internal");
10104 else
10105 vty_out(vty, ", internal");
9df8b37c 10106 }
05864da7
DS
10107 } else {
10108 if (bgp_confederation_peers_check(bgp,
10109 path->peer->as)) {
10110 if (json_paths)
10111 json_object_string_add(
10112 json_peer, "type",
10113 "confed-external");
d62a17ae 10114 else
05864da7 10115 vty_out(vty, ", confed-external");
d62a17ae 10116 } else {
05864da7
DS
10117 if (json_paths)
10118 json_object_string_add(
10119 json_peer, "type", "external");
10120 else
10121 vty_out(vty, ", external");
d62a17ae 10122 }
10123 }
05864da7
DS
10124 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10125 if (json_paths) {
10126 json_object_boolean_true_add(json_path, "aggregated");
10127 json_object_boolean_true_add(json_path, "local");
10128 } else {
10129 vty_out(vty, ", aggregated, local");
10130 }
10131 } else if (path->type != ZEBRA_ROUTE_BGP) {
10132 if (json_paths)
10133 json_object_boolean_true_add(json_path, "sourced");
10134 else
10135 vty_out(vty, ", sourced");
10136 } else {
10137 if (json_paths) {
10138 json_object_boolean_true_add(json_path, "sourced");
10139 json_object_boolean_true_add(json_path, "local");
10140 } else {
10141 vty_out(vty, ", sourced, local");
d62a17ae 10142 }
05864da7 10143 }
718e3744 10144
05864da7 10145 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10146 if (json_paths)
05864da7
DS
10147 json_object_boolean_true_add(json_path,
10148 "atomicAggregate");
d62a17ae 10149 else
05864da7
DS
10150 vty_out(vty, ", atomic-aggregate");
10151 }
d62a17ae 10152
05864da7
DS
10153 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10154 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10155 && bgp_path_info_mpath_count(path))) {
10156 if (json_paths)
10157 json_object_boolean_true_add(json_path, "multipath");
10158 else
10159 vty_out(vty, ", multipath");
10160 }
50e05855 10161
05864da7
DS
10162 // Mark the bestpath(s)
10163 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10164 first_as = aspath_get_first_as(attr->aspath);
718e3744 10165
05864da7
DS
10166 if (json_paths) {
10167 if (!json_bestpath)
10168 json_bestpath = json_object_new_object();
10169 json_object_int_add(json_bestpath, "bestpathFromAs",
10170 first_as);
10171 } else {
10172 if (first_as)
10173 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10174 else
05864da7 10175 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10176 }
05864da7 10177 }
718e3744 10178
05864da7
DS
10179 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10180 if (json_paths) {
10181 if (!json_bestpath)
10182 json_bestpath = json_object_new_object();
10183 json_object_boolean_true_add(json_bestpath, "overall");
10184 json_object_string_add(
10185 json_bestpath, "selectionReason",
10186 bgp_path_selection_reason2str(bn->reason));
10187 } else {
10188 vty_out(vty, ", best");
10189 vty_out(vty, " (%s)",
10190 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10191 }
05864da7 10192 }
718e3744 10193
4933eaaf 10194 if (curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10195 if (json_paths)
10196 json_object_string_add(
10197 json_path, "rpkiValidationState",
4933eaaf 10198 bgp_rpki_validation2str(curr_state));
b5b99af8 10199 else
1d327209 10200 vty_out(vty, ", rpki validation-state: %s",
4933eaaf 10201 bgp_rpki_validation2str(curr_state));
b5b99af8
DS
10202 }
10203
05864da7
DS
10204 if (json_bestpath)
10205 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10206
05864da7
DS
10207 if (!json_paths)
10208 vty_out(vty, "\n");
10209
10210 /* Line 4 display Community */
10211 if (attr->community) {
10212 if (json_paths) {
10213 if (!attr->community->json)
10214 community_str(attr->community, true);
10215 json_object_lock(attr->community->json);
10216 json_object_object_add(json_path, "community",
10217 attr->community->json);
10218 } else {
10219 vty_out(vty, " Community: %s\n",
10220 attr->community->str);
d62a17ae 10221 }
05864da7 10222 }
718e3744 10223
05864da7
DS
10224 /* Line 5 display Extended-community */
10225 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10226 if (json_paths) {
10227 json_ext_community = json_object_new_object();
10228 json_object_string_add(json_ext_community, "string",
10229 attr->ecommunity->str);
10230 json_object_object_add(json_path, "extendedCommunity",
10231 json_ext_community);
d62a17ae 10232 } else {
05864da7
DS
10233 vty_out(vty, " Extended Community: %s\n",
10234 attr->ecommunity->str);
d62a17ae 10235 }
05864da7 10236 }
718e3744 10237
05864da7
DS
10238 /* Line 6 display Large community */
10239 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10240 if (json_paths) {
10241 if (!attr->lcommunity->json)
10242 lcommunity_str(attr->lcommunity, true);
10243 json_object_lock(attr->lcommunity->json);
10244 json_object_object_add(json_path, "largeCommunity",
10245 attr->lcommunity->json);
10246 } else {
10247 vty_out(vty, " Large Community: %s\n",
10248 attr->lcommunity->str);
d62a17ae 10249 }
05864da7 10250 }
718e3744 10251
05864da7
DS
10252 /* Line 7 display Originator, Cluster-id */
10253 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10254 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10255 char buf[BUFSIZ] = {0};
10256
05864da7 10257 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10258 if (json_paths)
05864da7
DS
10259 json_object_string_add(
10260 json_path, "originatorId",
23d0a753
DA
10261 inet_ntop(AF_INET, &attr->originator_id,
10262 buf, sizeof(buf)));
d62a17ae 10263 else
23d0a753
DA
10264 vty_out(vty, " Originator: %pI4",
10265 &attr->originator_id);
d62a17ae 10266 }
856ca177 10267
05864da7 10268 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10269 struct cluster_list *cluster =
10270 bgp_attr_get_cluster(attr);
05864da7 10271 int i;
d62a17ae 10272
10273 if (json_paths) {
05864da7
DS
10274 json_cluster_list = json_object_new_object();
10275 json_cluster_list_list =
10276 json_object_new_array();
10277
779fee93 10278 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10279 json_string = json_object_new_string(
779fee93
DS
10280 inet_ntop(AF_INET,
10281 &cluster->list[i],
10282 buf, sizeof(buf)));
05864da7
DS
10283 json_object_array_add(
10284 json_cluster_list_list,
10285 json_string);
10286 }
718e3744 10287
05864da7
DS
10288 /*
10289 * struct cluster_list does not have
10290 * "str" variable like aspath and community
10291 * do. Add this someday if someone asks
10292 * for it.
10293 * json_object_string_add(json_cluster_list,
779fee93 10294 * "string", cluster->str);
05864da7
DS
10295 */
10296 json_object_object_add(json_cluster_list,
10297 "list",
10298 json_cluster_list_list);
10299 json_object_object_add(json_path, "clusterList",
10300 json_cluster_list);
0dc8ee70 10301 } else {
05864da7
DS
10302 vty_out(vty, ", Cluster list: ");
10303
779fee93 10304 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10305 vty_out(vty, "%pI4 ",
779fee93 10306 &cluster->list[i]);
05864da7 10307 }
0dc8ee70 10308 }
d62a17ae 10309 }
718e3744 10310
d62a17ae 10311 if (!json_paths)
10312 vty_out(vty, "\n");
05864da7 10313 }
d62a17ae 10314
05864da7 10315 if (path->extra && path->extra->damp_info)
40ec3340 10316 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10317
05864da7
DS
10318 /* Remote Label */
10319 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10320 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10321 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10322
05864da7
DS
10323 if (json_paths)
10324 json_object_int_add(json_path, "remoteLabel", label);
10325 else
10326 vty_out(vty, " Remote label: %d\n", label);
10327 }
d62a17ae 10328
e496b420
HS
10329 /* Remote SID */
10330 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10331 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10332 if (json_paths)
10333 json_object_string_add(json_path, "remoteSid", buf);
10334 else
10335 vty_out(vty, " Remote SID: %s\n", buf);
10336 }
10337
05864da7
DS
10338 /* Label Index */
10339 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10340 if (json_paths)
10341 json_object_int_add(json_path, "labelIndex",
10342 attr->label_index);
10343 else
10344 vty_out(vty, " Label Index: %d\n",
10345 attr->label_index);
10346 }
d62a17ae 10347
05864da7
DS
10348 /* Line 8 display Addpath IDs */
10349 if (path->addpath_rx_id
10350 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10351 if (json_paths) {
10352 json_object_int_add(json_path, "addpathRxId",
10353 path->addpath_rx_id);
d62a17ae 10354
05864da7
DS
10355 /* Keep backwards compatibility with the old API
10356 * by putting TX All's ID in the old field
10357 */
10358 json_object_int_add(
10359 json_path, "addpathTxId",
10360 path->tx_addpath
10361 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10362
05864da7
DS
10363 /* ... but create a specific field for each
10364 * strategy
10365 */
10366 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10367 json_object_int_add(
10368 json_path,
10369 bgp_addpath_names(i)->id_json_name,
10370 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10371 }
05864da7
DS
10372 } else {
10373 vty_out(vty, " AddPath ID: RX %u, ",
10374 path->addpath_rx_id);
d62a17ae 10375
05864da7 10376 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10377 }
05864da7 10378 }
520d5d76 10379
05864da7
DS
10380 /* If we used addpath to TX a non-bestpath we need to display
10381 * "Advertised to" on a path-by-path basis
10382 */
10383 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10384 first = 1;
dcc68b5e 10385
05864da7
DS
10386 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10387 addpath_capable =
10388 bgp_addpath_encode_tx(peer, afi, safi);
10389 has_adj = bgp_adj_out_lookup(
10390 peer, path->net,
10391 bgp_addpath_id_for_peer(peer, afi, safi,
10392 &path->tx_addpath));
10393
10394 if ((addpath_capable && has_adj)
10395 || (!addpath_capable && has_adj
10396 && CHECK_FLAG(path->flags,
10397 BGP_PATH_SELECTED))) {
10398 if (json_path && !json_adv_to)
10399 json_adv_to = json_object_new_object();
dcc68b5e 10400
05864da7
DS
10401 route_vty_out_advertised_to(
10402 vty, peer, &first,
10403 " Advertised to:", json_adv_to);
d62a17ae 10404 }
10405 }
718e3744 10406
05864da7
DS
10407 if (json_path) {
10408 if (json_adv_to) {
10409 json_object_object_add(
10410 json_path, "advertisedTo", json_adv_to);
d62a17ae 10411 }
05864da7
DS
10412 } else {
10413 if (!first) {
10414 vty_out(vty, "\n");
d62a17ae 10415 }
10416 }
05864da7 10417 }
b05a1c8b 10418
05864da7
DS
10419 /* Line 9 display Uptime */
10420 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10421 if (json_paths) {
10422 json_last_update = json_object_new_object();
10423 json_object_int_add(json_last_update, "epoch", tbuf);
10424 json_object_string_add(json_last_update, "string",
10425 ctime(&tbuf));
10426 json_object_object_add(json_path, "lastUpdate",
10427 json_last_update);
10428 } else
10429 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10430
05864da7
DS
10431 /* Line 10 display PMSI tunnel attribute, if present */
10432 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10433 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10434 bgp_attr_get_pmsi_tnl_type(attr),
10435 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10436
05864da7
DS
10437 if (json_paths) {
10438 json_pmsi = json_object_new_object();
10439 json_object_string_add(json_pmsi, "tunnelType", str);
10440 json_object_int_add(json_pmsi, "label",
10441 label2vni(&attr->label));
10442 json_object_object_add(json_path, "pmsi", json_pmsi);
10443 } else
10444 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10445 str, label2vni(&attr->label));
d62a17ae 10446 }
f1aa5d8a 10447
92269aa2
DS
10448 /* Output some debug about internal state of the dest flags */
10449 if (json_paths) {
10450 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10451 json_object_boolean_true_add(json_path, "processScheduled");
10452 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10453 json_object_boolean_true_add(json_path, "userCleared");
10454 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10455 json_object_boolean_true_add(json_path, "labelChanged");
10456 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10457 json_object_boolean_true_add(json_path, "registeredForLabel");
10458 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10459 json_object_boolean_true_add(json_path, "selectDefered");
10460 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10461 json_object_boolean_true_add(json_path, "fibInstalled");
10462 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10463 json_object_boolean_true_add(json_path, "fibPending");
10464 }
10465
d62a17ae 10466 /* We've constructed the json object for this path, add it to the json
10467 * array of paths
10468 */
10469 if (json_paths) {
10470 if (json_nexthop_global || json_nexthop_ll) {
10471 json_nexthops = json_object_new_array();
f1aa5d8a 10472
d62a17ae 10473 if (json_nexthop_global)
10474 json_object_array_add(json_nexthops,
10475 json_nexthop_global);
f1aa5d8a 10476
d62a17ae 10477 if (json_nexthop_ll)
10478 json_object_array_add(json_nexthops,
10479 json_nexthop_ll);
f1aa5d8a 10480
d62a17ae 10481 json_object_object_add(json_path, "nexthops",
10482 json_nexthops);
10483 }
10484
10485 json_object_object_add(json_path, "peer", json_peer);
10486 json_object_array_add(json_paths, json_path);
05864da7 10487 }
b366b518
BB
10488}
10489
96ade3ed 10490#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10491#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10492#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10493
d62a17ae 10494static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10495 const char *prefix_list_str, afi_t afi,
10496 safi_t safi, enum bgp_show_type type);
10497static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10498 const char *filter, afi_t afi, safi_t safi,
10499 enum bgp_show_type type);
10500static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10501 const char *rmap_str, afi_t afi, safi_t safi,
10502 enum bgp_show_type type);
10503static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10504 const char *com, int exact, afi_t afi,
10505 safi_t safi);
10506static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10507 const char *prefix, afi_t afi, safi_t safi,
10508 enum bgp_show_type type);
a4d82a8a 10509static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10510 afi_t afi, safi_t safi, enum bgp_show_type type,
10511 bool use_json);
7f323236
DW
10512static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10513 const char *comstr, int exact, afi_t afi,
96f3485c 10514 safi_t safi, uint8_t show_flags);
d62a17ae 10515
1ae44dfc
LB
10516
10517static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10518 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10519 void *output_arg, char *rd, int is_last,
10520 unsigned long *output_cum, unsigned long *total_cum,
10521 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10522{
40381db7 10523 struct bgp_path_info *pi;
9bcb3eef 10524 struct bgp_dest *dest;
d62a17ae 10525 int header = 1;
10526 int display;
1ae44dfc
LB
10527 unsigned long output_count = 0;
10528 unsigned long total_count = 0;
d62a17ae 10529 struct prefix *p;
d62a17ae 10530 json_object *json_paths = NULL;
10531 int first = 1;
96f3485c
MK
10532 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10533 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10534 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10535
1ae44dfc
LB
10536 if (output_cum && *output_cum != 0)
10537 header = 0;
10538
9386b588 10539 if (use_json && !*json_header_depth) {
96f3485c
MK
10540 if (all)
10541 *json_header_depth = 1;
10542 else {
10543 vty_out(vty, "{\n");
10544 *json_header_depth = 2;
10545 }
10546
d62a17ae 10547 vty_out(vty,
23d0a753
DA
10548 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10549 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10550 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10551 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10552 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10553 ? VRF_DEFAULT_NAME
10554 : bgp->name,
10555 table->version, &bgp->router_id,
01eced22 10556 bgp->default_local_pref, bgp->as);
9386b588 10557 if (rd) {
445c2480 10558 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10559 ++*json_header_depth;
10560 }
d62a17ae 10561 }
718e3744 10562
445c2480
DS
10563 if (use_json && rd) {
10564 vty_out(vty, " \"%s\" : { ", rd);
10565 }
10566
d62a17ae 10567 /* Start processing of routes. */
9bcb3eef
DS
10568 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10569 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10570
9bcb3eef 10571 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10572 if (pi == NULL)
98ce9a06 10573 continue;
d62a17ae 10574
98ce9a06 10575 display = 0;
98ce9a06
DS
10576 if (use_json)
10577 json_paths = json_object_new_array();
10578 else
10579 json_paths = NULL;
d62a17ae 10580
6f94b685 10581 for (; pi; pi = pi->next) {
98ce9a06
DS
10582 total_count++;
10583 if (type == bgp_show_type_flap_statistics
10584 || type == bgp_show_type_flap_neighbor
10585 || type == bgp_show_type_dampend_paths
10586 || type == bgp_show_type_damp_neighbor) {
40381db7 10587 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10588 continue;
10589 }
10590 if (type == bgp_show_type_regexp) {
10591 regex_t *regex = output_arg;
d62a17ae 10592
40381db7 10593 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10594 == REG_NOMATCH)
10595 continue;
10596 }
10597 if (type == bgp_show_type_prefix_list) {
10598 struct prefix_list *plist = output_arg;
d62a17ae 10599
9bcb3eef 10600 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10601 != PREFIX_PERMIT)
10602 continue;
10603 }
10604 if (type == bgp_show_type_filter_list) {
10605 struct as_list *as_list = output_arg;
d62a17ae 10606
40381db7 10607 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10608 != AS_FILTER_PERMIT)
10609 continue;
10610 }
10611 if (type == bgp_show_type_route_map) {
10612 struct route_map *rmap = output_arg;
9b6d8fcf 10613 struct bgp_path_info path;
98ce9a06 10614 struct attr dummy_attr;
b68885f9 10615 route_map_result_t ret;
d62a17ae 10616
6f4f49b2 10617 dummy_attr = *pi->attr;
d62a17ae 10618
40381db7 10619 path.peer = pi->peer;
9b6d8fcf 10620 path.attr = &dummy_attr;
d62a17ae 10621
1782514f 10622 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10623 if (ret == RMAP_DENYMATCH)
10624 continue;
10625 }
10626 if (type == bgp_show_type_neighbor
10627 || type == bgp_show_type_flap_neighbor
10628 || type == bgp_show_type_damp_neighbor) {
10629 union sockunion *su = output_arg;
10630
40381db7
DS
10631 if (pi->peer == NULL
10632 || pi->peer->su_remote == NULL
10633 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10634 continue;
10635 }
10636 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10637 uint32_t destination;
d62a17ae 10638
9bcb3eef 10639 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10640 if (IN_CLASSC(destination)
9bcb3eef 10641 && dest_p->prefixlen == 24)
98ce9a06
DS
10642 continue;
10643 if (IN_CLASSB(destination)
9bcb3eef 10644 && dest_p->prefixlen == 16)
98ce9a06
DS
10645 continue;
10646 if (IN_CLASSA(destination)
9bcb3eef 10647 && dest_p->prefixlen == 8)
98ce9a06
DS
10648 continue;
10649 }
10650 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10651 p = output_arg;
9bcb3eef 10652 if (!prefix_match(p, dest_p))
98ce9a06
DS
10653 continue;
10654 }
10655 if (type == bgp_show_type_community_all) {
40381db7 10656 if (!pi->attr->community)
98ce9a06
DS
10657 continue;
10658 }
10659 if (type == bgp_show_type_community) {
10660 struct community *com = output_arg;
d62a17ae 10661
40381db7
DS
10662 if (!pi->attr->community
10663 || !community_match(pi->attr->community,
98ce9a06
DS
10664 com))
10665 continue;
10666 }
10667 if (type == bgp_show_type_community_exact) {
10668 struct community *com = output_arg;
d62a17ae 10669
40381db7
DS
10670 if (!pi->attr->community
10671 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10672 continue;
10673 }
10674 if (type == bgp_show_type_community_list) {
10675 struct community_list *list = output_arg;
d62a17ae 10676
40381db7 10677 if (!community_list_match(pi->attr->community,
a4d82a8a 10678 list))
98ce9a06
DS
10679 continue;
10680 }
a4d82a8a 10681 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10682 struct community_list *list = output_arg;
d62a17ae 10683
98ce9a06 10684 if (!community_list_exact_match(
40381db7 10685 pi->attr->community, list))
98ce9a06
DS
10686 continue;
10687 }
10688 if (type == bgp_show_type_lcommunity) {
10689 struct lcommunity *lcom = output_arg;
d62a17ae 10690
40381db7
DS
10691 if (!pi->attr->lcommunity
10692 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10693 lcom))
10694 continue;
10695 }
36a206db 10696
10697 if (type == bgp_show_type_lcommunity_exact) {
10698 struct lcommunity *lcom = output_arg;
10699
10700 if (!pi->attr->lcommunity
10701 || !lcommunity_cmp(pi->attr->lcommunity,
10702 lcom))
10703 continue;
10704 }
98ce9a06
DS
10705 if (type == bgp_show_type_lcommunity_list) {
10706 struct community_list *list = output_arg;
d62a17ae 10707
40381db7 10708 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10709 list))
98ce9a06
DS
10710 continue;
10711 }
36a206db 10712 if (type
10713 == bgp_show_type_lcommunity_list_exact) {
10714 struct community_list *list = output_arg;
10715
10716 if (!lcommunity_list_exact_match(
10717 pi->attr->lcommunity, list))
10718 continue;
10719 }
98ce9a06 10720 if (type == bgp_show_type_lcommunity_all) {
40381db7 10721 if (!pi->attr->lcommunity)
98ce9a06
DS
10722 continue;
10723 }
10724 if (type == bgp_show_type_dampend_paths
10725 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10726 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10727 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10728 continue;
10729 }
10730
10731 if (!use_json && header) {
23d0a753
DA
10732 vty_out(vty,
10733 "BGP table version is %" PRIu64
10734 ", local router ID is %pI4, vrf id ",
10735 table->version, &bgp->router_id);
9df8b37c
PZ
10736 if (bgp->vrf_id == VRF_UNKNOWN)
10737 vty_out(vty, "%s", VRFID_NONE_STR);
10738 else
10739 vty_out(vty, "%u", bgp->vrf_id);
10740 vty_out(vty, "\n");
01eced22
AD
10741 vty_out(vty, "Default local pref %u, ",
10742 bgp->default_local_pref);
10743 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10744 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10745 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10746 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10747 if (type == bgp_show_type_dampend_paths
10748 || type == bgp_show_type_damp_neighbor)
98ce9a06 10749 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10750 else if (type == bgp_show_type_flap_statistics
10751 || type == bgp_show_type_flap_neighbor)
98ce9a06 10752 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10753 else
ae248832
MK
10754 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10755 : BGP_SHOW_HEADER));
98ce9a06 10756 header = 0;
d62a17ae 10757 }
98ce9a06
DS
10758 if (rd != NULL && !display && !output_count) {
10759 if (!use_json)
10760 vty_out(vty,
10761 "Route Distinguisher: %s\n",
10762 rd);
d62a17ae 10763 }
98ce9a06
DS
10764 if (type == bgp_show_type_dampend_paths
10765 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10766 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10767 AFI_IP, safi, use_json,
10768 json_paths);
98ce9a06
DS
10769 else if (type == bgp_show_type_flap_statistics
10770 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10771 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10772 AFI_IP, safi, use_json,
10773 json_paths);
98ce9a06 10774 else
9bcb3eef 10775 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10776 json_paths, wide);
98ce9a06 10777 display++;
d62a17ae 10778 }
10779
98ce9a06
DS
10780 if (display) {
10781 output_count++;
10782 if (!use_json)
10783 continue;
10784
625d2931 10785 /* encode prefix */
9bcb3eef 10786 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10787 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10788
1840384b 10789
b54892e0
DS
10790 bgp_fs_nlri_get_string(
10791 (unsigned char *)
9bcb3eef
DS
10792 dest_p->u.prefix_flowspec.ptr,
10793 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10794 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10795 family2afi(dest_p->u
10796 .prefix_flowspec.family));
625d2931 10797 if (first)
b54892e0 10798 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10799 dest_p->u.prefix_flowspec
b54892e0 10800 .prefixlen);
625d2931 10801 else
b54892e0 10802 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10803 dest_p->u.prefix_flowspec
b54892e0 10804 .prefixlen);
625d2931 10805 } else {
625d2931 10806 if (first)
1b78780b 10807 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10808 else
1b78780b 10809 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10810 }
98ce9a06 10811 vty_out(vty, "%s",
f4ec52f7
DA
10812 json_object_to_json_string_ext(
10813 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10814 json_object_free(json_paths);
449feb8e 10815 json_paths = NULL;
98ce9a06 10816 first = 0;
1f83ed02
DS
10817 } else
10818 json_object_free(json_paths);
98ce9a06
DS
10819 }
10820
1ae44dfc
LB
10821 if (output_cum) {
10822 output_count += *output_cum;
10823 *output_cum = output_count;
10824 }
10825 if (total_cum) {
10826 total_count += *total_cum;
10827 *total_cum = total_count;
10828 }
d62a17ae 10829 if (use_json) {
9386b588 10830 if (rd) {
a4d82a8a 10831 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10832 }
10833 if (is_last) {
a4d82a8a
PZ
10834 unsigned long i;
10835 for (i = 0; i < *json_header_depth; ++i)
10836 vty_out(vty, " } ");
96f3485c
MK
10837 if (!all)
10838 vty_out(vty, "\n");
9386b588 10839 }
d62a17ae 10840 } else {
1ae44dfc
LB
10841 if (is_last) {
10842 /* No route is displayed */
10843 if (output_count == 0) {
10844 if (type == bgp_show_type_normal)
10845 vty_out(vty,
10846 "No BGP prefixes displayed, %ld exist\n",
10847 total_count);
10848 } else
d62a17ae 10849 vty_out(vty,
1ae44dfc
LB
10850 "\nDisplayed %ld routes and %ld total paths\n",
10851 output_count, total_count);
10852 }
d62a17ae 10853 }
718e3744 10854
d62a17ae 10855 return CMD_SUCCESS;
718e3744 10856}
10857
1ae44dfc
LB
10858int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10859 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10860 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10861{
9bcb3eef 10862 struct bgp_dest *dest, *next;
1ae44dfc
LB
10863 unsigned long output_cum = 0;
10864 unsigned long total_cum = 0;
9386b588 10865 unsigned long json_header_depth = 0;
67009e22 10866 struct bgp_table *itable;
0136788c 10867 bool show_msg;
96f3485c 10868 uint8_t show_flags = 0;
0136788c
LB
10869
10870 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10871
96f3485c
MK
10872 if (use_json)
10873 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10874
9bcb3eef
DS
10875 for (dest = bgp_table_top(table); dest; dest = next) {
10876 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10877
9bcb3eef
DS
10878 next = bgp_route_next(dest);
10879 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10880 continue;
67009e22 10881
9bcb3eef 10882 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10883 if (itable != NULL) {
1ae44dfc 10884 struct prefix_rd prd;
06b9f471 10885 char rd[RD_ADDRSTRLEN];
1ae44dfc 10886
9bcb3eef 10887 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10888 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10889 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10890 rd, next == NULL, &output_cum,
10891 &total_cum, &json_header_depth,
10892 show_flags);
0136788c
LB
10893 if (next == NULL)
10894 show_msg = false;
1ae44dfc
LB
10895 }
10896 }
0136788c
LB
10897 if (show_msg) {
10898 if (output_cum == 0)
10899 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10900 total_cum);
10901 else
10902 vty_out(vty,
10903 "\nDisplayed %ld routes and %ld total paths\n",
10904 output_cum, total_cum);
10905 }
1ae44dfc
LB
10906 return CMD_SUCCESS;
10907}
d62a17ae 10908static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10909 enum bgp_show_type type, void *output_arg,
10910 uint8_t show_flags)
fee0f4c6 10911{
d62a17ae 10912 struct bgp_table *table;
9386b588 10913 unsigned long json_header_depth = 0;
96f3485c 10914 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10915
d62a17ae 10916 if (bgp == NULL) {
10917 bgp = bgp_get_default();
10918 }
fee0f4c6 10919
d62a17ae 10920 if (bgp == NULL) {
10921 if (!use_json)
10922 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10923 else
10924 vty_out(vty, "{}\n");
d62a17ae 10925 return CMD_WARNING;
10926 }
4dd6177e 10927
1ae44dfc 10928 table = bgp->rib[afi][safi];
d62a17ae 10929 /* use MPLS and ENCAP specific shows until they are merged */
10930 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10931 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10932 output_arg, use_json);
d62a17ae 10933 }
dba3c1d3
PG
10934
10935 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10936 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10937 output_arg, use_json,
10938 1, NULL, NULL);
10939 }
d62a17ae 10940 /* labeled-unicast routes live in the unicast table */
10941 else if (safi == SAFI_LABELED_UNICAST)
10942 safi = SAFI_UNICAST;
fee0f4c6 10943
96f3485c
MK
10944 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10945 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10946}
10947
d62a17ae 10948static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10949 safi_t safi, uint8_t show_flags)
f186de26 10950{
d62a17ae 10951 struct listnode *node, *nnode;
10952 struct bgp *bgp;
10953 int is_first = 1;
9f049418 10954 bool route_output = false;
96f3485c 10955 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10956
d62a17ae 10957 if (use_json)
10958 vty_out(vty, "{\n");
9f689658 10959
d62a17ae 10960 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10961 route_output = true;
d62a17ae 10962 if (use_json) {
10963 if (!is_first)
10964 vty_out(vty, ",\n");
10965 else
10966 is_first = 0;
10967
10968 vty_out(vty, "\"%s\":",
10969 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10970 ? VRF_DEFAULT_NAME
d62a17ae 10971 : bgp->name);
10972 } else {
10973 vty_out(vty, "\nInstance %s:\n",
10974 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10975 ? VRF_DEFAULT_NAME
d62a17ae 10976 : bgp->name);
10977 }
10978 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10979 show_flags);
d62a17ae 10980 }
9f689658 10981
d62a17ae 10982 if (use_json)
10983 vty_out(vty, "}\n");
9f049418
DS
10984 else if (!route_output)
10985 vty_out(vty, "%% BGP instance not found\n");
f186de26 10986}
10987
718e3744 10988/* Header of detailed BGP route information */
d62a17ae 10989void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10990 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10991 afi_t afi, safi_t safi, json_object *json)
10992{
40381db7 10993 struct bgp_path_info *pi;
b54892e0 10994 const struct prefix *p;
d62a17ae 10995 struct peer *peer;
10996 struct listnode *node, *nnode;
06b9f471 10997 char buf1[RD_ADDRSTRLEN];
0291c246 10998 char prefix_str[BUFSIZ];
d62a17ae 10999 int count = 0;
11000 int best = 0;
11001 int suppress = 0;
c5f1e1b2
C
11002 int accept_own = 0;
11003 int route_filter_translated_v4 = 0;
11004 int route_filter_v4 = 0;
11005 int route_filter_translated_v6 = 0;
11006 int route_filter_v6 = 0;
11007 int llgr_stale = 0;
11008 int no_llgr = 0;
11009 int accept_own_nexthop = 0;
11010 int blackhole = 0;
d62a17ae 11011 int no_export = 0;
11012 int no_advertise = 0;
11013 int local_as = 0;
c5f1e1b2 11014 int no_peer = 0;
d62a17ae 11015 int first = 1;
11016 int has_valid_label = 0;
11017 mpls_label_t label = 0;
11018 json_object *json_adv_to = NULL;
9bedbb1e 11019
9bcb3eef
DS
11020 p = bgp_dest_get_prefix(dest);
11021 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11022
11023 if (has_valid_label)
9bcb3eef 11024 label = label_pton(&dest->local_label);
d62a17ae 11025
44c69747 11026 if (safi == SAFI_EVPN) {
d62a17ae 11027
44c69747 11028 if (!json) {
2dbe669b 11029 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11030 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11031 : "",
2dbe669b 11032 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11033 } else {
11034 json_object_string_add(json, "rd",
11035 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11036 "");
11037 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11038 }
11039 } else {
11040 if (!json) {
8228a9a7 11041 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 11042 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11043 ? prefix_rd2str(prd, buf1,
11044 sizeof(buf1))
11045 : ""),
11046 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 11047
44c69747
LK
11048 } else
11049 json_object_string_add(json, "prefix",
11050 prefix2str(p, prefix_str, sizeof(prefix_str)));
11051 }
11052
11053 if (has_valid_label) {
11054 if (json)
11055 json_object_int_add(json, "localLabel", label);
11056 else
d62a17ae 11057 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11058 }
11059
11060 if (!json)
d62a17ae 11061 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11062 vty_out(vty, "not allocated\n");
718e3744 11063
9bcb3eef 11064 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11065 count++;
40381db7 11066 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11067 best = count;
4056a5f6 11068 if (bgp_path_suppressed(pi))
d62a17ae 11069 suppress = 1;
cee9c031 11070
40381db7 11071 if (pi->attr->community == NULL)
cee9c031
QY
11072 continue;
11073
11074 no_advertise += community_include(
40381db7
DS
11075 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11076 no_export += community_include(pi->attr->community,
cee9c031 11077 COMMUNITY_NO_EXPORT);
40381db7 11078 local_as += community_include(pi->attr->community,
cee9c031 11079 COMMUNITY_LOCAL_AS);
40381db7 11080 accept_own += community_include(pi->attr->community,
cee9c031
QY
11081 COMMUNITY_ACCEPT_OWN);
11082 route_filter_translated_v4 += community_include(
40381db7 11083 pi->attr->community,
cee9c031
QY
11084 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11085 route_filter_translated_v6 += community_include(
40381db7 11086 pi->attr->community,
cee9c031
QY
11087 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11088 route_filter_v4 += community_include(
40381db7 11089 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11090 route_filter_v6 += community_include(
40381db7
DS
11091 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11092 llgr_stale += community_include(pi->attr->community,
cee9c031 11093 COMMUNITY_LLGR_STALE);
40381db7 11094 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11095 COMMUNITY_NO_LLGR);
11096 accept_own_nexthop +=
40381db7 11097 community_include(pi->attr->community,
cee9c031 11098 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11099 blackhole += community_include(pi->attr->community,
cee9c031 11100 COMMUNITY_BLACKHOLE);
40381db7 11101 no_peer += community_include(pi->attr->community,
cee9c031 11102 COMMUNITY_NO_PEER);
d62a17ae 11103 }
718e3744 11104 }
718e3744 11105
d62a17ae 11106 if (!json) {
11107 vty_out(vty, "Paths: (%d available", count);
11108 if (best) {
11109 vty_out(vty, ", best #%d", best);
b84060bb
PG
11110 if (safi == SAFI_UNICAST) {
11111 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11112 vty_out(vty, ", table %s",
11113 VRF_DEFAULT_NAME);
11114 else
11115 vty_out(vty, ", vrf %s",
11116 bgp->name);
11117 }
d62a17ae 11118 } else
11119 vty_out(vty, ", no best path");
11120
c5f1e1b2
C
11121 if (accept_own)
11122 vty_out(vty,
11123 ", accept own local route exported and imported in different VRF");
11124 else if (route_filter_translated_v4)
11125 vty_out(vty,
11126 ", mark translated RTs for VPNv4 route filtering");
11127 else if (route_filter_v4)
11128 vty_out(vty,
11129 ", attach RT as-is for VPNv4 route filtering");
11130 else if (route_filter_translated_v6)
11131 vty_out(vty,
11132 ", mark translated RTs for VPNv6 route filtering");
11133 else if (route_filter_v6)
11134 vty_out(vty,
11135 ", attach RT as-is for VPNv6 route filtering");
11136 else if (llgr_stale)
11137 vty_out(vty,
11138 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11139 else if (no_llgr)
11140 vty_out(vty,
11141 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11142 else if (accept_own_nexthop)
11143 vty_out(vty,
11144 ", accept local nexthop");
11145 else if (blackhole)
11146 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11147 else if (no_export)
11148 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11149 else if (no_advertise)
11150 vty_out(vty, ", not advertised to any peer");
d62a17ae 11151 else if (local_as)
11152 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11153 else if (no_peer)
11154 vty_out(vty,
11155 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11156
11157 if (suppress)
11158 vty_out(vty,
11159 ", Advertisements suppressed by an aggregate.");
11160 vty_out(vty, ")\n");
11161 }
718e3744 11162
d62a17ae 11163 /* If we are not using addpath then we can display Advertised to and
11164 * that will
11165 * show what peers we advertised the bestpath to. If we are using
11166 * addpath
11167 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11168 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11169 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11170 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11171 if (json && !json_adv_to)
11172 json_adv_to = json_object_new_object();
11173
11174 route_vty_out_advertised_to(
11175 vty, peer, &first,
11176 " Advertised to non peer-group peers:\n ",
11177 json_adv_to);
11178 }
11179 }
11180
11181 if (json) {
11182 if (json_adv_to) {
11183 json_object_object_add(json, "advertisedTo",
11184 json_adv_to);
11185 }
11186 } else {
11187 if (first)
11188 vty_out(vty, " Not advertised to any peer");
11189 vty_out(vty, "\n");
11190 }
11191 }
718e3744 11192}
11193
44c69747 11194static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11195 struct bgp_dest *bgp_node, struct vty *vty,
11196 struct bgp *bgp, afi_t afi, safi_t safi,
11197 json_object *json, enum bgp_path_type pathtype,
4933eaaf 11198 int *display, enum rpki_states target_state)
44c69747
LK
11199{
11200 struct bgp_path_info *pi;
11201 int header = 1;
11202 char rdbuf[RD_ADDRSTRLEN];
11203 json_object *json_header = NULL;
11204 json_object *json_paths = NULL;
4933eaaf 11205 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11206
9bcb3eef 11207 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4933eaaf
DS
11208 enum rpki_states curr_state = RPKI_NOT_BEING_USED;
11209
11210 if (p->family == AF_INET || p->family == AF_INET6)
11211 curr_state = hook_call(bgp_rpki_prefix_status, pi->peer,
11212 pi->attr, p);
11213
11214 if (target_state != RPKI_NOT_BEING_USED
11215 && curr_state != target_state)
11216 continue;
44c69747
LK
11217
11218 if (json && !json_paths) {
11219 /* Instantiate json_paths only if path is valid */
11220 json_paths = json_object_new_array();
11221 if (pfx_rd) {
11222 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11223 json_header = json_object_new_object();
11224 } else
11225 json_header = json;
11226 }
11227
11228 if (header) {
11229 route_vty_out_detail_header(
11230 vty, bgp, bgp_node, pfx_rd,
11231 AFI_IP, safi, json_header);
11232 header = 0;
11233 }
11234 (*display)++;
11235
11236 if (pathtype == BGP_PATH_SHOW_ALL
11237 || (pathtype == BGP_PATH_SHOW_BESTPATH
11238 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11239 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11240 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11241 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf
DS
11242 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
11243 safi, curr_state, json_paths);
44c69747
LK
11244 }
11245
11246 if (json && json_paths) {
11247 json_object_object_add(json_header, "paths", json_paths);
11248
11249 if (pfx_rd)
11250 json_object_object_add(json, rdbuf, json_header);
11251 }
11252}
11253
718e3744 11254/* Display specified route of BGP table. */
d62a17ae 11255static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11256 struct bgp_table *rib, const char *ip_str,
11257 afi_t afi, safi_t safi,
11258 struct prefix_rd *prd, int prefix_check,
9f049418 11259 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11260{
11261 int ret;
d62a17ae 11262 int display = 0;
11263 struct prefix match;
9bcb3eef
DS
11264 struct bgp_dest *dest;
11265 struct bgp_dest *rm;
d62a17ae 11266 struct bgp_table *table;
11267 json_object *json = NULL;
11268 json_object *json_paths = NULL;
11269
11270 /* Check IP address argument. */
11271 ret = str2prefix(ip_str, &match);
11272 if (!ret) {
11273 vty_out(vty, "address is malformed\n");
11274 return CMD_WARNING;
11275 }
718e3744 11276
d62a17ae 11277 match.family = afi2family(afi);
b05a1c8b 11278
44c69747 11279 if (use_json)
d62a17ae 11280 json = json_object_new_object();
718e3744 11281
44c69747 11282 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11283 for (dest = bgp_table_top(rib); dest;
11284 dest = bgp_route_next(dest)) {
11285 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11286
9bcb3eef 11287 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11288 continue;
9bcb3eef 11289 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11290 if (!table)
ea47320b 11291 continue;
d62a17ae 11292
ea47320b
DL
11293 if ((rm = bgp_node_match(table, &match)) == NULL)
11294 continue;
d62a17ae 11295
9bcb3eef 11296 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11297 if (prefix_check
b54892e0 11298 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11299 bgp_dest_unlock_node(rm);
ea47320b
DL
11300 continue;
11301 }
d62a17ae 11302
9bcb3eef 11303 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11304 bgp, afi, safi, json, pathtype,
4933eaaf 11305 &display, RPKI_NOT_BEING_USED);
44c69747 11306
9bcb3eef 11307 bgp_dest_unlock_node(rm);
44c69747
LK
11308 }
11309 } else if (safi == SAFI_EVPN) {
9bcb3eef 11310 struct bgp_dest *longest_pfx;
cded3b72 11311 bool is_exact_pfxlen_match = false;
44c69747 11312
9bcb3eef
DS
11313 for (dest = bgp_table_top(rib); dest;
11314 dest = bgp_route_next(dest)) {
11315 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11316
9bcb3eef 11317 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11318 continue;
9bcb3eef 11319 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11320 if (!table)
11321 continue;
11322
11323 longest_pfx = NULL;
cded3b72 11324 is_exact_pfxlen_match = false;
44c69747
LK
11325 /*
11326 * Search through all the prefixes for a match. The
11327 * pfx's are enumerated in ascending order of pfxlens.
11328 * So, the last pfx match is the longest match. Set
11329 * is_exact_pfxlen_match when we get exact pfxlen match
11330 */
11331 for (rm = bgp_table_top(table); rm;
11332 rm = bgp_route_next(rm)) {
b54892e0 11333 const struct prefix *rm_p =
9bcb3eef 11334 bgp_dest_get_prefix(rm);
44c69747
LK
11335 /*
11336 * Get prefixlen of the ip-prefix within type5
11337 * evpn route
11338 */
b54892e0
DS
11339 if (evpn_type5_prefix_match(rm_p, &match)
11340 && rm->info) {
44c69747
LK
11341 longest_pfx = rm;
11342 int type5_pfxlen =
b54892e0
DS
11343 bgp_evpn_get_type5_prefixlen(
11344 rm_p);
44c69747 11345 if (type5_pfxlen == match.prefixlen) {
cded3b72 11346 is_exact_pfxlen_match = true;
9bcb3eef 11347 bgp_dest_unlock_node(rm);
44c69747
LK
11348 break;
11349 }
d62a17ae 11350 }
11351 }
ea47320b 11352
44c69747
LK
11353 if (!longest_pfx)
11354 continue;
11355
11356 if (prefix_check && !is_exact_pfxlen_match)
11357 continue;
11358
11359 rm = longest_pfx;
9bcb3eef 11360 bgp_dest_lock_node(rm);
44c69747 11361
9bcb3eef 11362 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11363 bgp, afi, safi, json, pathtype,
4933eaaf 11364 &display, RPKI_NOT_BEING_USED);
44c69747 11365
9bcb3eef 11366 bgp_dest_unlock_node(rm);
d62a17ae 11367 }
98a9dbc7 11368 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11369 if (use_json)
11370 json_paths = json_object_new_array();
11371
63a0b7a9
PG
11372 display = bgp_flowspec_display_match_per_ip(afi, rib,
11373 &match, prefix_check,
11374 vty,
11375 use_json,
11376 json_paths);
d5f20468
SP
11377 if (use_json) {
11378 if (display)
11379 json_object_object_add(json, "paths",
11380 json_paths);
11381 else
11382 json_object_free(json_paths);
11383 }
d62a17ae 11384 } else {
9bcb3eef
DS
11385 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11386 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11387 if (!prefix_check
9bcb3eef
DS
11388 || dest_p->prefixlen == match.prefixlen) {
11389 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11390 safi, json, pathtype,
4933eaaf
DS
11391 &display,
11392 RPKI_NOT_BEING_USED);
d62a17ae 11393 }
11394
9bcb3eef 11395 bgp_dest_unlock_node(dest);
d62a17ae 11396 }
11397 }
e5eee9af 11398
d62a17ae 11399 if (use_json) {
996c9314 11400 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11401 json, JSON_C_TO_STRING_PRETTY |
11402 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11403 json_object_free(json);
11404 } else {
11405 if (!display) {
11406 vty_out(vty, "%% Network not in table\n");
11407 return CMD_WARNING;
11408 }
11409 }
b05a1c8b 11410
d62a17ae 11411 return CMD_SUCCESS;
718e3744 11412}
11413
fee0f4c6 11414/* Display specified route of Main RIB */
d62a17ae 11415static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11416 afi_t afi, safi_t safi, struct prefix_rd *prd,
11417 int prefix_check, enum bgp_path_type pathtype,
9f049418 11418 bool use_json)
d62a17ae 11419{
9b86009a 11420 if (!bgp) {
d62a17ae 11421 bgp = bgp_get_default();
9b86009a
RW
11422 if (!bgp) {
11423 if (!use_json)
11424 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11425 else
11426 vty_out(vty, "{}\n");
9b86009a
RW
11427 return CMD_WARNING;
11428 }
11429 }
d62a17ae 11430
11431 /* labeled-unicast routes live in the unicast table */
11432 if (safi == SAFI_LABELED_UNICAST)
11433 safi = SAFI_UNICAST;
11434
11435 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11436 afi, safi, prd, prefix_check, pathtype,
11437 use_json);
11438}
11439
11440static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11441 struct cmd_token **argv, bool exact, afi_t afi,
11442 safi_t safi, bool uj)
d62a17ae 11443{
11444 struct lcommunity *lcom;
11445 struct buffer *b;
11446 int i;
11447 char *str;
11448 int first = 0;
96f3485c 11449 uint8_t show_flags = 0;
4f28b2b5 11450 int ret;
96f3485c
MK
11451
11452 if (uj)
11453 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11454
11455 b = buffer_new(1024);
11456 for (i = 0; i < argc; i++) {
11457 if (first)
11458 buffer_putc(b, ' ');
11459 else {
11460 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11461 first = 1;
11462 buffer_putstr(b, argv[i]->arg);
11463 }
11464 }
11465 }
11466 buffer_putc(b, '\0');
57d187bc 11467
d62a17ae 11468 str = buffer_getstr(b);
11469 buffer_free(b);
57d187bc 11470
d62a17ae 11471 lcom = lcommunity_str2com(str);
11472 XFREE(MTYPE_TMP, str);
11473 if (!lcom) {
11474 vty_out(vty, "%% Large-community malformed\n");
11475 return CMD_WARNING;
11476 }
57d187bc 11477
4f28b2b5 11478 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11479 (exact ? bgp_show_type_lcommunity_exact
ae248832 11480 : bgp_show_type_lcommunity),
96f3485c 11481 lcom, show_flags);
4f28b2b5
DS
11482
11483 lcommunity_free(&lcom);
11484 return ret;
57d187bc
JS
11485}
11486
d62a17ae 11487static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11488 const char *lcom, bool exact, afi_t afi,
11489 safi_t safi, bool uj)
57d187bc 11490{
d62a17ae 11491 struct community_list *list;
96f3485c
MK
11492 uint8_t show_flags = 0;
11493
11494 if (uj)
11495 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11496
57d187bc 11497
e237b0d2 11498 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11499 LARGE_COMMUNITY_LIST_MASTER);
11500 if (list == NULL) {
11501 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11502 lcom);
11503 return CMD_WARNING;
11504 }
57d187bc 11505
36a206db 11506 return bgp_show(vty, bgp, afi, safi,
11507 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11508 : bgp_show_type_lcommunity_list),
96f3485c 11509 list, show_flags);
fee0f4c6 11510}
11511
52951b63
DS
11512DEFUN (show_ip_bgp_large_community_list,
11513 show_ip_bgp_large_community_list_cmd,
36a206db 11514 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
11515 SHOW_STR
11516 IP_STR
11517 BGP_STR
11518 BGP_INSTANCE_HELP_STR
9bedbb1e 11519 BGP_AFI_HELP_STR
4dd6177e 11520 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11521 "Display routes matching the large-community-list\n"
11522 "large-community-list number\n"
11523 "large-community-list name\n"
36a206db 11524 "Exact match of the large-communities\n"
52951b63
DS
11525 JSON_STR)
11526{
d62a17ae 11527 afi_t afi = AFI_IP6;
11528 safi_t safi = SAFI_UNICAST;
11529 int idx = 0;
36a206db 11530 bool exact_match = 0;
4d678463 11531 struct bgp *bgp = NULL;
9f049418 11532 bool uj = use_json(argc, argv);
d62a17ae 11533
4d678463
KA
11534 if (uj)
11535 argc--;
11536
11537 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11538 &bgp, uj);
11539 if (!idx)
11540 return CMD_WARNING;
d62a17ae 11541
11542 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11543
11544 const char *clist_number_or_name = argv[++idx]->arg;
11545
11546 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11547 exact_match = 1;
11548
11549 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11550 exact_match, afi, safi, uj);
52951b63
DS
11551}
11552DEFUN (show_ip_bgp_large_community,
11553 show_ip_bgp_large_community_cmd,
36a206db 11554 "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
11555 SHOW_STR
11556 IP_STR
11557 BGP_STR
11558 BGP_INSTANCE_HELP_STR
9bedbb1e 11559 BGP_AFI_HELP_STR
4dd6177e 11560 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11561 "Display routes matching the large-communities\n"
11562 "List of large-community numbers\n"
36a206db 11563 "Exact match of the large-communities\n"
52951b63
DS
11564 JSON_STR)
11565{
d62a17ae 11566 afi_t afi = AFI_IP6;
11567 safi_t safi = SAFI_UNICAST;
11568 int idx = 0;
36a206db 11569 bool exact_match = 0;
4d678463 11570 struct bgp *bgp = NULL;
9f049418 11571 bool uj = use_json(argc, argv);
96f3485c 11572 uint8_t show_flags = 0;
d62a17ae 11573
96f3485c
MK
11574 if (uj) {
11575 argc--;
11576 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11577 }
4d678463 11578
96f3485c
MK
11579 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11580 &bgp, uj);
11581 if (!idx)
11582 return CMD_WARNING;
d62a17ae 11583
36a206db 11584 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11585 if (argv_find(argv, argc, "exact-match", &idx))
11586 exact_match = 1;
11587 return bgp_show_lcommunity(vty, bgp, argc, argv,
11588 exact_match, afi, safi, uj);
11589 } else
d62a17ae 11590 return bgp_show(vty, bgp, afi, safi,
96f3485c 11591 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11592}
11593
71f1613a
DA
11594static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11595 safi_t safi, struct json_object *json_array);
d62a17ae 11596static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11597 safi_t safi, struct json_object *json);
e01ca200 11598
7b2ff250 11599
9ab0cf58
PG
11600DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11602 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11603 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11604{
11605 bool uj = use_json(argc, argv);
11606 struct bgp *bgp = NULL;
ec76a1d1
DA
11607 safi_t safi = SAFI_UNICAST;
11608 afi_t afi = AFI_IP6;
4265b261 11609 int idx = 0;
6c9d22e2
PG
11610 struct json_object *json_all = NULL;
11611 struct json_object *json_afi_safi = NULL;
4265b261
PG
11612
11613 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11614 &bgp, false);
71f1613a 11615 if (!idx)
4265b261 11616 return CMD_WARNING;
6c9d22e2 11617
4265b261 11618 if (uj)
6c9d22e2 11619 json_all = json_object_new_object();
4265b261 11620
9ab0cf58
PG
11621 FOREACH_AFI_SAFI (afi, safi) {
11622 /*
11623 * So limit output to those afi/safi pairs that
11624 * actually have something interesting in them
11625 */
11626 if (strmatch(get_afi_safi_str(afi, safi, true),
11627 "Unknown")) {
11628 continue;
11629 }
11630 if (uj) {
11631 json_afi_safi = json_object_new_array();
11632 json_object_object_add(
11633 json_all,
11634 get_afi_safi_str(afi, safi, true),
11635 json_afi_safi);
11636 } else {
11637 json_afi_safi = NULL;
6c9d22e2 11638 }
9ab0cf58
PG
11639
11640 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11641 }
6c9d22e2
PG
11642
11643 if (uj) {
9ab0cf58
PG
11644 vty_out(vty, "%s",
11645 json_object_to_json_string_ext(
11646 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11647 json_object_free(json_all);
4265b261 11648 }
6c9d22e2 11649
4265b261
PG
11650 return CMD_SUCCESS;
11651}
11652
7b2ff250 11653/* BGP route print out function without JSON */
14718643
PG
11654DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11655 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11657 SHOW_STR
11658 IP_STR
11659 BGP_STR
11660 BGP_INSTANCE_HELP_STR
11661 L2VPN_HELP_STR
11662 EVPN_HELP_STR
11663 "BGP RIB advertisement statistics\n"
11664 JSON_STR)
11665{
ec76a1d1
DA
11666 afi_t afi = AFI_IP6;
11667 safi_t safi = SAFI_UNICAST;
14718643
PG
11668 struct bgp *bgp = NULL;
11669 int idx = 0, ret;
11670 bool uj = use_json(argc, argv);
11671 struct json_object *json_afi_safi = NULL, *json = NULL;
11672
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11674 &bgp, false);
11675 if (!idx)
11676 return CMD_WARNING;
11677
11678 if (uj)
11679 json_afi_safi = json_object_new_array();
11680 else
11681 json_afi_safi = NULL;
11682
11683 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11684
11685 if (uj) {
11686 json = json_object_new_object();
11687 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11688 json_afi_safi);
11689 vty_out(vty, "%s", json_object_to_json_string_ext(
11690 json, JSON_C_TO_STRING_PRETTY));
11691 json_object_free(json);
11692 }
11693 return ret;
11694}
11695
893cccd0 11696/* BGP route print out function without JSON */
9ab0cf58
PG
11697DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11698 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11699 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11700 "]]\
893cccd0 11701 statistics [json]",
9ab0cf58
PG
11702 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11703 BGP_SAFI_WITH_LABEL_HELP_STR
11704 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11705{
ec76a1d1
DA
11706 afi_t afi = AFI_IP6;
11707 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11708 struct bgp *bgp = NULL;
11709 int idx = 0, ret;
11710 bool uj = use_json(argc, argv);
6c9d22e2 11711 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11712
11713 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11714 &bgp, false);
11715 if (!idx)
11716 return CMD_WARNING;
6c9d22e2 11717
893cccd0 11718 if (uj)
6c9d22e2
PG
11719 json_afi_safi = json_object_new_array();
11720 else
11721 json_afi_safi = NULL;
11722
11723 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11724
11725 if (uj) {
11726 json = json_object_new_object();
11727 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11728 json_afi_safi);
9ab0cf58
PG
11729 vty_out(vty, "%s",
11730 json_object_to_json_string_ext(
11731 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11732 json_object_free(json);
11733 }
11734 return ret;
893cccd0 11735}
7b2ff250
DW
11736
11737/* BGP route print out function without JSON */
96f3485c 11738DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11739 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11740 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11741 "]]\
96f3485c 11742 <[all$all] dampening <parameters>\
7b2ff250
DW
11743 |route-map WORD\
11744 |prefix-list WORD\
11745 |filter-list WORD\
7b2ff250
DW
11746 |community-list <(1-500)|WORD> [exact-match]\
11747 |A.B.C.D/M longer-prefixes\
11748 |X:X::X:X/M longer-prefixes\
893cccd0 11749 >",
9ab0cf58
PG
11750 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11751 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11752 "Display the entries for all address families\n"
9ab0cf58
PG
11753 "Display detailed information about dampening\n"
11754 "Display detail of configured dampening parameters\n"
11755 "Display routes matching the route-map\n"
11756 "A route-map to match on\n"
11757 "Display routes conforming to the prefix-list\n"
11758 "Prefix-list name\n"
11759 "Display routes conforming to the filter-list\n"
11760 "Regular expression access list name\n"
11761 "Display routes matching the community-list\n"
11762 "community-list number\n"
11763 "community-list name\n"
11764 "Exact match of the communities\n"
11765 "IPv4 prefix\n"
11766 "Display route and more specific routes\n"
11767 "IPv6 prefix\n"
11768 "Display route and more specific routes\n")
718e3744 11769{
d62a17ae 11770 afi_t afi = AFI_IP6;
11771 safi_t safi = SAFI_UNICAST;
11772 int exact_match = 0;
d62a17ae 11773 struct bgp *bgp = NULL;
11774 int idx = 0;
96f3485c
MK
11775 uint8_t show_flags = 0;
11776
11777 /* [<ipv4|ipv6> [all]] */
11778 if (all) {
11779 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11780 if (argv_find(argv, argc, "ipv4", &idx))
11781 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11782
11783 if (argv_find(argv, argc, "ipv6", &idx))
11784 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11785 }
d62a17ae 11786
11787 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11788 &bgp, false);
d62a17ae 11789 if (!idx)
11790 return CMD_WARNING;
11791
d62a17ae 11792 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11793 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11794 return bgp_show_dampening_parameters(vty, afi, safi,
11795 show_flags);
d62a17ae 11796 }
c016b6c7 11797
d62a17ae 11798 if (argv_find(argv, argc, "prefix-list", &idx))
11799 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11800 safi, bgp_show_type_prefix_list);
11801
11802 if (argv_find(argv, argc, "filter-list", &idx))
11803 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11804 safi, bgp_show_type_filter_list);
11805
d62a17ae 11806 if (argv_find(argv, argc, "route-map", &idx))
11807 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11808 safi, bgp_show_type_route_map);
11809
d62a17ae 11810 if (argv_find(argv, argc, "community-list", &idx)) {
11811 const char *clist_number_or_name = argv[++idx]->arg;
11812 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11813 exact_match = 1;
11814 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11815 exact_match, afi, safi);
11816 }
11817 /* prefix-longer */
11818 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11819 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11820 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11821 safi,
11822 bgp_show_type_prefix_longer);
11823
7b2ff250
DW
11824 return CMD_WARNING;
11825}
11826
11827/* BGP route print out function with JSON */
ae248832 11828DEFPY (show_ip_bgp_json,
7b2ff250
DW
11829 show_ip_bgp_json_cmd,
11830 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11831 [all$all]\
cf4898bc
QY
11832 [cidr-only\
11833 |dampening <flap-statistics|dampened-paths>\
11834 |community [AA:NN|local-AS|no-advertise|no-export\
11835 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11836 |accept-own|accept-own-nexthop|route-filter-v6\
11837 |route-filter-v4|route-filter-translated-v6\
11838 |route-filter-translated-v4] [exact-match]\
ae248832 11839 ] [json$uj | wide$wide]",
7b2ff250
DW
11840 SHOW_STR
11841 IP_STR
11842 BGP_STR
11843 BGP_INSTANCE_HELP_STR
11844 BGP_AFI_HELP_STR
11845 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11846 "Display the entries for all address families\n"
7b2ff250
DW
11847 "Display only routes with non-natural netmasks\n"
11848 "Display detailed information about dampening\n"
11849 "Display flap statistics of routes\n"
11850 "Display paths suppressed due to dampening\n"
11851 "Display routes matching the communities\n"
d0086e8e
AD
11852 COMMUNITY_AANN_STR
11853 "Do not send outside local AS (well-known community)\n"
11854 "Do not advertise to any peer (well-known community)\n"
11855 "Do not export to next AS (well-known community)\n"
11856 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11857 "Do not export to any peer (well-known community)\n"
11858 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11859 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11860 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11861 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11862 "Should accept VPN route with local nexthop (well-known community)\n"
11863 "RT VPNv6 route filtering (well-known community)\n"
11864 "RT VPNv4 route filtering (well-known community)\n"
11865 "RT translated VPNv6 route filtering (well-known community)\n"
11866 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11867 "Exact match of the communities\n"
ae248832
MK
11868 JSON_STR
11869 "Increase table width for longer prefixes\n")
7b2ff250
DW
11870{
11871 afi_t afi = AFI_IP6;
11872 safi_t safi = SAFI_UNICAST;
11873 enum bgp_show_type sh_type = bgp_show_type_normal;
11874 struct bgp *bgp = NULL;
11875 int idx = 0;
d0086e8e 11876 int exact_match = 0;
96f3485c
MK
11877 char *community = NULL;
11878 bool first = true;
11879 uint8_t show_flags = 0;
9f049418 11880
96f3485c
MK
11881
11882 if (uj) {
9f049418 11883 argc--;
96f3485c
MK
11884 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11885 }
11886
11887 /* [<ipv4|ipv6> [all]] */
11888 if (all) {
11889 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11890
11891 if (argv_find(argv, argc, "ipv4", &idx))
11892 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11893
11894 if (argv_find(argv, argc, "ipv6", &idx))
11895 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11896 }
11897
11898 if (wide)
11899 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11900
11901 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11902 &bgp, uj);
7b2ff250
DW
11903 if (!idx)
11904 return CMD_WARNING;
11905
7b2ff250 11906 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11907 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11908
11909 if (argv_find(argv, argc, "dampening", &idx)) {
11910 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11911 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11912 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11913 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11914 }
11915
11916 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11917 char *maybecomm = NULL;
d0086e8e 11918
79bc257a
RW
11919 if (idx + 1 < argc) {
11920 if (argv[idx + 1]->type == VARIABLE_TKN)
11921 maybecomm = argv[idx + 1]->arg;
11922 else
11923 maybecomm = argv[idx + 1]->text;
11924 }
11925
cf4898bc
QY
11926 if (maybecomm && !strmatch(maybecomm, "json")
11927 && !strmatch(maybecomm, "exact-match"))
11928 community = maybecomm;
d0086e8e 11929
cf4898bc
QY
11930 if (argv_find(argv, argc, "exact-match", &idx))
11931 exact_match = 1;
d0086e8e 11932
96f3485c
MK
11933 if (!community)
11934 sh_type = bgp_show_type_community_all;
11935 }
11936
11937 if (!all) {
11938 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11939 if (community)
11940 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11941 exact_match, afi, safi,
11942 show_flags);
cf4898bc 11943 else
96f3485c
MK
11944 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11945 show_flags);
11946 } else {
11947 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11948 * AFI_IP6 */
11949
11950 if (uj)
11951 vty_out(vty, "{\n");
11952
11953 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11954 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11955 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11956 ? AFI_IP
11957 : AFI_IP6;
11958 FOREACH_SAFI (safi) {
96f3485c
MK
11959 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11960 continue;
11961
11962 if (uj) {
11963 if (first)
11964 first = false;
11965 else
11966 vty_out(vty, ",\n");
11967 vty_out(vty, "\"%s\":{\n",
11968 get_afi_safi_str(afi, safi,
11969 true));
11970 } else
11971 vty_out(vty,
11972 "\nFor address family: %s\n",
11973 get_afi_safi_str(afi, safi,
11974 false));
11975
11976 if (community)
11977 bgp_show_community(vty, bgp, community,
11978 exact_match, afi,
11979 safi, show_flags);
11980 else
11981 bgp_show(vty, bgp, afi, safi, sh_type,
11982 NULL, show_flags);
11983 if (uj)
11984 vty_out(vty, "}\n");
11985 }
11986 } else {
11987 /* show <ip> bgp all: for each AFI and SAFI*/
11988 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11989 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11990 continue;
11991
11992 if (uj) {
11993 if (first)
11994 first = false;
11995 else
11996 vty_out(vty, ",\n");
d0086e8e 11997
96f3485c
MK
11998 vty_out(vty, "\"%s\":{\n",
11999 get_afi_safi_str(afi, safi,
12000 true));
12001 } else
12002 vty_out(vty,
12003 "\nFor address family: %s\n",
12004 get_afi_safi_str(afi, safi,
12005 false));
12006
12007 if (community)
12008 bgp_show_community(vty, bgp, community,
12009 exact_match, afi,
12010 safi, show_flags);
12011 else
12012 bgp_show(vty, bgp, afi, safi, sh_type,
12013 NULL, show_flags);
12014 if (uj)
12015 vty_out(vty, "}\n");
12016 }
12017 }
12018 if (uj)
12019 vty_out(vty, "}\n");
12020 }
12021 return CMD_SUCCESS;
a636c635 12022}
47fc97cc 12023
718e3744 12024DEFUN (show_ip_bgp_route,
12025 show_ip_bgp_route_cmd,
3efd0893 12026 "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>] [json]",
718e3744 12027 SHOW_STR
12028 IP_STR
12029 BGP_STR
a636c635 12030 BGP_INSTANCE_HELP_STR
4f280b15 12031 BGP_AFI_HELP_STR
4dd6177e 12032 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12033 "Network in the BGP routing table to display\n"
0c7b1b01 12034 "IPv4 prefix\n"
8c3deaae 12035 "Network in the BGP routing table to display\n"
0c7b1b01 12036 "IPv6 prefix\n"
4092b06c 12037 "Display only the bestpath\n"
b05a1c8b 12038 "Display only multipaths\n"
9973d184 12039 JSON_STR)
4092b06c 12040{
d62a17ae 12041 int prefix_check = 0;
ae19d7dd 12042
d62a17ae 12043 afi_t afi = AFI_IP6;
12044 safi_t safi = SAFI_UNICAST;
12045 char *prefix = NULL;
12046 struct bgp *bgp = NULL;
12047 enum bgp_path_type path_type;
9f049418 12048 bool uj = use_json(argc, argv);
b05a1c8b 12049
d62a17ae 12050 int idx = 0;
ae19d7dd 12051
d62a17ae 12052 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12053 &bgp, uj);
d62a17ae 12054 if (!idx)
12055 return CMD_WARNING;
c41247f5 12056
d62a17ae 12057 if (!bgp) {
12058 vty_out(vty,
12059 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12060 return CMD_WARNING;
12061 }
a636c635 12062
d62a17ae 12063 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12064 if (argv_find(argv, argc, "A.B.C.D", &idx)
12065 || argv_find(argv, argc, "X:X::X:X", &idx))
12066 prefix_check = 0;
12067 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12068 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12069 prefix_check = 1;
12070
12071 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12072 && afi != AFI_IP6) {
12073 vty_out(vty,
12074 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12075 return CMD_WARNING;
12076 }
12077 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12078 && afi != AFI_IP) {
12079 vty_out(vty,
12080 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12081 return CMD_WARNING;
12082 }
12083
12084 prefix = argv[idx]->arg;
12085
12086 /* [<bestpath|multipath>] */
12087 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12088 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12089 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12090 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12091 else
360660c6 12092 path_type = BGP_PATH_SHOW_ALL;
a636c635 12093
d62a17ae 12094 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12095 path_type, uj);
4092b06c
DS
12096}
12097
8c3deaae
QY
12098DEFUN (show_ip_bgp_regexp,
12099 show_ip_bgp_regexp_cmd,
3e5b31b3 12100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12101 SHOW_STR
12102 IP_STR
12103 BGP_STR
b00b230a 12104 BGP_INSTANCE_HELP_STR
4f280b15 12105 BGP_AFI_HELP_STR
4dd6177e 12106 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12107 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12108 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12109 JSON_STR)
8c3deaae 12110{
d62a17ae 12111 afi_t afi = AFI_IP6;
12112 safi_t safi = SAFI_UNICAST;
12113 struct bgp *bgp = NULL;
3e5b31b3
DA
12114 bool uj = use_json(argc, argv);
12115 char *regstr = NULL;
8c3deaae 12116
d62a17ae 12117 int idx = 0;
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12119 &bgp, false);
d62a17ae 12120 if (!idx)
12121 return CMD_WARNING;
8c3deaae 12122
d62a17ae 12123 // get index of regex
3e5b31b3
DA
12124 if (argv_find(argv, argc, "REGEX", &idx))
12125 regstr = argv[idx]->arg;
8c3deaae 12126
5f71d11c 12127 assert(regstr);
3e5b31b3
DA
12128 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12129 bgp_show_type_regexp, uj);
8c3deaae
QY
12130}
12131
ae248832 12132DEFPY (show_ip_bgp_instance_all,
a636c635 12133 show_ip_bgp_instance_all_cmd,
ae248832 12134 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12135 SHOW_STR
a636c635 12136 IP_STR
4092b06c 12137 BGP_STR
a636c635 12138 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12139 BGP_AFI_HELP_STR
4dd6177e 12140 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12141 JSON_STR
12142 "Increase table width for longer prefixes\n")
4092b06c 12143{
d62a17ae 12144 afi_t afi = AFI_IP;
12145 safi_t safi = SAFI_UNICAST;
12146 struct bgp *bgp = NULL;
d62a17ae 12147 int idx = 0;
96f3485c 12148 uint8_t show_flags = 0;
ae19d7dd 12149
96f3485c 12150 if (uj) {
d62a17ae 12151 argc--;
96f3485c
MK
12152 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12153 }
12154
12155 if (wide)
12156 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12157
9f049418
DS
12158 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12159 &bgp, uj);
12160 if (!idx)
12161 return CMD_WARNING;
12162
96f3485c 12163 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12164 return CMD_SUCCESS;
e3e29b32
LB
12165}
12166
a4d82a8a 12167static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12168 afi_t afi, safi_t safi, enum bgp_show_type type,
12169 bool use_json)
718e3744 12170{
d62a17ae 12171 regex_t *regex;
12172 int rc;
96f3485c
MK
12173 uint8_t show_flags = 0;
12174
12175 if (use_json)
12176 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12177
c3900853 12178 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12179 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12180 regstr);
12181 return CMD_WARNING_CONFIG_FAILED;
12182 }
12183
d62a17ae 12184 regex = bgp_regcomp(regstr);
12185 if (!regex) {
12186 vty_out(vty, "Can't compile regexp %s\n", regstr);
12187 return CMD_WARNING;
12188 }
a636c635 12189
96f3485c 12190 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 12191 bgp_regex_free(regex);
12192 return rc;
e3e29b32
LB
12193}
12194
d62a17ae 12195static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12196 const char *prefix_list_str, afi_t afi,
12197 safi_t safi, enum bgp_show_type type)
e3e29b32 12198{
d62a17ae 12199 struct prefix_list *plist;
96f3485c 12200 uint8_t show_flags = 0;
718e3744 12201
d62a17ae 12202 plist = prefix_list_lookup(afi, prefix_list_str);
12203 if (plist == NULL) {
12204 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12205 prefix_list_str);
12206 return CMD_WARNING;
12207 }
718e3744 12208
96f3485c 12209 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12210}
12211
d62a17ae 12212static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12213 const char *filter, afi_t afi, safi_t safi,
12214 enum bgp_show_type type)
4092b06c 12215{
d62a17ae 12216 struct as_list *as_list;
96f3485c 12217 uint8_t show_flags = 0;
718e3744 12218
d62a17ae 12219 as_list = as_list_lookup(filter);
12220 if (as_list == NULL) {
12221 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12222 filter);
12223 return CMD_WARNING;
12224 }
a636c635 12225
96f3485c 12226 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12227}
12228
d62a17ae 12229static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12230 const char *rmap_str, afi_t afi, safi_t safi,
12231 enum bgp_show_type type)
718e3744 12232{
d62a17ae 12233 struct route_map *rmap;
96f3485c 12234 uint8_t show_flags = 0;
bb46e94f 12235
d62a17ae 12236 rmap = route_map_lookup_by_name(rmap_str);
12237 if (!rmap) {
12238 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12239 return CMD_WARNING;
12240 }
12241
96f3485c 12242 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12243}
12244
7f323236
DW
12245static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12246 const char *comstr, int exact, afi_t afi,
96f3485c 12247 safi_t safi, uint8_t show_flags)
d62a17ae 12248{
12249 struct community *com;
d62a17ae 12250 int ret = 0;
12251
7f323236 12252 com = community_str2com(comstr);
d62a17ae 12253 if (!com) {
7f323236 12254 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12255 return CMD_WARNING;
12256 }
12257
12258 ret = bgp_show(vty, bgp, afi, safi,
12259 (exact ? bgp_show_type_community_exact
12260 : bgp_show_type_community),
96f3485c 12261 com, show_flags);
3c1f53de 12262 community_free(&com);
46c3ce83 12263
d62a17ae 12264 return ret;
718e3744 12265}
12266
d62a17ae 12267static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12268 const char *com, int exact, afi_t afi,
12269 safi_t safi)
50ef26d4 12270{
d62a17ae 12271 struct community_list *list;
96f3485c 12272 uint8_t show_flags = 0;
50ef26d4 12273
e237b0d2 12274 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12275 if (list == NULL) {
12276 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12277 return CMD_WARNING;
12278 }
718e3744 12279
d62a17ae 12280 return bgp_show(vty, bgp, afi, safi,
12281 (exact ? bgp_show_type_community_list_exact
12282 : bgp_show_type_community_list),
96f3485c 12283 list, show_flags);
50ef26d4 12284}
12285
d62a17ae 12286static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12287 const char *prefix, afi_t afi, safi_t safi,
12288 enum bgp_show_type type)
718e3744 12289{
d62a17ae 12290 int ret;
12291 struct prefix *p;
96f3485c 12292 uint8_t show_flags = 0;
47fc97cc 12293
d62a17ae 12294 p = prefix_new();
95cbbd2a 12295
d62a17ae 12296 ret = str2prefix(prefix, p);
12297 if (!ret) {
12298 vty_out(vty, "%% Malformed Prefix\n");
12299 return CMD_WARNING;
12300 }
47e9b292 12301
96f3485c 12302 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12303 prefix_free(&p);
d62a17ae 12304 return ret;
12305}
12306
d62a17ae 12307enum bgp_stats {
12308 BGP_STATS_MAXBITLEN = 0,
12309 BGP_STATS_RIB,
12310 BGP_STATS_PREFIXES,
12311 BGP_STATS_TOTPLEN,
12312 BGP_STATS_UNAGGREGATEABLE,
12313 BGP_STATS_MAX_AGGREGATEABLE,
12314 BGP_STATS_AGGREGATES,
12315 BGP_STATS_SPACE,
12316 BGP_STATS_ASPATH_COUNT,
12317 BGP_STATS_ASPATH_MAXHOPS,
12318 BGP_STATS_ASPATH_TOTHOPS,
12319 BGP_STATS_ASPATH_MAXSIZE,
12320 BGP_STATS_ASPATH_TOTSIZE,
12321 BGP_STATS_ASN_HIGHEST,
12322 BGP_STATS_MAX,
a636c635 12323};
2815e61f 12324
9ab0cf58 12325#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12326#define TABLE_STATS_IDX_JSON 1
12327
12328static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12329 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12330 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12331 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12332 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12333 "unaggregateablePrefixes"},
12334 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12335 "maximumAggregateablePrefixes"},
12336 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12337 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12338 [BGP_STATS_SPACE] = {"Address space advertised",
12339 "addressSpaceAdvertised"},
9ab0cf58
PG
12340 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12341 "advertisementsWithPaths"},
12342 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12343 "longestAsPath"},
12344 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12345 "largestAsPath"},
12346 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12347 "averageAsPathLengthHops"},
12348 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12349 "averageAsPathSizeBytes"},
12350 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12351 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12352};
2815e61f 12353
d62a17ae 12354struct bgp_table_stats {
12355 struct bgp_table *table;
12356 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12357 double total_space;
ff7924f6
PJ
12358};
12359
9bcb3eef 12360static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12361 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12362{
9bcb3eef 12363 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12364 struct bgp_path_info *pi;
b54892e0 12365 const struct prefix *rn_p;
d62a17ae 12366
9bcb3eef 12367 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12368 return;
d62a17ae 12369
9bcb3eef 12370 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12371 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12372 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12373
9c14ec72 12374 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12375 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12376 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12377
9bcb3eef 12378 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12379 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12380 /* announced address space */
12381 if (space)
b54892e0 12382 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12383 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12384 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12385
9c14ec72 12386
9bcb3eef 12387 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12388 ts->counts[BGP_STATS_RIB]++;
12389
05864da7
DS
12390 if (CHECK_FLAG(pi->attr->flag,
12391 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12392 ts->counts[BGP_STATS_AGGREGATES]++;
12393
12394 /* as-path stats */
05864da7 12395 if (pi->attr->aspath) {
9c14ec72
RW
12396 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12397 unsigned int size = aspath_size(pi->attr->aspath);
12398 as_t highest = aspath_highest(pi->attr->aspath);
12399
12400 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12401
12402 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12403 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12404
12405 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12406 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12407
12408 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12409 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12410 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12411 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12412 }
12413 }
12414}
12415
12416static int bgp_table_stats_walker(struct thread *t)
12417{
9bcb3eef
DS
12418 struct bgp_dest *dest, *ndest;
12419 struct bgp_dest *top;
9c14ec72
RW
12420 struct bgp_table_stats *ts = THREAD_ARG(t);
12421 unsigned int space = 0;
12422
12423 if (!(top = bgp_table_top(ts->table)))
12424 return 0;
12425
12426 switch (ts->table->afi) {
12427 case AFI_IP:
12428 space = IPV4_MAX_BITLEN;
12429 break;
12430 case AFI_IP6:
12431 space = IPV6_MAX_BITLEN;
12432 break;
3ba7b4af
TA
12433 case AFI_L2VPN:
12434 space = EVPN_ROUTE_PREFIXLEN;
12435 break;
9c14ec72
RW
12436 default:
12437 return 0;
12438 }
12439
12440 ts->counts[BGP_STATS_MAXBITLEN] = space;
12441
9bcb3eef 12442 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12443 if (ts->table->safi == SAFI_MPLS_VPN
12444 || ts->table->safi == SAFI_ENCAP
12445 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12446 struct bgp_table *table;
12447
9bcb3eef 12448 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12449 if (!table)
12450 continue;
12451
12452 top = bgp_table_top(table);
9bcb3eef
DS
12453 for (ndest = bgp_table_top(table); ndest;
12454 ndest = bgp_route_next(ndest))
12455 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12456 } else {
9bcb3eef 12457 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12458 }
12459 }
9c14ec72 12460
d62a17ae 12461 return 0;
2815e61f 12462}
ff7924f6 12463
71f1613a
DA
12464static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12465 struct json_object *json_array)
12466{
12467 struct listnode *node, *nnode;
12468 struct bgp *bgp;
12469
12470 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12471 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12472}
12473
12474static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12475 safi_t safi, struct json_object *json_array)
2815e61f 12476{
d62a17ae 12477 struct bgp_table_stats ts;
12478 unsigned int i;
893cccd0
PG
12479 int ret = CMD_SUCCESS;
12480 char temp_buf[20];
6c9d22e2
PG
12481 struct json_object *json = NULL;
12482
12483 if (json_array)
12484 json = json_object_new_object();
019386c2 12485
d62a17ae 12486 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12487 char warning_msg[50];
12488
12489 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12490 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12491 safi);
6c9d22e2
PG
12492
12493 if (!json)
893cccd0
PG
12494 vty_out(vty, "%s\n", warning_msg);
12495 else
9ab0cf58 12496 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12497
893cccd0
PG
12498 ret = CMD_WARNING;
12499 goto end_table_stats;
d62a17ae 12500 }
019386c2 12501
893cccd0 12502 if (!json)
5290ceab
DA
12503 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12504 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12505 else
12506 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12507
d62a17ae 12508 /* labeled-unicast routes live in the unicast table */
12509 if (safi == SAFI_LABELED_UNICAST)
12510 safi = SAFI_UNICAST;
019386c2 12511
d62a17ae 12512 memset(&ts, 0, sizeof(ts));
12513 ts.table = bgp->rib[afi][safi];
12514 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12515
d62a17ae 12516 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12517 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12518 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12519 continue;
12520
12521 switch (i) {
d62a17ae 12522 case BGP_STATS_ASPATH_TOTHOPS:
12523 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12524 if (!json) {
9ab0cf58
PG
12525 snprintf(
12526 temp_buf, sizeof(temp_buf), "%12.2f",
12527 ts.counts[i]
12528 ? (float)ts.counts[i]
12529 / (float)ts.counts
12530 [BGP_STATS_ASPATH_COUNT]
12531 : 0);
893cccd0 12532 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12533 table_stats_strs[i]
12534 [TABLE_STATS_IDX_VTY],
893cccd0 12535 temp_buf);
9ab0cf58
PG
12536 } else {
12537 json_object_double_add(
12538 json,
12539 table_stats_strs[i]
12540 [TABLE_STATS_IDX_JSON],
12541 ts.counts[i]
12542 ? (double)ts.counts[i]
12543 / (double)ts.counts
d62a17ae 12544 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12545 : 0);
12546 }
d62a17ae 12547 break;
12548 case BGP_STATS_TOTPLEN:
6c9d22e2 12549 if (!json) {
9ab0cf58
PG
12550 snprintf(
12551 temp_buf, sizeof(temp_buf), "%12.2f",
12552 ts.counts[i]
12553 ? (float)ts.counts[i]
12554 / (float)ts.counts
12555 [BGP_STATS_PREFIXES]
12556 : 0);
893cccd0 12557 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12558 table_stats_strs[i]
12559 [TABLE_STATS_IDX_VTY],
893cccd0 12560 temp_buf);
9ab0cf58
PG
12561 } else {
12562 json_object_double_add(
12563 json,
12564 table_stats_strs[i]
12565 [TABLE_STATS_IDX_JSON],
12566 ts.counts[i]
12567 ? (double)ts.counts[i]
12568 / (double)ts.counts
d62a17ae 12569 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12570 : 0);
12571 }
d62a17ae 12572 break;
12573 case BGP_STATS_SPACE:
6c9d22e2
PG
12574 if (!json) {
12575 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12576 ts.total_space);
893cccd0 12577 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12578 table_stats_strs[i]
12579 [TABLE_STATS_IDX_VTY],
893cccd0 12580 temp_buf);
9ab0cf58
PG
12581 } else {
12582 json_object_double_add(
12583 json,
12584 table_stats_strs[i]
12585 [TABLE_STATS_IDX_JSON],
12586 (double)ts.total_space);
12587 }
8d0ab76d 12588 if (afi == AFI_IP6) {
6c9d22e2
PG
12589 if (!json) {
12590 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12591 "%12g",
12592 ts.total_space
12593 * pow(2.0, -128 + 32));
6c9d22e2
PG
12594 vty_out(vty, "%30s: %s\n",
12595 "/32 equivalent %s\n",
12596 temp_buf);
9ab0cf58
PG
12597 } else {
12598 json_object_double_add(
12599 json, "/32equivalent",
12600 (double)(ts.total_space
12601 * pow(2.0,
12602 -128 + 32)));
12603 }
6c9d22e2
PG
12604 if (!json) {
12605 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12606 "%12g",
12607 ts.total_space
12608 * pow(2.0, -128 + 48));
6c9d22e2
PG
12609 vty_out(vty, "%30s: %s\n",
12610 "/48 equivalent %s\n",
12611 temp_buf);
9ab0cf58
PG
12612 } else {
12613 json_object_double_add(
12614 json, "/48equivalent",
12615 (double)(ts.total_space
12616 * pow(2.0,
12617 -128 + 48)));
12618 }
8d0ab76d 12619 } else {
6c9d22e2
PG
12620 if (!json) {
12621 snprintf(temp_buf, sizeof(temp_buf),
12622 "%12.2f",
9ab0cf58
PG
12623 ts.total_space * 100.
12624 * pow(2.0, -32));
6c9d22e2 12625 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12626 "% announced ", temp_buf);
12627 } else {
12628 json_object_double_add(
12629 json, "%announced",
12630 (double)(ts.total_space * 100.
12631 * pow(2.0, -32)));
12632 }
6c9d22e2
PG
12633 if (!json) {
12634 snprintf(temp_buf, sizeof(temp_buf),
12635 "%12.2f",
9ab0cf58
PG
12636 ts.total_space
12637 * pow(2.0, -32 + 8));
6c9d22e2
PG
12638 vty_out(vty, "%30s: %s\n",
12639 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12640 } else {
12641 json_object_double_add(
12642 json, "/8equivalent",
12643 (double)(ts.total_space
12644 * pow(2.0, -32 + 8)));
12645 }
6c9d22e2
PG
12646 if (!json) {
12647 snprintf(temp_buf, sizeof(temp_buf),
12648 "%12.2f",
9ab0cf58
PG
12649 ts.total_space
12650 * pow(2.0, -32 + 24));
6c9d22e2 12651 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12652 "/24 equivalent ", temp_buf);
12653 } else {
12654 json_object_double_add(
12655 json, "/24equivalent",
12656 (double)(ts.total_space
12657 * pow(2.0, -32 + 24)));
12658 }
8d0ab76d 12659 }
d62a17ae 12660 break;
12661 default:
6c9d22e2
PG
12662 if (!json) {
12663 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12664 ts.counts[i]);
893cccd0 12665 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12666 table_stats_strs[i]
12667 [TABLE_STATS_IDX_VTY],
12668 temp_buf);
12669 } else {
12670 json_object_int_add(
12671 json,
12672 table_stats_strs[i]
12673 [TABLE_STATS_IDX_JSON],
12674 ts.counts[i]);
12675 }
d62a17ae 12676 }
893cccd0
PG
12677 if (!json)
12678 vty_out(vty, "\n");
d62a17ae 12679 }
9ab0cf58 12680end_table_stats:
6c9d22e2
PG
12681 if (json)
12682 json_object_array_add(json_array, json);
893cccd0 12683 return ret;
d62a17ae 12684}
12685
71f1613a
DA
12686static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12687 safi_t safi, struct json_object *json_array)
12688{
12689 if (!bgp) {
12690 bgp_table_stats_all(vty, afi, safi, json_array);
12691 return CMD_SUCCESS;
12692 }
12693
12694 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12695}
12696
d62a17ae 12697enum bgp_pcounts {
12698 PCOUNT_ADJ_IN = 0,
12699 PCOUNT_DAMPED,
12700 PCOUNT_REMOVED,
12701 PCOUNT_HISTORY,
12702 PCOUNT_STALE,
12703 PCOUNT_VALID,
12704 PCOUNT_ALL,
12705 PCOUNT_COUNTED,
7e3d9632 12706 PCOUNT_BPATH_SELECTED,
d62a17ae 12707 PCOUNT_PFCNT, /* the figure we display to users */
12708 PCOUNT_MAX,
a636c635 12709};
718e3744 12710
2b64873d 12711static const char *const pcount_strs[] = {
9d303b37
DL
12712 [PCOUNT_ADJ_IN] = "Adj-in",
12713 [PCOUNT_DAMPED] = "Damped",
12714 [PCOUNT_REMOVED] = "Removed",
12715 [PCOUNT_HISTORY] = "History",
12716 [PCOUNT_STALE] = "Stale",
12717 [PCOUNT_VALID] = "Valid",
12718 [PCOUNT_ALL] = "All RIB",
12719 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12720 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12721 [PCOUNT_PFCNT] = "Useable",
12722 [PCOUNT_MAX] = NULL,
a636c635 12723};
718e3744 12724
d62a17ae 12725struct peer_pcounts {
12726 unsigned int count[PCOUNT_MAX];
12727 const struct peer *peer;
12728 const struct bgp_table *table;
54317cba 12729 safi_t safi;
a636c635 12730};
47fc97cc 12731
9bcb3eef 12732static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12733{
54317cba
JW
12734 const struct bgp_adj_in *ain;
12735 const struct bgp_path_info *pi;
d62a17ae 12736 const struct peer *peer = pc->peer;
12737
54317cba
JW
12738 for (ain = rn->adj_in; ain; ain = ain->next)
12739 if (ain->peer == peer)
12740 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12741
9bcb3eef 12742 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12743
54317cba
JW
12744 if (pi->peer != peer)
12745 continue;
d62a17ae 12746
54317cba 12747 pc->count[PCOUNT_ALL]++;
d62a17ae 12748
54317cba
JW
12749 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12750 pc->count[PCOUNT_DAMPED]++;
12751 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12752 pc->count[PCOUNT_HISTORY]++;
12753 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12754 pc->count[PCOUNT_REMOVED]++;
12755 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12756 pc->count[PCOUNT_STALE]++;
12757 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12758 pc->count[PCOUNT_VALID]++;
12759 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12760 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12761 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12762 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12763
12764 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12765 pc->count[PCOUNT_COUNTED]++;
12766 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12767 flog_err(
12768 EC_LIB_DEVELOPMENT,
12769 "Attempting to count but flags say it is unusable");
12770 } else {
40381db7 12771 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12772 flog_err(
12773 EC_LIB_DEVELOPMENT,
12774 "Not counted but flags say we should");
d62a17ae 12775 }
12776 }
54317cba
JW
12777}
12778
12779static int bgp_peer_count_walker(struct thread *t)
12780{
9bcb3eef 12781 struct bgp_dest *rn, *rm;
54317cba
JW
12782 const struct bgp_table *table;
12783 struct peer_pcounts *pc = THREAD_ARG(t);
12784
12785 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12786 || pc->safi == SAFI_EVPN) {
12787 /* Special handling for 2-level routing tables. */
12788 for (rn = bgp_table_top(pc->table); rn;
12789 rn = bgp_route_next(rn)) {
9bcb3eef 12790 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12791 if (table != NULL)
12792 for (rm = bgp_table_top(table); rm;
12793 rm = bgp_route_next(rm))
12794 bgp_peer_count_proc(rm, pc);
12795 }
12796 } else
12797 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12798 bgp_peer_count_proc(rn, pc);
12799
d62a17ae 12800 return 0;
718e3744 12801}
12802
d62a17ae 12803static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12804 safi_t safi, bool use_json)
856ca177 12805{
d62a17ae 12806 struct peer_pcounts pcounts = {.peer = peer};
12807 unsigned int i;
12808 json_object *json = NULL;
12809 json_object *json_loop = NULL;
856ca177 12810
d62a17ae 12811 if (use_json) {
12812 json = json_object_new_object();
12813 json_loop = json_object_new_object();
12814 }
718e3744 12815
d62a17ae 12816 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12817 || !peer->bgp->rib[afi][safi]) {
12818 if (use_json) {
12819 json_object_string_add(
12820 json, "warning",
12821 "No such neighbor or address family");
12822 vty_out(vty, "%s\n", json_object_to_json_string(json));
12823 json_object_free(json);
d5f20468 12824 json_object_free(json_loop);
d62a17ae 12825 } else
12826 vty_out(vty, "%% No such neighbor or address family\n");
12827
12828 return CMD_WARNING;
12829 }
2a71e9ce 12830
d62a17ae 12831 memset(&pcounts, 0, sizeof(pcounts));
12832 pcounts.peer = peer;
12833 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12834 pcounts.safi = safi;
d62a17ae 12835
12836 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12837 * stats for the thread-walk (i.e. ensure this can't be blamed on
12838 * on just vty_read()).
12839 */
d62a17ae 12840 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12841
12842 if (use_json) {
12843 json_object_string_add(json, "prefixCountsFor", peer->host);
12844 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12845 get_afi_safi_str(afi, safi, true));
d62a17ae 12846 json_object_int_add(json, "pfxCounter",
12847 peer->pcount[afi][safi]);
12848
12849 for (i = 0; i < PCOUNT_MAX; i++)
12850 json_object_int_add(json_loop, pcount_strs[i],
12851 pcounts.count[i]);
12852
12853 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12854
12855 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12856 json_object_string_add(json, "pfxctDriftFor",
12857 peer->host);
12858 json_object_string_add(
12859 json, "recommended",
12860 "Please report this bug, with the above command output");
12861 }
996c9314
LB
12862 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12863 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12864 json_object_free(json);
12865 } else {
12866
12867 if (peer->hostname
892fedb6 12868 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12869 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12870 peer->hostname, peer->host,
5cb5f4d0 12871 get_afi_safi_str(afi, safi, false));
d62a17ae 12872 } else {
12873 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12874 get_afi_safi_str(afi, safi, false));
d62a17ae 12875 }
12876
6cde4b45 12877 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12878 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12879
12880 for (i = 0; i < PCOUNT_MAX; i++)
12881 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12882 pcounts.count[i]);
12883
12884 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12885 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12886 vty_out(vty,
12887 "Please report this bug, with the above command output\n");
12888 }
12889 }
12890
12891 return CMD_SUCCESS;
718e3744 12892}
12893
a636c635
DW
12894DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12895 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12896 "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 12897 SHOW_STR
12898 IP_STR
12899 BGP_STR
8386ac43 12900 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12901 BGP_AFI_HELP_STR
12902 BGP_SAFI_HELP_STR
0b16f239
DS
12903 "Detailed information on TCP and BGP neighbor connections\n"
12904 "Neighbor to display information about\n"
12905 "Neighbor to display information about\n"
91d37724 12906 "Neighbor on BGP configured interface\n"
a636c635 12907 "Display detailed prefix count information\n"
9973d184 12908 JSON_STR)
0b16f239 12909{
d62a17ae 12910 afi_t afi = AFI_IP6;
12911 safi_t safi = SAFI_UNICAST;
12912 struct peer *peer;
12913 int idx = 0;
12914 struct bgp *bgp = NULL;
9f049418
DS
12915 bool uj = use_json(argc, argv);
12916
12917 if (uj)
12918 argc--;
856ca177 12919
d62a17ae 12920 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12921 &bgp, uj);
d62a17ae 12922 if (!idx)
12923 return CMD_WARNING;
0b16f239 12924
d62a17ae 12925 argv_find(argv, argc, "neighbors", &idx);
12926 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12927 if (!peer)
12928 return CMD_WARNING;
bb46e94f 12929
29c8d9da 12930 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12931}
0b16f239 12932
d6902373
PG
12933#ifdef KEEP_OLD_VPN_COMMANDS
12934DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12935 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12936 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12937 SHOW_STR
12938 IP_STR
12939 BGP_STR
d6902373 12940 BGP_VPNVX_HELP_STR
91d37724 12941 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12942 "Detailed information on TCP and BGP neighbor connections\n"
12943 "Neighbor to display information about\n"
12944 "Neighbor to display information about\n"
91d37724 12945 "Neighbor on BGP configured interface\n"
a636c635 12946 "Display detailed prefix count information\n"
9973d184 12947 JSON_STR)
a636c635 12948{
d62a17ae 12949 int idx_peer = 6;
12950 struct peer *peer;
9f049418 12951 bool uj = use_json(argc, argv);
a636c635 12952
d62a17ae 12953 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12954 if (!peer)
12955 return CMD_WARNING;
12956
12957 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12958}
12959
d6902373
PG
12960DEFUN (show_ip_bgp_vpn_all_route_prefix,
12961 show_ip_bgp_vpn_all_route_prefix_cmd,
12962 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12963 SHOW_STR
12964 IP_STR
12965 BGP_STR
d6902373 12966 BGP_VPNVX_HELP_STR
91d37724
QY
12967 "Display information about all VPNv4 NLRIs\n"
12968 "Network in the BGP routing table to display\n"
3a2d747c 12969 "Network in the BGP routing table to display\n"
9973d184 12970 JSON_STR)
91d37724 12971{
d62a17ae 12972 int idx = 0;
12973 char *network = NULL;
12974 struct bgp *bgp = bgp_get_default();
12975 if (!bgp) {
12976 vty_out(vty, "Can't find default instance\n");
12977 return CMD_WARNING;
12978 }
87e34b58 12979
d62a17ae 12980 if (argv_find(argv, argc, "A.B.C.D", &idx))
12981 network = argv[idx]->arg;
12982 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12983 network = argv[idx]->arg;
12984 else {
12985 vty_out(vty, "Unable to figure out Network\n");
12986 return CMD_WARNING;
12987 }
87e34b58 12988
d62a17ae 12989 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12990 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12991}
d6902373 12992#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12993
44c69747
LK
12994DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12995 show_bgp_l2vpn_evpn_route_prefix_cmd,
12996 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12997 SHOW_STR
4c63a661
PG
12998 BGP_STR
12999 L2VPN_HELP_STR
13000 EVPN_HELP_STR
44c69747
LK
13001 "Network in the BGP routing table to display\n"
13002 "Network in the BGP routing table to display\n"
4c63a661
PG
13003 "Network in the BGP routing table to display\n"
13004 "Network in the BGP routing table to display\n"
13005 JSON_STR)
13006{
d62a17ae 13007 int idx = 0;
13008 char *network = NULL;
44c69747 13009 int prefix_check = 0;
a636c635 13010
44c69747
LK
13011 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13012 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13013 network = argv[idx]->arg;
44c69747 13014 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13015 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13016 network = argv[idx]->arg;
44c69747
LK
13017 prefix_check = 1;
13018 } else {
d62a17ae 13019 vty_out(vty, "Unable to figure out Network\n");
13020 return CMD_WARNING;
13021 }
44c69747
LK
13022 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13023 prefix_check, BGP_PATH_SHOW_ALL,
13024 use_json(argc, argv));
d62a17ae 13025}
13026
2f9bc755
DS
13027static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13028 struct bgp_table *table, int *header1,
13029 int *header2, json_object *json,
13030 json_object *json_scode,
13031 json_object *json_ocode, bool wide)
13032{
13033 uint64_t version = table ? table->version : 0;
23d0a753 13034 char buf[BUFSIZ] = {0};
2f9bc755
DS
13035
13036 if (*header1) {
13037 if (json) {
13038 json_object_int_add(json, "bgpTableVersion", version);
13039 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13040 inet_ntop(AF_INET,
13041 &bgp->router_id, buf,
13042 sizeof(buf)));
2f9bc755
DS
13043 json_object_int_add(json, "defaultLocPrf",
13044 bgp->default_local_pref);
13045 json_object_int_add(json, "localAS", bgp->as);
13046 json_object_object_add(json, "bgpStatusCodes",
13047 json_scode);
13048 json_object_object_add(json, "bgpOriginCodes",
13049 json_ocode);
13050 } else {
13051 vty_out(vty,
23d0a753
DA
13052 "BGP table version is %" PRIu64
13053 ", local router ID is %pI4, vrf id ",
13054 version, &bgp->router_id);
2f9bc755
DS
13055 if (bgp->vrf_id == VRF_UNKNOWN)
13056 vty_out(vty, "%s", VRFID_NONE_STR);
13057 else
13058 vty_out(vty, "%u", bgp->vrf_id);
13059 vty_out(vty, "\n");
13060 vty_out(vty, "Default local pref %u, ",
13061 bgp->default_local_pref);
13062 vty_out(vty, "local AS %u\n", bgp->as);
13063 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13064 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13065 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13066 }
13067 *header1 = 0;
13068 }
13069 if (*header2) {
13070 if (!json)
13071 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13072 : BGP_SHOW_HEADER));
13073 *header2 = 0;
13074 }
13075}
13076
d9478df0
TA
13077static void
13078show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13079 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13080 const char *rmap_name, json_object *json, json_object *json_ar,
13081 json_object *json_scode, json_object *json_ocode,
13082 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13083 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13084{
d62a17ae 13085 struct bgp_adj_in *ain;
13086 struct bgp_adj_out *adj;
9bcb3eef 13087 struct bgp_dest *dest;
d62a17ae 13088 struct bgp *bgp;
d62a17ae 13089 struct attr attr;
13090 int ret;
13091 struct update_subgroup *subgrp;
d62a17ae 13092 struct peer_af *paf;
f99def61 13093 bool route_filtered;
96f3485c
MK
13094 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13095 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13096 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13097 || (safi == SAFI_EVPN))
13098 ? true
13099 : false;
a636c635 13100
d62a17ae 13101 bgp = peer->bgp;
a636c635 13102
d62a17ae 13103 if (!bgp) {
13104 if (use_json) {
13105 json_object_string_add(json, "alert", "no BGP");
13106 vty_out(vty, "%s\n", json_object_to_json_string(json));
13107 json_object_free(json);
13108 } else
13109 vty_out(vty, "%% No bgp\n");
13110 return;
13111 }
a636c635 13112
d62a17ae 13113 subgrp = peer_subgroup(peer, afi, safi);
13114
6392aaa6 13115 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13116 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13117 char buf[BUFSIZ] = {0};
13118
d62a17ae 13119 if (use_json) {
13120 json_object_int_add(json, "bgpTableVersion",
13121 table->version);
13122 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13123 inet_ntop(AF_INET,
13124 &bgp->router_id, buf,
13125 sizeof(buf)));
01eced22
AD
13126 json_object_int_add(json, "defaultLocPrf",
13127 bgp->default_local_pref);
13128 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13129 json_object_object_add(json, "bgpStatusCodes",
13130 json_scode);
13131 json_object_object_add(json, "bgpOriginCodes",
13132 json_ocode);
07d0c4ed
DA
13133 json_object_string_add(
13134 json, "bgpOriginatingDefaultNetwork",
13135 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13136 } else {
23d0a753
DA
13137 vty_out(vty,
13138 "BGP table version is %" PRIu64
13139 ", local router ID is %pI4, vrf id ",
13140 table->version, &bgp->router_id);
9df8b37c
PZ
13141 if (bgp->vrf_id == VRF_UNKNOWN)
13142 vty_out(vty, "%s", VRFID_NONE_STR);
13143 else
13144 vty_out(vty, "%u", bgp->vrf_id);
13145 vty_out(vty, "\n");
01eced22
AD
13146 vty_out(vty, "Default local pref %u, ",
13147 bgp->default_local_pref);
13148 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13149 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13150 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13151 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13152
07d0c4ed
DA
13153 vty_out(vty, "Originating default network %s\n\n",
13154 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13155 }
d9478df0 13156 *header1 = 0;
d62a17ae 13157 }
a636c635 13158
9bcb3eef 13159 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13160 if (type == bgp_show_adj_route_received
13161 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13162 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13163 if (ain->peer != peer)
ea47320b 13164 continue;
6392aaa6 13165
d9478df0
TA
13166 show_adj_route_header(vty, bgp, table, header1,
13167 header2, json, json_scode,
13168 json_ocode, wide);
13169
13170 if ((safi == SAFI_MPLS_VPN)
13171 || (safi == SAFI_ENCAP)
13172 || (safi == SAFI_EVPN)) {
13173 if (use_json)
13174 json_object_string_add(
13175 json_ar, "rd", rd_str);
13176 else if (show_rd && rd_str) {
13177 vty_out(vty,
13178 "Route Distinguisher: %s\n",
13179 rd_str);
13180 show_rd = false;
13181 }
13182 }
6392aaa6 13183
6f4f49b2 13184 attr = *ain->attr;
f99def61
AD
13185 route_filtered = false;
13186
13187 /* Filter prefix using distribute list,
13188 * filter list or prefix list
13189 */
b54892e0 13190 const struct prefix *rn_p =
9bcb3eef 13191 bgp_dest_get_prefix(dest);
b54892e0
DS
13192 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13193 safi))
13194 == FILTER_DENY)
f99def61
AD
13195 route_filtered = true;
13196
13197 /* Filter prefix using route-map */
b54892e0
DS
13198 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13199 safi, rmap_name, NULL,
13200 0, NULL);
6392aaa6 13201
13c8e163
AD
13202 if (type == bgp_show_adj_route_filtered &&
13203 !route_filtered && ret != RMAP_DENY) {
b755861b 13204 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13205 continue;
d62a17ae 13206 }
6392aaa6 13207
d9478df0
TA
13208 if (type == bgp_show_adj_route_received
13209 && (route_filtered || ret == RMAP_DENY))
13210 (*filtered_count)++;
6392aaa6 13211
b54892e0 13212 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13213 use_json, json_ar, wide);
b755861b 13214 bgp_attr_undup(&attr, ain->attr);
d9478df0 13215 (*output_count)++;
d62a17ae 13216 }
6392aaa6 13217 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13218 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13219 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13220 if (paf->peer != peer || !adj->attr)
924c3f6a 13221 continue;
d62a17ae 13222
d9478df0
TA
13223 show_adj_route_header(vty, bgp, table,
13224 header1, header2,
13225 json, json_scode,
13226 json_ocode, wide);
d62a17ae 13227
b54892e0 13228 const struct prefix *rn_p =
9bcb3eef 13229 bgp_dest_get_prefix(dest);
b54892e0 13230
6f4f49b2 13231 attr = *adj->attr;
b755861b 13232 ret = bgp_output_modifier(
b54892e0 13233 peer, rn_p, &attr, afi, safi,
b755861b 13234 rmap_name);
f46d8e1e 13235
b755861b 13236 if (ret != RMAP_DENY) {
d9478df0
TA
13237 if ((safi == SAFI_MPLS_VPN)
13238 || (safi == SAFI_ENCAP)
13239 || (safi == SAFI_EVPN)) {
13240 if (use_json)
13241 json_object_string_add(
13242 json_ar,
13243 "rd",
13244 rd_str);
13245 else if (show_rd
13246 && rd_str) {
13247 vty_out(vty,
13248 "Route Distinguisher: %s\n",
13249 rd_str);
13250 show_rd = false;
13251 }
13252 }
b54892e0
DS
13253 route_vty_out_tmp(
13254 vty, rn_p, &attr, safi,
ae248832
MK
13255 use_json, json_ar,
13256 wide);
d9478df0 13257 (*output_count)++;
b755861b 13258 } else {
d9478df0 13259 (*filtered_count)++;
a2addae8 13260 }
b755861b
PM
13261
13262 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13263 }
f20ce998
DS
13264 } else if (type == bgp_show_adj_route_bestpath) {
13265 struct bgp_path_info *pi;
13266
d9478df0
TA
13267 show_adj_route_header(vty, bgp, table, header1, header2,
13268 json, json_scode, json_ocode,
13269 wide);
f20ce998
DS
13270
13271 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13272 pi = pi->next) {
13273 if (pi->peer != peer)
13274 continue;
13275
13276 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13277 continue;
13278
13279 route_vty_out_tmp(vty,
13280 bgp_dest_get_prefix(dest),
13281 pi->attr, safi, use_json,
13282 json_ar, wide);
d9478df0 13283 (*output_count)++;
f20ce998 13284 }
d62a17ae 13285 }
13286 }
a636c635 13287}
2a71e9ce 13288
d62a17ae 13289static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13290 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13291 const char *rmap_name, uint8_t show_flags)
0b16f239 13292{
d9478df0
TA
13293 struct bgp *bgp;
13294 struct bgp_table *table;
d62a17ae 13295 json_object *json = NULL;
d9478df0
TA
13296 json_object *json_scode = NULL;
13297 json_object *json_ocode = NULL;
13298 json_object *json_ar = NULL;
96f3485c 13299 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13300
d9478df0
TA
13301 /* Init BGP headers here so they're only displayed once
13302 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13303 */
13304 int header1 = 1;
13305 int header2 = 1;
13306
13307 /*
13308 * Initialize variables for each RD
13309 * All prefixes under an RD is aggregated within "json_routes"
13310 */
13311 char rd_str[BUFSIZ] = {0};
13312 json_object *json_routes = NULL;
13313
13314
13315 /* For 2-tier tables, prefix counts need to be
13316 * maintained across multiple runs of show_adj_route()
13317 */
13318 unsigned long output_count_per_rd;
13319 unsigned long filtered_count_per_rd;
13320 unsigned long output_count = 0;
13321 unsigned long filtered_count = 0;
13322
13323 if (use_json) {
d62a17ae 13324 json = json_object_new_object();
d9478df0
TA
13325 json_ar = json_object_new_object();
13326 json_scode = json_object_new_object();
13327 json_ocode = json_object_new_object();
13328
13329 json_object_string_add(json_scode, "suppressed", "s");
13330 json_object_string_add(json_scode, "damped", "d");
13331 json_object_string_add(json_scode, "history", "h");
13332 json_object_string_add(json_scode, "valid", "*");
13333 json_object_string_add(json_scode, "best", ">");
13334 json_object_string_add(json_scode, "multipath", "=");
13335 json_object_string_add(json_scode, "internal", "i");
13336 json_object_string_add(json_scode, "ribFailure", "r");
13337 json_object_string_add(json_scode, "stale", "S");
13338 json_object_string_add(json_scode, "removed", "R");
13339
13340 json_object_string_add(json_ocode, "igp", "i");
13341 json_object_string_add(json_ocode, "egp", "e");
13342 json_object_string_add(json_ocode, "incomplete", "?");
13343 }
0b16f239 13344
d62a17ae 13345 if (!peer || !peer->afc[afi][safi]) {
13346 if (use_json) {
13347 json_object_string_add(
13348 json, "warning",
13349 "No such neighbor or address family");
13350 vty_out(vty, "%s\n", json_object_to_json_string(json));
13351 json_object_free(json);
13352 } else
13353 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13354
d62a17ae 13355 return CMD_WARNING;
13356 }
13357
6392aaa6
PM
13358 if ((type == bgp_show_adj_route_received
13359 || type == bgp_show_adj_route_filtered)
d62a17ae 13360 && !CHECK_FLAG(peer->af_flags[afi][safi],
13361 PEER_FLAG_SOFT_RECONFIG)) {
13362 if (use_json) {
13363 json_object_string_add(
13364 json, "warning",
13365 "Inbound soft reconfiguration not enabled");
13366 vty_out(vty, "%s\n", json_object_to_json_string(json));
13367 json_object_free(json);
13368 } else
13369 vty_out(vty,
13370 "%% Inbound soft reconfiguration not enabled\n");
13371
13372 return CMD_WARNING;
13373 }
0b16f239 13374
d9478df0
TA
13375 bgp = peer->bgp;
13376
13377 /* labeled-unicast routes live in the unicast table */
13378 if (safi == SAFI_LABELED_UNICAST)
13379 table = bgp->rib[afi][SAFI_UNICAST];
13380 else
13381 table = bgp->rib[afi][safi];
13382
13383 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13384 || (safi == SAFI_EVPN)) {
13385
13386 struct bgp_dest *dest;
13387
13388 for (dest = bgp_table_top(table); dest;
13389 dest = bgp_route_next(dest)) {
13390 table = bgp_dest_get_bgp_table_info(dest);
13391 if (!table)
13392 continue;
13393
13394 output_count_per_rd = 0;
13395 filtered_count_per_rd = 0;
13396
13397 if (use_json)
13398 json_routes = json_object_new_object();
13399
13400 const struct prefix_rd *prd;
13401 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13402 dest);
13403
13404 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13405
13406 show_adj_route(vty, peer, table, afi, safi, type,
13407 rmap_name, json, json_routes, json_scode,
13408 json_ocode, show_flags, &header1,
13409 &header2, rd_str, &output_count_per_rd,
13410 &filtered_count_per_rd);
13411
13412 /* Don't include an empty RD in the output! */
13413 if (json_routes && (output_count_per_rd > 0))
13414 json_object_object_add(json_ar, rd_str,
13415 json_routes);
13416
13417 output_count += output_count_per_rd;
13418 filtered_count += filtered_count_per_rd;
13419 }
13420 } else
13421 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13422 json, json_ar, json_scode, json_ocode,
13423 show_flags, &header1, &header2, rd_str,
13424 &output_count, &filtered_count);
13425
13426 if (use_json) {
13427 json_object_object_add(json, "advertisedRoutes", json_ar);
13428 json_object_int_add(json, "totalPrefixCounter", output_count);
13429 json_object_int_add(json, "filteredPrefixCounter",
13430 filtered_count);
13431
13432 vty_out(vty, "%s\n",
13433 json_object_to_json_string_ext(
13434 json, JSON_C_TO_STRING_PRETTY));
13435
13436 if (!output_count && !filtered_count) {
13437 json_object_free(json_scode);
13438 json_object_free(json_ocode);
13439 }
13440
13441 if (json)
13442 json_object_free(json);
13443
13444 } else if (output_count > 0) {
13445 if (filtered_count > 0)
13446 vty_out(vty,
13447 "\nTotal number of prefixes %ld (%ld filtered)\n",
13448 output_count, filtered_count);
13449 else
13450 vty_out(vty, "\nTotal number of prefixes %ld\n",
13451 output_count);
13452 }
0b16f239 13453
d62a17ae 13454 return CMD_SUCCESS;
a636c635 13455}
50ef26d4 13456
f20ce998
DS
13457DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13458 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13459 "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]",
13460 SHOW_STR
13461 IP_STR
13462 BGP_STR
13463 BGP_INSTANCE_HELP_STR
13464 BGP_AFI_HELP_STR
13465 BGP_SAFI_WITH_LABEL_HELP_STR
13466 "Detailed information on TCP and BGP neighbor connections\n"
13467 "Neighbor to display information about\n"
13468 "Neighbor to display information about\n"
13469 "Neighbor on BGP configured interface\n"
13470 "Display the routes selected by best path\n"
13471 JSON_STR
13472 "Increase table width for longer prefixes\n")
13473{
13474 afi_t afi = AFI_IP6;
13475 safi_t safi = SAFI_UNICAST;
13476 char *rmap_name = NULL;
13477 char *peerstr = NULL;
13478 struct bgp *bgp = NULL;
13479 struct peer *peer;
13480 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13481 int idx = 0;
96f3485c
MK
13482 uint8_t show_flags = 0;
13483
13484 if (uj)
13485 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13486
13487 if (wide)
13488 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13489
13490 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13491 &bgp, uj);
13492
13493 if (!idx)
13494 return CMD_WARNING;
13495
13496 argv_find(argv, argc, "neighbors", &idx);
13497 peerstr = argv[++idx]->arg;
13498
13499 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13500 if (!peer)
13501 return CMD_WARNING;
13502
96f3485c
MK
13503 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13504 show_flags);
f20ce998
DS
13505}
13506
ae248832 13507DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13508 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13509 "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 WORD] [json$uj | wide$wide]",
718e3744 13510 SHOW_STR
13511 IP_STR
13512 BGP_STR
a636c635 13513 BGP_INSTANCE_HELP_STR
7395a2c9 13514 BGP_AFI_HELP_STR
4dd6177e 13515 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13516 "Display the entries for all address families\n"
718e3744 13517 "Detailed information on TCP and BGP neighbor connections\n"
13518 "Neighbor to display information about\n"
13519 "Neighbor to display information about\n"
91d37724 13520 "Neighbor on BGP configured interface\n"
a636c635 13521 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13522 "Display the received routes from neighbor\n"
13523 "Display the filtered routes received from neighbor\n"
a636c635
DW
13524 "Route-map to modify the attributes\n"
13525 "Name of the route map\n"
ae248832
MK
13526 JSON_STR
13527 "Increase table width for longer prefixes\n")
718e3744 13528{
d62a17ae 13529 afi_t afi = AFI_IP6;
13530 safi_t safi = SAFI_UNICAST;
13531 char *rmap_name = NULL;
13532 char *peerstr = NULL;
d62a17ae 13533 struct bgp *bgp = NULL;
13534 struct peer *peer;
6392aaa6 13535 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13536 int idx = 0;
96f3485c
MK
13537 bool first = true;
13538 uint8_t show_flags = 0;
6392aaa6 13539
96f3485c 13540 if (uj) {
d62a17ae 13541 argc--;
96f3485c
MK
13542 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13543 }
13544
13545 if (all) {
13546 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13547 if (argv_find(argv, argc, "ipv4", &idx))
13548 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13549
13550 if (argv_find(argv, argc, "ipv6", &idx))
13551 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13552 }
13553
13554 if (wide)
13555 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13556
9f049418
DS
13557 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13558 &bgp, uj);
13559 if (!idx)
13560 return CMD_WARNING;
13561
d62a17ae 13562 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13563 argv_find(argv, argc, "neighbors", &idx);
13564 peerstr = argv[++idx]->arg;
8c3deaae 13565
d62a17ae 13566 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13567 if (!peer)
13568 return CMD_WARNING;
856ca177 13569
d62a17ae 13570 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13571 type = bgp_show_adj_route_advertised;
13572 else if (argv_find(argv, argc, "received-routes", &idx))
13573 type = bgp_show_adj_route_received;
13574 else if (argv_find(argv, argc, "filtered-routes", &idx))
13575 type = bgp_show_adj_route_filtered;
13576
d62a17ae 13577 if (argv_find(argv, argc, "route-map", &idx))
13578 rmap_name = argv[++idx]->arg;
95cbbd2a 13579
96f3485c
MK
13580 if (!all)
13581 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13582 show_flags);
13583 if (uj)
13584 vty_out(vty, "{\n");
13585
13586 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13587 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13588 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13589 : AFI_IP6;
13590 FOREACH_SAFI (safi) {
96f3485c
MK
13591 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13592 continue;
13593
13594 if (uj) {
13595 if (first)
13596 first = false;
13597 else
13598 vty_out(vty, ",\n");
13599 vty_out(vty, "\"%s\":",
13600 get_afi_safi_str(afi, safi, true));
13601 } else
13602 vty_out(vty, "\nFor address family: %s\n",
13603 get_afi_safi_str(afi, safi, false));
13604
13605 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13606 show_flags);
13607 }
13608 } else {
13609 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13610 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13611 continue;
13612
13613 if (uj) {
13614 if (first)
13615 first = false;
13616 else
13617 vty_out(vty, ",\n");
13618 vty_out(vty, "\"%s\":",
13619 get_afi_safi_str(afi, safi, true));
13620 } else
13621 vty_out(vty, "\nFor address family: %s\n",
13622 get_afi_safi_str(afi, safi, false));
13623
13624 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13625 show_flags);
13626 }
13627 }
13628 if (uj)
13629 vty_out(vty, "}\n");
13630
13631 return CMD_SUCCESS;
95cbbd2a
ML
13632}
13633
718e3744 13634DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13635 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13636 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13637 SHOW_STR
13638 IP_STR
13639 BGP_STR
8c3deaae
QY
13640 "Address Family\n"
13641 "Address Family\n"
718e3744 13642 "Address Family modifier\n"
13643 "Detailed information on TCP and BGP neighbor connections\n"
13644 "Neighbor to display information about\n"
13645 "Neighbor to display information about\n"
91d37724 13646 "Neighbor on BGP configured interface\n"
718e3744 13647 "Display information received from a BGP neighbor\n"
856ca177 13648 "Display the prefixlist filter\n"
9973d184 13649 JSON_STR)
718e3744 13650{
d62a17ae 13651 afi_t afi = AFI_IP6;
13652 safi_t safi = SAFI_UNICAST;
13653 char *peerstr = NULL;
13654
13655 char name[BUFSIZ];
13656 union sockunion su;
13657 struct peer *peer;
13658 int count, ret;
13659
13660 int idx = 0;
13661
13662 /* show [ip] bgp */
13663 if (argv_find(argv, argc, "ip", &idx))
13664 afi = AFI_IP;
13665 /* [<ipv4|ipv6> [unicast]] */
13666 if (argv_find(argv, argc, "ipv4", &idx))
13667 afi = AFI_IP;
13668 if (argv_find(argv, argc, "ipv6", &idx))
13669 afi = AFI_IP6;
13670 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13671 argv_find(argv, argc, "neighbors", &idx);
13672 peerstr = argv[++idx]->arg;
13673
9f049418 13674 bool uj = use_json(argc, argv);
d62a17ae 13675
13676 ret = str2sockunion(peerstr, &su);
13677 if (ret < 0) {
13678 peer = peer_lookup_by_conf_if(NULL, peerstr);
13679 if (!peer) {
13680 if (uj)
13681 vty_out(vty, "{}\n");
13682 else
13683 vty_out(vty,
13684 "%% Malformed address or name: %s\n",
13685 peerstr);
13686 return CMD_WARNING;
13687 }
13688 } else {
13689 peer = peer_lookup(NULL, &su);
13690 if (!peer) {
13691 if (uj)
13692 vty_out(vty, "{}\n");
13693 else
13694 vty_out(vty, "No peer\n");
13695 return CMD_WARNING;
13696 }
13697 }
718e3744 13698
4ced1a2c 13699 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13700 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13701 if (count) {
13702 if (!uj)
13703 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13704 get_afi_safi_str(afi, safi, false));
d62a17ae 13705 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13706 } else {
13707 if (uj)
13708 vty_out(vty, "{}\n");
13709 else
13710 vty_out(vty, "No functional output\n");
13711 }
718e3744 13712
d62a17ae 13713 return CMD_SUCCESS;
13714}
13715
13716static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13717 afi_t afi, safi_t safi,
9f049418 13718 enum bgp_show_type type, bool use_json)
d62a17ae 13719{
96f3485c
MK
13720 uint8_t show_flags = 0;
13721
13722 if (use_json)
13723 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13724
d62a17ae 13725 if (!peer || !peer->afc[afi][safi]) {
13726 if (use_json) {
13727 json_object *json_no = NULL;
13728 json_no = json_object_new_object();
13729 json_object_string_add(
13730 json_no, "warning",
13731 "No such neighbor or address family");
13732 vty_out(vty, "%s\n",
13733 json_object_to_json_string(json_no));
13734 json_object_free(json_no);
13735 } else
13736 vty_out(vty, "%% No such neighbor or address family\n");
13737 return CMD_WARNING;
13738 }
47fc97cc 13739
7daf25a3
TA
13740 /* labeled-unicast routes live in the unicast table */
13741 if (safi == SAFI_LABELED_UNICAST)
13742 safi = SAFI_UNICAST;
13743
96f3485c 13744 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13745}
13746
dba3c1d3
PG
13747DEFUN (show_ip_bgp_flowspec_routes_detailed,
13748 show_ip_bgp_flowspec_routes_detailed_cmd,
13749 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13750 SHOW_STR
13751 IP_STR
13752 BGP_STR
13753 BGP_INSTANCE_HELP_STR
13754 BGP_AFI_HELP_STR
13755 "SAFI Flowspec\n"
13756 "Detailed information on flowspec entries\n"
13757 JSON_STR)
13758{
13759 afi_t afi = AFI_IP;
13760 safi_t safi = SAFI_UNICAST;
13761 struct bgp *bgp = NULL;
13762 int idx = 0;
9f049418 13763 bool uj = use_json(argc, argv);
96f3485c 13764 uint8_t show_flags = 0;
9f049418 13765
96f3485c 13766 if (uj) {
9f049418 13767 argc--;
96f3485c
MK
13768 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13769 }
dba3c1d3
PG
13770
13771 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13772 &bgp, uj);
dba3c1d3
PG
13773 if (!idx)
13774 return CMD_WARNING;
13775
96f3485c
MK
13776 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13777 show_flags);
dba3c1d3
PG
13778}
13779
718e3744 13780DEFUN (show_ip_bgp_neighbor_routes,
13781 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13782 "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 13783 SHOW_STR
13784 IP_STR
13785 BGP_STR
8386ac43 13786 BGP_INSTANCE_HELP_STR
4f280b15 13787 BGP_AFI_HELP_STR
4dd6177e 13788 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13789 "Detailed information on TCP and BGP neighbor connections\n"
13790 "Neighbor to display information about\n"
13791 "Neighbor to display information about\n"
91d37724 13792 "Neighbor on BGP configured interface\n"
2525cf39 13793 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13794 "Display the dampened routes received from neighbor\n"
13795 "Display routes learned from neighbor\n"
9973d184 13796 JSON_STR)
718e3744 13797{
d62a17ae 13798 char *peerstr = NULL;
13799 struct bgp *bgp = NULL;
13800 afi_t afi = AFI_IP6;
13801 safi_t safi = SAFI_UNICAST;
13802 struct peer *peer;
13803 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13804 int idx = 0;
9f049418
DS
13805 bool uj = use_json(argc, argv);
13806
13807 if (uj)
13808 argc--;
bb46e94f 13809
d62a17ae 13810 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13811 &bgp, uj);
d62a17ae 13812 if (!idx)
13813 return CMD_WARNING;
c493f2d8 13814
d62a17ae 13815 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13816 argv_find(argv, argc, "neighbors", &idx);
13817 peerstr = argv[++idx]->arg;
8c3deaae 13818
d62a17ae 13819 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13820 if (!peer)
d62a17ae 13821 return CMD_WARNING;
bb46e94f 13822
d62a17ae 13823 if (argv_find(argv, argc, "flap-statistics", &idx))
13824 sh_type = bgp_show_type_flap_neighbor;
13825 else if (argv_find(argv, argc, "dampened-routes", &idx))
13826 sh_type = bgp_show_type_damp_neighbor;
13827 else if (argv_find(argv, argc, "routes", &idx))
13828 sh_type = bgp_show_type_neighbor;
2525cf39 13829
d62a17ae 13830 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13831}
6b0655a2 13832
734b349e 13833struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13834
d62a17ae 13835struct bgp_distance {
13836 /* Distance value for the IP source prefix. */
d7c0a89a 13837 uint8_t distance;
718e3744 13838
d62a17ae 13839 /* Name of the access-list to be matched. */
13840 char *access_list;
718e3744 13841};
13842
4f280b15
LB
13843DEFUN (show_bgp_afi_vpn_rd_route,
13844 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13845 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
13846 SHOW_STR
13847 BGP_STR
13848 BGP_AFI_HELP_STR
13849 "Address Family modifier\n"
13850 "Display information for a route distinguisher\n"
13851 "Route Distinguisher\n"
7395a2c9
DS
13852 "Network in the BGP routing table to display\n"
13853 "Network in the BGP routing table to display\n"
13854 JSON_STR)
4f280b15 13855{
d62a17ae 13856 int ret;
13857 struct prefix_rd prd;
13858 afi_t afi = AFI_MAX;
13859 int idx = 0;
4f280b15 13860
ff6566f3
DS
13861 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13862 vty_out(vty, "%% Malformed Address Family\n");
13863 return CMD_WARNING;
13864 }
13865
d62a17ae 13866 ret = str2prefix_rd(argv[5]->arg, &prd);
13867 if (!ret) {
13868 vty_out(vty, "%% Malformed Route Distinguisher\n");
13869 return CMD_WARNING;
13870 }
ff6566f3 13871
d62a17ae 13872 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13873 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13874}
13875
d62a17ae 13876static struct bgp_distance *bgp_distance_new(void)
718e3744 13877{
d62a17ae 13878 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13879}
13880
d62a17ae 13881static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13882{
d62a17ae 13883 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13884}
13885
37a87b8f
CS
13886int bgp_distance_set(uint8_t distance, const char *ip_str,
13887 const char *access_list_str, afi_t afi, safi_t safi,
13888 char *errmsg, size_t errmsg_len)
718e3744 13889{
d62a17ae 13890 int ret;
d62a17ae 13891 struct prefix p;
9bcb3eef 13892 struct bgp_dest *dest;
d62a17ae 13893 struct bgp_distance *bdistance;
718e3744 13894
d62a17ae 13895 ret = str2prefix(ip_str, &p);
13896 if (ret == 0) {
37a87b8f 13897 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13898 return CMD_WARNING_CONFIG_FAILED;
13899 }
718e3744 13900
d62a17ae 13901 /* Get BGP distance node. */
9bcb3eef
DS
13902 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13903 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13904 if (bdistance)
9bcb3eef 13905 bgp_dest_unlock_node(dest);
ca2e160d 13906 else {
d62a17ae 13907 bdistance = bgp_distance_new();
9bcb3eef 13908 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13909 }
718e3744 13910
d62a17ae 13911 /* Set distance value. */
13912 bdistance->distance = distance;
718e3744 13913
d62a17ae 13914 /* Reset access-list configuration. */
e1b36e13 13915 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13916 if (access_list_str)
13917 bdistance->access_list =
13918 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13919
d62a17ae 13920 return CMD_SUCCESS;
718e3744 13921}
13922
37a87b8f
CS
13923int bgp_distance_unset(uint8_t distance, const char *ip_str,
13924 const char *access_list_str, afi_t afi, safi_t safi,
13925 char *errmsg, size_t errmsg_len)
718e3744 13926{
d62a17ae 13927 int ret;
d62a17ae 13928 struct prefix p;
9bcb3eef 13929 struct bgp_dest *dest;
d62a17ae 13930 struct bgp_distance *bdistance;
718e3744 13931
d62a17ae 13932 ret = str2prefix(ip_str, &p);
13933 if (ret == 0) {
37a87b8f 13934 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13935 return CMD_WARNING_CONFIG_FAILED;
13936 }
718e3744 13937
9bcb3eef
DS
13938 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13939 if (!dest) {
37a87b8f 13940 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13941 return CMD_WARNING_CONFIG_FAILED;
13942 }
718e3744 13943
9bcb3eef 13944 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13945
d62a17ae 13946 if (bdistance->distance != distance) {
37a87b8f
CS
13947 snprintf(errmsg, errmsg_len,
13948 "Distance does not match configured\n");
d62a17ae 13949 return CMD_WARNING_CONFIG_FAILED;
13950 }
718e3744 13951
0a22ddfb 13952 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13953 bgp_distance_free(bdistance);
718e3744 13954
9bcb3eef
DS
13955 bgp_dest_set_bgp_path_info(dest, NULL);
13956 bgp_dest_unlock_node(dest);
13957 bgp_dest_unlock_node(dest);
718e3744 13958
d62a17ae 13959 return CMD_SUCCESS;
718e3744 13960}
13961
718e3744 13962/* Apply BGP information to distance method. */
b8685f9b 13963uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13964 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13965{
9bcb3eef 13966 struct bgp_dest *dest;
801bb996 13967 struct prefix q = {0};
d62a17ae 13968 struct peer *peer;
13969 struct bgp_distance *bdistance;
13970 struct access_list *alist;
13971 struct bgp_static *bgp_static;
13972
13973 if (!bgp)
13974 return 0;
13975
40381db7 13976 peer = pinfo->peer;
d62a17ae 13977
7b7d48e5
DS
13978 if (pinfo->attr->distance)
13979 return pinfo->attr->distance;
13980
801bb996
CS
13981 /* Check source address.
13982 * Note: for aggregate route, peer can have unspec af type.
13983 */
13984 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13985 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13986 return 0;
13987
9bcb3eef
DS
13988 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13989 if (dest) {
13990 bdistance = bgp_dest_get_bgp_distance_info(dest);
13991 bgp_dest_unlock_node(dest);
d62a17ae 13992
13993 if (bdistance->access_list) {
13994 alist = access_list_lookup(afi, bdistance->access_list);
13995 if (alist
13996 && access_list_apply(alist, p) == FILTER_PERMIT)
13997 return bdistance->distance;
13998 } else
13999 return bdistance->distance;
718e3744 14000 }
718e3744 14001
d62a17ae 14002 /* Backdoor check. */
9bcb3eef
DS
14003 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14004 if (dest) {
14005 bgp_static = bgp_dest_get_bgp_static_info(dest);
14006 bgp_dest_unlock_node(dest);
718e3744 14007
d62a17ae 14008 if (bgp_static->backdoor) {
14009 if (bgp->distance_local[afi][safi])
14010 return bgp->distance_local[afi][safi];
14011 else
14012 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14013 }
718e3744 14014 }
718e3744 14015
d62a17ae 14016 if (peer->sort == BGP_PEER_EBGP) {
14017 if (bgp->distance_ebgp[afi][safi])
14018 return bgp->distance_ebgp[afi][safi];
14019 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14020 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14021 if (bgp->distance_ibgp[afi][safi])
14022 return bgp->distance_ibgp[afi][safi];
14023 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14024 } else {
14025 if (bgp->distance_local[afi][safi])
14026 return bgp->distance_local[afi][safi];
14027 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14028 }
718e3744 14029}
14030
a612fb77
DA
14031/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14032 * we should tell ZEBRA update the routes for a specific
14033 * AFI/SAFI to reflect changes in RIB.
14034 */
37a87b8f
CS
14035void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14036 safi_t update_safi)
a612fb77
DA
14037{
14038 afi_t afi;
14039 safi_t safi;
14040
14041 FOREACH_AFI_SAFI (afi, safi) {
14042 if (!bgp_fibupd_safi(safi))
14043 continue;
14044
8b54bc30
DA
14045 if (afi != update_afi && safi != update_safi)
14046 continue;
14047
14048 if (BGP_DEBUG(zebra, ZEBRA))
14049 zlog_debug(
14050 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14051 __func__, afi, safi);
14052 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14053 }
14054}
14055
37a87b8f
CS
14056DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14057 "distance bgp (1-255) (1-255) (1-255)",
14058 "Define an administrative distance\n"
14059 "BGP distance\n"
14060 "Distance for routes external to the AS\n"
14061 "Distance for routes internal to the AS\n"
14062 "Distance for local routes\n")
718e3744 14063{
d62a17ae 14064 int idx_number = 2;
14065 int idx_number_2 = 3;
14066 int idx_number_3 = 4;
14067 afi_t afi;
14068 safi_t safi;
37a87b8f 14069 char xpath[XPATH_MAXLEN];
718e3744 14070
d62a17ae 14071 afi = bgp_node_afi(vty);
14072 safi = bgp_node_safi(vty);
718e3744 14073
37a87b8f
CS
14074 snprintf(
14075 xpath, sizeof(xpath),
14076 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14077 yang_afi_safi_value2identity(afi, safi),
14078 bgp_afi_safi_get_container_str(afi, safi));
14079 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14080 snprintf(
14081 xpath, sizeof(xpath),
14082 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14083 yang_afi_safi_value2identity(afi, safi),
14084 bgp_afi_safi_get_container_str(afi, safi));
14085 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14086 argv[idx_number_2]->arg);
14087 snprintf(
14088 xpath, sizeof(xpath),
14089 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14090 yang_afi_safi_value2identity(afi, safi),
14091 bgp_afi_safi_get_container_str(afi, safi));
14092
14093 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14094 argv[idx_number_3]->arg);
14095
14096 return nb_cli_apply_changes(vty, NULL);
14097}
14098
14099DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14100 "no distance bgp [(1-255) (1-255) (1-255)]",
14101 NO_STR
14102 "Define an administrative distance\n"
14103 "BGP distance\n"
14104 "Distance for routes external to the AS\n"
14105 "Distance for routes internal to the AS\n"
14106 "Distance for local routes\n")
14107{
14108 afi_t afi;
14109 safi_t safi;
14110 char xpath[XPATH_MAXLEN];
14111
14112 afi = bgp_node_afi(vty);
14113 safi = bgp_node_safi(vty);
14114
14115 snprintf(
14116 xpath, sizeof(xpath),
14117 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14118 yang_afi_safi_value2identity(afi, safi),
14119 bgp_afi_safi_get_container_str(afi, safi));
14120 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14121 snprintf(
14122 xpath, sizeof(xpath),
14123 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14124 yang_afi_safi_value2identity(afi, safi),
14125 bgp_afi_safi_get_container_str(afi, safi));
14126 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14127 snprintf(
14128 xpath, sizeof(xpath),
14129 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14130 yang_afi_safi_value2identity(afi, safi),
14131 bgp_afi_safi_get_container_str(afi, safi));
14132
14133 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14134
14135 return nb_cli_apply_changes(vty, NULL);
718e3744 14136}
14137
37a87b8f
CS
14138void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14139 struct lyd_node *dnode,
14140 bool show_defaults)
718e3744 14141{
37a87b8f
CS
14142 uint8_t distance_ebgp, distance_ibgp, distance_local;
14143
14144 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14145 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14146 distance_local = yang_dnode_get_uint8(dnode, "./local");
14147
14148 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14149 distance_local);
14150}
14151
8cc7152a
CS
14152DEFPY_YANG(bgp_distance_source,
14153 bgp_distance_source_cmd,
14154 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14155 NO_STR
14156 "Define an administrative distance\n"
8cc7152a 14157 "Distance value\n"
e12affc1
SW
14158 "IPv4 source prefix\n"
14159 "IPv6 source prefix\n"
37a87b8f 14160 "Access list name\n")
718e3744 14161{
37a87b8f
CS
14162 afi_t afi;
14163 safi_t safi;
14164 char xpath[XPATH_MAXLEN];
14165
14166 afi = bgp_node_afi(vty);
14167 safi = bgp_node_safi(vty);
14168
8cc7152a
CS
14169 if (!no) {
14170 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14171 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14172 distance_str);
14173 if (acl)
14174 nb_cli_enqueue_change(vty,
14175 "./access-list-policy-export",
14176 NB_OP_CREATE, acl);
14177 else
14178 nb_cli_enqueue_change(vty,
14179 "./access-list-policy-export",
14180 NB_OP_DESTROY, NULL);
14181 } else {
14182 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14183 }
37a87b8f
CS
14184
14185 snprintf(
14186 xpath, sizeof(xpath),
14187 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14188 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14189 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14190
14191 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14192}
14193
37a87b8f
CS
14194void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14195 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14196{
14197 vty_out(vty, " distance %d %s %s\n",
14198 yang_dnode_get_uint8(dnode, "./distance"),
14199 yang_dnode_get_string(dnode, "./prefix"),
14200 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14201 ? yang_dnode_get_string(dnode,
14202 "./access-list-policy-export")
14203 : "");
14204}
14205
7c98d487
DA
14206DEFPY_YANG(
14207 bgp_dampening, bgp_dampening_cmd,
14208 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14209 NO_STR
14210 "BGP Specific commands\n"
14211 "Enable route-flap dampening\n"
14212 "Half-life time for the penalty\n"
14213 "Value to start reusing a route\n"
14214 "Value to start suppressing a route\n"
14215 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14216{
14217 afi_t afi;
14218 safi_t safi;
14219 char xpath[XPATH_MAXLEN];
718e3744 14220
37a87b8f
CS
14221 afi = bgp_node_afi(vty);
14222 safi = bgp_node_safi(vty);
14223
d9ce5113
CS
14224 if (!no) {
14225 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14226 if (argc == 6) {
14227 nb_cli_enqueue_change(vty, "./reach-decay",
14228 NB_OP_MODIFY, halflife_str);
14229 nb_cli_enqueue_change(vty, "./reuse-above",
14230 NB_OP_MODIFY, reuse_str);
14231 nb_cli_enqueue_change(vty, "./suppress-above",
14232 NB_OP_MODIFY, suppress_str);
14233 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14234 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14235 } if (argc == 3) {
14236 nb_cli_enqueue_change(vty, "./reach-decay",
14237 NB_OP_MODIFY, halflife_str);
14238 }
14239 } else {
14240 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14241 }
7ebe9748 14242
37a87b8f
CS
14243 snprintf(
14244 xpath, sizeof(xpath),
14245 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14246 yang_afi_safi_value2identity(afi, safi),
14247 bgp_afi_safi_get_container_str(afi, safi));
14248
14249 return nb_cli_apply_changes(vty, xpath);
718e3744 14250}
14251
37a87b8f
CS
14252void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14253 struct lyd_node *dnode,
14254 bool show_defaults)
718e3744 14255{
37a87b8f
CS
14256 if (!yang_dnode_get_bool(dnode, "./enable"))
14257 return;
14258
14259 int half = DEFAULT_HALF_LIFE * 60;
14260 int reuse = DEFAULT_REUSE;
14261 int suppress = DEFAULT_SUPPRESS;
14262 int max;
14263
14264 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14265 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14266 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14267 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14268
14269 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14270 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14271 vty_out(vty, " bgp dampening\n");
14272 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14273 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14274 vty_out(vty, " bgp dampening %u\n", half);
14275 else
14276 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14277 suppress, max);
718e3744 14278}
14279
718e3744 14280/* Display specified route of BGP table. */
d62a17ae 14281static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14282 const char *ip_str, afi_t afi, safi_t safi,
14283 struct prefix_rd *prd, int prefix_check)
14284{
14285 int ret;
14286 struct prefix match;
9bcb3eef
DS
14287 struct bgp_dest *dest;
14288 struct bgp_dest *rm;
40381db7
DS
14289 struct bgp_path_info *pi;
14290 struct bgp_path_info *pi_temp;
d62a17ae 14291 struct bgp *bgp;
14292 struct bgp_table *table;
14293
14294 /* BGP structure lookup. */
14295 if (view_name) {
14296 bgp = bgp_lookup_by_name(view_name);
14297 if (bgp == NULL) {
14298 vty_out(vty, "%% Can't find BGP instance %s\n",
14299 view_name);
14300 return CMD_WARNING;
14301 }
14302 } else {
14303 bgp = bgp_get_default();
14304 if (bgp == NULL) {
14305 vty_out(vty, "%% No BGP process is configured\n");
14306 return CMD_WARNING;
14307 }
718e3744 14308 }
718e3744 14309
d62a17ae 14310 /* Check IP address argument. */
14311 ret = str2prefix(ip_str, &match);
14312 if (!ret) {
14313 vty_out(vty, "%% address is malformed\n");
14314 return CMD_WARNING;
14315 }
718e3744 14316
d62a17ae 14317 match.family = afi2family(afi);
14318
14319 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14320 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14321 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14322 dest = bgp_route_next(dest)) {
14323 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14324
9bcb3eef 14325 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14326 continue;
9bcb3eef 14327 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14328 if (!table)
ea47320b
DL
14329 continue;
14330 if ((rm = bgp_node_match(table, &match)) == NULL)
14331 continue;
d62a17ae 14332
9bcb3eef 14333 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14334
ea47320b 14335 if (!prefix_check
b54892e0 14336 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14337 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14338 while (pi) {
14339 if (pi->extra && pi->extra->damp_info) {
14340 pi_temp = pi->next;
ea47320b 14341 bgp_damp_info_free(
40ec3340
DS
14342 &pi->extra->damp_info,
14343 &bgp->damp[afi][safi],
a935f597 14344 1, afi, safi);
40381db7 14345 pi = pi_temp;
ea47320b 14346 } else
40381db7 14347 pi = pi->next;
d62a17ae 14348 }
ea47320b
DL
14349 }
14350
9bcb3eef 14351 bgp_dest_unlock_node(rm);
d62a17ae 14352 }
14353 } else {
9bcb3eef 14354 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14355 != NULL) {
9bcb3eef 14356 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14357
d62a17ae 14358 if (!prefix_check
9bcb3eef
DS
14359 || dest_p->prefixlen == match.prefixlen) {
14360 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14361 while (pi) {
14362 if (pi->extra && pi->extra->damp_info) {
14363 pi_temp = pi->next;
c8ddbd48 14364 struct bgp_damp_info *bdi =
14365 pi->extra->damp_info;
14366 if (bdi->lastrecord
14367 == BGP_RECORD_UPDATE) {
14368 bgp_aggregate_increment(
14369 bgp,
14370 &bdi->dest->p,
14371 bdi->path,
14372 bdi->afi,
14373 bdi->safi);
14374 bgp_process(bgp,
14375 bdi->dest,
14376 bdi->afi,
14377 bdi->safi);
14378 }
d62a17ae 14379 bgp_damp_info_free(
40ec3340
DS
14380 &pi->extra->damp_info,
14381 &bgp->damp[afi][safi],
a935f597 14382 1, afi, safi);
40381db7 14383 pi = pi_temp;
d62a17ae 14384 } else
40381db7 14385 pi = pi->next;
d62a17ae 14386 }
14387 }
14388
9bcb3eef 14389 bgp_dest_unlock_node(dest);
d62a17ae 14390 }
14391 }
718e3744 14392
d62a17ae 14393 return CMD_SUCCESS;
718e3744 14394}
14395
14396DEFUN (clear_ip_bgp_dampening,
14397 clear_ip_bgp_dampening_cmd,
14398 "clear ip bgp dampening",
14399 CLEAR_STR
14400 IP_STR
14401 BGP_STR
14402 "Clear route flap dampening information\n")
14403{
40ec3340 14404 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14405 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14406 SAFI_UNICAST);
d62a17ae 14407 return CMD_SUCCESS;
718e3744 14408}
14409
14410DEFUN (clear_ip_bgp_dampening_prefix,
14411 clear_ip_bgp_dampening_prefix_cmd,
14412 "clear ip bgp dampening A.B.C.D/M",
14413 CLEAR_STR
14414 IP_STR
14415 BGP_STR
14416 "Clear route flap dampening information\n"
0c7b1b01 14417 "IPv4 prefix\n")
718e3744 14418{
d62a17ae 14419 int idx_ipv4_prefixlen = 4;
14420 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14421 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14422}
14423
14424DEFUN (clear_ip_bgp_dampening_address,
14425 clear_ip_bgp_dampening_address_cmd,
14426 "clear ip bgp dampening A.B.C.D",
14427 CLEAR_STR
14428 IP_STR
14429 BGP_STR
14430 "Clear route flap dampening information\n"
14431 "Network to clear damping information\n")
14432{
d62a17ae 14433 int idx_ipv4 = 4;
14434 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14435 SAFI_UNICAST, NULL, 0);
718e3744 14436}
14437
14438DEFUN (clear_ip_bgp_dampening_address_mask,
14439 clear_ip_bgp_dampening_address_mask_cmd,
14440 "clear ip bgp dampening A.B.C.D A.B.C.D",
14441 CLEAR_STR
14442 IP_STR
14443 BGP_STR
14444 "Clear route flap dampening information\n"
14445 "Network to clear damping information\n"
14446 "Network mask\n")
14447{
d62a17ae 14448 int idx_ipv4 = 4;
14449 int idx_ipv4_2 = 5;
14450 int ret;
14451 char prefix_str[BUFSIZ];
718e3744 14452
d62a17ae 14453 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14454 prefix_str, sizeof(prefix_str));
d62a17ae 14455 if (!ret) {
14456 vty_out(vty, "%% Inconsistent address and mask\n");
14457 return CMD_WARNING;
14458 }
718e3744 14459
d62a17ae 14460 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14461 NULL, 0);
718e3744 14462}
6b0655a2 14463
e3b78da8 14464static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14465{
14466 struct vty *vty = arg;
e3b78da8 14467 struct peer *peer = bucket->data;
825d9834
DS
14468 char buf[SU_ADDRSTRLEN];
14469
14470 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14471 sockunion2str(&peer->su, buf, sizeof(buf)));
14472}
14473
2a0e69ae
DS
14474DEFUN (show_bgp_listeners,
14475 show_bgp_listeners_cmd,
14476 "show bgp listeners",
14477 SHOW_STR
14478 BGP_STR
14479 "Display Listen Sockets and who created them\n")
14480{
14481 bgp_dump_listener_info(vty);
14482
14483 return CMD_SUCCESS;
14484}
14485
825d9834
DS
14486DEFUN (show_bgp_peerhash,
14487 show_bgp_peerhash_cmd,
14488 "show bgp peerhash",
14489 SHOW_STR
14490 BGP_STR
14491 "Display information about the BGP peerhash\n")
14492{
14493 struct list *instances = bm->bgp;
14494 struct listnode *node;
14495 struct bgp *bgp;
14496
14497 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14498 vty_out(vty, "BGP: %s\n", bgp->name);
14499 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14500 vty);
14501 }
14502
14503 return CMD_SUCCESS;
14504}
14505
587ff0fd 14506/* also used for encap safi */
2b791107
DL
14507static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14508 afi_t afi, safi_t safi)
d62a17ae 14509{
9bcb3eef
DS
14510 struct bgp_dest *pdest;
14511 struct bgp_dest *dest;
d62a17ae 14512 struct bgp_table *table;
b54892e0
DS
14513 const struct prefix *p;
14514 const struct prefix_rd *prd;
d62a17ae 14515 struct bgp_static *bgp_static;
14516 mpls_label_t label;
d62a17ae 14517 char rdbuf[RD_ADDRSTRLEN];
14518
14519 /* Network configuration. */
9bcb3eef
DS
14520 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14521 pdest = bgp_route_next(pdest)) {
14522 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14523 if (!table)
ea47320b 14524 continue;
d62a17ae 14525
9bcb3eef
DS
14526 for (dest = bgp_table_top(table); dest;
14527 dest = bgp_route_next(dest)) {
14528 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14529 if (bgp_static == NULL)
ea47320b 14530 continue;
d62a17ae 14531
9bcb3eef
DS
14532 p = bgp_dest_get_prefix(dest);
14533 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14534 pdest);
d62a17ae 14535
ea47320b 14536 /* "network" configuration display. */
06b9f471 14537 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14538 label = decode_label(&bgp_static->label);
14539
8228a9a7 14540 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14541 if (safi == SAFI_MPLS_VPN)
14542 vty_out(vty, " label %u", label);
14543
14544 if (bgp_static->rmap.name)
14545 vty_out(vty, " route-map %s",
14546 bgp_static->rmap.name);
e2a86ad9
DS
14547
14548 if (bgp_static->backdoor)
14549 vty_out(vty, " backdoor");
14550
ea47320b
DL
14551 vty_out(vty, "\n");
14552 }
14553 }
d62a17ae 14554}
14555
2b791107
DL
14556static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14557 afi_t afi, safi_t safi)
d62a17ae 14558{
9bcb3eef
DS
14559 struct bgp_dest *pdest;
14560 struct bgp_dest *dest;
d62a17ae 14561 struct bgp_table *table;
b54892e0
DS
14562 const struct prefix *p;
14563 const struct prefix_rd *prd;
d62a17ae 14564 struct bgp_static *bgp_static;
ff44f570 14565 char buf[PREFIX_STRLEN * 2];
d62a17ae 14566 char buf2[SU_ADDRSTRLEN];
14567 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14568 char esi_buf[ESI_BYTES];
d62a17ae 14569
14570 /* Network configuration. */
9bcb3eef
DS
14571 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14572 pdest = bgp_route_next(pdest)) {
14573 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14574 if (!table)
ea47320b 14575 continue;
d62a17ae 14576
9bcb3eef
DS
14577 for (dest = bgp_table_top(table); dest;
14578 dest = bgp_route_next(dest)) {
14579 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14580 if (bgp_static == NULL)
ea47320b 14581 continue;
d62a17ae 14582
ea47320b 14583 char *macrouter = NULL;
d62a17ae 14584
ea47320b
DL
14585 if (bgp_static->router_mac)
14586 macrouter = prefix_mac2str(
14587 bgp_static->router_mac, NULL, 0);
14588 if (bgp_static->eth_s_id)
0a50c248
AK
14589 esi_to_str(bgp_static->eth_s_id,
14590 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14591 p = bgp_dest_get_prefix(dest);
14592 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14593
ea47320b 14594 /* "network" configuration display. */
06b9f471 14595 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14596 if (p->u.prefix_evpn.route_type == 5) {
14597 char local_buf[PREFIX_STRLEN];
3714a385 14598 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14599 struct prefix_evpn *)p)
14600 ? AF_INET
14601 : AF_INET6;
3714a385 14602 inet_ntop(family,
14603 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14604 local_buf, PREFIX_STRLEN);
772270f3
QY
14605 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14606 p->u.prefix_evpn.prefix_addr
14607 .ip_prefix_length);
197cb530
PG
14608 } else {
14609 prefix2str(p, buf, sizeof(buf));
14610 }
ea47320b 14611
a4d82a8a
PZ
14612 if (bgp_static->gatewayIp.family == AF_INET
14613 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14614 inet_ntop(bgp_static->gatewayIp.family,
14615 &bgp_static->gatewayIp.u.prefix, buf2,
14616 sizeof(buf2));
ea47320b 14617 vty_out(vty,
7bcc8dac 14618 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14619 buf, rdbuf,
14620 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14621 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14622 macrouter);
14623
0a22ddfb 14624 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14625 }
14626 }
3da6fcd5
PG
14627}
14628
718e3744 14629/* Configuration of static route announcement and aggregate
14630 information. */
2b791107
DL
14631void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14632 safi_t safi)
d62a17ae 14633{
9bcb3eef 14634 struct bgp_dest *dest;
b54892e0 14635 const struct prefix *p;
d62a17ae 14636 struct bgp_static *bgp_static;
14637 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14638
2b791107
DL
14639 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14640 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14641 return;
14642 }
d62a17ae 14643
2b791107
DL
14644 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14645 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14646 return;
14647 }
d62a17ae 14648
14649 /* Network configuration. */
9bcb3eef
DS
14650 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14651 dest = bgp_route_next(dest)) {
14652 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14653 if (bgp_static == NULL)
ea47320b 14654 continue;
d62a17ae 14655
9bcb3eef 14656 p = bgp_dest_get_prefix(dest);
d62a17ae 14657
8228a9a7 14658 vty_out(vty, " network %pFX", p);
d62a17ae 14659
ea47320b
DL
14660 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14661 vty_out(vty, " label-index %u",
14662 bgp_static->label_index);
d62a17ae 14663
ea47320b
DL
14664 if (bgp_static->rmap.name)
14665 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14666
14667 if (bgp_static->backdoor)
14668 vty_out(vty, " backdoor");
718e3744 14669
ea47320b
DL
14670 vty_out(vty, "\n");
14671 }
14672
d62a17ae 14673 /* Aggregate-address configuration. */
9bcb3eef
DS
14674 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14675 dest = bgp_route_next(dest)) {
14676 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14677 if (bgp_aggregate == NULL)
ea47320b 14678 continue;
d62a17ae 14679
9bcb3eef 14680 p = bgp_dest_get_prefix(dest);
d62a17ae 14681
8228a9a7 14682 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14683
ea47320b
DL
14684 if (bgp_aggregate->as_set)
14685 vty_out(vty, " as-set");
d62a17ae 14686
ea47320b
DL
14687 if (bgp_aggregate->summary_only)
14688 vty_out(vty, " summary-only");
718e3744 14689
20894f50
DA
14690 if (bgp_aggregate->rmap.name)
14691 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14692
229757f1
DA
14693 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14694 vty_out(vty, " origin %s",
14695 bgp_origin2str(bgp_aggregate->origin));
14696
6aabb15d
RZ
14697 if (bgp_aggregate->match_med)
14698 vty_out(vty, " matching-MED-only");
14699
365ab2e7
RZ
14700 if (bgp_aggregate->suppress_map_name)
14701 vty_out(vty, " suppress-map %s",
14702 bgp_aggregate->suppress_map_name);
14703
ea47320b
DL
14704 vty_out(vty, "\n");
14705 }
d62a17ae 14706}
734b349e 14707
2b791107 14708void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14709 safi_t safi)
d62a17ae 14710{
9bcb3eef 14711 struct bgp_dest *dest;
d62a17ae 14712 struct bgp_distance *bdistance;
14713
14714 /* Distance configuration. */
14715 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14716 && bgp->distance_local[afi][safi]
14717 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14718 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14719 || bgp->distance_local[afi][safi]
14720 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14721 vty_out(vty, " distance bgp %d %d %d\n",
14722 bgp->distance_ebgp[afi][safi],
14723 bgp->distance_ibgp[afi][safi],
14724 bgp->distance_local[afi][safi]);
14725 }
734b349e 14726
9bcb3eef
DS
14727 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14728 dest = bgp_route_next(dest)) {
14729 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14730 if (bdistance != NULL)
56ca3b5b 14731 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14732 bdistance->distance, dest,
d62a17ae 14733 bdistance->access_list ? bdistance->access_list
14734 : "");
ca2e160d 14735 }
718e3744 14736}
14737
14738/* Allocate routing table structure and install commands. */
d62a17ae 14739void bgp_route_init(void)
14740{
14741 afi_t afi;
14742 safi_t safi;
14743
14744 /* Init BGP distance table. */
05c7a1cc 14745 FOREACH_AFI_SAFI (afi, safi)
960035b2 14746 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14747
14748 /* IPv4 BGP commands. */
14749 install_element(BGP_NODE, &bgp_table_map_cmd);
14750 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14751 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14752
554b3b10 14753 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14754
14755 /* IPv4 unicast configuration. */
14756 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14757 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14758 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14759
554b3b10 14760 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14761
14762 /* IPv4 multicast configuration. */
14763 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14764 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14765 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14766 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14767
14768 /* IPv4 labeled-unicast configuration. */
fb985e0c 14769 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14770 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14771
d62a17ae 14772 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14773 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14774 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14775 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14776 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14777 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14778 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14779 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14780
14781 install_element(VIEW_NODE,
14782 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14783 install_element(VIEW_NODE,
14784 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14785 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14786 install_element(VIEW_NODE,
14787 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14788#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14789 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14790#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14791 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14792 install_element(VIEW_NODE,
44c69747 14793 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14794
d62a17ae 14795 /* BGP dampening clear commands */
14796 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14797 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14798
d62a17ae 14799 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14800 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14801
14802 /* prefix count */
14803 install_element(ENABLE_NODE,
14804 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14805#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14806 install_element(ENABLE_NODE,
14807 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14808#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14809
d62a17ae 14810 /* New config IPv6 BGP commands. */
14811 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14812 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14813 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14814
554b3b10 14815 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14816
14817 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14818
fb985e0c
DA
14819 /* IPv6 labeled unicast address family. */
14820 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14821 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14822
d62a17ae 14823 install_element(BGP_NODE, &bgp_distance_cmd);
14824 install_element(BGP_NODE, &no_bgp_distance_cmd);
14825 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14826 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14827 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14828 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14829 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14830 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14831 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14832 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14833 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14834 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14835 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14836 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14837 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14838
ef5f4b23 14839 /* BGP dampening */
d9ce5113
CS
14840 install_element(BGP_NODE, &bgp_dampening_cmd);
14841 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14842 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14843 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14844 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14845 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14846 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14847
14848 /* Large Communities */
14849 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14850 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14851
14852 /* show bgp ipv4 flowspec detailed */
14853 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14854
2a0e69ae 14855 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14856 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14857}
14858
14859void bgp_route_finish(void)
14860{
14861 afi_t afi;
14862 safi_t safi;
14863
05c7a1cc
QY
14864 FOREACH_AFI_SAFI (afi, safi) {
14865 bgp_table_unlock(bgp_distance_table[afi][safi]);
14866 bgp_distance_table[afi][safi] = NULL;
14867 }
228da428 14868}