]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
doc: Add Displaying Routes by RD section
[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;
ee88563a
JM
569 int igp_metric_ret = 0;
570 int peer_sort_ret = -1;
d62a17ae 571 char new_buf[PATH_ADDPATH_STR_BUFFER];
572 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
573 uint32_t new_mm_seq;
574 uint32_t exist_mm_seq;
6d8c603a 575 int nh_cmp;
d071f237
AK
576 esi_t *exist_esi;
577 esi_t *new_esi;
578 bool same_esi;
579 bool old_proxy;
580 bool new_proxy;
33c6e933 581 bool new_origin, exist_origin;
d62a17ae 582
583 *paths_eq = 0;
584
585 /* 0. Null check. */
586 if (new == NULL) {
fdf81fa0 587 *reason = bgp_path_selection_none;
d62a17ae 588 if (debug)
589 zlog_debug("%s: new is NULL", pfx_buf);
590 return 0;
591 }
2ec1e66f 592
d62a17ae 593 if (debug)
7533cad7
QY
594 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
595 sizeof(new_buf));
718e3744 596
d62a17ae 597 if (exist == NULL) {
fdf81fa0 598 *reason = bgp_path_selection_first;
d62a17ae 599 if (debug)
600 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
601 new_buf);
602 return 1;
603 }
2ec1e66f 604
d62a17ae 605 if (debug) {
7533cad7
QY
606 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
607 sizeof(exist_buf));
d62a17ae 608 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
609 pfx_buf, new_buf, new->flags, exist_buf,
610 exist->flags);
611 }
8ff56318 612
d62a17ae 613 newattr = new->attr;
614 existattr = exist->attr;
615
616 /* For EVPN routes, we cannot just go by local vs remote, we have to
617 * look at the MAC mobility sequence number, if present.
618 */
619 if (safi == SAFI_EVPN) {
620 /* This is an error condition described in RFC 7432 Section
621 * 15.2. The RFC
622 * states that in this scenario "the PE MUST alert the operator"
623 * but it
624 * does not state what other action to take. In order to provide
625 * some
626 * consistency in this scenario we are going to prefer the path
627 * with the
628 * sticky flag.
629 */
630 if (newattr->sticky != existattr->sticky) {
631 if (!debug) {
9bcb3eef
DS
632 prefix2str(
633 bgp_dest_get_prefix(new->net), pfx_buf,
634 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310 635 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
636 new, new_buf, sizeof(new_buf));
637 bgp_path_info_path_with_addpath_rx_str(
638 exist, exist_buf, sizeof(exist_buf));
d62a17ae 639 }
640
641 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 642 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
643 if (debug)
644 zlog_debug(
645 "%s: %s wins over %s due to sticky MAC flag",
646 pfx_buf, new_buf, exist_buf);
d62a17ae 647 return 1;
648 }
649
650 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 651 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
652 if (debug)
653 zlog_debug(
654 "%s: %s loses to %s due to sticky MAC flag",
655 pfx_buf, new_buf, exist_buf);
d62a17ae 656 return 0;
657 }
658 }
128ea8ab 659
d071f237
AK
660 new_esi = bgp_evpn_attr_get_esi(newattr);
661 exist_esi = bgp_evpn_attr_get_esi(existattr);
662 if (bgp_evpn_is_esi_valid(new_esi) &&
663 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
664 same_esi = true;
665 } else {
666 same_esi = false;
667 }
668
669 /* If both paths have the same non-zero ES and
670 * one path is local it wins.
671 * PS: Note the local path wins even if the remote
672 * has the higher MM seq. The local path's
673 * MM seq will be fixed up to match the highest
674 * rem seq, subsequently.
675 */
676 if (same_esi) {
677 char esi_buf[ESI_STR_LEN];
678
679 if (bgp_evpn_is_path_local(bgp, new)) {
680 *reason = bgp_path_selection_evpn_local_path;
681 if (debug)
682 zlog_debug(
683 "%s: %s wins over %s as ES %s is same and local",
684 pfx_buf, new_buf, exist_buf,
685 esi_to_str(new_esi, esi_buf,
686 sizeof(esi_buf)));
687 return 1;
688 }
689 if (bgp_evpn_is_path_local(bgp, exist)) {
690 *reason = bgp_path_selection_evpn_local_path;
691 if (debug)
692 zlog_debug(
693 "%s: %s loses to %s as ES %s is same and local",
694 pfx_buf, new_buf, exist_buf,
695 esi_to_str(new_esi, esi_buf,
696 sizeof(esi_buf)));
697 return 0;
698 }
699 }
700
d62a17ae 701 new_mm_seq = mac_mobility_seqnum(newattr);
702 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 703
d62a17ae 704 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 705 *reason = bgp_path_selection_evpn_seq;
d62a17ae 706 if (debug)
707 zlog_debug(
708 "%s: %s wins over %s due to MM seq %u > %u",
709 pfx_buf, new_buf, exist_buf, new_mm_seq,
710 exist_mm_seq);
711 return 1;
712 }
8ff56318 713
d62a17ae 714 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 715 *reason = bgp_path_selection_evpn_seq;
d62a17ae 716 if (debug)
717 zlog_debug(
718 "%s: %s loses to %s due to MM seq %u < %u",
719 pfx_buf, new_buf, exist_buf, new_mm_seq,
720 exist_mm_seq);
721 return 0;
722 }
6d8c603a 723
d071f237
AK
724 /* if the sequence numbers and ESI are the same and one path
725 * is non-proxy it wins (over proxy)
726 */
727 new_proxy = bgp_evpn_attr_is_proxy(newattr);
728 old_proxy = bgp_evpn_attr_is_proxy(existattr);
729 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
730 old_proxy != new_proxy) {
731 if (!new_proxy) {
732 *reason = bgp_path_selection_evpn_non_proxy;
733 if (debug)
734 zlog_debug(
735 "%s: %s wins over %s, same seq/es and non-proxy",
736 pfx_buf, new_buf, exist_buf);
737 return 1;
738 }
739
740 *reason = bgp_path_selection_evpn_non_proxy;
741 if (debug)
742 zlog_debug(
743 "%s: %s loses to %s, same seq/es and non-proxy",
744 pfx_buf, new_buf, exist_buf);
745 return 0;
746 }
747
6d8c603a
AK
748 /*
749 * if sequence numbers are the same path with the lowest IP
750 * wins
751 */
752 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
753 if (nh_cmp < 0) {
fdf81fa0 754 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
755 if (debug)
756 zlog_debug(
23d0a753 757 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 758 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 759 &new->attr->nexthop);
6d8c603a
AK
760 return 1;
761 }
762 if (nh_cmp > 0) {
fdf81fa0 763 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
764 if (debug)
765 zlog_debug(
23d0a753 766 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 767 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 768 &new->attr->nexthop);
6d8c603a
AK
769 return 0;
770 }
d62a17ae 771 }
9fbdd100 772
d62a17ae 773 /* 1. Weight check. */
d62a17ae 774 new_weight = newattr->weight;
775 exist_weight = existattr->weight;
8ff56318 776
d62a17ae 777 if (new_weight > exist_weight) {
fdf81fa0 778 *reason = bgp_path_selection_weight;
d62a17ae 779 if (debug)
780 zlog_debug("%s: %s wins over %s due to weight %d > %d",
781 pfx_buf, new_buf, exist_buf, new_weight,
782 exist_weight);
783 return 1;
784 }
718e3744 785
d62a17ae 786 if (new_weight < exist_weight) {
fdf81fa0 787 *reason = bgp_path_selection_weight;
d62a17ae 788 if (debug)
789 zlog_debug("%s: %s loses to %s due to weight %d < %d",
790 pfx_buf, new_buf, exist_buf, new_weight,
791 exist_weight);
792 return 0;
793 }
9fbdd100 794
d62a17ae 795 /* 2. Local preference check. */
796 new_pref = exist_pref = bgp->default_local_pref;
797
798 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
799 new_pref = newattr->local_pref;
800 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
801 exist_pref = existattr->local_pref;
802
803 if (new_pref > exist_pref) {
fdf81fa0 804 *reason = bgp_path_selection_local_pref;
d62a17ae 805 if (debug)
806 zlog_debug(
807 "%s: %s wins over %s due to localpref %d > %d",
808 pfx_buf, new_buf, exist_buf, new_pref,
809 exist_pref);
810 return 1;
811 }
718e3744 812
d62a17ae 813 if (new_pref < exist_pref) {
fdf81fa0 814 *reason = bgp_path_selection_local_pref;
d62a17ae 815 if (debug)
816 zlog_debug(
817 "%s: %s loses to %s due to localpref %d < %d",
818 pfx_buf, new_buf, exist_buf, new_pref,
819 exist_pref);
820 return 0;
821 }
9fbdd100 822
d62a17ae 823 /* 3. Local route check. We prefer:
824 * - BGP_ROUTE_STATIC
825 * - BGP_ROUTE_AGGREGATE
826 * - BGP_ROUTE_REDISTRIBUTE
827 */
33c6e933
DS
828 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
829 new->sub_type == BGP_ROUTE_IMPORTED);
830 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
831 exist->sub_type == BGP_ROUTE_IMPORTED);
832
833 if (new_origin && !exist_origin) {
fdf81fa0 834 *reason = bgp_path_selection_local_route;
d62a17ae 835 if (debug)
836 zlog_debug(
837 "%s: %s wins over %s due to preferred BGP_ROUTE type",
838 pfx_buf, new_buf, exist_buf);
839 return 1;
840 }
718e3744 841
33c6e933 842 if (!new_origin && exist_origin) {
fdf81fa0 843 *reason = bgp_path_selection_local_route;
d62a17ae 844 if (debug)
845 zlog_debug(
846 "%s: %s loses to %s due to preferred BGP_ROUTE type",
847 pfx_buf, new_buf, exist_buf);
848 return 0;
6811845b 849 }
718e3744 850
d62a17ae 851 /* 4. AS path length check. */
892fedb6 852 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 853 int exist_hops = aspath_count_hops(existattr->aspath);
854 int exist_confeds = aspath_count_confeds(existattr->aspath);
855
892fedb6 856 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 857 int aspath_hops;
858
859 aspath_hops = aspath_count_hops(newattr->aspath);
860 aspath_hops += aspath_count_confeds(newattr->aspath);
861
862 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 863 *reason = bgp_path_selection_confed_as_path;
d62a17ae 864 if (debug)
865 zlog_debug(
866 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
867 pfx_buf, new_buf, exist_buf,
868 aspath_hops,
869 (exist_hops + exist_confeds));
870 return 1;
871 }
872
873 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 874 *reason = bgp_path_selection_confed_as_path;
d62a17ae 875 if (debug)
876 zlog_debug(
877 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
878 pfx_buf, new_buf, exist_buf,
879 aspath_hops,
880 (exist_hops + exist_confeds));
881 return 0;
882 }
883 } else {
884 int newhops = aspath_count_hops(newattr->aspath);
885
886 if (newhops < exist_hops) {
fdf81fa0 887 *reason = bgp_path_selection_as_path;
d62a17ae 888 if (debug)
889 zlog_debug(
890 "%s: %s wins over %s due to aspath hopcount %d < %d",
891 pfx_buf, new_buf, exist_buf,
892 newhops, exist_hops);
893 return 1;
894 }
895
896 if (newhops > exist_hops) {
fdf81fa0 897 *reason = bgp_path_selection_as_path;
d62a17ae 898 if (debug)
899 zlog_debug(
900 "%s: %s loses to %s due to aspath hopcount %d > %d",
901 pfx_buf, new_buf, exist_buf,
902 newhops, exist_hops);
903 return 0;
904 }
905 }
906 }
9fbdd100 907
d62a17ae 908 /* 5. Origin check. */
909 if (newattr->origin < existattr->origin) {
fdf81fa0 910 *reason = bgp_path_selection_origin;
d62a17ae 911 if (debug)
912 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
913 pfx_buf, new_buf, exist_buf,
914 bgp_origin_long_str[newattr->origin],
915 bgp_origin_long_str[existattr->origin]);
916 return 1;
917 }
718e3744 918
d62a17ae 919 if (newattr->origin > existattr->origin) {
fdf81fa0 920 *reason = bgp_path_selection_origin;
d62a17ae 921 if (debug)
922 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
923 pfx_buf, new_buf, exist_buf,
924 bgp_origin_long_str[newattr->origin],
925 bgp_origin_long_str[existattr->origin]);
926 return 0;
927 }
718e3744 928
d62a17ae 929 /* 6. MED check. */
930 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
931 && aspath_count_hops(existattr->aspath) == 0);
932 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
933 && aspath_count_confeds(existattr->aspath) > 0
934 && aspath_count_hops(newattr->aspath) == 0
935 && aspath_count_hops(existattr->aspath) == 0);
936
892fedb6
DA
937 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
938 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 939 || aspath_cmp_left(newattr->aspath, existattr->aspath)
940 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
941 || internal_as_route) {
942 new_med = bgp_med_value(new->attr, bgp);
943 exist_med = bgp_med_value(exist->attr, bgp);
944
945 if (new_med < exist_med) {
fdf81fa0 946 *reason = bgp_path_selection_med;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to MED %d < %d",
950 pfx_buf, new_buf, exist_buf, new_med,
951 exist_med);
952 return 1;
953 }
8ff56318 954
d62a17ae 955 if (new_med > exist_med) {
fdf81fa0 956 *reason = bgp_path_selection_med;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to MED %d > %d",
960 pfx_buf, new_buf, exist_buf, new_med,
961 exist_med);
962 return 0;
963 }
964 }
9fbdd100 965
d62a17ae 966 /* 7. Peer type check. */
967 new_sort = new->peer->sort;
968 exist_sort = exist->peer->sort;
969
970 if (new_sort == BGP_PEER_EBGP
971 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 972 *reason = bgp_path_selection_peer;
d62a17ae 973 if (debug)
974 zlog_debug(
975 "%s: %s wins over %s due to eBGP peer > iBGP peer",
976 pfx_buf, new_buf, exist_buf);
ee88563a
JM
977 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
978 return 1;
979 peer_sort_ret = 1;
d62a17ae 980 }
718e3744 981
d62a17ae 982 if (exist_sort == BGP_PEER_EBGP
983 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 984 *reason = bgp_path_selection_peer;
d62a17ae 985 if (debug)
986 zlog_debug(
987 "%s: %s loses to %s due to iBGP peer < eBGP peer",
988 pfx_buf, new_buf, exist_buf);
ee88563a
JM
989 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
990 return 0;
991 peer_sort_ret = 0;
d62a17ae 992 }
8ff56318 993
d62a17ae 994 /* 8. IGP metric check. */
995 newm = existm = 0;
8ff56318 996
d62a17ae 997 if (new->extra)
998 newm = new->extra->igpmetric;
999 if (exist->extra)
1000 existm = exist->extra->igpmetric;
9fbdd100 1001
d62a17ae 1002 if (newm < existm) {
ee88563a 1003 if (debug && peer_sort_ret < 0)
d62a17ae 1004 zlog_debug(
d588b995 1005 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1006 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1007 igp_metric_ret = 1;
d62a17ae 1008 }
718e3744 1009
d62a17ae 1010 if (newm > existm) {
ee88563a 1011 if (debug && peer_sort_ret < 0)
d62a17ae 1012 zlog_debug(
d588b995 1013 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1014 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1015 igp_metric_ret = 0;
5e242b0d 1016 }
5e242b0d 1017
d62a17ae 1018 /* 9. Same IGP metric. Compare the cluster list length as
1019 representative of IGP hops metric. Rewrite the metric value
1020 pair (newm, existm) with the cluster list length. Prefer the
1021 path with smaller cluster list length. */
1022 if (newm == existm) {
bf0d28dc
DS
1023 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1024 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1025 && (mpath_cfg == NULL
1026 || CHECK_FLAG(
1027 mpath_cfg->ibgp_flags,
1028 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1029 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1030 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1031
1032 if (newm < existm) {
ee88563a 1033 if (debug && peer_sort_ret < 0)
d62a17ae 1034 zlog_debug(
d588b995 1035 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1036 pfx_buf, new_buf, exist_buf,
1037 newm, existm);
ee88563a 1038 igp_metric_ret = 1;
d62a17ae 1039 }
1040
1041 if (newm > existm) {
ee88563a 1042 if (debug && peer_sort_ret < 0)
d62a17ae 1043 zlog_debug(
d588b995 1044 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1045 pfx_buf, new_buf, exist_buf,
1046 newm, existm);
ee88563a 1047 igp_metric_ret = 0;
d62a17ae 1048 }
1049 }
1050 }
31a4638f 1051
d62a17ae 1052 /* 10. confed-external vs. confed-internal */
1053 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1054 if (new_sort == BGP_PEER_CONFED
1055 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1056 *reason = bgp_path_selection_confed;
d62a17ae 1057 if (debug)
1058 zlog_debug(
1059 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1060 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1061 if (!CHECK_FLAG(bgp->flags,
1062 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1063 return 1;
1064 peer_sort_ret = 1;
d62a17ae 1065 }
718e3744 1066
d62a17ae 1067 if (exist_sort == BGP_PEER_CONFED
1068 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1069 *reason = bgp_path_selection_confed;
d62a17ae 1070 if (debug)
1071 zlog_debug(
1072 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1073 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1074 if (!CHECK_FLAG(bgp->flags,
1075 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1076 return 0;
1077 peer_sort_ret = 0;
d62a17ae 1078 }
1079 }
718e3744 1080
d62a17ae 1081 /* 11. Maximum path check. */
1082 if (newm == existm) {
1083 /* If one path has a label but the other does not, do not treat
1084 * them as equals for multipath
1085 */
a4d82a8a 1086 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1087 != (exist->extra
b57ba6d2 1088 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1089 if (debug)
1090 zlog_debug(
1091 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1092 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1093 } else if (CHECK_FLAG(bgp->flags,
1094 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1095
1096 /*
1097 * For the two paths, all comparison steps till IGP
1098 * metric
1099 * have succeeded - including AS_PATH hop count. Since
1100 * 'bgp
1101 * bestpath as-path multipath-relax' knob is on, we
1102 * don't need
1103 * an exact match of AS_PATH. Thus, mark the paths are
1104 * equal.
1105 * That will trigger both these paths to get into the
1106 * multipath
1107 * array.
1108 */
1109 *paths_eq = 1;
1110
1111 if (debug)
1112 zlog_debug(
1113 "%s: %s and %s are equal via multipath-relax",
1114 pfx_buf, new_buf, exist_buf);
1115 } else if (new->peer->sort == BGP_PEER_IBGP) {
1116 if (aspath_cmp(new->attr->aspath,
1117 exist->attr->aspath)) {
1118 *paths_eq = 1;
1119
1120 if (debug)
1121 zlog_debug(
1122 "%s: %s and %s are equal via matching aspaths",
1123 pfx_buf, new_buf, exist_buf);
1124 }
1125 } else if (new->peer->as == exist->peer->as) {
1126 *paths_eq = 1;
1127
1128 if (debug)
1129 zlog_debug(
1130 "%s: %s and %s are equal via same remote-as",
1131 pfx_buf, new_buf, exist_buf);
1132 }
1133 } else {
1134 /*
1135 * TODO: If unequal cost ibgp multipath is enabled we can
1136 * mark the paths as equal here instead of returning
1137 */
ee88563a
JM
1138
1139 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1140 * if either step 7 or 10 (peer type checks) yielded a winner,
1141 * that result was returned immediately. Returning from step 10
1142 * ignored the return value computed in steps 8 and 9 (IGP
1143 * metric checks). In order to preserve that behavior, if
1144 * peer_sort_ret is set, return that rather than igp_metric_ret.
1145 */
1146 ret = peer_sort_ret;
1147 if (peer_sort_ret < 0) {
1148 ret = igp_metric_ret;
1149 if (debug) {
1150 if (ret == 1)
1151 zlog_debug(
1152 "%s: %s wins over %s after IGP metric comparison",
1153 pfx_buf, new_buf, exist_buf);
1154 else
1155 zlog_debug(
1156 "%s: %s loses to %s after IGP metric comparison",
1157 pfx_buf, new_buf, exist_buf);
1158 }
1159 *reason = bgp_path_selection_igp_metric;
d62a17ae 1160 }
1161 return ret;
1162 }
718e3744 1163
ee88563a
JM
1164 /*
1165 * At this point, the decision whether to set *paths_eq = 1 has been
1166 * completed. If we deferred returning because of bestpath peer-type
1167 * relax configuration, return now.
1168 */
1169 if (peer_sort_ret >= 0)
1170 return peer_sort_ret;
1171
d62a17ae 1172 /* 12. If both paths are external, prefer the path that was received
1173 first (the oldest one). This step minimizes route-flap, since a
1174 newer path won't displace an older one, even if it was the
1175 preferred route based on the additional decision criteria below. */
892fedb6 1176 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1177 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1178 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1179 *reason = bgp_path_selection_older;
d62a17ae 1180 if (debug)
1181 zlog_debug(
1182 "%s: %s wins over %s due to oldest external",
1183 pfx_buf, new_buf, exist_buf);
1184 return 1;
1185 }
9fbdd100 1186
1defdda8 1187 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1188 *reason = bgp_path_selection_older;
d62a17ae 1189 if (debug)
1190 zlog_debug(
1191 "%s: %s loses to %s due to oldest external",
1192 pfx_buf, new_buf, exist_buf);
1193 return 0;
1194 }
1195 }
718e3744 1196
d62a17ae 1197 /* 13. Router-ID comparision. */
1198 /* If one of the paths is "stale", the corresponding peer router-id will
1199 * be 0 and would always win over the other path. If originator id is
1200 * used for the comparision, it will decide which path is better.
1201 */
1202 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1203 new_id.s_addr = newattr->originator_id.s_addr;
1204 else
1205 new_id.s_addr = new->peer->remote_id.s_addr;
1206 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1207 exist_id.s_addr = existattr->originator_id.s_addr;
1208 else
1209 exist_id.s_addr = exist->peer->remote_id.s_addr;
1210
1211 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1212 *reason = bgp_path_selection_router_id;
d62a17ae 1213 if (debug)
1214 zlog_debug(
1215 "%s: %s wins over %s due to Router-ID comparison",
1216 pfx_buf, new_buf, exist_buf);
1217 return 1;
1218 }
718e3744 1219
d62a17ae 1220 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1221 *reason = bgp_path_selection_router_id;
d62a17ae 1222 if (debug)
1223 zlog_debug(
1224 "%s: %s loses to %s due to Router-ID comparison",
1225 pfx_buf, new_buf, exist_buf);
1226 return 0;
1227 }
9fbdd100 1228
d62a17ae 1229 /* 14. Cluster length comparision. */
1230 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1231 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1232
1233 if (new_cluster < exist_cluster) {
fdf81fa0 1234 *reason = bgp_path_selection_cluster_length;
d62a17ae 1235 if (debug)
1236 zlog_debug(
1237 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1238 pfx_buf, new_buf, exist_buf, new_cluster,
1239 exist_cluster);
1240 return 1;
1241 }
718e3744 1242
d62a17ae 1243 if (new_cluster > exist_cluster) {
fdf81fa0 1244 *reason = bgp_path_selection_cluster_length;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1248 pfx_buf, new_buf, exist_buf, new_cluster,
1249 exist_cluster);
1250 return 0;
1251 }
9fbdd100 1252
d62a17ae 1253 /* 15. Neighbor address comparision. */
1254 /* Do this only if neither path is "stale" as stale paths do not have
1255 * valid peer information (as the connection may or may not be up).
1256 */
1defdda8 1257 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1258 *reason = bgp_path_selection_stale;
d62a17ae 1259 if (debug)
1260 zlog_debug(
1261 "%s: %s wins over %s due to latter path being STALE",
1262 pfx_buf, new_buf, exist_buf);
1263 return 1;
1264 }
0de5153c 1265
1defdda8 1266 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1267 *reason = bgp_path_selection_stale;
d62a17ae 1268 if (debug)
1269 zlog_debug(
1270 "%s: %s loses to %s due to former path being STALE",
1271 pfx_buf, new_buf, exist_buf);
1272 return 0;
1273 }
718e3744 1274
d62a17ae 1275 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1276 if (new->peer->su_remote == NULL) {
1277 *reason = bgp_path_selection_local_configured;
d62a17ae 1278 return 0;
fdf81fa0
DS
1279 }
1280 if (exist->peer->su_remote == NULL) {
1281 *reason = bgp_path_selection_local_configured;
d62a17ae 1282 return 1;
fdf81fa0 1283 }
9fbdd100 1284
d62a17ae 1285 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1286
1287 if (ret == 1) {
fdf81fa0 1288 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1289 if (debug)
1290 zlog_debug(
1291 "%s: %s loses to %s due to Neighor IP comparison",
1292 pfx_buf, new_buf, exist_buf);
1293 return 0;
1294 }
1295
1296 if (ret == -1) {
fdf81fa0 1297 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1298 if (debug)
1299 zlog_debug(
1300 "%s: %s wins over %s due to Neighor IP comparison",
1301 pfx_buf, new_buf, exist_buf);
1302 return 1;
1303 }
9fbdd100 1304
fdf81fa0 1305 *reason = bgp_path_selection_default;
d62a17ae 1306 if (debug)
1307 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1308 pfx_buf, new_buf, exist_buf);
718e3744 1309
d62a17ae 1310 return 1;
718e3744 1311}
1312
d071f237
AK
1313
1314int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1315 struct bgp_path_info *exist, int *paths_eq)
1316{
1317 enum bgp_path_selection_reason reason;
1318 char pfx_buf[PREFIX2STR_BUFFER];
1319
1320 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1321 AFI_L2VPN, SAFI_EVPN, &reason);
1322}
1323
65efcfce
LB
1324/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1325 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1326 * multipath is enabled
65efcfce 1327 * This version is compatible with */
18ee8310
DS
1328int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1329 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1330 afi_t afi, safi_t safi,
1331 enum bgp_path_selection_reason *reason)
d62a17ae 1332{
1333 int paths_eq;
1334 int ret;
18ee8310 1335 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1336 afi, safi, reason);
d62a17ae 1337
1338 if (paths_eq)
1339 ret = 0;
1340 else {
1341 if (ret == 1)
1342 ret = -1;
1343 else
1344 ret = 1;
1345 }
1346 return ret;
65efcfce
LB
1347}
1348
5a1ae2c2
DS
1349static enum filter_type bgp_input_filter(struct peer *peer,
1350 const struct prefix *p,
d62a17ae 1351 struct attr *attr, afi_t afi,
1352 safi_t safi)
718e3744 1353{
d62a17ae 1354 struct bgp_filter *filter;
6401252f 1355 enum filter_type ret = FILTER_PERMIT;
718e3744 1356
d62a17ae 1357 filter = &peer->filter[afi][safi];
718e3744 1358
d62a17ae 1359#define FILTER_EXIST_WARN(F, f, filter) \
1360 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1361 zlog_debug("%s: Could not find configured input %s-list %s!", \
1362 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1363
1364 if (DISTRIBUTE_IN_NAME(filter)) {
1365 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1366
6401252f
QY
1367 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1368 == FILTER_DENY) {
1369 ret = FILTER_DENY;
1370 goto done;
1371 }
d62a17ae 1372 }
1373
1374 if (PREFIX_LIST_IN_NAME(filter)) {
1375 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1376
6401252f
QY
1377 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1378 == PREFIX_DENY) {
1379 ret = FILTER_DENY;
1380 goto done;
1381 }
d62a17ae 1382 }
1383
1384 if (FILTER_LIST_IN_NAME(filter)) {
1385 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1386
1387 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1388 == AS_FILTER_DENY) {
1389 ret = FILTER_DENY;
1390 goto done;
1391 }
d62a17ae 1392 }
1393
6401252f 1394done:
c7bb4f00 1395 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1396 char pfxprint[PREFIX2STR_BUFFER];
1397
1398 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1399 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1400 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1401 }
1402
1403 return ret;
650f76c2 1404#undef FILTER_EXIST_WARN
718e3744 1405}
1406
b8685f9b
DS
1407static enum filter_type bgp_output_filter(struct peer *peer,
1408 const struct prefix *p,
d62a17ae 1409 struct attr *attr, afi_t afi,
1410 safi_t safi)
718e3744 1411{
d62a17ae 1412 struct bgp_filter *filter;
6401252f 1413 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1414
1415 filter = &peer->filter[afi][safi];
1416
1417#define FILTER_EXIST_WARN(F, f, filter) \
1418 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1419 zlog_debug("%s: Could not find configured output %s-list %s!", \
1420 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1421
d62a17ae 1422 if (DISTRIBUTE_OUT_NAME(filter)) {
1423 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1424
6401252f
QY
1425 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1426 == FILTER_DENY) {
1427 ret = FILTER_DENY;
1428 goto done;
1429 }
d62a17ae 1430 }
1431
1432 if (PREFIX_LIST_OUT_NAME(filter)) {
1433 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1434
d62a17ae 1435 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1436 == PREFIX_DENY) {
1437 ret = FILTER_DENY;
1438 goto done;
1439 }
d62a17ae 1440 }
718e3744 1441
d62a17ae 1442 if (FILTER_LIST_OUT_NAME(filter)) {
1443 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1444
d62a17ae 1445 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1446 == AS_FILTER_DENY) {
1447 ret = FILTER_DENY;
1448 goto done;
1449 }
1450 }
1451
c7bb4f00 1452 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1453 char pfxprint[PREFIX2STR_BUFFER];
1454
1455 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1456 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1457 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1458 }
718e3744 1459
6401252f
QY
1460done:
1461 return ret;
650f76c2 1462#undef FILTER_EXIST_WARN
718e3744 1463}
1464
1465/* If community attribute includes no_export then return 1. */
3dc339cd 1466static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1467{
1468 if (attr->community) {
1469 /* NO_ADVERTISE check. */
1470 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1471 return true;
d62a17ae 1472
1473 /* NO_EXPORT check. */
1474 if (peer->sort == BGP_PEER_EBGP
1475 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1476 return true;
d62a17ae 1477
1478 /* NO_EXPORT_SUBCONFED check. */
1479 if (peer->sort == BGP_PEER_EBGP
1480 || peer->sort == BGP_PEER_CONFED)
1481 if (community_include(attr->community,
1482 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1483 return true;
d62a17ae 1484 }
3dc339cd 1485 return false;
718e3744 1486}
1487
1488/* Route reflection loop check. */
3dc339cd 1489static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1490{
d62a17ae 1491 struct in_addr cluster_id;
779fee93 1492 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1493
779fee93 1494 if (cluster) {
d62a17ae 1495 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1496 cluster_id = peer->bgp->cluster_id;
1497 else
1498 cluster_id = peer->bgp->router_id;
1499
779fee93 1500 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1501 return true;
d62a17ae 1502 }
3dc339cd 1503 return false;
718e3744 1504}
6b0655a2 1505
5a1ae2c2 1506static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1507 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1508 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1509 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1510{
d62a17ae 1511 struct bgp_filter *filter;
82b692c0
LK
1512 struct bgp_path_info rmap_path = { 0 };
1513 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1514 route_map_result_t ret;
1515 struct route_map *rmap = NULL;
718e3744 1516
d62a17ae 1517 filter = &peer->filter[afi][safi];
718e3744 1518
d62a17ae 1519 /* Apply default weight value. */
1520 if (peer->weight[afi][safi])
1521 attr->weight = peer->weight[afi][safi];
718e3744 1522
d62a17ae 1523 if (rmap_name) {
1524 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1525
d62a17ae 1526 if (rmap == NULL)
1527 return RMAP_DENY;
1528 } else {
1529 if (ROUTE_MAP_IN_NAME(filter)) {
1530 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1531
d62a17ae 1532 if (rmap == NULL)
1533 return RMAP_DENY;
1534 }
1535 }
0b16f239 1536
d62a17ae 1537 /* Route map apply. */
1538 if (rmap) {
40381db7 1539 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1540 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1541 rmap_path.peer = peer;
1542 rmap_path.attr = attr;
82b692c0 1543 rmap_path.extra = &extra;
9bcb3eef 1544 rmap_path.net = dest;
196c6b09 1545
82b692c0
LK
1546 extra.num_labels = num_labels;
1547 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1548 memcpy(extra.label, label,
1549 num_labels * sizeof(mpls_label_t));
718e3744 1550
d62a17ae 1551 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1552
d62a17ae 1553 /* Apply BGP route map to the attribute. */
1782514f 1554 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1555
d62a17ae 1556 peer->rmap_type = 0;
0b16f239 1557
1f2263be 1558 if (ret == RMAP_DENYMATCH)
d62a17ae 1559 return RMAP_DENY;
0b16f239 1560 }
d62a17ae 1561 return RMAP_PERMIT;
0b16f239
DS
1562}
1563
5f040085 1564static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1565 struct attr *attr, afi_t afi, safi_t safi,
1566 const char *rmap_name)
0b16f239 1567{
40381db7 1568 struct bgp_path_info rmap_path;
d62a17ae 1569 route_map_result_t ret;
1570 struct route_map *rmap = NULL;
d7c0a89a 1571 uint8_t rmap_type;
0b16f239 1572
b787157a
DS
1573 /*
1574 * So if we get to this point and have no rmap_name
1575 * we want to just show the output as it currently
1576 * exists.
1577 */
1578 if (!rmap_name)
1579 return RMAP_PERMIT;
0b16f239 1580
d62a17ae 1581 /* Apply default weight value. */
1582 if (peer->weight[afi][safi])
1583 attr->weight = peer->weight[afi][safi];
0b16f239 1584
b787157a 1585 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1586
b787157a
DS
1587 /*
1588 * If we have a route map name and we do not find
1589 * the routemap that means we have an implicit
1590 * deny.
1591 */
1592 if (rmap == NULL)
1593 return RMAP_DENY;
0b16f239 1594
40381db7 1595 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1596 /* Route map apply. */
b787157a 1597 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1598 rmap_path.peer = peer;
1599 rmap_path.attr = attr;
0b16f239 1600
0f672529 1601 rmap_type = peer->rmap_type;
b787157a 1602 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1603
b787157a 1604 /* Apply BGP route map to the attribute. */
1782514f 1605 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1606
0f672529 1607 peer->rmap_type = rmap_type;
b787157a
DS
1608
1609 if (ret == RMAP_DENYMATCH)
1610 /*
1611 * caller has multiple error paths with bgp_attr_flush()
1612 */
1613 return RMAP_DENY;
ac41b2a2 1614
d62a17ae 1615 return RMAP_PERMIT;
718e3744 1616}
6b0655a2 1617
5000f21c 1618/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1619static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1620 struct peer *peer, struct attr *attr)
1621{
1622 if (peer->sort == BGP_PEER_EBGP
1623 && (peer_af_flag_check(peer, afi, safi,
1624 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1625 || peer_af_flag_check(peer, afi, safi,
1626 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1627 || peer_af_flag_check(peer, afi, safi,
1628 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1629 || peer_af_flag_check(peer, afi, safi,
1630 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1631 // Take action on the entire aspath
1632 if (peer_af_flag_check(peer, afi, safi,
1633 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1634 || peer_af_flag_check(peer, afi, safi,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1636 if (peer_af_flag_check(
1637 peer, afi, safi,
1638 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1639 attr->aspath = aspath_replace_private_asns(
bf26b80e 1640 attr->aspath, bgp->as, peer->as);
d62a17ae 1641
1642 // The entire aspath consists of private ASNs so create
1643 // an empty aspath
1644 else if (aspath_private_as_check(attr->aspath))
1645 attr->aspath = aspath_empty_get();
1646
1647 // There are some public and some private ASNs, remove
1648 // the private ASNs
1649 else
1650 attr->aspath = aspath_remove_private_asns(
bf26b80e 1651 attr->aspath, peer->as);
d62a17ae 1652 }
1653
1654 // 'all' was not specified so the entire aspath must be private
1655 // ASNs
1656 // for us to do anything
1657 else if (aspath_private_as_check(attr->aspath)) {
1658 if (peer_af_flag_check(
1659 peer, afi, safi,
1660 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1661 attr->aspath = aspath_replace_private_asns(
bf26b80e 1662 attr->aspath, bgp->as, peer->as);
d62a17ae 1663 else
1664 attr->aspath = aspath_empty_get();
1665 }
1666 }
5000f21c
DS
1667}
1668
c7122e14 1669/* If this is an EBGP peer with as-override */
d62a17ae 1670static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1671 struct peer *peer, struct attr *attr)
1672{
1673 if (peer->sort == BGP_PEER_EBGP
1674 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1675 if (aspath_single_asn_check(attr->aspath, peer->as))
1676 attr->aspath = aspath_replace_specific_asn(
1677 attr->aspath, peer->as, bgp->as);
1678 }
1679}
1680
7f323236
DW
1681void bgp_attr_add_gshut_community(struct attr *attr)
1682{
1683 struct community *old;
1684 struct community *new;
1685 struct community *merge;
1686 struct community *gshut;
1687
1688 old = attr->community;
1689 gshut = community_str2com("graceful-shutdown");
1690
990f4f91 1691 assert(gshut);
1692
7f323236
DW
1693 if (old) {
1694 merge = community_merge(community_dup(old), gshut);
1695
a4d82a8a 1696 if (old->refcnt == 0)
3c1f53de 1697 community_free(&old);
7f323236
DW
1698
1699 new = community_uniq_sort(merge);
3c1f53de 1700 community_free(&merge);
7f323236
DW
1701 } else {
1702 new = community_dup(gshut);
1703 }
1704
3c1f53de 1705 community_free(&gshut);
7f323236
DW
1706 attr->community = new;
1707 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1708
1709 /* When we add the graceful-shutdown community we must also
1710 * lower the local-preference */
1711 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1712 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1713}
1714
1715
e73c112e
MK
1716/* Notify BGP Conditional advertisement scanner process. */
1717void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1718{
1719 struct peer *temp_peer;
1720 struct peer *peer = SUBGRP_PEER(subgrp);
1721 struct listnode *temp_node, *temp_nnode = NULL;
1722 afi_t afi = SUBGRP_AFI(subgrp);
1723 safi_t safi = SUBGRP_SAFI(subgrp);
1724 struct bgp *bgp = SUBGRP_INST(subgrp);
1725 struct bgp_filter *filter = &peer->filter[afi][safi];
1726
1727 if (!ADVERTISE_MAP_NAME(filter))
1728 return;
1729
1730 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1731 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1732 continue;
1733
1734 if (peer != temp_peer)
1735 continue;
1736
1737 temp_peer->advmap_table_change = true;
1738 break;
1739 }
1740}
1741
1742
f2ee6d5c 1743void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1744{
960035b2 1745 if (family == AF_INET) {
975a328e
DA
1746 attr->nexthop.s_addr = INADDR_ANY;
1747 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1748 }
d62a17ae 1749 if (family == AF_INET6)
1750 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1751 if (family == AF_EVPN)
1752 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1753}
1754
9bcb3eef 1755bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1756 struct update_subgroup *subgrp,
7f7940e6
MK
1757 const struct prefix *p, struct attr *attr,
1758 bool skip_rmap_check)
d62a17ae 1759{
1760 struct bgp_filter *filter;
1761 struct peer *from;
1762 struct peer *peer;
1763 struct peer *onlypeer;
1764 struct bgp *bgp;
40381db7 1765 struct attr *piattr;
b68885f9 1766 route_map_result_t ret;
d62a17ae 1767 int transparent;
1768 int reflect;
1769 afi_t afi;
1770 safi_t safi;
1771 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1772 bool nh_reset = false;
1773 uint64_t cum_bw;
d62a17ae 1774
1775 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1776 return false;
d62a17ae 1777
1778 afi = SUBGRP_AFI(subgrp);
1779 safi = SUBGRP_SAFI(subgrp);
1780 peer = SUBGRP_PEER(subgrp);
1781 onlypeer = NULL;
1782 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1783 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1784
40381db7 1785 from = pi->peer;
d62a17ae 1786 filter = &peer->filter[afi][safi];
1787 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1788 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1789 : pi->attr;
3f9c7369 1790
49e5a4a0 1791#ifdef ENABLE_BGP_VNC
d62a17ae 1792 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1793 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1794 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1795
1796 /*
1797 * direct and direct_ext type routes originate internally even
1798 * though they can have peer pointers that reference other
1799 * systems
1800 */
8228a9a7
DS
1801 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1802 __func__, p);
d62a17ae 1803 samepeer_safe = 1;
1804 }
65efcfce
LB
1805#endif
1806
ddb5b488
PZ
1807 if (((afi == AFI_IP) || (afi == AFI_IP6))
1808 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1809 && (pi->type == ZEBRA_ROUTE_BGP)
1810 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1811
1812 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1813
1814 samepeer_safe = 1;
1815 }
1816
d62a17ae 1817 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1818 * pi is valid */
1819 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1820 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1821 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1822 return false;
d62a17ae 1823 }
adbac85e 1824
d62a17ae 1825 /* If this is not the bestpath then check to see if there is an enabled
1826 * addpath
1827 * feature that requires us to advertise it */
40381db7 1828 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1829 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1830 return false;
d62a17ae 1831 }
1832 }
06370dac 1833
d62a17ae 1834 /* Aggregate-address suppress check. */
4056a5f6
RZ
1835 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1836 return false;
3f9c7369 1837
13b7e7f0
DS
1838 /*
1839 * If we are doing VRF 2 VRF leaking via the import
1840 * statement, we want to prevent the route going
1841 * off box as that the RT and RD created are localy
1842 * significant and globaly useless.
1843 */
40381db7
DS
1844 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1845 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1846 return false;
13b7e7f0 1847
d62a17ae 1848 /* If it's labeled safi, make sure the route has a valid label. */
1849 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1850 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1851 if (!bgp_is_valid_label(&label)) {
1852 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1853 zlog_debug("u%" PRIu64 ":s%" PRIu64
1854 " %pFX is filtered - no label (%p)",
d62a17ae 1855 subgrp->update_group->id, subgrp->id,
8228a9a7 1856 p, &label);
3dc339cd 1857 return false;
d62a17ae 1858 }
1859 }
cd1964ff 1860
d62a17ae 1861 /* Do not send back route to sender. */
1862 if (onlypeer && from == onlypeer) {
3dc339cd 1863 return false;
d62a17ae 1864 }
3f9c7369 1865
d62a17ae 1866 /* Do not send the default route in the BGP table if the neighbor is
1867 * configured for default-originate */
1868 if (CHECK_FLAG(peer->af_flags[afi][safi],
1869 PEER_FLAG_DEFAULT_ORIGINATE)) {
1870 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1871 return false;
d62a17ae 1872 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1873 return false;
d62a17ae 1874 }
4125bb67 1875
d62a17ae 1876 /* Transparency check. */
1877 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1878 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1879 transparent = 1;
1880 else
1881 transparent = 0;
1882
1883 /* If community is not disabled check the no-export and local. */
40381db7 1884 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1885 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1886 zlog_debug("%s: community filter check fail for %pFX",
1887 __func__, p);
3dc339cd 1888 return false;
d62a17ae 1889 }
3f9c7369 1890
d62a17ae 1891 /* If the attribute has originator-id and it is same as remote
1892 peer's id. */
40381db7
DS
1893 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1894 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1895 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1896 zlog_debug(
8228a9a7
DS
1897 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1898 onlypeer->host, p);
3dc339cd 1899 return false;
d62a17ae 1900 }
3f9c7369 1901
d62a17ae 1902 /* ORF prefix-list filter check */
1903 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1904 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1905 || CHECK_FLAG(peer->af_cap[afi][safi],
1906 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1907 if (peer->orf_plist[afi][safi]) {
1908 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1909 == PREFIX_DENY) {
1910 if (bgp_debug_update(NULL, p,
1911 subgrp->update_group, 0))
1912 zlog_debug(
8228a9a7
DS
1913 "%s [Update:SEND] %pFX is filtered via ORF",
1914 peer->host, p);
3dc339cd 1915 return false;
d62a17ae 1916 }
1917 }
1918
1919 /* Output filter check. */
40381db7 1920 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1921 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1922 zlog_debug("%s [Update:SEND] %pFX is filtered",
1923 peer->host, p);
3dc339cd 1924 return false;
d62a17ae 1925 }
3f9c7369 1926
d62a17ae 1927 /* AS path loop check. */
2b31007c
RZ
1928 if (onlypeer && onlypeer->as_path_loop_detection
1929 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1930 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1931 zlog_debug(
3efd0893 1932 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1933 onlypeer->host, onlypeer->as);
3dc339cd 1934 return false;
d62a17ae 1935 }
3f9c7369 1936
d62a17ae 1937 /* If we're a CONFED we need to loop check the CONFED ID too */
1938 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1939 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1940 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1941 zlog_debug(
3efd0893 1942 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1943 peer->host, bgp->confed_id);
3dc339cd 1944 return false;
d62a17ae 1945 }
3f9c7369 1946 }
3f9c7369 1947
d62a17ae 1948 /* Route-Reflect check. */
1949 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1950 reflect = 1;
1951 else
1952 reflect = 0;
1953
1954 /* IBGP reflection check. */
1955 if (reflect && !samepeer_safe) {
1956 /* A route from a Client peer. */
1957 if (CHECK_FLAG(from->af_flags[afi][safi],
1958 PEER_FLAG_REFLECTOR_CLIENT)) {
1959 /* Reflect to all the Non-Client peers and also to the
1960 Client peers other than the originator. Originator
1961 check
1962 is already done. So there is noting to do. */
1963 /* no bgp client-to-client reflection check. */
892fedb6
DA
1964 if (CHECK_FLAG(bgp->flags,
1965 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1966 if (CHECK_FLAG(peer->af_flags[afi][safi],
1967 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1968 return false;
d62a17ae 1969 } else {
1970 /* A route from a Non-client peer. Reflect to all other
1971 clients. */
1972 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1973 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1974 return false;
d62a17ae 1975 }
1976 }
3f9c7369 1977
d62a17ae 1978 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1979 *attr = *piattr;
d62a17ae 1980
1981 /* If local-preference is not set. */
1982 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1983 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1984 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1985 attr->local_pref = bgp->default_local_pref;
3f9c7369 1986 }
3f9c7369 1987
d62a17ae 1988 /* If originator-id is not set and the route is to be reflected,
1989 set the originator id */
1990 if (reflect
1991 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1992 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1993 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1994 }
3f9c7369 1995
d62a17ae 1996 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1997 */
1998 if (peer->sort == BGP_PEER_EBGP
1999 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2000 if (from != bgp->peer_self && !transparent
2001 && !CHECK_FLAG(peer->af_flags[afi][safi],
2002 PEER_FLAG_MED_UNCHANGED))
2003 attr->flag &=
2004 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2005 }
3f9c7369 2006
d62a17ae 2007 /* Since the nexthop attribute can vary per peer, it is not explicitly
2008 * set
2009 * in announce check, only certain flags and length (or number of
2010 * nexthops
2011 * -- for IPv6/MP_REACH) are set here in order to guide the update
2012 * formation
2013 * code in setting the nexthop(s) on a per peer basis in
2014 * reformat_peer().
2015 * Typically, the source nexthop in the attribute is preserved but in
2016 * the
2017 * scenarios where we know it will always be overwritten, we reset the
2018 * nexthop to "0" in an attempt to achieve better Update packing. An
2019 * example of this is when a prefix from each of 2 IBGP peers needs to
2020 * be
2021 * announced to an EBGP peer (and they have the same attributes barring
2022 * their nexthop).
2023 */
2024 if (reflect)
2025 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2026
2027#define NEXTHOP_IS_V6 \
2028 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2029 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2030 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2031 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2032
2033 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2034 * if
2035 * the peer (group) is configured to receive link-local nexthop
2036 * unchanged
c728d027
DA
2037 * and it is available in the prefix OR we're not reflecting the route,
2038 * link-local nexthop address is valid and
d62a17ae 2039 * the peer (group) to whom we're going to announce is on a shared
2040 * network
2041 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2042 * By checking if nexthop LL address is valid we are sure that
2043 * we do not announce LL address as `::`.
d62a17ae 2044 */
2045 if (NEXTHOP_IS_V6) {
2046 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2047 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2048 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2049 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2050 || (!reflect
2051 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2052 && peer->shared_network
d62a17ae 2053 && (from == bgp->peer_self
2054 || peer->sort == BGP_PEER_EBGP))) {
2055 attr->mp_nexthop_len =
2056 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2057 }
3f9c7369 2058
d62a17ae 2059 /* Clear off link-local nexthop in source, whenever it is not
2060 * needed to
2061 * ensure more prefixes share the same attribute for
2062 * announcement.
2063 */
2064 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2065 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2066 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2067 }
3f9c7369 2068
d62a17ae 2069 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2070 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2071
2072 /* Route map & unsuppress-map apply. */
7f7940e6 2073 if (!skip_rmap_check
e73c112e 2074 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2075 struct bgp_path_info rmap_path = {0};
2076 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2077 struct attr dummy_attr = {0};
d62a17ae 2078
e34291b8 2079 /* Fill temp path_info */
9bcb3eef
DS
2080 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2081 pi, peer, attr);
16f7ce2b 2082
d62a17ae 2083 /* don't confuse inbound and outbound setting */
2084 RESET_FLAG(attr->rmap_change_flags);
2085
2086 /*
2087 * The route reflector is not allowed to modify the attributes
2088 * of the reflected IBGP routes unless explicitly allowed.
2089 */
2090 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2091 && !CHECK_FLAG(bgp->flags,
2092 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2093 dummy_attr = *attr;
40381db7 2094 rmap_path.attr = &dummy_attr;
d62a17ae 2095 }
3f9c7369 2096
d62a17ae 2097 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2098
4056a5f6 2099 if (bgp_path_suppressed(pi))
d62a17ae 2100 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2101 &rmap_path);
d62a17ae 2102 else
2103 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2104 &rmap_path);
d62a17ae 2105
2106 peer->rmap_type = 0;
2107
2108 if (ret == RMAP_DENYMATCH) {
778048bf 2109 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2110 zlog_debug(
2111 "%s [Update:SEND] %pFX is filtered by route-map",
2112 peer->host, p);
778048bf 2113
d62a17ae 2114 bgp_attr_flush(attr);
3dc339cd 2115 return false;
d62a17ae 2116 }
3f9c7369 2117 }
3f9c7369 2118
9dac9fc8
DA
2119 /* RFC 8212 to prevent route leaks.
2120 * This specification intends to improve this situation by requiring the
2121 * explicit configuration of both BGP Import and Export Policies for any
2122 * External BGP (EBGP) session such as customers, peers, or
2123 * confederation boundaries for all enabled address families. Through
2124 * codification of the aforementioned requirement, operators will
2125 * benefit from consistent behavior across different BGP
2126 * implementations.
2127 */
1d3fdccf 2128 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2129 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2130 return false;
9dac9fc8 2131
fb29348a
DA
2132 /* draft-ietf-idr-deprecate-as-set-confed-set
2133 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2134 * Eventually, This document (if approved) updates RFC 4271
2135 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2136 * and obsoletes RFC 6472.
2137 */
7f972cd8 2138 if (peer->bgp->reject_as_sets)
fb29348a 2139 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2140 return false;
fb29348a 2141
33d022bc
DA
2142 /* Codification of AS 0 Processing */
2143 if (aspath_check_as_zero(attr->aspath))
e2369003 2144 return false;
33d022bc 2145
637e5ba4 2146 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2147 if (peer->sort == BGP_PEER_IBGP
2148 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2149 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2150 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2151 } else {
2152 bgp_attr_add_gshut_community(attr);
2153 }
2154 }
2155
d62a17ae 2156 /* After route-map has been applied, we check to see if the nexthop to
2157 * be carried in the attribute (that is used for the announcement) can
2158 * be cleared off or not. We do this in all cases where we would be
2159 * setting the nexthop to "ourselves". For IPv6, we only need to
2160 * consider
2161 * the global nexthop here; the link-local nexthop would have been
2162 * cleared
2163 * already, and if not, it is required by the update formation code.
2164 * Also see earlier comments in this function.
2165 */
2166 /*
2167 * If route-map has performed some operation on the nexthop or the peer
2168 * configuration says to pass it unchanged, we cannot reset the nexthop
2169 * here, so only attempt to do it if these aren't true. Note that the
2170 * route-map handler itself might have cleared the nexthop, if for
2171 * example,
2172 * it is configured as 'peer-address'.
2173 */
2174 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2175 piattr->rmap_change_flags)
d62a17ae 2176 && !transparent
2177 && !CHECK_FLAG(peer->af_flags[afi][safi],
2178 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2179 /* We can reset the nexthop, if setting (or forcing) it to
2180 * 'self' */
2181 if (CHECK_FLAG(peer->af_flags[afi][safi],
2182 PEER_FLAG_NEXTHOP_SELF)
2183 || CHECK_FLAG(peer->af_flags[afi][safi],
2184 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2185 if (!reflect
2186 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2187 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2188 subgroup_announce_reset_nhop(
2189 (peer_cap_enhe(peer, afi, safi)
2190 ? AF_INET6
2191 : p->family),
2192 attr);
7b651a32 2193 nh_reset = true;
2194 }
d62a17ae 2195 } else if (peer->sort == BGP_PEER_EBGP) {
2196 /* Can also reset the nexthop if announcing to EBGP, but
2197 * only if
2198 * no peer in the subgroup is on a shared subnet.
2199 * Note: 3rd party nexthop currently implemented for
2200 * IPv4 only.
2201 */
737af885
BS
2202 if ((p->family == AF_INET) &&
2203 (!bgp_subgrp_multiaccess_check_v4(
2204 piattr->nexthop,
7b651a32 2205 subgrp, from))) {
d62a17ae 2206 subgroup_announce_reset_nhop(
2207 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2208 ? AF_INET6
2209 : p->family),
737af885 2210 attr);
7b651a32 2211 nh_reset = true;
2212 }
737af885
BS
2213
2214 if ((p->family == AF_INET6) &&
2215 (!bgp_subgrp_multiaccess_check_v6(
2216 piattr->mp_nexthop_global,
7b651a32 2217 subgrp, from))) {
737af885
BS
2218 subgroup_announce_reset_nhop(
2219 (peer_cap_enhe(peer, afi, safi)
2220 ? AF_INET6
2221 : p->family),
2222 attr);
7b651a32 2223 nh_reset = true;
2224 }
737af885
BS
2225
2226
2227
40381db7 2228 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2229 /*
2230 * This flag is used for leaked vpn-vrf routes
2231 */
2232 int family = p->family;
2233
2234 if (peer_cap_enhe(peer, afi, safi))
2235 family = AF_INET6;
2236
2237 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2238 zlog_debug(
1defdda8 2239 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2240 __func__, family2str(family));
2241 subgroup_announce_reset_nhop(family, attr);
7b651a32 2242 nh_reset = true;
d62a17ae 2243 }
63696f1d 2244 }
960035b2 2245
63696f1d 2246 /* If IPv6/MP and nexthop does not have any override and happens
2247 * to
2248 * be a link-local address, reset it so that we don't pass along
2249 * the
2250 * source's link-local IPv6 address to recipients who may not be
2251 * on
2252 * the same interface.
2253 */
2254 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2255 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2256 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2257 nh_reset = true;
2258 }
d62a17ae 2259 }
3f9c7369 2260
7b651a32 2261 /*
2262 * When the next hop is set to ourselves, if all multipaths have
2263 * link-bandwidth announce the cumulative bandwidth as that makes
2264 * the most sense. However, don't modify if the link-bandwidth has
2265 * been explicitly set by user policy.
2266 */
2267 if (nh_reset &&
f7e1c681 2268 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2269 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2270 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2271 attr->ecommunity = ecommunity_replace_linkbw(
2272 bgp->as, attr->ecommunity, cum_bw);
2273
3dc339cd 2274 return true;
3f9c7369
DS
2275}
2276
f009ff26 2277static int bgp_route_select_timer_expire(struct thread *thread)
2278{
2279 struct afi_safi_info *info;
2280 afi_t afi;
2281 safi_t safi;
2282 struct bgp *bgp;
2283
2284 info = THREAD_ARG(thread);
2285 afi = info->afi;
2286 safi = info->safi;
2287 bgp = info->bgp;
2288
2289 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2290 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2291 safi);
f009ff26 2292
2293 bgp->gr_info[afi][safi].t_route_select = NULL;
2294
2295 XFREE(MTYPE_TMP, info);
2296
2297 /* Best path selection */
2298 return bgp_best_path_select_defer(bgp, afi, safi);
2299}
2300
9bcb3eef 2301void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2302 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2303 struct bgp_path_info_pair *result, afi_t afi,
2304 safi_t safi)
2305{
2306 struct bgp_path_info *new_select;
2307 struct bgp_path_info *old_select;
40381db7
DS
2308 struct bgp_path_info *pi;
2309 struct bgp_path_info *pi1;
2310 struct bgp_path_info *pi2;
2311 struct bgp_path_info *nextpi = NULL;
d62a17ae 2312 int paths_eq, do_mpath, debug;
2313 struct list mp_list;
2314 char pfx_buf[PREFIX2STR_BUFFER];
2315 char path_buf[PATH_ADDPATH_STR_BUFFER];
2316
2317 bgp_mp_list_init(&mp_list);
2318 do_mpath =
2319 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2320
9bcb3eef 2321 debug = bgp_debug_bestpath(dest);
d62a17ae 2322
2323 if (debug)
9bcb3eef 2324 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2325
9bcb3eef 2326 dest->reason = bgp_path_selection_none;
d62a17ae 2327 /* bgp deterministic-med */
2328 new_select = NULL;
892fedb6 2329 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2330
1defdda8 2331 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2332 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2333 pi1 = pi1->next)
9bcb3eef 2334 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2335 BGP_PATH_DMED_SELECTED);
d62a17ae 2336
9bcb3eef 2337 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2338 pi1 = pi1->next) {
40381db7 2339 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2340 continue;
40381db7 2341 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2342 continue;
ea8b2282 2343 if (pi1->peer != bgp->peer_self)
40381db7 2344 if (pi1->peer->status != Established)
d62a17ae 2345 continue;
2346
40381db7
DS
2347 new_select = pi1;
2348 if (pi1->next) {
2349 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2350 if (CHECK_FLAG(pi2->flags,
1defdda8 2351 BGP_PATH_DMED_CHECK))
d62a17ae 2352 continue;
40381db7 2353 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2354 continue;
ea8b2282 2355 if (pi2->peer != bgp->peer_self
d62a17ae 2356 && !CHECK_FLAG(
ea8b2282
DS
2357 pi2->peer->sflags,
2358 PEER_STATUS_NSF_WAIT))
40381db7 2359 if (pi2->peer->status
d62a17ae 2360 != Established)
2361 continue;
2362
121e245d
DS
2363 if (!aspath_cmp_left(pi1->attr->aspath,
2364 pi2->attr->aspath)
2365 && !aspath_cmp_left_confed(
40381db7 2366 pi1->attr->aspath,
121e245d
DS
2367 pi2->attr->aspath))
2368 continue;
d62a17ae 2369
121e245d
DS
2370 if (bgp_path_info_cmp(
2371 bgp, pi2, new_select,
2372 &paths_eq, mpath_cfg, debug,
fdf81fa0 2373 pfx_buf, afi, safi,
9bcb3eef 2374 &dest->reason)) {
121e245d 2375 bgp_path_info_unset_flag(
9bcb3eef 2376 dest, new_select,
121e245d
DS
2377 BGP_PATH_DMED_SELECTED);
2378 new_select = pi2;
d62a17ae 2379 }
121e245d
DS
2380
2381 bgp_path_info_set_flag(
9bcb3eef 2382 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2383 }
2384 }
9bcb3eef 2385 bgp_path_info_set_flag(dest, new_select,
18ee8310 2386 BGP_PATH_DMED_CHECK);
9bcb3eef 2387 bgp_path_info_set_flag(dest, new_select,
18ee8310 2388 BGP_PATH_DMED_SELECTED);
d62a17ae 2389
2390 if (debug) {
18ee8310 2391 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2392 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2393 zlog_debug(
2394 "%pBD: %s is the bestpath from AS %u",
2395 dest, path_buf,
2396 aspath_get_first_as(
2397 new_select->attr->aspath));
d62a17ae 2398 }
2399 }
2400 }
96450faf 2401
d62a17ae 2402 /* Check old selected route and new selected route. */
2403 old_select = NULL;
2404 new_select = NULL;
9bcb3eef 2405 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2406 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2407 enum bgp_path_selection_reason reason;
2408
40381db7
DS
2409 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2410 old_select = pi;
d62a17ae 2411
40381db7 2412 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2413 /* reap REMOVED routes, if needs be
2414 * selected route must stay for a while longer though
2415 */
40381db7
DS
2416 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2417 && (pi != old_select))
9bcb3eef 2418 bgp_path_info_reap(dest, pi);
d62a17ae 2419
ddb5b488 2420 if (debug)
40381db7
DS
2421 zlog_debug("%s: pi %p in holddown", __func__,
2422 pi);
ddb5b488 2423
d62a17ae 2424 continue;
2425 }
96450faf 2426
40381db7
DS
2427 if (pi->peer && pi->peer != bgp->peer_self
2428 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2429 if (pi->peer->status != Established) {
ddb5b488
PZ
2430
2431 if (debug)
2432 zlog_debug(
40381db7
DS
2433 "%s: pi %p non self peer %s not estab state",
2434 __func__, pi, pi->peer->host);
ddb5b488 2435
d62a17ae 2436 continue;
ddb5b488 2437 }
9fbdd100 2438
892fedb6 2439 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2440 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2441 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2442 if (debug)
40381db7 2443 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2444 continue;
2445 }
9fbdd100 2446
9bcb3eef 2447 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2448
9bcb3eef 2449 reason = dest->reason;
40381db7 2450 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2451 debug, pfx_buf, afi, safi,
2452 &dest->reason)) {
19ea4cec
DS
2453 if (new_select == NULL &&
2454 reason != bgp_path_selection_none)
9bcb3eef 2455 dest->reason = reason;
40381db7 2456 new_select = pi;
d62a17ae 2457 }
2458 }
718e3744 2459
d62a17ae 2460 /* Now that we know which path is the bestpath see if any of the other
2461 * paths
2462 * qualify as multipaths
2463 */
2464 if (debug) {
2465 if (new_select)
7533cad7
QY
2466 bgp_path_info_path_with_addpath_rx_str(
2467 new_select, path_buf, sizeof(path_buf));
d62a17ae 2468 else
772270f3 2469 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2470 zlog_debug(
8228a9a7
DS
2471 "%pBD: After path selection, newbest is %s oldbest was %s",
2472 dest, path_buf,
d62a17ae 2473 old_select ? old_select->peer->host : "NONE");
96450faf 2474 }
9fbdd100 2475
d62a17ae 2476 if (do_mpath && new_select) {
9bcb3eef 2477 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2478 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2479
2480 if (debug)
18ee8310 2481 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2482 pi, path_buf, sizeof(path_buf));
d62a17ae 2483
40381db7 2484 if (pi == new_select) {
d62a17ae 2485 if (debug)
2486 zlog_debug(
8228a9a7
DS
2487 "%pBD: %s is the bestpath, add to the multipath list",
2488 dest, path_buf);
40381db7 2489 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2490 continue;
2491 }
2492
40381db7 2493 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2494 continue;
2495
40381db7
DS
2496 if (pi->peer && pi->peer != bgp->peer_self
2497 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2498 PEER_STATUS_NSF_WAIT))
40381db7 2499 if (pi->peer->status != Established)
d62a17ae 2500 continue;
2501
40381db7 2502 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2503 if (debug)
2504 zlog_debug(
8228a9a7
DS
2505 "%pBD: %s has the same nexthop as the bestpath, skip it",
2506 dest, path_buf);
d62a17ae 2507 continue;
2508 }
2509
40381db7 2510 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2511 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2512 &dest->reason);
d62a17ae 2513
2514 if (paths_eq) {
2515 if (debug)
2516 zlog_debug(
8228a9a7
DS
2517 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2518 dest, path_buf);
40381db7 2519 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2520 }
2521 }
2522 }
fee0f4c6 2523
9bcb3eef 2524 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2525 mpath_cfg);
2526 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2527 bgp_mp_list_clear(&mp_list);
96450faf 2528
9bcb3eef 2529 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2530
d62a17ae 2531 result->old = old_select;
2532 result->new = new_select;
96450faf 2533
d62a17ae 2534 return;
fee0f4c6 2535}
2536
3f9c7369
DS
2537/*
2538 * A new route/change in bestpath of an existing route. Evaluate the path
2539 * for advertisement to the subgroup.
2540 */
3dc339cd
DA
2541void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2542 struct bgp_path_info *selected,
9bcb3eef 2543 struct bgp_dest *dest,
3dc339cd 2544 uint32_t addpath_tx_id)
d62a17ae 2545{
b54892e0 2546 const struct prefix *p;
d62a17ae 2547 struct peer *onlypeer;
2548 struct attr attr;
2549 afi_t afi;
2550 safi_t safi;
a77e2f4b
S
2551 struct bgp *bgp;
2552 bool advertise;
adbac85e 2553
9bcb3eef 2554 p = bgp_dest_get_prefix(dest);
d62a17ae 2555 afi = SUBGRP_AFI(subgrp);
2556 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2557 bgp = SUBGRP_INST(subgrp);
d62a17ae 2558 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2559 : NULL);
2560
2dbe669b
DA
2561 if (BGP_DEBUG(update, UPDATE_OUT))
2562 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2563
d62a17ae 2564 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2565 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2566 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2567 return;
d62a17ae 2568
2569 memset(&attr, 0, sizeof(struct attr));
2570 /* It's initialized in bgp_announce_check() */
2571
a77e2f4b
S
2572 /* Announcement to the subgroup. If the route is filtered withdraw it.
2573 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2574 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2575 * route
d62a17ae 2576 */
a77e2f4b
S
2577 advertise = bgp_check_advertise(bgp, dest);
2578
d62a17ae 2579 if (selected) {
7f7940e6 2580 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2581 false)) {
2582 /* Route is selected, if the route is already installed
2583 * in FIB, then it is advertised
2584 */
2585 if (advertise)
2586 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2587 selected);
2588 } else
9bcb3eef 2589 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2590 addpath_tx_id);
d62a17ae 2591 }
2592
2593 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2594 else {
9bcb3eef 2595 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2596 }
200df115 2597}
fee0f4c6 2598
3064bf43 2599/*
e1072051 2600 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2601 * This is called at the end of route processing.
3064bf43 2602 */
9bcb3eef 2603void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2604{
40381db7 2605 struct bgp_path_info *pi;
3064bf43 2606
9bcb3eef 2607 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2608 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2609 continue;
40381db7
DS
2610 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2611 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2612 }
3064bf43 2613}
2614
2615/*
2616 * Has the route changed from the RIB's perspective? This is invoked only
2617 * if the route selection returns the same best route as earlier - to
2618 * determine if we need to update zebra or not.
2619 */
9bcb3eef 2620bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2621{
4b7e6066 2622 struct bgp_path_info *mpinfo;
d62a17ae 2623
2bb9eff4
DS
2624 /* If this is multipath, check all selected paths for any nexthop
2625 * change or attribute change. Some attribute changes (e.g., community)
2626 * aren't of relevance to the RIB, but we'll update zebra to ensure
2627 * we handle the case of BGP nexthop change. This is the behavior
2628 * when the best path has an attribute change anyway.
d62a17ae 2629 */
1defdda8 2630 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2631 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2632 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2633 return true;
d62a17ae 2634
2bb9eff4
DS
2635 /*
2636 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2637 */
18ee8310
DS
2638 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2639 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2640 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2641 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2642 return true;
d62a17ae 2643 }
3064bf43 2644
d62a17ae 2645 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2646 return false;
3064bf43 2647}
2648
d62a17ae 2649struct bgp_process_queue {
2650 struct bgp *bgp;
9bcb3eef 2651 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2652#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2653 unsigned int flags;
2654 unsigned int queued;
200df115 2655};
2656
3b0c17e1 2657static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2658 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2659 struct bgp_path_info *new_select,
2660 struct bgp_path_info *old_select)
2661{
9bcb3eef 2662 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2663
2664 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2665 return;
2666
2667 if (advertise_type5_routes(bgp, afi) && new_select
2668 && is_route_injectable_into_evpn(new_select)) {
2669
2670 /* apply the route-map */
2671 if (bgp->adv_cmd_rmap[afi][safi].map) {
2672 route_map_result_t ret;
2673 struct bgp_path_info rmap_path;
2674 struct bgp_path_info_extra rmap_path_extra;
2675 struct attr dummy_attr;
2676
2677 dummy_attr = *new_select->attr;
2678
2679 /* Fill temp path_info */
9bcb3eef 2680 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2681 new_select, new_select->peer,
2682 &dummy_attr);
2683
2684 RESET_FLAG(dummy_attr.rmap_change_flags);
2685
2686 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2687 p, &rmap_path);
3b0c17e1 2688
2689 if (ret == RMAP_DENYMATCH) {
2690 bgp_attr_flush(&dummy_attr);
2691 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2692 safi);
2693 } else
2694 bgp_evpn_advertise_type5_route(
2695 bgp, p, &dummy_attr, afi, safi);
2696 } else {
2697 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2698 afi, safi);
2699 }
2700 } else if (advertise_type5_routes(bgp, afi) && old_select
2701 && is_route_injectable_into_evpn(old_select))
2702 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2703}
2704
3103e8d2
DS
2705/*
2706 * old_select = The old best path
2707 * new_select = the new best path
2708 *
2709 * if (!old_select && new_select)
2710 * We are sending new information on.
2711 *
2712 * if (old_select && new_select) {
2713 * if (new_select != old_select)
2714 * We have a new best path send a change
2715 * else
2716 * We've received a update with new attributes that needs
2717 * to be passed on.
2718 * }
2719 *
2720 * if (old_select && !new_select)
2721 * We have no eligible route that we can announce or the rn
2722 * is being removed.
2723 */
9bcb3eef 2724static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2725 afi_t afi, safi_t safi)
d62a17ae 2726{
4b7e6066
DS
2727 struct bgp_path_info *new_select;
2728 struct bgp_path_info *old_select;
2729 struct bgp_path_info_pair old_and_new;
ddb5b488 2730 int debug = 0;
d62a17ae 2731
892fedb6 2732 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2733 if (dest)
2734 debug = bgp_debug_bestpath(dest);
b54892e0 2735 if (debug)
f4c713ae 2736 zlog_debug(
56ca3b5b 2737 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2738 __func__, dest);
f4c713ae
LB
2739 return;
2740 }
d62a17ae 2741 /* Is it end of initial update? (after startup) */
9bcb3eef 2742 if (!dest) {
d62a17ae 2743 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2744 sizeof(bgp->update_delay_zebra_resume_time));
2745
2746 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2747 FOREACH_AFI_SAFI (afi, safi) {
2748 if (bgp_fibupd_safi(safi))
2749 bgp_zebra_announce_table(bgp, afi, safi);
2750 }
d62a17ae 2751 bgp->main_peers_update_hold = 0;
2752
2753 bgp_start_routeadv(bgp);
aac24838 2754 return;
d62a17ae 2755 }
cb1faec9 2756
9bcb3eef 2757 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2758
9bcb3eef 2759 debug = bgp_debug_bestpath(dest);
b54892e0 2760 if (debug)
56ca3b5b 2761 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2762 afi2str(afi), safi2str(safi));
ddb5b488 2763
f009ff26 2764 /* The best path calculation for the route is deferred if
2765 * BGP_NODE_SELECT_DEFER is set
2766 */
9bcb3eef 2767 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2768 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2769 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2770 return;
2771 }
2772
d62a17ae 2773 /* Best path selection. */
9bcb3eef 2774 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2775 afi, safi);
2776 old_select = old_and_new.old;
2777 new_select = old_and_new.new;
2778
2779 /* Do we need to allocate or free labels?
2780 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2781 * necessary to do this upon changes to best path. Exceptions:
2782 * - label index has changed -> recalculate resulting label
2783 * - path_info sub_type changed -> switch to/from implicit-null
2784 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2785 */
318cac96 2786 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2787 if (new_select) {
2788 if (!old_select
2789 || bgp_label_index_differs(new_select, old_select)
57592a53 2790 || new_select->sub_type != old_select->sub_type
9bcb3eef 2791 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2792 /* Enforced penultimate hop popping:
2793 * implicit-null for local routes, aggregate
2794 * and redistributed routes
2795 */
d62a17ae 2796 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2797 || new_select->sub_type
2798 == BGP_ROUTE_AGGREGATE
2799 || new_select->sub_type
2800 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2801 if (CHECK_FLAG(
9bcb3eef 2802 dest->flags,
992dd67e
PR
2803 BGP_NODE_REGISTERED_FOR_LABEL)
2804 || CHECK_FLAG(
2805 dest->flags,
2806 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2807 bgp_unregister_for_label(dest);
70e98a7f 2808 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2809 &dest->local_label);
2810 bgp_set_valid_label(&dest->local_label);
d62a17ae 2811 } else
9bcb3eef
DS
2812 bgp_register_for_label(dest,
2813 new_select);
d62a17ae 2814 }
9bcb3eef 2815 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2816 BGP_NODE_REGISTERED_FOR_LABEL)
2817 || CHECK_FLAG(dest->flags,
2818 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2819 bgp_unregister_for_label(dest);
318cac96 2820 }
992dd67e
PR
2821 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2822 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2823 bgp_unregister_for_label(dest);
d62a17ae 2824 }
cd1964ff 2825
b54892e0 2826 if (debug)
ddb5b488 2827 zlog_debug(
56ca3b5b 2828 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2829 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2830 old_select, new_select);
ddb5b488 2831
d62a17ae 2832 /* If best route remains the same and this is not due to user-initiated
2833 * clear, see exactly what needs to be done.
2834 */
d62a17ae 2835 if (old_select && old_select == new_select
9bcb3eef 2836 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2837 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2838 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2839 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2840#ifdef ENABLE_BGP_VNC
d62a17ae 2841 vnc_import_bgp_add_route(bgp, p, old_select);
2842 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2843#endif
bb744275 2844 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2845 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2846
2847 if (new_select->type == ZEBRA_ROUTE_BGP
2848 && (new_select->sub_type == BGP_ROUTE_NORMAL
2849 || new_select->sub_type
2850 == BGP_ROUTE_IMPORTED))
2851
9bcb3eef 2852 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2853 bgp, afi, safi);
2854 }
d62a17ae 2855 }
d62a17ae 2856
2857 /* If there is a change of interest to peers, reannounce the
2858 * route. */
1defdda8 2859 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2860 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2861 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2862 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2863
2864 /* unicast routes must also be annouced to
2865 * labeled-unicast update-groups */
2866 if (safi == SAFI_UNICAST)
2867 group_announce_route(bgp, afi,
9bcb3eef 2868 SAFI_LABELED_UNICAST, dest,
d62a17ae 2869 new_select);
2870
1defdda8 2871 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2872 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2873 }
fee0f4c6 2874
3b0c17e1 2875 /* advertise/withdraw type-5 routes */
2876 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2877 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2878 bgp_process_evpn_route_injection(
9bcb3eef 2879 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2880
b1875e65 2881 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2882 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2883 bgp_zebra_clear_route_change_flags(dest);
2884 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2885 return;
d62a17ae 2886 }
8ad7271d 2887
d62a17ae 2888 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2889 */
9bcb3eef 2890 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2891
2892 /* bestpath has changed; bump version */
2893 if (old_select || new_select) {
9bcb3eef 2894 bgp_bump_version(dest);
d62a17ae 2895
2896 if (!bgp->t_rmap_def_originate_eval) {
2897 bgp_lock(bgp);
2898 thread_add_timer(
2899 bm->master,
2900 update_group_refresh_default_originate_route_map,
2901 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2902 &bgp->t_rmap_def_originate_eval);
2903 }
2904 }
3f9c7369 2905
d62a17ae 2906 if (old_select)
9bcb3eef 2907 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2908 if (new_select) {
ddb5b488
PZ
2909 if (debug)
2910 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2911 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2912 bgp_path_info_unset_flag(dest, new_select,
2913 BGP_PATH_ATTR_CHANGED);
1defdda8 2914 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2915 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2916 }
338b3424 2917
49e5a4a0 2918#ifdef ENABLE_BGP_VNC
d62a17ae 2919 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2920 if (old_select != new_select) {
2921 if (old_select) {
2922 vnc_import_bgp_exterior_del_route(bgp, p,
2923 old_select);
2924 vnc_import_bgp_del_route(bgp, p, old_select);
2925 }
2926 if (new_select) {
2927 vnc_import_bgp_exterior_add_route(bgp, p,
2928 new_select);
2929 vnc_import_bgp_add_route(bgp, p, new_select);
2930 }
2931 }
2932 }
65efcfce
LB
2933#endif
2934
9bcb3eef 2935 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2936
2937 /* unicast routes must also be annouced to labeled-unicast update-groups
2938 */
2939 if (safi == SAFI_UNICAST)
9bcb3eef 2940 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2941 new_select);
2942
2943 /* FIB update. */
2944 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2945 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2946 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2947 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2948 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2949 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2950
2951 /* if this is an evpn imported type-5 prefix,
2952 * we need to withdraw the route first to clear
2953 * the nh neigh and the RMAC entry.
2954 */
2955 if (old_select &&
2956 is_route_parent_evpn(old_select))
2957 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2958
9bcb3eef 2959 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2960 } else {
d62a17ae 2961 /* Withdraw the route from the kernel. */
2962 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2963 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2964 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2965 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2966
568e10ca 2967 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2968 }
718e3744 2969 }
3064bf43 2970
9bcb3eef 2971 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2972 old_select);
5424b7ba 2973
d62a17ae 2974 /* Clear any route change flags. */
9bcb3eef 2975 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2976
18ee8310 2977 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2978 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2979 bgp_path_info_reap(dest, old_select);
d62a17ae 2980
9bcb3eef 2981 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2982 return;
718e3744 2983}
2984
f009ff26 2985/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2986int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2987{
9bcb3eef 2988 struct bgp_dest *dest;
f009ff26 2989 int cnt = 0;
2990 struct afi_safi_info *thread_info;
f009ff26 2991
56c226e7
DS
2992 if (bgp->gr_info[afi][safi].t_route_select) {
2993 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2994
2995 thread_info = THREAD_ARG(t);
2996 XFREE(MTYPE_TMP, thread_info);
f009ff26 2997 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2998 }
f009ff26 2999
3000 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3001 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3002 get_afi_safi_str(afi, safi, false),
26742171 3003 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3004 }
3005
3006 /* Process the route list */
6338d242
DS
3007 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3008 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3009 dest = bgp_route_next(dest)) {
3010 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3011 continue;
3012
3013 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3014 bgp->gr_info[afi][safi].gr_deferred--;
3015 bgp_process_main_one(bgp, dest, afi, safi);
3016 cnt++;
3017 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3018 bgp_dest_unlock_node(dest);
3019 break;
f009ff26 3020 }
f009ff26 3021 }
3022
9e3b51a7 3023 /* Send EOR message when all routes are processed */
6338d242 3024 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3025 bgp_send_delayed_eor(bgp);
8c48b3b6 3026 /* Send route processing complete message to RIB */
3027 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3028 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3029 return 0;
9e3b51a7 3030 }
f009ff26 3031
3032 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3033
3034 thread_info->afi = afi;
3035 thread_info->safi = safi;
3036 thread_info->bgp = bgp;
3037
3038 /* If there are more routes to be processed, start the
3039 * selection timer
3040 */
3041 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3042 BGP_ROUTE_SELECT_DELAY,
3043 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3044 return 0;
3045}
3046
aac24838 3047static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3048{
aac24838
JB
3049 struct bgp_process_queue *pqnode = data;
3050 struct bgp *bgp = pqnode->bgp;
d62a17ae 3051 struct bgp_table *table;
9bcb3eef 3052 struct bgp_dest *dest;
aac24838
JB
3053
3054 /* eoiu marker */
3055 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3056 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3057 /* should always have dedicated wq call */
3058 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3059 return WQ_SUCCESS;
3060 }
3061
ac021f40 3062 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3063 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3064 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3065 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3066 table = bgp_dest_table(dest);
3067 /* note, new DESTs may be added as part of processing */
3068 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3069
9bcb3eef 3070 bgp_dest_unlock_node(dest);
d62a17ae 3071 bgp_table_unlock(table);
3072 }
aac24838
JB
3073
3074 return WQ_SUCCESS;
3075}
3076
3077static void bgp_processq_del(struct work_queue *wq, void *data)
3078{
3079 struct bgp_process_queue *pqnode = data;
3080
3081 bgp_unlock(pqnode->bgp);
3082
3083 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3084}
3085
b6c386bb 3086void bgp_process_queue_init(struct bgp *bgp)
200df115 3087{
b6c386bb
DS
3088 if (!bgp->process_queue) {
3089 char name[BUFSIZ];
3090
3091 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3092 bgp->process_queue = work_queue_new(bm->master, name);
3093 }
3094
3095 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3096 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3097 bgp->process_queue->spec.max_retries = 0;
3098 bgp->process_queue->spec.hold = 50;
d62a17ae 3099 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3100 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3101}
3102
cfe8d15a 3103static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3104{
3105 struct bgp_process_queue *pqnode;
3106
a4d82a8a
PZ
3107 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3108 sizeof(struct bgp_process_queue));
aac24838
JB
3109
3110 /* unlocked in bgp_processq_del */
3111 pqnode->bgp = bgp_lock(bgp);
3112 STAILQ_INIT(&pqnode->pqueue);
3113
aac24838
JB
3114 return pqnode;
3115}
3116
9bcb3eef 3117void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3118{
aac24838 3119#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3120 struct work_queue *wq = bgp->process_queue;
d62a17ae 3121 struct bgp_process_queue *pqnode;
cfe8d15a 3122 int pqnode_reuse = 0;
495f0b13 3123
d62a17ae 3124 /* already scheduled for processing? */
9bcb3eef 3125 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3126 return;
2e02b9b2 3127
f009ff26 3128 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3129 * the workqueue
3130 */
9bcb3eef 3131 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3132 if (BGP_DEBUG(update, UPDATE_OUT))
3133 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3134 dest);
f009ff26 3135 return;
3136 }
3137
aac24838 3138 if (wq == NULL)
d62a17ae 3139 return;
3140
aac24838 3141 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3142 limit only if is from the same BGP view and it's not an EOIU marker
3143 */
aac24838
JB
3144 if (work_queue_item_count(wq)) {
3145 struct work_queue_item *item = work_queue_last_item(wq);
3146 pqnode = item->data;
228da428 3147
a4d82a8a
PZ
3148 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3149 || pqnode->bgp != bgp
3150 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3151 pqnode = bgp_processq_alloc(bgp);
3152 else
3153 pqnode_reuse = 1;
aac24838 3154 } else
cfe8d15a 3155 pqnode = bgp_processq_alloc(bgp);
aac24838 3156 /* all unlocked in bgp_process_wq */
9bcb3eef 3157 bgp_table_lock(bgp_dest_table(dest));
aac24838 3158
9bcb3eef
DS
3159 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3160 bgp_dest_lock_node(dest);
aac24838 3161
60466a63 3162 /* can't be enqueued twice */
9bcb3eef
DS
3163 assert(STAILQ_NEXT(dest, pq) == NULL);
3164 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3165 pqnode->queued++;
3166
cfe8d15a
LB
3167 if (!pqnode_reuse)
3168 work_queue_add(wq, pqnode);
3169
d62a17ae 3170 return;
fee0f4c6 3171}
0a486e5f 3172
d62a17ae 3173void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3174{
d62a17ae 3175 struct bgp_process_queue *pqnode;
cb1faec9 3176
b6c386bb 3177 if (bgp->process_queue == NULL)
d62a17ae 3178 return;
2e02b9b2 3179
cfe8d15a 3180 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3181
aac24838 3182 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3183 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3184}
3185
d62a17ae 3186static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3187{
d62a17ae 3188 struct peer *peer;
0a486e5f 3189
d62a17ae 3190 peer = THREAD_ARG(thread);
3191 peer->t_pmax_restart = NULL;
0a486e5f 3192
d62a17ae 3193 if (bgp_debug_neighbor_events(peer))
3194 zlog_debug(
3195 "%s Maximum-prefix restart timer expired, restore peering",
3196 peer->host);
0a486e5f 3197
a9bafa95 3198 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3199 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3200
d62a17ae 3201 return 0;
0a486e5f 3202}
3203
9cbd06e0
DA
3204static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3205 safi_t safi)
3206{
3207 uint32_t count = 0;
f41b0459 3208 bool filtered = false;
9cbd06e0
DA
3209 struct bgp_dest *dest;
3210 struct bgp_adj_in *ain;
40bb2ccf 3211 struct attr attr = {};
9cbd06e0
DA
3212 struct bgp_table *table = peer->bgp->rib[afi][safi];
3213
3214 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3215 for (ain = dest->adj_in; ain; ain = ain->next) {
3216 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3217
3218 attr = *ain->attr;
9cbd06e0
DA
3219
3220 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3221 == FILTER_DENY)
f41b0459
DA
3222 filtered = true;
3223
3224 if (bgp_input_modifier(
3225 peer, rn_p, &attr, afi, safi,
3226 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3227 NULL, 0, NULL)
3228 == RMAP_DENY)
3229 filtered = true;
3230
3231 if (filtered)
9cbd06e0 3232 count++;
f41b0459
DA
3233
3234 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3235 }
3236 }
3237
3238 return count;
3239}
3240
3dc339cd
DA
3241bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3242 int always)
718e3744 3243{
d62a17ae 3244 iana_afi_t pkt_afi;
5c525538 3245 iana_safi_t pkt_safi;
9cbd06e0
DA
3246 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3247 PEER_FLAG_MAX_PREFIX_FORCE))
3248 ? bgp_filtered_routes_count(peer, afi, safi)
3249 + peer->pcount[afi][safi]
3250 : peer->pcount[afi][safi];
9cabb64b 3251
d62a17ae 3252 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3253 return false;
e0701b79 3254
9cbd06e0 3255 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3256 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3257 PEER_STATUS_PREFIX_LIMIT)
3258 && !always)
3dc339cd 3259 return false;
e0701b79 3260
d62a17ae 3261 zlog_info(
6cde4b45 3262 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3263 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3264 peer->pmax[afi][safi]);
d62a17ae 3265 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3266
3267 if (CHECK_FLAG(peer->af_flags[afi][safi],
3268 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3269 return false;
d62a17ae 3270
3271 /* Convert AFI, SAFI to values for packet. */
3272 pkt_afi = afi_int2iana(afi);
3273 pkt_safi = safi_int2iana(safi);
3274 {
d7c0a89a 3275 uint8_t ndata[7];
d62a17ae 3276
3277 ndata[0] = (pkt_afi >> 8);
3278 ndata[1] = pkt_afi;
3279 ndata[2] = pkt_safi;
3280 ndata[3] = (peer->pmax[afi][safi] >> 24);
3281 ndata[4] = (peer->pmax[afi][safi] >> 16);
3282 ndata[5] = (peer->pmax[afi][safi] >> 8);
3283 ndata[6] = (peer->pmax[afi][safi]);
3284
3285 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3286 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3287 BGP_NOTIFY_CEASE_MAX_PREFIX,
3288 ndata, 7);
3289 }
3290
3291 /* Dynamic peers will just close their connection. */
3292 if (peer_dynamic_neighbor(peer))
3dc339cd 3293 return true;
d62a17ae 3294
3295 /* restart timer start */
3296 if (peer->pmax_restart[afi][safi]) {
3297 peer->v_pmax_restart =
3298 peer->pmax_restart[afi][safi] * 60;
3299
3300 if (bgp_debug_neighbor_events(peer))
3301 zlog_debug(
3302 "%s Maximum-prefix restart timer started for %d secs",
3303 peer->host, peer->v_pmax_restart);
3304
3305 BGP_TIMER_ON(peer->t_pmax_restart,
3306 bgp_maximum_prefix_restart_timer,
3307 peer->v_pmax_restart);
3308 }
3309
3dc339cd 3310 return true;
d62a17ae 3311 } else
3312 UNSET_FLAG(peer->af_sflags[afi][safi],
3313 PEER_STATUS_PREFIX_LIMIT);
3314
b1823b69
DS
3315 if (pcount
3316 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3317 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3318 PEER_STATUS_PREFIX_THRESHOLD)
3319 && !always)
3dc339cd 3320 return false;
d62a17ae 3321
3322 zlog_info(
6cde4b45 3323 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3324 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3325 peer->pmax[afi][safi]);
d62a17ae 3326 SET_FLAG(peer->af_sflags[afi][safi],
3327 PEER_STATUS_PREFIX_THRESHOLD);
3328 } else
3329 UNSET_FLAG(peer->af_sflags[afi][safi],
3330 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3331 return false;
718e3744 3332}
3333
b40d939b 3334/* Unconditionally remove the route from the RIB, without taking
3335 * damping into consideration (eg, because the session went down)
3336 */
9bcb3eef 3337void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3338 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3339{
f009ff26 3340
3341 struct bgp *bgp = NULL;
3342 bool delete_route = false;
3343
9bcb3eef
DS
3344 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3345 safi);
d62a17ae 3346
f009ff26 3347 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3348 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3349
f009ff26 3350 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3351 * flag
3352 */
3353 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3354 delete_route = true;
9bcb3eef 3355 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3356 delete_route = true;
f009ff26 3357 if (delete_route) {
9bcb3eef
DS
3358 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3359 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3360 bgp = pi->peer->bgp;
26742171 3361 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3362 }
3363 }
3364 }
4a11bf2c 3365
9bcb3eef
DS
3366 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3367 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3368}
3369
9bcb3eef 3370static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3371 struct peer *peer, afi_t afi, safi_t safi,
3372 struct prefix_rd *prd)
3373{
9bcb3eef 3374 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3375
d62a17ae 3376 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3377 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3378 */
40ec3340
DS
3379 if (peer->sort == BGP_PEER_EBGP) {
3380 if (get_active_bdc_from_pi(pi, afi, safi)) {
3381 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3382 == BGP_DAMP_SUPPRESSED) {
3383 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3384 safi);
3385 return;
3386 }
d62a17ae 3387 }
40ec3340 3388 }
d62a17ae 3389
49e5a4a0 3390#ifdef ENABLE_BGP_VNC
d62a17ae 3391 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3392 struct bgp_dest *pdest = NULL;
d62a17ae 3393 struct bgp_table *table = NULL;
3394
9bcb3eef
DS
3395 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3396 (struct prefix *)prd);
3397 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3398 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3399
3400 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3401 peer->bgp, prd, table, p, pi);
d62a17ae 3402 }
9bcb3eef 3403 bgp_dest_unlock_node(pdest);
d62a17ae 3404 }
3405 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3406 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3407
b54892e0
DS
3408 vnc_import_bgp_del_route(peer->bgp, p, pi);
3409 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3410 }
65efcfce 3411 }
d62a17ae 3412#endif
128ea8ab 3413
d62a17ae 3414 /* If this is an EVPN route, process for un-import. */
3415 if (safi == SAFI_EVPN)
b54892e0 3416 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3417
9bcb3eef 3418 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3419}
3420
4b7e6066
DS
3421struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3422 struct peer *peer, struct attr *attr,
9bcb3eef 3423 struct bgp_dest *dest)
fb018d25 3424{
4b7e6066 3425 struct bgp_path_info *new;
fb018d25 3426
d62a17ae 3427 /* Make new BGP info. */
4b7e6066 3428 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3429 new->type = type;
3430 new->instance = instance;
3431 new->sub_type = sub_type;
3432 new->peer = peer;
3433 new->attr = attr;
3434 new->uptime = bgp_clock();
9bcb3eef 3435 new->net = dest;
d62a17ae 3436 return new;
fb018d25
DS
3437}
3438
d62a17ae 3439static void overlay_index_update(struct attr *attr,
d62a17ae 3440 union gw_addr *gw_ip)
684a7227 3441{
d62a17ae 3442 if (!attr)
3443 return;
d62a17ae 3444 if (gw_ip == NULL) {
6c924775
DS
3445 struct bgp_route_evpn eo;
3446
3447 memset(&eo, 0, sizeof(eo));
3448 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3449 } else {
6c924775
DS
3450 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3451
3452 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3453 }
684a7227
PG
3454}
3455
40381db7 3456static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3457 union gw_addr *gw_ip)
3458{
6c924775
DS
3459 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3460 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3461 union {
0a50c248 3462 esi_t esi;
11ebf4ed
DS
3463 union gw_addr ip;
3464 } temp;
d62a17ae 3465
3466 if (afi != AFI_L2VPN)
3467 return true;
11ebf4ed 3468
6c924775 3469 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3470
3471 if (gw_ip == NULL) {
3472 memset(&temp, 0, sizeof(temp));
40381db7 3473 path_gw_ip_remote = &temp.ip;
11ebf4ed 3474 } else
40381db7 3475 path_gw_ip_remote = gw_ip;
11ebf4ed 3476
6c924775 3477 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3478}
3479
c265ee22 3480/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3481bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3482 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3483 struct bgp_dest *dest)
d62a17ae 3484{
2dbe3fa9 3485 bool ret = false;
b099a5c8
DA
3486 bool is_bgp_static_route =
3487 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3488 : false;
d62a17ae 3489
e8442016
DS
3490 /*
3491 * Only validated for unicast and multicast currently.
3492 * Also valid for EVPN where the nexthop is an IP address.
3493 * If we are a bgp static route being checked then there is
3494 * no need to check to see if the nexthop is martian as
3495 * that it should be ok.
3496 */
3497 if (is_bgp_static_route ||
3498 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3499 return false;
d62a17ae 3500
3501 /* If NEXT_HOP is present, validate it. */
3502 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3503 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3504 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3505 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3506 return true;
d62a17ae 3507 }
c265ee22 3508
d62a17ae 3509 /* If MP_NEXTHOP is present, validate it. */
3510 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3511 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3512 * it is not an IPv6 link-local address.
0355b41d
DA
3513 *
3514 * If we receive an UPDATE with nexthop length set to 32 bytes
3515 * we shouldn't discard an UPDATE if it's set to (::).
3516 * The link-local (2st) is validated along the code path later.
d62a17ae 3517 */
3518 if (attr->mp_nexthop_len) {
3519 switch (attr->mp_nexthop_len) {
3520 case BGP_ATTR_NHLEN_IPV4:
3521 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3522 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3523 || IPV4_CLASS_DE(
3524 ntohl(attr->mp_nexthop_global_in.s_addr))
3525 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3526 dest));
d62a17ae 3527 break;
3528
3529 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3530 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3531 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3532 &attr->mp_nexthop_global)
d62a17ae 3533 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3534 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3535 &attr->mp_nexthop_global)
3536 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3537 dest));
d62a17ae 3538 break;
0355b41d
DA
3539 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3540 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3541 || IN6_IS_ADDR_MULTICAST(
3542 &attr->mp_nexthop_global)
3543 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3544 dest));
0355b41d 3545 break;
d62a17ae 3546
3547 default:
3dc339cd 3548 ret = true;
d62a17ae 3549 break;
3550 }
3551 }
c265ee22 3552
d62a17ae 3553 return ret;
3554}
3555
aade37d7 3556static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3557{
3558 struct community *old;
3559 struct community *new;
3560 struct community *merge;
aade37d7 3561 struct community *no_export;
2721dd61
DA
3562
3563 old = attr->community;
aade37d7 3564 no_export = community_str2com("no-export");
2721dd61 3565
b4efa101
DA
3566 assert(no_export);
3567
2721dd61 3568 if (old) {
aade37d7 3569 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3570
3571 if (!old->refcnt)
3572 community_free(&old);
3573
3574 new = community_uniq_sort(merge);
3575 community_free(&merge);
3576 } else {
aade37d7 3577 new = community_dup(no_export);
2721dd61
DA
3578 }
3579
aade37d7 3580 community_free(&no_export);
2721dd61
DA
3581
3582 attr->community = new;
3583 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3584}
3585
5a1ae2c2 3586int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3587 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3588 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3589 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3590 struct bgp_route_evpn *evpn)
d62a17ae 3591{
3592 int ret;
3593 int aspath_loop_count = 0;
9bcb3eef 3594 struct bgp_dest *dest;
d62a17ae 3595 struct bgp *bgp;
3596 struct attr new_attr;
3597 struct attr *attr_new;
40381db7 3598 struct bgp_path_info *pi;
4b7e6066
DS
3599 struct bgp_path_info *new;
3600 struct bgp_path_info_extra *extra;
d62a17ae 3601 const char *reason;
3602 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3603 int connected = 0;
3604 int do_loop_check = 1;
3605 int has_valid_label = 0;
7c312383 3606 afi_t nh_afi;
949b0f24 3607 uint8_t pi_type = 0;
3608 uint8_t pi_sub_type = 0;
3609
c7bb4f00 3610 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3611 char pfxprint[PREFIX2STR_BUFFER];
3612
3613 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3614 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3615 afi, safi, attr);
6401252f
QY
3616 }
3617
49e5a4a0 3618#ifdef ENABLE_BGP_VNC
d62a17ae 3619 int vnc_implicit_withdraw = 0;
65efcfce 3620#endif
d62a17ae 3621 int same_attr = 0;
718e3744 3622
d62a17ae 3623 memset(&new_attr, 0, sizeof(struct attr));
3624 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3625 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3626
d62a17ae 3627 bgp = peer->bgp;
9bcb3eef 3628 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3629 /* TODO: Check to see if we can get rid of "is_valid_label" */
3630 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3631 has_valid_label = (num_labels > 0) ? 1 : 0;
3632 else
3633 has_valid_label = bgp_is_valid_label(label);
718e3744 3634
28f66de2
MS
3635 if (has_valid_label)
3636 assert(label != NULL);
3637
d62a17ae 3638 /* When peer's soft reconfiguration enabled. Record input packet in
3639 Adj-RIBs-In. */
3640 if (!soft_reconfig
3641 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3642 && peer != bgp->peer_self)
9bcb3eef 3643 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3644
3645 /* Check previously received route. */
9bcb3eef 3646 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3647 if (pi->peer == peer && pi->type == type
3648 && pi->sub_type == sub_type
3649 && pi->addpath_rx_id == addpath_id)
d62a17ae 3650 break;
3651
3652 /* AS path local-as loop check. */
3653 if (peer->change_local_as) {
c4368918
DW
3654 if (peer->allowas_in[afi][safi])
3655 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3656 else if (!CHECK_FLAG(peer->flags,
3657 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3658 aspath_loop_count = 1;
3659
3660 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3661 > aspath_loop_count) {
b4d46cc9 3662 peer->stat_pfx_aspath_loop++;
9bcb3eef 3663 reason = "as-path contains our own AS A;";
d62a17ae 3664 goto filtered;
3665 }
718e3744 3666 }
718e3744 3667
d62a17ae 3668 /* If the peer is configured for "allowas-in origin" and the last ASN in
3669 * the
3670 * as-path is our ASN then we do not need to call aspath_loop_check
3671 */
3672 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3673 if (aspath_get_last_as(attr->aspath) == bgp->as)
3674 do_loop_check = 0;
3675
3676 /* AS path loop check. */
3677 if (do_loop_check) {
3678 if (aspath_loop_check(attr->aspath, bgp->as)
3679 > peer->allowas_in[afi][safi]
3680 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3681 && aspath_loop_check(attr->aspath, bgp->confed_id)
3682 > peer->allowas_in[afi][safi])) {
b4d46cc9 3683 peer->stat_pfx_aspath_loop++;
d62a17ae 3684 reason = "as-path contains our own AS;";
3685 goto filtered;
3686 }
3687 }
aac9ef6c 3688
d62a17ae 3689 /* Route reflector originator ID check. */
3690 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3691 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3692 peer->stat_pfx_originator_loop++;
d62a17ae 3693 reason = "originator is us;";
3694 goto filtered;
3695 }
718e3744 3696
d62a17ae 3697 /* Route reflector cluster ID check. */
3698 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3699 peer->stat_pfx_cluster_loop++;
d62a17ae 3700 reason = "reflected from the same cluster;";
3701 goto filtered;
3702 }
718e3744 3703
d62a17ae 3704 /* Apply incoming filter. */
3705 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3706 peer->stat_pfx_filter++;
d62a17ae 3707 reason = "filter;";
3708 goto filtered;
3709 }
718e3744 3710
a8b72dc6
DA
3711 /* RFC 8212 to prevent route leaks.
3712 * This specification intends to improve this situation by requiring the
3713 * explicit configuration of both BGP Import and Export Policies for any
3714 * External BGP (EBGP) session such as customers, peers, or
3715 * confederation boundaries for all enabled address families. Through
3716 * codification of the aforementioned requirement, operators will
3717 * benefit from consistent behavior across different BGP
3718 * implementations.
3719 */
1d3fdccf 3720 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3721 if (!bgp_inbound_policy_exists(peer,
3722 &peer->filter[afi][safi])) {
3723 reason = "inbound policy missing";
3724 goto filtered;
3725 }
3726
fb29348a
DA
3727 /* draft-ietf-idr-deprecate-as-set-confed-set
3728 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3729 * Eventually, This document (if approved) updates RFC 4271
3730 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3731 * and obsoletes RFC 6472.
3732 */
7f972cd8 3733 if (peer->bgp->reject_as_sets)
fb29348a
DA
3734 if (aspath_check_as_sets(attr->aspath)) {
3735 reason =
3736 "as-path contains AS_SET or AS_CONFED_SET type;";
3737 goto filtered;
3738 }
3739
6f4f49b2 3740 new_attr = *attr;
d62a17ae 3741
3742 /* Apply incoming route-map.
3743 * NB: new_attr may now contain newly allocated values from route-map
3744 * "set"
3745 * commands, so we need bgp_attr_flush in the error paths, until we
3746 * intern
3747 * the attr (which takes over the memory references) */
9bcb3eef
DS
3748 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3749 num_labels, dest)
3750 == RMAP_DENY) {
b4d46cc9 3751 peer->stat_pfx_filter++;
d62a17ae 3752 reason = "route-map;";
3753 bgp_attr_flush(&new_attr);
3754 goto filtered;
3755 }
718e3744 3756
05864da7 3757 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3758 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3759 /* remove from RIB previous entry */
3760 bgp_zebra_withdraw(p, pi, bgp, safi);
3761 }
3762
7f323236
DW
3763 if (peer->sort == BGP_PEER_EBGP) {
3764
2721dd61
DA
3765 /* rfc7999:
3766 * A BGP speaker receiving an announcement tagged with the
3767 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3768 * NO_EXPORT community as defined in RFC1997, or a
3769 * similar community, to prevent propagation of the
3770 * prefix outside the local AS. The community to prevent
3771 * propagation SHOULD be chosen according to the operator's
3772 * routing policy.
3773 */
3774 if (new_attr.community
3775 && community_include(new_attr.community,
3776 COMMUNITY_BLACKHOLE))
aade37d7 3777 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3778
a4d82a8a
PZ
3779 /* If we receive the graceful-shutdown community from an eBGP
3780 * peer we must lower local-preference */
3781 if (new_attr.community
3782 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3783 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3784 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3785
a4d82a8a
PZ
3786 /* If graceful-shutdown is configured then add the GSHUT
3787 * community to all paths received from eBGP peers */
637e5ba4 3788 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3789 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3790 }
3791
949b0f24 3792 if (pi) {
3793 pi_type = pi->type;
3794 pi_sub_type = pi->sub_type;
3795 }
3796
d62a17ae 3797 /* next hop check. */
a4d82a8a 3798 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3799 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3800 &new_attr, dest)) {
b4d46cc9 3801 peer->stat_pfx_nh_invalid++;
d62a17ae 3802 reason = "martian or self next-hop;";
3803 bgp_attr_flush(&new_attr);
3804 goto filtered;
3805 }
718e3744 3806
5c14a191 3807 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3808 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3809 reason = "self mac;";
3810 goto filtered;
3811 }
3812
1e9be514
QY
3813 /* Update Overlay Index */
3814 if (afi == AFI_L2VPN) {
3815 overlay_index_update(&new_attr,
3816 evpn == NULL ? NULL : &evpn->gw_ip);
3817 }
3818
a1b773e2
DS
3819 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3820 * condition :
3821 * Suppress fib is enabled
3822 * BGP_OPT_NO_FIB is not enabled
3823 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3824 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3825 */
3826 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3827 && (sub_type == BGP_ROUTE_NORMAL)
3828 && (!bgp_option_check(BGP_OPT_NO_FIB))
3829 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3830 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3831
d62a17ae 3832 attr_new = bgp_attr_intern(&new_attr);
3833
9cbd06e0
DA
3834 /* If maximum prefix count is configured and current prefix
3835 * count exeed it.
3836 */
3837 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3838 return -1;
3839
d62a17ae 3840 /* If the update is implicit withdraw. */
40381db7
DS
3841 if (pi) {
3842 pi->uptime = bgp_clock();
3843 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3844
9bcb3eef 3845 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3846
d62a17ae 3847 /* Same attribute comes in. */
40381db7 3848 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3849 && same_attr
d62a17ae 3850 && (!has_valid_label
40381db7 3851 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3852 num_labels * sizeof(mpls_label_t))
d62a17ae 3853 == 0)
3854 && (overlay_index_equal(
0a50c248 3855 afi, pi,
d62a17ae 3856 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3857 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3858 && peer->sort == BGP_PEER_EBGP
40381db7 3859 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3860 if (bgp_debug_update(peer, p, NULL, 1)) {
3861 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3862 afi, safi, prd, p, label,
3863 num_labels, addpath_id ? 1 : 0,
3864 addpath_id, pfx_buf,
3865 sizeof(pfx_buf));
d62a17ae 3866 zlog_debug("%s rcvd %s", peer->host,
3867 pfx_buf);
3868 }
3869
9bcb3eef 3870 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3871 != BGP_DAMP_SUPPRESSED) {
40381db7 3872 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3873 safi);
9bcb3eef 3874 bgp_process(bgp, dest, afi, safi);
d62a17ae 3875 }
3876 } else /* Duplicate - odd */
3877 {
3878 if (bgp_debug_update(peer, p, NULL, 1)) {
3879 if (!peer->rcvd_attr_printed) {
3880 zlog_debug(
3881 "%s rcvd UPDATE w/ attr: %s",
3882 peer->host,
3883 peer->rcvd_attr_str);
3884 peer->rcvd_attr_printed = 1;
3885 }
3886
3887 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3888 afi, safi, prd, p, label,
3889 num_labels, addpath_id ? 1 : 0,
3890 addpath_id, pfx_buf,
3891 sizeof(pfx_buf));
d62a17ae 3892 zlog_debug(
3893 "%s rcvd %s...duplicate ignored",
3894 peer->host, pfx_buf);
3895 }
3896
3897 /* graceful restart STALE flag unset. */
40381db7 3898 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3899 bgp_path_info_unset_flag(
9bcb3eef
DS
3900 dest, pi, BGP_PATH_STALE);
3901 bgp_dest_set_defer_flag(dest, false);
3902 bgp_process(bgp, dest, afi, safi);
d62a17ae 3903 }
3904 }
3905
9bcb3eef 3906 bgp_dest_unlock_node(dest);
d62a17ae 3907 bgp_attr_unintern(&attr_new);
3908
3909 return 0;
3910 }
718e3744 3911
d62a17ae 3912 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3913 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3914 if (bgp_debug_update(peer, p, NULL, 1)) {
3915 bgp_debug_rdpfxpath2str(
a4d82a8a 3916 afi, safi, prd, p, label, num_labels,
d62a17ae 3917 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3918 sizeof(pfx_buf));
3919 zlog_debug(
3920 "%s rcvd %s, flapped quicker than processing",
3921 peer->host, pfx_buf);
3922 }
3923
9bcb3eef 3924 bgp_path_info_restore(dest, pi);
d62a17ae 3925 }
718e3744 3926
d62a17ae 3927 /* Received Logging. */
3928 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3929 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3930 num_labels, addpath_id ? 1 : 0,
3931 addpath_id, pfx_buf,
3932 sizeof(pfx_buf));
d62a17ae 3933 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3934 }
718e3744 3935
d62a17ae 3936 /* graceful restart STALE flag unset. */
f009ff26 3937 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3938 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3939 bgp_dest_set_defer_flag(dest, false);
f009ff26 3940 }
d62a17ae 3941
3942 /* The attribute is changed. */
9bcb3eef 3943 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3944
3945 /* implicit withdraw, decrement aggregate and pcount here.
3946 * only if update is accepted, they'll increment below.
3947 */
40381db7 3948 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3949
3950 /* Update bgp route dampening information. */
40ec3340 3951 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3952 && peer->sort == BGP_PEER_EBGP) {
3953 /* This is implicit withdraw so we should update
40ec3340
DS
3954 * dampening information.
3955 */
40381db7 3956 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3957 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3958 }
49e5a4a0 3959#ifdef ENABLE_BGP_VNC
d62a17ae 3960 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3961 struct bgp_dest *pdest = NULL;
d62a17ae 3962 struct bgp_table *table = NULL;
3963
9bcb3eef
DS
3964 pdest = bgp_node_get(bgp->rib[afi][safi],
3965 (struct prefix *)prd);
3966 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3967 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3968
3969 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3970 bgp, prd, table, p, pi);
d62a17ae 3971 }
9bcb3eef 3972 bgp_dest_unlock_node(pdest);
d62a17ae 3973 }
3974 if ((afi == AFI_IP || afi == AFI_IP6)
3975 && (safi == SAFI_UNICAST)) {
40381db7 3976 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3977 /*
3978 * Implicit withdraw case.
3979 */
3980 ++vnc_implicit_withdraw;
40381db7
DS
3981 vnc_import_bgp_del_route(bgp, p, pi);
3982 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3983 }
3984 }
65efcfce 3985#endif
128ea8ab 3986
d62a17ae 3987 /* Special handling for EVPN update of an existing route. If the
3988 * extended community attribute has changed, we need to
3989 * un-import
3990 * the route using its existing extended community. It will be
3991 * subsequently processed for import with the new extended
3992 * community.
3993 */
6f8c9c11
PR
3994 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3995 && !same_attr) {
40381db7 3996 if ((pi->attr->flag
d62a17ae 3997 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3998 && (attr_new->flag
3999 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4000 int cmp;
4001
40381db7 4002 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4003 attr_new->ecommunity);
4004 if (!cmp) {
4005 if (bgp_debug_update(peer, p, NULL, 1))
4006 zlog_debug(
4007 "Change in EXT-COMM, existing %s new %s",
4008 ecommunity_str(
40381db7 4009 pi->attr->ecommunity),
d62a17ae 4010 ecommunity_str(
4011 attr_new->ecommunity));
6f8c9c11
PR
4012 if (safi == SAFI_EVPN)
4013 bgp_evpn_unimport_route(
4014 bgp, afi, safi, p, pi);
4015 else /* SAFI_MPLS_VPN */
4016 vpn_leak_to_vrf_withdraw(bgp,
4017 pi);
d62a17ae 4018 }
4019 }
4020 }
718e3744 4021
d62a17ae 4022 /* Update to new attribute. */
40381db7
DS
4023 bgp_attr_unintern(&pi->attr);
4024 pi->attr = attr_new;
d62a17ae 4025
4026 /* Update MPLS label */
4027 if (has_valid_label) {
40381db7 4028 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4029 if (extra->label != label) {
4030 memcpy(&extra->label, label,
dbd587da 4031 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4032 extra->num_labels = num_labels;
4033 }
b57ba6d2
MK
4034 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4035 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4036 }
718e3744 4037
e496b420
HS
4038 /* Update SRv6 SID */
4039 if (attr->srv6_l3vpn) {
4040 extra = bgp_path_info_extra_get(pi);
4041 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4042 sid_copy(&extra->sid[0],
4043 &attr->srv6_l3vpn->sid);
4044 extra->num_sids = 1;
4045 }
4046 } else if (attr->srv6_vpn) {
4047 extra = bgp_path_info_extra_get(pi);
4048 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4049 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4050 extra->num_sids = 1;
4051 }
4052 }
4053
49e5a4a0 4054#ifdef ENABLE_BGP_VNC
d62a17ae 4055 if ((afi == AFI_IP || afi == AFI_IP6)
4056 && (safi == SAFI_UNICAST)) {
4057 if (vnc_implicit_withdraw) {
4058 /*
4059 * Add back the route with its new attributes
4060 * (e.g., nexthop).
4061 * The route is still selected, until the route
4062 * selection
4063 * queued by bgp_process actually runs. We have
4064 * to make this
4065 * update to the VNC side immediately to avoid
4066 * racing against
4067 * configuration changes (e.g., route-map
4068 * changes) which
4069 * trigger re-importation of the entire RIB.
4070 */
40381db7
DS
4071 vnc_import_bgp_add_route(bgp, p, pi);
4072 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4073 }
4074 }
65efcfce
LB
4075#endif
4076
d62a17ae 4077 /* Update bgp route dampening information. */
40ec3340 4078 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4079 && peer->sort == BGP_PEER_EBGP) {
4080 /* Now we do normal update dampening. */
9bcb3eef 4081 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4082 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4083 bgp_dest_unlock_node(dest);
d62a17ae 4084 return 0;
4085 }
4086 }
128ea8ab 4087
d62a17ae 4088 /* Nexthop reachability check - for unicast and
4089 * labeled-unicast.. */
7c312383
AD
4090 if (((afi == AFI_IP || afi == AFI_IP6)
4091 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4092 || (safi == SAFI_EVPN &&
4093 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4094 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4095 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4096 && !CHECK_FLAG(peer->flags,
4097 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4098 && !CHECK_FLAG(bgp->flags,
4099 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4100 connected = 1;
4101 else
4102 connected = 0;
4103
960035b2
PZ
4104 struct bgp *bgp_nexthop = bgp;
4105
40381db7
DS
4106 if (pi->extra && pi->extra->bgp_orig)
4107 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4108
7c312383
AD
4109 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4110
4111 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4112 safi, pi, NULL, connected)
a4d82a8a 4113 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4114 bgp_path_info_set_flag(dest, pi,
4115 BGP_PATH_VALID);
d62a17ae 4116 else {
4117 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4118 zlog_debug("%s(%pI4): NH unresolved",
4119 __func__,
4120 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4121 }
9bcb3eef 4122 bgp_path_info_unset_flag(dest, pi,
18ee8310 4123 BGP_PATH_VALID);
d62a17ae 4124 }
4125 } else
9bcb3eef 4126 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4127
49e5a4a0 4128#ifdef ENABLE_BGP_VNC
d62a17ae 4129 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4130 struct bgp_dest *pdest = NULL;
d62a17ae 4131 struct bgp_table *table = NULL;
4132
9bcb3eef
DS
4133 pdest = bgp_node_get(bgp->rib[afi][safi],
4134 (struct prefix *)prd);
4135 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4136 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4137
4138 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4139 bgp, prd, table, p, pi);
d62a17ae 4140 }
9bcb3eef 4141 bgp_dest_unlock_node(pdest);
d62a17ae 4142 }
4143#endif
718e3744 4144
d62a17ae 4145 /* If this is an EVPN route and some attribute has changed,
4146 * process
4147 * route for import. If the extended community has changed, we
4148 * would
4149 * have done the un-import earlier and the import would result
4150 * in the
4151 * route getting injected into appropriate L2 VNIs. If it is
4152 * just
4153 * some other attribute change, the import will result in
4154 * updating
4155 * the attributes for the route in the VNI(s).
4156 */
7c312383
AD
4157 if (safi == SAFI_EVPN && !same_attr &&
4158 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4159 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4160
4161 /* Process change. */
40381db7 4162 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4163
9bcb3eef
DS
4164 bgp_process(bgp, dest, afi, safi);
4165 bgp_dest_unlock_node(dest);
558d1fec 4166
ddb5b488
PZ
4167 if (SAFI_UNICAST == safi
4168 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4169 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4170
40381db7 4171 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4172 }
4173 if ((SAFI_MPLS_VPN == safi)
4174 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4175
40381db7 4176 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4177 }
4178
49e5a4a0 4179#ifdef ENABLE_BGP_VNC
d62a17ae 4180 if (SAFI_MPLS_VPN == safi) {
4181 mpls_label_t label_decoded = decode_label(label);
28070ee3 4182
d62a17ae 4183 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4184 type, sub_type, &label_decoded);
4185 }
4186 if (SAFI_ENCAP == safi) {
4187 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4188 type, sub_type, NULL);
4189 }
28070ee3
PZ
4190#endif
4191
d62a17ae 4192 return 0;
4193 } // End of implicit withdraw
718e3744 4194
d62a17ae 4195 /* Received Logging. */
4196 if (bgp_debug_update(peer, p, NULL, 1)) {
4197 if (!peer->rcvd_attr_printed) {
4198 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4199 peer->rcvd_attr_str);
4200 peer->rcvd_attr_printed = 1;
4201 }
718e3744 4202
a4d82a8a 4203 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4204 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4205 sizeof(pfx_buf));
4206 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4207 }
718e3744 4208
d62a17ae 4209 /* Make new BGP info. */
9bcb3eef 4210 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4211
d62a17ae 4212 /* Update MPLS label */
4213 if (has_valid_label) {
18ee8310 4214 extra = bgp_path_info_extra_get(new);
8ba71050 4215 if (extra->label != label) {
dbd587da
QY
4216 memcpy(&extra->label, label,
4217 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4218 extra->num_labels = num_labels;
4219 }
b57ba6d2
MK
4220 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4221 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4222 }
718e3744 4223
e496b420
HS
4224 /* Update SRv6 SID */
4225 if (safi == SAFI_MPLS_VPN) {
4226 extra = bgp_path_info_extra_get(new);
4227 if (attr->srv6_l3vpn) {
4228 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4229 extra->num_sids = 1;
4230 } else if (attr->srv6_vpn) {
4231 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4232 extra->num_sids = 1;
4233 }
4234 }
4235
d62a17ae 4236 /* Update Overlay Index */
4237 if (afi == AFI_L2VPN) {
4238 overlay_index_update(new->attr,
d62a17ae 4239 evpn == NULL ? NULL : &evpn->gw_ip);
4240 }
4241 /* Nexthop reachability check. */
7c312383
AD
4242 if (((afi == AFI_IP || afi == AFI_IP6)
4243 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4244 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4245 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4246 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4247 && !CHECK_FLAG(peer->flags,
4248 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4249 && !CHECK_FLAG(bgp->flags,
4250 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4251 connected = 1;
4252 else
4253 connected = 0;
4254
7c312383
AD
4255 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4256
4053e952 4257 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4258 connected)
a4d82a8a 4259 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4260 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4261 else {
4262 if (BGP_DEBUG(nht, NHT)) {
4263 char buf1[INET6_ADDRSTRLEN];
4264 inet_ntop(AF_INET,
4265 (const void *)&attr_new->nexthop,
4266 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4267 zlog_debug("%s(%s): NH unresolved", __func__,
4268 buf1);
d62a17ae 4269 }
9bcb3eef 4270 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4271 }
4272 } else
9bcb3eef 4273 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4274
d62a17ae 4275 /* Addpath ID */
4276 new->addpath_rx_id = addpath_id;
4277
4278 /* Increment prefix */
4279 bgp_aggregate_increment(bgp, p, new, afi, safi);
4280
4281 /* Register new BGP information. */
9bcb3eef 4282 bgp_path_info_add(dest, new);
d62a17ae 4283
4284 /* route_node_get lock */
9bcb3eef 4285 bgp_dest_unlock_node(dest);
558d1fec 4286
49e5a4a0 4287#ifdef ENABLE_BGP_VNC
d62a17ae 4288 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4289 struct bgp_dest *pdest = NULL;
d62a17ae 4290 struct bgp_table *table = NULL;
4291
9bcb3eef
DS
4292 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4293 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4294 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4295
4296 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4297 bgp, prd, table, p, new);
4298 }
9bcb3eef 4299 bgp_dest_unlock_node(pdest);
d62a17ae 4300 }
65efcfce
LB
4301#endif
4302
d62a17ae 4303 /* If this is an EVPN route, process for import. */
7c312383 4304 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4305 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4306
9bcb3eef 4307 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4308
d62a17ae 4309 /* Process change. */
9bcb3eef 4310 bgp_process(bgp, dest, afi, safi);
718e3744 4311
ddb5b488
PZ
4312 if (SAFI_UNICAST == safi
4313 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4314 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4315 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4316 }
4317 if ((SAFI_MPLS_VPN == safi)
4318 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4319
4320 vpn_leak_to_vrf_update(bgp, new);
4321 }
49e5a4a0 4322#ifdef ENABLE_BGP_VNC
d62a17ae 4323 if (SAFI_MPLS_VPN == safi) {
4324 mpls_label_t label_decoded = decode_label(label);
28070ee3 4325
d62a17ae 4326 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4327 sub_type, &label_decoded);
4328 }
4329 if (SAFI_ENCAP == safi) {
4330 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4331 sub_type, NULL);
4332 }
28070ee3
PZ
4333#endif
4334
d62a17ae 4335 return 0;
718e3744 4336
d62a17ae 4337/* This BGP update is filtered. Log the reason then update BGP
4338 entry. */
4339filtered:
9bcb3eef 4340 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4341
d62a17ae 4342 if (bgp_debug_update(peer, p, NULL, 1)) {
4343 if (!peer->rcvd_attr_printed) {
4344 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4345 peer->rcvd_attr_str);
4346 peer->rcvd_attr_printed = 1;
4347 }
718e3744 4348
a4d82a8a 4349 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4350 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4351 sizeof(pfx_buf));
4352 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4353 peer->host, pfx_buf, reason);
4354 }
128ea8ab 4355
40381db7 4356 if (pi) {
d62a17ae 4357 /* If this is an EVPN route, un-import it as it is now filtered.
4358 */
4359 if (safi == SAFI_EVPN)
40381db7 4360 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4361
ddb5b488
PZ
4362 if (SAFI_UNICAST == safi
4363 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4364 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4365
40381db7 4366 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4367 }
4368 if ((SAFI_MPLS_VPN == safi)
4369 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4370
40381db7 4371 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4372 }
4373
9bcb3eef 4374 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4375 }
4376
9bcb3eef 4377 bgp_dest_unlock_node(dest);
558d1fec 4378
49e5a4a0 4379#ifdef ENABLE_BGP_VNC
d62a17ae 4380 /*
4381 * Filtered update is treated as an implicit withdrawal (see
4382 * bgp_rib_remove()
4383 * a few lines above)
4384 */
4385 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4386 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4387 0);
4388 }
97736e32
PZ
4389#endif
4390
d62a17ae 4391 return 0;
718e3744 4392}
4393
26a3ffd6 4394int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4395 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4396 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4397 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4398{
d62a17ae 4399 struct bgp *bgp;
4400 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4401 struct bgp_dest *dest;
40381db7 4402 struct bgp_path_info *pi;
718e3744 4403
49e5a4a0 4404#ifdef ENABLE_BGP_VNC
d62a17ae 4405 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4406 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4407 0);
4408 }
28070ee3
PZ
4409#endif
4410
d62a17ae 4411 bgp = peer->bgp;
4412
4413 /* Lookup node. */
9bcb3eef 4414 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4415
4416 /* If peer is soft reconfiguration enabled. Record input packet for
4417 * further calculation.
4418 *
4419 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4420 * routes that are filtered. This tanks out Quagga RS pretty badly due
4421 * to
4422 * the iteration over all RS clients.
4423 * Since we need to remove the entry from adj_in anyway, do that first
4424 * and
4425 * if there was no entry, we don't need to do anything more.
4426 */
4427 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4428 && peer != bgp->peer_self)
9bcb3eef 4429 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4430 peer->stat_pfx_dup_withdraw++;
4431
d62a17ae 4432 if (bgp_debug_update(peer, p, NULL, 1)) {
4433 bgp_debug_rdpfxpath2str(
a4d82a8a 4434 afi, safi, prd, p, label, num_labels,
d62a17ae 4435 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4436 sizeof(pfx_buf));
4437 zlog_debug(
4438 "%s withdrawing route %s not in adj-in",
4439 peer->host, pfx_buf);
4440 }
9bcb3eef 4441 bgp_dest_unlock_node(dest);
d62a17ae 4442 return 0;
4443 }
cd808e74 4444
d62a17ae 4445 /* Lookup withdrawn route. */
9bcb3eef 4446 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4447 if (pi->peer == peer && pi->type == type
4448 && pi->sub_type == sub_type
4449 && pi->addpath_rx_id == addpath_id)
d62a17ae 4450 break;
4451
4452 /* Logging. */
4453 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4454 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4455 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4456 sizeof(pfx_buf));
4457 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4458 pfx_buf);
4459 }
718e3744 4460
d62a17ae 4461 /* Withdraw specified route from routing table. */
40381db7 4462 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4463 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4464 if (SAFI_UNICAST == safi
4465 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4466 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4467 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4468 }
4469 if ((SAFI_MPLS_VPN == safi)
4470 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4471
40381db7 4472 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4473 }
4474 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4475 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4476 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4477 sizeof(pfx_buf));
4478 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4479 }
718e3744 4480
d62a17ae 4481 /* Unlock bgp_node_get() lock. */
9bcb3eef 4482 bgp_dest_unlock_node(dest);
d62a17ae 4483
4484 return 0;
718e3744 4485}
6b0655a2 4486
d62a17ae 4487void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4488 int withdraw)
718e3744 4489{
d62a17ae 4490 struct update_subgroup *subgrp;
4491 subgrp = peer_subgroup(peer, afi, safi);
4492 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4493}
6182d65b 4494
718e3744 4495
3f9c7369
DS
4496/*
4497 * bgp_stop_announce_route_timer
4498 */
d62a17ae 4499void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4500{
d62a17ae 4501 if (!paf->t_announce_route)
4502 return;
4503
50478845 4504 thread_cancel(&paf->t_announce_route);
718e3744 4505}
6b0655a2 4506
3f9c7369
DS
4507/*
4508 * bgp_announce_route_timer_expired
4509 *
4510 * Callback that is invoked when the route announcement timer for a
4511 * peer_af expires.
4512 */
d62a17ae 4513static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4514{
d62a17ae 4515 struct peer_af *paf;
4516 struct peer *peer;
558d1fec 4517
d62a17ae 4518 paf = THREAD_ARG(t);
4519 peer = paf->peer;
718e3744 4520
d62a17ae 4521 if (peer->status != Established)
4522 return 0;
3f9c7369 4523
d62a17ae 4524 if (!peer->afc_nego[paf->afi][paf->safi])
4525 return 0;
3f9c7369 4526
d62a17ae 4527 peer_af_announce_route(paf, 1);
c5aec50b
MK
4528
4529 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4530 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4531
d62a17ae 4532 return 0;
718e3744 4533}
4534
3f9c7369
DS
4535/*
4536 * bgp_announce_route
4537 *
4538 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4539 */
d62a17ae 4540void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4541{
4542 struct peer_af *paf;
4543 struct update_subgroup *subgrp;
4544
4545 paf = peer_af_find(peer, afi, safi);
4546 if (!paf)
4547 return;
4548 subgrp = PAF_SUBGRP(paf);
4549
4550 /*
4551 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4552 * or a refresh has already been triggered.
4553 */
4554 if (!subgrp || paf->t_announce_route)
4555 return;
4556
4557 /*
4558 * Start a timer to stagger/delay the announce. This serves
4559 * two purposes - announcement can potentially be combined for
4560 * multiple peers and the announcement doesn't happen in the
4561 * vty context.
4562 */
4563 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4564 (subgrp->peer_count == 1)
4565 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4566 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4567 &paf->t_announce_route);
3f9c7369
DS
4568}
4569
4570/*
4571 * Announce routes from all AF tables to a peer.
4572 *
4573 * This should ONLY be called when there is a need to refresh the
4574 * routes to the peer based on a policy change for this peer alone
4575 * or a route refresh request received from the peer.
4576 * The operation will result in splitting the peer from its existing
4577 * subgroups and putting it in new subgroups.
4578 */
d62a17ae 4579void bgp_announce_route_all(struct peer *peer)
718e3744 4580{
d62a17ae 4581 afi_t afi;
4582 safi_t safi;
4583
05c7a1cc
QY
4584 FOREACH_AFI_SAFI (afi, safi)
4585 bgp_announce_route(peer, afi, safi);
718e3744 4586}
6b0655a2 4587
d62a17ae 4588static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4589 struct bgp_table *table,
4590 struct prefix_rd *prd)
718e3744 4591{
d62a17ae 4592 int ret;
9bcb3eef 4593 struct bgp_dest *dest;
d62a17ae 4594 struct bgp_adj_in *ain;
718e3744 4595
d62a17ae 4596 if (!table)
4597 table = peer->bgp->rib[afi][safi];
718e3744 4598
9bcb3eef
DS
4599 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4600 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4601 if (ain->peer != peer)
4602 continue;
8692c506 4603
d7d15889 4604 struct bgp_path_info *pi;
d7c0a89a 4605 uint32_t num_labels = 0;
b57ba6d2 4606 mpls_label_t *label_pnt = NULL;
8cb687c2 4607 struct bgp_route_evpn evpn;
b57ba6d2 4608
9bcb3eef 4609 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4610 pi = pi->next)
4611 if (pi->peer == peer)
4612 break;
4613
40381db7
DS
4614 if (pi && pi->extra)
4615 num_labels = pi->extra->num_labels;
b57ba6d2 4616 if (num_labels)
40381db7 4617 label_pnt = &pi->extra->label[0];
8cb687c2 4618 if (pi)
6c924775
DS
4619 memcpy(&evpn,
4620 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4621 sizeof(evpn));
4622 else
4623 memset(&evpn, 0, sizeof(evpn));
8692c506 4624
9bcb3eef
DS
4625 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4626 ain->addpath_rx_id, ain->attr, afi,
4627 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4628 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4629 num_labels, 1, &evpn);
ea47320b
DL
4630
4631 if (ret < 0) {
9bcb3eef 4632 bgp_dest_unlock_node(dest);
ea47320b 4633 return;
d62a17ae 4634 }
4635 }
718e3744 4636}
4637
d62a17ae 4638void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4639{
9bcb3eef 4640 struct bgp_dest *dest;
d62a17ae 4641 struct bgp_table *table;
718e3744 4642
d62a17ae 4643 if (peer->status != Established)
4644 return;
718e3744 4645
d62a17ae 4646 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4647 && (safi != SAFI_EVPN))
4648 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4649 else
9bcb3eef
DS
4650 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4651 dest = bgp_route_next(dest)) {
4652 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4653
b54892e0
DS
4654 if (table == NULL)
4655 continue;
8692c506 4656
9bcb3eef 4657 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4658 struct prefix_rd prd;
4659
4660 prd.family = AF_UNSPEC;
4661 prd.prefixlen = 64;
4662 memcpy(&prd.val, p->u.val, 8);
4663
4664 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4665 }
718e3744 4666}
6b0655a2 4667
228da428 4668
d62a17ae 4669struct bgp_clear_node_queue {
9bcb3eef 4670 struct bgp_dest *dest;
228da428
CC
4671};
4672
d62a17ae 4673static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4674{
d62a17ae 4675 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4676 struct bgp_dest *dest = cnq->dest;
d62a17ae 4677 struct peer *peer = wq->spec.data;
40381db7 4678 struct bgp_path_info *pi;
3103e8d2 4679 struct bgp *bgp;
9bcb3eef
DS
4680 afi_t afi = bgp_dest_table(dest)->afi;
4681 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4682
9bcb3eef 4683 assert(dest && peer);
3103e8d2 4684 bgp = peer->bgp;
d62a17ae 4685
4686 /* It is possible that we have multiple paths for a prefix from a peer
4687 * if that peer is using AddPath.
4688 */
9bcb3eef 4689 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4690 if (pi->peer != peer)
ea47320b
DL
4691 continue;
4692
4693 /* graceful restart STALE flag set. */
9af52ccf
DA
4694 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4695 && peer->nsf[afi][safi])
4696 || CHECK_FLAG(peer->af_sflags[afi][safi],
4697 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4698 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4699 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4700 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4701 else {
4702 /* If this is an EVPN route, process for
4703 * un-import. */
4704 if (safi == SAFI_EVPN)
9bcb3eef
DS
4705 bgp_evpn_unimport_route(
4706 bgp, afi, safi,
4707 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4708 /* Handle withdraw for VRF route-leaking and L3VPN */
4709 if (SAFI_UNICAST == safi
4710 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4711 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4712 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4713 bgp, pi);
960035b2 4714 }
3103e8d2 4715 if (SAFI_MPLS_VPN == safi &&
960035b2 4716 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4717 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4718 }
3103e8d2 4719
9bcb3eef 4720 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4721 }
ea47320b 4722 }
d62a17ae 4723 return WQ_SUCCESS;
200df115 4724}
4725
d62a17ae 4726static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4727{
d62a17ae 4728 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4729 struct bgp_dest *dest = cnq->dest;
4730 struct bgp_table *table = bgp_dest_table(dest);
228da428 4731
9bcb3eef 4732 bgp_dest_unlock_node(dest);
d62a17ae 4733 bgp_table_unlock(table);
4734 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4735}
4736
d62a17ae 4737static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4738{
d62a17ae 4739 struct peer *peer = wq->spec.data;
64e580a7 4740
d62a17ae 4741 /* Tickle FSM to start moving again */
4742 BGP_EVENT_ADD(peer, Clearing_Completed);
4743
4744 peer_unlock(peer); /* bgp_clear_route */
200df115 4745}
718e3744 4746
d62a17ae 4747static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4748{
d62a17ae 4749 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4750
4751 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4752#undef CLEAR_QUEUE_NAME_LEN
4753
0ce1ca80 4754 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4755 peer->clear_node_queue->spec.hold = 10;
4756 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4757 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4758 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4759 peer->clear_node_queue->spec.max_retries = 0;
4760
4761 /* we only 'lock' this peer reference when the queue is actually active
4762 */
4763 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4764}
4765
d62a17ae 4766static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4767 struct bgp_table *table)
65ca75e0 4768{
9bcb3eef 4769 struct bgp_dest *dest;
b6c386bb 4770 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4771
d62a17ae 4772 if (!table)
4773 table = peer->bgp->rib[afi][safi];
dc83d712 4774
d62a17ae 4775 /* If still no table => afi/safi isn't configured at all or smth. */
4776 if (!table)
4777 return;
dc83d712 4778
9bcb3eef 4779 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4780 struct bgp_path_info *pi, *next;
d62a17ae 4781 struct bgp_adj_in *ain;
4782 struct bgp_adj_in *ain_next;
4783
4784 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4785 * queued for every clearing peer, regardless of whether it is
4786 * relevant to the peer at hand.
4787 *
4788 * Overview: There are 3 different indices which need to be
4789 * scrubbed, potentially, when a peer is removed:
4790 *
4791 * 1 peer's routes visible via the RIB (ie accepted routes)
4792 * 2 peer's routes visible by the (optional) peer's adj-in index
4793 * 3 other routes visible by the peer's adj-out index
4794 *
4795 * 3 there is no hurry in scrubbing, once the struct peer is
4796 * removed from bgp->peer, we could just GC such deleted peer's
4797 * adj-outs at our leisure.
4798 *
4799 * 1 and 2 must be 'scrubbed' in some way, at least made
4800 * invisible via RIB index before peer session is allowed to be
4801 * brought back up. So one needs to know when such a 'search' is
4802 * complete.
4803 *
4804 * Ideally:
4805 *
4806 * - there'd be a single global queue or a single RIB walker
4807 * - rather than tracking which route_nodes still need to be
4808 * examined on a peer basis, we'd track which peers still
4809 * aren't cleared
4810 *
4811 * Given that our per-peer prefix-counts now should be reliable,
4812 * this may actually be achievable. It doesn't seem to be a huge
4813 * problem at this time,
4814 *
4815 * It is possible that we have multiple paths for a prefix from
4816 * a peer
4817 * if that peer is using AddPath.
4818 */
9bcb3eef 4819 ain = dest->adj_in;
d62a17ae 4820 while (ain) {
4821 ain_next = ain->next;
4822
4823 if (ain->peer == peer) {
9bcb3eef
DS
4824 bgp_adj_in_remove(dest, ain);
4825 bgp_dest_unlock_node(dest);
d62a17ae 4826 }
4827
4828 ain = ain_next;
4829 }
4830
9bcb3eef 4831 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4832 next = pi->next;
4833 if (pi->peer != peer)
d62a17ae 4834 continue;
4835
4836 if (force)
9bcb3eef 4837 bgp_path_info_reap(dest, pi);
d62a17ae 4838 else {
4839 struct bgp_clear_node_queue *cnq;
4840
4841 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4842 bgp_table_lock(bgp_dest_table(dest));
4843 bgp_dest_lock_node(dest);
d62a17ae 4844 cnq = XCALLOC(
4845 MTYPE_BGP_CLEAR_NODE_QUEUE,
4846 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4847 cnq->dest = dest;
d62a17ae 4848 work_queue_add(peer->clear_node_queue, cnq);
4849 break;
4850 }
4851 }
4852 }
4853 return;
4854}
4855
4856void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4857{
9bcb3eef 4858 struct bgp_dest *dest;
d62a17ae 4859 struct bgp_table *table;
4860
4861 if (peer->clear_node_queue == NULL)
4862 bgp_clear_node_queue_init(peer);
4863
4864 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4865 * Idle until it receives a Clearing_Completed event. This protects
4866 * against peers which flap faster than we can we clear, which could
4867 * lead to:
4868 *
4869 * a) race with routes from the new session being installed before
4870 * clear_route_node visits the node (to delete the route of that
4871 * peer)
4872 * b) resource exhaustion, clear_route_node likely leads to an entry
4873 * on the process_main queue. Fast-flapping could cause that queue
4874 * to grow and grow.
4875 */
4876
4877 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4878 * the unlock will happen upon work-queue completion; other wise, the
4879 * unlock happens at the end of this function.
4880 */
4881 if (!peer->clear_node_queue->thread)
4882 peer_lock(peer);
4883
4884 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4885 bgp_clear_route_table(peer, afi, safi, NULL);
4886 else
9bcb3eef
DS
4887 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4888 dest = bgp_route_next(dest)) {
4889 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4890 if (!table)
4891 continue;
4892
4893 bgp_clear_route_table(peer, afi, safi, table);
4894 }
d62a17ae 4895
4896 /* unlock if no nodes got added to the clear-node-queue. */
4897 if (!peer->clear_node_queue->thread)
4898 peer_unlock(peer);
718e3744 4899}
d62a17ae 4900
4901void bgp_clear_route_all(struct peer *peer)
718e3744 4902{
d62a17ae 4903 afi_t afi;
4904 safi_t safi;
718e3744 4905
05c7a1cc
QY
4906 FOREACH_AFI_SAFI (afi, safi)
4907 bgp_clear_route(peer, afi, safi);
65efcfce 4908
49e5a4a0 4909#ifdef ENABLE_BGP_VNC
d62a17ae 4910 rfapiProcessPeerDown(peer);
65efcfce 4911#endif
718e3744 4912}
4913
d62a17ae 4914void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4915{
d62a17ae 4916 struct bgp_table *table;
9bcb3eef 4917 struct bgp_dest *dest;
d62a17ae 4918 struct bgp_adj_in *ain;
4919 struct bgp_adj_in *ain_next;
718e3744 4920
d62a17ae 4921 table = peer->bgp->rib[afi][safi];
718e3744 4922
d62a17ae 4923 /* It is possible that we have multiple paths for a prefix from a peer
4924 * if that peer is using AddPath.
4925 */
9bcb3eef
DS
4926 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4927 ain = dest->adj_in;
43143c8f 4928
d62a17ae 4929 while (ain) {
4930 ain_next = ain->next;
43143c8f 4931
d62a17ae 4932 if (ain->peer == peer) {
9bcb3eef
DS
4933 bgp_adj_in_remove(dest, ain);
4934 bgp_dest_unlock_node(dest);
d62a17ae 4935 }
43143c8f 4936
d62a17ae 4937 ain = ain_next;
4938 }
4939 }
718e3744 4940}
93406d87 4941
d62a17ae 4942void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4943{
9bcb3eef 4944 struct bgp_dest *dest;
40381db7 4945 struct bgp_path_info *pi;
d62a17ae 4946 struct bgp_table *table;
4947
9af52ccf 4948 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4949 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4950 dest = bgp_route_next(dest)) {
4951 struct bgp_dest *rm;
d62a17ae 4952
4953 /* look for neighbor in tables */
9bcb3eef 4954 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4955 if (!table)
ea47320b
DL
4956 continue;
4957
4958 for (rm = bgp_table_top(table); rm;
4959 rm = bgp_route_next(rm))
9bcb3eef 4960 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4961 pi = pi->next) {
40381db7 4962 if (pi->peer != peer)
ea47320b 4963 continue;
40381db7 4964 if (!CHECK_FLAG(pi->flags,
1defdda8 4965 BGP_PATH_STALE))
ea47320b
DL
4966 break;
4967
40381db7 4968 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4969 break;
4970 }
d62a17ae 4971 }
4972 } else {
9bcb3eef
DS
4973 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4974 dest = bgp_route_next(dest))
4975 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4976 pi = pi->next) {
40381db7 4977 if (pi->peer != peer)
ea47320b 4978 continue;
40381db7 4979 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4980 break;
9bcb3eef 4981 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4982 break;
4983 }
d62a17ae 4984 }
93406d87 4985}
6b0655a2 4986
9af52ccf
DA
4987void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4988{
4989 struct bgp_dest *dest, *ndest;
4990 struct bgp_path_info *pi;
4991 struct bgp_table *table;
4992
4993 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4994 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4995 dest = bgp_route_next(dest)) {
4996 table = bgp_dest_get_bgp_table_info(dest);
4997 if (!table)
4998 continue;
4999
5000 for (ndest = bgp_table_top(table); ndest;
5001 ndest = bgp_route_next(ndest)) {
5002 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5003 pi = pi->next) {
5004 if (pi->peer != peer)
5005 continue;
5006
5007 if ((CHECK_FLAG(
5008 peer->af_sflags[afi][safi],
5009 PEER_STATUS_ENHANCED_REFRESH))
5010 && !CHECK_FLAG(pi->flags,
5011 BGP_PATH_STALE)
5012 && !CHECK_FLAG(
5013 pi->flags,
5014 BGP_PATH_UNUSEABLE)) {
5015 if (bgp_debug_neighbor_events(
5016 peer))
5017 zlog_debug(
5018 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5019 peer->host,
5020 afi2str(afi),
5021 safi2str(safi),
5022 bgp_dest_get_prefix(
5023 ndest));
5024
5025 bgp_path_info_set_flag(
5026 ndest, pi,
5027 BGP_PATH_STALE);
5028 }
5029 }
5030 }
5031 }
5032 } else {
5033 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5034 dest = bgp_route_next(dest)) {
5035 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5036 pi = pi->next) {
5037 if (pi->peer != peer)
5038 continue;
5039
5040 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5041 PEER_STATUS_ENHANCED_REFRESH))
5042 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5043 && !CHECK_FLAG(pi->flags,
5044 BGP_PATH_UNUSEABLE)) {
5045 if (bgp_debug_neighbor_events(peer))
5046 zlog_debug(
5047 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5048 peer->host,
5049 afi2str(afi),
5050 safi2str(safi),
5051 bgp_dest_get_prefix(
5052 dest));
5053
5054 bgp_path_info_set_flag(dest, pi,
5055 BGP_PATH_STALE);
5056 }
5057 }
5058 }
5059 }
5060}
5061
3dc339cd 5062bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5063{
e0df4c04 5064 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5065 return true;
e0df4c04 5066
9dac9fc8
DA
5067 if (peer->sort == BGP_PEER_EBGP
5068 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5069 || FILTER_LIST_OUT_NAME(filter)
5070 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5071 return true;
5072 return false;
9dac9fc8
DA
5073}
5074
3dc339cd 5075bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5076{
e0df4c04 5077 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5078 return true;
e0df4c04 5079
9dac9fc8
DA
5080 if (peer->sort == BGP_PEER_EBGP
5081 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5082 || FILTER_LIST_IN_NAME(filter)
5083 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5084 return true;
5085 return false;
9dac9fc8
DA
5086}
5087
568e10ca 5088static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5089 safi_t safi)
bb86c601 5090{
9bcb3eef 5091 struct bgp_dest *dest;
40381db7 5092 struct bgp_path_info *pi;
4b7e6066 5093 struct bgp_path_info *next;
bb86c601 5094
9bcb3eef
DS
5095 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5096 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5097 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5098
40381db7 5099 next = pi->next;
1b7bb747
CS
5100
5101 /* Unimport EVPN routes from VRFs */
5102 if (safi == SAFI_EVPN)
5103 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5104 SAFI_EVPN, p, pi);
1b7bb747 5105
40381db7
DS
5106 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5107 && pi->type == ZEBRA_ROUTE_BGP
5108 && (pi->sub_type == BGP_ROUTE_NORMAL
5109 || pi->sub_type == BGP_ROUTE_AGGREGATE
5110 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5111
d62a17ae 5112 if (bgp_fibupd_safi(safi))
b54892e0 5113 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5114 }
9514b37d 5115
9bcb3eef 5116 bgp_path_info_reap(dest, pi);
d62a17ae 5117 }
bb86c601
LB
5118}
5119
718e3744 5120/* Delete all kernel routes. */
d62a17ae 5121void bgp_cleanup_routes(struct bgp *bgp)
5122{
5123 afi_t afi;
9bcb3eef 5124 struct bgp_dest *dest;
67009e22 5125 struct bgp_table *table;
d62a17ae 5126
5127 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5128 if (afi == AFI_L2VPN)
5129 continue;
568e10ca 5130 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5131 SAFI_UNICAST);
d62a17ae 5132 /*
5133 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5134 */
5135 if (afi != AFI_L2VPN) {
5136 safi_t safi;
5137 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5138 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5139 dest = bgp_route_next(dest)) {
5140 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5141 if (table != NULL) {
5142 bgp_cleanup_table(bgp, table, safi);
5143 bgp_table_finish(&table);
9bcb3eef
DS
5144 bgp_dest_set_bgp_table_info(dest, NULL);
5145 bgp_dest_unlock_node(dest);
d62a17ae 5146 }
5147 }
5148 safi = SAFI_ENCAP;
9bcb3eef
DS
5149 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5150 dest = bgp_route_next(dest)) {
5151 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5152 if (table != NULL) {
5153 bgp_cleanup_table(bgp, table, safi);
5154 bgp_table_finish(&table);
9bcb3eef
DS
5155 bgp_dest_set_bgp_table_info(dest, NULL);
5156 bgp_dest_unlock_node(dest);
d62a17ae 5157 }
5158 }
5159 }
5160 }
9bcb3eef
DS
5161 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5162 dest = bgp_route_next(dest)) {
5163 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5164 if (table != NULL) {
5165 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5166 bgp_table_finish(&table);
9bcb3eef
DS
5167 bgp_dest_set_bgp_table_info(dest, NULL);
5168 bgp_dest_unlock_node(dest);
d62a17ae 5169 }
bb86c601 5170 }
718e3744 5171}
5172
d62a17ae 5173void bgp_reset(void)
718e3744 5174{
d62a17ae 5175 vty_reset();
5176 bgp_zclient_reset();
5177 access_list_reset();
5178 prefix_list_reset();
718e3744 5179}
6b0655a2 5180
d62a17ae 5181static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5182{
d62a17ae 5183 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5184 && CHECK_FLAG(peer->af_cap[afi][safi],
5185 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5186}
5187
718e3744 5188/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5189 value. */
d62a17ae 5190int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5191 struct bgp_nlri *packet)
5192{
d7c0a89a
QY
5193 uint8_t *pnt;
5194 uint8_t *lim;
d62a17ae 5195 struct prefix p;
5196 int psize;
5197 int ret;
5198 afi_t afi;
5199 safi_t safi;
5200 int addpath_encoded;
d7c0a89a 5201 uint32_t addpath_id;
d62a17ae 5202
d62a17ae 5203 pnt = packet->nlri;
5204 lim = pnt + packet->length;
5205 afi = packet->afi;
5206 safi = packet->safi;
5207 addpath_id = 0;
5208 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5209
5210 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5211 syntactic validity. If the field is syntactically incorrect,
5212 then the Error Subcode is set to Invalid Network Field. */
5213 for (; pnt < lim; pnt += psize) {
5214 /* Clear prefix structure. */
5215 memset(&p, 0, sizeof(struct prefix));
5216
5217 if (addpath_encoded) {
5218
5219 /* When packet overflow occurs return immediately. */
761ed665 5220 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5221 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5222
a3a850a1 5223 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5224 addpath_id = ntohl(addpath_id);
d62a17ae 5225 pnt += BGP_ADDPATH_ID_LEN;
5226 }
718e3744 5227
d62a17ae 5228 /* Fetch prefix length. */
5229 p.prefixlen = *pnt++;
5230 /* afi/safi validity already verified by caller,
5231 * bgp_update_receive */
5232 p.family = afi2family(afi);
5233
5234 /* Prefix length check. */
5235 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5236 flog_err(
e50f7cfd 5237 EC_BGP_UPDATE_RCV,
14454c9f 5238 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5239 peer->host, p.prefixlen, packet->afi);
513386b5 5240 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5241 }
6b0655a2 5242
d62a17ae 5243 /* Packet size overflow check. */
5244 psize = PSIZE(p.prefixlen);
5245
5246 /* When packet overflow occur return immediately. */
5247 if (pnt + psize > lim) {
af4c2728 5248 flog_err(
e50f7cfd 5249 EC_BGP_UPDATE_RCV,
d62a17ae 5250 "%s [Error] Update packet error (prefix length %d overflows packet)",
5251 peer->host, p.prefixlen);
513386b5 5252 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5253 }
5254
5255 /* Defensive coding, double-check the psize fits in a struct
5256 * prefix */
5257 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5258 flog_err(
e50f7cfd 5259 EC_BGP_UPDATE_RCV,
d62a17ae 5260 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5261 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5262 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5263 }
5264
5265 /* Fetch prefix from NLRI packet. */
a85297a7 5266 memcpy(p.u.val, pnt, psize);
d62a17ae 5267
5268 /* Check address. */
5269 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5270 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5271 /* From RFC4271 Section 6.3:
5272 *
5273 * If a prefix in the NLRI field is semantically
5274 * incorrect
5275 * (e.g., an unexpected multicast IP address),
5276 * an error SHOULD
5277 * be logged locally, and the prefix SHOULD be
5278 * ignored.
a4d82a8a 5279 */
af4c2728 5280 flog_err(
e50f7cfd 5281 EC_BGP_UPDATE_RCV,
23d0a753
DA
5282 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5283 peer->host, &p.u.prefix4);
d62a17ae 5284 continue;
5285 }
5286 }
5287
5288 /* Check address. */
5289 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5290 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5291 flog_err(
e50f7cfd 5292 EC_BGP_UPDATE_RCV,
c0d72166
DS
5293 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5294 peer->host, &p.u.prefix6);
d62a17ae 5295
5296 continue;
5297 }
5298 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5299 flog_err(
e50f7cfd 5300 EC_BGP_UPDATE_RCV,
c0d72166
DS
5301 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5302 peer->host, &p.u.prefix6);
d62a17ae 5303
5304 continue;
5305 }
5306 }
5307
5308 /* Normal process. */
5309 if (attr)
5310 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5311 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5312 NULL, NULL, 0, 0, NULL);
d62a17ae 5313 else
5314 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5315 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5316 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5317 NULL);
d62a17ae 5318
513386b5
DA
5319 /* Do not send BGP notification twice when maximum-prefix count
5320 * overflow. */
5321 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5322 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5323
5324 /* Address family configuration mismatch. */
d62a17ae 5325 if (ret < 0)
513386b5 5326 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5327 }
5328
5329 /* Packet length consistency check. */
5330 if (pnt != lim) {
af4c2728 5331 flog_err(
e50f7cfd 5332 EC_BGP_UPDATE_RCV,
d62a17ae 5333 "%s [Error] Update packet error (prefix length mismatch with total length)",
5334 peer->host);
513386b5 5335 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5336 }
6b0655a2 5337
513386b5 5338 return BGP_NLRI_PARSE_OK;
718e3744 5339}
5340
d62a17ae 5341static struct bgp_static *bgp_static_new(void)
718e3744 5342{
d62a17ae 5343 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5344}
5345
d62a17ae 5346static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5347{
0a22ddfb 5348 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5349 route_map_counter_decrement(bgp_static->rmap.map);
5350
0a22ddfb 5351 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5352 XFREE(MTYPE_BGP_STATIC, bgp_static);
5353}
5354
5f040085 5355void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5356 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5357{
9bcb3eef 5358 struct bgp_dest *dest;
40381db7 5359 struct bgp_path_info *pi;
4b7e6066 5360 struct bgp_path_info *new;
40381db7 5361 struct bgp_path_info rmap_path;
d62a17ae 5362 struct attr attr;
5363 struct attr *attr_new;
b68885f9 5364 route_map_result_t ret;
49e5a4a0 5365#ifdef ENABLE_BGP_VNC
d62a17ae 5366 int vnc_implicit_withdraw = 0;
65efcfce 5367#endif
fee0f4c6 5368
d62a17ae 5369 assert(bgp_static);
dd8103a9 5370
9bcb3eef 5371 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5372
d62a17ae 5373 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5374
d62a17ae 5375 attr.nexthop = bgp_static->igpnexthop;
5376 attr.med = bgp_static->igpmetric;
5377 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5378
d62a17ae 5379 if (bgp_static->atomic)
5380 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5381
d62a17ae 5382 /* Store label index, if required. */
5383 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5384 attr.label_index = bgp_static->label_index;
5385 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5386 }
718e3744 5387
d62a17ae 5388 /* Apply route-map. */
5389 if (bgp_static->rmap.name) {
5390 struct attr attr_tmp = attr;
80ced710 5391
40381db7
DS
5392 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5393 rmap_path.peer = bgp->peer_self;
5394 rmap_path.attr = &attr_tmp;
fee0f4c6 5395
d62a17ae 5396 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5397
1782514f 5398 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5399
d62a17ae 5400 bgp->peer_self->rmap_type = 0;
718e3744 5401
d62a17ae 5402 if (ret == RMAP_DENYMATCH) {
5403 /* Free uninterned attribute. */
5404 bgp_attr_flush(&attr_tmp);
718e3744 5405
d62a17ae 5406 /* Unintern original. */
5407 aspath_unintern(&attr.aspath);
5408 bgp_static_withdraw(bgp, p, afi, safi);
5409 return;
5410 }
7f323236 5411
637e5ba4 5412 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5413 bgp_attr_add_gshut_community(&attr_tmp);
5414
d62a17ae 5415 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5416 } else {
5417
637e5ba4 5418 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5419 bgp_attr_add_gshut_community(&attr);
5420
d62a17ae 5421 attr_new = bgp_attr_intern(&attr);
7f323236 5422 }
718e3744 5423
9bcb3eef 5424 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5425 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5426 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5427 break;
5428
40381db7
DS
5429 if (pi) {
5430 if (attrhash_cmp(pi->attr, attr_new)
5431 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5432 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5433 bgp_dest_unlock_node(dest);
d62a17ae 5434 bgp_attr_unintern(&attr_new);
5435 aspath_unintern(&attr.aspath);
5436 return;
5437 } else {
5438 /* The attribute is changed. */
9bcb3eef 5439 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5440
5441 /* Rewrite BGP route information. */
40381db7 5442 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5443 bgp_path_info_restore(dest, pi);
d62a17ae 5444 else
40381db7 5445 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5446#ifdef ENABLE_BGP_VNC
d62a17ae 5447 if ((afi == AFI_IP || afi == AFI_IP6)
5448 && (safi == SAFI_UNICAST)) {
40381db7 5449 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5450 /*
5451 * Implicit withdraw case.
40381db7 5452 * We have to do this before pi is
d62a17ae 5453 * changed
5454 */
5455 ++vnc_implicit_withdraw;
40381db7 5456 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5457 vnc_import_bgp_exterior_del_route(
40381db7 5458 bgp, p, pi);
d62a17ae 5459 }
5460 }
65efcfce 5461#endif
40381db7
DS
5462 bgp_attr_unintern(&pi->attr);
5463 pi->attr = attr_new;
5464 pi->uptime = bgp_clock();
49e5a4a0 5465#ifdef ENABLE_BGP_VNC
d62a17ae 5466 if ((afi == AFI_IP || afi == AFI_IP6)
5467 && (safi == SAFI_UNICAST)) {
5468 if (vnc_implicit_withdraw) {
40381db7 5469 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5470 vnc_import_bgp_exterior_add_route(
40381db7 5471 bgp, p, pi);
d62a17ae 5472 }
5473 }
65efcfce 5474#endif
718e3744 5475
d62a17ae 5476 /* Nexthop reachability check. */
892fedb6 5477 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5478 && (safi == SAFI_UNICAST
5479 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5480
5481 struct bgp *bgp_nexthop = bgp;
5482
40381db7
DS
5483 if (pi->extra && pi->extra->bgp_orig)
5484 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5485
5486 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5487 afi, safi, pi, NULL,
5488 0))
9bcb3eef 5489 bgp_path_info_set_flag(dest, pi,
18ee8310 5490 BGP_PATH_VALID);
d62a17ae 5491 else {
5492 if (BGP_DEBUG(nht, NHT)) {
5493 char buf1[INET6_ADDRSTRLEN];
5494 inet_ntop(p->family,
5495 &p->u.prefix, buf1,
5496 INET6_ADDRSTRLEN);
5497 zlog_debug(
5498 "%s(%s): Route not in table, not advertising",
15569c58 5499 __func__, buf1);
d62a17ae 5500 }
18ee8310 5501 bgp_path_info_unset_flag(
9bcb3eef 5502 dest, pi, BGP_PATH_VALID);
d62a17ae 5503 }
5504 } else {
5505 /* Delete the NHT structure if any, if we're
5506 * toggling between
5507 * enabling/disabling import check. We
5508 * deregister the route
5509 * from NHT to avoid overloading NHT and the
5510 * process interaction
5511 */
40381db7 5512 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5513 bgp_path_info_set_flag(dest, pi,
5514 BGP_PATH_VALID);
d62a17ae 5515 }
5516 /* Process change. */
40381db7 5517 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5518 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5519
5520 if (SAFI_UNICAST == safi
5521 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5522 || bgp->inst_type
5523 == BGP_INSTANCE_TYPE_DEFAULT)) {
5524 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5525 pi);
ddb5b488
PZ
5526 }
5527
9bcb3eef 5528 bgp_dest_unlock_node(dest);
d62a17ae 5529 aspath_unintern(&attr.aspath);
5530 return;
5531 }
718e3744 5532 }
718e3744 5533
d62a17ae 5534 /* Make new BGP info. */
5535 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5536 attr_new, dest);
d62a17ae 5537 /* Nexthop reachability check. */
892fedb6 5538 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5539 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5540 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5541 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5542 else {
5543 if (BGP_DEBUG(nht, NHT)) {
5544 char buf1[INET6_ADDRSTRLEN];
5545 inet_ntop(p->family, &p->u.prefix, buf1,
5546 INET6_ADDRSTRLEN);
5547 zlog_debug(
5548 "%s(%s): Route not in table, not advertising",
15569c58 5549 __func__, buf1);
d62a17ae 5550 }
9bcb3eef 5551 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5552 }
5553 } else {
5554 /* Delete the NHT structure if any, if we're toggling between
5555 * enabling/disabling import check. We deregister the route
5556 * from NHT to avoid overloading NHT and the process interaction
5557 */
5558 bgp_unlink_nexthop(new);
5559
9bcb3eef 5560 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5561 }
078430f6 5562
d62a17ae 5563 /* Aggregate address increment. */
5564 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5565
d62a17ae 5566 /* Register new BGP information. */
9bcb3eef 5567 bgp_path_info_add(dest, new);
718e3744 5568
d62a17ae 5569 /* route_node_get lock */
9bcb3eef 5570 bgp_dest_unlock_node(dest);
d62a17ae 5571
5572 /* Process change. */
9bcb3eef 5573 bgp_process(bgp, dest, afi, safi);
d62a17ae 5574
ddb5b488
PZ
5575 if (SAFI_UNICAST == safi
5576 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5577 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5578 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5579 }
5580
d62a17ae 5581 /* Unintern original. */
5582 aspath_unintern(&attr.aspath);
718e3744 5583}
5584
5f040085 5585void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5586 safi_t safi)
718e3744 5587{
9bcb3eef 5588 struct bgp_dest *dest;
40381db7 5589 struct bgp_path_info *pi;
718e3744 5590
9bcb3eef 5591 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5592
d62a17ae 5593 /* Check selected route and self inserted route. */
9bcb3eef 5594 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5595 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5596 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5597 break;
5598
5599 /* Withdraw static BGP route from routing table. */
40381db7 5600 if (pi) {
ddb5b488
PZ
5601 if (SAFI_UNICAST == safi
5602 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5603 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5604 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5605 }
40381db7
DS
5606 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5607 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5608 bgp_path_info_delete(dest, pi);
5609 bgp_process(bgp, dest, afi, safi);
d62a17ae 5610 }
718e3744 5611
d62a17ae 5612 /* Unlock bgp_node_lookup. */
9bcb3eef 5613 bgp_dest_unlock_node(dest);
718e3744 5614}
5615
137446f9
LB
5616/*
5617 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5618 */
5f040085 5619static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5620 afi_t afi, safi_t safi,
5621 struct prefix_rd *prd)
718e3744 5622{
9bcb3eef 5623 struct bgp_dest *dest;
40381db7 5624 struct bgp_path_info *pi;
718e3744 5625
9bcb3eef 5626 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5627
d62a17ae 5628 /* Check selected route and self inserted route. */
9bcb3eef 5629 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5630 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5631 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5632 break;
718e3744 5633
d62a17ae 5634 /* Withdraw static BGP route from routing table. */
40381db7 5635 if (pi) {
49e5a4a0 5636#ifdef ENABLE_BGP_VNC
d62a17ae 5637 rfapiProcessWithdraw(
40381db7 5638 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5639 1); /* Kill, since it is an administrative change */
65efcfce 5640#endif
ddb5b488
PZ
5641 if (SAFI_MPLS_VPN == safi
5642 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5643 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5644 }
40381db7 5645 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5646 bgp_path_info_delete(dest, pi);
5647 bgp_process(bgp, dest, afi, safi);
d62a17ae 5648 }
718e3744 5649
d62a17ae 5650 /* Unlock bgp_node_lookup. */
9bcb3eef 5651 bgp_dest_unlock_node(dest);
718e3744 5652}
5653
5f040085 5654static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5655 struct bgp_static *bgp_static, afi_t afi,
5656 safi_t safi)
137446f9 5657{
9bcb3eef 5658 struct bgp_dest *dest;
4b7e6066 5659 struct bgp_path_info *new;
d62a17ae 5660 struct attr *attr_new;
5661 struct attr attr = {0};
40381db7 5662 struct bgp_path_info *pi;
49e5a4a0 5663#ifdef ENABLE_BGP_VNC
d62a17ae 5664 mpls_label_t label = 0;
65efcfce 5665#endif
d7c0a89a 5666 uint32_t num_labels = 0;
d62a17ae 5667 union gw_addr add;
137446f9 5668
d62a17ae 5669 assert(bgp_static);
137446f9 5670
b57ba6d2
MK
5671 if (bgp_static->label != MPLS_INVALID_LABEL)
5672 num_labels = 1;
9bcb3eef
DS
5673 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5674 &bgp_static->prd);
137446f9 5675
d62a17ae 5676 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5677
d62a17ae 5678 attr.nexthop = bgp_static->igpnexthop;
5679 attr.med = bgp_static->igpmetric;
5680 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5681
d62a17ae 5682 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5683 || (safi == SAFI_ENCAP)) {
5684 if (afi == AFI_IP) {
5685 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5686 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5687 }
5688 }
5689 if (afi == AFI_L2VPN) {
5690 if (bgp_static->gatewayIp.family == AF_INET)
5691 add.ipv4.s_addr =
5692 bgp_static->gatewayIp.u.prefix4.s_addr;
5693 else if (bgp_static->gatewayIp.family == AF_INET6)
5694 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5695 sizeof(struct in6_addr));
0a50c248 5696 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5697 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5698 struct bgp_encap_type_vxlan bet;
5699 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5700 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5701 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5702 }
5703 if (bgp_static->router_mac) {
5704 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5705 }
5706 }
5707 /* Apply route-map. */
5708 if (bgp_static->rmap.name) {
5709 struct attr attr_tmp = attr;
40381db7 5710 struct bgp_path_info rmap_path;
b68885f9 5711 route_map_result_t ret;
137446f9 5712
40381db7
DS
5713 rmap_path.peer = bgp->peer_self;
5714 rmap_path.attr = &attr_tmp;
137446f9 5715
d62a17ae 5716 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5717
1782514f 5718 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5719
d62a17ae 5720 bgp->peer_self->rmap_type = 0;
137446f9 5721
d62a17ae 5722 if (ret == RMAP_DENYMATCH) {
5723 /* Free uninterned attribute. */
5724 bgp_attr_flush(&attr_tmp);
137446f9 5725
d62a17ae 5726 /* Unintern original. */
5727 aspath_unintern(&attr.aspath);
5728 bgp_static_withdraw_safi(bgp, p, afi, safi,
5729 &bgp_static->prd);
5730 return;
5731 }
137446f9 5732
d62a17ae 5733 attr_new = bgp_attr_intern(&attr_tmp);
5734 } else {
5735 attr_new = bgp_attr_intern(&attr);
5736 }
137446f9 5737
9bcb3eef 5738 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5739 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5740 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5741 break;
5742
40381db7 5743 if (pi) {
d62a17ae 5744 memset(&add, 0, sizeof(union gw_addr));
40381db7 5745 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5746 && overlay_index_equal(afi, pi, &add)
40381db7 5747 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5748 bgp_dest_unlock_node(dest);
d62a17ae 5749 bgp_attr_unintern(&attr_new);
5750 aspath_unintern(&attr.aspath);
5751 return;
5752 } else {
5753 /* The attribute is changed. */
9bcb3eef 5754 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5755
5756 /* Rewrite BGP route information. */
40381db7 5757 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5758 bgp_path_info_restore(dest, pi);
d62a17ae 5759 else
40381db7
DS
5760 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5761 bgp_attr_unintern(&pi->attr);
5762 pi->attr = attr_new;
5763 pi->uptime = bgp_clock();
49e5a4a0 5764#ifdef ENABLE_BGP_VNC
40381db7
DS
5765 if (pi->extra)
5766 label = decode_label(&pi->extra->label[0]);
65efcfce 5767#endif
137446f9 5768
d62a17ae 5769 /* Process change. */
40381db7 5770 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5771 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5772
5773 if (SAFI_MPLS_VPN == safi
5774 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5775 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5776 }
49e5a4a0 5777#ifdef ENABLE_BGP_VNC
40381db7
DS
5778 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5779 pi->attr, afi, safi, pi->type,
5780 pi->sub_type, &label);
65efcfce 5781#endif
9bcb3eef 5782 bgp_dest_unlock_node(dest);
d62a17ae 5783 aspath_unintern(&attr.aspath);
5784 return;
5785 }
5786 }
137446f9
LB
5787
5788
d62a17ae 5789 /* Make new BGP info. */
5790 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5791 attr_new, dest);
1defdda8 5792 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5793 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5794 if (num_labels) {
5795 new->extra->label[0] = bgp_static->label;
5796 new->extra->num_labels = num_labels;
5797 }
49e5a4a0 5798#ifdef ENABLE_BGP_VNC
d62a17ae 5799 label = decode_label(&bgp_static->label);
65efcfce 5800#endif
137446f9 5801
d62a17ae 5802 /* Aggregate address increment. */
5803 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5804
d62a17ae 5805 /* Register new BGP information. */
9bcb3eef 5806 bgp_path_info_add(dest, new);
d62a17ae 5807 /* route_node_get lock */
9bcb3eef 5808 bgp_dest_unlock_node(dest);
137446f9 5809
d62a17ae 5810 /* Process change. */
9bcb3eef 5811 bgp_process(bgp, dest, afi, safi);
137446f9 5812
ddb5b488
PZ
5813 if (SAFI_MPLS_VPN == safi
5814 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5815 vpn_leak_to_vrf_update(bgp, new);
5816 }
49e5a4a0 5817#ifdef ENABLE_BGP_VNC
d62a17ae 5818 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5819 safi, new->type, new->sub_type, &label);
65efcfce
LB
5820#endif
5821
d62a17ae 5822 /* Unintern original. */
5823 aspath_unintern(&attr.aspath);
137446f9
LB
5824}
5825
718e3744 5826/* Configure static BGP network. When user don't run zebra, static
5827 route should be installed as valid. */
37a87b8f
CS
5828int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5829 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5830 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5831{
d62a17ae 5832 struct prefix p;
5833 struct bgp_static *bgp_static;
9bcb3eef 5834 struct bgp_dest *dest;
d7c0a89a 5835 uint8_t need_update = 0;
d62a17ae 5836
37a87b8f 5837 prefix_copy(&p, pfx);
d62a17ae 5838 apply_mask(&p);
718e3744 5839
e2a86ad9 5840 if (negate) {
718e3744 5841
e2a86ad9 5842 /* Set BGP static route configuration. */
9bcb3eef 5843 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5844
9bcb3eef 5845 if (!dest) {
37a87b8f
CS
5846 snprintf(errmsg, errmsg_len,
5847 "Can't find static route specified\n");
5848 return -1;
d62a17ae 5849 }
5850
9bcb3eef 5851 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5852
e2a86ad9
DS
5853 if ((label_index != BGP_INVALID_LABEL_INDEX)
5854 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5855 snprintf(errmsg, errmsg_len,
5856 "label-index doesn't match static route\n");
5857 return -1;
d62a17ae 5858 }
d62a17ae 5859
e2a86ad9
DS
5860 if ((rmap && bgp_static->rmap.name)
5861 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5862 snprintf(errmsg, errmsg_len,
5863 "route-map name doesn't match static route\n");
5864 return -1;
d62a17ae 5865 }
718e3744 5866
e2a86ad9
DS
5867 /* Update BGP RIB. */
5868 if (!bgp_static->backdoor)
5869 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5870
e2a86ad9
DS
5871 /* Clear configuration. */
5872 bgp_static_free(bgp_static);
9bcb3eef
DS
5873 bgp_dest_set_bgp_static_info(dest, NULL);
5874 bgp_dest_unlock_node(dest);
5875 bgp_dest_unlock_node(dest);
e2a86ad9 5876 } else {
718e3744 5877
e2a86ad9 5878 /* Set BGP static route configuration. */
9bcb3eef
DS
5879 dest = bgp_node_get(bgp->route[afi][safi], &p);
5880 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5881 if (bgp_static) {
e2a86ad9 5882 /* Configuration change. */
e2a86ad9
DS
5883 /* Label index cannot be changed. */
5884 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5885 snprintf(errmsg, errmsg_len,
5886 "cannot change label-index\n");
5887 return -1;
e2a86ad9 5888 }
d62a17ae 5889
e2a86ad9 5890 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5891 if (bgp_static->valid
5892 && bgp_static->backdoor != backdoor)
e2a86ad9 5893 need_update = 1;
718e3744 5894
e2a86ad9 5895 bgp_static->backdoor = backdoor;
718e3744 5896
e2a86ad9 5897 if (rmap) {
0a22ddfb
QY
5898 XFREE(MTYPE_ROUTE_MAP_NAME,
5899 bgp_static->rmap.name);
b4897fa5 5900 route_map_counter_decrement(
5901 bgp_static->rmap.map);
e2a86ad9
DS
5902 bgp_static->rmap.name =
5903 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5904 bgp_static->rmap.map =
5905 route_map_lookup_by_name(rmap);
b4897fa5 5906 route_map_counter_increment(
5907 bgp_static->rmap.map);
e2a86ad9 5908 } else {
0a22ddfb
QY
5909 XFREE(MTYPE_ROUTE_MAP_NAME,
5910 bgp_static->rmap.name);
b4897fa5 5911 route_map_counter_decrement(
5912 bgp_static->rmap.map);
e2a86ad9
DS
5913 bgp_static->rmap.map = NULL;
5914 bgp_static->valid = 0;
5915 }
9bcb3eef 5916 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5917 } else {
5918 /* New configuration. */
5919 bgp_static = bgp_static_new();
5920 bgp_static->backdoor = backdoor;
5921 bgp_static->valid = 0;
5922 bgp_static->igpmetric = 0;
975a328e 5923 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5924 bgp_static->label_index = label_index;
718e3744 5925
e2a86ad9 5926 if (rmap) {
0a22ddfb
QY
5927 XFREE(MTYPE_ROUTE_MAP_NAME,
5928 bgp_static->rmap.name);
b4897fa5 5929 route_map_counter_decrement(
5930 bgp_static->rmap.map);
e2a86ad9
DS
5931 bgp_static->rmap.name =
5932 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5933 bgp_static->rmap.map =
5934 route_map_lookup_by_name(rmap);
b4897fa5 5935 route_map_counter_increment(
5936 bgp_static->rmap.map);
e2a86ad9 5937 }
9bcb3eef 5938 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5939 }
d62a17ae 5940
e2a86ad9
DS
5941 bgp_static->valid = 1;
5942 if (need_update)
5943 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5944
e2a86ad9
DS
5945 if (!bgp_static->backdoor)
5946 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5947 }
d62a17ae 5948
37a87b8f 5949 return 0;
d62a17ae 5950}
5951
5952void bgp_static_add(struct bgp *bgp)
5953{
5954 afi_t afi;
5955 safi_t safi;
9bcb3eef
DS
5956 struct bgp_dest *dest;
5957 struct bgp_dest *rm;
d62a17ae 5958 struct bgp_table *table;
5959 struct bgp_static *bgp_static;
5960
05c7a1cc 5961 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5962 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5963 dest = bgp_route_next(dest)) {
5964 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5965 continue;
ea47320b 5966
05c7a1cc
QY
5967 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5968 || (safi == SAFI_EVPN)) {
9bcb3eef 5969 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5970
5971 for (rm = bgp_table_top(table); rm;
5972 rm = bgp_route_next(rm)) {
a78beeb5 5973 bgp_static =
9bcb3eef 5974 bgp_dest_get_bgp_static_info(
5a8ba9fc 5975 rm);
9bcb3eef
DS
5976 bgp_static_update_safi(
5977 bgp, bgp_dest_get_prefix(rm),
5978 bgp_static, afi, safi);
d62a17ae 5979 }
05c7a1cc 5980 } else {
5a8ba9fc 5981 bgp_static_update(
9bcb3eef
DS
5982 bgp, bgp_dest_get_prefix(dest),
5983 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5984 safi);
ea47320b 5985 }
05c7a1cc 5986 }
6aeb9e78
DS
5987}
5988
718e3744 5989/* Called from bgp_delete(). Delete all static routes from the BGP
5990 instance. */
d62a17ae 5991void bgp_static_delete(struct bgp *bgp)
5992{
5993 afi_t afi;
5994 safi_t safi;
9bcb3eef
DS
5995 struct bgp_dest *dest;
5996 struct bgp_dest *rm;
d62a17ae 5997 struct bgp_table *table;
5998 struct bgp_static *bgp_static;
5999
05c7a1cc 6000 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6001 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6002 dest = bgp_route_next(dest)) {
6003 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6004 continue;
ea47320b 6005
05c7a1cc
QY
6006 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6007 || (safi == SAFI_EVPN)) {
9bcb3eef 6008 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6009
6010 for (rm = bgp_table_top(table); rm;
6011 rm = bgp_route_next(rm)) {
a78beeb5 6012 bgp_static =
9bcb3eef 6013 bgp_dest_get_bgp_static_info(
5a8ba9fc 6014 rm);
c7d14ba6
PG
6015 if (!bgp_static)
6016 continue;
6017
05c7a1cc 6018 bgp_static_withdraw_safi(
9bcb3eef 6019 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6020 AFI_IP, safi,
6021 (struct prefix_rd *)
9bcb3eef
DS
6022 bgp_dest_get_prefix(
6023 dest));
ea47320b 6024 bgp_static_free(bgp_static);
811c6797 6025 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6026 NULL);
811c6797 6027 bgp_dest_unlock_node(rm);
d62a17ae 6028 }
05c7a1cc 6029 } else {
9bcb3eef 6030 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6031 bgp_static_withdraw(bgp,
9bcb3eef 6032 bgp_dest_get_prefix(dest),
b54892e0 6033 afi, safi);
05c7a1cc 6034 bgp_static_free(bgp_static);
9bcb3eef
DS
6035 bgp_dest_set_bgp_static_info(dest, NULL);
6036 bgp_dest_unlock_node(dest);
ea47320b 6037 }
05c7a1cc 6038 }
d62a17ae 6039}
6040
6041void bgp_static_redo_import_check(struct bgp *bgp)
6042{
6043 afi_t afi;
6044 safi_t safi;
9bcb3eef
DS
6045 struct bgp_dest *dest;
6046 struct bgp_dest *rm;
d62a17ae 6047 struct bgp_table *table;
6048 struct bgp_static *bgp_static;
6049
6050 /* Use this flag to force reprocessing of the route */
892fedb6 6051 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6052 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6053 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6054 dest = bgp_route_next(dest)) {
6055 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6056 continue;
ea47320b 6057
05c7a1cc
QY
6058 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6059 || (safi == SAFI_EVPN)) {
9bcb3eef 6060 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6061
6062 for (rm = bgp_table_top(table); rm;
6063 rm = bgp_route_next(rm)) {
a78beeb5 6064 bgp_static =
9bcb3eef 6065 bgp_dest_get_bgp_static_info(
5a8ba9fc 6066 rm);
9bcb3eef
DS
6067 bgp_static_update_safi(
6068 bgp, bgp_dest_get_prefix(rm),
6069 bgp_static, afi, safi);
d62a17ae 6070 }
05c7a1cc 6071 } else {
9bcb3eef
DS
6072 bgp_static = bgp_dest_get_bgp_static_info(dest);
6073 bgp_static_update(bgp,
6074 bgp_dest_get_prefix(dest),
6075 bgp_static, afi, safi);
ea47320b 6076 }
05c7a1cc
QY
6077 }
6078 }
892fedb6 6079 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6080}
6081
6082static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6083 safi_t safi)
6084{
6085 struct bgp_table *table;
9bcb3eef 6086 struct bgp_dest *dest;
40381db7 6087 struct bgp_path_info *pi;
d62a17ae 6088
dfb6fd1d
NT
6089 /* Do not install the aggregate route if BGP is in the
6090 * process of termination.
6091 */
892fedb6
DA
6092 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6093 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6094 return;
6095
d62a17ae 6096 table = bgp->rib[afi][safi];
9bcb3eef
DS
6097 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6098 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6099 if (pi->peer == bgp->peer_self
6100 && ((pi->type == ZEBRA_ROUTE_BGP
6101 && pi->sub_type == BGP_ROUTE_STATIC)
6102 || (pi->type != ZEBRA_ROUTE_BGP
6103 && pi->sub_type
d62a17ae 6104 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6105 bgp_aggregate_decrement(
6106 bgp, bgp_dest_get_prefix(dest), pi, afi,
6107 safi);
40381db7 6108 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6109 bgp_path_info_delete(dest, pi);
6110 bgp_process(bgp, dest, afi, safi);
d62a17ae 6111 }
6112 }
6113 }
ad4cbda1 6114}
6115
6116/*
6117 * Purge all networks and redistributed routes from routing table.
6118 * Invoked upon the instance going down.
6119 */
d62a17ae 6120void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6121{
d62a17ae 6122 afi_t afi;
6123 safi_t safi;
ad4cbda1 6124
05c7a1cc
QY
6125 FOREACH_AFI_SAFI (afi, safi)
6126 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6127}
6128
137446f9
LB
6129/*
6130 * gpz 110624
6131 * Currently this is used to set static routes for VPN and ENCAP.
6132 * I think it can probably be factored with bgp_static_set.
6133 */
d62a17ae 6134int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6135 const char *ip_str, const char *rd_str,
6136 const char *label_str, const char *rmap_str,
6137 int evpn_type, const char *esi, const char *gwip,
6138 const char *ethtag, const char *routermac)
6139{
6140 VTY_DECLVAR_CONTEXT(bgp, bgp);
6141 int ret;
6142 struct prefix p;
6143 struct prefix_rd prd;
9bcb3eef
DS
6144 struct bgp_dest *pdest;
6145 struct bgp_dest *dest;
d62a17ae 6146 struct bgp_table *table;
6147 struct bgp_static *bgp_static;
6148 mpls_label_t label = MPLS_INVALID_LABEL;
6149 struct prefix gw_ip;
6150
6151 /* validate ip prefix */
6152 ret = str2prefix(ip_str, &p);
6153 if (!ret) {
6154 vty_out(vty, "%% Malformed prefix\n");
6155 return CMD_WARNING_CONFIG_FAILED;
6156 }
6157 apply_mask(&p);
6158 if ((afi == AFI_L2VPN)
6159 && (bgp_build_evpn_prefix(evpn_type,
6160 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6161 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6162 return CMD_WARNING_CONFIG_FAILED;
6163 }
718e3744 6164
d62a17ae 6165 ret = str2prefix_rd(rd_str, &prd);
6166 if (!ret) {
6167 vty_out(vty, "%% Malformed rd\n");
6168 return CMD_WARNING_CONFIG_FAILED;
6169 }
718e3744 6170
d62a17ae 6171 if (label_str) {
6172 unsigned long label_val;
6173 label_val = strtoul(label_str, NULL, 10);
6174 encode_label(label_val, &label);
6175 }
9bedbb1e 6176
d62a17ae 6177 if (safi == SAFI_EVPN) {
6178 if (esi && str2esi(esi, NULL) == 0) {
6179 vty_out(vty, "%% Malformed ESI\n");
6180 return CMD_WARNING_CONFIG_FAILED;
6181 }
6182 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6183 vty_out(vty, "%% Malformed Router MAC\n");
6184 return CMD_WARNING_CONFIG_FAILED;
6185 }
6186 if (gwip) {
6187 memset(&gw_ip, 0, sizeof(struct prefix));
6188 ret = str2prefix(gwip, &gw_ip);
6189 if (!ret) {
6190 vty_out(vty, "%% Malformed GatewayIp\n");
6191 return CMD_WARNING_CONFIG_FAILED;
6192 }
6193 if ((gw_ip.family == AF_INET
3714a385 6194 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6195 (struct prefix_evpn *)&p))
6196 || (gw_ip.family == AF_INET6
3714a385 6197 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6198 (struct prefix_evpn *)&p))) {
6199 vty_out(vty,
6200 "%% GatewayIp family differs with IP prefix\n");
6201 return CMD_WARNING_CONFIG_FAILED;
6202 }
6203 }
6204 }
9bcb3eef
DS
6205 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6206 if (!bgp_dest_has_bgp_path_info_data(pdest))
6207 bgp_dest_set_bgp_table_info(pdest,
67009e22 6208 bgp_table_init(bgp, afi, safi));
9bcb3eef 6209 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6210
9bcb3eef 6211 dest = bgp_node_get(table, &p);
d62a17ae 6212
9bcb3eef 6213 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6214 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6215 bgp_dest_unlock_node(dest);
d62a17ae 6216 } else {
6217 /* New configuration. */
6218 bgp_static = bgp_static_new();
6219 bgp_static->backdoor = 0;
6220 bgp_static->valid = 0;
6221 bgp_static->igpmetric = 0;
975a328e 6222 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6223 bgp_static->label = label;
6224 bgp_static->prd = prd;
6225
6226 if (rmap_str) {
0a22ddfb 6227 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6228 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6229 bgp_static->rmap.name =
6230 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6231 bgp_static->rmap.map =
6232 route_map_lookup_by_name(rmap_str);
b4897fa5 6233 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6234 }
718e3744 6235
d62a17ae 6236 if (safi == SAFI_EVPN) {
6237 if (esi) {
6238 bgp_static->eth_s_id =
6239 XCALLOC(MTYPE_ATTR,
0a50c248 6240 sizeof(esi_t));
d62a17ae 6241 str2esi(esi, bgp_static->eth_s_id);
6242 }
6243 if (routermac) {
6244 bgp_static->router_mac =
28328ea9 6245 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6246 (void)prefix_str2mac(routermac,
6247 bgp_static->router_mac);
d62a17ae 6248 }
6249 if (gwip)
6250 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6251 }
9bcb3eef 6252 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6253
d62a17ae 6254 bgp_static->valid = 1;
6255 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6256 }
718e3744 6257
d62a17ae 6258 return CMD_SUCCESS;
718e3744 6259}
6260
6261/* Configure static BGP network. */
d62a17ae 6262int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6263 const char *ip_str, const char *rd_str,
6264 const char *label_str, int evpn_type, const char *esi,
6265 const char *gwip, const char *ethtag)
6266{
6267 VTY_DECLVAR_CONTEXT(bgp, bgp);
6268 int ret;
6269 struct prefix p;
6270 struct prefix_rd prd;
9bcb3eef
DS
6271 struct bgp_dest *pdest;
6272 struct bgp_dest *dest;
d62a17ae 6273 struct bgp_table *table;
6274 struct bgp_static *bgp_static;
6275 mpls_label_t label = MPLS_INVALID_LABEL;
6276
6277 /* Convert IP prefix string to struct prefix. */
6278 ret = str2prefix(ip_str, &p);
6279 if (!ret) {
6280 vty_out(vty, "%% Malformed prefix\n");
6281 return CMD_WARNING_CONFIG_FAILED;
6282 }
6283 apply_mask(&p);
6284 if ((afi == AFI_L2VPN)
6285 && (bgp_build_evpn_prefix(evpn_type,
6286 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6287 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6288 return CMD_WARNING_CONFIG_FAILED;
6289 }
6290 ret = str2prefix_rd(rd_str, &prd);
6291 if (!ret) {
6292 vty_out(vty, "%% Malformed rd\n");
6293 return CMD_WARNING_CONFIG_FAILED;
6294 }
718e3744 6295
d62a17ae 6296 if (label_str) {
6297 unsigned long label_val;
6298 label_val = strtoul(label_str, NULL, 10);
6299 encode_label(label_val, &label);
6300 }
718e3744 6301
9bcb3eef
DS
6302 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6303 if (!bgp_dest_has_bgp_path_info_data(pdest))
6304 bgp_dest_set_bgp_table_info(pdest,
67009e22 6305 bgp_table_init(bgp, afi, safi));
d62a17ae 6306 else
9bcb3eef
DS
6307 bgp_dest_unlock_node(pdest);
6308 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6309
9bcb3eef 6310 dest = bgp_node_lookup(table, &p);
6b0655a2 6311
9bcb3eef 6312 if (dest) {
d62a17ae 6313 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6314
9bcb3eef 6315 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6316 bgp_static_free(bgp_static);
9bcb3eef
DS
6317 bgp_dest_set_bgp_static_info(dest, NULL);
6318 bgp_dest_unlock_node(dest);
6319 bgp_dest_unlock_node(dest);
d62a17ae 6320 } else
6321 vty_out(vty, "%% Can't find the route\n");
6322
6323 return CMD_SUCCESS;
6324}
6325
6326static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6327 const char *rmap_name)
6328{
6329 VTY_DECLVAR_CONTEXT(bgp, bgp);
6330 struct bgp_rmap *rmap;
6331
6332 rmap = &bgp->table_map[afi][safi];
6333 if (rmap_name) {
0a22ddfb 6334 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6335 route_map_counter_decrement(rmap->map);
d62a17ae 6336 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6337 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6338 route_map_counter_increment(rmap->map);
d62a17ae 6339 } else {
0a22ddfb 6340 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6341 route_map_counter_decrement(rmap->map);
d62a17ae 6342 rmap->map = NULL;
6343 }
73ac8160 6344
d62a17ae 6345 if (bgp_fibupd_safi(safi))
6346 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6347
d62a17ae 6348 return CMD_SUCCESS;
73ac8160
DS
6349}
6350
d62a17ae 6351static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6352 const char *rmap_name)
73ac8160 6353{
d62a17ae 6354 VTY_DECLVAR_CONTEXT(bgp, bgp);
6355 struct bgp_rmap *rmap;
73ac8160 6356
d62a17ae 6357 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6358 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6359 route_map_counter_decrement(rmap->map);
d62a17ae 6360 rmap->map = NULL;
73ac8160 6361
d62a17ae 6362 if (bgp_fibupd_safi(safi))
6363 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6364
d62a17ae 6365 return CMD_SUCCESS;
73ac8160
DS
6366}
6367
2b791107 6368void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6369 safi_t safi)
73ac8160 6370{
d62a17ae 6371 if (bgp->table_map[afi][safi].name) {
d62a17ae 6372 vty_out(vty, " table-map %s\n",
6373 bgp->table_map[afi][safi].name);
6374 }
73ac8160
DS
6375}
6376
73ac8160
DS
6377DEFUN (bgp_table_map,
6378 bgp_table_map_cmd,
6379 "table-map WORD",
6380 "BGP table to RIB route download filter\n"
6381 "Name of the route map\n")
6382{
d62a17ae 6383 int idx_word = 1;
6384 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6385 argv[idx_word]->arg);
73ac8160
DS
6386}
6387DEFUN (no_bgp_table_map,
6388 no_bgp_table_map_cmd,
6389 "no table-map WORD",
3a2d747c 6390 NO_STR
73ac8160
DS
6391 "BGP table to RIB route download filter\n"
6392 "Name of the route map\n")
6393{
d62a17ae 6394 int idx_word = 2;
6395 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6396 argv[idx_word]->arg);
73ac8160
DS
6397}
6398
37a87b8f
CS
6399DEFPY_YANG (bgp_network, bgp_network_cmd,
6400 "[no] network \
6401 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6402 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6403 backdoor$backdoor}]",
6404 NO_STR
6405 "Specify a network to announce via BGP\n"
6406 "IPv4 prefix\n"
6407 "Network number\n"
6408 "Network mask\n"
6409 "Network mask\n"
6410 "Route-map to modify the attributes\n"
6411 "Name of the route map\n"
6412 "Label index to associate with the prefix\n"
6413 "Label index value\n"
6414 "Specify a BGP backdoor route\n")
6415{
6416 char addr_prefix_str[PREFIX_STRLEN];
6417 char base_xpath[XPATH_MAXLEN];
6418 afi_t afi;
6419 safi_t safi;
e2a86ad9
DS
6420
6421 if (address_str) {
6422 int ret;
718e3744 6423
e2a86ad9 6424 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6425 addr_prefix_str,
6426 sizeof(addr_prefix_str));
e2a86ad9
DS
6427 if (!ret) {
6428 vty_out(vty, "%% Inconsistent address and mask\n");
6429 return CMD_WARNING_CONFIG_FAILED;
6430 }
d62a17ae 6431 }
718e3744 6432
37a87b8f
CS
6433 afi = bgp_node_afi(vty);
6434 safi = bgp_node_safi(vty);
6435
6436 if (no) {
6437 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6438 } else {
6439 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6440
6441 if (map_name)
6442 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6443 NB_OP_CREATE, map_name);
6444 else
6445 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6446 NB_OP_DESTROY, NULL);
6447
6448 if (label_index_str)
6449 nb_cli_enqueue_change(vty, "./label-index",
6450 NB_OP_MODIFY, label_index_str);
6451
6452 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6453 backdoor ? "true" : "false");
6454 }
6455
6456 snprintf(
6457 base_xpath, sizeof(base_xpath),
6458 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6459 yang_afi_safi_value2identity(afi, safi),
6460 bgp_afi_safi_get_container_str(afi, safi),
6461 address_str ? addr_prefix_str : prefix_str);
6462
6463 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6464}
6465
37a87b8f
CS
6466DEFPY_YANG (ipv6_bgp_network,
6467 ipv6_bgp_network_cmd,
6468 "[no] network X:X::X:X/M$prefix \
6469 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6470 NO_STR
6471 "Specify a network to announce via BGP\n"
6472 "IPv6 prefix\n"
6473 "Route-map to modify the attributes\n"
6474 "Name of the route map\n"
6475 "Label index to associate with the prefix\n"
6476 "Label index value\n")
6477{
6478 char base_xpath[XPATH_MAXLEN];
6479 afi_t afi;
6480 safi_t safi;
6481
6482 afi = bgp_node_afi(vty);
6483 safi = bgp_node_safi(vty);
6484
6485 if (no) {
6486 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6487 } else {
6488 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6489
6490 if (map_name)
6491 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6492 NB_OP_MODIFY, map_name);
6493 else
6494 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6495 NB_OP_DESTROY, NULL);
6496
6497 if (label_index_str)
6498 nb_cli_enqueue_change(vty, "./label-index",
6499 NB_OP_MODIFY, label_index_str);
6500 }
6501
6502 snprintf(
6503 base_xpath, sizeof(base_xpath),
6504 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6505 yang_afi_safi_value2identity(afi, safi),
6506 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6507
6508 return nb_cli_apply_changes(vty, base_xpath);
6509}
6510
6511void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6512 struct lyd_node *dnode,
6513 bool show_defaults)
718e3744 6514{
37a87b8f
CS
6515 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6516
6517 if (yang_dnode_exists(dnode, "./label-index"))
6518 vty_out(vty, " label-index %s",
6519 yang_dnode_get_string(dnode, "./label-index"));
6520
6521 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6522 vty_out(vty, " route-map %s",
6523 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6524
6525 if (yang_dnode_get_bool(dnode, "./backdoor"))
6526 vty_out(vty, " backdoor");
6527
6528 vty_out(vty, "\n");
1b6d5c7e
VV
6529}
6530
d62a17ae 6531static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6532{
d62a17ae 6533 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6534}
6535
d62a17ae 6536static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6537{
365ab2e7
RZ
6538 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6539 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6540 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6541 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6542 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6543}
718e3744 6544
365ab2e7
RZ
6545/**
6546 * Helper function to avoid repeated code: prepare variables for a
6547 * `route_map_apply` call.
6548 *
6549 * \returns `true` on route map match, otherwise `false`.
6550 */
6551static bool aggr_suppress_map_test(struct bgp *bgp,
6552 struct bgp_aggregate *aggregate,
6553 struct bgp_path_info *pi)
6554{
6555 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6556 route_map_result_t rmr = RMAP_DENYMATCH;
6557 struct bgp_path_info rmap_path = {};
6558 struct attr attr = {};
6559
6560 /* No route map entries created, just don't match. */
6561 if (aggregate->suppress_map == NULL)
6562 return false;
6563
6564 /* Call route map matching and return result. */
6565 attr.aspath = aspath_empty();
6566 rmap_path.peer = bgp->peer_self;
6567 rmap_path.attr = &attr;
6568
6569 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6570 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6571 bgp->peer_self->rmap_type = 0;
6572
6573 bgp_attr_flush(&attr);
6574
6575 return rmr == RMAP_PERMITMATCH;
6576}
6577
4056a5f6
RZ
6578/** Test whether the aggregation has suppressed this path or not. */
6579static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6580 struct bgp_path_info *pi)
6581{
6582 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6583 return false;
6584
6585 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6586}
6587
6588/**
6589 * Suppress this path and keep the reference.
6590 *
6591 * \returns `true` if needs processing otherwise `false`.
6592 */
6593static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6594 struct bgp_path_info *pi)
6595{
6596 struct bgp_path_info_extra *pie;
6597
6598 /* Path is already suppressed by this aggregation. */
6599 if (aggr_suppress_exists(aggregate, pi))
6600 return false;
6601
6602 pie = bgp_path_info_extra_get(pi);
6603
6604 /* This is the first suppression, allocate memory and list it. */
6605 if (pie->aggr_suppressors == NULL)
6606 pie->aggr_suppressors = list_new();
6607
6608 listnode_add(pie->aggr_suppressors, aggregate);
6609
6610 /* Only mark for processing if suppressed. */
6611 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6612 if (BGP_DEBUG(update, UPDATE_OUT))
6613 zlog_debug("aggregate-address suppressing: %pFX",
6614 bgp_dest_get_prefix(pi->net));
6615
4056a5f6
RZ
6616 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6617 return true;
6618 }
6619
6620 return false;
6621}
6622
6623/**
6624 * Unsuppress this path and remove the reference.
6625 *
6626 * \returns `true` if needs processing otherwise `false`.
6627 */
6628static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6629 struct bgp_path_info *pi)
6630{
6631 /* Path wasn't suppressed. */
6632 if (!aggr_suppress_exists(aggregate, pi))
6633 return false;
6634
6635 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6636
6637 /* Unsuppress and free extra memory if last item. */
6638 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6639 if (BGP_DEBUG(update, UPDATE_OUT))
6640 zlog_debug("aggregate-address unsuppressing: %pFX",
6641 bgp_dest_get_prefix(pi->net));
6642
4056a5f6
RZ
6643 list_delete(&pi->extra->aggr_suppressors);
6644 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6645 return true;
6646 }
6647
6648 return false;
6649}
6650
3dc339cd
DA
6651static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6652 struct aspath *aspath,
6653 struct community *comm,
6654 struct ecommunity *ecomm,
6655 struct lcommunity *lcomm)
eaaf8adb
DS
6656{
6657 static struct aspath *ae = NULL;
6658
6659 if (!ae)
6660 ae = aspath_empty();
6661
40381db7 6662 if (!pi)
3dc339cd 6663 return false;
eaaf8adb 6664
40381db7 6665 if (origin != pi->attr->origin)
3dc339cd 6666 return false;
eaaf8adb 6667
40381db7 6668 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6669 return false;
29f7d023 6670
40381db7 6671 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6672 return false;
eaaf8adb 6673
3da2cc32 6674 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6675 return false;
eaaf8adb 6676
dd18c5a9 6677 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6678 return false;
dd18c5a9 6679
40381db7 6680 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6681 return false;
7ce8a8e0 6682
3dc339cd 6683 return true;
eaaf8adb
DS
6684}
6685
5f040085
DS
6686static void bgp_aggregate_install(
6687 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6688 uint8_t origin, struct aspath *aspath, struct community *community,
6689 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6690 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6691{
9bcb3eef 6692 struct bgp_dest *dest;
c701010e 6693 struct bgp_table *table;
6f94b685 6694 struct bgp_path_info *pi, *orig, *new;
20894f50 6695 struct attr *attr;
c701010e
DS
6696
6697 table = bgp->rib[afi][safi];
6698
9bcb3eef 6699 dest = bgp_node_get(table, p);
eaaf8adb 6700
9bcb3eef 6701 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6702 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6703 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6704 break;
6705
6aabb15d
RZ
6706 /*
6707 * If we have paths with different MEDs, then don't install
6708 * (or uninstall) the aggregate route.
6709 */
6710 if (aggregate->match_med && aggregate->med_mismatched)
6711 goto uninstall_aggregate_route;
6712
c701010e 6713 if (aggregate->count > 0) {
eaaf8adb
DS
6714 /*
6715 * If the aggregate information has not changed
6716 * no need to re-install it again.
6717 */
6f94b685 6718 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6719 ecommunity, lcommunity)) {
9bcb3eef 6720 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6721
6722 if (aspath)
6723 aspath_free(aspath);
6724 if (community)
3c1f53de 6725 community_free(&community);
3da2cc32
DS
6726 if (ecommunity)
6727 ecommunity_free(&ecommunity);
dd18c5a9
DS
6728 if (lcommunity)
6729 lcommunity_free(&lcommunity);
eaaf8adb
DS
6730
6731 return;
6732 }
6733
6734 /*
6735 * Mark the old as unusable
6736 */
40381db7 6737 if (pi)
9bcb3eef 6738 bgp_path_info_delete(dest, pi);
eaaf8adb 6739
20894f50
DA
6740 attr = bgp_attr_aggregate_intern(
6741 bgp, origin, aspath, community, ecommunity, lcommunity,
6742 aggregate, atomic_aggregate, p);
6743
6744 if (!attr) {
6745 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6746 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6747 zlog_debug("%s: %pFX null attribute", __func__,
6748 p);
20894f50
DA
6749 return;
6750 }
6751
3da2cc32 6752 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6753 bgp->peer_self, attr, dest);
20894f50 6754
1defdda8 6755 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6756
9bcb3eef
DS
6757 bgp_path_info_add(dest, new);
6758 bgp_process(bgp, dest, afi, safi);
c701010e 6759 } else {
6aabb15d 6760 uninstall_aggregate_route:
6f94b685 6761 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6762 if (pi->peer == bgp->peer_self
6763 && pi->type == ZEBRA_ROUTE_BGP
6764 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6765 break;
6766
6767 /* Withdraw static BGP route from routing table. */
40381db7 6768 if (pi) {
9bcb3eef
DS
6769 bgp_path_info_delete(dest, pi);
6770 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6771 }
6772 }
6773
9bcb3eef 6774 bgp_dest_unlock_node(dest);
c701010e
DS
6775}
6776
6aabb15d
RZ
6777/**
6778 * Check if the current path has different MED than other known paths.
6779 *
6780 * \returns `true` if the MED matched the others else `false`.
6781 */
6782static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6783 struct bgp *bgp, struct bgp_path_info *pi)
6784{
6785 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6786
6787 /* This is the first route being analyzed. */
6788 if (!aggregate->med_initialized) {
6789 aggregate->med_initialized = true;
6790 aggregate->med_mismatched = false;
6791 aggregate->med_matched_value = cur_med;
6792 } else {
6793 /* Check if routes with different MED showed up. */
6794 if (cur_med != aggregate->med_matched_value)
6795 aggregate->med_mismatched = true;
6796 }
6797
6798 return !aggregate->med_mismatched;
6799}
6800
6801/**
6802 * Initializes and tests all routes in the aggregate address path for MED
6803 * values.
6804 *
6805 * \returns `true` if all MEDs are the same otherwise `false`.
6806 */
6807static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6808 struct bgp *bgp, const struct prefix *p,
6809 afi_t afi, safi_t safi)
6810{
6811 struct bgp_table *table = bgp->rib[afi][safi];
6812 const struct prefix *dest_p;
6813 struct bgp_dest *dest, *top;
6814 struct bgp_path_info *pi;
6815 bool med_matched = true;
6816
6817 aggregate->med_initialized = false;
6818
6819 top = bgp_node_get(table, p);
6820 for (dest = bgp_node_get(table, p); dest;
6821 dest = bgp_route_next_until(dest, top)) {
6822 dest_p = bgp_dest_get_prefix(dest);
6823 if (dest_p->prefixlen <= p->prefixlen)
6824 continue;
6825
6826 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6827 if (BGP_PATH_HOLDDOWN(pi))
6828 continue;
6829 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6830 continue;
6831 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6832 med_matched = false;
6833 break;
6834 }
6835 }
6836 if (!med_matched)
6837 break;
6838 }
6839 bgp_dest_unlock_node(top);
6840
6841 return med_matched;
6842}
6843
6844/**
6845 * Toggles the route suppression status for this aggregate address
6846 * configuration.
6847 */
4056a5f6
RZ
6848void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6849 struct bgp *bgp, const struct prefix *p,
6850 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6851{
6852 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6853 const struct prefix *dest_p;
6854 struct bgp_dest *dest, *top;
6855 struct bgp_path_info *pi;
6856 bool toggle_suppression;
6857
6858 /* We've found a different MED we must revert any suppressed routes. */
6859 top = bgp_node_get(table, p);
6860 for (dest = bgp_node_get(table, p); dest;
6861 dest = bgp_route_next_until(dest, top)) {
6862 dest_p = bgp_dest_get_prefix(dest);
6863 if (dest_p->prefixlen <= p->prefixlen)
6864 continue;
6865
6866 toggle_suppression = false;
6867 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6868 if (BGP_PATH_HOLDDOWN(pi))
6869 continue;
6870 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6871 continue;
6872
6aabb15d
RZ
6873 /* We are toggling suppression back. */
6874 if (suppress) {
6aabb15d 6875 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6876 if (aggr_suppress_path(aggregate, pi))
6877 toggle_suppression = true;
6aabb15d
RZ
6878 continue;
6879 }
6880
6aabb15d 6881 /* Install route if there is no more suppression. */
4056a5f6 6882 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6883 toggle_suppression = true;
6aabb15d
RZ
6884 }
6885
6886 if (toggle_suppression)
6887 bgp_process(bgp, dest, afi, safi);
6888 }
6889 bgp_dest_unlock_node(top);
6890}
6891
6892/**
6893 * Aggregate address MED matching incremental test: this function is called
6894 * when the initial aggregation occurred and we are only testing a single
6895 * new path.
6896 *
6897 * In addition to testing and setting the MED validity it also installs back
6898 * suppressed routes (if summary is configured).
6899 *
6900 * Must not be called in `bgp_aggregate_route`.
6901 */
6902static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6903 struct bgp *bgp, const struct prefix *p,
6904 afi_t afi, safi_t safi,
6905 struct bgp_path_info *pi, bool is_adding)
6906{
6907 /* MED matching disabled. */
6908 if (!aggregate->match_med)
6909 return;
6910
6911 /* Aggregation with different MED, nothing to do. */
6912 if (aggregate->med_mismatched)
6913 return;
6914
6915 /*
6916 * Test the current entry:
6917 *
6918 * is_adding == true: if the new entry doesn't match then we must
6919 * install all suppressed routes.
6920 *
6921 * is_adding == false: if the entry being removed was the last
6922 * unmatching entry then we can suppress all routes.
6923 */
6924 if (!is_adding) {
6925 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6926 && aggregate->summary_only)
6927 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6928 safi, true);
6929 } else
6930 bgp_aggregate_med_match(aggregate, bgp, pi);
6931
6932 /* No mismatches, just quit. */
6933 if (!aggregate->med_mismatched)
6934 return;
6935
6936 /* Route summarization is disabled. */
6937 if (!aggregate->summary_only)
6938 return;
6939
6940 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6941}
6942
b5d58c32 6943/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6944void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6945 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6946{
6947 struct bgp_table *table;
9bcb3eef
DS
6948 struct bgp_dest *top;
6949 struct bgp_dest *dest;
d7c0a89a 6950 uint8_t origin;
d62a17ae 6951 struct aspath *aspath = NULL;
d62a17ae 6952 struct community *community = NULL;
3da2cc32 6953 struct ecommunity *ecommunity = NULL;
dd18c5a9 6954 struct lcommunity *lcommunity = NULL;
40381db7 6955 struct bgp_path_info *pi;
d62a17ae 6956 unsigned long match = 0;
d7c0a89a 6957 uint8_t atomic_aggregate = 0;
d62a17ae 6958
9f822fa2
S
6959 /* If the bgp instance is being deleted or self peer is deleted
6960 * then do not create aggregate route
6961 */
892fedb6
DA
6962 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6963 || (bgp->peer_self == NULL))
9f822fa2
S
6964 return;
6965
6aabb15d
RZ
6966 /* Initialize and test routes for MED difference. */
6967 if (aggregate->match_med)
6968 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6969
4056a5f6
RZ
6970 /*
6971 * Reset aggregate count: we might've been called from route map
6972 * update so in that case we must retest all more specific routes.
6973 *
6974 * \see `bgp_route_map_process_update`.
6975 */
6976 aggregate->count = 0;
6977 aggregate->incomplete_origin_count = 0;
6978 aggregate->incomplete_origin_count = 0;
6979 aggregate->egp_origin_count = 0;
6980
d62a17ae 6981 /* ORIGIN attribute: If at least one route among routes that are
6982 aggregated has ORIGIN with the value INCOMPLETE, then the
6983 aggregated route must have the ORIGIN attribute with the value
6984 INCOMPLETE. Otherwise, if at least one route among routes that
6985 are aggregated has ORIGIN with the value EGP, then the aggregated
6986 route must have the origin attribute with the value EGP. In all
6987 other case the value of the ORIGIN attribute of the aggregated
6988 route is INTERNAL. */
6989 origin = BGP_ORIGIN_IGP;
718e3744 6990
d62a17ae 6991 table = bgp->rib[afi][safi];
718e3744 6992
d62a17ae 6993 top = bgp_node_get(table, p);
9bcb3eef
DS
6994 for (dest = bgp_node_get(table, p); dest;
6995 dest = bgp_route_next_until(dest, top)) {
6996 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6997
9bcb3eef 6998 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6999 continue;
d62a17ae 7000
a77e2f4b
S
7001 /* If suppress fib is enabled and route not installed
7002 * in FIB, skip the route
7003 */
7004 if (!bgp_check_advertise(bgp, dest))
7005 continue;
7006
c2ff8b3e 7007 match = 0;
d62a17ae 7008
9bcb3eef 7009 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7010 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7011 continue;
718e3744 7012
40381db7 7013 if (pi->attr->flag
c2ff8b3e
DS
7014 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7015 atomic_aggregate = 1;
d62a17ae 7016
40381db7 7017 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7018 continue;
d62a17ae 7019
f273fef1
DS
7020 /*
7021 * summary-only aggregate route suppress
7022 * aggregated route announcements.
6aabb15d
RZ
7023 *
7024 * MED matching:
7025 * Don't create summaries if MED didn't match
7026 * otherwise neither the specific routes and the
7027 * aggregation will be announced.
f273fef1 7028 */
6aabb15d
RZ
7029 if (aggregate->summary_only
7030 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7031 if (aggr_suppress_path(aggregate, pi))
7032 match++;
d62a17ae 7033 }
c2ff8b3e 7034
365ab2e7
RZ
7035 /*
7036 * Suppress more specific routes that match the route
7037 * map results.
7038 *
7039 * MED matching:
7040 * Don't suppress routes if MED matching is enabled and
7041 * it mismatched otherwise we might end up with no
7042 * routes for this path.
7043 */
7044 if (aggregate->suppress_map_name
7045 && AGGREGATE_MED_VALID(aggregate)
7046 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7047 if (aggr_suppress_path(aggregate, pi))
7048 match++;
d62a17ae 7049 }
c2ff8b3e
DS
7050
7051 aggregate->count++;
7052
f273fef1
DS
7053 /*
7054 * If at least one route among routes that are
7055 * aggregated has ORIGIN with the value INCOMPLETE,
7056 * then the aggregated route MUST have the ORIGIN
7057 * attribute with the value INCOMPLETE. Otherwise, if
7058 * at least one route among routes that are aggregated
7059 * has ORIGIN with the value EGP, then the aggregated
7060 * route MUST have the ORIGIN attribute with the value
7061 * EGP.
7062 */
fc968841
NT
7063 switch (pi->attr->origin) {
7064 case BGP_ORIGIN_INCOMPLETE:
7065 aggregate->incomplete_origin_count++;
7066 break;
7067 case BGP_ORIGIN_EGP:
7068 aggregate->egp_origin_count++;
7069 break;
7070 default:
7071 /*Do nothing.
7072 */
7073 break;
7074 }
c2ff8b3e
DS
7075
7076 if (!aggregate->as_set)
7077 continue;
7078
f273fef1
DS
7079 /*
7080 * as-set aggregate route generate origin, as path,
7081 * and community aggregation.
7082 */
fc968841
NT
7083 /* Compute aggregate route's as-path.
7084 */
ef51a7d8 7085 bgp_compute_aggregate_aspath_hash(aggregate,
7086 pi->attr->aspath);
c2ff8b3e 7087
fc968841
NT
7088 /* Compute aggregate route's community.
7089 */
7090 if (pi->attr->community)
21fec674 7091 bgp_compute_aggregate_community_hash(
fc968841
NT
7092 aggregate,
7093 pi->attr->community);
dd18c5a9 7094
fc968841
NT
7095 /* Compute aggregate route's extended community.
7096 */
7097 if (pi->attr->ecommunity)
4edd83f9 7098 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7099 aggregate,
7100 pi->attr->ecommunity);
7101
7102 /* Compute aggregate route's large community.
7103 */
7104 if (pi->attr->lcommunity)
f1eb1f05 7105 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7106 aggregate,
7107 pi->attr->lcommunity);
d62a17ae 7108 }
c2ff8b3e 7109 if (match)
9bcb3eef 7110 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7111 }
21fec674 7112 if (aggregate->as_set) {
ef51a7d8 7113 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7114 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7115 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7116 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7117 }
7118
f1eb1f05 7119
9bcb3eef 7120 bgp_dest_unlock_node(top);
718e3744 7121
718e3744 7122
fc968841
NT
7123 if (aggregate->incomplete_origin_count > 0)
7124 origin = BGP_ORIGIN_INCOMPLETE;
7125 else if (aggregate->egp_origin_count > 0)
7126 origin = BGP_ORIGIN_EGP;
d62a17ae 7127
229757f1
DA
7128 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7129 origin = aggregate->origin;
7130
fc968841
NT
7131 if (aggregate->as_set) {
7132 if (aggregate->aspath)
7133 /* Retrieve aggregate route's as-path.
7134 */
7135 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7136
fc968841
NT
7137 if (aggregate->community)
7138 /* Retrieve aggregate route's community.
7139 */
7140 community = community_dup(aggregate->community);
3da2cc32 7141
fc968841
NT
7142 if (aggregate->ecommunity)
7143 /* Retrieve aggregate route's ecommunity.
7144 */
7145 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7146
fc968841
NT
7147 if (aggregate->lcommunity)
7148 /* Retrieve aggregate route's lcommunity.
7149 */
7150 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7151 }
718e3744 7152
c701010e 7153 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7154 ecommunity, lcommunity, atomic_aggregate,
7155 aggregate);
718e3744 7156}
7157
5f040085
DS
7158void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7159 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7160{
7161 struct bgp_table *table;
9bcb3eef
DS
7162 struct bgp_dest *top;
7163 struct bgp_dest *dest;
40381db7 7164 struct bgp_path_info *pi;
3b7db173
DS
7165 unsigned long match;
7166
7167 table = bgp->rib[afi][safi];
7168
7169 /* If routes exists below this node, generate aggregate routes. */
7170 top = bgp_node_get(table, p);
9bcb3eef
DS
7171 for (dest = bgp_node_get(table, p); dest;
7172 dest = bgp_route_next_until(dest, top)) {
7173 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7174
9bcb3eef 7175 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7176 continue;
7177 match = 0;
7178
9bcb3eef 7179 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7180 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7181 continue;
7182
40381db7 7183 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7184 continue;
7185
6aabb15d
RZ
7186 if (aggregate->summary_only && pi->extra
7187 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7188 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7189 match++;
3b7db173 7190 }
3b7db173 7191
365ab2e7
RZ
7192 if (aggregate->suppress_map_name
7193 && AGGREGATE_MED_VALID(aggregate)
7194 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7195 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7196 match++;
3b7db173 7197 }
365ab2e7 7198
3b7db173 7199 aggregate->count--;
fc968841
NT
7200
7201 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7202 aggregate->incomplete_origin_count--;
7203 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7204 aggregate->egp_origin_count--;
7205
7206 if (aggregate->as_set) {
7207 /* Remove as-path from aggregate.
7208 */
ef51a7d8 7209 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7210 aggregate,
7211 pi->attr->aspath);
7212
7213 if (pi->attr->community)
7214 /* Remove community from aggregate.
7215 */
21fec674 7216 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7217 aggregate,
7218 pi->attr->community);
7219
7220 if (pi->attr->ecommunity)
7221 /* Remove ecommunity from aggregate.
7222 */
4edd83f9 7223 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7224 aggregate,
7225 pi->attr->ecommunity);
7226
7227 if (pi->attr->lcommunity)
7228 /* Remove lcommunity from aggregate.
7229 */
f1eb1f05 7230 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7231 aggregate,
7232 pi->attr->lcommunity);
7233 }
3b7db173
DS
7234 }
7235
7236 /* If this node was suppressed, process the change. */
7237 if (match)
9bcb3eef 7238 bgp_process(bgp, dest, afi, safi);
3b7db173 7239 }
f1eb1f05 7240 if (aggregate->as_set) {
ef51a7d8 7241 aspath_free(aggregate->aspath);
7242 aggregate->aspath = NULL;
21fec674 7243 if (aggregate->community)
7244 community_free(&aggregate->community);
4edd83f9 7245 if (aggregate->ecommunity)
7246 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7247 if (aggregate->lcommunity)
7248 lcommunity_free(&aggregate->lcommunity);
7249 }
7250
9bcb3eef 7251 bgp_dest_unlock_node(top);
3b7db173 7252}
718e3744 7253
5f040085
DS
7254static void bgp_add_route_to_aggregate(struct bgp *bgp,
7255 const struct prefix *aggr_p,
fc968841
NT
7256 struct bgp_path_info *pinew, afi_t afi,
7257 safi_t safi,
7258 struct bgp_aggregate *aggregate)
7259{
7260 uint8_t origin;
7261 struct aspath *aspath = NULL;
7262 uint8_t atomic_aggregate = 0;
7263 struct community *community = NULL;
7264 struct ecommunity *ecommunity = NULL;
7265 struct lcommunity *lcommunity = NULL;
7266
a4559740 7267 /* If the bgp instance is being deleted or self peer is deleted
7268 * then do not create aggregate route
7269 */
7270 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7271 || (bgp->peer_self == NULL))
7272 return;
7273
fc968841
NT
7274 /* ORIGIN attribute: If at least one route among routes that are
7275 * aggregated has ORIGIN with the value INCOMPLETE, then the
7276 * aggregated route must have the ORIGIN attribute with the value
7277 * INCOMPLETE. Otherwise, if at least one route among routes that
7278 * are aggregated has ORIGIN with the value EGP, then the aggregated
7279 * route must have the origin attribute with the value EGP. In all
7280 * other case the value of the ORIGIN attribute of the aggregated
7281 * route is INTERNAL.
7282 */
7283 origin = BGP_ORIGIN_IGP;
7284
7285 aggregate->count++;
7286
6aabb15d
RZ
7287 /*
7288 * This must be called before `summary` check to avoid
7289 * "suppressing" twice.
7290 */
7291 if (aggregate->match_med)
7292 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7293 pinew, true);
7294
7295 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7296 aggr_suppress_path(aggregate, pinew);
fc968841 7297
365ab2e7
RZ
7298 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7299 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7300 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7301
7302 switch (pinew->attr->origin) {
7303 case BGP_ORIGIN_INCOMPLETE:
7304 aggregate->incomplete_origin_count++;
7305 break;
7306 case BGP_ORIGIN_EGP:
7307 aggregate->egp_origin_count++;
7308 break;
7309 default:
7310 /* Do nothing.
7311 */
7312 break;
7313 }
7314
7315 if (aggregate->incomplete_origin_count > 0)
7316 origin = BGP_ORIGIN_INCOMPLETE;
7317 else if (aggregate->egp_origin_count > 0)
7318 origin = BGP_ORIGIN_EGP;
7319
229757f1
DA
7320 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7321 origin = aggregate->origin;
7322
fc968841
NT
7323 if (aggregate->as_set) {
7324 /* Compute aggregate route's as-path.
7325 */
7326 bgp_compute_aggregate_aspath(aggregate,
7327 pinew->attr->aspath);
7328
7329 /* Compute aggregate route's community.
7330 */
7331 if (pinew->attr->community)
7332 bgp_compute_aggregate_community(
7333 aggregate,
7334 pinew->attr->community);
7335
7336 /* Compute aggregate route's extended community.
7337 */
7338 if (pinew->attr->ecommunity)
7339 bgp_compute_aggregate_ecommunity(
7340 aggregate,
7341 pinew->attr->ecommunity);
7342
7343 /* Compute aggregate route's large community.
7344 */
7345 if (pinew->attr->lcommunity)
7346 bgp_compute_aggregate_lcommunity(
7347 aggregate,
7348 pinew->attr->lcommunity);
7349
7350 /* Retrieve aggregate route's as-path.
7351 */
7352 if (aggregate->aspath)
7353 aspath = aspath_dup(aggregate->aspath);
7354
7355 /* Retrieve aggregate route's community.
7356 */
7357 if (aggregate->community)
7358 community = community_dup(aggregate->community);
7359
7360 /* Retrieve aggregate route's ecommunity.
7361 */
7362 if (aggregate->ecommunity)
7363 ecommunity = ecommunity_dup(aggregate->ecommunity);
7364
7365 /* Retrieve aggregate route's lcommunity.
7366 */
7367 if (aggregate->lcommunity)
7368 lcommunity = lcommunity_dup(aggregate->lcommunity);
7369 }
7370
7371 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7372 aspath, community, ecommunity,
7373 lcommunity, atomic_aggregate, aggregate);
7374}
7375
7376static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7377 safi_t safi,
7378 struct bgp_path_info *pi,
7379 struct bgp_aggregate *aggregate,
5f040085 7380 const struct prefix *aggr_p)
fc968841
NT
7381{
7382 uint8_t origin;
7383 struct aspath *aspath = NULL;
7384 uint8_t atomic_aggregate = 0;
7385 struct community *community = NULL;
7386 struct ecommunity *ecommunity = NULL;
7387 struct lcommunity *lcommunity = NULL;
7388 unsigned long match = 0;
7389
a4559740 7390 /* If the bgp instance is being deleted or self peer is deleted
7391 * then do not create aggregate route
7392 */
7393 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7394 || (bgp->peer_self == NULL))
7395 return;
7396
fc968841
NT
7397 if (BGP_PATH_HOLDDOWN(pi))
7398 return;
7399
7400 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7401 return;
7402
4056a5f6
RZ
7403 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7404 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7405 match++;
fc968841 7406
365ab2e7 7407 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7408 && aggr_suppress_map_test(bgp, aggregate, pi))
7409 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7410 match++;
fc968841 7411
6aabb15d 7412 /*
365ab2e7 7413 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7414 * "unsuppressing" twice.
7415 */
7416 if (aggregate->match_med)
7417 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7418 true);
7419
fc968841
NT
7420 if (aggregate->count > 0)
7421 aggregate->count--;
7422
7423 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7424 aggregate->incomplete_origin_count--;
7425 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7426 aggregate->egp_origin_count--;
7427
7428 if (aggregate->as_set) {
7429 /* Remove as-path from aggregate.
7430 */
7431 bgp_remove_aspath_from_aggregate(aggregate,
7432 pi->attr->aspath);
7433
7434 if (pi->attr->community)
7435 /* Remove community from aggregate.
7436 */
7437 bgp_remove_community_from_aggregate(
7438 aggregate,
7439 pi->attr->community);
7440
7441 if (pi->attr->ecommunity)
7442 /* Remove ecommunity from aggregate.
7443 */
7444 bgp_remove_ecommunity_from_aggregate(
7445 aggregate,
7446 pi->attr->ecommunity);
7447
7448 if (pi->attr->lcommunity)
7449 /* Remove lcommunity from aggregate.
7450 */
7451 bgp_remove_lcommunity_from_aggregate(
7452 aggregate,
7453 pi->attr->lcommunity);
7454 }
7455
7456 /* If this node was suppressed, process the change. */
7457 if (match)
7458 bgp_process(bgp, pi->net, afi, safi);
7459
7460 origin = BGP_ORIGIN_IGP;
7461 if (aggregate->incomplete_origin_count > 0)
7462 origin = BGP_ORIGIN_INCOMPLETE;
7463 else if (aggregate->egp_origin_count > 0)
7464 origin = BGP_ORIGIN_EGP;
7465
229757f1
DA
7466 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7467 origin = aggregate->origin;
7468
fc968841
NT
7469 if (aggregate->as_set) {
7470 /* Retrieve aggregate route's as-path.
7471 */
7472 if (aggregate->aspath)
7473 aspath = aspath_dup(aggregate->aspath);
7474
7475 /* Retrieve aggregate route's community.
7476 */
7477 if (aggregate->community)
7478 community = community_dup(aggregate->community);
7479
7480 /* Retrieve aggregate route's ecommunity.
7481 */
7482 if (aggregate->ecommunity)
7483 ecommunity = ecommunity_dup(aggregate->ecommunity);
7484
7485 /* Retrieve aggregate route's lcommunity.
7486 */
7487 if (aggregate->lcommunity)
7488 lcommunity = lcommunity_dup(aggregate->lcommunity);
7489 }
7490
7491 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7492 aspath, community, ecommunity,
7493 lcommunity, atomic_aggregate, aggregate);
7494}
7495
5a1ae2c2 7496void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7497 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7498{
9bcb3eef
DS
7499 struct bgp_dest *child;
7500 struct bgp_dest *dest;
d62a17ae 7501 struct bgp_aggregate *aggregate;
7502 struct bgp_table *table;
718e3744 7503
d62a17ae 7504 table = bgp->aggregate[afi][safi];
f018db83 7505
d62a17ae 7506 /* No aggregates configured. */
7507 if (bgp_table_top_nolock(table) == NULL)
7508 return;
f018db83 7509
d62a17ae 7510 if (p->prefixlen == 0)
7511 return;
718e3744 7512
40381db7 7513 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7514 return;
718e3744 7515
a77e2f4b
S
7516 /* If suppress fib is enabled and route not installed
7517 * in FIB, do not update the aggregate route
7518 */
7519 if (!bgp_check_advertise(bgp, pi->net))
7520 return;
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) {
7530 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7531 aggregate);
d62a17ae 7532 }
b1e62edd 7533 }
9bcb3eef 7534 bgp_dest_unlock_node(child);
718e3744 7535}
7536
5a1ae2c2 7537void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7538 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7539{
9bcb3eef
DS
7540 struct bgp_dest *child;
7541 struct bgp_dest *dest;
d62a17ae 7542 struct bgp_aggregate *aggregate;
7543 struct bgp_table *table;
718e3744 7544
d62a17ae 7545 table = bgp->aggregate[afi][safi];
718e3744 7546
d62a17ae 7547 /* No aggregates configured. */
7548 if (bgp_table_top_nolock(table) == NULL)
7549 return;
718e3744 7550
d62a17ae 7551 if (p->prefixlen == 0)
7552 return;
718e3744 7553
d62a17ae 7554 child = bgp_node_get(table, p);
718e3744 7555
d62a17ae 7556 /* Aggregate address configuration check. */
9bcb3eef
DS
7557 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7558 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7559
9bcb3eef
DS
7560 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7561 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7562 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7563 aggregate, dest_p);
d62a17ae 7564 }
b1e62edd 7565 }
9bcb3eef 7566 bgp_dest_unlock_node(child);
d62a17ae 7567}
718e3744 7568
718e3744 7569/* Aggregate route attribute. */
7570#define AGGREGATE_SUMMARY_ONLY 1
7571#define AGGREGATE_AS_SET 1
fb29348a 7572#define AGGREGATE_AS_UNSET 0
718e3744 7573
229757f1
DA
7574static const char *bgp_origin2str(uint8_t origin)
7575{
7576 switch (origin) {
7577 case BGP_ORIGIN_IGP:
7578 return "igp";
7579 case BGP_ORIGIN_EGP:
7580 return "egp";
7581 case BGP_ORIGIN_INCOMPLETE:
7582 return "incomplete";
7583 }
7584 return "n/a";
7585}
7586
fdeb5a81 7587static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7588{
7589 switch (v_state) {
fdeb5a81
DS
7590 case RPKI_NOT_BEING_USED:
7591 return "not used";
7592 case RPKI_VALID:
b5b99af8 7593 return "valid";
fdeb5a81 7594 case RPKI_NOTFOUND:
b5b99af8 7595 return "not found";
fdeb5a81 7596 case RPKI_INVALID:
b5b99af8 7597 return "invalid";
b5b99af8 7598 }
fdeb5a81
DS
7599
7600 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7601 return "ERROR";
7602}
7603
37a87b8f
CS
7604int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7605 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7606{
9bcb3eef 7607 struct bgp_dest *dest;
d62a17ae 7608 struct bgp_aggregate *aggregate;
718e3744 7609
a4559740 7610 /* If the bgp instance is being deleted or self peer is deleted
7611 * then do not create aggregate route
7612 */
7613 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7614 || (bgp->peer_self == NULL))
7615 return 0;
7616
37a87b8f 7617 apply_mask(prefix);
d62a17ae 7618 /* Old configuration check. */
37a87b8f 7619 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7620 if (!dest) {
37a87b8f
CS
7621 snprintf(errmsg, errmsg_len,
7622 "There is no aggregate-address configuration.\n");
7623 return -1;
d62a17ae 7624 }
f6269b4f 7625
9bcb3eef 7626 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7627 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7628 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7629 0, aggregate);
d62a17ae 7630
7631 /* Unlock aggregate address configuration. */
9bcb3eef 7632 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7633
7634 if (aggregate->community)
7635 community_free(&aggregate->community);
7636
7637 if (aggregate->community_hash) {
7638 /* Delete all communities in the hash.
7639 */
7640 hash_clean(aggregate->community_hash,
7641 bgp_aggr_community_remove);
7642 /* Free up the community_hash.
7643 */
7644 hash_free(aggregate->community_hash);
7645 }
7646
7647 if (aggregate->ecommunity)
7648 ecommunity_free(&aggregate->ecommunity);
7649
7650 if (aggregate->ecommunity_hash) {
7651 /* Delete all ecommunities in the hash.
7652 */
7653 hash_clean(aggregate->ecommunity_hash,
7654 bgp_aggr_ecommunity_remove);
7655 /* Free up the ecommunity_hash.
7656 */
7657 hash_free(aggregate->ecommunity_hash);
7658 }
7659
7660 if (aggregate->lcommunity)
7661 lcommunity_free(&aggregate->lcommunity);
7662
7663 if (aggregate->lcommunity_hash) {
7664 /* Delete all lcommunities in the hash.
7665 */
7666 hash_clean(aggregate->lcommunity_hash,
7667 bgp_aggr_lcommunity_remove);
7668 /* Free up the lcommunity_hash.
7669 */
7670 hash_free(aggregate->lcommunity_hash);
7671 }
7672
7673 if (aggregate->aspath)
7674 aspath_free(aggregate->aspath);
7675
7676 if (aggregate->aspath_hash) {
7677 /* Delete all as-paths in the hash.
7678 */
7679 hash_clean(aggregate->aspath_hash,
7680 bgp_aggr_aspath_remove);
7681 /* Free up the aspath_hash.
7682 */
7683 hash_free(aggregate->aspath_hash);
7684 }
7685
d62a17ae 7686 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7687 bgp_dest_unlock_node(dest);
7688 bgp_dest_unlock_node(dest);
d62a17ae 7689
37a87b8f 7690 return 0;
d62a17ae 7691}
7692
37a87b8f
CS
7693int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7694 safi_t safi, const char *rmap, uint8_t summary_only,
7695 uint8_t as_set, uint8_t origin, bool match_med,
7696 const char *suppress_map,
7697 char *errmsg, size_t errmsg_len)
d62a17ae 7698{
d62a17ae 7699 int ret;
9bcb3eef 7700 struct bgp_dest *dest;
d62a17ae 7701 struct bgp_aggregate *aggregate;
fb29348a 7702 uint8_t as_set_new = as_set;
37a87b8f 7703 char buf[PREFIX2STR_BUFFER];
d62a17ae 7704
365ab2e7 7705 if (suppress_map && summary_only) {
37a87b8f 7706 snprintf(errmsg, errmsg_len,
365ab2e7 7707 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7708 return -1;
365ab2e7
RZ
7709 }
7710
37a87b8f 7711 apply_mask(prefix);
d62a17ae 7712
37a87b8f
CS
7713 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7714 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7715 snprintf(
7716 errmsg, errmsg_len,
7717 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7718 prefix2str(prefix, buf, PREFIX_STRLEN));
7719 return -1;
3624ac81
DS
7720 }
7721
d62a17ae 7722 /* Old configuration check. */
37a87b8f 7723 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7724 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7725
20894f50 7726 if (aggregate) {
37a87b8f
CS
7727 snprintf(errmsg, errmsg_len,
7728 "There is already same aggregate network.\n");
d62a17ae 7729 /* try to remove the old entry */
37a87b8f
CS
7730 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7731 errmsg_len);
d62a17ae 7732 if (ret) {
37a87b8f
CS
7733 snprintf(errmsg, errmsg_len,
7734 "Error deleting aggregate.\n");
9bcb3eef 7735 bgp_dest_unlock_node(dest);
37a87b8f 7736 return -1;
d62a17ae 7737 }
7738 }
718e3744 7739
d62a17ae 7740 /* Make aggregate address structure. */
7741 aggregate = bgp_aggregate_new();
7742 aggregate->summary_only = summary_only;
6aabb15d 7743 aggregate->match_med = match_med;
fb29348a
DA
7744
7745 /* Network operators MUST NOT locally generate any new
7746 * announcements containing AS_SET or AS_CONFED_SET. If they have
7747 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7748 * SHOULD withdraw those routes and re-announce routes for the
7749 * aggregate or component prefixes (i.e., the more-specific routes
7750 * subsumed by the previously aggregated route) without AS_SET
7751 * or AS_CONFED_SET in the updates.
7752 */
7f972cd8 7753 if (bgp->reject_as_sets) {
fb29348a
DA
7754 if (as_set == AGGREGATE_AS_SET) {
7755 as_set_new = AGGREGATE_AS_UNSET;
7756 zlog_warn(
63efca0e 7757 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7758 __func__);
37a87b8f
CS
7759 snprintf(
7760 errmsg, errmsg_len,
fb29348a
DA
7761 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7762 }
7763 }
7764
7765 aggregate->as_set = as_set_new;
d62a17ae 7766 aggregate->safi = safi;
229757f1
DA
7767 /* Override ORIGIN attribute if defined.
7768 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7769 * to IGP which is not what rfc4271 says.
7770 * This enables the same behavior, optionally.
7771 */
7772 aggregate->origin = origin;
20894f50
DA
7773
7774 if (rmap) {
7775 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7776 route_map_counter_decrement(aggregate->rmap.map);
7777 aggregate->rmap.name =
7778 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7779 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7780 route_map_counter_increment(aggregate->rmap.map);
7781 }
365ab2e7
RZ
7782
7783 if (suppress_map) {
7784 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7785 route_map_counter_decrement(aggregate->suppress_map);
7786
7787 aggregate->suppress_map_name =
7788 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7789 aggregate->suppress_map =
7790 route_map_lookup_by_name(aggregate->suppress_map_name);
7791 route_map_counter_increment(aggregate->suppress_map);
7792 }
7793
9bcb3eef 7794 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7795
d62a17ae 7796 /* Aggregate address insert into BGP routing table. */
37a87b8f 7797 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7798
37a87b8f 7799 return 0;
718e3744 7800}
7801
37a87b8f
CS
7802DEFPY_YANG(
7803 aggregate_addressv4, aggregate_addressv4_cmd,
7804 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7805 "as-set$as_set_s"
7806 "|summary-only$summary_only"
7807 "|route-map WORD$rmap_name"
7808 "|origin <egp|igp|incomplete>$origin_s"
7809 "|matching-MED-only$match_med"
90e21f35 7810 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7811 "}",
7812 NO_STR
7813 "Configure BGP aggregate entries\n"
7814 "Aggregate prefix\n"
7815 "Aggregate address\n"
7816 "Aggregate mask\n"
7817 "Generate AS set path information\n"
7818 "Filter more specific routes from updates\n"
7819 "Apply route map to aggregate network\n"
7820 "Route map name\n"
7821 "BGP origin code\n"
7822 "Remote EGP\n"
7823 "Local IGP\n"
7824 "Unknown heritage\n"
7825 "Only aggregate routes with matching MED\n"
90e21f35
CS
7826 "Suppress the selected more specific routes\n"
7827 "Route map with the route selectors\n")
37a87b8f
CS
7828{
7829 char base_xpath[XPATH_MAXLEN];
554b3b10 7830 safi_t safi = bgp_node_safi(vty);
554b3b10 7831 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7832
554b3b10 7833 if (addr_str) {
7533cad7
QY
7834 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7835 sizeof(prefix_buf))
554b3b10
RZ
7836 == 0) {
7837 vty_out(vty, "%% Inconsistent address and mask\n");
7838 return CMD_WARNING_CONFIG_FAILED;
7839 }
37a87b8f
CS
7840 } else {
7841 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7842 }
7843
37a87b8f
CS
7844 if (!no && origin_s)
7845 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7846
7847 if (!no && as_set_s)
7848 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7849 else
7850 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7851
7852 if (!no && summary_only)
7853 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7854 "true");
7855 else
7856 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7857 "false");
7858
fa423774
CS
7859 if (!no && match_med)
7860 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7861 else
7862 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7863 "false");
7864
37a87b8f
CS
7865 if (rmap_name)
7866 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7867 rmap_name);
7868 else
7869 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7870 NB_OP_DESTROY, NULL);
7871
90e21f35
CS
7872 if (suppress_map)
7873 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7874 suppress_map);
7875 else
7876 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7877 NULL);
7878
37a87b8f
CS
7879 snprintf(
7880 base_xpath, sizeof(base_xpath),
7881 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7882 yang_afi_safi_value2identity(AFI_IP, safi),
7883 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7884
554b3b10 7885 if (no)
37a87b8f
CS
7886 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7887 else
7888 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7889
7890 return nb_cli_apply_changes(vty, base_xpath);
7891}
7892
7893DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7894 "[no] aggregate-address X:X::X:X/M$prefix {"
7895 "as-set$as_set_s"
7896 "|summary-only$summary_only"
7897 "|route-map WORD$rmap_name"
7898 "|origin <egp|igp|incomplete>$origin_s"
7899 "|matching-MED-only$match_med"
90e21f35 7900 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7901 "}",
7902 NO_STR
7903 "Configure BGP aggregate entries\n"
7904 "Aggregate prefix\n"
7905 "Generate AS set path information\n"
7906 "Filter more specific routes from updates\n"
7907 "Apply route map to aggregate network\n"
7908 "Route map name\n"
7909 "BGP origin code\n"
7910 "Remote EGP\n"
7911 "Local IGP\n"
7912 "Unknown heritage\n"
7913 "Only aggregate routes with matching MED\n"
7914 "Suppress the selected more specific routes\n"
90e21f35 7915 "Route map with the route selectors\n")
37a87b8f
CS
7916{
7917 char base_xpath[XPATH_MAXLEN];
7918 safi_t safi = bgp_node_safi(vty);
7919
7920 if (!no && origin_s)
7921 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7922
7923 if (!no && as_set_s)
7924 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7925 else
7926 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7927
7928 if (!no && summary_only)
7929 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7930 "true");
7931 else
7932 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7933 "false");
7934
fa423774
CS
7935 if (!no && match_med)
7936 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7937 else
7938 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7939 "false");
7940
37a87b8f
CS
7941 if (rmap_name)
7942 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7943 rmap_name);
7944
90e21f35
CS
7945 if (suppress_map)
7946 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7947 suppress_map);
7948 else
7949 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7950 NULL);
7951
37a87b8f
CS
7952 snprintf(
7953 base_xpath, sizeof(base_xpath),
7954 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7955 yang_afi_safi_value2identity(AFI_IP6, safi),
7956 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7957
554b3b10 7958 if (no)
37a87b8f
CS
7959 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7960 else
7961 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7962
37a87b8f
CS
7963 return nb_cli_apply_changes(vty, base_xpath);
7964}
7965
7966void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7967 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7968{
7969 uint8_t origin;
7970
7971 vty_out(vty, " aggregate-address %s",
7972 yang_dnode_get_string(dnode, "./prefix"));
7973
7974 if (yang_dnode_get_bool(dnode, "./as-set"))
7975 vty_out(vty, " as-set");
7976
7977 if (yang_dnode_get_bool(dnode, "./summary-only"))
7978 vty_out(vty, " summary-only");
7979
7980 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7981 vty_out(vty, " route-map %s",
7982 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7983
7984 origin = yang_dnode_get_enum(dnode, "./origin");
7985 if (origin != BGP_ORIGIN_UNSPECIFIED)
7986 vty_out(vty, " origin %s", bgp_origin2str(origin));
7987
fa423774
CS
7988 if (yang_dnode_get_bool(dnode, "./match-med"))
7989 vty_out(vty, " matching-MED-only");
7990
37a87b8f 7991 vty_out(vty, "\n");
718e3744 7992}
7993
718e3744 7994/* Redistribute route treatment. */
d62a17ae 7995void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7996 const union g_addr *nexthop, ifindex_t ifindex,
7997 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7998 uint8_t type, unsigned short instance,
7999 route_tag_t tag)
d62a17ae 8000{
4b7e6066 8001 struct bgp_path_info *new;
40381db7
DS
8002 struct bgp_path_info *bpi;
8003 struct bgp_path_info rmap_path;
9bcb3eef 8004 struct bgp_dest *bn;
d62a17ae 8005 struct attr attr;
8006 struct attr *new_attr;
8007 afi_t afi;
b68885f9 8008 route_map_result_t ret;
d62a17ae 8009 struct bgp_redist *red;
8010
8011 /* Make default attribute. */
8012 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8013 /*
8014 * This must not be NULL to satisfy Coverity SA
8015 */
8016 assert(attr.aspath);
9de1f7ff 8017
a4d82a8a 8018 switch (nhtype) {
9de1f7ff
DS
8019 case NEXTHOP_TYPE_IFINDEX:
8020 break;
8021 case NEXTHOP_TYPE_IPV4:
8022 case NEXTHOP_TYPE_IPV4_IFINDEX:
8023 attr.nexthop = nexthop->ipv4;
8024 break;
8025 case NEXTHOP_TYPE_IPV6:
8026 case NEXTHOP_TYPE_IPV6_IFINDEX:
8027 attr.mp_nexthop_global = nexthop->ipv6;
8028 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8029 break;
8030 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8031 switch (p->family) {
8032 case AF_INET:
9de1f7ff 8033 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8034 break;
8035 case AF_INET6:
9de1f7ff
DS
8036 memset(&attr.mp_nexthop_global, 0,
8037 sizeof(attr.mp_nexthop_global));
74489921 8038 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8039 break;
74489921 8040 }
9de1f7ff 8041 break;
d62a17ae 8042 }
74489921 8043 attr.nh_ifindex = ifindex;
f04a80a5 8044
d62a17ae 8045 attr.med = metric;
8046 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8047 attr.tag = tag;
718e3744 8048
d62a17ae 8049 afi = family2afi(p->family);
6aeb9e78 8050
d62a17ae 8051 red = bgp_redist_lookup(bgp, afi, type, instance);
8052 if (red) {
8053 struct attr attr_new;
718e3744 8054
d62a17ae 8055 /* Copy attribute for modification. */
6f4f49b2 8056 attr_new = attr;
718e3744 8057
d62a17ae 8058 if (red->redist_metric_flag)
8059 attr_new.med = red->redist_metric;
718e3744 8060
d62a17ae 8061 /* Apply route-map. */
8062 if (red->rmap.name) {
40381db7
DS
8063 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8064 rmap_path.peer = bgp->peer_self;
8065 rmap_path.attr = &attr_new;
718e3744 8066
d62a17ae 8067 SET_FLAG(bgp->peer_self->rmap_type,
8068 PEER_RMAP_TYPE_REDISTRIBUTE);
8069
1782514f 8070 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8071
8072 bgp->peer_self->rmap_type = 0;
8073
8074 if (ret == RMAP_DENYMATCH) {
8075 /* Free uninterned attribute. */
8076 bgp_attr_flush(&attr_new);
8077
8078 /* Unintern original. */
8079 aspath_unintern(&attr.aspath);
8080 bgp_redistribute_delete(bgp, p, type, instance);
8081 return;
8082 }
8083 }
8084
637e5ba4 8085 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8086 bgp_attr_add_gshut_community(&attr_new);
8087
d62a17ae 8088 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8089 SAFI_UNICAST, p, NULL);
8090
8091 new_attr = bgp_attr_intern(&attr_new);
8092
9bcb3eef 8093 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8094 if (bpi->peer == bgp->peer_self
8095 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8096 break;
8097
40381db7 8098 if (bpi) {
d62a17ae 8099 /* Ensure the (source route) type is updated. */
40381db7
DS
8100 bpi->type = type;
8101 if (attrhash_cmp(bpi->attr, new_attr)
8102 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8103 bgp_attr_unintern(&new_attr);
8104 aspath_unintern(&attr.aspath);
9bcb3eef 8105 bgp_dest_unlock_node(bn);
d62a17ae 8106 return;
8107 } else {
8108 /* The attribute is changed. */
40381db7 8109 bgp_path_info_set_flag(bn, bpi,
18ee8310 8110 BGP_PATH_ATTR_CHANGED);
d62a17ae 8111
8112 /* Rewrite BGP route information. */
40381db7
DS
8113 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8114 bgp_path_info_restore(bn, bpi);
d62a17ae 8115 else
40381db7
DS
8116 bgp_aggregate_decrement(
8117 bgp, p, bpi, afi, SAFI_UNICAST);
8118 bgp_attr_unintern(&bpi->attr);
8119 bpi->attr = new_attr;
8120 bpi->uptime = bgp_clock();
d62a17ae 8121
8122 /* Process change. */
40381db7 8123 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8124 SAFI_UNICAST);
8125 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8126 bgp_dest_unlock_node(bn);
d62a17ae 8127 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8128
8129 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8130 || (bgp->inst_type
8131 == BGP_INSTANCE_TYPE_DEFAULT)) {
8132
8133 vpn_leak_from_vrf_update(
40381db7 8134 bgp_get_default(), bgp, bpi);
ddb5b488 8135 }
d62a17ae 8136 return;
8137 }
8138 }
8139
8140 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8141 bgp->peer_self, new_attr, bn);
1defdda8 8142 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8143
8144 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8145 bgp_path_info_add(bn, new);
9bcb3eef 8146 bgp_dest_unlock_node(bn);
d62a17ae 8147 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8148
8149 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8150 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8151
8152 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8153 }
d62a17ae 8154 }
8155
8156 /* Unintern original. */
8157 aspath_unintern(&attr.aspath);
718e3744 8158}
8159
d7c0a89a
QY
8160void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8161 unsigned short instance)
718e3744 8162{
d62a17ae 8163 afi_t afi;
9bcb3eef 8164 struct bgp_dest *dest;
40381db7 8165 struct bgp_path_info *pi;
d62a17ae 8166 struct bgp_redist *red;
718e3744 8167
d62a17ae 8168 afi = family2afi(p->family);
718e3744 8169
d62a17ae 8170 red = bgp_redist_lookup(bgp, afi, type, instance);
8171 if (red) {
9bcb3eef
DS
8172 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8173 SAFI_UNICAST, p, NULL);
d62a17ae 8174
9bcb3eef 8175 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8176 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8177 break;
8178
40381db7 8179 if (pi) {
ddb5b488
PZ
8180 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8181 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8182
8183 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8184 bgp, pi);
ddb5b488 8185 }
40381db7 8186 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8187 bgp_path_info_delete(dest, pi);
8188 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8189 }
9bcb3eef 8190 bgp_dest_unlock_node(dest);
d62a17ae 8191 }
8192}
8193
8194/* Withdraw specified route type's route. */
8195void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8196 unsigned short instance)
d62a17ae 8197{
9bcb3eef 8198 struct bgp_dest *dest;
40381db7 8199 struct bgp_path_info *pi;
d62a17ae 8200 struct bgp_table *table;
8201
8202 table = bgp->rib[afi][SAFI_UNICAST];
8203
9bcb3eef
DS
8204 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8205 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8206 if (pi->peer == bgp->peer_self && pi->type == type
8207 && pi->instance == instance)
d62a17ae 8208 break;
8209
40381db7 8210 if (pi) {
ddb5b488
PZ
8211 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8212 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8213
8214 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8215 bgp, pi);
ddb5b488 8216 }
9bcb3eef 8217 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8218 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8219 bgp_path_info_delete(dest, pi);
8220 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8221 }
718e3744 8222 }
718e3744 8223}
6b0655a2 8224
718e3744 8225/* Static function to display route. */
bd494ec5 8226static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8227 json_object *json, bool wide)
718e3744 8228{
be054588 8229 int len = 0;
d62a17ae 8230 char buf[BUFSIZ];
50e05855 8231 char buf2[BUFSIZ];
718e3744 8232
d62a17ae 8233 if (p->family == AF_INET) {
c6462ff4 8234 if (!json) {
8228a9a7 8235 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8236 } else {
8237 json_object_string_add(json, "prefix",
8238 inet_ntop(p->family,
8239 &p->u.prefix, buf,
8240 BUFSIZ));
8241 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8242 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8243 json_object_string_add(json, "network", buf2);
c6462ff4 8244 }
d62a17ae 8245 } else if (p->family == AF_ETHERNET) {
8228a9a7 8246 len = vty_out(vty, "%pFX", p);
b03b8898 8247 } else if (p->family == AF_EVPN) {
57f7feb6 8248 if (!json)
2dbe669b 8249 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8250 else
60466a63 8251 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8252 } else if (p->family == AF_FLOWSPEC) {
8253 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8254 json ?
8255 NLRI_STRING_FORMAT_JSON_SIMPLE :
8256 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8257 } else {
c6462ff4 8258 if (!json)
8228a9a7 8259 len = vty_out(vty, "%pFX", p);
50e05855
AD
8260 else {
8261 json_object_string_add(json, "prefix",
8262 inet_ntop(p->family,
8263 &p->u.prefix, buf,
8264 BUFSIZ));
8265 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8266 prefix2str(p, buf2, PREFIX_STRLEN);
8267 json_object_string_add(json, "network", buf2);
8268 }
9c92b5f7 8269 }
d62a17ae 8270
9c92b5f7 8271 if (!json) {
ae248832 8272 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8273 if (len < 1)
8274 vty_out(vty, "\n%*s", 20, " ");
8275 else
8276 vty_out(vty, "%*s", len, " ");
8277 }
718e3744 8278}
8279
d62a17ae 8280enum bgp_display_type {
8281 normal_list,
718e3744 8282};
8283
bbb46eb5
DA
8284static const char *
8285bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8286{
8287 switch (reason) {
8288 case bgp_path_selection_none:
8289 return "Nothing to Select";
8290 case bgp_path_selection_first:
8291 return "First path received";
8292 case bgp_path_selection_evpn_sticky_mac:
8293 return "EVPN Sticky Mac";
8294 case bgp_path_selection_evpn_seq:
8295 return "EVPN sequence number";
8296 case bgp_path_selection_evpn_lower_ip:
8297 return "EVPN lower IP";
8298 case bgp_path_selection_evpn_local_path:
8299 return "EVPN local ES path";
8300 case bgp_path_selection_evpn_non_proxy:
8301 return "EVPN non proxy";
8302 case bgp_path_selection_weight:
8303 return "Weight";
8304 case bgp_path_selection_local_pref:
8305 return "Local Pref";
8306 case bgp_path_selection_local_route:
8307 return "Local Route";
8308 case bgp_path_selection_confed_as_path:
8309 return "Confederation based AS Path";
8310 case bgp_path_selection_as_path:
8311 return "AS Path";
8312 case bgp_path_selection_origin:
8313 return "Origin";
8314 case bgp_path_selection_med:
8315 return "MED";
8316 case bgp_path_selection_peer:
8317 return "Peer Type";
8318 case bgp_path_selection_confed:
8319 return "Confed Peer Type";
8320 case bgp_path_selection_igp_metric:
8321 return "IGP Metric";
8322 case bgp_path_selection_older:
8323 return "Older Path";
8324 case bgp_path_selection_router_id:
8325 return "Router ID";
8326 case bgp_path_selection_cluster_length:
bcab253c 8327 return "Cluster length";
bbb46eb5
DA
8328 case bgp_path_selection_stale:
8329 return "Path Staleness";
8330 case bgp_path_selection_local_configured:
8331 return "Locally configured route";
8332 case bgp_path_selection_neighbor_ip:
8333 return "Neighbor IP";
8334 case bgp_path_selection_default:
8335 return "Nothing left to compare";
8336 }
8337 return "Invalid (internal error)";
8338}
8339
18ee8310 8340/* Print the short form route status for a bgp_path_info */
4b7e6066 8341static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8342 struct bgp_path_info *path,
d62a17ae 8343 json_object *json_path)
718e3744 8344{
d62a17ae 8345 if (json_path) {
b05a1c8b 8346
d62a17ae 8347 /* Route status display. */
9b6d8fcf 8348 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8349 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8350
9b6d8fcf 8351 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8352 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8353
4056a5f6 8354 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8355 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8356
9b6d8fcf
DS
8357 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8358 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8359 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8360
d62a17ae 8361 /* Selected */
9b6d8fcf 8362 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8363 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8364
9b6d8fcf 8365 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8366 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8367
bbb46eb5 8368 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8369 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8370 json_object_string_add(json_path, "selectionReason",
8371 bgp_path_selection_reason2str(
8372 path->net->reason));
8373 }
b05a1c8b 8374
9b6d8fcf 8375 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8376 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8377
d62a17ae 8378 /* Internal route. */
9b6d8fcf
DS
8379 if ((path->peer->as)
8380 && (path->peer->as == path->peer->local_as))
d62a17ae 8381 json_object_string_add(json_path, "pathFrom",
8382 "internal");
8383 else
8384 json_object_string_add(json_path, "pathFrom",
8385 "external");
b05a1c8b 8386
d62a17ae 8387 return;
8388 }
b05a1c8b 8389
d62a17ae 8390 /* Route status display. */
9b6d8fcf 8391 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8392 vty_out(vty, "R");
9b6d8fcf 8393 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8394 vty_out(vty, "S");
4056a5f6 8395 else if (bgp_path_suppressed(path))
d62a17ae 8396 vty_out(vty, "s");
9b6d8fcf
DS
8397 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8398 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8399 vty_out(vty, "*");
8400 else
8401 vty_out(vty, " ");
8402
8403 /* Selected */
9b6d8fcf 8404 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8405 vty_out(vty, "h");
9b6d8fcf 8406 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8407 vty_out(vty, "d");
9b6d8fcf 8408 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8409 vty_out(vty, ">");
9b6d8fcf 8410 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8411 vty_out(vty, "=");
8412 else
8413 vty_out(vty, " ");
718e3744 8414
d62a17ae 8415 /* Internal route. */
9b6d8fcf
DS
8416 if (path->peer && (path->peer->as)
8417 && (path->peer->as == path->peer->local_as))
d62a17ae 8418 vty_out(vty, "i");
8419 else
8420 vty_out(vty, " ");
b40d939b 8421}
8422
2ba93fd6
DA
8423static char *bgp_nexthop_hostname(struct peer *peer,
8424 struct bgp_nexthop_cache *bnc)
25b5da8d 8425{
892fedb6 8426 if (peer->hostname
aef999a2 8427 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8428 return peer->hostname;
8429 return NULL;
8430}
8431
b40d939b 8432/* called from terminal list command */
bd494ec5 8433void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8434 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8435 json_object *json_paths, bool wide)
d62a17ae 8436{
aef999a2 8437 int len;
515c2602 8438 struct attr *attr = path->attr;
d62a17ae 8439 json_object *json_path = NULL;
8440 json_object *json_nexthops = NULL;
8441 json_object *json_nexthop_global = NULL;
8442 json_object *json_nexthop_ll = NULL;
6f214dd3 8443 json_object *json_ext_community = NULL;
9df8b37c 8444 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8445 bool nexthop_self =
9b6d8fcf 8446 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8447 bool nexthop_othervrf = false;
43089216 8448 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8449 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8450 char *nexthop_hostname =
8451 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8452 char esi_buf[ESI_STR_LEN];
d62a17ae 8453
8454 if (json_paths)
8455 json_path = json_object_new_object();
8456
8457 /* short status lead text */
9b6d8fcf 8458 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8459
8460 if (!json_paths) {
8461 /* print prefix and mask */
8462 if (!display)
ae248832 8463 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8464 else
ae248832 8465 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8466 } else {
ae248832 8467 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8468 }
47fc97cc 8469
9df8b37c
PZ
8470 /*
8471 * If vrf id of nexthop is different from that of prefix,
8472 * set up printable string to append
8473 */
9b6d8fcf 8474 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8475 const char *self = "";
8476
8477 if (nexthop_self)
8478 self = "<";
8479
8480 nexthop_othervrf = true;
9b6d8fcf 8481 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8482
9b6d8fcf 8483 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8484 snprintf(vrf_id_str, sizeof(vrf_id_str),
8485 "@%s%s", VRFID_NONE_STR, self);
8486 else
8487 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8488 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8489
9b6d8fcf
DS
8490 if (path->extra->bgp_orig->inst_type
8491 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8492
9b6d8fcf 8493 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8494 } else {
8495 const char *self = "";
8496
8497 if (nexthop_self)
8498 self = "<";
8499
8500 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8501 }
8502
445c2480
DS
8503 /*
8504 * For ENCAP and EVPN routes, nexthop address family is not
8505 * neccessarily the same as the prefix address family.
8506 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8507 * EVPN routes are also exchanged with a MP nexthop. Currently,
8508 * this
8509 * is only IPv4, the value will be present in either
8510 * attr->nexthop or
8511 * attr->mp_nexthop_global_in
8512 */
8513 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8514 char buf[BUFSIZ];
8515 char nexthop[128];
8516 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8517
8518 switch (af) {
8519 case AF_INET:
772270f3
QY
8520 snprintf(nexthop, sizeof(nexthop), "%s",
8521 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8522 BUFSIZ));
445c2480
DS
8523 break;
8524 case AF_INET6:
772270f3
QY
8525 snprintf(nexthop, sizeof(nexthop), "%s",
8526 inet_ntop(af, &attr->mp_nexthop_global, buf,
8527 BUFSIZ));
445c2480
DS
8528 break;
8529 default:
772270f3 8530 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8531 break;
d62a17ae 8532 }
d62a17ae 8533
445c2480
DS
8534 if (json_paths) {
8535 json_nexthop_global = json_object_new_object();
8536
515c2602
DA
8537 json_object_string_add(json_nexthop_global, "ip",
8538 nexthop);
8539
939a97f4 8540 if (path->peer->hostname)
515c2602
DA
8541 json_object_string_add(json_nexthop_global,
8542 "hostname",
939a97f4 8543 path->peer->hostname);
515c2602
DA
8544
8545 json_object_string_add(json_nexthop_global, "afi",
8546 (af == AF_INET) ? "ipv4"
8547 : "ipv6");
445c2480
DS
8548 json_object_boolean_true_add(json_nexthop_global,
8549 "used");
aef999a2
DA
8550 } else {
8551 if (nexthop_hostname)
8552 len = vty_out(vty, "%s(%s)%s", nexthop,
8553 nexthop_hostname, vrf_id_str);
8554 else
8555 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8556
ae248832 8557 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8558 if (len < 1)
8559 vty_out(vty, "\n%*s", 36, " ");
8560 else
8561 vty_out(vty, "%*s", len, " ");
8562 }
445c2480
DS
8563 } else if (safi == SAFI_EVPN) {
8564 if (json_paths) {
23d0a753
DA
8565 char buf[BUFSIZ] = {0};
8566
445c2480
DS
8567 json_nexthop_global = json_object_new_object();
8568
515c2602 8569 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8570 inet_ntop(AF_INET,
8571 &attr->nexthop, buf,
8572 sizeof(buf)));
515c2602 8573
939a97f4 8574 if (path->peer->hostname)
515c2602
DA
8575 json_object_string_add(json_nexthop_global,
8576 "hostname",
939a97f4 8577 path->peer->hostname);
515c2602 8578
a4d82a8a
PZ
8579 json_object_string_add(json_nexthop_global, "afi",
8580 "ipv4");
445c2480
DS
8581 json_object_boolean_true_add(json_nexthop_global,
8582 "used");
aef999a2
DA
8583 } else {
8584 if (nexthop_hostname)
8585 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8586 nexthop_hostname, vrf_id_str);
8587 else
8588 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8589 vrf_id_str);
8590
ae248832 8591 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8592 if (len < 1)
8593 vty_out(vty, "\n%*s", 36, " ");
8594 else
8595 vty_out(vty, "%*s", len, " ");
8596 }
d33fc23b 8597 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8598 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8599 if (json_paths) {
23d0a753
DA
8600 char buf[BUFSIZ] = {0};
8601
026b914a 8602 json_nexthop_global = json_object_new_object();
515c2602 8603
026b914a
PG
8604 json_object_string_add(json_nexthop_global,
8605 "afi", "ipv4");
515c2602
DA
8606 json_object_string_add(
8607 json_nexthop_global, "ip",
23d0a753
DA
8608 inet_ntop(AF_INET, &attr->nexthop, buf,
8609 sizeof(buf)));
515c2602 8610
939a97f4 8611 if (path->peer->hostname)
515c2602
DA
8612 json_object_string_add(
8613 json_nexthop_global, "hostname",
939a97f4 8614 path->peer->hostname);
515c2602 8615
50e05855
AD
8616 json_object_boolean_true_add(
8617 json_nexthop_global,
026b914a
PG
8618 "used");
8619 } else {
aef999a2
DA
8620 if (nexthop_hostname)
8621 len = vty_out(vty, "%pI4(%s)%s",
8622 &attr->nexthop,
8623 nexthop_hostname,
8624 vrf_id_str);
8625 else
8626 len = vty_out(vty, "%pI4%s",
8627 &attr->nexthop,
8628 vrf_id_str);
8629
ae248832 8630 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8631 if (len < 1)
8632 vty_out(vty, "\n%*s", 36, " ");
8633 else
8634 vty_out(vty, "%*s", len, " ");
026b914a
PG
8635 }
8636 }
d33fc23b 8637 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8638 if (json_paths) {
23d0a753
DA
8639 char buf[BUFSIZ] = {0};
8640
445c2480 8641 json_nexthop_global = json_object_new_object();
d62a17ae 8642
515c2602 8643 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8644 inet_ntop(AF_INET,
8645 &attr->nexthop, buf,
8646 sizeof(buf)));
515c2602 8647
939a97f4 8648 if (path->peer->hostname)
515c2602
DA
8649 json_object_string_add(json_nexthop_global,
8650 "hostname",
939a97f4 8651 path->peer->hostname);
445c2480 8652
a4d82a8a
PZ
8653 json_object_string_add(json_nexthop_global, "afi",
8654 "ipv4");
445c2480
DS
8655 json_object_boolean_true_add(json_nexthop_global,
8656 "used");
8657 } else {
aef999a2
DA
8658 if (nexthop_hostname)
8659 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8660 nexthop_hostname, vrf_id_str);
8661 else
8662 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8663 vrf_id_str);
9df8b37c 8664
ae248832 8665 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8666 if (len < 1)
8667 vty_out(vty, "\n%*s", 36, " ");
8668 else
8669 vty_out(vty, "%*s", len, " ");
d62a17ae 8670 }
445c2480 8671 }
b05a1c8b 8672
445c2480 8673 /* IPv6 Next Hop */
a4d82a8a 8674 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8675 char buf[BUFSIZ];
d62a17ae 8676
445c2480
DS
8677 if (json_paths) {
8678 json_nexthop_global = json_object_new_object();
a4d82a8a 8679 json_object_string_add(
515c2602
DA
8680 json_nexthop_global, "ip",
8681 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8682 buf, BUFSIZ));
8683
939a97f4 8684 if (path->peer->hostname)
515c2602
DA
8685 json_object_string_add(json_nexthop_global,
8686 "hostname",
939a97f4 8687 path->peer->hostname);
515c2602 8688
a4d82a8a
PZ
8689 json_object_string_add(json_nexthop_global, "afi",
8690 "ipv6");
8691 json_object_string_add(json_nexthop_global, "scope",
8692 "global");
445c2480
DS
8693
8694 /* We display both LL & GL if both have been
8695 * received */
0606039c
DA
8696 if ((attr->mp_nexthop_len
8697 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8698 || (path->peer->conf_if)) {
a4d82a8a 8699 json_nexthop_ll = json_object_new_object();
d62a17ae 8700 json_object_string_add(
515c2602
DA
8701 json_nexthop_ll, "ip",
8702 inet_ntop(AF_INET6,
8703 &attr->mp_nexthop_local, buf,
8704 BUFSIZ));
8705
939a97f4 8706 if (path->peer->hostname)
515c2602
DA
8707 json_object_string_add(
8708 json_nexthop_ll, "hostname",
939a97f4 8709 path->peer->hostname);
515c2602 8710
a4d82a8a
PZ
8711 json_object_string_add(json_nexthop_ll, "afi",
8712 "ipv6");
8713 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8714 "link-local");
d62a17ae 8715
a4d82a8a
PZ
8716 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8717 &attr->mp_nexthop_local)
445c2480
DS
8718 != 0)
8719 && !attr->mp_nexthop_prefer_global)
d62a17ae 8720 json_object_boolean_true_add(
a4d82a8a 8721 json_nexthop_ll, "used");
445c2480
DS
8722 else
8723 json_object_boolean_true_add(
a4d82a8a 8724 json_nexthop_global, "used");
445c2480
DS
8725 } else
8726 json_object_boolean_true_add(
8727 json_nexthop_global, "used");
8728 } else {
8729 /* Display LL if LL/Global both in table unless
8730 * prefer-global is set */
0606039c
DA
8731 if (((attr->mp_nexthop_len
8732 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8733 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8734 || (path->peer->conf_if)) {
8735 if (path->peer->conf_if) {
a4d82a8a 8736 len = vty_out(vty, "%s",
9b6d8fcf 8737 path->peer->conf_if);
ae248832
MK
8738 /* len of IPv6 addr + max len of def
8739 * ifname */
8740 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8741
8742 if (len < 1)
a4d82a8a 8743 vty_out(vty, "\n%*s", 36, " ");
445c2480 8744 else
a4d82a8a 8745 vty_out(vty, "%*s", len, " ");
d62a17ae 8746 } else {
aef999a2
DA
8747 if (nexthop_hostname)
8748 len = vty_out(
8749 vty, "%pI6(%s)%s",
8750 &attr->mp_nexthop_local,
8751 nexthop_hostname,
8752 vrf_id_str);
8753 else
8754 len = vty_out(
8755 vty, "%pI6%s",
8756 &attr->mp_nexthop_local,
8757 vrf_id_str);
8758
ae248832 8759 len = wide ? (41 - len) : (16 - len);
d62a17ae 8760
8761 if (len < 1)
a4d82a8a 8762 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8763 else
a4d82a8a 8764 vty_out(vty, "%*s", len, " ");
d62a17ae 8765 }
445c2480 8766 } else {
aef999a2
DA
8767 if (nexthop_hostname)
8768 len = vty_out(vty, "%pI6(%s)%s",
8769 &attr->mp_nexthop_global,
8770 nexthop_hostname,
8771 vrf_id_str);
8772 else
8773 len = vty_out(vty, "%pI6%s",
8774 &attr->mp_nexthop_global,
8775 vrf_id_str);
8776
ae248832 8777 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8778
8779 if (len < 1)
8780 vty_out(vty, "\n%*s", 36, " ");
8781 else
8782 vty_out(vty, "%*s", len, " ");
d62a17ae 8783 }
8784 }
445c2480 8785 }
718e3744 8786
445c2480
DS
8787 /* MED/Metric */
8788 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8789 if (json_paths)
50e05855 8790 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8791 else if (wide)
8792 vty_out(vty, "%7u", attr->med);
0fbac0b4 8793 else
445c2480 8794 vty_out(vty, "%10u", attr->med);
ae248832
MK
8795 else if (!json_paths) {
8796 if (wide)
8797 vty_out(vty, "%*s", 7, " ");
8798 else
8799 vty_out(vty, "%*s", 10, " ");
8800 }
d62a17ae 8801
445c2480
DS
8802 /* Local Pref */
8803 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8804 if (json_paths)
50e05855 8805 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8806 attr->local_pref);
8807 else
445c2480
DS
8808 vty_out(vty, "%7u", attr->local_pref);
8809 else if (!json_paths)
8810 vty_out(vty, " ");
d62a17ae 8811
445c2480
DS
8812 if (json_paths)
8813 json_object_int_add(json_path, "weight", attr->weight);
8814 else
8815 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8816
445c2480
DS
8817 if (json_paths) {
8818 char buf[BUFSIZ];
a4d82a8a
PZ
8819 json_object_string_add(
8820 json_path, "peerId",
9b6d8fcf 8821 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8822 }
b05a1c8b 8823
445c2480
DS
8824 /* Print aspath */
8825 if (attr->aspath) {
0fbac0b4 8826 if (json_paths)
50e05855 8827 json_object_string_add(json_path, "path",
0fbac0b4
DA
8828 attr->aspath->str);
8829 else
445c2480 8830 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8831 }
f1aa5d8a 8832
445c2480
DS
8833 /* Print origin */
8834 if (json_paths)
a4d82a8a
PZ
8835 json_object_string_add(json_path, "origin",
8836 bgp_origin_long_str[attr->origin]);
445c2480
DS
8837 else
8838 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8839
9df8b37c 8840 if (json_paths) {
d071f237 8841 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8842 json_object_string_add(json_path, "esi",
8843 esi_to_str(&attr->esi,
8844 esi_buf, sizeof(esi_buf)));
8845 }
6f214dd3
CS
8846 if (safi == SAFI_EVPN &&
8847 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8848 json_ext_community = json_object_new_object();
8849 json_object_string_add(json_ext_community,
8850 "string",
8851 attr->ecommunity->str);
8852 json_object_object_add(json_path,
8853 "extendedCommunity",
8854 json_ext_community);
8855 }
8856
9df8b37c
PZ
8857 if (nexthop_self)
8858 json_object_boolean_true_add(json_path,
8859 "announceNexthopSelf");
8860 if (nexthop_othervrf) {
8861 json_object_string_add(json_path, "nhVrfName",
8862 nexthop_vrfname);
8863
8864 json_object_int_add(json_path, "nhVrfId",
8865 ((nexthop_vrfid == VRF_UNKNOWN)
8866 ? -1
8867 : (int)nexthop_vrfid));
8868 }
8869 }
8870
d62a17ae 8871 if (json_paths) {
8872 if (json_nexthop_global || json_nexthop_ll) {
8873 json_nexthops = json_object_new_array();
f1aa5d8a 8874
d62a17ae 8875 if (json_nexthop_global)
8876 json_object_array_add(json_nexthops,
8877 json_nexthop_global);
f1aa5d8a 8878
d62a17ae 8879 if (json_nexthop_ll)
8880 json_object_array_add(json_nexthops,
8881 json_nexthop_ll);
f1aa5d8a 8882
d62a17ae 8883 json_object_object_add(json_path, "nexthops",
8884 json_nexthops);
8885 }
8886
8887 json_object_array_add(json_paths, json_path);
8888 } else {
8889 vty_out(vty, "\n");
6f214dd3 8890
b5e140c8 8891 if (safi == SAFI_EVPN) {
229587fb
AK
8892 struct bgp_path_es_info *path_es_info = NULL;
8893
d071f237 8894 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8895 /* XXX - add these params to the json out */
b5e140c8 8896 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8897 vty_out(vty, "ESI:%s",
8898 esi_to_str(&attr->esi, esi_buf,
8899 sizeof(esi_buf)));
60605cbc
AK
8900
8901 if (path->extra && path->extra->mh_info)
8902 path_es_info =
8903 path->extra->mh_info->es_info;
8904
229587fb
AK
8905 if (path_es_info && path_es_info->es)
8906 vty_out(vty, " VNI: %u",
8907 path_es_info->vni);
8908 vty_out(vty, "\n");
b5e140c8
AK
8909 }
8910 if (attr->flag &
8911 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8912 vty_out(vty, "%*s", 20, " ");
8913 vty_out(vty, "%s\n", attr->ecommunity->str);
8914 }
6f214dd3
CS
8915 }
8916
49e5a4a0 8917#ifdef ENABLE_BGP_VNC
d62a17ae 8918 /* prints an additional line, indented, with VNC info, if
8919 * present */
8920 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8921 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8922#endif
d62a17ae 8923 }
8924}
718e3744 8925
8926/* called from terminal list command */
5f040085
DS
8927void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8928 struct attr *attr, safi_t safi, bool use_json,
ae248832 8929 json_object *json_ar, bool wide)
d62a17ae 8930{
8931 json_object *json_status = NULL;
8932 json_object *json_net = NULL;
aef999a2 8933 int len;
d62a17ae 8934 char buff[BUFSIZ];
dc387b0f 8935
d62a17ae 8936 /* Route status display. */
8937 if (use_json) {
8938 json_status = json_object_new_object();
8939 json_net = json_object_new_object();
8940 } else {
8941 vty_out(vty, "*");
8942 vty_out(vty, ">");
8943 vty_out(vty, " ");
8944 }
718e3744 8945
d62a17ae 8946 /* print prefix and mask */
50e05855 8947 if (use_json) {
dc387b0f
LK
8948 if (safi == SAFI_EVPN)
8949 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8950 else if (p->family == AF_INET || p->family == AF_INET6) {
8951 json_object_string_add(
8952 json_net, "addrPrefix",
8953 inet_ntop(p->family, &p->u.prefix, buff,
8954 BUFSIZ));
8955 json_object_int_add(json_net, "prefixLen",
8956 p->prefixlen);
8957 prefix2str(p, buff, PREFIX_STRLEN);
8958 json_object_string_add(json_net, "network", buff);
8959 }
50e05855 8960 } else
ae248832 8961 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8962
8963 /* Print attribute */
8964 if (attr) {
8965 if (use_json) {
23d0a753
DA
8966 char buf[BUFSIZ] = {0};
8967
d62a17ae 8968 if (p->family == AF_INET
8969 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8970 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8971 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8972 json_object_string_add(
8973 json_net, "nextHop",
23d0a753
DA
8974 inet_ntop(
8975 AF_INET,
8976 &attr->mp_nexthop_global_in,
8977 buf, sizeof(buf)));
d62a17ae 8978 else
8979 json_object_string_add(
8980 json_net, "nextHop",
23d0a753
DA
8981 inet_ntop(AF_INET,
8982 &attr->nexthop, buf,
8983 sizeof(buf)));
d62a17ae 8984 } else if (p->family == AF_INET6
8985 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8986 char buf[BUFSIZ];
8987
8988 json_object_string_add(
aa0a10fc 8989 json_net, "nextHopGlobal",
d62a17ae 8990 inet_ntop(AF_INET6,
8991 &attr->mp_nexthop_global, buf,
8992 BUFSIZ));
23d0a753
DA
8993 } else if (p->family == AF_EVPN
8994 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8995 char buf[BUFSIZ] = {0};
8996
8997 json_object_string_add(
8998 json_net, "nextHop",
8999 inet_ntop(AF_INET,
9000 &attr->mp_nexthop_global_in,
9001 buf, sizeof(buf)));
9002 }
d62a17ae 9003
9004 if (attr->flag
9005 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9006 json_object_int_add(json_net, "metric",
9007 attr->med);
9008
0fbac0b4 9009 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9010 json_object_int_add(json_net, "locPrf",
0fbac0b4 9011 attr->local_pref);
d62a17ae 9012
9013 json_object_int_add(json_net, "weight", attr->weight);
9014
9015 /* Print aspath */
0fbac0b4 9016 if (attr->aspath)
50e05855 9017 json_object_string_add(json_net, "path",
0fbac0b4 9018 attr->aspath->str);
d62a17ae 9019
9020 /* Print origin */
9021 json_object_string_add(json_net, "bgpOriginCode",
9022 bgp_origin_str[attr->origin]);
9023 } else {
9024 if (p->family == AF_INET
9025 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9026 || safi == SAFI_EVPN
9027 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9028 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9029 || safi == SAFI_EVPN)
23d0a753
DA
9030 vty_out(vty, "%-16pI4",
9031 &attr->mp_nexthop_global_in);
ae248832 9032 else if (wide)
23d0a753 9033 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9034 else
23d0a753 9035 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9036 } else if (p->family == AF_INET6
9037 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9038 char buf[BUFSIZ];
9039
9040 len = vty_out(
9041 vty, "%s",
9042 inet_ntop(AF_INET6,
9043 &attr->mp_nexthop_global, buf,
9044 BUFSIZ));
ae248832 9045 len = wide ? (41 - len) : (16 - len);
d62a17ae 9046 if (len < 1)
9047 vty_out(vty, "\n%*s", 36, " ");
9048 else
9049 vty_out(vty, "%*s", len, " ");
9050 }
9051 if (attr->flag
9052 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9053 if (wide)
9054 vty_out(vty, "%7u", attr->med);
9055 else
9056 vty_out(vty, "%10u", attr->med);
9057 else if (wide)
9058 vty_out(vty, " ");
d62a17ae 9059 else
9060 vty_out(vty, " ");
718e3744 9061
d62a17ae 9062 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9063 vty_out(vty, "%7u", attr->local_pref);
9064 else
9065 vty_out(vty, " ");
9066
9067 vty_out(vty, "%7u ", attr->weight);
9068
9069 /* Print aspath */
9070 if (attr->aspath)
9071 aspath_print_vty(vty, "%s", attr->aspath, " ");
9072
9073 /* Print origin */
9074 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9075 }
9076 }
9077 if (use_json) {
9078 json_object_boolean_true_add(json_status, "*");
9079 json_object_boolean_true_add(json_status, ">");
9080 json_object_object_add(json_net, "appliedStatusSymbols",
9081 json_status);
1608ff77 9082
dc387b0f
LK
9083 prefix2str(p, buff, PREFIX_STRLEN);
9084 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9085 } else
9086 vty_out(vty, "\n");
9087}
9088
bd494ec5 9089void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9090 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9091 json_object *json)
9092{
9093 json_object *json_out = NULL;
9094 struct attr *attr;
9095 mpls_label_t label = MPLS_INVALID_LABEL;
9096
9b6d8fcf 9097 if (!path->extra)
d62a17ae 9098 return;
9099
9100 if (json)
9101 json_out = json_object_new_object();
9102
9103 /* short status lead text */
9b6d8fcf 9104 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9105
9106 /* print prefix and mask */
9107 if (json == NULL) {
9108 if (!display)
ae248832 9109 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9110 else
9111 vty_out(vty, "%*s", 17, " ");
9112 }
9113
9114 /* Print attribute */
9b6d8fcf 9115 attr = path->attr;
05864da7
DS
9116 if (((p->family == AF_INET)
9117 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9118 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9119 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9120 char buf[BUFSIZ] = {0};
9121
05864da7
DS
9122 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9123 || safi == SAFI_EVPN) {
9124 if (json)
9125 json_object_string_add(
9126 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9127 inet_ntop(AF_INET,
9128 &attr->mp_nexthop_global_in,
9129 buf, sizeof(buf)));
05864da7 9130 else
23d0a753
DA
9131 vty_out(vty, "%-16pI4",
9132 &attr->mp_nexthop_global_in);
05864da7
DS
9133 } else {
9134 if (json)
9135 json_object_string_add(
9136 json_out, "nexthop",
23d0a753
DA
9137 inet_ntop(AF_INET, &attr->nexthop, buf,
9138 sizeof(buf)));
05864da7 9139 else
23d0a753 9140 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9141 }
9142 } else if (((p->family == AF_INET6)
9143 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9144 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9145 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9146 char buf_a[512];
9147
9148 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9149 if (json)
9150 json_object_string_add(
9151 json_out, "mpNexthopGlobalIn",
9152 inet_ntop(AF_INET6,
9153 &attr->mp_nexthop_global,
9154 buf_a, sizeof(buf_a)));
9155 else
9156 vty_out(vty, "%s",
9157 inet_ntop(AF_INET6,
9158 &attr->mp_nexthop_global,
9159 buf_a, sizeof(buf_a)));
9160 } else if (attr->mp_nexthop_len
9161 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9162 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9163 &attr->mp_nexthop_global,
9164 &attr->mp_nexthop_local);
9165 if (json)
9166 json_object_string_add(json_out,
9167 "mpNexthopGlobalLocal",
9168 buf_a);
9169 else
9170 vty_out(vty, "%s", buf_a);
d62a17ae 9171 }
9172 }
9173
9b6d8fcf 9174 label = decode_label(&path->extra->label[0]);
d62a17ae 9175
9176 if (bgp_is_valid_label(&label)) {
9177 if (json) {
9178 json_object_int_add(json_out, "notag", label);
9179 json_object_array_add(json, json_out);
9180 } else {
9181 vty_out(vty, "notag/%d", label);
9182 vty_out(vty, "\n");
9183 }
9184 }
9185}
718e3744 9186
bd494ec5 9187void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9188 struct bgp_path_info *path, int display,
d62a17ae 9189 json_object *json_paths)
718e3744 9190{
d62a17ae 9191 struct attr *attr;
14f51eba 9192 char buf[BUFSIZ] = {0};
d62a17ae 9193 json_object *json_path = NULL;
14f51eba
LK
9194 json_object *json_nexthop = NULL;
9195 json_object *json_overlay = NULL;
856ca177 9196
9b6d8fcf 9197 if (!path->extra)
d62a17ae 9198 return;
718e3744 9199
14f51eba
LK
9200 if (json_paths) {
9201 json_path = json_object_new_object();
9202 json_overlay = json_object_new_object();
9203 json_nexthop = json_object_new_object();
9204 }
9205
d62a17ae 9206 /* short status lead text */
9b6d8fcf 9207 route_vty_short_status_out(vty, path, json_path);
856ca177 9208
d62a17ae 9209 /* print prefix and mask */
9210 if (!display)
ae248832 9211 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9212 else
9213 vty_out(vty, "%*s", 17, " ");
9214
9215 /* Print attribute */
9b6d8fcf 9216 attr = path->attr;
05864da7
DS
9217 char buf1[BUFSIZ];
9218 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9219
05864da7
DS
9220 switch (af) {
9221 case AF_INET:
9222 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9223 if (!json_path) {
9224 vty_out(vty, "%-16s", buf);
9225 } else {
9226 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9227
05864da7 9228 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9229
05864da7
DS
9230 json_object_object_add(json_path, "nexthop",
9231 json_nexthop);
9232 }
9233 break;
9234 case AF_INET6:
9235 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9236 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9237 if (!json_path) {
9238 vty_out(vty, "%s(%s)", buf, buf1);
9239 } else {
9240 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9241
05864da7
DS
9242 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9243 buf1);
14f51eba 9244
05864da7 9245 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9246
05864da7
DS
9247 json_object_object_add(json_path, "nexthop",
9248 json_nexthop);
9249 }
9250 break;
9251 default:
9252 if (!json_path) {
9253 vty_out(vty, "?");
9254 } else {
9255 json_object_string_add(json_nexthop, "Error",
9256 "Unsupported address-family");
d62a17ae 9257 }
05864da7 9258 }
988258b4 9259
6c924775
DS
9260 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9261
9262 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9263 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9264 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9265 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9266
05864da7
DS
9267 if (!json_path)
9268 vty_out(vty, "/%s", buf);
9269 else
9270 json_object_string_add(json_overlay, "gw", buf);
9271
9272 if (attr->ecommunity) {
9273 char *mac = NULL;
9274 struct ecommunity_val *routermac = ecommunity_lookup(
9275 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9276 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9277
9278 if (routermac)
9279 mac = ecom_mac2str((char *)routermac->val);
9280 if (mac) {
9281 if (!json_path) {
c4efd0f4 9282 vty_out(vty, "/%s", mac);
05864da7
DS
9283 } else {
9284 json_object_string_add(json_overlay, "rmac",
9285 mac);
988258b4 9286 }
05864da7 9287 XFREE(MTYPE_TMP, mac);
988258b4 9288 }
05864da7 9289 }
718e3744 9290
05864da7
DS
9291 if (!json_path) {
9292 vty_out(vty, "\n");
9293 } else {
9294 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9295
05864da7 9296 json_object_array_add(json_paths, json_path);
14f51eba 9297 }
d62a17ae 9298}
718e3744 9299
d62a17ae 9300/* dampening route */
5f040085
DS
9301static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9302 struct bgp_path_info *path, int display,
9303 afi_t afi, safi_t safi, bool use_json,
9304 json_object *json)
d62a17ae 9305{
9306 struct attr *attr;
9307 int len;
9308 char timebuf[BGP_UPTIME_LEN];
9309
9310 /* short status lead text */
9b6d8fcf 9311 route_vty_short_status_out(vty, path, json);
d62a17ae 9312
9313 /* print prefix and mask */
9314 if (!use_json) {
9315 if (!display)
ae248832 9316 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9317 else
9318 vty_out(vty, "%*s", 17, " ");
9319 }
9320
9b6d8fcf 9321 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9322 len = 17 - len;
9323 if (len < 1) {
9324 if (!use_json)
9325 vty_out(vty, "\n%*s", 34, " ");
9326 } else {
9327 if (use_json)
9328 json_object_int_add(json, "peerHost", len);
9329 else
9330 vty_out(vty, "%*s", len, " ");
9331 }
9332
9333 if (use_json)
a935f597
DA
9334 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9335 safi, use_json, json);
d62a17ae 9336 else
9b6d8fcf
DS
9337 vty_out(vty, "%s ",
9338 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9339 BGP_UPTIME_LEN, afi, safi,
9340 use_json, json));
d62a17ae 9341
9342 /* Print attribute */
9b6d8fcf 9343 attr = path->attr;
d62a17ae 9344
05864da7
DS
9345 /* Print aspath */
9346 if (attr->aspath) {
d62a17ae 9347 if (use_json)
05864da7
DS
9348 json_object_string_add(json, "asPath",
9349 attr->aspath->str);
d62a17ae 9350 else
05864da7 9351 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9352 }
05864da7
DS
9353
9354 /* Print origin */
9355 if (use_json)
9356 json_object_string_add(json, "origin",
9357 bgp_origin_str[attr->origin]);
9358 else
9359 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9360
d62a17ae 9361 if (!use_json)
9362 vty_out(vty, "\n");
9363}
718e3744 9364
d62a17ae 9365/* flap route */
5f040085
DS
9366static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9367 struct bgp_path_info *path, int display,
9368 afi_t afi, safi_t safi, bool use_json,
9369 json_object *json)
784d3a42 9370{
d62a17ae 9371 struct attr *attr;
9372 struct bgp_damp_info *bdi;
9373 char timebuf[BGP_UPTIME_LEN];
9374 int len;
784d3a42 9375
9b6d8fcf 9376 if (!path->extra)
d62a17ae 9377 return;
784d3a42 9378
9b6d8fcf 9379 bdi = path->extra->damp_info;
784d3a42 9380
d62a17ae 9381 /* short status lead text */
9b6d8fcf 9382 route_vty_short_status_out(vty, path, json);
784d3a42 9383
d62a17ae 9384 /* print prefix and mask */
9385 if (!use_json) {
9386 if (!display)
ae248832 9387 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9388 else
9389 vty_out(vty, "%*s", 17, " ");
9390 }
784d3a42 9391
9b6d8fcf 9392 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9393 len = 16 - len;
9394 if (len < 1) {
9395 if (!use_json)
9396 vty_out(vty, "\n%*s", 33, " ");
9397 } else {
9398 if (use_json)
9399 json_object_int_add(json, "peerHost", len);
9400 else
9401 vty_out(vty, "%*s", len, " ");
9402 }
784d3a42 9403
d62a17ae 9404 len = vty_out(vty, "%d", bdi->flap);
9405 len = 5 - len;
9406 if (len < 1) {
9407 if (!use_json)
9408 vty_out(vty, " ");
9409 } else {
9410 if (use_json)
9411 json_object_int_add(json, "bdiFlap", len);
9412 else
9413 vty_out(vty, "%*s", len, " ");
9414 }
9415
9416 if (use_json)
9417 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9418 json);
9419 else
996c9314
LB
9420 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9421 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9422
9b6d8fcf
DS
9423 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9424 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9425 if (use_json)
9b6d8fcf 9426 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9427 BGP_UPTIME_LEN, afi, safi,
9428 use_json, json);
d62a17ae 9429 else
9430 vty_out(vty, "%s ",
9b6d8fcf 9431 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9432 BGP_UPTIME_LEN, afi,
9433 safi, use_json, json));
d62a17ae 9434 } else {
9435 if (!use_json)
9436 vty_out(vty, "%*s ", 8, " ");
9437 }
9438
9439 /* Print attribute */
9b6d8fcf 9440 attr = path->attr;
d62a17ae 9441
05864da7
DS
9442 /* Print aspath */
9443 if (attr->aspath) {
d62a17ae 9444 if (use_json)
05864da7
DS
9445 json_object_string_add(json, "asPath",
9446 attr->aspath->str);
d62a17ae 9447 else
05864da7 9448 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9449 }
05864da7
DS
9450
9451 /* Print origin */
9452 if (use_json)
9453 json_object_string_add(json, "origin",
9454 bgp_origin_str[attr->origin]);
9455 else
9456 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9457
d62a17ae 9458 if (!use_json)
9459 vty_out(vty, "\n");
9460}
9461
9462static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9463 int *first, const char *header,
9464 json_object *json_adv_to)
9465{
9466 char buf1[INET6_ADDRSTRLEN];
9467 json_object *json_peer = NULL;
9468
9469 if (json_adv_to) {
9470 /* 'advertised-to' is a dictionary of peers we have advertised
9471 * this
9472 * prefix too. The key is the peer's IP or swpX, the value is
9473 * the
9474 * hostname if we know it and "" if not.
9475 */
9476 json_peer = json_object_new_object();
9477
9478 if (peer->hostname)
9479 json_object_string_add(json_peer, "hostname",
9480 peer->hostname);
9481
9482 if (peer->conf_if)
9483 json_object_object_add(json_adv_to, peer->conf_if,
9484 json_peer);
9485 else
9486 json_object_object_add(
9487 json_adv_to,
9488 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9489 json_peer);
9490 } else {
9491 if (*first) {
9492 vty_out(vty, "%s", header);
9493 *first = 0;
9494 }
9495
9496 if (peer->hostname
892fedb6 9497 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9498 if (peer->conf_if)
9499 vty_out(vty, " %s(%s)", peer->hostname,
9500 peer->conf_if);
9501 else
9502 vty_out(vty, " %s(%s)", peer->hostname,
9503 sockunion2str(&peer->su, buf1,
9504 SU_ADDRSTRLEN));
9505 } else {
9506 if (peer->conf_if)
9507 vty_out(vty, " %s", peer->conf_if);
9508 else
9509 vty_out(vty, " %s",
9510 sockunion2str(&peer->su, buf1,
9511 SU_ADDRSTRLEN));
9512 }
9513 }
784d3a42
PG
9514}
9515
dcc68b5e
MS
9516static void route_vty_out_tx_ids(struct vty *vty,
9517 struct bgp_addpath_info_data *d)
9518{
9519 int i;
9520
9521 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9522 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9523 d->addpath_tx_id[i],
9524 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9525 }
9526}
9527
5e4d4c8a 9528static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9529 struct bgp_path_info *pi,
9530 struct attr *attr,
9531 json_object *json_path)
5e4d4c8a
AK
9532{
9533 char esi_buf[ESI_STR_LEN];
9534 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9535 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9536 ATTR_ES_PEER_ROUTER);
9537 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9538 ATTR_ES_PEER_ACTIVE);
9539 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9540 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9541 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9542 if (json_path) {
9543 json_object *json_es_info = NULL;
9544
9545 json_object_string_add(
9546 json_path, "esi",
9547 esi_buf);
9548 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9549 json_es_info = json_object_new_object();
9550 if (es_local)
9551 json_object_boolean_true_add(
9552 json_es_info, "localEs");
9553 if (peer_active)
9554 json_object_boolean_true_add(
9555 json_es_info, "peerActive");
9556 if (peer_proxy)
9557 json_object_boolean_true_add(
9558 json_es_info, "peerProxy");
9559 if (peer_router)
9560 json_object_boolean_true_add(
9561 json_es_info, "peerRouter");
9562 if (attr->mm_sync_seqnum)
9563 json_object_int_add(
9564 json_es_info, "peerSeq",
9565 attr->mm_sync_seqnum);
9566 json_object_object_add(
9567 json_path, "es_info",
9568 json_es_info);
9569 }
9570 } else {
9571 if (bgp_evpn_attr_is_sync(attr))
9572 vty_out(vty,
9573 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9574 esi_buf,
9575 es_local ? "local-es":"",
9576 peer_proxy ? "proxy " : "",
9577 peer_active ? "active ":"",
9578 peer_router ? "router ":"",
9579 attr->mm_sync_seqnum);
9580 else
9581 vty_out(vty, " ESI %s %s\n",
9582 esi_buf,
9583 es_local ? "local-es":"");
9584 }
9585}
9586
4933eaaf
DS
9587void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9588 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9589 enum rpki_states rpki_curr_state,
9590 json_object *json_paths)
d62a17ae 9591{
9592 char buf[INET6_ADDRSTRLEN];
9593 char buf1[BUFSIZ];
515c2602 9594 struct attr *attr = path->attr;
d62a17ae 9595 int sockunion_vty_out(struct vty *, union sockunion *);
9596 time_t tbuf;
9597 json_object *json_bestpath = NULL;
9598 json_object *json_cluster_list = NULL;
9599 json_object *json_cluster_list_list = NULL;
9600 json_object *json_ext_community = NULL;
9601 json_object *json_last_update = NULL;
7fd077aa 9602 json_object *json_pmsi = NULL;
d62a17ae 9603 json_object *json_nexthop_global = NULL;
9604 json_object *json_nexthop_ll = NULL;
9605 json_object *json_nexthops = NULL;
9606 json_object *json_path = NULL;
9607 json_object *json_peer = NULL;
9608 json_object *json_string = NULL;
9609 json_object *json_adv_to = NULL;
9610 int first = 0;
9611 struct listnode *node, *nnode;
9612 struct peer *peer;
9613 int addpath_capable;
9614 int has_adj;
9615 unsigned int first_as;
1defdda8 9616 bool nexthop_self =
9b6d8fcf 9617 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9618 int i;
2ba93fd6
DA
9619 char *nexthop_hostname =
9620 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9621
9622 if (json_paths) {
9623 json_path = json_object_new_object();
9624 json_peer = json_object_new_object();
9625 json_nexthop_global = json_object_new_object();
9626 }
9627
44c69747 9628 if (path->extra) {
b57ba6d2 9629 char tag_buf[30];
d62a17ae 9630
d62a17ae 9631 tag_buf[0] = '\0';
9b6d8fcf
DS
9632 if (path->extra && path->extra->num_labels) {
9633 bgp_evpn_label2str(path->extra->label,
9634 path->extra->num_labels, tag_buf,
a4d82a8a 9635 sizeof(tag_buf));
d62a17ae 9636 }
d7325ee7 9637 if (safi == SAFI_EVPN) {
44c69747 9638 if (!json_paths) {
2dbe669b
DA
9639 vty_out(vty, " Route %pFX",
9640 (struct prefix_evpn *)
9641 bgp_dest_get_prefix(bn));
44c69747
LK
9642 if (tag_buf[0] != '\0')
9643 vty_out(vty, " VNI %s", tag_buf);
9644 vty_out(vty, "\n");
9645 } else {
9646 if (tag_buf[0])
9647 json_object_string_add(json_path, "VNI",
9648 tag_buf);
9649 }
d7325ee7
DD
9650 }
9651
44c69747 9652 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9653 struct bgp_path_info *parent_ri;
9bcb3eef 9654 struct bgp_dest *dest, *pdest;
d62a17ae 9655
9b6d8fcf 9656 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9657 dest = parent_ri->net;
9658 if (dest && dest->pdest) {
9659 pdest = dest->pdest;
9660 prefix_rd2str(
9661 (struct prefix_rd *)bgp_dest_get_prefix(
9662 pdest),
9663 buf1, sizeof(buf1));
d7325ee7 9664 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9665 vty_out(vty,
58bff4d1 9666 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9667 buf1,
9668 (struct prefix_evpn *)
9669 bgp_dest_get_prefix(
9670 dest),
9671 tag_buf);
58bff4d1
AK
9672 if (attr->es_flags & ATTR_ES_L3_NHG)
9673 vty_out(vty, ", L3NHG %s",
9674 (attr->es_flags
9675 & ATTR_ES_L3_NHG_ACTIVE)
9676 ? "active"
9677 : "inactive");
9678 vty_out(vty, "\n");
9679
d7325ee7 9680 } else
2dbe669b
DA
9681 vty_out(vty,
9682 " Imported from %s:%pFX\n",
9683 buf1,
9684 (struct prefix_evpn *)
9685 bgp_dest_get_prefix(
9686 dest));
d62a17ae 9687 }
9688 }
9689 }
d62a17ae 9690
05864da7
DS
9691 /* Line1 display AS-path, Aggregator */
9692 if (attr->aspath) {
9693 if (json_paths) {
9694 if (!attr->aspath->json)
9695 aspath_str_update(attr->aspath, true);
9696 json_object_lock(attr->aspath->json);
9697 json_object_object_add(json_path, "aspath",
9698 attr->aspath->json);
9699 } else {
9700 if (attr->aspath->segments)
9701 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9702 else
05864da7 9703 vty_out(vty, " Local");
d62a17ae 9704 }
05864da7 9705 }
d62a17ae 9706
05864da7
DS
9707 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9708 if (json_paths)
9709 json_object_boolean_true_add(json_path, "removed");
9710 else
9711 vty_out(vty, ", (removed)");
9712 }
d62a17ae 9713
05864da7
DS
9714 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9715 if (json_paths)
9716 json_object_boolean_true_add(json_path, "stale");
9717 else
9718 vty_out(vty, ", (stale)");
9719 }
d62a17ae 9720
05864da7
DS
9721 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9722 if (json_paths) {
23d0a753
DA
9723 char buf[BUFSIZ] = {0};
9724
05864da7
DS
9725 json_object_int_add(json_path, "aggregatorAs",
9726 attr->aggregator_as);
23d0a753
DA
9727 json_object_string_add(json_path, "aggregatorId",
9728 inet_ntop(AF_INET,
9729 &attr->aggregator_addr,
9730 buf, sizeof(buf)));
05864da7 9731 } else {
88d495a9
DA
9732 vty_out(vty, ", (aggregated by %u %pI4)",
9733 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9734 }
05864da7 9735 }
d62a17ae 9736
05864da7
DS
9737 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9738 PEER_FLAG_REFLECTOR_CLIENT)) {
9739 if (json_paths)
9740 json_object_boolean_true_add(json_path,
9741 "rxedFromRrClient");
9742 else
9743 vty_out(vty, ", (Received from a RR-client)");
9744 }
d62a17ae 9745
05864da7
DS
9746 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9747 PEER_FLAG_RSERVER_CLIENT)) {
9748 if (json_paths)
9749 json_object_boolean_true_add(json_path,
9750 "rxedFromRsClient");
9751 else
9752 vty_out(vty, ", (Received from a RS-client)");
9753 }
d62a17ae 9754
05864da7
DS
9755 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9756 if (json_paths)
9757 json_object_boolean_true_add(json_path,
9758 "dampeningHistoryEntry");
9759 else
9760 vty_out(vty, ", (history entry)");
9761 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9762 if (json_paths)
9763 json_object_boolean_true_add(json_path,
9764 "dampeningSuppressed");
9765 else
9766 vty_out(vty, ", (suppressed due to dampening)");
9767 }
d62a17ae 9768
05864da7
DS
9769 if (!json_paths)
9770 vty_out(vty, "\n");
d62a17ae 9771
05864da7
DS
9772 /* Line2 display Next-hop, Neighbor, Router-id */
9773 /* Display the nexthop */
9bcb3eef 9774 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9775
9776 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9777 || bn_p->family == AF_EVPN)
05864da7
DS
9778 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9779 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9780 char buf[BUFSIZ] = {0};
9781
05864da7
DS
9782 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9783 || safi == SAFI_EVPN) {
515c2602 9784 if (json_paths) {
d62a17ae 9785 json_object_string_add(
515c2602 9786 json_nexthop_global, "ip",
23d0a753
DA
9787 inet_ntop(AF_INET,
9788 &attr->mp_nexthop_global_in,
9789 buf, sizeof(buf)));
515c2602 9790
939a97f4 9791 if (path->peer->hostname)
515c2602
DA
9792 json_object_string_add(
9793 json_nexthop_global, "hostname",
939a97f4 9794 path->peer->hostname);
aef999a2
DA
9795 } else {
9796 if (nexthop_hostname)
9797 vty_out(vty, " %pI4(%s)",
9798 &attr->mp_nexthop_global_in,
9799 nexthop_hostname);
9800 else
9801 vty_out(vty, " %pI4",
9802 &attr->mp_nexthop_global_in);
9803 }
d62a17ae 9804 } else {
515c2602 9805 if (json_paths) {
05864da7 9806 json_object_string_add(
515c2602 9807 json_nexthop_global, "ip",
23d0a753
DA
9808 inet_ntop(AF_INET, &attr->nexthop, buf,
9809 sizeof(buf)));
515c2602 9810
939a97f4 9811 if (path->peer->hostname)
515c2602
DA
9812 json_object_string_add(
9813 json_nexthop_global, "hostname",
939a97f4 9814 path->peer->hostname);
aef999a2
DA
9815 } else {
9816 if (nexthop_hostname)
9817 vty_out(vty, " %pI4(%s)",
9818 &attr->nexthop,
9819 nexthop_hostname);
9820 else
9821 vty_out(vty, " %pI4",
9822 &attr->nexthop);
9823 }
d62a17ae 9824 }
9825
05864da7
DS
9826 if (json_paths)
9827 json_object_string_add(json_nexthop_global, "afi",
9828 "ipv4");
9829 } else {
9830 if (json_paths) {
9831 json_object_string_add(
515c2602
DA
9832 json_nexthop_global, "ip",
9833 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9834 buf, INET6_ADDRSTRLEN));
9835
939a97f4 9836 if (path->peer->hostname)
515c2602
DA
9837 json_object_string_add(json_nexthop_global,
9838 "hostname",
939a97f4 9839 path->peer->hostname);
515c2602 9840
05864da7
DS
9841 json_object_string_add(json_nexthop_global, "afi",
9842 "ipv6");
9843 json_object_string_add(json_nexthop_global, "scope",
9844 "global");
9845 } else {
aef999a2
DA
9846 if (nexthop_hostname)
9847 vty_out(vty, " %pI6(%s)",
9848 &attr->mp_nexthop_global,
9849 nexthop_hostname);
9850 else
9851 vty_out(vty, " %pI6",
9852 &attr->mp_nexthop_global);
d62a17ae 9853 }
05864da7 9854 }
d62a17ae 9855
05864da7
DS
9856 /* Display the IGP cost or 'inaccessible' */
9857 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9858 if (json_paths)
9859 json_object_boolean_false_add(json_nexthop_global,
9860 "accessible");
9861 else
9862 vty_out(vty, " (inaccessible)");
9863 } else {
9864 if (path->extra && path->extra->igpmetric) {
d62a17ae 9865 if (json_paths)
05864da7
DS
9866 json_object_int_add(json_nexthop_global,
9867 "metric",
9868 path->extra->igpmetric);
d62a17ae 9869 else
05864da7
DS
9870 vty_out(vty, " (metric %u)",
9871 path->extra->igpmetric);
d62a17ae 9872 }
9873
05864da7 9874 /* IGP cost is 0, display this only for json */
d62a17ae 9875 else {
d62a17ae 9876 if (json_paths)
05864da7
DS
9877 json_object_int_add(json_nexthop_global,
9878 "metric", 0);
d62a17ae 9879 }
d62a17ae 9880
05864da7
DS
9881 if (json_paths)
9882 json_object_boolean_true_add(json_nexthop_global,
9883 "accessible");
9884 }
d62a17ae 9885
05864da7
DS
9886 /* Display peer "from" output */
9887 /* This path was originated locally */
9888 if (path->peer == bgp->peer_self) {
d62a17ae 9889
05864da7 9890 if (safi == SAFI_EVPN
b54892e0 9891 || (bn_p->family == AF_INET
05864da7 9892 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9893 if (json_paths)
05864da7
DS
9894 json_object_string_add(json_peer, "peerId",
9895 "0.0.0.0");
d62a17ae 9896 else
05864da7
DS
9897 vty_out(vty, " from 0.0.0.0 ");
9898 } else {
d62a17ae 9899 if (json_paths)
05864da7
DS
9900 json_object_string_add(json_peer, "peerId",
9901 "::");
d62a17ae 9902 else
05864da7 9903 vty_out(vty, " from :: ");
d62a17ae 9904 }
d62a17ae 9905
23d0a753
DA
9906 if (json_paths) {
9907 char buf[BUFSIZ] = {0};
9908
05864da7 9909 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9910 inet_ntop(AF_INET,
9911 &bgp->router_id, buf,
9912 sizeof(buf)));
9913 } else {
9914 vty_out(vty, "(%pI4)", &bgp->router_id);
9915 }
05864da7 9916 }
d62a17ae 9917
05864da7
DS
9918 /* We RXed this path from one of our peers */
9919 else {
9920
9921 if (json_paths) {
9922 json_object_string_add(json_peer, "peerId",
9923 sockunion2str(&path->peer->su,
9924 buf,
9925 SU_ADDRSTRLEN));
9926 json_object_string_add(json_peer, "routerId",
9927 inet_ntop(AF_INET,
9928 &path->peer->remote_id,
9929 buf1, sizeof(buf1)));
9930
9931 if (path->peer->hostname)
9932 json_object_string_add(json_peer, "hostname",
9933 path->peer->hostname);
9934
9935 if (path->peer->domainname)
9936 json_object_string_add(json_peer, "domainname",
9937 path->peer->domainname);
9938
9939 if (path->peer->conf_if)
9940 json_object_string_add(json_peer, "interface",
9941 path->peer->conf_if);
9942 } else {
9943 if (path->peer->conf_if) {
9944 if (path->peer->hostname
892fedb6
DA
9945 && CHECK_FLAG(path->peer->bgp->flags,
9946 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9947 vty_out(vty, " from %s(%s)",
9948 path->peer->hostname,
9949 path->peer->conf_if);
d62a17ae 9950 else
05864da7 9951 vty_out(vty, " from %s",
9b6d8fcf 9952 path->peer->conf_if);
d62a17ae 9953 } else {
05864da7 9954 if (path->peer->hostname
892fedb6
DA
9955 && CHECK_FLAG(path->peer->bgp->flags,
9956 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9957 vty_out(vty, " from %s(%s)",
9958 path->peer->hostname,
9959 path->peer->host);
d62a17ae 9960 else
05864da7
DS
9961 vty_out(vty, " from %s",
9962 sockunion2str(&path->peer->su,
9963 buf,
9964 SU_ADDRSTRLEN));
d62a17ae 9965 }
d62a17ae 9966
05864da7 9967 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9968 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9969 else
9970 vty_out(vty, " (%s)",
9971 inet_ntop(AF_INET,
9972 &path->peer->remote_id, buf1,
9973 sizeof(buf1)));
d62a17ae 9974 }
05864da7 9975 }
9df8b37c 9976
05864da7
DS
9977 /*
9978 * Note when vrfid of nexthop is different from that of prefix
9979 */
9980 if (path->extra && path->extra->bgp_orig) {
9981 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9982
05864da7
DS
9983 if (json_paths) {
9984 const char *vn;
9df8b37c 9985
05864da7
DS
9986 if (path->extra->bgp_orig->inst_type
9987 == BGP_INSTANCE_TYPE_DEFAULT)
9988 vn = VRF_DEFAULT_NAME;
9989 else
9990 vn = path->extra->bgp_orig->name;
9df8b37c 9991
05864da7 9992 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9993
05864da7
DS
9994 if (nexthop_vrfid == VRF_UNKNOWN) {
9995 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9996 } else {
05864da7
DS
9997 json_object_int_add(json_path, "nhVrfId",
9998 (int)nexthop_vrfid);
9df8b37c 9999 }
05864da7
DS
10000 } else {
10001 if (nexthop_vrfid == VRF_UNKNOWN)
10002 vty_out(vty, " vrf ?");
137147c6
DS
10003 else {
10004 struct vrf *vrf;
10005
10006 vrf = vrf_lookup_by_id(nexthop_vrfid);
10007 vty_out(vty, " vrf %s(%u)",
10008 VRF_LOGNAME(vrf), nexthop_vrfid);
10009 }
9df8b37c 10010 }
05864da7 10011 }
9df8b37c 10012
05864da7
DS
10013 if (nexthop_self) {
10014 if (json_paths) {
10015 json_object_boolean_true_add(json_path,
10016 "announceNexthopSelf");
10017 } else {
10018 vty_out(vty, " announce-nh-self");
9df8b37c 10019 }
05864da7 10020 }
9df8b37c 10021
05864da7
DS
10022 if (!json_paths)
10023 vty_out(vty, "\n");
d62a17ae 10024
05864da7
DS
10025 /* display the link-local nexthop */
10026 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10027 if (json_paths) {
10028 json_nexthop_ll = json_object_new_object();
10029 json_object_string_add(
515c2602
DA
10030 json_nexthop_ll, "ip",
10031 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10032 buf, INET6_ADDRSTRLEN));
10033
939a97f4 10034 if (path->peer->hostname)
515c2602
DA
10035 json_object_string_add(json_nexthop_ll,
10036 "hostname",
939a97f4 10037 path->peer->hostname);
515c2602 10038
05864da7
DS
10039 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10040 json_object_string_add(json_nexthop_ll, "scope",
10041 "link-local");
d62a17ae 10042
05864da7
DS
10043 json_object_boolean_true_add(json_nexthop_ll,
10044 "accessible");
d62a17ae 10045
05864da7 10046 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10047 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10048 "used");
10049 else
10050 json_object_boolean_true_add(
10051 json_nexthop_global, "used");
10052 } else {
10053 vty_out(vty, " (%s) %s\n",
10054 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10055 buf, INET6_ADDRSTRLEN),
10056 attr->mp_nexthop_prefer_global
10057 ? "(prefer-global)"
10058 : "(used)");
d62a17ae 10059 }
05864da7
DS
10060 }
10061 /* If we do not have a link-local nexthop then we must flag the
10062 global as "used" */
10063 else {
10064 if (json_paths)
10065 json_object_boolean_true_add(json_nexthop_global,
10066 "used");
10067 }
d62a17ae 10068
b5e140c8 10069 if (safi == SAFI_EVPN &&
5e4d4c8a 10070 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10071 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10072 }
10073
05864da7
DS
10074 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10075 * Int/Ext/Local, Atomic, best */
10076 if (json_paths)
10077 json_object_string_add(json_path, "origin",
10078 bgp_origin_long_str[attr->origin]);
10079 else
10080 vty_out(vty, " Origin %s",
10081 bgp_origin_long_str[attr->origin]);
9df8b37c 10082
05864da7 10083 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10084 if (json_paths)
05864da7 10085 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10086 else
05864da7
DS
10087 vty_out(vty, ", metric %u", attr->med);
10088 }
9df8b37c 10089
05864da7
DS
10090 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10091 if (json_paths)
0fbac0b4 10092 json_object_int_add(json_path, "locPrf",
05864da7
DS
10093 attr->local_pref);
10094 else
10095 vty_out(vty, ", localpref %u", attr->local_pref);
10096 }
9df8b37c 10097
05864da7
DS
10098 if (attr->weight != 0) {
10099 if (json_paths)
10100 json_object_int_add(json_path, "weight", attr->weight);
10101 else
10102 vty_out(vty, ", weight %u", attr->weight);
10103 }
9df8b37c 10104
05864da7
DS
10105 if (attr->tag != 0) {
10106 if (json_paths)
10107 json_object_int_add(json_path, "tag", attr->tag);
10108 else
10109 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10110 }
9df8b37c 10111
05864da7
DS
10112 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10113 if (json_paths)
10114 json_object_boolean_false_add(json_path, "valid");
10115 else
10116 vty_out(vty, ", invalid");
10117 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10118 if (json_paths)
10119 json_object_boolean_true_add(json_path, "valid");
10120 else
10121 vty_out(vty, ", valid");
10122 }
9df8b37c 10123
05864da7
DS
10124 if (path->peer != bgp->peer_self) {
10125 if (path->peer->as == path->peer->local_as) {
10126 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10127 if (json_paths)
10128 json_object_string_add(
10129 json_peer, "type",
10130 "confed-internal");
d62a17ae 10131 else
05864da7 10132 vty_out(vty, ", confed-internal");
d62a17ae 10133 } else {
05864da7
DS
10134 if (json_paths)
10135 json_object_string_add(
10136 json_peer, "type", "internal");
10137 else
10138 vty_out(vty, ", internal");
9df8b37c 10139 }
05864da7
DS
10140 } else {
10141 if (bgp_confederation_peers_check(bgp,
10142 path->peer->as)) {
10143 if (json_paths)
10144 json_object_string_add(
10145 json_peer, "type",
10146 "confed-external");
d62a17ae 10147 else
05864da7 10148 vty_out(vty, ", confed-external");
d62a17ae 10149 } else {
05864da7
DS
10150 if (json_paths)
10151 json_object_string_add(
10152 json_peer, "type", "external");
10153 else
10154 vty_out(vty, ", external");
d62a17ae 10155 }
10156 }
05864da7
DS
10157 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10158 if (json_paths) {
10159 json_object_boolean_true_add(json_path, "aggregated");
10160 json_object_boolean_true_add(json_path, "local");
10161 } else {
10162 vty_out(vty, ", aggregated, local");
10163 }
10164 } else if (path->type != ZEBRA_ROUTE_BGP) {
10165 if (json_paths)
10166 json_object_boolean_true_add(json_path, "sourced");
10167 else
10168 vty_out(vty, ", sourced");
10169 } else {
10170 if (json_paths) {
10171 json_object_boolean_true_add(json_path, "sourced");
10172 json_object_boolean_true_add(json_path, "local");
10173 } else {
10174 vty_out(vty, ", sourced, local");
d62a17ae 10175 }
05864da7 10176 }
718e3744 10177
05864da7 10178 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10179 if (json_paths)
05864da7
DS
10180 json_object_boolean_true_add(json_path,
10181 "atomicAggregate");
d62a17ae 10182 else
05864da7
DS
10183 vty_out(vty, ", atomic-aggregate");
10184 }
d62a17ae 10185
05864da7
DS
10186 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10187 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10188 && bgp_path_info_mpath_count(path))) {
10189 if (json_paths)
10190 json_object_boolean_true_add(json_path, "multipath");
10191 else
10192 vty_out(vty, ", multipath");
10193 }
50e05855 10194
05864da7
DS
10195 // Mark the bestpath(s)
10196 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10197 first_as = aspath_get_first_as(attr->aspath);
718e3744 10198
05864da7
DS
10199 if (json_paths) {
10200 if (!json_bestpath)
10201 json_bestpath = json_object_new_object();
10202 json_object_int_add(json_bestpath, "bestpathFromAs",
10203 first_as);
10204 } else {
10205 if (first_as)
10206 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10207 else
05864da7 10208 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10209 }
05864da7 10210 }
718e3744 10211
05864da7
DS
10212 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10213 if (json_paths) {
10214 if (!json_bestpath)
10215 json_bestpath = json_object_new_object();
10216 json_object_boolean_true_add(json_bestpath, "overall");
10217 json_object_string_add(
10218 json_bestpath, "selectionReason",
10219 bgp_path_selection_reason2str(bn->reason));
10220 } else {
10221 vty_out(vty, ", best");
10222 vty_out(vty, " (%s)",
10223 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10224 }
05864da7 10225 }
718e3744 10226
4027d19b 10227 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10228 if (json_paths)
10229 json_object_string_add(
10230 json_path, "rpkiValidationState",
4027d19b 10231 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10232 else
1d327209 10233 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10234 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10235 }
10236
05864da7
DS
10237 if (json_bestpath)
10238 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10239
05864da7
DS
10240 if (!json_paths)
10241 vty_out(vty, "\n");
10242
10243 /* Line 4 display Community */
10244 if (attr->community) {
10245 if (json_paths) {
10246 if (!attr->community->json)
10247 community_str(attr->community, true);
10248 json_object_lock(attr->community->json);
10249 json_object_object_add(json_path, "community",
10250 attr->community->json);
10251 } else {
10252 vty_out(vty, " Community: %s\n",
10253 attr->community->str);
d62a17ae 10254 }
05864da7 10255 }
718e3744 10256
05864da7
DS
10257 /* Line 5 display Extended-community */
10258 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10259 if (json_paths) {
10260 json_ext_community = json_object_new_object();
10261 json_object_string_add(json_ext_community, "string",
10262 attr->ecommunity->str);
10263 json_object_object_add(json_path, "extendedCommunity",
10264 json_ext_community);
d62a17ae 10265 } else {
05864da7
DS
10266 vty_out(vty, " Extended Community: %s\n",
10267 attr->ecommunity->str);
d62a17ae 10268 }
05864da7 10269 }
718e3744 10270
05864da7
DS
10271 /* Line 6 display Large community */
10272 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10273 if (json_paths) {
10274 if (!attr->lcommunity->json)
10275 lcommunity_str(attr->lcommunity, true);
10276 json_object_lock(attr->lcommunity->json);
10277 json_object_object_add(json_path, "largeCommunity",
10278 attr->lcommunity->json);
10279 } else {
10280 vty_out(vty, " Large Community: %s\n",
10281 attr->lcommunity->str);
d62a17ae 10282 }
05864da7 10283 }
718e3744 10284
05864da7
DS
10285 /* Line 7 display Originator, Cluster-id */
10286 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10287 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10288 char buf[BUFSIZ] = {0};
10289
05864da7 10290 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10291 if (json_paths)
05864da7
DS
10292 json_object_string_add(
10293 json_path, "originatorId",
23d0a753
DA
10294 inet_ntop(AF_INET, &attr->originator_id,
10295 buf, sizeof(buf)));
d62a17ae 10296 else
23d0a753
DA
10297 vty_out(vty, " Originator: %pI4",
10298 &attr->originator_id);
d62a17ae 10299 }
856ca177 10300
05864da7 10301 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10302 struct cluster_list *cluster =
10303 bgp_attr_get_cluster(attr);
05864da7 10304 int i;
d62a17ae 10305
10306 if (json_paths) {
05864da7
DS
10307 json_cluster_list = json_object_new_object();
10308 json_cluster_list_list =
10309 json_object_new_array();
10310
779fee93 10311 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10312 json_string = json_object_new_string(
779fee93
DS
10313 inet_ntop(AF_INET,
10314 &cluster->list[i],
10315 buf, sizeof(buf)));
05864da7
DS
10316 json_object_array_add(
10317 json_cluster_list_list,
10318 json_string);
10319 }
718e3744 10320
05864da7
DS
10321 /*
10322 * struct cluster_list does not have
10323 * "str" variable like aspath and community
10324 * do. Add this someday if someone asks
10325 * for it.
10326 * json_object_string_add(json_cluster_list,
779fee93 10327 * "string", cluster->str);
05864da7
DS
10328 */
10329 json_object_object_add(json_cluster_list,
10330 "list",
10331 json_cluster_list_list);
10332 json_object_object_add(json_path, "clusterList",
10333 json_cluster_list);
0dc8ee70 10334 } else {
05864da7
DS
10335 vty_out(vty, ", Cluster list: ");
10336
779fee93 10337 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10338 vty_out(vty, "%pI4 ",
779fee93 10339 &cluster->list[i]);
05864da7 10340 }
0dc8ee70 10341 }
d62a17ae 10342 }
718e3744 10343
d62a17ae 10344 if (!json_paths)
10345 vty_out(vty, "\n");
05864da7 10346 }
d62a17ae 10347
05864da7 10348 if (path->extra && path->extra->damp_info)
40ec3340 10349 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10350
05864da7
DS
10351 /* Remote Label */
10352 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10353 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10354 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10355
05864da7
DS
10356 if (json_paths)
10357 json_object_int_add(json_path, "remoteLabel", label);
10358 else
10359 vty_out(vty, " Remote label: %d\n", label);
10360 }
d62a17ae 10361
e496b420
HS
10362 /* Remote SID */
10363 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10364 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10365 if (json_paths)
10366 json_object_string_add(json_path, "remoteSid", buf);
10367 else
10368 vty_out(vty, " Remote SID: %s\n", buf);
10369 }
10370
05864da7
DS
10371 /* Label Index */
10372 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10373 if (json_paths)
10374 json_object_int_add(json_path, "labelIndex",
10375 attr->label_index);
10376 else
10377 vty_out(vty, " Label Index: %d\n",
10378 attr->label_index);
10379 }
d62a17ae 10380
05864da7
DS
10381 /* Line 8 display Addpath IDs */
10382 if (path->addpath_rx_id
10383 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10384 if (json_paths) {
10385 json_object_int_add(json_path, "addpathRxId",
10386 path->addpath_rx_id);
d62a17ae 10387
05864da7
DS
10388 /* Keep backwards compatibility with the old API
10389 * by putting TX All's ID in the old field
10390 */
10391 json_object_int_add(
10392 json_path, "addpathTxId",
10393 path->tx_addpath
10394 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10395
05864da7
DS
10396 /* ... but create a specific field for each
10397 * strategy
10398 */
10399 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10400 json_object_int_add(
10401 json_path,
10402 bgp_addpath_names(i)->id_json_name,
10403 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10404 }
05864da7
DS
10405 } else {
10406 vty_out(vty, " AddPath ID: RX %u, ",
10407 path->addpath_rx_id);
d62a17ae 10408
05864da7 10409 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10410 }
05864da7 10411 }
520d5d76 10412
05864da7
DS
10413 /* If we used addpath to TX a non-bestpath we need to display
10414 * "Advertised to" on a path-by-path basis
10415 */
10416 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10417 first = 1;
dcc68b5e 10418
05864da7
DS
10419 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10420 addpath_capable =
10421 bgp_addpath_encode_tx(peer, afi, safi);
10422 has_adj = bgp_adj_out_lookup(
10423 peer, path->net,
10424 bgp_addpath_id_for_peer(peer, afi, safi,
10425 &path->tx_addpath));
10426
10427 if ((addpath_capable && has_adj)
10428 || (!addpath_capable && has_adj
10429 && CHECK_FLAG(path->flags,
10430 BGP_PATH_SELECTED))) {
10431 if (json_path && !json_adv_to)
10432 json_adv_to = json_object_new_object();
dcc68b5e 10433
05864da7
DS
10434 route_vty_out_advertised_to(
10435 vty, peer, &first,
10436 " Advertised to:", json_adv_to);
d62a17ae 10437 }
10438 }
718e3744 10439
05864da7
DS
10440 if (json_path) {
10441 if (json_adv_to) {
10442 json_object_object_add(
10443 json_path, "advertisedTo", json_adv_to);
d62a17ae 10444 }
05864da7
DS
10445 } else {
10446 if (!first) {
10447 vty_out(vty, "\n");
d62a17ae 10448 }
10449 }
05864da7 10450 }
b05a1c8b 10451
05864da7
DS
10452 /* Line 9 display Uptime */
10453 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10454 if (json_paths) {
10455 json_last_update = json_object_new_object();
10456 json_object_int_add(json_last_update, "epoch", tbuf);
10457 json_object_string_add(json_last_update, "string",
10458 ctime(&tbuf));
10459 json_object_object_add(json_path, "lastUpdate",
10460 json_last_update);
10461 } else
10462 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10463
05864da7
DS
10464 /* Line 10 display PMSI tunnel attribute, if present */
10465 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10466 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10467 bgp_attr_get_pmsi_tnl_type(attr),
10468 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10469
05864da7
DS
10470 if (json_paths) {
10471 json_pmsi = json_object_new_object();
10472 json_object_string_add(json_pmsi, "tunnelType", str);
10473 json_object_int_add(json_pmsi, "label",
10474 label2vni(&attr->label));
10475 json_object_object_add(json_path, "pmsi", json_pmsi);
10476 } else
10477 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10478 str, label2vni(&attr->label));
d62a17ae 10479 }
f1aa5d8a 10480
92269aa2
DS
10481 /* Output some debug about internal state of the dest flags */
10482 if (json_paths) {
10483 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10484 json_object_boolean_true_add(json_path, "processScheduled");
10485 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10486 json_object_boolean_true_add(json_path, "userCleared");
10487 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10488 json_object_boolean_true_add(json_path, "labelChanged");
10489 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10490 json_object_boolean_true_add(json_path, "registeredForLabel");
10491 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10492 json_object_boolean_true_add(json_path, "selectDefered");
10493 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10494 json_object_boolean_true_add(json_path, "fibInstalled");
10495 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10496 json_object_boolean_true_add(json_path, "fibPending");
10497 }
10498
d62a17ae 10499 /* We've constructed the json object for this path, add it to the json
10500 * array of paths
10501 */
10502 if (json_paths) {
10503 if (json_nexthop_global || json_nexthop_ll) {
10504 json_nexthops = json_object_new_array();
f1aa5d8a 10505
d62a17ae 10506 if (json_nexthop_global)
10507 json_object_array_add(json_nexthops,
10508 json_nexthop_global);
f1aa5d8a 10509
d62a17ae 10510 if (json_nexthop_ll)
10511 json_object_array_add(json_nexthops,
10512 json_nexthop_ll);
f1aa5d8a 10513
d62a17ae 10514 json_object_object_add(json_path, "nexthops",
10515 json_nexthops);
10516 }
10517
10518 json_object_object_add(json_path, "peer", json_peer);
10519 json_object_array_add(json_paths, json_path);
05864da7 10520 }
b366b518
BB
10521}
10522
96ade3ed 10523#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10524#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10525#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10526
d62a17ae 10527static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10528 const char *prefix_list_str, afi_t afi,
10529 safi_t safi, enum bgp_show_type type);
10530static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10531 const char *filter, afi_t afi, safi_t safi,
10532 enum bgp_show_type type);
10533static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10534 const char *rmap_str, afi_t afi, safi_t safi,
10535 enum bgp_show_type type);
10536static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10537 const char *com, int exact, afi_t afi,
10538 safi_t safi);
10539static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10540 const char *prefix, afi_t afi, safi_t safi,
10541 enum bgp_show_type type);
a4d82a8a 10542static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10543 afi_t afi, safi_t safi, enum bgp_show_type type,
10544 bool use_json);
7f323236
DW
10545static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10546 const char *comstr, int exact, afi_t afi,
96f3485c 10547 safi_t safi, uint8_t show_flags);
d62a17ae 10548
1ae44dfc
LB
10549
10550static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10551 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10552 void *output_arg, char *rd, int is_last,
10553 unsigned long *output_cum, unsigned long *total_cum,
1e2ce4f1 10554 unsigned long *json_header_depth, uint8_t show_flags,
4027d19b 10555 enum rpki_states rpki_target_state)
d62a17ae 10556{
40381db7 10557 struct bgp_path_info *pi;
9bcb3eef 10558 struct bgp_dest *dest;
d62a17ae 10559 int header = 1;
10560 int display;
1ae44dfc
LB
10561 unsigned long output_count = 0;
10562 unsigned long total_count = 0;
d62a17ae 10563 struct prefix *p;
d62a17ae 10564 json_object *json_paths = NULL;
10565 int first = 1;
96f3485c
MK
10566 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10567 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10568 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10569
1ae44dfc
LB
10570 if (output_cum && *output_cum != 0)
10571 header = 0;
10572
9386b588 10573 if (use_json && !*json_header_depth) {
96f3485c
MK
10574 if (all)
10575 *json_header_depth = 1;
10576 else {
10577 vty_out(vty, "{\n");
10578 *json_header_depth = 2;
10579 }
10580
d62a17ae 10581 vty_out(vty,
23d0a753
DA
10582 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10583 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10584 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10585 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10586 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10587 ? VRF_DEFAULT_NAME
10588 : bgp->name,
10589 table->version, &bgp->router_id,
01eced22 10590 bgp->default_local_pref, bgp->as);
9386b588 10591 if (rd) {
445c2480 10592 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10593 ++*json_header_depth;
10594 }
d62a17ae 10595 }
718e3744 10596
445c2480
DS
10597 if (use_json && rd) {
10598 vty_out(vty, " \"%s\" : { ", rd);
10599 }
10600
d62a17ae 10601 /* Start processing of routes. */
9bcb3eef
DS
10602 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10603 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10604 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10605
9bcb3eef 10606 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10607 if (pi == NULL)
98ce9a06 10608 continue;
d62a17ae 10609
98ce9a06 10610 display = 0;
98ce9a06
DS
10611 if (use_json)
10612 json_paths = json_object_new_array();
10613 else
10614 json_paths = NULL;
d62a17ae 10615
6f94b685 10616 for (; pi; pi = pi->next) {
98ce9a06 10617 total_count++;
1e2ce4f1
DS
10618
10619 if (type == bgp_show_type_rpki) {
10620 if (dest_p->family == AF_INET
10621 || dest_p->family == AF_INET6)
4027d19b 10622 rpki_curr_state = hook_call(
1e2ce4f1
DS
10623 bgp_rpki_prefix_status,
10624 pi->peer, pi->attr, dest_p);
4027d19b
DS
10625 if (rpki_target_state != RPKI_NOT_BEING_USED
10626 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10627 continue;
10628 }
10629
98ce9a06
DS
10630 if (type == bgp_show_type_flap_statistics
10631 || type == bgp_show_type_flap_neighbor
10632 || type == bgp_show_type_dampend_paths
10633 || type == bgp_show_type_damp_neighbor) {
40381db7 10634 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10635 continue;
10636 }
10637 if (type == bgp_show_type_regexp) {
10638 regex_t *regex = output_arg;
d62a17ae 10639
40381db7 10640 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10641 == REG_NOMATCH)
10642 continue;
10643 }
10644 if (type == bgp_show_type_prefix_list) {
10645 struct prefix_list *plist = output_arg;
d62a17ae 10646
9bcb3eef 10647 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10648 != PREFIX_PERMIT)
10649 continue;
10650 }
10651 if (type == bgp_show_type_filter_list) {
10652 struct as_list *as_list = output_arg;
d62a17ae 10653
40381db7 10654 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10655 != AS_FILTER_PERMIT)
10656 continue;
10657 }
10658 if (type == bgp_show_type_route_map) {
10659 struct route_map *rmap = output_arg;
9b6d8fcf 10660 struct bgp_path_info path;
98ce9a06 10661 struct attr dummy_attr;
b68885f9 10662 route_map_result_t ret;
d62a17ae 10663
6f4f49b2 10664 dummy_attr = *pi->attr;
d62a17ae 10665
40381db7 10666 path.peer = pi->peer;
9b6d8fcf 10667 path.attr = &dummy_attr;
d62a17ae 10668
1782514f 10669 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10670 if (ret == RMAP_DENYMATCH)
10671 continue;
10672 }
10673 if (type == bgp_show_type_neighbor
10674 || type == bgp_show_type_flap_neighbor
10675 || type == bgp_show_type_damp_neighbor) {
10676 union sockunion *su = output_arg;
10677
40381db7
DS
10678 if (pi->peer == NULL
10679 || pi->peer->su_remote == NULL
10680 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10681 continue;
10682 }
10683 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10684 uint32_t destination;
d62a17ae 10685
9bcb3eef 10686 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10687 if (IN_CLASSC(destination)
9bcb3eef 10688 && dest_p->prefixlen == 24)
98ce9a06
DS
10689 continue;
10690 if (IN_CLASSB(destination)
9bcb3eef 10691 && dest_p->prefixlen == 16)
98ce9a06
DS
10692 continue;
10693 if (IN_CLASSA(destination)
9bcb3eef 10694 && dest_p->prefixlen == 8)
98ce9a06
DS
10695 continue;
10696 }
10697 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10698 p = output_arg;
9bcb3eef 10699 if (!prefix_match(p, dest_p))
98ce9a06
DS
10700 continue;
10701 }
10702 if (type == bgp_show_type_community_all) {
40381db7 10703 if (!pi->attr->community)
98ce9a06
DS
10704 continue;
10705 }
10706 if (type == bgp_show_type_community) {
10707 struct community *com = output_arg;
d62a17ae 10708
40381db7
DS
10709 if (!pi->attr->community
10710 || !community_match(pi->attr->community,
98ce9a06
DS
10711 com))
10712 continue;
10713 }
10714 if (type == bgp_show_type_community_exact) {
10715 struct community *com = output_arg;
d62a17ae 10716
40381db7
DS
10717 if (!pi->attr->community
10718 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10719 continue;
10720 }
10721 if (type == bgp_show_type_community_list) {
10722 struct community_list *list = output_arg;
d62a17ae 10723
40381db7 10724 if (!community_list_match(pi->attr->community,
a4d82a8a 10725 list))
98ce9a06
DS
10726 continue;
10727 }
a4d82a8a 10728 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10729 struct community_list *list = output_arg;
d62a17ae 10730
98ce9a06 10731 if (!community_list_exact_match(
40381db7 10732 pi->attr->community, list))
98ce9a06
DS
10733 continue;
10734 }
10735 if (type == bgp_show_type_lcommunity) {
10736 struct lcommunity *lcom = output_arg;
d62a17ae 10737
40381db7
DS
10738 if (!pi->attr->lcommunity
10739 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10740 lcom))
10741 continue;
10742 }
36a206db 10743
10744 if (type == bgp_show_type_lcommunity_exact) {
10745 struct lcommunity *lcom = output_arg;
10746
10747 if (!pi->attr->lcommunity
10748 || !lcommunity_cmp(pi->attr->lcommunity,
10749 lcom))
10750 continue;
10751 }
98ce9a06
DS
10752 if (type == bgp_show_type_lcommunity_list) {
10753 struct community_list *list = output_arg;
d62a17ae 10754
40381db7 10755 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10756 list))
98ce9a06
DS
10757 continue;
10758 }
36a206db 10759 if (type
10760 == bgp_show_type_lcommunity_list_exact) {
10761 struct community_list *list = output_arg;
10762
10763 if (!lcommunity_list_exact_match(
10764 pi->attr->lcommunity, list))
10765 continue;
10766 }
98ce9a06 10767 if (type == bgp_show_type_lcommunity_all) {
40381db7 10768 if (!pi->attr->lcommunity)
98ce9a06
DS
10769 continue;
10770 }
10771 if (type == bgp_show_type_dampend_paths
10772 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10773 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10774 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10775 continue;
10776 }
10777
10778 if (!use_json && header) {
23d0a753
DA
10779 vty_out(vty,
10780 "BGP table version is %" PRIu64
10781 ", local router ID is %pI4, vrf id ",
10782 table->version, &bgp->router_id);
9df8b37c
PZ
10783 if (bgp->vrf_id == VRF_UNKNOWN)
10784 vty_out(vty, "%s", VRFID_NONE_STR);
10785 else
10786 vty_out(vty, "%u", bgp->vrf_id);
10787 vty_out(vty, "\n");
01eced22
AD
10788 vty_out(vty, "Default local pref %u, ",
10789 bgp->default_local_pref);
10790 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10791 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10792 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10793 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10794 if (type == bgp_show_type_dampend_paths
10795 || type == bgp_show_type_damp_neighbor)
98ce9a06 10796 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10797 else if (type == bgp_show_type_flap_statistics
10798 || type == bgp_show_type_flap_neighbor)
98ce9a06 10799 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10800 else
ae248832
MK
10801 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10802 : BGP_SHOW_HEADER));
98ce9a06 10803 header = 0;
d62a17ae 10804 }
98ce9a06
DS
10805 if (rd != NULL && !display && !output_count) {
10806 if (!use_json)
10807 vty_out(vty,
10808 "Route Distinguisher: %s\n",
10809 rd);
d62a17ae 10810 }
98ce9a06
DS
10811 if (type == bgp_show_type_dampend_paths
10812 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10813 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10814 AFI_IP, safi, use_json,
10815 json_paths);
98ce9a06
DS
10816 else if (type == bgp_show_type_flap_statistics
10817 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10818 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10819 AFI_IP, safi, use_json,
10820 json_paths);
98ce9a06 10821 else
9bcb3eef 10822 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10823 json_paths, wide);
98ce9a06 10824 display++;
d62a17ae 10825 }
10826
98ce9a06
DS
10827 if (display) {
10828 output_count++;
10829 if (!use_json)
10830 continue;
10831
625d2931 10832 /* encode prefix */
9bcb3eef 10833 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10834 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10835
1840384b 10836
b54892e0
DS
10837 bgp_fs_nlri_get_string(
10838 (unsigned char *)
9bcb3eef
DS
10839 dest_p->u.prefix_flowspec.ptr,
10840 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10841 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10842 family2afi(dest_p->u
10843 .prefix_flowspec.family));
625d2931 10844 if (first)
b54892e0 10845 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10846 dest_p->u.prefix_flowspec
b54892e0 10847 .prefixlen);
625d2931 10848 else
b54892e0 10849 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10850 dest_p->u.prefix_flowspec
b54892e0 10851 .prefixlen);
625d2931 10852 } else {
625d2931 10853 if (first)
1b78780b 10854 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10855 else
1b78780b 10856 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10857 }
98ce9a06 10858 vty_out(vty, "%s",
f4ec52f7
DA
10859 json_object_to_json_string_ext(
10860 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10861 json_object_free(json_paths);
449feb8e 10862 json_paths = NULL;
98ce9a06 10863 first = 0;
1f83ed02
DS
10864 } else
10865 json_object_free(json_paths);
98ce9a06
DS
10866 }
10867
1ae44dfc
LB
10868 if (output_cum) {
10869 output_count += *output_cum;
10870 *output_cum = output_count;
10871 }
10872 if (total_cum) {
10873 total_count += *total_cum;
10874 *total_cum = total_count;
10875 }
d62a17ae 10876 if (use_json) {
9386b588 10877 if (rd) {
a4d82a8a 10878 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10879 }
10880 if (is_last) {
a4d82a8a
PZ
10881 unsigned long i;
10882 for (i = 0; i < *json_header_depth; ++i)
10883 vty_out(vty, " } ");
96f3485c
MK
10884 if (!all)
10885 vty_out(vty, "\n");
9386b588 10886 }
d62a17ae 10887 } else {
1ae44dfc
LB
10888 if (is_last) {
10889 /* No route is displayed */
10890 if (output_count == 0) {
10891 if (type == bgp_show_type_normal)
10892 vty_out(vty,
10893 "No BGP prefixes displayed, %ld exist\n",
10894 total_count);
10895 } else
d62a17ae 10896 vty_out(vty,
1ae44dfc
LB
10897 "\nDisplayed %ld routes and %ld total paths\n",
10898 output_count, total_count);
10899 }
d62a17ae 10900 }
718e3744 10901
d62a17ae 10902 return CMD_SUCCESS;
718e3744 10903}
10904
1ae44dfc
LB
10905int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10906 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10907 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10908{
9bcb3eef 10909 struct bgp_dest *dest, *next;
1ae44dfc
LB
10910 unsigned long output_cum = 0;
10911 unsigned long total_cum = 0;
9386b588 10912 unsigned long json_header_depth = 0;
67009e22 10913 struct bgp_table *itable;
0136788c 10914 bool show_msg;
96f3485c 10915 uint8_t show_flags = 0;
0136788c
LB
10916
10917 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10918
96f3485c
MK
10919 if (use_json)
10920 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10921
9bcb3eef
DS
10922 for (dest = bgp_table_top(table); dest; dest = next) {
10923 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10924
9bcb3eef
DS
10925 next = bgp_route_next(dest);
10926 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10927 continue;
67009e22 10928
9bcb3eef 10929 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10930 if (itable != NULL) {
1ae44dfc 10931 struct prefix_rd prd;
06b9f471 10932 char rd[RD_ADDRSTRLEN];
1ae44dfc 10933
9bcb3eef 10934 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10935 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10936 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10937 rd, next == NULL, &output_cum,
10938 &total_cum, &json_header_depth,
1e2ce4f1 10939 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
10940 if (next == NULL)
10941 show_msg = false;
1ae44dfc
LB
10942 }
10943 }
0136788c
LB
10944 if (show_msg) {
10945 if (output_cum == 0)
10946 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10947 total_cum);
10948 else
10949 vty_out(vty,
10950 "\nDisplayed %ld routes and %ld total paths\n",
10951 output_cum, total_cum);
10952 }
1ae44dfc
LB
10953 return CMD_SUCCESS;
10954}
d62a17ae 10955static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 10956 enum bgp_show_type type, void *output_arg,
4027d19b 10957 uint8_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 10958{
d62a17ae 10959 struct bgp_table *table;
9386b588 10960 unsigned long json_header_depth = 0;
96f3485c 10961 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10962
d62a17ae 10963 if (bgp == NULL) {
10964 bgp = bgp_get_default();
10965 }
fee0f4c6 10966
d62a17ae 10967 if (bgp == NULL) {
10968 if (!use_json)
10969 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10970 else
10971 vty_out(vty, "{}\n");
d62a17ae 10972 return CMD_WARNING;
10973 }
4dd6177e 10974
1ae44dfc 10975 table = bgp->rib[afi][safi];
d62a17ae 10976 /* use MPLS and ENCAP specific shows until they are merged */
10977 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10978 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10979 output_arg, use_json);
d62a17ae 10980 }
dba3c1d3
PG
10981
10982 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10983 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10984 output_arg, use_json,
10985 1, NULL, NULL);
10986 }
d62a17ae 10987 /* labeled-unicast routes live in the unicast table */
10988 else if (safi == SAFI_LABELED_UNICAST)
10989 safi = SAFI_UNICAST;
fee0f4c6 10990
96f3485c 10991 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 10992 NULL, NULL, &json_header_depth, show_flags,
4027d19b 10993 rpki_target_state);
fee0f4c6 10994}
10995
d62a17ae 10996static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10997 safi_t safi, uint8_t show_flags)
f186de26 10998{
d62a17ae 10999 struct listnode *node, *nnode;
11000 struct bgp *bgp;
11001 int is_first = 1;
9f049418 11002 bool route_output = false;
96f3485c 11003 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11004
d62a17ae 11005 if (use_json)
11006 vty_out(vty, "{\n");
9f689658 11007
d62a17ae 11008 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11009 route_output = true;
d62a17ae 11010 if (use_json) {
11011 if (!is_first)
11012 vty_out(vty, ",\n");
11013 else
11014 is_first = 0;
11015
11016 vty_out(vty, "\"%s\":",
11017 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11018 ? VRF_DEFAULT_NAME
d62a17ae 11019 : bgp->name);
11020 } else {
11021 vty_out(vty, "\nInstance %s:\n",
11022 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11023 ? VRF_DEFAULT_NAME
d62a17ae 11024 : bgp->name);
11025 }
11026 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11027 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11028 }
9f689658 11029
d62a17ae 11030 if (use_json)
11031 vty_out(vty, "}\n");
9f049418
DS
11032 else if (!route_output)
11033 vty_out(vty, "%% BGP instance not found\n");
f186de26 11034}
11035
718e3744 11036/* Header of detailed BGP route information */
d62a17ae 11037void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11038 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11039 afi_t afi, safi_t safi, json_object *json)
11040{
40381db7 11041 struct bgp_path_info *pi;
b54892e0 11042 const struct prefix *p;
d62a17ae 11043 struct peer *peer;
11044 struct listnode *node, *nnode;
06b9f471 11045 char buf1[RD_ADDRSTRLEN];
0291c246 11046 char prefix_str[BUFSIZ];
d62a17ae 11047 int count = 0;
11048 int best = 0;
11049 int suppress = 0;
c5f1e1b2
C
11050 int accept_own = 0;
11051 int route_filter_translated_v4 = 0;
11052 int route_filter_v4 = 0;
11053 int route_filter_translated_v6 = 0;
11054 int route_filter_v6 = 0;
11055 int llgr_stale = 0;
11056 int no_llgr = 0;
11057 int accept_own_nexthop = 0;
11058 int blackhole = 0;
d62a17ae 11059 int no_export = 0;
11060 int no_advertise = 0;
11061 int local_as = 0;
c5f1e1b2 11062 int no_peer = 0;
d62a17ae 11063 int first = 1;
11064 int has_valid_label = 0;
11065 mpls_label_t label = 0;
11066 json_object *json_adv_to = NULL;
9bedbb1e 11067
9bcb3eef
DS
11068 p = bgp_dest_get_prefix(dest);
11069 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11070
11071 if (has_valid_label)
9bcb3eef 11072 label = label_pton(&dest->local_label);
d62a17ae 11073
44c69747 11074 if (safi == SAFI_EVPN) {
d62a17ae 11075
44c69747 11076 if (!json) {
2dbe669b 11077 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11078 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11079 : "",
2dbe669b 11080 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11081 } else {
11082 json_object_string_add(json, "rd",
11083 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11084 "");
11085 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11086 }
11087 } else {
11088 if (!json) {
8228a9a7 11089 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 11090 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11091 ? prefix_rd2str(prd, buf1,
11092 sizeof(buf1))
11093 : ""),
11094 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 11095
44c69747
LK
11096 } else
11097 json_object_string_add(json, "prefix",
11098 prefix2str(p, prefix_str, sizeof(prefix_str)));
11099 }
11100
11101 if (has_valid_label) {
11102 if (json)
11103 json_object_int_add(json, "localLabel", label);
11104 else
d62a17ae 11105 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11106 }
11107
11108 if (!json)
d62a17ae 11109 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11110 vty_out(vty, "not allocated\n");
718e3744 11111
9bcb3eef 11112 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11113 count++;
40381db7 11114 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11115 best = count;
4056a5f6 11116 if (bgp_path_suppressed(pi))
d62a17ae 11117 suppress = 1;
cee9c031 11118
40381db7 11119 if (pi->attr->community == NULL)
cee9c031
QY
11120 continue;
11121
11122 no_advertise += community_include(
40381db7
DS
11123 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11124 no_export += community_include(pi->attr->community,
cee9c031 11125 COMMUNITY_NO_EXPORT);
40381db7 11126 local_as += community_include(pi->attr->community,
cee9c031 11127 COMMUNITY_LOCAL_AS);
40381db7 11128 accept_own += community_include(pi->attr->community,
cee9c031
QY
11129 COMMUNITY_ACCEPT_OWN);
11130 route_filter_translated_v4 += community_include(
40381db7 11131 pi->attr->community,
cee9c031
QY
11132 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11133 route_filter_translated_v6 += community_include(
40381db7 11134 pi->attr->community,
cee9c031
QY
11135 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11136 route_filter_v4 += community_include(
40381db7 11137 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11138 route_filter_v6 += community_include(
40381db7
DS
11139 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11140 llgr_stale += community_include(pi->attr->community,
cee9c031 11141 COMMUNITY_LLGR_STALE);
40381db7 11142 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11143 COMMUNITY_NO_LLGR);
11144 accept_own_nexthop +=
40381db7 11145 community_include(pi->attr->community,
cee9c031 11146 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11147 blackhole += community_include(pi->attr->community,
cee9c031 11148 COMMUNITY_BLACKHOLE);
40381db7 11149 no_peer += community_include(pi->attr->community,
cee9c031 11150 COMMUNITY_NO_PEER);
d62a17ae 11151 }
718e3744 11152 }
718e3744 11153
d62a17ae 11154 if (!json) {
11155 vty_out(vty, "Paths: (%d available", count);
11156 if (best) {
11157 vty_out(vty, ", best #%d", best);
b84060bb
PG
11158 if (safi == SAFI_UNICAST) {
11159 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11160 vty_out(vty, ", table %s",
11161 VRF_DEFAULT_NAME);
11162 else
11163 vty_out(vty, ", vrf %s",
11164 bgp->name);
11165 }
d62a17ae 11166 } else
11167 vty_out(vty, ", no best path");
11168
c5f1e1b2
C
11169 if (accept_own)
11170 vty_out(vty,
11171 ", accept own local route exported and imported in different VRF");
11172 else if (route_filter_translated_v4)
11173 vty_out(vty,
11174 ", mark translated RTs for VPNv4 route filtering");
11175 else if (route_filter_v4)
11176 vty_out(vty,
11177 ", attach RT as-is for VPNv4 route filtering");
11178 else if (route_filter_translated_v6)
11179 vty_out(vty,
11180 ", mark translated RTs for VPNv6 route filtering");
11181 else if (route_filter_v6)
11182 vty_out(vty,
11183 ", attach RT as-is for VPNv6 route filtering");
11184 else if (llgr_stale)
11185 vty_out(vty,
11186 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11187 else if (no_llgr)
11188 vty_out(vty,
11189 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11190 else if (accept_own_nexthop)
11191 vty_out(vty,
11192 ", accept local nexthop");
11193 else if (blackhole)
11194 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11195 else if (no_export)
11196 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11197 else if (no_advertise)
11198 vty_out(vty, ", not advertised to any peer");
d62a17ae 11199 else if (local_as)
11200 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11201 else if (no_peer)
11202 vty_out(vty,
11203 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11204
11205 if (suppress)
11206 vty_out(vty,
11207 ", Advertisements suppressed by an aggregate.");
11208 vty_out(vty, ")\n");
11209 }
718e3744 11210
d62a17ae 11211 /* If we are not using addpath then we can display Advertised to and
11212 * that will
11213 * show what peers we advertised the bestpath to. If we are using
11214 * addpath
11215 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11216 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11217 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11218 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11219 if (json && !json_adv_to)
11220 json_adv_to = json_object_new_object();
11221
11222 route_vty_out_advertised_to(
11223 vty, peer, &first,
11224 " Advertised to non peer-group peers:\n ",
11225 json_adv_to);
11226 }
11227 }
11228
11229 if (json) {
11230 if (json_adv_to) {
11231 json_object_object_add(json, "advertisedTo",
11232 json_adv_to);
11233 }
11234 } else {
11235 if (first)
11236 vty_out(vty, " Not advertised to any peer");
11237 vty_out(vty, "\n");
11238 }
11239 }
718e3744 11240}
11241
44c69747 11242static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11243 struct bgp_dest *bgp_node, struct vty *vty,
11244 struct bgp *bgp, afi_t afi, safi_t safi,
11245 json_object *json, enum bgp_path_type pathtype,
4027d19b 11246 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11247{
11248 struct bgp_path_info *pi;
11249 int header = 1;
11250 char rdbuf[RD_ADDRSTRLEN];
11251 json_object *json_header = NULL;
11252 json_object *json_paths = NULL;
4933eaaf 11253 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11254
9bcb3eef 11255 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11256 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11257
11258 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11259 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11260 pi->peer, pi->attr, p);
4933eaaf 11261
4027d19b
DS
11262 if (rpki_target_state != RPKI_NOT_BEING_USED
11263 && rpki_curr_state != rpki_target_state)
4933eaaf 11264 continue;
44c69747
LK
11265
11266 if (json && !json_paths) {
11267 /* Instantiate json_paths only if path is valid */
11268 json_paths = json_object_new_array();
11269 if (pfx_rd) {
11270 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11271 json_header = json_object_new_object();
11272 } else
11273 json_header = json;
11274 }
11275
11276 if (header) {
11277 route_vty_out_detail_header(
11278 vty, bgp, bgp_node, pfx_rd,
11279 AFI_IP, safi, json_header);
11280 header = 0;
11281 }
11282 (*display)++;
11283
11284 if (pathtype == BGP_PATH_SHOW_ALL
11285 || (pathtype == BGP_PATH_SHOW_BESTPATH
11286 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11287 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11288 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11289 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11290 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11291 safi, rpki_curr_state, json_paths);
44c69747
LK
11292 }
11293
11294 if (json && json_paths) {
11295 json_object_object_add(json_header, "paths", json_paths);
11296
11297 if (pfx_rd)
11298 json_object_object_add(json, rdbuf, json_header);
11299 }
11300}
11301
718e3744 11302/* Display specified route of BGP table. */
d62a17ae 11303static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11304 struct bgp_table *rib, const char *ip_str,
11305 afi_t afi, safi_t safi,
4027d19b 11306 enum rpki_states rpki_target_state,
d62a17ae 11307 struct prefix_rd *prd, int prefix_check,
9f049418 11308 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11309{
11310 int ret;
d62a17ae 11311 int display = 0;
11312 struct prefix match;
9bcb3eef
DS
11313 struct bgp_dest *dest;
11314 struct bgp_dest *rm;
d62a17ae 11315 struct bgp_table *table;
11316 json_object *json = NULL;
11317 json_object *json_paths = NULL;
11318
11319 /* Check IP address argument. */
11320 ret = str2prefix(ip_str, &match);
11321 if (!ret) {
11322 vty_out(vty, "address is malformed\n");
11323 return CMD_WARNING;
11324 }
718e3744 11325
d62a17ae 11326 match.family = afi2family(afi);
b05a1c8b 11327
44c69747 11328 if (use_json)
d62a17ae 11329 json = json_object_new_object();
718e3744 11330
44c69747 11331 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11332 for (dest = bgp_table_top(rib); dest;
11333 dest = bgp_route_next(dest)) {
11334 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11335
9bcb3eef 11336 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11337 continue;
9bcb3eef 11338 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11339 if (!table)
ea47320b 11340 continue;
d62a17ae 11341
ea47320b
DL
11342 if ((rm = bgp_node_match(table, &match)) == NULL)
11343 continue;
d62a17ae 11344
9bcb3eef 11345 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11346 if (prefix_check
b54892e0 11347 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11348 bgp_dest_unlock_node(rm);
ea47320b
DL
11349 continue;
11350 }
d62a17ae 11351
9bcb3eef 11352 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11353 bgp, afi, safi, json, pathtype,
4027d19b 11354 &display, rpki_target_state);
44c69747 11355
9bcb3eef 11356 bgp_dest_unlock_node(rm);
44c69747
LK
11357 }
11358 } else if (safi == SAFI_EVPN) {
9bcb3eef 11359 struct bgp_dest *longest_pfx;
cded3b72 11360 bool is_exact_pfxlen_match = false;
44c69747 11361
9bcb3eef
DS
11362 for (dest = bgp_table_top(rib); dest;
11363 dest = bgp_route_next(dest)) {
11364 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11365
9bcb3eef 11366 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11367 continue;
9bcb3eef 11368 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11369 if (!table)
11370 continue;
11371
11372 longest_pfx = NULL;
cded3b72 11373 is_exact_pfxlen_match = false;
44c69747
LK
11374 /*
11375 * Search through all the prefixes for a match. The
11376 * pfx's are enumerated in ascending order of pfxlens.
11377 * So, the last pfx match is the longest match. Set
11378 * is_exact_pfxlen_match when we get exact pfxlen match
11379 */
11380 for (rm = bgp_table_top(table); rm;
11381 rm = bgp_route_next(rm)) {
b54892e0 11382 const struct prefix *rm_p =
9bcb3eef 11383 bgp_dest_get_prefix(rm);
44c69747
LK
11384 /*
11385 * Get prefixlen of the ip-prefix within type5
11386 * evpn route
11387 */
b54892e0
DS
11388 if (evpn_type5_prefix_match(rm_p, &match)
11389 && rm->info) {
44c69747
LK
11390 longest_pfx = rm;
11391 int type5_pfxlen =
b54892e0
DS
11392 bgp_evpn_get_type5_prefixlen(
11393 rm_p);
44c69747 11394 if (type5_pfxlen == match.prefixlen) {
cded3b72 11395 is_exact_pfxlen_match = true;
9bcb3eef 11396 bgp_dest_unlock_node(rm);
44c69747
LK
11397 break;
11398 }
d62a17ae 11399 }
11400 }
ea47320b 11401
44c69747
LK
11402 if (!longest_pfx)
11403 continue;
11404
11405 if (prefix_check && !is_exact_pfxlen_match)
11406 continue;
11407
11408 rm = longest_pfx;
9bcb3eef 11409 bgp_dest_lock_node(rm);
44c69747 11410
9bcb3eef 11411 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11412 bgp, afi, safi, json, pathtype,
4027d19b 11413 &display, rpki_target_state);
44c69747 11414
9bcb3eef 11415 bgp_dest_unlock_node(rm);
d62a17ae 11416 }
98a9dbc7 11417 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11418 if (use_json)
11419 json_paths = json_object_new_array();
11420
63a0b7a9
PG
11421 display = bgp_flowspec_display_match_per_ip(afi, rib,
11422 &match, prefix_check,
11423 vty,
11424 use_json,
11425 json_paths);
d5f20468
SP
11426 if (use_json) {
11427 if (display)
11428 json_object_object_add(json, "paths",
11429 json_paths);
11430 else
11431 json_object_free(json_paths);
11432 }
d62a17ae 11433 } else {
9bcb3eef
DS
11434 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11435 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11436 if (!prefix_check
9bcb3eef
DS
11437 || dest_p->prefixlen == match.prefixlen) {
11438 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11439 safi, json, pathtype,
4027d19b 11440 &display, rpki_target_state);
d62a17ae 11441 }
11442
9bcb3eef 11443 bgp_dest_unlock_node(dest);
d62a17ae 11444 }
11445 }
e5eee9af 11446
d62a17ae 11447 if (use_json) {
996c9314 11448 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11449 json, JSON_C_TO_STRING_PRETTY |
11450 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11451 json_object_free(json);
11452 } else {
11453 if (!display) {
11454 vty_out(vty, "%% Network not in table\n");
11455 return CMD_WARNING;
11456 }
11457 }
b05a1c8b 11458
d62a17ae 11459 return CMD_SUCCESS;
718e3744 11460}
11461
fee0f4c6 11462/* Display specified route of Main RIB */
d62a17ae 11463static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11464 afi_t afi, safi_t safi, struct prefix_rd *prd,
11465 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11466 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11467{
9b86009a 11468 if (!bgp) {
d62a17ae 11469 bgp = bgp_get_default();
9b86009a
RW
11470 if (!bgp) {
11471 if (!use_json)
11472 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11473 else
11474 vty_out(vty, "{}\n");
9b86009a
RW
11475 return CMD_WARNING;
11476 }
11477 }
d62a17ae 11478
11479 /* labeled-unicast routes live in the unicast table */
11480 if (safi == SAFI_LABELED_UNICAST)
11481 safi = SAFI_UNICAST;
11482
11483 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11484 afi, safi, rpki_target_state, prd,
8aa22bbb 11485 prefix_check, pathtype, use_json);
d62a17ae 11486}
11487
11488static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11489 struct cmd_token **argv, bool exact, afi_t afi,
11490 safi_t safi, bool uj)
d62a17ae 11491{
11492 struct lcommunity *lcom;
11493 struct buffer *b;
11494 int i;
11495 char *str;
11496 int first = 0;
96f3485c 11497 uint8_t show_flags = 0;
4f28b2b5 11498 int ret;
96f3485c
MK
11499
11500 if (uj)
11501 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11502
11503 b = buffer_new(1024);
11504 for (i = 0; i < argc; i++) {
11505 if (first)
11506 buffer_putc(b, ' ');
11507 else {
11508 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11509 first = 1;
11510 buffer_putstr(b, argv[i]->arg);
11511 }
11512 }
11513 }
11514 buffer_putc(b, '\0');
57d187bc 11515
d62a17ae 11516 str = buffer_getstr(b);
11517 buffer_free(b);
57d187bc 11518
d62a17ae 11519 lcom = lcommunity_str2com(str);
11520 XFREE(MTYPE_TMP, str);
11521 if (!lcom) {
11522 vty_out(vty, "%% Large-community malformed\n");
11523 return CMD_WARNING;
11524 }
57d187bc 11525
4f28b2b5 11526 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11527 (exact ? bgp_show_type_lcommunity_exact
11528 : bgp_show_type_lcommunity),
11529 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11530
11531 lcommunity_free(&lcom);
11532 return ret;
57d187bc
JS
11533}
11534
d62a17ae 11535static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11536 const char *lcom, bool exact, afi_t afi,
11537 safi_t safi, bool uj)
57d187bc 11538{
d62a17ae 11539 struct community_list *list;
96f3485c
MK
11540 uint8_t show_flags = 0;
11541
11542 if (uj)
11543 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11544
57d187bc 11545
e237b0d2 11546 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11547 LARGE_COMMUNITY_LIST_MASTER);
11548 if (list == NULL) {
11549 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11550 lcom);
11551 return CMD_WARNING;
11552 }
57d187bc 11553
36a206db 11554 return bgp_show(vty, bgp, afi, safi,
11555 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11556 : bgp_show_type_lcommunity_list),
1e2ce4f1 11557 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11558}
11559
52951b63
DS
11560DEFUN (show_ip_bgp_large_community_list,
11561 show_ip_bgp_large_community_list_cmd,
36a206db 11562 "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
11563 SHOW_STR
11564 IP_STR
11565 BGP_STR
11566 BGP_INSTANCE_HELP_STR
9bedbb1e 11567 BGP_AFI_HELP_STR
4dd6177e 11568 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11569 "Display routes matching the large-community-list\n"
11570 "large-community-list number\n"
11571 "large-community-list name\n"
36a206db 11572 "Exact match of the large-communities\n"
52951b63
DS
11573 JSON_STR)
11574{
d62a17ae 11575 afi_t afi = AFI_IP6;
11576 safi_t safi = SAFI_UNICAST;
11577 int idx = 0;
36a206db 11578 bool exact_match = 0;
4d678463 11579 struct bgp *bgp = NULL;
9f049418 11580 bool uj = use_json(argc, argv);
d62a17ae 11581
4d678463
KA
11582 if (uj)
11583 argc--;
11584
11585 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11586 &bgp, uj);
11587 if (!idx)
11588 return CMD_WARNING;
d62a17ae 11589
11590 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11591
11592 const char *clist_number_or_name = argv[++idx]->arg;
11593
11594 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11595 exact_match = 1;
11596
11597 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11598 exact_match, afi, safi, uj);
52951b63
DS
11599}
11600DEFUN (show_ip_bgp_large_community,
11601 show_ip_bgp_large_community_cmd,
36a206db 11602 "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
11603 SHOW_STR
11604 IP_STR
11605 BGP_STR
11606 BGP_INSTANCE_HELP_STR
9bedbb1e 11607 BGP_AFI_HELP_STR
4dd6177e 11608 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11609 "Display routes matching the large-communities\n"
11610 "List of large-community numbers\n"
36a206db 11611 "Exact match of the large-communities\n"
52951b63
DS
11612 JSON_STR)
11613{
d62a17ae 11614 afi_t afi = AFI_IP6;
11615 safi_t safi = SAFI_UNICAST;
11616 int idx = 0;
36a206db 11617 bool exact_match = 0;
4d678463 11618 struct bgp *bgp = NULL;
9f049418 11619 bool uj = use_json(argc, argv);
96f3485c 11620 uint8_t show_flags = 0;
d62a17ae 11621
96f3485c
MK
11622 if (uj) {
11623 argc--;
11624 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11625 }
4d678463 11626
96f3485c
MK
11627 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11628 &bgp, uj);
11629 if (!idx)
11630 return CMD_WARNING;
d62a17ae 11631
36a206db 11632 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11633 if (argv_find(argv, argc, "exact-match", &idx))
11634 exact_match = 1;
11635 return bgp_show_lcommunity(vty, bgp, argc, argv,
11636 exact_match, afi, safi, uj);
11637 } else
d62a17ae 11638 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11639 bgp_show_type_lcommunity_all, NULL, show_flags,
11640 RPKI_NOT_BEING_USED);
52951b63
DS
11641}
11642
71f1613a
DA
11643static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11644 safi_t safi, struct json_object *json_array);
d62a17ae 11645static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11646 safi_t safi, struct json_object *json);
e01ca200 11647
7b2ff250 11648
9ab0cf58
PG
11649DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11650 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11651 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11652 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11653{
11654 bool uj = use_json(argc, argv);
11655 struct bgp *bgp = NULL;
ec76a1d1
DA
11656 safi_t safi = SAFI_UNICAST;
11657 afi_t afi = AFI_IP6;
4265b261 11658 int idx = 0;
6c9d22e2
PG
11659 struct json_object *json_all = NULL;
11660 struct json_object *json_afi_safi = NULL;
4265b261
PG
11661
11662 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11663 &bgp, false);
71f1613a 11664 if (!idx)
4265b261 11665 return CMD_WARNING;
6c9d22e2 11666
4265b261 11667 if (uj)
6c9d22e2 11668 json_all = json_object_new_object();
4265b261 11669
9ab0cf58
PG
11670 FOREACH_AFI_SAFI (afi, safi) {
11671 /*
11672 * So limit output to those afi/safi pairs that
11673 * actually have something interesting in them
11674 */
11675 if (strmatch(get_afi_safi_str(afi, safi, true),
11676 "Unknown")) {
11677 continue;
11678 }
11679 if (uj) {
11680 json_afi_safi = json_object_new_array();
11681 json_object_object_add(
11682 json_all,
11683 get_afi_safi_str(afi, safi, true),
11684 json_afi_safi);
11685 } else {
11686 json_afi_safi = NULL;
6c9d22e2 11687 }
9ab0cf58
PG
11688
11689 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11690 }
6c9d22e2
PG
11691
11692 if (uj) {
9ab0cf58
PG
11693 vty_out(vty, "%s",
11694 json_object_to_json_string_ext(
11695 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11696 json_object_free(json_all);
4265b261 11697 }
6c9d22e2 11698
4265b261
PG
11699 return CMD_SUCCESS;
11700}
11701
7b2ff250 11702/* BGP route print out function without JSON */
14718643
PG
11703DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11704 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11705 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11706 SHOW_STR
11707 IP_STR
11708 BGP_STR
11709 BGP_INSTANCE_HELP_STR
11710 L2VPN_HELP_STR
11711 EVPN_HELP_STR
11712 "BGP RIB advertisement statistics\n"
11713 JSON_STR)
11714{
ec76a1d1
DA
11715 afi_t afi = AFI_IP6;
11716 safi_t safi = SAFI_UNICAST;
14718643
PG
11717 struct bgp *bgp = NULL;
11718 int idx = 0, ret;
11719 bool uj = use_json(argc, argv);
11720 struct json_object *json_afi_safi = NULL, *json = NULL;
11721
11722 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11723 &bgp, false);
11724 if (!idx)
11725 return CMD_WARNING;
11726
11727 if (uj)
11728 json_afi_safi = json_object_new_array();
11729 else
11730 json_afi_safi = NULL;
11731
11732 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11733
11734 if (uj) {
11735 json = json_object_new_object();
11736 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11737 json_afi_safi);
11738 vty_out(vty, "%s", json_object_to_json_string_ext(
11739 json, JSON_C_TO_STRING_PRETTY));
11740 json_object_free(json);
11741 }
11742 return ret;
11743}
11744
893cccd0 11745/* BGP route print out function without JSON */
9ab0cf58
PG
11746DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11747 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11748 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11749 "]]\
893cccd0 11750 statistics [json]",
9ab0cf58
PG
11751 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11752 BGP_SAFI_WITH_LABEL_HELP_STR
11753 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11754{
ec76a1d1
DA
11755 afi_t afi = AFI_IP6;
11756 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11757 struct bgp *bgp = NULL;
11758 int idx = 0, ret;
11759 bool uj = use_json(argc, argv);
6c9d22e2 11760 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11761
11762 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11763 &bgp, false);
11764 if (!idx)
11765 return CMD_WARNING;
6c9d22e2 11766
893cccd0 11767 if (uj)
6c9d22e2
PG
11768 json_afi_safi = json_object_new_array();
11769 else
11770 json_afi_safi = NULL;
11771
11772 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11773
11774 if (uj) {
11775 json = json_object_new_object();
11776 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11777 json_afi_safi);
9ab0cf58
PG
11778 vty_out(vty, "%s",
11779 json_object_to_json_string_ext(
11780 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11781 json_object_free(json);
11782 }
11783 return ret;
893cccd0 11784}
7b2ff250
DW
11785
11786/* BGP route print out function without JSON */
96f3485c 11787DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11788 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11789 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11790 "]]\
96f3485c 11791 <[all$all] dampening <parameters>\
7b2ff250
DW
11792 |route-map WORD\
11793 |prefix-list WORD\
11794 |filter-list WORD\
7b2ff250
DW
11795 |community-list <(1-500)|WORD> [exact-match]\
11796 |A.B.C.D/M longer-prefixes\
11797 |X:X::X:X/M longer-prefixes\
893cccd0 11798 >",
9ab0cf58
PG
11799 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11800 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11801 "Display the entries for all address families\n"
9ab0cf58
PG
11802 "Display detailed information about dampening\n"
11803 "Display detail of configured dampening parameters\n"
11804 "Display routes matching the route-map\n"
11805 "A route-map to match on\n"
11806 "Display routes conforming to the prefix-list\n"
11807 "Prefix-list name\n"
11808 "Display routes conforming to the filter-list\n"
11809 "Regular expression access list name\n"
11810 "Display routes matching the community-list\n"
11811 "community-list number\n"
11812 "community-list name\n"
11813 "Exact match of the communities\n"
11814 "IPv4 prefix\n"
11815 "Display route and more specific routes\n"
11816 "IPv6 prefix\n"
11817 "Display route and more specific routes\n")
718e3744 11818{
d62a17ae 11819 afi_t afi = AFI_IP6;
11820 safi_t safi = SAFI_UNICAST;
11821 int exact_match = 0;
d62a17ae 11822 struct bgp *bgp = NULL;
11823 int idx = 0;
96f3485c
MK
11824 uint8_t show_flags = 0;
11825
11826 /* [<ipv4|ipv6> [all]] */
11827 if (all) {
11828 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11829 if (argv_find(argv, argc, "ipv4", &idx))
11830 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11831
11832 if (argv_find(argv, argc, "ipv6", &idx))
11833 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11834 }
d62a17ae 11835
11836 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11837 &bgp, false);
d62a17ae 11838 if (!idx)
11839 return CMD_WARNING;
11840
d62a17ae 11841 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11842 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11843 return bgp_show_dampening_parameters(vty, afi, safi,
11844 show_flags);
d62a17ae 11845 }
c016b6c7 11846
d62a17ae 11847 if (argv_find(argv, argc, "prefix-list", &idx))
11848 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11849 safi, bgp_show_type_prefix_list);
11850
11851 if (argv_find(argv, argc, "filter-list", &idx))
11852 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11853 safi, bgp_show_type_filter_list);
11854
d62a17ae 11855 if (argv_find(argv, argc, "route-map", &idx))
11856 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11857 safi, bgp_show_type_route_map);
11858
d62a17ae 11859 if (argv_find(argv, argc, "community-list", &idx)) {
11860 const char *clist_number_or_name = argv[++idx]->arg;
11861 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11862 exact_match = 1;
11863 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11864 exact_match, afi, safi);
11865 }
11866 /* prefix-longer */
11867 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11868 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11869 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11870 safi,
11871 bgp_show_type_prefix_longer);
11872
7b2ff250
DW
11873 return CMD_WARNING;
11874}
11875
11876/* BGP route print out function with JSON */
ae248832 11877DEFPY (show_ip_bgp_json,
7b2ff250
DW
11878 show_ip_bgp_json_cmd,
11879 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11880 [all$all]\
cf4898bc
QY
11881 [cidr-only\
11882 |dampening <flap-statistics|dampened-paths>\
11883 |community [AA:NN|local-AS|no-advertise|no-export\
11884 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11885 |accept-own|accept-own-nexthop|route-filter-v6\
11886 |route-filter-v4|route-filter-translated-v6\
11887 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 11888 |rpki <invalid|valid|notfound>\
ae248832 11889 ] [json$uj | wide$wide]",
7b2ff250
DW
11890 SHOW_STR
11891 IP_STR
11892 BGP_STR
11893 BGP_INSTANCE_HELP_STR
11894 BGP_AFI_HELP_STR
11895 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11896 "Display the entries for all address families\n"
7b2ff250
DW
11897 "Display only routes with non-natural netmasks\n"
11898 "Display detailed information about dampening\n"
11899 "Display flap statistics of routes\n"
11900 "Display paths suppressed due to dampening\n"
11901 "Display routes matching the communities\n"
d0086e8e
AD
11902 COMMUNITY_AANN_STR
11903 "Do not send outside local AS (well-known community)\n"
11904 "Do not advertise to any peer (well-known community)\n"
11905 "Do not export to next AS (well-known community)\n"
11906 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11907 "Do not export to any peer (well-known community)\n"
11908 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11909 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11910 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11911 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11912 "Should accept VPN route with local nexthop (well-known community)\n"
11913 "RT VPNv6 route filtering (well-known community)\n"
11914 "RT VPNv4 route filtering (well-known community)\n"
11915 "RT translated VPNv6 route filtering (well-known community)\n"
11916 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11917 "Exact match of the communities\n"
1e2ce4f1
DS
11918 "RPKI route types\n"
11919 "A valid path as determined by rpki\n"
11920 "A invalid path as determined by rpki\n"
11921 "A path that has no rpki data\n"
ae248832
MK
11922 JSON_STR
11923 "Increase table width for longer prefixes\n")
7b2ff250
DW
11924{
11925 afi_t afi = AFI_IP6;
11926 safi_t safi = SAFI_UNICAST;
11927 enum bgp_show_type sh_type = bgp_show_type_normal;
11928 struct bgp *bgp = NULL;
11929 int idx = 0;
d0086e8e 11930 int exact_match = 0;
96f3485c
MK
11931 char *community = NULL;
11932 bool first = true;
11933 uint8_t show_flags = 0;
4027d19b 11934 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
11935
11936 if (uj) {
9f049418 11937 argc--;
96f3485c
MK
11938 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11939 }
11940
11941 /* [<ipv4|ipv6> [all]] */
11942 if (all) {
11943 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11944
11945 if (argv_find(argv, argc, "ipv4", &idx))
11946 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11947
11948 if (argv_find(argv, argc, "ipv6", &idx))
11949 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11950 }
11951
11952 if (wide)
11953 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11954
11955 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11956 &bgp, uj);
7b2ff250
DW
11957 if (!idx)
11958 return CMD_WARNING;
11959
7b2ff250 11960 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11961 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11962
11963 if (argv_find(argv, argc, "dampening", &idx)) {
11964 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11965 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11966 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11967 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11968 }
11969
11970 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11971 char *maybecomm = NULL;
d0086e8e 11972
79bc257a
RW
11973 if (idx + 1 < argc) {
11974 if (argv[idx + 1]->type == VARIABLE_TKN)
11975 maybecomm = argv[idx + 1]->arg;
11976 else
11977 maybecomm = argv[idx + 1]->text;
11978 }
11979
cf4898bc
QY
11980 if (maybecomm && !strmatch(maybecomm, "json")
11981 && !strmatch(maybecomm, "exact-match"))
11982 community = maybecomm;
d0086e8e 11983
cf4898bc
QY
11984 if (argv_find(argv, argc, "exact-match", &idx))
11985 exact_match = 1;
d0086e8e 11986
96f3485c
MK
11987 if (!community)
11988 sh_type = bgp_show_type_community_all;
11989 }
11990
1e2ce4f1
DS
11991 if (argv_find(argv, argc, "rpki", &idx)) {
11992 sh_type = bgp_show_type_rpki;
11993 if (argv_find(argv, argc, "valid", &idx))
4027d19b 11994 rpki_target_state = RPKI_VALID;
1e2ce4f1 11995 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 11996 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
11997 }
11998
96f3485c
MK
11999 if (!all) {
12000 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12001 if (community)
12002 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12003 exact_match, afi, safi,
12004 show_flags);
cf4898bc 12005 else
96f3485c 12006 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12007 show_flags, rpki_target_state);
96f3485c
MK
12008 } else {
12009 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12010 * AFI_IP6 */
12011
12012 if (uj)
12013 vty_out(vty, "{\n");
12014
12015 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12016 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12017 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12018 ? AFI_IP
12019 : AFI_IP6;
12020 FOREACH_SAFI (safi) {
96f3485c
MK
12021 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12022 continue;
12023
12024 if (uj) {
12025 if (first)
12026 first = false;
12027 else
12028 vty_out(vty, ",\n");
12029 vty_out(vty, "\"%s\":{\n",
12030 get_afi_safi_str(afi, safi,
12031 true));
12032 } else
12033 vty_out(vty,
12034 "\nFor address family: %s\n",
12035 get_afi_safi_str(afi, safi,
12036 false));
12037
12038 if (community)
12039 bgp_show_community(vty, bgp, community,
12040 exact_match, afi,
12041 safi, show_flags);
12042 else
12043 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12044 NULL, show_flags,
4027d19b 12045 rpki_target_state);
96f3485c
MK
12046 if (uj)
12047 vty_out(vty, "}\n");
12048 }
12049 } else {
12050 /* show <ip> bgp all: for each AFI and SAFI*/
12051 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12052 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12053 continue;
12054
12055 if (uj) {
12056 if (first)
12057 first = false;
12058 else
12059 vty_out(vty, ",\n");
d0086e8e 12060
96f3485c
MK
12061 vty_out(vty, "\"%s\":{\n",
12062 get_afi_safi_str(afi, safi,
12063 true));
12064 } else
12065 vty_out(vty,
12066 "\nFor address family: %s\n",
12067 get_afi_safi_str(afi, safi,
12068 false));
12069
12070 if (community)
12071 bgp_show_community(vty, bgp, community,
12072 exact_match, afi,
12073 safi, show_flags);
12074 else
12075 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12076 NULL, show_flags,
4027d19b 12077 rpki_target_state);
96f3485c
MK
12078 if (uj)
12079 vty_out(vty, "}\n");
12080 }
12081 }
12082 if (uj)
12083 vty_out(vty, "}\n");
12084 }
12085 return CMD_SUCCESS;
a636c635 12086}
47fc97cc 12087
718e3744 12088DEFUN (show_ip_bgp_route,
12089 show_ip_bgp_route_cmd,
8aa22bbb 12090 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
718e3744 12091 SHOW_STR
12092 IP_STR
12093 BGP_STR
a636c635 12094 BGP_INSTANCE_HELP_STR
4f280b15 12095 BGP_AFI_HELP_STR
4dd6177e 12096 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12097 "Network in the BGP routing table to display\n"
0c7b1b01 12098 "IPv4 prefix\n"
8c3deaae 12099 "Network in the BGP routing table to display\n"
0c7b1b01 12100 "IPv6 prefix\n"
4092b06c 12101 "Display only the bestpath\n"
b05a1c8b 12102 "Display only multipaths\n"
8aa22bbb
DS
12103 "Display only paths that match the specified rpki state\n"
12104 "A valid path as determined by rpki\n"
12105 "A invalid path as determined by rpki\n"
12106 "A path that has no rpki data\n"
9973d184 12107 JSON_STR)
4092b06c 12108{
d62a17ae 12109 int prefix_check = 0;
ae19d7dd 12110
d62a17ae 12111 afi_t afi = AFI_IP6;
12112 safi_t safi = SAFI_UNICAST;
12113 char *prefix = NULL;
12114 struct bgp *bgp = NULL;
12115 enum bgp_path_type path_type;
9f049418 12116 bool uj = use_json(argc, argv);
b05a1c8b 12117
d62a17ae 12118 int idx = 0;
ae19d7dd 12119
d62a17ae 12120 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12121 &bgp, uj);
d62a17ae 12122 if (!idx)
12123 return CMD_WARNING;
c41247f5 12124
d62a17ae 12125 if (!bgp) {
12126 vty_out(vty,
12127 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12128 return CMD_WARNING;
12129 }
a636c635 12130
d62a17ae 12131 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12132 if (argv_find(argv, argc, "A.B.C.D", &idx)
12133 || argv_find(argv, argc, "X:X::X:X", &idx))
12134 prefix_check = 0;
12135 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12136 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12137 prefix_check = 1;
12138
12139 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12140 && afi != AFI_IP6) {
12141 vty_out(vty,
12142 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12143 return CMD_WARNING;
12144 }
12145 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12146 && afi != AFI_IP) {
12147 vty_out(vty,
12148 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12149 return CMD_WARNING;
12150 }
12151
12152 prefix = argv[idx]->arg;
12153
12154 /* [<bestpath|multipath>] */
12155 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12156 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12157 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12158 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12159 else
360660c6 12160 path_type = BGP_PATH_SHOW_ALL;
a636c635 12161
d62a17ae 12162 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12163 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12164}
12165
8c3deaae
QY
12166DEFUN (show_ip_bgp_regexp,
12167 show_ip_bgp_regexp_cmd,
3e5b31b3 12168 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12169 SHOW_STR
12170 IP_STR
12171 BGP_STR
b00b230a 12172 BGP_INSTANCE_HELP_STR
4f280b15 12173 BGP_AFI_HELP_STR
4dd6177e 12174 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12175 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12176 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12177 JSON_STR)
8c3deaae 12178{
d62a17ae 12179 afi_t afi = AFI_IP6;
12180 safi_t safi = SAFI_UNICAST;
12181 struct bgp *bgp = NULL;
3e5b31b3
DA
12182 bool uj = use_json(argc, argv);
12183 char *regstr = NULL;
8c3deaae 12184
d62a17ae 12185 int idx = 0;
12186 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12187 &bgp, false);
d62a17ae 12188 if (!idx)
12189 return CMD_WARNING;
8c3deaae 12190
d62a17ae 12191 // get index of regex
3e5b31b3
DA
12192 if (argv_find(argv, argc, "REGEX", &idx))
12193 regstr = argv[idx]->arg;
8c3deaae 12194
5f71d11c 12195 assert(regstr);
3e5b31b3
DA
12196 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12197 bgp_show_type_regexp, uj);
8c3deaae
QY
12198}
12199
ae248832 12200DEFPY (show_ip_bgp_instance_all,
a636c635 12201 show_ip_bgp_instance_all_cmd,
ae248832 12202 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12203 SHOW_STR
a636c635 12204 IP_STR
4092b06c 12205 BGP_STR
a636c635 12206 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12207 BGP_AFI_HELP_STR
4dd6177e 12208 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12209 JSON_STR
12210 "Increase table width for longer prefixes\n")
4092b06c 12211{
d62a17ae 12212 afi_t afi = AFI_IP;
12213 safi_t safi = SAFI_UNICAST;
12214 struct bgp *bgp = NULL;
d62a17ae 12215 int idx = 0;
96f3485c 12216 uint8_t show_flags = 0;
ae19d7dd 12217
96f3485c 12218 if (uj) {
d62a17ae 12219 argc--;
96f3485c
MK
12220 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12221 }
12222
12223 if (wide)
12224 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12225
9f049418
DS
12226 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12227 &bgp, uj);
12228 if (!idx)
12229 return CMD_WARNING;
12230
96f3485c 12231 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12232 return CMD_SUCCESS;
e3e29b32
LB
12233}
12234
a4d82a8a 12235static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12236 afi_t afi, safi_t safi, enum bgp_show_type type,
12237 bool use_json)
718e3744 12238{
d62a17ae 12239 regex_t *regex;
12240 int rc;
96f3485c
MK
12241 uint8_t show_flags = 0;
12242
12243 if (use_json)
12244 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12245
c3900853 12246 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12247 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12248 regstr);
12249 return CMD_WARNING_CONFIG_FAILED;
12250 }
12251
d62a17ae 12252 regex = bgp_regcomp(regstr);
12253 if (!regex) {
12254 vty_out(vty, "Can't compile regexp %s\n", regstr);
12255 return CMD_WARNING;
12256 }
a636c635 12257
1e2ce4f1
DS
12258 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12259 RPKI_NOT_BEING_USED);
d62a17ae 12260 bgp_regex_free(regex);
12261 return rc;
e3e29b32
LB
12262}
12263
d62a17ae 12264static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12265 const char *prefix_list_str, afi_t afi,
12266 safi_t safi, enum bgp_show_type type)
e3e29b32 12267{
d62a17ae 12268 struct prefix_list *plist;
96f3485c 12269 uint8_t show_flags = 0;
718e3744 12270
d62a17ae 12271 plist = prefix_list_lookup(afi, prefix_list_str);
12272 if (plist == NULL) {
12273 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12274 prefix_list_str);
12275 return CMD_WARNING;
12276 }
718e3744 12277
1e2ce4f1
DS
12278 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12279 RPKI_NOT_BEING_USED);
4092b06c
DS
12280}
12281
d62a17ae 12282static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12283 const char *filter, afi_t afi, safi_t safi,
12284 enum bgp_show_type type)
4092b06c 12285{
d62a17ae 12286 struct as_list *as_list;
96f3485c 12287 uint8_t show_flags = 0;
718e3744 12288
d62a17ae 12289 as_list = as_list_lookup(filter);
12290 if (as_list == NULL) {
12291 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12292 filter);
12293 return CMD_WARNING;
12294 }
a636c635 12295
1e2ce4f1
DS
12296 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12297 RPKI_NOT_BEING_USED);
718e3744 12298}
12299
d62a17ae 12300static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12301 const char *rmap_str, afi_t afi, safi_t safi,
12302 enum bgp_show_type type)
718e3744 12303{
d62a17ae 12304 struct route_map *rmap;
96f3485c 12305 uint8_t show_flags = 0;
bb46e94f 12306
d62a17ae 12307 rmap = route_map_lookup_by_name(rmap_str);
12308 if (!rmap) {
12309 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12310 return CMD_WARNING;
12311 }
12312
1e2ce4f1
DS
12313 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12314 RPKI_NOT_BEING_USED);
d62a17ae 12315}
12316
7f323236
DW
12317static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12318 const char *comstr, int exact, afi_t afi,
96f3485c 12319 safi_t safi, uint8_t show_flags)
d62a17ae 12320{
12321 struct community *com;
d62a17ae 12322 int ret = 0;
12323
7f323236 12324 com = community_str2com(comstr);
d62a17ae 12325 if (!com) {
7f323236 12326 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12327 return CMD_WARNING;
12328 }
12329
12330 ret = bgp_show(vty, bgp, afi, safi,
12331 (exact ? bgp_show_type_community_exact
12332 : bgp_show_type_community),
1e2ce4f1 12333 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12334 community_free(&com);
46c3ce83 12335
d62a17ae 12336 return ret;
718e3744 12337}
12338
d62a17ae 12339static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12340 const char *com, int exact, afi_t afi,
12341 safi_t safi)
50ef26d4 12342{
d62a17ae 12343 struct community_list *list;
96f3485c 12344 uint8_t show_flags = 0;
50ef26d4 12345
e237b0d2 12346 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12347 if (list == NULL) {
12348 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12349 return CMD_WARNING;
12350 }
718e3744 12351
d62a17ae 12352 return bgp_show(vty, bgp, afi, safi,
12353 (exact ? bgp_show_type_community_list_exact
12354 : bgp_show_type_community_list),
1e2ce4f1 12355 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12356}
12357
d62a17ae 12358static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12359 const char *prefix, afi_t afi, safi_t safi,
12360 enum bgp_show_type type)
718e3744 12361{
d62a17ae 12362 int ret;
12363 struct prefix *p;
96f3485c 12364 uint8_t show_flags = 0;
47fc97cc 12365
d62a17ae 12366 p = prefix_new();
95cbbd2a 12367
d62a17ae 12368 ret = str2prefix(prefix, p);
12369 if (!ret) {
12370 vty_out(vty, "%% Malformed Prefix\n");
12371 return CMD_WARNING;
12372 }
47e9b292 12373
1e2ce4f1
DS
12374 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12375 RPKI_NOT_BEING_USED);
63265b5c 12376 prefix_free(&p);
d62a17ae 12377 return ret;
12378}
12379
d62a17ae 12380enum bgp_stats {
12381 BGP_STATS_MAXBITLEN = 0,
12382 BGP_STATS_RIB,
12383 BGP_STATS_PREFIXES,
12384 BGP_STATS_TOTPLEN,
12385 BGP_STATS_UNAGGREGATEABLE,
12386 BGP_STATS_MAX_AGGREGATEABLE,
12387 BGP_STATS_AGGREGATES,
12388 BGP_STATS_SPACE,
12389 BGP_STATS_ASPATH_COUNT,
12390 BGP_STATS_ASPATH_MAXHOPS,
12391 BGP_STATS_ASPATH_TOTHOPS,
12392 BGP_STATS_ASPATH_MAXSIZE,
12393 BGP_STATS_ASPATH_TOTSIZE,
12394 BGP_STATS_ASN_HIGHEST,
12395 BGP_STATS_MAX,
a636c635 12396};
2815e61f 12397
9ab0cf58 12398#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12399#define TABLE_STATS_IDX_JSON 1
12400
12401static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12402 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12403 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12404 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12405 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12406 "unaggregateablePrefixes"},
12407 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12408 "maximumAggregateablePrefixes"},
12409 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12410 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12411 [BGP_STATS_SPACE] = {"Address space advertised",
12412 "addressSpaceAdvertised"},
9ab0cf58
PG
12413 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12414 "advertisementsWithPaths"},
12415 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12416 "longestAsPath"},
12417 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12418 "largestAsPath"},
12419 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12420 "averageAsPathLengthHops"},
12421 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12422 "averageAsPathSizeBytes"},
12423 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12424 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12425};
2815e61f 12426
d62a17ae 12427struct bgp_table_stats {
12428 struct bgp_table *table;
12429 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12430 double total_space;
ff7924f6
PJ
12431};
12432
9bcb3eef 12433static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12434 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12435{
9bcb3eef 12436 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12437 struct bgp_path_info *pi;
b54892e0 12438 const struct prefix *rn_p;
d62a17ae 12439
9bcb3eef 12440 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12441 return;
d62a17ae 12442
9bcb3eef 12443 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12444 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12445 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12446
9c14ec72 12447 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12448 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12449 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12450
9bcb3eef 12451 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12452 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12453 /* announced address space */
12454 if (space)
b54892e0 12455 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12456 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12457 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12458
9c14ec72 12459
9bcb3eef 12460 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12461 ts->counts[BGP_STATS_RIB]++;
12462
05864da7
DS
12463 if (CHECK_FLAG(pi->attr->flag,
12464 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12465 ts->counts[BGP_STATS_AGGREGATES]++;
12466
12467 /* as-path stats */
05864da7 12468 if (pi->attr->aspath) {
9c14ec72
RW
12469 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12470 unsigned int size = aspath_size(pi->attr->aspath);
12471 as_t highest = aspath_highest(pi->attr->aspath);
12472
12473 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12474
12475 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12476 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12477
12478 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12479 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12480
12481 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12482 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12483 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12484 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12485 }
12486 }
12487}
12488
12489static int bgp_table_stats_walker(struct thread *t)
12490{
9bcb3eef
DS
12491 struct bgp_dest *dest, *ndest;
12492 struct bgp_dest *top;
9c14ec72
RW
12493 struct bgp_table_stats *ts = THREAD_ARG(t);
12494 unsigned int space = 0;
12495
12496 if (!(top = bgp_table_top(ts->table)))
12497 return 0;
12498
12499 switch (ts->table->afi) {
12500 case AFI_IP:
12501 space = IPV4_MAX_BITLEN;
12502 break;
12503 case AFI_IP6:
12504 space = IPV6_MAX_BITLEN;
12505 break;
3ba7b4af
TA
12506 case AFI_L2VPN:
12507 space = EVPN_ROUTE_PREFIXLEN;
12508 break;
9c14ec72
RW
12509 default:
12510 return 0;
12511 }
12512
12513 ts->counts[BGP_STATS_MAXBITLEN] = space;
12514
9bcb3eef 12515 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12516 if (ts->table->safi == SAFI_MPLS_VPN
12517 || ts->table->safi == SAFI_ENCAP
12518 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12519 struct bgp_table *table;
12520
9bcb3eef 12521 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12522 if (!table)
12523 continue;
12524
12525 top = bgp_table_top(table);
9bcb3eef
DS
12526 for (ndest = bgp_table_top(table); ndest;
12527 ndest = bgp_route_next(ndest))
12528 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12529 } else {
9bcb3eef 12530 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12531 }
12532 }
9c14ec72 12533
d62a17ae 12534 return 0;
2815e61f 12535}
ff7924f6 12536
71f1613a
DA
12537static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12538 struct json_object *json_array)
12539{
12540 struct listnode *node, *nnode;
12541 struct bgp *bgp;
12542
12543 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12544 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12545}
12546
12547static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12548 safi_t safi, struct json_object *json_array)
2815e61f 12549{
d62a17ae 12550 struct bgp_table_stats ts;
12551 unsigned int i;
893cccd0
PG
12552 int ret = CMD_SUCCESS;
12553 char temp_buf[20];
6c9d22e2
PG
12554 struct json_object *json = NULL;
12555
12556 if (json_array)
12557 json = json_object_new_object();
019386c2 12558
d62a17ae 12559 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12560 char warning_msg[50];
12561
12562 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12563 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12564 safi);
6c9d22e2
PG
12565
12566 if (!json)
893cccd0
PG
12567 vty_out(vty, "%s\n", warning_msg);
12568 else
9ab0cf58 12569 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12570
893cccd0
PG
12571 ret = CMD_WARNING;
12572 goto end_table_stats;
d62a17ae 12573 }
019386c2 12574
893cccd0 12575 if (!json)
5290ceab
DA
12576 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12577 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12578 else
12579 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12580
d62a17ae 12581 /* labeled-unicast routes live in the unicast table */
12582 if (safi == SAFI_LABELED_UNICAST)
12583 safi = SAFI_UNICAST;
019386c2 12584
d62a17ae 12585 memset(&ts, 0, sizeof(ts));
12586 ts.table = bgp->rib[afi][safi];
12587 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12588
d62a17ae 12589 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12590 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12591 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12592 continue;
12593
12594 switch (i) {
d62a17ae 12595 case BGP_STATS_ASPATH_TOTHOPS:
12596 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12597 if (!json) {
9ab0cf58
PG
12598 snprintf(
12599 temp_buf, sizeof(temp_buf), "%12.2f",
12600 ts.counts[i]
12601 ? (float)ts.counts[i]
12602 / (float)ts.counts
12603 [BGP_STATS_ASPATH_COUNT]
12604 : 0);
893cccd0 12605 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12606 table_stats_strs[i]
12607 [TABLE_STATS_IDX_VTY],
893cccd0 12608 temp_buf);
9ab0cf58
PG
12609 } else {
12610 json_object_double_add(
12611 json,
12612 table_stats_strs[i]
12613 [TABLE_STATS_IDX_JSON],
12614 ts.counts[i]
12615 ? (double)ts.counts[i]
12616 / (double)ts.counts
d62a17ae 12617 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12618 : 0);
12619 }
d62a17ae 12620 break;
12621 case BGP_STATS_TOTPLEN:
6c9d22e2 12622 if (!json) {
9ab0cf58
PG
12623 snprintf(
12624 temp_buf, sizeof(temp_buf), "%12.2f",
12625 ts.counts[i]
12626 ? (float)ts.counts[i]
12627 / (float)ts.counts
12628 [BGP_STATS_PREFIXES]
12629 : 0);
893cccd0 12630 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12631 table_stats_strs[i]
12632 [TABLE_STATS_IDX_VTY],
893cccd0 12633 temp_buf);
9ab0cf58
PG
12634 } else {
12635 json_object_double_add(
12636 json,
12637 table_stats_strs[i]
12638 [TABLE_STATS_IDX_JSON],
12639 ts.counts[i]
12640 ? (double)ts.counts[i]
12641 / (double)ts.counts
d62a17ae 12642 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12643 : 0);
12644 }
d62a17ae 12645 break;
12646 case BGP_STATS_SPACE:
6c9d22e2
PG
12647 if (!json) {
12648 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12649 ts.total_space);
893cccd0 12650 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12651 table_stats_strs[i]
12652 [TABLE_STATS_IDX_VTY],
893cccd0 12653 temp_buf);
9ab0cf58
PG
12654 } else {
12655 json_object_double_add(
12656 json,
12657 table_stats_strs[i]
12658 [TABLE_STATS_IDX_JSON],
12659 (double)ts.total_space);
12660 }
8d0ab76d 12661 if (afi == AFI_IP6) {
6c9d22e2
PG
12662 if (!json) {
12663 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12664 "%12g",
12665 ts.total_space
12666 * pow(2.0, -128 + 32));
6c9d22e2
PG
12667 vty_out(vty, "%30s: %s\n",
12668 "/32 equivalent %s\n",
12669 temp_buf);
9ab0cf58
PG
12670 } else {
12671 json_object_double_add(
12672 json, "/32equivalent",
12673 (double)(ts.total_space
12674 * pow(2.0,
12675 -128 + 32)));
12676 }
6c9d22e2
PG
12677 if (!json) {
12678 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12679 "%12g",
12680 ts.total_space
12681 * pow(2.0, -128 + 48));
6c9d22e2
PG
12682 vty_out(vty, "%30s: %s\n",
12683 "/48 equivalent %s\n",
12684 temp_buf);
9ab0cf58
PG
12685 } else {
12686 json_object_double_add(
12687 json, "/48equivalent",
12688 (double)(ts.total_space
12689 * pow(2.0,
12690 -128 + 48)));
12691 }
8d0ab76d 12692 } else {
6c9d22e2
PG
12693 if (!json) {
12694 snprintf(temp_buf, sizeof(temp_buf),
12695 "%12.2f",
9ab0cf58
PG
12696 ts.total_space * 100.
12697 * pow(2.0, -32));
6c9d22e2 12698 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12699 "% announced ", temp_buf);
12700 } else {
12701 json_object_double_add(
12702 json, "%announced",
12703 (double)(ts.total_space * 100.
12704 * pow(2.0, -32)));
12705 }
6c9d22e2
PG
12706 if (!json) {
12707 snprintf(temp_buf, sizeof(temp_buf),
12708 "%12.2f",
9ab0cf58
PG
12709 ts.total_space
12710 * pow(2.0, -32 + 8));
6c9d22e2
PG
12711 vty_out(vty, "%30s: %s\n",
12712 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12713 } else {
12714 json_object_double_add(
12715 json, "/8equivalent",
12716 (double)(ts.total_space
12717 * pow(2.0, -32 + 8)));
12718 }
6c9d22e2
PG
12719 if (!json) {
12720 snprintf(temp_buf, sizeof(temp_buf),
12721 "%12.2f",
9ab0cf58
PG
12722 ts.total_space
12723 * pow(2.0, -32 + 24));
6c9d22e2 12724 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12725 "/24 equivalent ", temp_buf);
12726 } else {
12727 json_object_double_add(
12728 json, "/24equivalent",
12729 (double)(ts.total_space
12730 * pow(2.0, -32 + 24)));
12731 }
8d0ab76d 12732 }
d62a17ae 12733 break;
12734 default:
6c9d22e2
PG
12735 if (!json) {
12736 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12737 ts.counts[i]);
893cccd0 12738 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12739 table_stats_strs[i]
12740 [TABLE_STATS_IDX_VTY],
12741 temp_buf);
12742 } else {
12743 json_object_int_add(
12744 json,
12745 table_stats_strs[i]
12746 [TABLE_STATS_IDX_JSON],
12747 ts.counts[i]);
12748 }
d62a17ae 12749 }
893cccd0
PG
12750 if (!json)
12751 vty_out(vty, "\n");
d62a17ae 12752 }
9ab0cf58 12753end_table_stats:
6c9d22e2
PG
12754 if (json)
12755 json_object_array_add(json_array, json);
893cccd0 12756 return ret;
d62a17ae 12757}
12758
71f1613a
DA
12759static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12760 safi_t safi, struct json_object *json_array)
12761{
12762 if (!bgp) {
12763 bgp_table_stats_all(vty, afi, safi, json_array);
12764 return CMD_SUCCESS;
12765 }
12766
12767 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12768}
12769
d62a17ae 12770enum bgp_pcounts {
12771 PCOUNT_ADJ_IN = 0,
12772 PCOUNT_DAMPED,
12773 PCOUNT_REMOVED,
12774 PCOUNT_HISTORY,
12775 PCOUNT_STALE,
12776 PCOUNT_VALID,
12777 PCOUNT_ALL,
12778 PCOUNT_COUNTED,
7e3d9632 12779 PCOUNT_BPATH_SELECTED,
d62a17ae 12780 PCOUNT_PFCNT, /* the figure we display to users */
12781 PCOUNT_MAX,
a636c635 12782};
718e3744 12783
2b64873d 12784static const char *const pcount_strs[] = {
9d303b37
DL
12785 [PCOUNT_ADJ_IN] = "Adj-in",
12786 [PCOUNT_DAMPED] = "Damped",
12787 [PCOUNT_REMOVED] = "Removed",
12788 [PCOUNT_HISTORY] = "History",
12789 [PCOUNT_STALE] = "Stale",
12790 [PCOUNT_VALID] = "Valid",
12791 [PCOUNT_ALL] = "All RIB",
12792 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12793 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12794 [PCOUNT_PFCNT] = "Useable",
12795 [PCOUNT_MAX] = NULL,
a636c635 12796};
718e3744 12797
d62a17ae 12798struct peer_pcounts {
12799 unsigned int count[PCOUNT_MAX];
12800 const struct peer *peer;
12801 const struct bgp_table *table;
54317cba 12802 safi_t safi;
a636c635 12803};
47fc97cc 12804
9bcb3eef 12805static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12806{
54317cba
JW
12807 const struct bgp_adj_in *ain;
12808 const struct bgp_path_info *pi;
d62a17ae 12809 const struct peer *peer = pc->peer;
12810
54317cba
JW
12811 for (ain = rn->adj_in; ain; ain = ain->next)
12812 if (ain->peer == peer)
12813 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12814
9bcb3eef 12815 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12816
54317cba
JW
12817 if (pi->peer != peer)
12818 continue;
d62a17ae 12819
54317cba 12820 pc->count[PCOUNT_ALL]++;
d62a17ae 12821
54317cba
JW
12822 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12823 pc->count[PCOUNT_DAMPED]++;
12824 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12825 pc->count[PCOUNT_HISTORY]++;
12826 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12827 pc->count[PCOUNT_REMOVED]++;
12828 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12829 pc->count[PCOUNT_STALE]++;
12830 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12831 pc->count[PCOUNT_VALID]++;
12832 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12833 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12834 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12835 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12836
12837 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12838 pc->count[PCOUNT_COUNTED]++;
12839 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12840 flog_err(
12841 EC_LIB_DEVELOPMENT,
12842 "Attempting to count but flags say it is unusable");
12843 } else {
40381db7 12844 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12845 flog_err(
12846 EC_LIB_DEVELOPMENT,
12847 "Not counted but flags say we should");
d62a17ae 12848 }
12849 }
54317cba
JW
12850}
12851
12852static int bgp_peer_count_walker(struct thread *t)
12853{
9bcb3eef 12854 struct bgp_dest *rn, *rm;
54317cba
JW
12855 const struct bgp_table *table;
12856 struct peer_pcounts *pc = THREAD_ARG(t);
12857
12858 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12859 || pc->safi == SAFI_EVPN) {
12860 /* Special handling for 2-level routing tables. */
12861 for (rn = bgp_table_top(pc->table); rn;
12862 rn = bgp_route_next(rn)) {
9bcb3eef 12863 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12864 if (table != NULL)
12865 for (rm = bgp_table_top(table); rm;
12866 rm = bgp_route_next(rm))
12867 bgp_peer_count_proc(rm, pc);
12868 }
12869 } else
12870 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12871 bgp_peer_count_proc(rn, pc);
12872
d62a17ae 12873 return 0;
718e3744 12874}
12875
d62a17ae 12876static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12877 safi_t safi, bool use_json)
856ca177 12878{
d62a17ae 12879 struct peer_pcounts pcounts = {.peer = peer};
12880 unsigned int i;
12881 json_object *json = NULL;
12882 json_object *json_loop = NULL;
856ca177 12883
d62a17ae 12884 if (use_json) {
12885 json = json_object_new_object();
12886 json_loop = json_object_new_object();
12887 }
718e3744 12888
d62a17ae 12889 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12890 || !peer->bgp->rib[afi][safi]) {
12891 if (use_json) {
12892 json_object_string_add(
12893 json, "warning",
12894 "No such neighbor or address family");
12895 vty_out(vty, "%s\n", json_object_to_json_string(json));
12896 json_object_free(json);
d5f20468 12897 json_object_free(json_loop);
d62a17ae 12898 } else
12899 vty_out(vty, "%% No such neighbor or address family\n");
12900
12901 return CMD_WARNING;
12902 }
2a71e9ce 12903
d62a17ae 12904 memset(&pcounts, 0, sizeof(pcounts));
12905 pcounts.peer = peer;
12906 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12907 pcounts.safi = safi;
d62a17ae 12908
12909 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12910 * stats for the thread-walk (i.e. ensure this can't be blamed on
12911 * on just vty_read()).
12912 */
d62a17ae 12913 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12914
12915 if (use_json) {
12916 json_object_string_add(json, "prefixCountsFor", peer->host);
12917 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12918 get_afi_safi_str(afi, safi, true));
d62a17ae 12919 json_object_int_add(json, "pfxCounter",
12920 peer->pcount[afi][safi]);
12921
12922 for (i = 0; i < PCOUNT_MAX; i++)
12923 json_object_int_add(json_loop, pcount_strs[i],
12924 pcounts.count[i]);
12925
12926 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12927
12928 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12929 json_object_string_add(json, "pfxctDriftFor",
12930 peer->host);
12931 json_object_string_add(
12932 json, "recommended",
12933 "Please report this bug, with the above command output");
12934 }
996c9314
LB
12935 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12936 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12937 json_object_free(json);
12938 } else {
12939
12940 if (peer->hostname
892fedb6 12941 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12942 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12943 peer->hostname, peer->host,
5cb5f4d0 12944 get_afi_safi_str(afi, safi, false));
d62a17ae 12945 } else {
12946 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12947 get_afi_safi_str(afi, safi, false));
d62a17ae 12948 }
12949
6cde4b45 12950 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12951 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12952
12953 for (i = 0; i < PCOUNT_MAX; i++)
12954 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12955 pcounts.count[i]);
12956
12957 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12958 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12959 vty_out(vty,
12960 "Please report this bug, with the above command output\n");
12961 }
12962 }
12963
12964 return CMD_SUCCESS;
718e3744 12965}
12966
a636c635
DW
12967DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12968 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12969 "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 12970 SHOW_STR
12971 IP_STR
12972 BGP_STR
8386ac43 12973 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12974 BGP_AFI_HELP_STR
12975 BGP_SAFI_HELP_STR
0b16f239
DS
12976 "Detailed information on TCP and BGP neighbor connections\n"
12977 "Neighbor to display information about\n"
12978 "Neighbor to display information about\n"
91d37724 12979 "Neighbor on BGP configured interface\n"
a636c635 12980 "Display detailed prefix count information\n"
9973d184 12981 JSON_STR)
0b16f239 12982{
d62a17ae 12983 afi_t afi = AFI_IP6;
12984 safi_t safi = SAFI_UNICAST;
12985 struct peer *peer;
12986 int idx = 0;
12987 struct bgp *bgp = NULL;
9f049418
DS
12988 bool uj = use_json(argc, argv);
12989
12990 if (uj)
12991 argc--;
856ca177 12992
d62a17ae 12993 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12994 &bgp, uj);
d62a17ae 12995 if (!idx)
12996 return CMD_WARNING;
0b16f239 12997
d62a17ae 12998 argv_find(argv, argc, "neighbors", &idx);
12999 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13000 if (!peer)
13001 return CMD_WARNING;
bb46e94f 13002
29c8d9da 13003 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13004}
0b16f239 13005
d6902373
PG
13006#ifdef KEEP_OLD_VPN_COMMANDS
13007DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13008 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13009 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13010 SHOW_STR
13011 IP_STR
13012 BGP_STR
d6902373 13013 BGP_VPNVX_HELP_STR
91d37724 13014 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13015 "Detailed information on TCP and BGP neighbor connections\n"
13016 "Neighbor to display information about\n"
13017 "Neighbor to display information about\n"
91d37724 13018 "Neighbor on BGP configured interface\n"
a636c635 13019 "Display detailed prefix count information\n"
9973d184 13020 JSON_STR)
a636c635 13021{
d62a17ae 13022 int idx_peer = 6;
13023 struct peer *peer;
9f049418 13024 bool uj = use_json(argc, argv);
a636c635 13025
d62a17ae 13026 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13027 if (!peer)
13028 return CMD_WARNING;
13029
13030 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13031}
13032
d6902373
PG
13033DEFUN (show_ip_bgp_vpn_all_route_prefix,
13034 show_ip_bgp_vpn_all_route_prefix_cmd,
13035 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13036 SHOW_STR
13037 IP_STR
13038 BGP_STR
d6902373 13039 BGP_VPNVX_HELP_STR
91d37724
QY
13040 "Display information about all VPNv4 NLRIs\n"
13041 "Network in the BGP routing table to display\n"
3a2d747c 13042 "Network in the BGP routing table to display\n"
9973d184 13043 JSON_STR)
91d37724 13044{
d62a17ae 13045 int idx = 0;
13046 char *network = NULL;
13047 struct bgp *bgp = bgp_get_default();
13048 if (!bgp) {
13049 vty_out(vty, "Can't find default instance\n");
13050 return CMD_WARNING;
13051 }
87e34b58 13052
d62a17ae 13053 if (argv_find(argv, argc, "A.B.C.D", &idx))
13054 network = argv[idx]->arg;
13055 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13056 network = argv[idx]->arg;
13057 else {
13058 vty_out(vty, "Unable to figure out Network\n");
13059 return CMD_WARNING;
13060 }
87e34b58 13061
d62a17ae 13062 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 13063 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 13064}
d6902373 13065#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13066
44c69747
LK
13067DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13068 show_bgp_l2vpn_evpn_route_prefix_cmd,
13069 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13070 SHOW_STR
4c63a661
PG
13071 BGP_STR
13072 L2VPN_HELP_STR
13073 EVPN_HELP_STR
44c69747
LK
13074 "Network in the BGP routing table to display\n"
13075 "Network in the BGP routing table to display\n"
4c63a661
PG
13076 "Network in the BGP routing table to display\n"
13077 "Network in the BGP routing table to display\n"
13078 JSON_STR)
13079{
d62a17ae 13080 int idx = 0;
13081 char *network = NULL;
44c69747 13082 int prefix_check = 0;
a636c635 13083
44c69747
LK
13084 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13085 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13086 network = argv[idx]->arg;
44c69747 13087 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13088 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13089 network = argv[idx]->arg;
44c69747
LK
13090 prefix_check = 1;
13091 } else {
d62a17ae 13092 vty_out(vty, "Unable to figure out Network\n");
13093 return CMD_WARNING;
13094 }
44c69747
LK
13095 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13096 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13097 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13098}
13099
2f9bc755
DS
13100static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13101 struct bgp_table *table, int *header1,
13102 int *header2, json_object *json,
13103 json_object *json_scode,
13104 json_object *json_ocode, bool wide)
13105{
13106 uint64_t version = table ? table->version : 0;
23d0a753 13107 char buf[BUFSIZ] = {0};
2f9bc755
DS
13108
13109 if (*header1) {
13110 if (json) {
13111 json_object_int_add(json, "bgpTableVersion", version);
13112 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13113 inet_ntop(AF_INET,
13114 &bgp->router_id, buf,
13115 sizeof(buf)));
2f9bc755
DS
13116 json_object_int_add(json, "defaultLocPrf",
13117 bgp->default_local_pref);
13118 json_object_int_add(json, "localAS", bgp->as);
13119 json_object_object_add(json, "bgpStatusCodes",
13120 json_scode);
13121 json_object_object_add(json, "bgpOriginCodes",
13122 json_ocode);
13123 } else {
13124 vty_out(vty,
23d0a753
DA
13125 "BGP table version is %" PRIu64
13126 ", local router ID is %pI4, vrf id ",
13127 version, &bgp->router_id);
2f9bc755
DS
13128 if (bgp->vrf_id == VRF_UNKNOWN)
13129 vty_out(vty, "%s", VRFID_NONE_STR);
13130 else
13131 vty_out(vty, "%u", bgp->vrf_id);
13132 vty_out(vty, "\n");
13133 vty_out(vty, "Default local pref %u, ",
13134 bgp->default_local_pref);
13135 vty_out(vty, "local AS %u\n", bgp->as);
13136 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13137 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13138 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13139 }
13140 *header1 = 0;
13141 }
13142 if (*header2) {
13143 if (!json)
13144 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13145 : BGP_SHOW_HEADER));
13146 *header2 = 0;
13147 }
13148}
13149
d9478df0
TA
13150static void
13151show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13152 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13153 const char *rmap_name, json_object *json, json_object *json_ar,
13154 json_object *json_scode, json_object *json_ocode,
13155 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13156 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13157{
d62a17ae 13158 struct bgp_adj_in *ain;
13159 struct bgp_adj_out *adj;
9bcb3eef 13160 struct bgp_dest *dest;
d62a17ae 13161 struct bgp *bgp;
d62a17ae 13162 struct attr attr;
13163 int ret;
13164 struct update_subgroup *subgrp;
d62a17ae 13165 struct peer_af *paf;
f99def61 13166 bool route_filtered;
96f3485c
MK
13167 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13168 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13169 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13170 || (safi == SAFI_EVPN))
13171 ? true
13172 : false;
a636c635 13173
d62a17ae 13174 bgp = peer->bgp;
a636c635 13175
d62a17ae 13176 if (!bgp) {
13177 if (use_json) {
13178 json_object_string_add(json, "alert", "no BGP");
13179 vty_out(vty, "%s\n", json_object_to_json_string(json));
13180 json_object_free(json);
13181 } else
13182 vty_out(vty, "%% No bgp\n");
13183 return;
13184 }
a636c635 13185
d62a17ae 13186 subgrp = peer_subgroup(peer, afi, safi);
13187
6392aaa6 13188 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13189 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13190 char buf[BUFSIZ] = {0};
13191
d62a17ae 13192 if (use_json) {
13193 json_object_int_add(json, "bgpTableVersion",
13194 table->version);
13195 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13196 inet_ntop(AF_INET,
13197 &bgp->router_id, buf,
13198 sizeof(buf)));
01eced22
AD
13199 json_object_int_add(json, "defaultLocPrf",
13200 bgp->default_local_pref);
13201 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13202 json_object_object_add(json, "bgpStatusCodes",
13203 json_scode);
13204 json_object_object_add(json, "bgpOriginCodes",
13205 json_ocode);
07d0c4ed
DA
13206 json_object_string_add(
13207 json, "bgpOriginatingDefaultNetwork",
13208 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13209 } else {
23d0a753
DA
13210 vty_out(vty,
13211 "BGP table version is %" PRIu64
13212 ", local router ID is %pI4, vrf id ",
13213 table->version, &bgp->router_id);
9df8b37c
PZ
13214 if (bgp->vrf_id == VRF_UNKNOWN)
13215 vty_out(vty, "%s", VRFID_NONE_STR);
13216 else
13217 vty_out(vty, "%u", bgp->vrf_id);
13218 vty_out(vty, "\n");
01eced22
AD
13219 vty_out(vty, "Default local pref %u, ",
13220 bgp->default_local_pref);
13221 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13222 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13223 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13224 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13225
07d0c4ed
DA
13226 vty_out(vty, "Originating default network %s\n\n",
13227 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13228 }
d9478df0 13229 *header1 = 0;
d62a17ae 13230 }
a636c635 13231
9bcb3eef 13232 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13233 if (type == bgp_show_adj_route_received
13234 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13235 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13236 if (ain->peer != peer)
ea47320b 13237 continue;
6392aaa6 13238
d9478df0
TA
13239 show_adj_route_header(vty, bgp, table, header1,
13240 header2, json, json_scode,
13241 json_ocode, wide);
13242
13243 if ((safi == SAFI_MPLS_VPN)
13244 || (safi == SAFI_ENCAP)
13245 || (safi == SAFI_EVPN)) {
13246 if (use_json)
13247 json_object_string_add(
13248 json_ar, "rd", rd_str);
13249 else if (show_rd && rd_str) {
13250 vty_out(vty,
13251 "Route Distinguisher: %s\n",
13252 rd_str);
13253 show_rd = false;
13254 }
13255 }
6392aaa6 13256
6f4f49b2 13257 attr = *ain->attr;
f99def61
AD
13258 route_filtered = false;
13259
13260 /* Filter prefix using distribute list,
13261 * filter list or prefix list
13262 */
b54892e0 13263 const struct prefix *rn_p =
9bcb3eef 13264 bgp_dest_get_prefix(dest);
b54892e0
DS
13265 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13266 safi))
13267 == FILTER_DENY)
f99def61
AD
13268 route_filtered = true;
13269
13270 /* Filter prefix using route-map */
b54892e0
DS
13271 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13272 safi, rmap_name, NULL,
13273 0, NULL);
6392aaa6 13274
13c8e163
AD
13275 if (type == bgp_show_adj_route_filtered &&
13276 !route_filtered && ret != RMAP_DENY) {
b755861b 13277 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13278 continue;
d62a17ae 13279 }
6392aaa6 13280
d9478df0
TA
13281 if (type == bgp_show_adj_route_received
13282 && (route_filtered || ret == RMAP_DENY))
13283 (*filtered_count)++;
6392aaa6 13284
b54892e0 13285 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13286 use_json, json_ar, wide);
b755861b 13287 bgp_attr_undup(&attr, ain->attr);
d9478df0 13288 (*output_count)++;
d62a17ae 13289 }
6392aaa6 13290 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13291 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13292 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13293 if (paf->peer != peer || !adj->attr)
924c3f6a 13294 continue;
d62a17ae 13295
d9478df0
TA
13296 show_adj_route_header(vty, bgp, table,
13297 header1, header2,
13298 json, json_scode,
13299 json_ocode, wide);
d62a17ae 13300
b54892e0 13301 const struct prefix *rn_p =
9bcb3eef 13302 bgp_dest_get_prefix(dest);
b54892e0 13303
6f4f49b2 13304 attr = *adj->attr;
b755861b 13305 ret = bgp_output_modifier(
b54892e0 13306 peer, rn_p, &attr, afi, safi,
b755861b 13307 rmap_name);
f46d8e1e 13308
b755861b 13309 if (ret != RMAP_DENY) {
d9478df0
TA
13310 if ((safi == SAFI_MPLS_VPN)
13311 || (safi == SAFI_ENCAP)
13312 || (safi == SAFI_EVPN)) {
13313 if (use_json)
13314 json_object_string_add(
13315 json_ar,
13316 "rd",
13317 rd_str);
13318 else if (show_rd
13319 && rd_str) {
13320 vty_out(vty,
13321 "Route Distinguisher: %s\n",
13322 rd_str);
13323 show_rd = false;
13324 }
13325 }
b54892e0
DS
13326 route_vty_out_tmp(
13327 vty, rn_p, &attr, safi,
ae248832
MK
13328 use_json, json_ar,
13329 wide);
d9478df0 13330 (*output_count)++;
b755861b 13331 } else {
d9478df0 13332 (*filtered_count)++;
a2addae8 13333 }
b755861b
PM
13334
13335 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13336 }
f20ce998
DS
13337 } else if (type == bgp_show_adj_route_bestpath) {
13338 struct bgp_path_info *pi;
13339
d9478df0
TA
13340 show_adj_route_header(vty, bgp, table, header1, header2,
13341 json, json_scode, json_ocode,
13342 wide);
f20ce998
DS
13343
13344 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13345 pi = pi->next) {
13346 if (pi->peer != peer)
13347 continue;
13348
13349 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13350 continue;
13351
13352 route_vty_out_tmp(vty,
13353 bgp_dest_get_prefix(dest),
13354 pi->attr, safi, use_json,
13355 json_ar, wide);
d9478df0 13356 (*output_count)++;
f20ce998 13357 }
d62a17ae 13358 }
13359 }
a636c635 13360}
2a71e9ce 13361
d62a17ae 13362static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13363 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13364 const char *rmap_name, uint8_t show_flags)
0b16f239 13365{
d9478df0
TA
13366 struct bgp *bgp;
13367 struct bgp_table *table;
d62a17ae 13368 json_object *json = NULL;
d9478df0
TA
13369 json_object *json_scode = NULL;
13370 json_object *json_ocode = NULL;
13371 json_object *json_ar = NULL;
96f3485c 13372 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13373
d9478df0
TA
13374 /* Init BGP headers here so they're only displayed once
13375 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13376 */
13377 int header1 = 1;
13378 int header2 = 1;
13379
13380 /*
13381 * Initialize variables for each RD
13382 * All prefixes under an RD is aggregated within "json_routes"
13383 */
13384 char rd_str[BUFSIZ] = {0};
13385 json_object *json_routes = NULL;
13386
13387
13388 /* For 2-tier tables, prefix counts need to be
13389 * maintained across multiple runs of show_adj_route()
13390 */
13391 unsigned long output_count_per_rd;
13392 unsigned long filtered_count_per_rd;
13393 unsigned long output_count = 0;
13394 unsigned long filtered_count = 0;
13395
13396 if (use_json) {
d62a17ae 13397 json = json_object_new_object();
d9478df0
TA
13398 json_ar = json_object_new_object();
13399 json_scode = json_object_new_object();
13400 json_ocode = json_object_new_object();
13401
13402 json_object_string_add(json_scode, "suppressed", "s");
13403 json_object_string_add(json_scode, "damped", "d");
13404 json_object_string_add(json_scode, "history", "h");
13405 json_object_string_add(json_scode, "valid", "*");
13406 json_object_string_add(json_scode, "best", ">");
13407 json_object_string_add(json_scode, "multipath", "=");
13408 json_object_string_add(json_scode, "internal", "i");
13409 json_object_string_add(json_scode, "ribFailure", "r");
13410 json_object_string_add(json_scode, "stale", "S");
13411 json_object_string_add(json_scode, "removed", "R");
13412
13413 json_object_string_add(json_ocode, "igp", "i");
13414 json_object_string_add(json_ocode, "egp", "e");
13415 json_object_string_add(json_ocode, "incomplete", "?");
13416 }
0b16f239 13417
d62a17ae 13418 if (!peer || !peer->afc[afi][safi]) {
13419 if (use_json) {
13420 json_object_string_add(
13421 json, "warning",
13422 "No such neighbor or address family");
13423 vty_out(vty, "%s\n", json_object_to_json_string(json));
13424 json_object_free(json);
13425 } else
13426 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13427
d62a17ae 13428 return CMD_WARNING;
13429 }
13430
6392aaa6
PM
13431 if ((type == bgp_show_adj_route_received
13432 || type == bgp_show_adj_route_filtered)
d62a17ae 13433 && !CHECK_FLAG(peer->af_flags[afi][safi],
13434 PEER_FLAG_SOFT_RECONFIG)) {
13435 if (use_json) {
13436 json_object_string_add(
13437 json, "warning",
13438 "Inbound soft reconfiguration not enabled");
13439 vty_out(vty, "%s\n", json_object_to_json_string(json));
13440 json_object_free(json);
13441 } else
13442 vty_out(vty,
13443 "%% Inbound soft reconfiguration not enabled\n");
13444
13445 return CMD_WARNING;
13446 }
0b16f239 13447
d9478df0
TA
13448 bgp = peer->bgp;
13449
13450 /* labeled-unicast routes live in the unicast table */
13451 if (safi == SAFI_LABELED_UNICAST)
13452 table = bgp->rib[afi][SAFI_UNICAST];
13453 else
13454 table = bgp->rib[afi][safi];
13455
13456 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13457 || (safi == SAFI_EVPN)) {
13458
13459 struct bgp_dest *dest;
13460
13461 for (dest = bgp_table_top(table); dest;
13462 dest = bgp_route_next(dest)) {
13463 table = bgp_dest_get_bgp_table_info(dest);
13464 if (!table)
13465 continue;
13466
13467 output_count_per_rd = 0;
13468 filtered_count_per_rd = 0;
13469
13470 if (use_json)
13471 json_routes = json_object_new_object();
13472
13473 const struct prefix_rd *prd;
13474 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13475 dest);
13476
13477 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13478
13479 show_adj_route(vty, peer, table, afi, safi, type,
13480 rmap_name, json, json_routes, json_scode,
13481 json_ocode, show_flags, &header1,
13482 &header2, rd_str, &output_count_per_rd,
13483 &filtered_count_per_rd);
13484
13485 /* Don't include an empty RD in the output! */
13486 if (json_routes && (output_count_per_rd > 0))
13487 json_object_object_add(json_ar, rd_str,
13488 json_routes);
13489
13490 output_count += output_count_per_rd;
13491 filtered_count += filtered_count_per_rd;
13492 }
13493 } else
13494 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13495 json, json_ar, json_scode, json_ocode,
13496 show_flags, &header1, &header2, rd_str,
13497 &output_count, &filtered_count);
13498
13499 if (use_json) {
13500 json_object_object_add(json, "advertisedRoutes", json_ar);
13501 json_object_int_add(json, "totalPrefixCounter", output_count);
13502 json_object_int_add(json, "filteredPrefixCounter",
13503 filtered_count);
13504
13505 vty_out(vty, "%s\n",
13506 json_object_to_json_string_ext(
13507 json, JSON_C_TO_STRING_PRETTY));
13508
13509 if (!output_count && !filtered_count) {
13510 json_object_free(json_scode);
13511 json_object_free(json_ocode);
13512 }
13513
13514 if (json)
13515 json_object_free(json);
13516
13517 } else if (output_count > 0) {
13518 if (filtered_count > 0)
13519 vty_out(vty,
13520 "\nTotal number of prefixes %ld (%ld filtered)\n",
13521 output_count, filtered_count);
13522 else
13523 vty_out(vty, "\nTotal number of prefixes %ld\n",
13524 output_count);
13525 }
0b16f239 13526
d62a17ae 13527 return CMD_SUCCESS;
a636c635 13528}
50ef26d4 13529
f20ce998
DS
13530DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13531 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13532 "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]",
13533 SHOW_STR
13534 IP_STR
13535 BGP_STR
13536 BGP_INSTANCE_HELP_STR
13537 BGP_AFI_HELP_STR
13538 BGP_SAFI_WITH_LABEL_HELP_STR
13539 "Detailed information on TCP and BGP neighbor connections\n"
13540 "Neighbor to display information about\n"
13541 "Neighbor to display information about\n"
13542 "Neighbor on BGP configured interface\n"
13543 "Display the routes selected by best path\n"
13544 JSON_STR
13545 "Increase table width for longer prefixes\n")
13546{
13547 afi_t afi = AFI_IP6;
13548 safi_t safi = SAFI_UNICAST;
13549 char *rmap_name = NULL;
13550 char *peerstr = NULL;
13551 struct bgp *bgp = NULL;
13552 struct peer *peer;
13553 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13554 int idx = 0;
96f3485c
MK
13555 uint8_t show_flags = 0;
13556
13557 if (uj)
13558 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13559
13560 if (wide)
13561 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13562
13563 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13564 &bgp, uj);
13565
13566 if (!idx)
13567 return CMD_WARNING;
13568
13569 argv_find(argv, argc, "neighbors", &idx);
13570 peerstr = argv[++idx]->arg;
13571
13572 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13573 if (!peer)
13574 return CMD_WARNING;
13575
96f3485c
MK
13576 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13577 show_flags);
f20ce998
DS
13578}
13579
ae248832 13580DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13581 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13582 "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 13583 SHOW_STR
13584 IP_STR
13585 BGP_STR
a636c635 13586 BGP_INSTANCE_HELP_STR
7395a2c9 13587 BGP_AFI_HELP_STR
4dd6177e 13588 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13589 "Display the entries for all address families\n"
718e3744 13590 "Detailed information on TCP and BGP neighbor connections\n"
13591 "Neighbor to display information about\n"
13592 "Neighbor to display information about\n"
91d37724 13593 "Neighbor on BGP configured interface\n"
a636c635 13594 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13595 "Display the received routes from neighbor\n"
13596 "Display the filtered routes received from neighbor\n"
a636c635
DW
13597 "Route-map to modify the attributes\n"
13598 "Name of the route map\n"
ae248832
MK
13599 JSON_STR
13600 "Increase table width for longer prefixes\n")
718e3744 13601{
d62a17ae 13602 afi_t afi = AFI_IP6;
13603 safi_t safi = SAFI_UNICAST;
13604 char *rmap_name = NULL;
13605 char *peerstr = NULL;
d62a17ae 13606 struct bgp *bgp = NULL;
13607 struct peer *peer;
6392aaa6 13608 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13609 int idx = 0;
96f3485c
MK
13610 bool first = true;
13611 uint8_t show_flags = 0;
6392aaa6 13612
96f3485c 13613 if (uj) {
d62a17ae 13614 argc--;
96f3485c
MK
13615 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13616 }
13617
13618 if (all) {
13619 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13620 if (argv_find(argv, argc, "ipv4", &idx))
13621 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13622
13623 if (argv_find(argv, argc, "ipv6", &idx))
13624 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13625 }
13626
13627 if (wide)
13628 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13629
9f049418
DS
13630 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13631 &bgp, uj);
13632 if (!idx)
13633 return CMD_WARNING;
13634
d62a17ae 13635 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13636 argv_find(argv, argc, "neighbors", &idx);
13637 peerstr = argv[++idx]->arg;
8c3deaae 13638
d62a17ae 13639 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13640 if (!peer)
13641 return CMD_WARNING;
856ca177 13642
d62a17ae 13643 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13644 type = bgp_show_adj_route_advertised;
13645 else if (argv_find(argv, argc, "received-routes", &idx))
13646 type = bgp_show_adj_route_received;
13647 else if (argv_find(argv, argc, "filtered-routes", &idx))
13648 type = bgp_show_adj_route_filtered;
13649
d62a17ae 13650 if (argv_find(argv, argc, "route-map", &idx))
13651 rmap_name = argv[++idx]->arg;
95cbbd2a 13652
96f3485c
MK
13653 if (!all)
13654 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13655 show_flags);
13656 if (uj)
13657 vty_out(vty, "{\n");
13658
13659 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13660 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13661 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13662 : AFI_IP6;
13663 FOREACH_SAFI (safi) {
96f3485c
MK
13664 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13665 continue;
13666
13667 if (uj) {
13668 if (first)
13669 first = false;
13670 else
13671 vty_out(vty, ",\n");
13672 vty_out(vty, "\"%s\":",
13673 get_afi_safi_str(afi, safi, true));
13674 } else
13675 vty_out(vty, "\nFor address family: %s\n",
13676 get_afi_safi_str(afi, safi, false));
13677
13678 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13679 show_flags);
13680 }
13681 } else {
13682 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13683 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13684 continue;
13685
13686 if (uj) {
13687 if (first)
13688 first = false;
13689 else
13690 vty_out(vty, ",\n");
13691 vty_out(vty, "\"%s\":",
13692 get_afi_safi_str(afi, safi, true));
13693 } else
13694 vty_out(vty, "\nFor address family: %s\n",
13695 get_afi_safi_str(afi, safi, false));
13696
13697 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13698 show_flags);
13699 }
13700 }
13701 if (uj)
13702 vty_out(vty, "}\n");
13703
13704 return CMD_SUCCESS;
95cbbd2a
ML
13705}
13706
718e3744 13707DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13708 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13709 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13710 SHOW_STR
13711 IP_STR
13712 BGP_STR
8c3deaae
QY
13713 "Address Family\n"
13714 "Address Family\n"
718e3744 13715 "Address Family modifier\n"
13716 "Detailed information on TCP and BGP neighbor connections\n"
13717 "Neighbor to display information about\n"
13718 "Neighbor to display information about\n"
91d37724 13719 "Neighbor on BGP configured interface\n"
718e3744 13720 "Display information received from a BGP neighbor\n"
856ca177 13721 "Display the prefixlist filter\n"
9973d184 13722 JSON_STR)
718e3744 13723{
d62a17ae 13724 afi_t afi = AFI_IP6;
13725 safi_t safi = SAFI_UNICAST;
13726 char *peerstr = NULL;
13727
13728 char name[BUFSIZ];
13729 union sockunion su;
13730 struct peer *peer;
13731 int count, ret;
13732
13733 int idx = 0;
13734
13735 /* show [ip] bgp */
13736 if (argv_find(argv, argc, "ip", &idx))
13737 afi = AFI_IP;
13738 /* [<ipv4|ipv6> [unicast]] */
13739 if (argv_find(argv, argc, "ipv4", &idx))
13740 afi = AFI_IP;
13741 if (argv_find(argv, argc, "ipv6", &idx))
13742 afi = AFI_IP6;
13743 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13744 argv_find(argv, argc, "neighbors", &idx);
13745 peerstr = argv[++idx]->arg;
13746
9f049418 13747 bool uj = use_json(argc, argv);
d62a17ae 13748
13749 ret = str2sockunion(peerstr, &su);
13750 if (ret < 0) {
13751 peer = peer_lookup_by_conf_if(NULL, peerstr);
13752 if (!peer) {
13753 if (uj)
13754 vty_out(vty, "{}\n");
13755 else
13756 vty_out(vty,
13757 "%% Malformed address or name: %s\n",
13758 peerstr);
13759 return CMD_WARNING;
13760 }
13761 } else {
13762 peer = peer_lookup(NULL, &su);
13763 if (!peer) {
13764 if (uj)
13765 vty_out(vty, "{}\n");
13766 else
13767 vty_out(vty, "No peer\n");
13768 return CMD_WARNING;
13769 }
13770 }
718e3744 13771
4ced1a2c 13772 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13773 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13774 if (count) {
13775 if (!uj)
13776 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13777 get_afi_safi_str(afi, safi, false));
d62a17ae 13778 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13779 } else {
13780 if (uj)
13781 vty_out(vty, "{}\n");
13782 else
13783 vty_out(vty, "No functional output\n");
13784 }
718e3744 13785
d62a17ae 13786 return CMD_SUCCESS;
13787}
13788
13789static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13790 afi_t afi, safi_t safi,
9f049418 13791 enum bgp_show_type type, bool use_json)
d62a17ae 13792{
96f3485c
MK
13793 uint8_t show_flags = 0;
13794
13795 if (use_json)
13796 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13797
d62a17ae 13798 if (!peer || !peer->afc[afi][safi]) {
13799 if (use_json) {
13800 json_object *json_no = NULL;
13801 json_no = json_object_new_object();
13802 json_object_string_add(
13803 json_no, "warning",
13804 "No such neighbor or address family");
13805 vty_out(vty, "%s\n",
13806 json_object_to_json_string(json_no));
13807 json_object_free(json_no);
13808 } else
13809 vty_out(vty, "%% No such neighbor or address family\n");
13810 return CMD_WARNING;
13811 }
47fc97cc 13812
7daf25a3
TA
13813 /* labeled-unicast routes live in the unicast table */
13814 if (safi == SAFI_LABELED_UNICAST)
13815 safi = SAFI_UNICAST;
13816
1e2ce4f1
DS
13817 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
13818 RPKI_NOT_BEING_USED);
718e3744 13819}
13820
dba3c1d3
PG
13821DEFUN (show_ip_bgp_flowspec_routes_detailed,
13822 show_ip_bgp_flowspec_routes_detailed_cmd,
13823 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13824 SHOW_STR
13825 IP_STR
13826 BGP_STR
13827 BGP_INSTANCE_HELP_STR
13828 BGP_AFI_HELP_STR
13829 "SAFI Flowspec\n"
13830 "Detailed information on flowspec entries\n"
13831 JSON_STR)
13832{
13833 afi_t afi = AFI_IP;
13834 safi_t safi = SAFI_UNICAST;
13835 struct bgp *bgp = NULL;
13836 int idx = 0;
9f049418 13837 bool uj = use_json(argc, argv);
96f3485c 13838 uint8_t show_flags = 0;
9f049418 13839
96f3485c 13840 if (uj) {
9f049418 13841 argc--;
96f3485c
MK
13842 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13843 }
dba3c1d3
PG
13844
13845 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13846 &bgp, uj);
dba3c1d3
PG
13847 if (!idx)
13848 return CMD_WARNING;
13849
96f3485c 13850 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 13851 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
13852}
13853
718e3744 13854DEFUN (show_ip_bgp_neighbor_routes,
13855 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13856 "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 13857 SHOW_STR
13858 IP_STR
13859 BGP_STR
8386ac43 13860 BGP_INSTANCE_HELP_STR
4f280b15 13861 BGP_AFI_HELP_STR
4dd6177e 13862 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13863 "Detailed information on TCP and BGP neighbor connections\n"
13864 "Neighbor to display information about\n"
13865 "Neighbor to display information about\n"
91d37724 13866 "Neighbor on BGP configured interface\n"
2525cf39 13867 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13868 "Display the dampened routes received from neighbor\n"
13869 "Display routes learned from neighbor\n"
9973d184 13870 JSON_STR)
718e3744 13871{
d62a17ae 13872 char *peerstr = NULL;
13873 struct bgp *bgp = NULL;
13874 afi_t afi = AFI_IP6;
13875 safi_t safi = SAFI_UNICAST;
13876 struct peer *peer;
13877 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13878 int idx = 0;
9f049418
DS
13879 bool uj = use_json(argc, argv);
13880
13881 if (uj)
13882 argc--;
bb46e94f 13883
d62a17ae 13884 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13885 &bgp, uj);
d62a17ae 13886 if (!idx)
13887 return CMD_WARNING;
c493f2d8 13888
d62a17ae 13889 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13890 argv_find(argv, argc, "neighbors", &idx);
13891 peerstr = argv[++idx]->arg;
8c3deaae 13892
d62a17ae 13893 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13894 if (!peer)
d62a17ae 13895 return CMD_WARNING;
bb46e94f 13896
d62a17ae 13897 if (argv_find(argv, argc, "flap-statistics", &idx))
13898 sh_type = bgp_show_type_flap_neighbor;
13899 else if (argv_find(argv, argc, "dampened-routes", &idx))
13900 sh_type = bgp_show_type_damp_neighbor;
13901 else if (argv_find(argv, argc, "routes", &idx))
13902 sh_type = bgp_show_type_neighbor;
2525cf39 13903
d62a17ae 13904 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13905}
6b0655a2 13906
734b349e 13907struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13908
d62a17ae 13909struct bgp_distance {
13910 /* Distance value for the IP source prefix. */
d7c0a89a 13911 uint8_t distance;
718e3744 13912
d62a17ae 13913 /* Name of the access-list to be matched. */
13914 char *access_list;
718e3744 13915};
13916
4f280b15
LB
13917DEFUN (show_bgp_afi_vpn_rd_route,
13918 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 13919 "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
13920 SHOW_STR
13921 BGP_STR
13922 BGP_AFI_HELP_STR
13923 "Address Family modifier\n"
13924 "Display information for a route distinguisher\n"
13925 "Route Distinguisher\n"
a111dd97 13926 "All Route Distinguishers\n"
7395a2c9
DS
13927 "Network in the BGP routing table to display\n"
13928 "Network in the BGP routing table to display\n"
13929 JSON_STR)
4f280b15 13930{
d62a17ae 13931 int ret;
13932 struct prefix_rd prd;
13933 afi_t afi = AFI_MAX;
13934 int idx = 0;
4f280b15 13935
ff6566f3
DS
13936 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13937 vty_out(vty, "%% Malformed Address Family\n");
13938 return CMD_WARNING;
13939 }
13940
a111dd97
TA
13941 if (!strcmp(argv[5]->arg, "all"))
13942 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
13943 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
13944 RPKI_NOT_BEING_USED,
13945 use_json(argc, argv));
13946
d62a17ae 13947 ret = str2prefix_rd(argv[5]->arg, &prd);
13948 if (!ret) {
13949 vty_out(vty, "%% Malformed Route Distinguisher\n");
13950 return CMD_WARNING;
13951 }
ff6566f3 13952
d62a17ae 13953 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
13954 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13955 use_json(argc, argv));
4f280b15
LB
13956}
13957
d62a17ae 13958static struct bgp_distance *bgp_distance_new(void)
718e3744 13959{
d62a17ae 13960 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13961}
13962
d62a17ae 13963static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13964{
d62a17ae 13965 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13966}
13967
37a87b8f
CS
13968int bgp_distance_set(uint8_t distance, const char *ip_str,
13969 const char *access_list_str, afi_t afi, safi_t safi,
13970 char *errmsg, size_t errmsg_len)
718e3744 13971{
d62a17ae 13972 int ret;
d62a17ae 13973 struct prefix p;
9bcb3eef 13974 struct bgp_dest *dest;
d62a17ae 13975 struct bgp_distance *bdistance;
718e3744 13976
d62a17ae 13977 ret = str2prefix(ip_str, &p);
13978 if (ret == 0) {
37a87b8f 13979 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13980 return CMD_WARNING_CONFIG_FAILED;
13981 }
718e3744 13982
d62a17ae 13983 /* Get BGP distance node. */
9bcb3eef
DS
13984 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13985 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13986 if (bdistance)
9bcb3eef 13987 bgp_dest_unlock_node(dest);
ca2e160d 13988 else {
d62a17ae 13989 bdistance = bgp_distance_new();
9bcb3eef 13990 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13991 }
718e3744 13992
d62a17ae 13993 /* Set distance value. */
13994 bdistance->distance = distance;
718e3744 13995
d62a17ae 13996 /* Reset access-list configuration. */
e1b36e13 13997 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13998 if (access_list_str)
13999 bdistance->access_list =
14000 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14001
d62a17ae 14002 return CMD_SUCCESS;
718e3744 14003}
14004
37a87b8f
CS
14005int bgp_distance_unset(uint8_t distance, const char *ip_str,
14006 const char *access_list_str, afi_t afi, safi_t safi,
14007 char *errmsg, size_t errmsg_len)
718e3744 14008{
d62a17ae 14009 int ret;
d62a17ae 14010 struct prefix p;
9bcb3eef 14011 struct bgp_dest *dest;
d62a17ae 14012 struct bgp_distance *bdistance;
718e3744 14013
d62a17ae 14014 ret = str2prefix(ip_str, &p);
14015 if (ret == 0) {
37a87b8f 14016 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14017 return CMD_WARNING_CONFIG_FAILED;
14018 }
718e3744 14019
9bcb3eef
DS
14020 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14021 if (!dest) {
37a87b8f 14022 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 14023 return CMD_WARNING_CONFIG_FAILED;
14024 }
718e3744 14025
9bcb3eef 14026 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 14027
d62a17ae 14028 if (bdistance->distance != distance) {
37a87b8f
CS
14029 snprintf(errmsg, errmsg_len,
14030 "Distance does not match configured\n");
d62a17ae 14031 return CMD_WARNING_CONFIG_FAILED;
14032 }
718e3744 14033
0a22ddfb 14034 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14035 bgp_distance_free(bdistance);
718e3744 14036
9bcb3eef
DS
14037 bgp_dest_set_bgp_path_info(dest, NULL);
14038 bgp_dest_unlock_node(dest);
14039 bgp_dest_unlock_node(dest);
718e3744 14040
d62a17ae 14041 return CMD_SUCCESS;
718e3744 14042}
14043
718e3744 14044/* Apply BGP information to distance method. */
b8685f9b 14045uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14046 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14047{
9bcb3eef 14048 struct bgp_dest *dest;
801bb996 14049 struct prefix q = {0};
d62a17ae 14050 struct peer *peer;
14051 struct bgp_distance *bdistance;
14052 struct access_list *alist;
14053 struct bgp_static *bgp_static;
14054
14055 if (!bgp)
14056 return 0;
14057
40381db7 14058 peer = pinfo->peer;
d62a17ae 14059
7b7d48e5
DS
14060 if (pinfo->attr->distance)
14061 return pinfo->attr->distance;
14062
801bb996
CS
14063 /* Check source address.
14064 * Note: for aggregate route, peer can have unspec af type.
14065 */
14066 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14067 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14068 return 0;
14069
9bcb3eef
DS
14070 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14071 if (dest) {
14072 bdistance = bgp_dest_get_bgp_distance_info(dest);
14073 bgp_dest_unlock_node(dest);
d62a17ae 14074
14075 if (bdistance->access_list) {
14076 alist = access_list_lookup(afi, bdistance->access_list);
14077 if (alist
14078 && access_list_apply(alist, p) == FILTER_PERMIT)
14079 return bdistance->distance;
14080 } else
14081 return bdistance->distance;
718e3744 14082 }
718e3744 14083
d62a17ae 14084 /* Backdoor check. */
9bcb3eef
DS
14085 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14086 if (dest) {
14087 bgp_static = bgp_dest_get_bgp_static_info(dest);
14088 bgp_dest_unlock_node(dest);
718e3744 14089
d62a17ae 14090 if (bgp_static->backdoor) {
14091 if (bgp->distance_local[afi][safi])
14092 return bgp->distance_local[afi][safi];
14093 else
14094 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14095 }
718e3744 14096 }
718e3744 14097
d62a17ae 14098 if (peer->sort == BGP_PEER_EBGP) {
14099 if (bgp->distance_ebgp[afi][safi])
14100 return bgp->distance_ebgp[afi][safi];
14101 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14102 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14103 if (bgp->distance_ibgp[afi][safi])
14104 return bgp->distance_ibgp[afi][safi];
14105 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14106 } else {
14107 if (bgp->distance_local[afi][safi])
14108 return bgp->distance_local[afi][safi];
14109 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14110 }
718e3744 14111}
14112
a612fb77
DA
14113/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14114 * we should tell ZEBRA update the routes for a specific
14115 * AFI/SAFI to reflect changes in RIB.
14116 */
37a87b8f
CS
14117void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14118 safi_t update_safi)
a612fb77
DA
14119{
14120 afi_t afi;
14121 safi_t safi;
14122
14123 FOREACH_AFI_SAFI (afi, safi) {
14124 if (!bgp_fibupd_safi(safi))
14125 continue;
14126
8b54bc30
DA
14127 if (afi != update_afi && safi != update_safi)
14128 continue;
14129
14130 if (BGP_DEBUG(zebra, ZEBRA))
14131 zlog_debug(
14132 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14133 __func__, afi, safi);
14134 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14135 }
14136}
14137
37a87b8f
CS
14138DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14139 "distance bgp (1-255) (1-255) (1-255)",
14140 "Define an administrative distance\n"
14141 "BGP distance\n"
14142 "Distance for routes external to the AS\n"
14143 "Distance for routes internal to the AS\n"
14144 "Distance for local routes\n")
718e3744 14145{
d62a17ae 14146 int idx_number = 2;
14147 int idx_number_2 = 3;
14148 int idx_number_3 = 4;
14149 afi_t afi;
14150 safi_t safi;
37a87b8f 14151 char xpath[XPATH_MAXLEN];
718e3744 14152
d62a17ae 14153 afi = bgp_node_afi(vty);
14154 safi = bgp_node_safi(vty);
718e3744 14155
37a87b8f
CS
14156 snprintf(
14157 xpath, sizeof(xpath),
14158 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14159 yang_afi_safi_value2identity(afi, safi),
14160 bgp_afi_safi_get_container_str(afi, safi));
14161 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14162 snprintf(
14163 xpath, sizeof(xpath),
14164 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14165 yang_afi_safi_value2identity(afi, safi),
14166 bgp_afi_safi_get_container_str(afi, safi));
14167 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14168 argv[idx_number_2]->arg);
14169 snprintf(
14170 xpath, sizeof(xpath),
14171 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14172 yang_afi_safi_value2identity(afi, safi),
14173 bgp_afi_safi_get_container_str(afi, safi));
14174
14175 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14176 argv[idx_number_3]->arg);
14177
14178 return nb_cli_apply_changes(vty, NULL);
14179}
14180
14181DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14182 "no distance bgp [(1-255) (1-255) (1-255)]",
14183 NO_STR
14184 "Define an administrative distance\n"
14185 "BGP distance\n"
14186 "Distance for routes external to the AS\n"
14187 "Distance for routes internal to the AS\n"
14188 "Distance for local routes\n")
14189{
14190 afi_t afi;
14191 safi_t safi;
14192 char xpath[XPATH_MAXLEN];
14193
14194 afi = bgp_node_afi(vty);
14195 safi = bgp_node_safi(vty);
14196
14197 snprintf(
14198 xpath, sizeof(xpath),
14199 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14200 yang_afi_safi_value2identity(afi, safi),
14201 bgp_afi_safi_get_container_str(afi, safi));
14202 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14203 snprintf(
14204 xpath, sizeof(xpath),
14205 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14206 yang_afi_safi_value2identity(afi, safi),
14207 bgp_afi_safi_get_container_str(afi, safi));
14208 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14209 snprintf(
14210 xpath, sizeof(xpath),
14211 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14212 yang_afi_safi_value2identity(afi, safi),
14213 bgp_afi_safi_get_container_str(afi, safi));
14214
14215 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14216
14217 return nb_cli_apply_changes(vty, NULL);
718e3744 14218}
14219
37a87b8f
CS
14220void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14221 struct lyd_node *dnode,
14222 bool show_defaults)
718e3744 14223{
37a87b8f
CS
14224 uint8_t distance_ebgp, distance_ibgp, distance_local;
14225
14226 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14227 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14228 distance_local = yang_dnode_get_uint8(dnode, "./local");
14229
14230 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14231 distance_local);
14232}
14233
8cc7152a
CS
14234DEFPY_YANG(bgp_distance_source,
14235 bgp_distance_source_cmd,
14236 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14237 NO_STR
14238 "Define an administrative distance\n"
8cc7152a 14239 "Distance value\n"
e12affc1
SW
14240 "IPv4 source prefix\n"
14241 "IPv6 source prefix\n"
37a87b8f 14242 "Access list name\n")
718e3744 14243{
37a87b8f
CS
14244 afi_t afi;
14245 safi_t safi;
14246 char xpath[XPATH_MAXLEN];
14247
14248 afi = bgp_node_afi(vty);
14249 safi = bgp_node_safi(vty);
14250
8cc7152a
CS
14251 if (!no) {
14252 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14253 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14254 distance_str);
14255 if (acl)
14256 nb_cli_enqueue_change(vty,
14257 "./access-list-policy-export",
14258 NB_OP_CREATE, acl);
14259 else
14260 nb_cli_enqueue_change(vty,
14261 "./access-list-policy-export",
14262 NB_OP_DESTROY, NULL);
14263 } else {
14264 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14265 }
37a87b8f
CS
14266
14267 snprintf(
14268 xpath, sizeof(xpath),
14269 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14270 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14271 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14272
14273 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14274}
14275
37a87b8f
CS
14276void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14277 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14278{
14279 vty_out(vty, " distance %d %s %s\n",
14280 yang_dnode_get_uint8(dnode, "./distance"),
14281 yang_dnode_get_string(dnode, "./prefix"),
14282 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14283 ? yang_dnode_get_string(dnode,
14284 "./access-list-policy-export")
14285 : "");
14286}
14287
7c98d487
DA
14288DEFPY_YANG(
14289 bgp_dampening, bgp_dampening_cmd,
14290 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14291 NO_STR
14292 "BGP Specific commands\n"
14293 "Enable route-flap dampening\n"
14294 "Half-life time for the penalty\n"
14295 "Value to start reusing a route\n"
14296 "Value to start suppressing a route\n"
14297 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14298{
14299 afi_t afi;
14300 safi_t safi;
14301 char xpath[XPATH_MAXLEN];
718e3744 14302
37a87b8f
CS
14303 afi = bgp_node_afi(vty);
14304 safi = bgp_node_safi(vty);
14305
d9ce5113
CS
14306 if (!no) {
14307 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14308 if (argc == 6) {
14309 nb_cli_enqueue_change(vty, "./reach-decay",
14310 NB_OP_MODIFY, halflife_str);
14311 nb_cli_enqueue_change(vty, "./reuse-above",
14312 NB_OP_MODIFY, reuse_str);
14313 nb_cli_enqueue_change(vty, "./suppress-above",
14314 NB_OP_MODIFY, suppress_str);
14315 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14316 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14317 } if (argc == 3) {
14318 nb_cli_enqueue_change(vty, "./reach-decay",
14319 NB_OP_MODIFY, halflife_str);
14320 }
14321 } else {
14322 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14323 }
7ebe9748 14324
37a87b8f
CS
14325 snprintf(
14326 xpath, sizeof(xpath),
14327 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14328 yang_afi_safi_value2identity(afi, safi),
14329 bgp_afi_safi_get_container_str(afi, safi));
14330
14331 return nb_cli_apply_changes(vty, xpath);
718e3744 14332}
14333
37a87b8f
CS
14334void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14335 struct lyd_node *dnode,
14336 bool show_defaults)
718e3744 14337{
37a87b8f
CS
14338 if (!yang_dnode_get_bool(dnode, "./enable"))
14339 return;
14340
14341 int half = DEFAULT_HALF_LIFE * 60;
14342 int reuse = DEFAULT_REUSE;
14343 int suppress = DEFAULT_SUPPRESS;
14344 int max;
14345
14346 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14347 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14348 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14349 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14350
14351 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14352 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14353 vty_out(vty, " bgp dampening\n");
14354 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14355 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14356 vty_out(vty, " bgp dampening %u\n", half);
14357 else
14358 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14359 suppress, max);
718e3744 14360}
14361
718e3744 14362/* Display specified route of BGP table. */
d62a17ae 14363static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14364 const char *ip_str, afi_t afi, safi_t safi,
14365 struct prefix_rd *prd, int prefix_check)
14366{
14367 int ret;
14368 struct prefix match;
9bcb3eef
DS
14369 struct bgp_dest *dest;
14370 struct bgp_dest *rm;
40381db7
DS
14371 struct bgp_path_info *pi;
14372 struct bgp_path_info *pi_temp;
d62a17ae 14373 struct bgp *bgp;
14374 struct bgp_table *table;
14375
14376 /* BGP structure lookup. */
14377 if (view_name) {
14378 bgp = bgp_lookup_by_name(view_name);
14379 if (bgp == NULL) {
14380 vty_out(vty, "%% Can't find BGP instance %s\n",
14381 view_name);
14382 return CMD_WARNING;
14383 }
14384 } else {
14385 bgp = bgp_get_default();
14386 if (bgp == NULL) {
14387 vty_out(vty, "%% No BGP process is configured\n");
14388 return CMD_WARNING;
14389 }
718e3744 14390 }
718e3744 14391
d62a17ae 14392 /* Check IP address argument. */
14393 ret = str2prefix(ip_str, &match);
14394 if (!ret) {
14395 vty_out(vty, "%% address is malformed\n");
14396 return CMD_WARNING;
14397 }
718e3744 14398
d62a17ae 14399 match.family = afi2family(afi);
14400
14401 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14402 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14403 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14404 dest = bgp_route_next(dest)) {
14405 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14406
9bcb3eef 14407 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14408 continue;
9bcb3eef 14409 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14410 if (!table)
ea47320b
DL
14411 continue;
14412 if ((rm = bgp_node_match(table, &match)) == NULL)
14413 continue;
d62a17ae 14414
9bcb3eef 14415 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14416
ea47320b 14417 if (!prefix_check
b54892e0 14418 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14419 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14420 while (pi) {
14421 if (pi->extra && pi->extra->damp_info) {
14422 pi_temp = pi->next;
ea47320b 14423 bgp_damp_info_free(
40ec3340
DS
14424 &pi->extra->damp_info,
14425 &bgp->damp[afi][safi],
a935f597 14426 1, afi, safi);
40381db7 14427 pi = pi_temp;
ea47320b 14428 } else
40381db7 14429 pi = pi->next;
d62a17ae 14430 }
ea47320b
DL
14431 }
14432
9bcb3eef 14433 bgp_dest_unlock_node(rm);
d62a17ae 14434 }
14435 } else {
9bcb3eef 14436 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14437 != NULL) {
9bcb3eef 14438 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14439
d62a17ae 14440 if (!prefix_check
9bcb3eef
DS
14441 || dest_p->prefixlen == match.prefixlen) {
14442 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14443 while (pi) {
14444 if (pi->extra && pi->extra->damp_info) {
14445 pi_temp = pi->next;
c8ddbd48 14446 struct bgp_damp_info *bdi =
14447 pi->extra->damp_info;
14448 if (bdi->lastrecord
14449 == BGP_RECORD_UPDATE) {
14450 bgp_aggregate_increment(
14451 bgp,
14452 &bdi->dest->p,
14453 bdi->path,
14454 bdi->afi,
14455 bdi->safi);
14456 bgp_process(bgp,
14457 bdi->dest,
14458 bdi->afi,
14459 bdi->safi);
14460 }
d62a17ae 14461 bgp_damp_info_free(
40ec3340
DS
14462 &pi->extra->damp_info,
14463 &bgp->damp[afi][safi],
a935f597 14464 1, afi, safi);
40381db7 14465 pi = pi_temp;
d62a17ae 14466 } else
40381db7 14467 pi = pi->next;
d62a17ae 14468 }
14469 }
14470
9bcb3eef 14471 bgp_dest_unlock_node(dest);
d62a17ae 14472 }
14473 }
718e3744 14474
d62a17ae 14475 return CMD_SUCCESS;
718e3744 14476}
14477
14478DEFUN (clear_ip_bgp_dampening,
14479 clear_ip_bgp_dampening_cmd,
14480 "clear ip bgp dampening",
14481 CLEAR_STR
14482 IP_STR
14483 BGP_STR
14484 "Clear route flap dampening information\n")
14485{
40ec3340 14486 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14487 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14488 SAFI_UNICAST);
d62a17ae 14489 return CMD_SUCCESS;
718e3744 14490}
14491
14492DEFUN (clear_ip_bgp_dampening_prefix,
14493 clear_ip_bgp_dampening_prefix_cmd,
14494 "clear ip bgp dampening A.B.C.D/M",
14495 CLEAR_STR
14496 IP_STR
14497 BGP_STR
14498 "Clear route flap dampening information\n"
0c7b1b01 14499 "IPv4 prefix\n")
718e3744 14500{
d62a17ae 14501 int idx_ipv4_prefixlen = 4;
14502 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14503 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14504}
14505
14506DEFUN (clear_ip_bgp_dampening_address,
14507 clear_ip_bgp_dampening_address_cmd,
14508 "clear ip bgp dampening A.B.C.D",
14509 CLEAR_STR
14510 IP_STR
14511 BGP_STR
14512 "Clear route flap dampening information\n"
14513 "Network to clear damping information\n")
14514{
d62a17ae 14515 int idx_ipv4 = 4;
14516 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14517 SAFI_UNICAST, NULL, 0);
718e3744 14518}
14519
14520DEFUN (clear_ip_bgp_dampening_address_mask,
14521 clear_ip_bgp_dampening_address_mask_cmd,
14522 "clear ip bgp dampening A.B.C.D A.B.C.D",
14523 CLEAR_STR
14524 IP_STR
14525 BGP_STR
14526 "Clear route flap dampening information\n"
14527 "Network to clear damping information\n"
14528 "Network mask\n")
14529{
d62a17ae 14530 int idx_ipv4 = 4;
14531 int idx_ipv4_2 = 5;
14532 int ret;
14533 char prefix_str[BUFSIZ];
718e3744 14534
d62a17ae 14535 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14536 prefix_str, sizeof(prefix_str));
d62a17ae 14537 if (!ret) {
14538 vty_out(vty, "%% Inconsistent address and mask\n");
14539 return CMD_WARNING;
14540 }
718e3744 14541
d62a17ae 14542 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14543 NULL, 0);
718e3744 14544}
6b0655a2 14545
e3b78da8 14546static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14547{
14548 struct vty *vty = arg;
e3b78da8 14549 struct peer *peer = bucket->data;
825d9834
DS
14550 char buf[SU_ADDRSTRLEN];
14551
14552 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14553 sockunion2str(&peer->su, buf, sizeof(buf)));
14554}
14555
2a0e69ae
DS
14556DEFUN (show_bgp_listeners,
14557 show_bgp_listeners_cmd,
14558 "show bgp listeners",
14559 SHOW_STR
14560 BGP_STR
14561 "Display Listen Sockets and who created them\n")
14562{
14563 bgp_dump_listener_info(vty);
14564
14565 return CMD_SUCCESS;
14566}
14567
825d9834
DS
14568DEFUN (show_bgp_peerhash,
14569 show_bgp_peerhash_cmd,
14570 "show bgp peerhash",
14571 SHOW_STR
14572 BGP_STR
14573 "Display information about the BGP peerhash\n")
14574{
14575 struct list *instances = bm->bgp;
14576 struct listnode *node;
14577 struct bgp *bgp;
14578
14579 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14580 vty_out(vty, "BGP: %s\n", bgp->name);
14581 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14582 vty);
14583 }
14584
14585 return CMD_SUCCESS;
14586}
14587
587ff0fd 14588/* also used for encap safi */
2b791107
DL
14589static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14590 afi_t afi, safi_t safi)
d62a17ae 14591{
9bcb3eef
DS
14592 struct bgp_dest *pdest;
14593 struct bgp_dest *dest;
d62a17ae 14594 struct bgp_table *table;
b54892e0
DS
14595 const struct prefix *p;
14596 const struct prefix_rd *prd;
d62a17ae 14597 struct bgp_static *bgp_static;
14598 mpls_label_t label;
d62a17ae 14599 char rdbuf[RD_ADDRSTRLEN];
14600
14601 /* Network configuration. */
9bcb3eef
DS
14602 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14603 pdest = bgp_route_next(pdest)) {
14604 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14605 if (!table)
ea47320b 14606 continue;
d62a17ae 14607
9bcb3eef
DS
14608 for (dest = bgp_table_top(table); dest;
14609 dest = bgp_route_next(dest)) {
14610 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14611 if (bgp_static == NULL)
ea47320b 14612 continue;
d62a17ae 14613
9bcb3eef
DS
14614 p = bgp_dest_get_prefix(dest);
14615 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14616 pdest);
d62a17ae 14617
ea47320b 14618 /* "network" configuration display. */
06b9f471 14619 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14620 label = decode_label(&bgp_static->label);
14621
8228a9a7 14622 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14623 if (safi == SAFI_MPLS_VPN)
14624 vty_out(vty, " label %u", label);
14625
14626 if (bgp_static->rmap.name)
14627 vty_out(vty, " route-map %s",
14628 bgp_static->rmap.name);
e2a86ad9
DS
14629
14630 if (bgp_static->backdoor)
14631 vty_out(vty, " backdoor");
14632
ea47320b
DL
14633 vty_out(vty, "\n");
14634 }
14635 }
d62a17ae 14636}
14637
2b791107
DL
14638static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14639 afi_t afi, safi_t safi)
d62a17ae 14640{
9bcb3eef
DS
14641 struct bgp_dest *pdest;
14642 struct bgp_dest *dest;
d62a17ae 14643 struct bgp_table *table;
b54892e0
DS
14644 const struct prefix *p;
14645 const struct prefix_rd *prd;
d62a17ae 14646 struct bgp_static *bgp_static;
ff44f570 14647 char buf[PREFIX_STRLEN * 2];
d62a17ae 14648 char buf2[SU_ADDRSTRLEN];
14649 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14650 char esi_buf[ESI_BYTES];
d62a17ae 14651
14652 /* Network configuration. */
9bcb3eef
DS
14653 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14654 pdest = bgp_route_next(pdest)) {
14655 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14656 if (!table)
ea47320b 14657 continue;
d62a17ae 14658
9bcb3eef
DS
14659 for (dest = bgp_table_top(table); dest;
14660 dest = bgp_route_next(dest)) {
14661 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14662 if (bgp_static == NULL)
ea47320b 14663 continue;
d62a17ae 14664
ea47320b 14665 char *macrouter = NULL;
d62a17ae 14666
ea47320b
DL
14667 if (bgp_static->router_mac)
14668 macrouter = prefix_mac2str(
14669 bgp_static->router_mac, NULL, 0);
14670 if (bgp_static->eth_s_id)
0a50c248
AK
14671 esi_to_str(bgp_static->eth_s_id,
14672 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14673 p = bgp_dest_get_prefix(dest);
14674 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14675
ea47320b 14676 /* "network" configuration display. */
06b9f471 14677 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14678 if (p->u.prefix_evpn.route_type == 5) {
14679 char local_buf[PREFIX_STRLEN];
3714a385 14680 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14681 struct prefix_evpn *)p)
14682 ? AF_INET
14683 : AF_INET6;
3714a385 14684 inet_ntop(family,
14685 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14686 local_buf, PREFIX_STRLEN);
772270f3
QY
14687 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14688 p->u.prefix_evpn.prefix_addr
14689 .ip_prefix_length);
197cb530
PG
14690 } else {
14691 prefix2str(p, buf, sizeof(buf));
14692 }
ea47320b 14693
a4d82a8a
PZ
14694 if (bgp_static->gatewayIp.family == AF_INET
14695 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14696 inet_ntop(bgp_static->gatewayIp.family,
14697 &bgp_static->gatewayIp.u.prefix, buf2,
14698 sizeof(buf2));
ea47320b 14699 vty_out(vty,
7bcc8dac 14700 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14701 buf, rdbuf,
14702 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14703 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14704 macrouter);
14705
0a22ddfb 14706 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14707 }
14708 }
3da6fcd5
PG
14709}
14710
718e3744 14711/* Configuration of static route announcement and aggregate
14712 information. */
2b791107
DL
14713void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14714 safi_t safi)
d62a17ae 14715{
9bcb3eef 14716 struct bgp_dest *dest;
b54892e0 14717 const struct prefix *p;
d62a17ae 14718 struct bgp_static *bgp_static;
14719 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14720
2b791107
DL
14721 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14722 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14723 return;
14724 }
d62a17ae 14725
2b791107
DL
14726 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14727 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14728 return;
14729 }
d62a17ae 14730
14731 /* Network configuration. */
9bcb3eef
DS
14732 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14733 dest = bgp_route_next(dest)) {
14734 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14735 if (bgp_static == NULL)
ea47320b 14736 continue;
d62a17ae 14737
9bcb3eef 14738 p = bgp_dest_get_prefix(dest);
d62a17ae 14739
8228a9a7 14740 vty_out(vty, " network %pFX", p);
d62a17ae 14741
ea47320b
DL
14742 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14743 vty_out(vty, " label-index %u",
14744 bgp_static->label_index);
d62a17ae 14745
ea47320b
DL
14746 if (bgp_static->rmap.name)
14747 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14748
14749 if (bgp_static->backdoor)
14750 vty_out(vty, " backdoor");
718e3744 14751
ea47320b
DL
14752 vty_out(vty, "\n");
14753 }
14754
d62a17ae 14755 /* Aggregate-address configuration. */
9bcb3eef
DS
14756 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14757 dest = bgp_route_next(dest)) {
14758 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14759 if (bgp_aggregate == NULL)
ea47320b 14760 continue;
d62a17ae 14761
9bcb3eef 14762 p = bgp_dest_get_prefix(dest);
d62a17ae 14763
8228a9a7 14764 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14765
ea47320b
DL
14766 if (bgp_aggregate->as_set)
14767 vty_out(vty, " as-set");
d62a17ae 14768
ea47320b
DL
14769 if (bgp_aggregate->summary_only)
14770 vty_out(vty, " summary-only");
718e3744 14771
20894f50
DA
14772 if (bgp_aggregate->rmap.name)
14773 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14774
229757f1
DA
14775 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14776 vty_out(vty, " origin %s",
14777 bgp_origin2str(bgp_aggregate->origin));
14778
6aabb15d
RZ
14779 if (bgp_aggregate->match_med)
14780 vty_out(vty, " matching-MED-only");
14781
365ab2e7
RZ
14782 if (bgp_aggregate->suppress_map_name)
14783 vty_out(vty, " suppress-map %s",
14784 bgp_aggregate->suppress_map_name);
14785
ea47320b
DL
14786 vty_out(vty, "\n");
14787 }
d62a17ae 14788}
734b349e 14789
2b791107 14790void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14791 safi_t safi)
d62a17ae 14792{
9bcb3eef 14793 struct bgp_dest *dest;
d62a17ae 14794 struct bgp_distance *bdistance;
14795
14796 /* Distance configuration. */
14797 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14798 && bgp->distance_local[afi][safi]
14799 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14800 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14801 || bgp->distance_local[afi][safi]
14802 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14803 vty_out(vty, " distance bgp %d %d %d\n",
14804 bgp->distance_ebgp[afi][safi],
14805 bgp->distance_ibgp[afi][safi],
14806 bgp->distance_local[afi][safi]);
14807 }
734b349e 14808
9bcb3eef
DS
14809 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14810 dest = bgp_route_next(dest)) {
14811 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14812 if (bdistance != NULL)
56ca3b5b 14813 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14814 bdistance->distance, dest,
d62a17ae 14815 bdistance->access_list ? bdistance->access_list
14816 : "");
ca2e160d 14817 }
718e3744 14818}
14819
14820/* Allocate routing table structure and install commands. */
d62a17ae 14821void bgp_route_init(void)
14822{
14823 afi_t afi;
14824 safi_t safi;
14825
14826 /* Init BGP distance table. */
05c7a1cc 14827 FOREACH_AFI_SAFI (afi, safi)
960035b2 14828 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14829
14830 /* IPv4 BGP commands. */
14831 install_element(BGP_NODE, &bgp_table_map_cmd);
14832 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14833 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14834
554b3b10 14835 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14836
14837 /* IPv4 unicast configuration. */
14838 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14839 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14840 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14841
554b3b10 14842 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14843
14844 /* IPv4 multicast configuration. */
14845 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14846 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14847 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14848 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14849
14850 /* IPv4 labeled-unicast configuration. */
fb985e0c 14851 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14852 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14853
d62a17ae 14854 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14855 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14856 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14857 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14858 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14859 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14860 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14861 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14862
14863 install_element(VIEW_NODE,
14864 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14865 install_element(VIEW_NODE,
14866 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14867 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14868 install_element(VIEW_NODE,
14869 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14870#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14871 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14872#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14873 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14874 install_element(VIEW_NODE,
44c69747 14875 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14876
d62a17ae 14877 /* BGP dampening clear commands */
14878 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14879 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14880
d62a17ae 14881 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14882 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14883
14884 /* prefix count */
14885 install_element(ENABLE_NODE,
14886 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14887#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14888 install_element(ENABLE_NODE,
14889 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14890#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14891
d62a17ae 14892 /* New config IPv6 BGP commands. */
14893 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14894 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14895 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14896
554b3b10 14897 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14898
14899 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14900
fb985e0c
DA
14901 /* IPv6 labeled unicast address family. */
14902 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14903 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14904
d62a17ae 14905 install_element(BGP_NODE, &bgp_distance_cmd);
14906 install_element(BGP_NODE, &no_bgp_distance_cmd);
14907 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14908 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14909 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14910 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14911 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14912 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14913 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14914 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14915 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14916 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14917 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14918 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14919 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14920
ef5f4b23 14921 /* BGP dampening */
d9ce5113
CS
14922 install_element(BGP_NODE, &bgp_dampening_cmd);
14923 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14924 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14925 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14926 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14927 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14928 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14929
14930 /* Large Communities */
14931 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14932 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14933
14934 /* show bgp ipv4 flowspec detailed */
14935 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14936
2a0e69ae 14937 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14938 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14939}
14940
14941void bgp_route_finish(void)
14942{
14943 afi_t afi;
14944 safi_t safi;
14945
05c7a1cc
QY
14946 FOREACH_AFI_SAFI (afi, safi) {
14947 bgp_table_unlock(bgp_distance_table[afi][safi]);
14948 bgp_distance_table[afi][safi] = NULL;
14949 }
228da428 14950}