]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #8153 from reubendowle/nhrp-multicast
[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. */
7d3cae70
DA
8226static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8227 struct vty *vty, 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);
7d3cae70 8244 json_object_int_add(json, "version", dest->version);
c6462ff4 8245 }
d62a17ae 8246 } else if (p->family == AF_ETHERNET) {
8228a9a7 8247 len = vty_out(vty, "%pFX", p);
b03b8898 8248 } else if (p->family == AF_EVPN) {
57f7feb6 8249 if (!json)
2dbe669b 8250 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8251 else
60466a63 8252 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8253 } else if (p->family == AF_FLOWSPEC) {
8254 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8255 json ?
8256 NLRI_STRING_FORMAT_JSON_SIMPLE :
8257 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8258 } else {
c6462ff4 8259 if (!json)
8228a9a7 8260 len = vty_out(vty, "%pFX", p);
50e05855
AD
8261 else {
8262 json_object_string_add(json, "prefix",
8263 inet_ntop(p->family,
8264 &p->u.prefix, buf,
8265 BUFSIZ));
8266 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8267 prefix2str(p, buf2, PREFIX_STRLEN);
8268 json_object_string_add(json, "network", buf2);
7d3cae70 8269 json_object_int_add(json, "version", dest->version);
37d4e0df 8270 }
9c92b5f7 8271 }
d62a17ae 8272
9c92b5f7 8273 if (!json) {
ae248832 8274 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8275 if (len < 1)
8276 vty_out(vty, "\n%*s", 20, " ");
8277 else
8278 vty_out(vty, "%*s", len, " ");
8279 }
718e3744 8280}
8281
d62a17ae 8282enum bgp_display_type {
8283 normal_list,
718e3744 8284};
8285
bbb46eb5
DA
8286static const char *
8287bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8288{
8289 switch (reason) {
8290 case bgp_path_selection_none:
8291 return "Nothing to Select";
8292 case bgp_path_selection_first:
8293 return "First path received";
8294 case bgp_path_selection_evpn_sticky_mac:
8295 return "EVPN Sticky Mac";
8296 case bgp_path_selection_evpn_seq:
8297 return "EVPN sequence number";
8298 case bgp_path_selection_evpn_lower_ip:
8299 return "EVPN lower IP";
8300 case bgp_path_selection_evpn_local_path:
8301 return "EVPN local ES path";
8302 case bgp_path_selection_evpn_non_proxy:
8303 return "EVPN non proxy";
8304 case bgp_path_selection_weight:
8305 return "Weight";
8306 case bgp_path_selection_local_pref:
8307 return "Local Pref";
8308 case bgp_path_selection_local_route:
8309 return "Local Route";
8310 case bgp_path_selection_confed_as_path:
8311 return "Confederation based AS Path";
8312 case bgp_path_selection_as_path:
8313 return "AS Path";
8314 case bgp_path_selection_origin:
8315 return "Origin";
8316 case bgp_path_selection_med:
8317 return "MED";
8318 case bgp_path_selection_peer:
8319 return "Peer Type";
8320 case bgp_path_selection_confed:
8321 return "Confed Peer Type";
8322 case bgp_path_selection_igp_metric:
8323 return "IGP Metric";
8324 case bgp_path_selection_older:
8325 return "Older Path";
8326 case bgp_path_selection_router_id:
8327 return "Router ID";
8328 case bgp_path_selection_cluster_length:
bcab253c 8329 return "Cluster length";
bbb46eb5
DA
8330 case bgp_path_selection_stale:
8331 return "Path Staleness";
8332 case bgp_path_selection_local_configured:
8333 return "Locally configured route";
8334 case bgp_path_selection_neighbor_ip:
8335 return "Neighbor IP";
8336 case bgp_path_selection_default:
8337 return "Nothing left to compare";
8338 }
8339 return "Invalid (internal error)";
8340}
8341
18ee8310 8342/* Print the short form route status for a bgp_path_info */
4b7e6066 8343static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8344 struct bgp_path_info *path,
d62a17ae 8345 json_object *json_path)
718e3744 8346{
d62a17ae 8347 if (json_path) {
b05a1c8b 8348
d62a17ae 8349 /* Route status display. */
9b6d8fcf 8350 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8351 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8352
9b6d8fcf 8353 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8354 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8355
4056a5f6 8356 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8357 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8358
9b6d8fcf
DS
8359 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8360 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8361 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8362
d62a17ae 8363 /* Selected */
9b6d8fcf 8364 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8365 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8366
9b6d8fcf 8367 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8368 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8369
bbb46eb5 8370 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8371 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8372 json_object_string_add(json_path, "selectionReason",
8373 bgp_path_selection_reason2str(
8374 path->net->reason));
8375 }
b05a1c8b 8376
9b6d8fcf 8377 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8378 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8379
d62a17ae 8380 /* Internal route. */
9b6d8fcf
DS
8381 if ((path->peer->as)
8382 && (path->peer->as == path->peer->local_as))
d62a17ae 8383 json_object_string_add(json_path, "pathFrom",
8384 "internal");
8385 else
8386 json_object_string_add(json_path, "pathFrom",
8387 "external");
b05a1c8b 8388
d62a17ae 8389 return;
8390 }
b05a1c8b 8391
d62a17ae 8392 /* Route status display. */
9b6d8fcf 8393 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8394 vty_out(vty, "R");
9b6d8fcf 8395 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8396 vty_out(vty, "S");
4056a5f6 8397 else if (bgp_path_suppressed(path))
d62a17ae 8398 vty_out(vty, "s");
9b6d8fcf
DS
8399 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8400 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8401 vty_out(vty, "*");
8402 else
8403 vty_out(vty, " ");
8404
8405 /* Selected */
9b6d8fcf 8406 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8407 vty_out(vty, "h");
9b6d8fcf 8408 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8409 vty_out(vty, "d");
9b6d8fcf 8410 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8411 vty_out(vty, ">");
9b6d8fcf 8412 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8413 vty_out(vty, "=");
8414 else
8415 vty_out(vty, " ");
718e3744 8416
d62a17ae 8417 /* Internal route. */
9b6d8fcf
DS
8418 if (path->peer && (path->peer->as)
8419 && (path->peer->as == path->peer->local_as))
d62a17ae 8420 vty_out(vty, "i");
8421 else
8422 vty_out(vty, " ");
b40d939b 8423}
8424
2ba93fd6
DA
8425static char *bgp_nexthop_hostname(struct peer *peer,
8426 struct bgp_nexthop_cache *bnc)
25b5da8d 8427{
892fedb6 8428 if (peer->hostname
aef999a2 8429 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8430 return peer->hostname;
8431 return NULL;
8432}
8433
b40d939b 8434/* called from terminal list command */
bd494ec5 8435void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8436 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8437 json_object *json_paths, bool wide)
d62a17ae 8438{
aef999a2 8439 int len;
515c2602 8440 struct attr *attr = path->attr;
d62a17ae 8441 json_object *json_path = NULL;
8442 json_object *json_nexthops = NULL;
8443 json_object *json_nexthop_global = NULL;
8444 json_object *json_nexthop_ll = NULL;
6f214dd3 8445 json_object *json_ext_community = NULL;
9df8b37c 8446 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8447 bool nexthop_self =
9b6d8fcf 8448 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8449 bool nexthop_othervrf = false;
43089216 8450 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8451 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8452 char *nexthop_hostname =
8453 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8454 char esi_buf[ESI_STR_LEN];
d62a17ae 8455
8456 if (json_paths)
8457 json_path = json_object_new_object();
8458
8459 /* short status lead text */
9b6d8fcf 8460 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8461
8462 if (!json_paths) {
8463 /* print prefix and mask */
8464 if (!display)
7d3cae70 8465 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8466 else
ae248832 8467 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8468 } else {
7d3cae70 8469 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8470 }
47fc97cc 8471
9df8b37c
PZ
8472 /*
8473 * If vrf id of nexthop is different from that of prefix,
8474 * set up printable string to append
8475 */
9b6d8fcf 8476 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8477 const char *self = "";
8478
8479 if (nexthop_self)
8480 self = "<";
8481
8482 nexthop_othervrf = true;
9b6d8fcf 8483 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8484
9b6d8fcf 8485 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8486 snprintf(vrf_id_str, sizeof(vrf_id_str),
8487 "@%s%s", VRFID_NONE_STR, self);
8488 else
8489 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8490 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8491
9b6d8fcf
DS
8492 if (path->extra->bgp_orig->inst_type
8493 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8494
9b6d8fcf 8495 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8496 } else {
8497 const char *self = "";
8498
8499 if (nexthop_self)
8500 self = "<";
8501
8502 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8503 }
8504
445c2480
DS
8505 /*
8506 * For ENCAP and EVPN routes, nexthop address family is not
8507 * neccessarily the same as the prefix address family.
8508 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8509 * EVPN routes are also exchanged with a MP nexthop. Currently,
8510 * this
8511 * is only IPv4, the value will be present in either
8512 * attr->nexthop or
8513 * attr->mp_nexthop_global_in
8514 */
8515 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8516 char buf[BUFSIZ];
8517 char nexthop[128];
8518 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8519
8520 switch (af) {
8521 case AF_INET:
772270f3
QY
8522 snprintf(nexthop, sizeof(nexthop), "%s",
8523 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8524 BUFSIZ));
445c2480
DS
8525 break;
8526 case AF_INET6:
772270f3
QY
8527 snprintf(nexthop, sizeof(nexthop), "%s",
8528 inet_ntop(af, &attr->mp_nexthop_global, buf,
8529 BUFSIZ));
445c2480
DS
8530 break;
8531 default:
772270f3 8532 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8533 break;
d62a17ae 8534 }
d62a17ae 8535
445c2480
DS
8536 if (json_paths) {
8537 json_nexthop_global = json_object_new_object();
8538
515c2602
DA
8539 json_object_string_add(json_nexthop_global, "ip",
8540 nexthop);
8541
939a97f4 8542 if (path->peer->hostname)
515c2602
DA
8543 json_object_string_add(json_nexthop_global,
8544 "hostname",
939a97f4 8545 path->peer->hostname);
515c2602
DA
8546
8547 json_object_string_add(json_nexthop_global, "afi",
8548 (af == AF_INET) ? "ipv4"
8549 : "ipv6");
445c2480
DS
8550 json_object_boolean_true_add(json_nexthop_global,
8551 "used");
aef999a2
DA
8552 } else {
8553 if (nexthop_hostname)
8554 len = vty_out(vty, "%s(%s)%s", nexthop,
8555 nexthop_hostname, vrf_id_str);
8556 else
8557 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8558
ae248832 8559 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8560 if (len < 1)
8561 vty_out(vty, "\n%*s", 36, " ");
8562 else
8563 vty_out(vty, "%*s", len, " ");
8564 }
445c2480
DS
8565 } else if (safi == SAFI_EVPN) {
8566 if (json_paths) {
23d0a753
DA
8567 char buf[BUFSIZ] = {0};
8568
445c2480
DS
8569 json_nexthop_global = json_object_new_object();
8570
515c2602 8571 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8572 inet_ntop(AF_INET,
8573 &attr->nexthop, buf,
8574 sizeof(buf)));
515c2602 8575
939a97f4 8576 if (path->peer->hostname)
515c2602
DA
8577 json_object_string_add(json_nexthop_global,
8578 "hostname",
939a97f4 8579 path->peer->hostname);
515c2602 8580
a4d82a8a
PZ
8581 json_object_string_add(json_nexthop_global, "afi",
8582 "ipv4");
445c2480
DS
8583 json_object_boolean_true_add(json_nexthop_global,
8584 "used");
aef999a2
DA
8585 } else {
8586 if (nexthop_hostname)
8587 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8588 nexthop_hostname, vrf_id_str);
8589 else
8590 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8591 vrf_id_str);
8592
ae248832 8593 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8594 if (len < 1)
8595 vty_out(vty, "\n%*s", 36, " ");
8596 else
8597 vty_out(vty, "%*s", len, " ");
8598 }
d33fc23b 8599 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8600 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8601 if (json_paths) {
23d0a753
DA
8602 char buf[BUFSIZ] = {0};
8603
026b914a 8604 json_nexthop_global = json_object_new_object();
515c2602 8605
026b914a
PG
8606 json_object_string_add(json_nexthop_global,
8607 "afi", "ipv4");
515c2602
DA
8608 json_object_string_add(
8609 json_nexthop_global, "ip",
23d0a753
DA
8610 inet_ntop(AF_INET, &attr->nexthop, buf,
8611 sizeof(buf)));
515c2602 8612
939a97f4 8613 if (path->peer->hostname)
515c2602
DA
8614 json_object_string_add(
8615 json_nexthop_global, "hostname",
939a97f4 8616 path->peer->hostname);
515c2602 8617
50e05855
AD
8618 json_object_boolean_true_add(
8619 json_nexthop_global,
026b914a
PG
8620 "used");
8621 } else {
aef999a2
DA
8622 if (nexthop_hostname)
8623 len = vty_out(vty, "%pI4(%s)%s",
8624 &attr->nexthop,
8625 nexthop_hostname,
8626 vrf_id_str);
8627 else
8628 len = vty_out(vty, "%pI4%s",
8629 &attr->nexthop,
8630 vrf_id_str);
8631
ae248832 8632 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8633 if (len < 1)
8634 vty_out(vty, "\n%*s", 36, " ");
8635 else
8636 vty_out(vty, "%*s", len, " ");
026b914a
PG
8637 }
8638 }
d33fc23b 8639 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8640 if (json_paths) {
23d0a753
DA
8641 char buf[BUFSIZ] = {0};
8642
445c2480 8643 json_nexthop_global = json_object_new_object();
d62a17ae 8644
515c2602 8645 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8646 inet_ntop(AF_INET,
8647 &attr->nexthop, buf,
8648 sizeof(buf)));
515c2602 8649
939a97f4 8650 if (path->peer->hostname)
515c2602
DA
8651 json_object_string_add(json_nexthop_global,
8652 "hostname",
939a97f4 8653 path->peer->hostname);
445c2480 8654
a4d82a8a
PZ
8655 json_object_string_add(json_nexthop_global, "afi",
8656 "ipv4");
445c2480
DS
8657 json_object_boolean_true_add(json_nexthop_global,
8658 "used");
8659 } else {
aef999a2
DA
8660 if (nexthop_hostname)
8661 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8662 nexthop_hostname, vrf_id_str);
8663 else
8664 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8665 vrf_id_str);
9df8b37c 8666
ae248832 8667 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8668 if (len < 1)
8669 vty_out(vty, "\n%*s", 36, " ");
8670 else
8671 vty_out(vty, "%*s", len, " ");
d62a17ae 8672 }
445c2480 8673 }
b05a1c8b 8674
445c2480 8675 /* IPv6 Next Hop */
a4d82a8a 8676 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8677 char buf[BUFSIZ];
d62a17ae 8678
445c2480
DS
8679 if (json_paths) {
8680 json_nexthop_global = json_object_new_object();
a4d82a8a 8681 json_object_string_add(
515c2602
DA
8682 json_nexthop_global, "ip",
8683 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8684 buf, BUFSIZ));
8685
939a97f4 8686 if (path->peer->hostname)
515c2602
DA
8687 json_object_string_add(json_nexthop_global,
8688 "hostname",
939a97f4 8689 path->peer->hostname);
515c2602 8690
a4d82a8a
PZ
8691 json_object_string_add(json_nexthop_global, "afi",
8692 "ipv6");
8693 json_object_string_add(json_nexthop_global, "scope",
8694 "global");
445c2480
DS
8695
8696 /* We display both LL & GL if both have been
8697 * received */
0606039c
DA
8698 if ((attr->mp_nexthop_len
8699 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8700 || (path->peer->conf_if)) {
a4d82a8a 8701 json_nexthop_ll = json_object_new_object();
d62a17ae 8702 json_object_string_add(
515c2602
DA
8703 json_nexthop_ll, "ip",
8704 inet_ntop(AF_INET6,
8705 &attr->mp_nexthop_local, buf,
8706 BUFSIZ));
8707
939a97f4 8708 if (path->peer->hostname)
515c2602
DA
8709 json_object_string_add(
8710 json_nexthop_ll, "hostname",
939a97f4 8711 path->peer->hostname);
515c2602 8712
a4d82a8a
PZ
8713 json_object_string_add(json_nexthop_ll, "afi",
8714 "ipv6");
8715 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8716 "link-local");
d62a17ae 8717
a4d82a8a
PZ
8718 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8719 &attr->mp_nexthop_local)
445c2480
DS
8720 != 0)
8721 && !attr->mp_nexthop_prefer_global)
d62a17ae 8722 json_object_boolean_true_add(
a4d82a8a 8723 json_nexthop_ll, "used");
445c2480
DS
8724 else
8725 json_object_boolean_true_add(
a4d82a8a 8726 json_nexthop_global, "used");
445c2480
DS
8727 } else
8728 json_object_boolean_true_add(
8729 json_nexthop_global, "used");
8730 } else {
8731 /* Display LL if LL/Global both in table unless
8732 * prefer-global is set */
0606039c
DA
8733 if (((attr->mp_nexthop_len
8734 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8735 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8736 || (path->peer->conf_if)) {
8737 if (path->peer->conf_if) {
a4d82a8a 8738 len = vty_out(vty, "%s",
9b6d8fcf 8739 path->peer->conf_if);
ae248832
MK
8740 /* len of IPv6 addr + max len of def
8741 * ifname */
8742 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8743
8744 if (len < 1)
a4d82a8a 8745 vty_out(vty, "\n%*s", 36, " ");
445c2480 8746 else
a4d82a8a 8747 vty_out(vty, "%*s", len, " ");
d62a17ae 8748 } else {
aef999a2
DA
8749 if (nexthop_hostname)
8750 len = vty_out(
8751 vty, "%pI6(%s)%s",
8752 &attr->mp_nexthop_local,
8753 nexthop_hostname,
8754 vrf_id_str);
8755 else
8756 len = vty_out(
8757 vty, "%pI6%s",
8758 &attr->mp_nexthop_local,
8759 vrf_id_str);
8760
ae248832 8761 len = wide ? (41 - len) : (16 - len);
d62a17ae 8762
8763 if (len < 1)
a4d82a8a 8764 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8765 else
a4d82a8a 8766 vty_out(vty, "%*s", len, " ");
d62a17ae 8767 }
445c2480 8768 } else {
aef999a2
DA
8769 if (nexthop_hostname)
8770 len = vty_out(vty, "%pI6(%s)%s",
8771 &attr->mp_nexthop_global,
8772 nexthop_hostname,
8773 vrf_id_str);
8774 else
8775 len = vty_out(vty, "%pI6%s",
8776 &attr->mp_nexthop_global,
8777 vrf_id_str);
8778
ae248832 8779 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8780
8781 if (len < 1)
8782 vty_out(vty, "\n%*s", 36, " ");
8783 else
8784 vty_out(vty, "%*s", len, " ");
d62a17ae 8785 }
8786 }
445c2480 8787 }
718e3744 8788
445c2480
DS
8789 /* MED/Metric */
8790 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8791 if (json_paths)
50e05855 8792 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8793 else if (wide)
8794 vty_out(vty, "%7u", attr->med);
0fbac0b4 8795 else
445c2480 8796 vty_out(vty, "%10u", attr->med);
ae248832
MK
8797 else if (!json_paths) {
8798 if (wide)
8799 vty_out(vty, "%*s", 7, " ");
8800 else
8801 vty_out(vty, "%*s", 10, " ");
8802 }
d62a17ae 8803
445c2480
DS
8804 /* Local Pref */
8805 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8806 if (json_paths)
50e05855 8807 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8808 attr->local_pref);
8809 else
445c2480
DS
8810 vty_out(vty, "%7u", attr->local_pref);
8811 else if (!json_paths)
8812 vty_out(vty, " ");
d62a17ae 8813
445c2480
DS
8814 if (json_paths)
8815 json_object_int_add(json_path, "weight", attr->weight);
8816 else
8817 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8818
445c2480
DS
8819 if (json_paths) {
8820 char buf[BUFSIZ];
a4d82a8a
PZ
8821 json_object_string_add(
8822 json_path, "peerId",
9b6d8fcf 8823 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8824 }
b05a1c8b 8825
445c2480
DS
8826 /* Print aspath */
8827 if (attr->aspath) {
0fbac0b4 8828 if (json_paths)
50e05855 8829 json_object_string_add(json_path, "path",
0fbac0b4
DA
8830 attr->aspath->str);
8831 else
445c2480 8832 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8833 }
f1aa5d8a 8834
445c2480
DS
8835 /* Print origin */
8836 if (json_paths)
a4d82a8a
PZ
8837 json_object_string_add(json_path, "origin",
8838 bgp_origin_long_str[attr->origin]);
445c2480
DS
8839 else
8840 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8841
9df8b37c 8842 if (json_paths) {
d071f237 8843 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8844 json_object_string_add(json_path, "esi",
8845 esi_to_str(&attr->esi,
8846 esi_buf, sizeof(esi_buf)));
8847 }
6f214dd3
CS
8848 if (safi == SAFI_EVPN &&
8849 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8850 json_ext_community = json_object_new_object();
8851 json_object_string_add(json_ext_community,
8852 "string",
8853 attr->ecommunity->str);
8854 json_object_object_add(json_path,
8855 "extendedCommunity",
8856 json_ext_community);
8857 }
8858
9df8b37c
PZ
8859 if (nexthop_self)
8860 json_object_boolean_true_add(json_path,
8861 "announceNexthopSelf");
8862 if (nexthop_othervrf) {
8863 json_object_string_add(json_path, "nhVrfName",
8864 nexthop_vrfname);
8865
8866 json_object_int_add(json_path, "nhVrfId",
8867 ((nexthop_vrfid == VRF_UNKNOWN)
8868 ? -1
8869 : (int)nexthop_vrfid));
8870 }
8871 }
8872
d62a17ae 8873 if (json_paths) {
8874 if (json_nexthop_global || json_nexthop_ll) {
8875 json_nexthops = json_object_new_array();
f1aa5d8a 8876
d62a17ae 8877 if (json_nexthop_global)
8878 json_object_array_add(json_nexthops,
8879 json_nexthop_global);
f1aa5d8a 8880
d62a17ae 8881 if (json_nexthop_ll)
8882 json_object_array_add(json_nexthops,
8883 json_nexthop_ll);
f1aa5d8a 8884
d62a17ae 8885 json_object_object_add(json_path, "nexthops",
8886 json_nexthops);
8887 }
8888
8889 json_object_array_add(json_paths, json_path);
8890 } else {
8891 vty_out(vty, "\n");
6f214dd3 8892
b5e140c8 8893 if (safi == SAFI_EVPN) {
229587fb
AK
8894 struct bgp_path_es_info *path_es_info = NULL;
8895
d071f237 8896 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8897 /* XXX - add these params to the json out */
b5e140c8 8898 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8899 vty_out(vty, "ESI:%s",
8900 esi_to_str(&attr->esi, esi_buf,
8901 sizeof(esi_buf)));
60605cbc
AK
8902
8903 if (path->extra && path->extra->mh_info)
8904 path_es_info =
8905 path->extra->mh_info->es_info;
8906
229587fb
AK
8907 if (path_es_info && path_es_info->es)
8908 vty_out(vty, " VNI: %u",
8909 path_es_info->vni);
8910 vty_out(vty, "\n");
b5e140c8
AK
8911 }
8912 if (attr->flag &
8913 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8914 vty_out(vty, "%*s", 20, " ");
8915 vty_out(vty, "%s\n", attr->ecommunity->str);
8916 }
6f214dd3
CS
8917 }
8918
49e5a4a0 8919#ifdef ENABLE_BGP_VNC
d62a17ae 8920 /* prints an additional line, indented, with VNC info, if
8921 * present */
8922 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8923 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8924#endif
d62a17ae 8925 }
8926}
718e3744 8927
8928/* called from terminal list command */
7d3cae70
DA
8929void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
8930 const struct prefix *p, struct attr *attr, safi_t safi,
8931 bool use_json, json_object *json_ar, bool wide)
d62a17ae 8932{
8933 json_object *json_status = NULL;
8934 json_object *json_net = NULL;
aef999a2 8935 int len;
d62a17ae 8936 char buff[BUFSIZ];
dc387b0f 8937
d62a17ae 8938 /* Route status display. */
8939 if (use_json) {
8940 json_status = json_object_new_object();
8941 json_net = json_object_new_object();
8942 } else {
8943 vty_out(vty, "*");
8944 vty_out(vty, ">");
8945 vty_out(vty, " ");
8946 }
718e3744 8947
d62a17ae 8948 /* print prefix and mask */
50e05855 8949 if (use_json) {
dc387b0f
LK
8950 if (safi == SAFI_EVPN)
8951 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8952 else if (p->family == AF_INET || p->family == AF_INET6) {
8953 json_object_string_add(
8954 json_net, "addrPrefix",
8955 inet_ntop(p->family, &p->u.prefix, buff,
8956 BUFSIZ));
8957 json_object_int_add(json_net, "prefixLen",
8958 p->prefixlen);
8959 prefix2str(p, buff, PREFIX_STRLEN);
8960 json_object_string_add(json_net, "network", buff);
8961 }
50e05855 8962 } else
7d3cae70 8963 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 8964
8965 /* Print attribute */
8966 if (attr) {
8967 if (use_json) {
23d0a753
DA
8968 char buf[BUFSIZ] = {0};
8969
d62a17ae 8970 if (p->family == AF_INET
8971 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8972 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8973 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8974 json_object_string_add(
8975 json_net, "nextHop",
23d0a753
DA
8976 inet_ntop(
8977 AF_INET,
8978 &attr->mp_nexthop_global_in,
8979 buf, sizeof(buf)));
d62a17ae 8980 else
8981 json_object_string_add(
8982 json_net, "nextHop",
23d0a753
DA
8983 inet_ntop(AF_INET,
8984 &attr->nexthop, buf,
8985 sizeof(buf)));
d62a17ae 8986 } else if (p->family == AF_INET6
8987 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8988 char buf[BUFSIZ];
8989
8990 json_object_string_add(
aa0a10fc 8991 json_net, "nextHopGlobal",
d62a17ae 8992 inet_ntop(AF_INET6,
8993 &attr->mp_nexthop_global, buf,
8994 BUFSIZ));
23d0a753
DA
8995 } else if (p->family == AF_EVPN
8996 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8997 char buf[BUFSIZ] = {0};
8998
8999 json_object_string_add(
9000 json_net, "nextHop",
9001 inet_ntop(AF_INET,
9002 &attr->mp_nexthop_global_in,
9003 buf, sizeof(buf)));
9004 }
d62a17ae 9005
9006 if (attr->flag
9007 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9008 json_object_int_add(json_net, "metric",
9009 attr->med);
9010
0fbac0b4 9011 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9012 json_object_int_add(json_net, "locPrf",
0fbac0b4 9013 attr->local_pref);
d62a17ae 9014
9015 json_object_int_add(json_net, "weight", attr->weight);
9016
9017 /* Print aspath */
0fbac0b4 9018 if (attr->aspath)
50e05855 9019 json_object_string_add(json_net, "path",
0fbac0b4 9020 attr->aspath->str);
d62a17ae 9021
9022 /* Print origin */
9023 json_object_string_add(json_net, "bgpOriginCode",
9024 bgp_origin_str[attr->origin]);
9025 } else {
9026 if (p->family == AF_INET
9027 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9028 || safi == SAFI_EVPN
9029 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9030 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9031 || safi == SAFI_EVPN)
23d0a753
DA
9032 vty_out(vty, "%-16pI4",
9033 &attr->mp_nexthop_global_in);
ae248832 9034 else if (wide)
23d0a753 9035 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9036 else
23d0a753 9037 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9038 } else if (p->family == AF_INET6
9039 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9040 char buf[BUFSIZ];
9041
9042 len = vty_out(
9043 vty, "%s",
9044 inet_ntop(AF_INET6,
9045 &attr->mp_nexthop_global, buf,
9046 BUFSIZ));
ae248832 9047 len = wide ? (41 - len) : (16 - len);
d62a17ae 9048 if (len < 1)
9049 vty_out(vty, "\n%*s", 36, " ");
9050 else
9051 vty_out(vty, "%*s", len, " ");
9052 }
9053 if (attr->flag
9054 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9055 if (wide)
9056 vty_out(vty, "%7u", attr->med);
9057 else
9058 vty_out(vty, "%10u", attr->med);
9059 else if (wide)
9060 vty_out(vty, " ");
d62a17ae 9061 else
9062 vty_out(vty, " ");
718e3744 9063
d62a17ae 9064 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9065 vty_out(vty, "%7u", attr->local_pref);
9066 else
9067 vty_out(vty, " ");
9068
9069 vty_out(vty, "%7u ", attr->weight);
9070
9071 /* Print aspath */
9072 if (attr->aspath)
9073 aspath_print_vty(vty, "%s", attr->aspath, " ");
9074
9075 /* Print origin */
9076 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9077 }
9078 }
9079 if (use_json) {
9080 json_object_boolean_true_add(json_status, "*");
9081 json_object_boolean_true_add(json_status, ">");
9082 json_object_object_add(json_net, "appliedStatusSymbols",
9083 json_status);
1608ff77 9084
dc387b0f
LK
9085 prefix2str(p, buff, PREFIX_STRLEN);
9086 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9087 } else
9088 vty_out(vty, "\n");
9089}
9090
bd494ec5 9091void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9092 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9093 json_object *json)
9094{
9095 json_object *json_out = NULL;
9096 struct attr *attr;
9097 mpls_label_t label = MPLS_INVALID_LABEL;
9098
9b6d8fcf 9099 if (!path->extra)
d62a17ae 9100 return;
9101
9102 if (json)
9103 json_out = json_object_new_object();
9104
9105 /* short status lead text */
9b6d8fcf 9106 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9107
9108 /* print prefix and mask */
9109 if (json == NULL) {
9110 if (!display)
7d3cae70 9111 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9112 else
9113 vty_out(vty, "%*s", 17, " ");
9114 }
9115
9116 /* Print attribute */
9b6d8fcf 9117 attr = path->attr;
05864da7
DS
9118 if (((p->family == AF_INET)
9119 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9120 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9121 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9122 char buf[BUFSIZ] = {0};
9123
05864da7
DS
9124 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9125 || safi == SAFI_EVPN) {
9126 if (json)
9127 json_object_string_add(
9128 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9129 inet_ntop(AF_INET,
9130 &attr->mp_nexthop_global_in,
9131 buf, sizeof(buf)));
05864da7 9132 else
23d0a753
DA
9133 vty_out(vty, "%-16pI4",
9134 &attr->mp_nexthop_global_in);
05864da7
DS
9135 } else {
9136 if (json)
9137 json_object_string_add(
9138 json_out, "nexthop",
23d0a753
DA
9139 inet_ntop(AF_INET, &attr->nexthop, buf,
9140 sizeof(buf)));
05864da7 9141 else
23d0a753 9142 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9143 }
9144 } else if (((p->family == AF_INET6)
9145 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9146 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9147 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9148 char buf_a[512];
9149
9150 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9151 if (json)
9152 json_object_string_add(
9153 json_out, "mpNexthopGlobalIn",
9154 inet_ntop(AF_INET6,
9155 &attr->mp_nexthop_global,
9156 buf_a, sizeof(buf_a)));
9157 else
9158 vty_out(vty, "%s",
9159 inet_ntop(AF_INET6,
9160 &attr->mp_nexthop_global,
9161 buf_a, sizeof(buf_a)));
9162 } else if (attr->mp_nexthop_len
9163 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9164 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9165 &attr->mp_nexthop_global,
9166 &attr->mp_nexthop_local);
9167 if (json)
9168 json_object_string_add(json_out,
9169 "mpNexthopGlobalLocal",
9170 buf_a);
9171 else
9172 vty_out(vty, "%s", buf_a);
d62a17ae 9173 }
9174 }
9175
9b6d8fcf 9176 label = decode_label(&path->extra->label[0]);
d62a17ae 9177
9178 if (bgp_is_valid_label(&label)) {
9179 if (json) {
9180 json_object_int_add(json_out, "notag", label);
9181 json_object_array_add(json, json_out);
9182 } else {
9183 vty_out(vty, "notag/%d", label);
9184 vty_out(vty, "\n");
9185 }
9186 }
9187}
718e3744 9188
bd494ec5 9189void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9190 struct bgp_path_info *path, int display,
d62a17ae 9191 json_object *json_paths)
718e3744 9192{
d62a17ae 9193 struct attr *attr;
14f51eba 9194 char buf[BUFSIZ] = {0};
d62a17ae 9195 json_object *json_path = NULL;
14f51eba
LK
9196 json_object *json_nexthop = NULL;
9197 json_object *json_overlay = NULL;
856ca177 9198
9b6d8fcf 9199 if (!path->extra)
d62a17ae 9200 return;
718e3744 9201
14f51eba
LK
9202 if (json_paths) {
9203 json_path = json_object_new_object();
9204 json_overlay = json_object_new_object();
9205 json_nexthop = json_object_new_object();
9206 }
9207
d62a17ae 9208 /* short status lead text */
9b6d8fcf 9209 route_vty_short_status_out(vty, path, json_path);
856ca177 9210
d62a17ae 9211 /* print prefix and mask */
9212 if (!display)
7d3cae70 9213 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9214 else
9215 vty_out(vty, "%*s", 17, " ");
9216
9217 /* Print attribute */
9b6d8fcf 9218 attr = path->attr;
05864da7
DS
9219 char buf1[BUFSIZ];
9220 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9221
05864da7
DS
9222 switch (af) {
9223 case AF_INET:
9224 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9225 if (!json_path) {
9226 vty_out(vty, "%-16s", buf);
9227 } else {
9228 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9229
05864da7 9230 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9231
05864da7
DS
9232 json_object_object_add(json_path, "nexthop",
9233 json_nexthop);
9234 }
9235 break;
9236 case AF_INET6:
9237 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9238 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9239 if (!json_path) {
9240 vty_out(vty, "%s(%s)", buf, buf1);
9241 } else {
9242 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9243
05864da7
DS
9244 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9245 buf1);
14f51eba 9246
05864da7 9247 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9248
05864da7
DS
9249 json_object_object_add(json_path, "nexthop",
9250 json_nexthop);
9251 }
9252 break;
9253 default:
9254 if (!json_path) {
9255 vty_out(vty, "?");
9256 } else {
9257 json_object_string_add(json_nexthop, "Error",
9258 "Unsupported address-family");
d62a17ae 9259 }
05864da7 9260 }
988258b4 9261
6c924775
DS
9262 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9263
9264 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9265 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9266 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9267 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9268
05864da7
DS
9269 if (!json_path)
9270 vty_out(vty, "/%s", buf);
9271 else
9272 json_object_string_add(json_overlay, "gw", buf);
9273
9274 if (attr->ecommunity) {
9275 char *mac = NULL;
9276 struct ecommunity_val *routermac = ecommunity_lookup(
9277 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9278 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9279
9280 if (routermac)
9281 mac = ecom_mac2str((char *)routermac->val);
9282 if (mac) {
9283 if (!json_path) {
c4efd0f4 9284 vty_out(vty, "/%s", mac);
05864da7
DS
9285 } else {
9286 json_object_string_add(json_overlay, "rmac",
9287 mac);
988258b4 9288 }
05864da7 9289 XFREE(MTYPE_TMP, mac);
988258b4 9290 }
05864da7 9291 }
718e3744 9292
05864da7
DS
9293 if (!json_path) {
9294 vty_out(vty, "\n");
9295 } else {
9296 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9297
05864da7 9298 json_object_array_add(json_paths, json_path);
14f51eba 9299 }
d62a17ae 9300}
718e3744 9301
d62a17ae 9302/* dampening route */
5f040085
DS
9303static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9304 struct bgp_path_info *path, int display,
9305 afi_t afi, safi_t safi, bool use_json,
9306 json_object *json)
d62a17ae 9307{
9308 struct attr *attr;
9309 int len;
9310 char timebuf[BGP_UPTIME_LEN];
9311
9312 /* short status lead text */
9b6d8fcf 9313 route_vty_short_status_out(vty, path, json);
d62a17ae 9314
9315 /* print prefix and mask */
9316 if (!use_json) {
9317 if (!display)
7d3cae70 9318 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9319 else
9320 vty_out(vty, "%*s", 17, " ");
9321 }
9322
9b6d8fcf 9323 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9324 len = 17 - len;
9325 if (len < 1) {
9326 if (!use_json)
9327 vty_out(vty, "\n%*s", 34, " ");
9328 } else {
9329 if (use_json)
9330 json_object_int_add(json, "peerHost", len);
9331 else
9332 vty_out(vty, "%*s", len, " ");
9333 }
9334
9335 if (use_json)
a935f597
DA
9336 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9337 safi, use_json, json);
d62a17ae 9338 else
9b6d8fcf
DS
9339 vty_out(vty, "%s ",
9340 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9341 BGP_UPTIME_LEN, afi, safi,
9342 use_json, json));
d62a17ae 9343
9344 /* Print attribute */
9b6d8fcf 9345 attr = path->attr;
d62a17ae 9346
05864da7
DS
9347 /* Print aspath */
9348 if (attr->aspath) {
d62a17ae 9349 if (use_json)
05864da7
DS
9350 json_object_string_add(json, "asPath",
9351 attr->aspath->str);
d62a17ae 9352 else
05864da7 9353 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9354 }
05864da7
DS
9355
9356 /* Print origin */
9357 if (use_json)
9358 json_object_string_add(json, "origin",
9359 bgp_origin_str[attr->origin]);
9360 else
9361 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9362
d62a17ae 9363 if (!use_json)
9364 vty_out(vty, "\n");
9365}
718e3744 9366
d62a17ae 9367/* flap route */
5f040085
DS
9368static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9369 struct bgp_path_info *path, int display,
9370 afi_t afi, safi_t safi, bool use_json,
9371 json_object *json)
784d3a42 9372{
d62a17ae 9373 struct attr *attr;
9374 struct bgp_damp_info *bdi;
9375 char timebuf[BGP_UPTIME_LEN];
9376 int len;
784d3a42 9377
9b6d8fcf 9378 if (!path->extra)
d62a17ae 9379 return;
784d3a42 9380
9b6d8fcf 9381 bdi = path->extra->damp_info;
784d3a42 9382
d62a17ae 9383 /* short status lead text */
9b6d8fcf 9384 route_vty_short_status_out(vty, path, json);
784d3a42 9385
d62a17ae 9386 /* print prefix and mask */
9387 if (!use_json) {
9388 if (!display)
7d3cae70 9389 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9390 else
9391 vty_out(vty, "%*s", 17, " ");
9392 }
784d3a42 9393
9b6d8fcf 9394 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9395 len = 16 - len;
9396 if (len < 1) {
9397 if (!use_json)
9398 vty_out(vty, "\n%*s", 33, " ");
9399 } else {
9400 if (use_json)
9401 json_object_int_add(json, "peerHost", len);
9402 else
9403 vty_out(vty, "%*s", len, " ");
9404 }
784d3a42 9405
d62a17ae 9406 len = vty_out(vty, "%d", bdi->flap);
9407 len = 5 - len;
9408 if (len < 1) {
9409 if (!use_json)
9410 vty_out(vty, " ");
9411 } else {
9412 if (use_json)
9413 json_object_int_add(json, "bdiFlap", len);
9414 else
9415 vty_out(vty, "%*s", len, " ");
9416 }
9417
9418 if (use_json)
9419 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9420 json);
9421 else
996c9314
LB
9422 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9423 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9424
9b6d8fcf
DS
9425 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9426 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9427 if (use_json)
9b6d8fcf 9428 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9429 BGP_UPTIME_LEN, afi, safi,
9430 use_json, json);
d62a17ae 9431 else
9432 vty_out(vty, "%s ",
9b6d8fcf 9433 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9434 BGP_UPTIME_LEN, afi,
9435 safi, use_json, json));
d62a17ae 9436 } else {
9437 if (!use_json)
9438 vty_out(vty, "%*s ", 8, " ");
9439 }
9440
9441 /* Print attribute */
9b6d8fcf 9442 attr = path->attr;
d62a17ae 9443
05864da7
DS
9444 /* Print aspath */
9445 if (attr->aspath) {
d62a17ae 9446 if (use_json)
05864da7
DS
9447 json_object_string_add(json, "asPath",
9448 attr->aspath->str);
d62a17ae 9449 else
05864da7 9450 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9451 }
05864da7
DS
9452
9453 /* Print origin */
9454 if (use_json)
9455 json_object_string_add(json, "origin",
9456 bgp_origin_str[attr->origin]);
9457 else
9458 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9459
d62a17ae 9460 if (!use_json)
9461 vty_out(vty, "\n");
9462}
9463
9464static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9465 int *first, const char *header,
9466 json_object *json_adv_to)
9467{
9468 char buf1[INET6_ADDRSTRLEN];
9469 json_object *json_peer = NULL;
9470
9471 if (json_adv_to) {
9472 /* 'advertised-to' is a dictionary of peers we have advertised
9473 * this
9474 * prefix too. The key is the peer's IP or swpX, the value is
9475 * the
9476 * hostname if we know it and "" if not.
9477 */
9478 json_peer = json_object_new_object();
9479
9480 if (peer->hostname)
9481 json_object_string_add(json_peer, "hostname",
9482 peer->hostname);
9483
9484 if (peer->conf_if)
9485 json_object_object_add(json_adv_to, peer->conf_if,
9486 json_peer);
9487 else
9488 json_object_object_add(
9489 json_adv_to,
9490 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9491 json_peer);
9492 } else {
9493 if (*first) {
9494 vty_out(vty, "%s", header);
9495 *first = 0;
9496 }
9497
9498 if (peer->hostname
892fedb6 9499 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9500 if (peer->conf_if)
9501 vty_out(vty, " %s(%s)", peer->hostname,
9502 peer->conf_if);
9503 else
9504 vty_out(vty, " %s(%s)", peer->hostname,
9505 sockunion2str(&peer->su, buf1,
9506 SU_ADDRSTRLEN));
9507 } else {
9508 if (peer->conf_if)
9509 vty_out(vty, " %s", peer->conf_if);
9510 else
9511 vty_out(vty, " %s",
9512 sockunion2str(&peer->su, buf1,
9513 SU_ADDRSTRLEN));
9514 }
9515 }
784d3a42
PG
9516}
9517
dcc68b5e
MS
9518static void route_vty_out_tx_ids(struct vty *vty,
9519 struct bgp_addpath_info_data *d)
9520{
9521 int i;
9522
9523 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9524 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9525 d->addpath_tx_id[i],
9526 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9527 }
9528}
9529
5e4d4c8a 9530static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9531 struct bgp_path_info *pi,
9532 struct attr *attr,
9533 json_object *json_path)
5e4d4c8a
AK
9534{
9535 char esi_buf[ESI_STR_LEN];
9536 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9537 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9538 ATTR_ES_PEER_ROUTER);
9539 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9540 ATTR_ES_PEER_ACTIVE);
9541 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9542 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9543 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9544 if (json_path) {
9545 json_object *json_es_info = NULL;
9546
9547 json_object_string_add(
9548 json_path, "esi",
9549 esi_buf);
9550 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9551 json_es_info = json_object_new_object();
9552 if (es_local)
9553 json_object_boolean_true_add(
9554 json_es_info, "localEs");
9555 if (peer_active)
9556 json_object_boolean_true_add(
9557 json_es_info, "peerActive");
9558 if (peer_proxy)
9559 json_object_boolean_true_add(
9560 json_es_info, "peerProxy");
9561 if (peer_router)
9562 json_object_boolean_true_add(
9563 json_es_info, "peerRouter");
9564 if (attr->mm_sync_seqnum)
9565 json_object_int_add(
9566 json_es_info, "peerSeq",
9567 attr->mm_sync_seqnum);
9568 json_object_object_add(
9569 json_path, "es_info",
9570 json_es_info);
9571 }
9572 } else {
9573 if (bgp_evpn_attr_is_sync(attr))
9574 vty_out(vty,
9575 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9576 esi_buf,
9577 es_local ? "local-es":"",
9578 peer_proxy ? "proxy " : "",
9579 peer_active ? "active ":"",
9580 peer_router ? "router ":"",
9581 attr->mm_sync_seqnum);
9582 else
9583 vty_out(vty, " ESI %s %s\n",
9584 esi_buf,
9585 es_local ? "local-es":"");
9586 }
9587}
9588
4933eaaf
DS
9589void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9590 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9591 enum rpki_states rpki_curr_state,
9592 json_object *json_paths)
d62a17ae 9593{
9594 char buf[INET6_ADDRSTRLEN];
9595 char buf1[BUFSIZ];
515c2602 9596 struct attr *attr = path->attr;
d62a17ae 9597 int sockunion_vty_out(struct vty *, union sockunion *);
9598 time_t tbuf;
9599 json_object *json_bestpath = NULL;
9600 json_object *json_cluster_list = NULL;
9601 json_object *json_cluster_list_list = NULL;
9602 json_object *json_ext_community = NULL;
9603 json_object *json_last_update = NULL;
7fd077aa 9604 json_object *json_pmsi = NULL;
d62a17ae 9605 json_object *json_nexthop_global = NULL;
9606 json_object *json_nexthop_ll = NULL;
9607 json_object *json_nexthops = NULL;
9608 json_object *json_path = NULL;
9609 json_object *json_peer = NULL;
9610 json_object *json_string = NULL;
9611 json_object *json_adv_to = NULL;
9612 int first = 0;
9613 struct listnode *node, *nnode;
9614 struct peer *peer;
9615 int addpath_capable;
9616 int has_adj;
9617 unsigned int first_as;
1defdda8 9618 bool nexthop_self =
9b6d8fcf 9619 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9620 int i;
2ba93fd6
DA
9621 char *nexthop_hostname =
9622 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9623
9624 if (json_paths) {
9625 json_path = json_object_new_object();
9626 json_peer = json_object_new_object();
9627 json_nexthop_global = json_object_new_object();
9628 }
9629
44c69747 9630 if (path->extra) {
b57ba6d2 9631 char tag_buf[30];
d62a17ae 9632
d62a17ae 9633 tag_buf[0] = '\0';
9b6d8fcf
DS
9634 if (path->extra && path->extra->num_labels) {
9635 bgp_evpn_label2str(path->extra->label,
9636 path->extra->num_labels, tag_buf,
a4d82a8a 9637 sizeof(tag_buf));
d62a17ae 9638 }
d7325ee7 9639 if (safi == SAFI_EVPN) {
44c69747 9640 if (!json_paths) {
2dbe669b
DA
9641 vty_out(vty, " Route %pFX",
9642 (struct prefix_evpn *)
9643 bgp_dest_get_prefix(bn));
44c69747
LK
9644 if (tag_buf[0] != '\0')
9645 vty_out(vty, " VNI %s", tag_buf);
9646 vty_out(vty, "\n");
9647 } else {
9648 if (tag_buf[0])
9649 json_object_string_add(json_path, "VNI",
9650 tag_buf);
9651 }
d7325ee7
DD
9652 }
9653
44c69747 9654 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9655 struct bgp_path_info *parent_ri;
9bcb3eef 9656 struct bgp_dest *dest, *pdest;
d62a17ae 9657
9b6d8fcf 9658 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9659 dest = parent_ri->net;
9660 if (dest && dest->pdest) {
9661 pdest = dest->pdest;
9662 prefix_rd2str(
9663 (struct prefix_rd *)bgp_dest_get_prefix(
9664 pdest),
9665 buf1, sizeof(buf1));
d7325ee7 9666 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9667 vty_out(vty,
58bff4d1 9668 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9669 buf1,
9670 (struct prefix_evpn *)
9671 bgp_dest_get_prefix(
9672 dest),
9673 tag_buf);
58bff4d1
AK
9674 if (attr->es_flags & ATTR_ES_L3_NHG)
9675 vty_out(vty, ", L3NHG %s",
9676 (attr->es_flags
9677 & ATTR_ES_L3_NHG_ACTIVE)
9678 ? "active"
9679 : "inactive");
9680 vty_out(vty, "\n");
9681
d7325ee7 9682 } else
2dbe669b
DA
9683 vty_out(vty,
9684 " Imported from %s:%pFX\n",
9685 buf1,
9686 (struct prefix_evpn *)
9687 bgp_dest_get_prefix(
9688 dest));
d62a17ae 9689 }
9690 }
9691 }
d62a17ae 9692
05864da7
DS
9693 /* Line1 display AS-path, Aggregator */
9694 if (attr->aspath) {
9695 if (json_paths) {
9696 if (!attr->aspath->json)
9697 aspath_str_update(attr->aspath, true);
9698 json_object_lock(attr->aspath->json);
9699 json_object_object_add(json_path, "aspath",
9700 attr->aspath->json);
9701 } else {
9702 if (attr->aspath->segments)
9703 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9704 else
05864da7 9705 vty_out(vty, " Local");
d62a17ae 9706 }
05864da7 9707 }
d62a17ae 9708
05864da7
DS
9709 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9710 if (json_paths)
9711 json_object_boolean_true_add(json_path, "removed");
9712 else
9713 vty_out(vty, ", (removed)");
9714 }
d62a17ae 9715
05864da7
DS
9716 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9717 if (json_paths)
9718 json_object_boolean_true_add(json_path, "stale");
9719 else
9720 vty_out(vty, ", (stale)");
9721 }
d62a17ae 9722
05864da7
DS
9723 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9724 if (json_paths) {
23d0a753
DA
9725 char buf[BUFSIZ] = {0};
9726
05864da7
DS
9727 json_object_int_add(json_path, "aggregatorAs",
9728 attr->aggregator_as);
23d0a753
DA
9729 json_object_string_add(json_path, "aggregatorId",
9730 inet_ntop(AF_INET,
9731 &attr->aggregator_addr,
9732 buf, sizeof(buf)));
05864da7 9733 } else {
88d495a9
DA
9734 vty_out(vty, ", (aggregated by %u %pI4)",
9735 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9736 }
05864da7 9737 }
d62a17ae 9738
05864da7
DS
9739 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9740 PEER_FLAG_REFLECTOR_CLIENT)) {
9741 if (json_paths)
9742 json_object_boolean_true_add(json_path,
9743 "rxedFromRrClient");
9744 else
9745 vty_out(vty, ", (Received from a RR-client)");
9746 }
d62a17ae 9747
05864da7
DS
9748 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9749 PEER_FLAG_RSERVER_CLIENT)) {
9750 if (json_paths)
9751 json_object_boolean_true_add(json_path,
9752 "rxedFromRsClient");
9753 else
9754 vty_out(vty, ", (Received from a RS-client)");
9755 }
d62a17ae 9756
05864da7
DS
9757 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9758 if (json_paths)
9759 json_object_boolean_true_add(json_path,
9760 "dampeningHistoryEntry");
9761 else
9762 vty_out(vty, ", (history entry)");
9763 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9764 if (json_paths)
9765 json_object_boolean_true_add(json_path,
9766 "dampeningSuppressed");
9767 else
9768 vty_out(vty, ", (suppressed due to dampening)");
9769 }
d62a17ae 9770
05864da7
DS
9771 if (!json_paths)
9772 vty_out(vty, "\n");
d62a17ae 9773
05864da7
DS
9774 /* Line2 display Next-hop, Neighbor, Router-id */
9775 /* Display the nexthop */
9bcb3eef 9776 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9777
9778 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9779 || bn_p->family == AF_EVPN)
05864da7
DS
9780 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9781 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9782 char buf[BUFSIZ] = {0};
9783
05864da7
DS
9784 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9785 || safi == SAFI_EVPN) {
515c2602 9786 if (json_paths) {
d62a17ae 9787 json_object_string_add(
515c2602 9788 json_nexthop_global, "ip",
23d0a753
DA
9789 inet_ntop(AF_INET,
9790 &attr->mp_nexthop_global_in,
9791 buf, sizeof(buf)));
515c2602 9792
939a97f4 9793 if (path->peer->hostname)
515c2602
DA
9794 json_object_string_add(
9795 json_nexthop_global, "hostname",
939a97f4 9796 path->peer->hostname);
aef999a2
DA
9797 } else {
9798 if (nexthop_hostname)
9799 vty_out(vty, " %pI4(%s)",
9800 &attr->mp_nexthop_global_in,
9801 nexthop_hostname);
9802 else
9803 vty_out(vty, " %pI4",
9804 &attr->mp_nexthop_global_in);
9805 }
d62a17ae 9806 } else {
515c2602 9807 if (json_paths) {
05864da7 9808 json_object_string_add(
515c2602 9809 json_nexthop_global, "ip",
23d0a753
DA
9810 inet_ntop(AF_INET, &attr->nexthop, buf,
9811 sizeof(buf)));
515c2602 9812
939a97f4 9813 if (path->peer->hostname)
515c2602
DA
9814 json_object_string_add(
9815 json_nexthop_global, "hostname",
939a97f4 9816 path->peer->hostname);
aef999a2
DA
9817 } else {
9818 if (nexthop_hostname)
9819 vty_out(vty, " %pI4(%s)",
9820 &attr->nexthop,
9821 nexthop_hostname);
9822 else
9823 vty_out(vty, " %pI4",
9824 &attr->nexthop);
9825 }
d62a17ae 9826 }
9827
05864da7
DS
9828 if (json_paths)
9829 json_object_string_add(json_nexthop_global, "afi",
9830 "ipv4");
9831 } else {
9832 if (json_paths) {
9833 json_object_string_add(
515c2602
DA
9834 json_nexthop_global, "ip",
9835 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9836 buf, INET6_ADDRSTRLEN));
9837
939a97f4 9838 if (path->peer->hostname)
515c2602
DA
9839 json_object_string_add(json_nexthop_global,
9840 "hostname",
939a97f4 9841 path->peer->hostname);
515c2602 9842
05864da7
DS
9843 json_object_string_add(json_nexthop_global, "afi",
9844 "ipv6");
9845 json_object_string_add(json_nexthop_global, "scope",
9846 "global");
9847 } else {
aef999a2
DA
9848 if (nexthop_hostname)
9849 vty_out(vty, " %pI6(%s)",
9850 &attr->mp_nexthop_global,
9851 nexthop_hostname);
9852 else
9853 vty_out(vty, " %pI6",
9854 &attr->mp_nexthop_global);
d62a17ae 9855 }
05864da7 9856 }
d62a17ae 9857
05864da7
DS
9858 /* Display the IGP cost or 'inaccessible' */
9859 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9860 if (json_paths)
9861 json_object_boolean_false_add(json_nexthop_global,
9862 "accessible");
9863 else
9864 vty_out(vty, " (inaccessible)");
9865 } else {
9866 if (path->extra && path->extra->igpmetric) {
d62a17ae 9867 if (json_paths)
05864da7
DS
9868 json_object_int_add(json_nexthop_global,
9869 "metric",
9870 path->extra->igpmetric);
d62a17ae 9871 else
05864da7
DS
9872 vty_out(vty, " (metric %u)",
9873 path->extra->igpmetric);
d62a17ae 9874 }
9875
05864da7 9876 /* IGP cost is 0, display this only for json */
d62a17ae 9877 else {
d62a17ae 9878 if (json_paths)
05864da7
DS
9879 json_object_int_add(json_nexthop_global,
9880 "metric", 0);
d62a17ae 9881 }
d62a17ae 9882
05864da7
DS
9883 if (json_paths)
9884 json_object_boolean_true_add(json_nexthop_global,
9885 "accessible");
9886 }
d62a17ae 9887
05864da7
DS
9888 /* Display peer "from" output */
9889 /* This path was originated locally */
9890 if (path->peer == bgp->peer_self) {
d62a17ae 9891
05864da7 9892 if (safi == SAFI_EVPN
b54892e0 9893 || (bn_p->family == AF_INET
05864da7 9894 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9895 if (json_paths)
05864da7
DS
9896 json_object_string_add(json_peer, "peerId",
9897 "0.0.0.0");
d62a17ae 9898 else
05864da7
DS
9899 vty_out(vty, " from 0.0.0.0 ");
9900 } else {
d62a17ae 9901 if (json_paths)
05864da7
DS
9902 json_object_string_add(json_peer, "peerId",
9903 "::");
d62a17ae 9904 else
05864da7 9905 vty_out(vty, " from :: ");
d62a17ae 9906 }
d62a17ae 9907
23d0a753
DA
9908 if (json_paths) {
9909 char buf[BUFSIZ] = {0};
9910
05864da7 9911 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9912 inet_ntop(AF_INET,
9913 &bgp->router_id, buf,
9914 sizeof(buf)));
9915 } else {
9916 vty_out(vty, "(%pI4)", &bgp->router_id);
9917 }
05864da7 9918 }
d62a17ae 9919
05864da7
DS
9920 /* We RXed this path from one of our peers */
9921 else {
9922
9923 if (json_paths) {
9924 json_object_string_add(json_peer, "peerId",
9925 sockunion2str(&path->peer->su,
9926 buf,
9927 SU_ADDRSTRLEN));
9928 json_object_string_add(json_peer, "routerId",
9929 inet_ntop(AF_INET,
9930 &path->peer->remote_id,
9931 buf1, sizeof(buf1)));
9932
9933 if (path->peer->hostname)
9934 json_object_string_add(json_peer, "hostname",
9935 path->peer->hostname);
9936
9937 if (path->peer->domainname)
9938 json_object_string_add(json_peer, "domainname",
9939 path->peer->domainname);
9940
9941 if (path->peer->conf_if)
9942 json_object_string_add(json_peer, "interface",
9943 path->peer->conf_if);
9944 } else {
9945 if (path->peer->conf_if) {
9946 if (path->peer->hostname
892fedb6
DA
9947 && CHECK_FLAG(path->peer->bgp->flags,
9948 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9949 vty_out(vty, " from %s(%s)",
9950 path->peer->hostname,
9951 path->peer->conf_if);
d62a17ae 9952 else
05864da7 9953 vty_out(vty, " from %s",
9b6d8fcf 9954 path->peer->conf_if);
d62a17ae 9955 } else {
05864da7 9956 if (path->peer->hostname
892fedb6
DA
9957 && CHECK_FLAG(path->peer->bgp->flags,
9958 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9959 vty_out(vty, " from %s(%s)",
9960 path->peer->hostname,
9961 path->peer->host);
d62a17ae 9962 else
05864da7
DS
9963 vty_out(vty, " from %s",
9964 sockunion2str(&path->peer->su,
9965 buf,
9966 SU_ADDRSTRLEN));
d62a17ae 9967 }
d62a17ae 9968
05864da7 9969 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9970 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9971 else
9972 vty_out(vty, " (%s)",
9973 inet_ntop(AF_INET,
9974 &path->peer->remote_id, buf1,
9975 sizeof(buf1)));
d62a17ae 9976 }
05864da7 9977 }
9df8b37c 9978
05864da7
DS
9979 /*
9980 * Note when vrfid of nexthop is different from that of prefix
9981 */
9982 if (path->extra && path->extra->bgp_orig) {
9983 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9984
05864da7
DS
9985 if (json_paths) {
9986 const char *vn;
9df8b37c 9987
05864da7
DS
9988 if (path->extra->bgp_orig->inst_type
9989 == BGP_INSTANCE_TYPE_DEFAULT)
9990 vn = VRF_DEFAULT_NAME;
9991 else
9992 vn = path->extra->bgp_orig->name;
9df8b37c 9993
05864da7 9994 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9995
05864da7
DS
9996 if (nexthop_vrfid == VRF_UNKNOWN) {
9997 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9998 } else {
05864da7
DS
9999 json_object_int_add(json_path, "nhVrfId",
10000 (int)nexthop_vrfid);
9df8b37c 10001 }
05864da7
DS
10002 } else {
10003 if (nexthop_vrfid == VRF_UNKNOWN)
10004 vty_out(vty, " vrf ?");
137147c6
DS
10005 else {
10006 struct vrf *vrf;
10007
10008 vrf = vrf_lookup_by_id(nexthop_vrfid);
10009 vty_out(vty, " vrf %s(%u)",
10010 VRF_LOGNAME(vrf), nexthop_vrfid);
10011 }
9df8b37c 10012 }
05864da7 10013 }
9df8b37c 10014
05864da7
DS
10015 if (nexthop_self) {
10016 if (json_paths) {
10017 json_object_boolean_true_add(json_path,
10018 "announceNexthopSelf");
10019 } else {
10020 vty_out(vty, " announce-nh-self");
9df8b37c 10021 }
05864da7 10022 }
9df8b37c 10023
05864da7
DS
10024 if (!json_paths)
10025 vty_out(vty, "\n");
d62a17ae 10026
05864da7
DS
10027 /* display the link-local nexthop */
10028 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10029 if (json_paths) {
10030 json_nexthop_ll = json_object_new_object();
10031 json_object_string_add(
515c2602
DA
10032 json_nexthop_ll, "ip",
10033 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10034 buf, INET6_ADDRSTRLEN));
10035
939a97f4 10036 if (path->peer->hostname)
515c2602
DA
10037 json_object_string_add(json_nexthop_ll,
10038 "hostname",
939a97f4 10039 path->peer->hostname);
515c2602 10040
05864da7
DS
10041 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10042 json_object_string_add(json_nexthop_ll, "scope",
10043 "link-local");
d62a17ae 10044
05864da7
DS
10045 json_object_boolean_true_add(json_nexthop_ll,
10046 "accessible");
d62a17ae 10047
05864da7 10048 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10049 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10050 "used");
10051 else
10052 json_object_boolean_true_add(
10053 json_nexthop_global, "used");
10054 } else {
10055 vty_out(vty, " (%s) %s\n",
10056 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10057 buf, INET6_ADDRSTRLEN),
10058 attr->mp_nexthop_prefer_global
10059 ? "(prefer-global)"
10060 : "(used)");
d62a17ae 10061 }
05864da7
DS
10062 }
10063 /* If we do not have a link-local nexthop then we must flag the
10064 global as "used" */
10065 else {
10066 if (json_paths)
10067 json_object_boolean_true_add(json_nexthop_global,
10068 "used");
10069 }
d62a17ae 10070
b5e140c8 10071 if (safi == SAFI_EVPN &&
5e4d4c8a 10072 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10073 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10074 }
10075
05864da7
DS
10076 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10077 * Int/Ext/Local, Atomic, best */
10078 if (json_paths)
10079 json_object_string_add(json_path, "origin",
10080 bgp_origin_long_str[attr->origin]);
10081 else
10082 vty_out(vty, " Origin %s",
10083 bgp_origin_long_str[attr->origin]);
9df8b37c 10084
05864da7 10085 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10086 if (json_paths)
05864da7 10087 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10088 else
05864da7
DS
10089 vty_out(vty, ", metric %u", attr->med);
10090 }
9df8b37c 10091
05864da7
DS
10092 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10093 if (json_paths)
0fbac0b4 10094 json_object_int_add(json_path, "locPrf",
05864da7
DS
10095 attr->local_pref);
10096 else
10097 vty_out(vty, ", localpref %u", attr->local_pref);
10098 }
9df8b37c 10099
05864da7
DS
10100 if (attr->weight != 0) {
10101 if (json_paths)
10102 json_object_int_add(json_path, "weight", attr->weight);
10103 else
10104 vty_out(vty, ", weight %u", attr->weight);
10105 }
9df8b37c 10106
05864da7
DS
10107 if (attr->tag != 0) {
10108 if (json_paths)
10109 json_object_int_add(json_path, "tag", attr->tag);
10110 else
10111 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10112 }
9df8b37c 10113
05864da7
DS
10114 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10115 if (json_paths)
10116 json_object_boolean_false_add(json_path, "valid");
10117 else
10118 vty_out(vty, ", invalid");
10119 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10120 if (json_paths)
10121 json_object_boolean_true_add(json_path, "valid");
10122 else
10123 vty_out(vty, ", valid");
10124 }
9df8b37c 10125
7d3cae70
DA
10126 if (json_paths)
10127 json_object_int_add(json_path, "version", bn->version);
10128
05864da7
DS
10129 if (path->peer != bgp->peer_self) {
10130 if (path->peer->as == path->peer->local_as) {
10131 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10132 if (json_paths)
10133 json_object_string_add(
10134 json_peer, "type",
10135 "confed-internal");
d62a17ae 10136 else
05864da7 10137 vty_out(vty, ", confed-internal");
d62a17ae 10138 } else {
05864da7
DS
10139 if (json_paths)
10140 json_object_string_add(
10141 json_peer, "type", "internal");
10142 else
10143 vty_out(vty, ", internal");
9df8b37c 10144 }
05864da7
DS
10145 } else {
10146 if (bgp_confederation_peers_check(bgp,
10147 path->peer->as)) {
10148 if (json_paths)
10149 json_object_string_add(
10150 json_peer, "type",
10151 "confed-external");
d62a17ae 10152 else
05864da7 10153 vty_out(vty, ", confed-external");
d62a17ae 10154 } else {
05864da7
DS
10155 if (json_paths)
10156 json_object_string_add(
10157 json_peer, "type", "external");
10158 else
10159 vty_out(vty, ", external");
d62a17ae 10160 }
10161 }
05864da7
DS
10162 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10163 if (json_paths) {
10164 json_object_boolean_true_add(json_path, "aggregated");
10165 json_object_boolean_true_add(json_path, "local");
10166 } else {
10167 vty_out(vty, ", aggregated, local");
10168 }
10169 } else if (path->type != ZEBRA_ROUTE_BGP) {
10170 if (json_paths)
10171 json_object_boolean_true_add(json_path, "sourced");
10172 else
10173 vty_out(vty, ", sourced");
10174 } else {
10175 if (json_paths) {
10176 json_object_boolean_true_add(json_path, "sourced");
10177 json_object_boolean_true_add(json_path, "local");
10178 } else {
10179 vty_out(vty, ", sourced, local");
d62a17ae 10180 }
05864da7 10181 }
718e3744 10182
05864da7 10183 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10184 if (json_paths)
05864da7
DS
10185 json_object_boolean_true_add(json_path,
10186 "atomicAggregate");
d62a17ae 10187 else
05864da7
DS
10188 vty_out(vty, ", atomic-aggregate");
10189 }
d62a17ae 10190
05864da7
DS
10191 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10192 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10193 && bgp_path_info_mpath_count(path))) {
10194 if (json_paths)
10195 json_object_boolean_true_add(json_path, "multipath");
10196 else
10197 vty_out(vty, ", multipath");
10198 }
50e05855 10199
05864da7
DS
10200 // Mark the bestpath(s)
10201 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10202 first_as = aspath_get_first_as(attr->aspath);
718e3744 10203
05864da7
DS
10204 if (json_paths) {
10205 if (!json_bestpath)
10206 json_bestpath = json_object_new_object();
10207 json_object_int_add(json_bestpath, "bestpathFromAs",
10208 first_as);
10209 } else {
10210 if (first_as)
10211 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10212 else
05864da7 10213 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10214 }
05864da7 10215 }
718e3744 10216
05864da7
DS
10217 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10218 if (json_paths) {
10219 if (!json_bestpath)
10220 json_bestpath = json_object_new_object();
10221 json_object_boolean_true_add(json_bestpath, "overall");
10222 json_object_string_add(
10223 json_bestpath, "selectionReason",
10224 bgp_path_selection_reason2str(bn->reason));
10225 } else {
10226 vty_out(vty, ", best");
10227 vty_out(vty, " (%s)",
10228 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10229 }
05864da7 10230 }
718e3744 10231
4027d19b 10232 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10233 if (json_paths)
10234 json_object_string_add(
10235 json_path, "rpkiValidationState",
4027d19b 10236 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10237 else
1d327209 10238 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10239 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10240 }
10241
05864da7
DS
10242 if (json_bestpath)
10243 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10244
05864da7
DS
10245 if (!json_paths)
10246 vty_out(vty, "\n");
10247
10248 /* Line 4 display Community */
10249 if (attr->community) {
10250 if (json_paths) {
10251 if (!attr->community->json)
10252 community_str(attr->community, true);
10253 json_object_lock(attr->community->json);
10254 json_object_object_add(json_path, "community",
10255 attr->community->json);
10256 } else {
10257 vty_out(vty, " Community: %s\n",
10258 attr->community->str);
d62a17ae 10259 }
05864da7 10260 }
718e3744 10261
05864da7
DS
10262 /* Line 5 display Extended-community */
10263 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10264 if (json_paths) {
10265 json_ext_community = json_object_new_object();
10266 json_object_string_add(json_ext_community, "string",
10267 attr->ecommunity->str);
10268 json_object_object_add(json_path, "extendedCommunity",
10269 json_ext_community);
d62a17ae 10270 } else {
05864da7
DS
10271 vty_out(vty, " Extended Community: %s\n",
10272 attr->ecommunity->str);
d62a17ae 10273 }
05864da7 10274 }
718e3744 10275
05864da7
DS
10276 /* Line 6 display Large community */
10277 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10278 if (json_paths) {
10279 if (!attr->lcommunity->json)
10280 lcommunity_str(attr->lcommunity, true);
10281 json_object_lock(attr->lcommunity->json);
10282 json_object_object_add(json_path, "largeCommunity",
10283 attr->lcommunity->json);
10284 } else {
10285 vty_out(vty, " Large Community: %s\n",
10286 attr->lcommunity->str);
d62a17ae 10287 }
05864da7 10288 }
718e3744 10289
05864da7
DS
10290 /* Line 7 display Originator, Cluster-id */
10291 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10292 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10293 char buf[BUFSIZ] = {0};
10294
05864da7 10295 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10296 if (json_paths)
05864da7
DS
10297 json_object_string_add(
10298 json_path, "originatorId",
23d0a753
DA
10299 inet_ntop(AF_INET, &attr->originator_id,
10300 buf, sizeof(buf)));
d62a17ae 10301 else
23d0a753
DA
10302 vty_out(vty, " Originator: %pI4",
10303 &attr->originator_id);
d62a17ae 10304 }
856ca177 10305
05864da7 10306 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10307 struct cluster_list *cluster =
10308 bgp_attr_get_cluster(attr);
05864da7 10309 int i;
d62a17ae 10310
10311 if (json_paths) {
05864da7
DS
10312 json_cluster_list = json_object_new_object();
10313 json_cluster_list_list =
10314 json_object_new_array();
10315
779fee93 10316 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10317 json_string = json_object_new_string(
779fee93
DS
10318 inet_ntop(AF_INET,
10319 &cluster->list[i],
10320 buf, sizeof(buf)));
05864da7
DS
10321 json_object_array_add(
10322 json_cluster_list_list,
10323 json_string);
10324 }
718e3744 10325
05864da7
DS
10326 /*
10327 * struct cluster_list does not have
10328 * "str" variable like aspath and community
10329 * do. Add this someday if someone asks
10330 * for it.
10331 * json_object_string_add(json_cluster_list,
779fee93 10332 * "string", cluster->str);
05864da7
DS
10333 */
10334 json_object_object_add(json_cluster_list,
10335 "list",
10336 json_cluster_list_list);
10337 json_object_object_add(json_path, "clusterList",
10338 json_cluster_list);
0dc8ee70 10339 } else {
05864da7
DS
10340 vty_out(vty, ", Cluster list: ");
10341
779fee93 10342 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10343 vty_out(vty, "%pI4 ",
779fee93 10344 &cluster->list[i]);
05864da7 10345 }
0dc8ee70 10346 }
d62a17ae 10347 }
718e3744 10348
d62a17ae 10349 if (!json_paths)
10350 vty_out(vty, "\n");
05864da7 10351 }
d62a17ae 10352
05864da7 10353 if (path->extra && path->extra->damp_info)
40ec3340 10354 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10355
05864da7
DS
10356 /* Remote Label */
10357 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10358 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10359 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10360
05864da7
DS
10361 if (json_paths)
10362 json_object_int_add(json_path, "remoteLabel", label);
10363 else
10364 vty_out(vty, " Remote label: %d\n", label);
10365 }
d62a17ae 10366
e496b420
HS
10367 /* Remote SID */
10368 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10369 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10370 if (json_paths)
10371 json_object_string_add(json_path, "remoteSid", buf);
10372 else
10373 vty_out(vty, " Remote SID: %s\n", buf);
10374 }
10375
05864da7
DS
10376 /* Label Index */
10377 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10378 if (json_paths)
10379 json_object_int_add(json_path, "labelIndex",
10380 attr->label_index);
10381 else
10382 vty_out(vty, " Label Index: %d\n",
10383 attr->label_index);
10384 }
d62a17ae 10385
05864da7
DS
10386 /* Line 8 display Addpath IDs */
10387 if (path->addpath_rx_id
10388 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10389 if (json_paths) {
10390 json_object_int_add(json_path, "addpathRxId",
10391 path->addpath_rx_id);
d62a17ae 10392
05864da7
DS
10393 /* Keep backwards compatibility with the old API
10394 * by putting TX All's ID in the old field
10395 */
10396 json_object_int_add(
10397 json_path, "addpathTxId",
10398 path->tx_addpath
10399 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10400
05864da7
DS
10401 /* ... but create a specific field for each
10402 * strategy
10403 */
10404 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10405 json_object_int_add(
10406 json_path,
10407 bgp_addpath_names(i)->id_json_name,
10408 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10409 }
05864da7
DS
10410 } else {
10411 vty_out(vty, " AddPath ID: RX %u, ",
10412 path->addpath_rx_id);
d62a17ae 10413
05864da7 10414 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10415 }
05864da7 10416 }
520d5d76 10417
05864da7
DS
10418 /* If we used addpath to TX a non-bestpath we need to display
10419 * "Advertised to" on a path-by-path basis
10420 */
10421 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10422 first = 1;
dcc68b5e 10423
05864da7
DS
10424 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10425 addpath_capable =
10426 bgp_addpath_encode_tx(peer, afi, safi);
10427 has_adj = bgp_adj_out_lookup(
10428 peer, path->net,
10429 bgp_addpath_id_for_peer(peer, afi, safi,
10430 &path->tx_addpath));
10431
10432 if ((addpath_capable && has_adj)
10433 || (!addpath_capable && has_adj
10434 && CHECK_FLAG(path->flags,
10435 BGP_PATH_SELECTED))) {
10436 if (json_path && !json_adv_to)
10437 json_adv_to = json_object_new_object();
dcc68b5e 10438
05864da7
DS
10439 route_vty_out_advertised_to(
10440 vty, peer, &first,
10441 " Advertised to:", json_adv_to);
d62a17ae 10442 }
10443 }
718e3744 10444
05864da7
DS
10445 if (json_path) {
10446 if (json_adv_to) {
10447 json_object_object_add(
10448 json_path, "advertisedTo", json_adv_to);
d62a17ae 10449 }
05864da7
DS
10450 } else {
10451 if (!first) {
10452 vty_out(vty, "\n");
d62a17ae 10453 }
10454 }
05864da7 10455 }
b05a1c8b 10456
05864da7
DS
10457 /* Line 9 display Uptime */
10458 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10459 if (json_paths) {
10460 json_last_update = json_object_new_object();
10461 json_object_int_add(json_last_update, "epoch", tbuf);
10462 json_object_string_add(json_last_update, "string",
10463 ctime(&tbuf));
10464 json_object_object_add(json_path, "lastUpdate",
10465 json_last_update);
10466 } else
10467 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10468
05864da7
DS
10469 /* Line 10 display PMSI tunnel attribute, if present */
10470 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10471 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10472 bgp_attr_get_pmsi_tnl_type(attr),
10473 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10474
05864da7
DS
10475 if (json_paths) {
10476 json_pmsi = json_object_new_object();
10477 json_object_string_add(json_pmsi, "tunnelType", str);
10478 json_object_int_add(json_pmsi, "label",
10479 label2vni(&attr->label));
10480 json_object_object_add(json_path, "pmsi", json_pmsi);
10481 } else
10482 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10483 str, label2vni(&attr->label));
d62a17ae 10484 }
f1aa5d8a 10485
92269aa2
DS
10486 /* Output some debug about internal state of the dest flags */
10487 if (json_paths) {
10488 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10489 json_object_boolean_true_add(json_path, "processScheduled");
10490 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10491 json_object_boolean_true_add(json_path, "userCleared");
10492 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10493 json_object_boolean_true_add(json_path, "labelChanged");
10494 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10495 json_object_boolean_true_add(json_path, "registeredForLabel");
10496 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10497 json_object_boolean_true_add(json_path, "selectDefered");
10498 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10499 json_object_boolean_true_add(json_path, "fibInstalled");
10500 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10501 json_object_boolean_true_add(json_path, "fibPending");
10502 }
10503
d62a17ae 10504 /* We've constructed the json object for this path, add it to the json
10505 * array of paths
10506 */
10507 if (json_paths) {
10508 if (json_nexthop_global || json_nexthop_ll) {
10509 json_nexthops = json_object_new_array();
f1aa5d8a 10510
d62a17ae 10511 if (json_nexthop_global)
10512 json_object_array_add(json_nexthops,
10513 json_nexthop_global);
f1aa5d8a 10514
d62a17ae 10515 if (json_nexthop_ll)
10516 json_object_array_add(json_nexthops,
10517 json_nexthop_ll);
f1aa5d8a 10518
d62a17ae 10519 json_object_object_add(json_path, "nexthops",
10520 json_nexthops);
10521 }
10522
10523 json_object_object_add(json_path, "peer", json_peer);
10524 json_object_array_add(json_paths, json_path);
05864da7 10525 }
b366b518
BB
10526}
10527
96ade3ed 10528#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10529#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10530#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10531
d62a17ae 10532static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10533 const char *prefix_list_str, afi_t afi,
10534 safi_t safi, enum bgp_show_type type);
10535static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10536 const char *filter, afi_t afi, safi_t safi,
10537 enum bgp_show_type type);
10538static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10539 const char *rmap_str, afi_t afi, safi_t safi,
10540 enum bgp_show_type type);
10541static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10542 const char *com, int exact, afi_t afi,
10543 safi_t safi);
10544static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10545 const char *prefix, afi_t afi, safi_t safi,
10546 enum bgp_show_type type);
a4d82a8a 10547static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10548 afi_t afi, safi_t safi, enum bgp_show_type type,
10549 bool use_json);
7f323236
DW
10550static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10551 const char *comstr, int exact, afi_t afi,
96f3485c 10552 safi_t safi, uint8_t show_flags);
d62a17ae 10553
1ae44dfc
LB
10554
10555static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10556 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10557 void *output_arg, char *rd, int is_last,
10558 unsigned long *output_cum, unsigned long *total_cum,
1e2ce4f1 10559 unsigned long *json_header_depth, uint8_t show_flags,
4027d19b 10560 enum rpki_states rpki_target_state)
d62a17ae 10561{
40381db7 10562 struct bgp_path_info *pi;
9bcb3eef 10563 struct bgp_dest *dest;
d62a17ae 10564 int header = 1;
10565 int display;
1ae44dfc
LB
10566 unsigned long output_count = 0;
10567 unsigned long total_count = 0;
d62a17ae 10568 struct prefix *p;
d62a17ae 10569 json_object *json_paths = NULL;
10570 int first = 1;
96f3485c
MK
10571 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10572 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10573 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10574
1ae44dfc
LB
10575 if (output_cum && *output_cum != 0)
10576 header = 0;
10577
9386b588 10578 if (use_json && !*json_header_depth) {
96f3485c
MK
10579 if (all)
10580 *json_header_depth = 1;
10581 else {
10582 vty_out(vty, "{\n");
10583 *json_header_depth = 2;
10584 }
10585
d62a17ae 10586 vty_out(vty,
23d0a753
DA
10587 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10588 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10589 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10590 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10591 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10592 ? VRF_DEFAULT_NAME
10593 : bgp->name,
10594 table->version, &bgp->router_id,
01eced22 10595 bgp->default_local_pref, bgp->as);
9386b588 10596 if (rd) {
445c2480 10597 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10598 ++*json_header_depth;
10599 }
d62a17ae 10600 }
718e3744 10601
445c2480
DS
10602 if (use_json && rd) {
10603 vty_out(vty, " \"%s\" : { ", rd);
10604 }
10605
d62a17ae 10606 /* Start processing of routes. */
9bcb3eef
DS
10607 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10608 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10609 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10610
9bcb3eef 10611 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10612 if (pi == NULL)
98ce9a06 10613 continue;
d62a17ae 10614
98ce9a06 10615 display = 0;
98ce9a06
DS
10616 if (use_json)
10617 json_paths = json_object_new_array();
10618 else
10619 json_paths = NULL;
d62a17ae 10620
6f94b685 10621 for (; pi; pi = pi->next) {
98ce9a06 10622 total_count++;
1e2ce4f1 10623
7d3cae70
DA
10624 if (type == bgp_show_type_prefix_version) {
10625 uint32_t version =
10626 strtoul(output_arg, NULL, 10);
10627 if (dest->version < version)
10628 continue;
10629 }
10630
1e2ce4f1
DS
10631 if (type == bgp_show_type_rpki) {
10632 if (dest_p->family == AF_INET
10633 || dest_p->family == AF_INET6)
4027d19b 10634 rpki_curr_state = hook_call(
1e2ce4f1
DS
10635 bgp_rpki_prefix_status,
10636 pi->peer, pi->attr, dest_p);
4027d19b
DS
10637 if (rpki_target_state != RPKI_NOT_BEING_USED
10638 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10639 continue;
10640 }
10641
98ce9a06
DS
10642 if (type == bgp_show_type_flap_statistics
10643 || type == bgp_show_type_flap_neighbor
10644 || type == bgp_show_type_dampend_paths
10645 || type == bgp_show_type_damp_neighbor) {
40381db7 10646 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10647 continue;
10648 }
10649 if (type == bgp_show_type_regexp) {
10650 regex_t *regex = output_arg;
d62a17ae 10651
40381db7 10652 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10653 == REG_NOMATCH)
10654 continue;
10655 }
10656 if (type == bgp_show_type_prefix_list) {
10657 struct prefix_list *plist = output_arg;
d62a17ae 10658
9bcb3eef 10659 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10660 != PREFIX_PERMIT)
10661 continue;
10662 }
10663 if (type == bgp_show_type_filter_list) {
10664 struct as_list *as_list = output_arg;
d62a17ae 10665
40381db7 10666 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10667 != AS_FILTER_PERMIT)
10668 continue;
10669 }
10670 if (type == bgp_show_type_route_map) {
10671 struct route_map *rmap = output_arg;
9b6d8fcf 10672 struct bgp_path_info path;
98ce9a06 10673 struct attr dummy_attr;
b68885f9 10674 route_map_result_t ret;
d62a17ae 10675
6f4f49b2 10676 dummy_attr = *pi->attr;
d62a17ae 10677
40381db7 10678 path.peer = pi->peer;
9b6d8fcf 10679 path.attr = &dummy_attr;
d62a17ae 10680
1782514f 10681 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10682 if (ret == RMAP_DENYMATCH)
10683 continue;
10684 }
10685 if (type == bgp_show_type_neighbor
10686 || type == bgp_show_type_flap_neighbor
10687 || type == bgp_show_type_damp_neighbor) {
10688 union sockunion *su = output_arg;
10689
40381db7
DS
10690 if (pi->peer == NULL
10691 || pi->peer->su_remote == NULL
10692 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10693 continue;
10694 }
10695 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10696 uint32_t destination;
d62a17ae 10697
9bcb3eef 10698 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10699 if (IN_CLASSC(destination)
9bcb3eef 10700 && dest_p->prefixlen == 24)
98ce9a06
DS
10701 continue;
10702 if (IN_CLASSB(destination)
9bcb3eef 10703 && dest_p->prefixlen == 16)
98ce9a06
DS
10704 continue;
10705 if (IN_CLASSA(destination)
9bcb3eef 10706 && dest_p->prefixlen == 8)
98ce9a06
DS
10707 continue;
10708 }
10709 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10710 p = output_arg;
9bcb3eef 10711 if (!prefix_match(p, dest_p))
98ce9a06
DS
10712 continue;
10713 }
10714 if (type == bgp_show_type_community_all) {
40381db7 10715 if (!pi->attr->community)
98ce9a06
DS
10716 continue;
10717 }
10718 if (type == bgp_show_type_community) {
10719 struct community *com = output_arg;
d62a17ae 10720
40381db7
DS
10721 if (!pi->attr->community
10722 || !community_match(pi->attr->community,
98ce9a06
DS
10723 com))
10724 continue;
10725 }
10726 if (type == bgp_show_type_community_exact) {
10727 struct community *com = output_arg;
d62a17ae 10728
40381db7
DS
10729 if (!pi->attr->community
10730 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10731 continue;
10732 }
10733 if (type == bgp_show_type_community_list) {
10734 struct community_list *list = output_arg;
d62a17ae 10735
40381db7 10736 if (!community_list_match(pi->attr->community,
a4d82a8a 10737 list))
98ce9a06
DS
10738 continue;
10739 }
a4d82a8a 10740 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10741 struct community_list *list = output_arg;
d62a17ae 10742
98ce9a06 10743 if (!community_list_exact_match(
40381db7 10744 pi->attr->community, list))
98ce9a06
DS
10745 continue;
10746 }
10747 if (type == bgp_show_type_lcommunity) {
10748 struct lcommunity *lcom = output_arg;
d62a17ae 10749
40381db7
DS
10750 if (!pi->attr->lcommunity
10751 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10752 lcom))
10753 continue;
10754 }
36a206db 10755
10756 if (type == bgp_show_type_lcommunity_exact) {
10757 struct lcommunity *lcom = output_arg;
10758
10759 if (!pi->attr->lcommunity
10760 || !lcommunity_cmp(pi->attr->lcommunity,
10761 lcom))
10762 continue;
10763 }
98ce9a06
DS
10764 if (type == bgp_show_type_lcommunity_list) {
10765 struct community_list *list = output_arg;
d62a17ae 10766
40381db7 10767 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10768 list))
98ce9a06
DS
10769 continue;
10770 }
36a206db 10771 if (type
10772 == bgp_show_type_lcommunity_list_exact) {
10773 struct community_list *list = output_arg;
10774
10775 if (!lcommunity_list_exact_match(
10776 pi->attr->lcommunity, list))
10777 continue;
10778 }
98ce9a06 10779 if (type == bgp_show_type_lcommunity_all) {
40381db7 10780 if (!pi->attr->lcommunity)
98ce9a06
DS
10781 continue;
10782 }
10783 if (type == bgp_show_type_dampend_paths
10784 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10785 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10786 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10787 continue;
10788 }
10789
10790 if (!use_json && header) {
23d0a753
DA
10791 vty_out(vty,
10792 "BGP table version is %" PRIu64
10793 ", local router ID is %pI4, vrf id ",
10794 table->version, &bgp->router_id);
9df8b37c
PZ
10795 if (bgp->vrf_id == VRF_UNKNOWN)
10796 vty_out(vty, "%s", VRFID_NONE_STR);
10797 else
10798 vty_out(vty, "%u", bgp->vrf_id);
10799 vty_out(vty, "\n");
01eced22
AD
10800 vty_out(vty, "Default local pref %u, ",
10801 bgp->default_local_pref);
10802 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10803 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10804 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10805 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10806 if (type == bgp_show_type_dampend_paths
10807 || type == bgp_show_type_damp_neighbor)
98ce9a06 10808 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10809 else if (type == bgp_show_type_flap_statistics
10810 || type == bgp_show_type_flap_neighbor)
98ce9a06 10811 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10812 else
ae248832
MK
10813 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10814 : BGP_SHOW_HEADER));
98ce9a06 10815 header = 0;
d62a17ae 10816 }
98ce9a06
DS
10817 if (rd != NULL && !display && !output_count) {
10818 if (!use_json)
10819 vty_out(vty,
10820 "Route Distinguisher: %s\n",
10821 rd);
d62a17ae 10822 }
98ce9a06
DS
10823 if (type == bgp_show_type_dampend_paths
10824 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10825 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10826 AFI_IP, safi, use_json,
10827 json_paths);
98ce9a06
DS
10828 else if (type == bgp_show_type_flap_statistics
10829 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10830 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10831 AFI_IP, safi, use_json,
10832 json_paths);
98ce9a06 10833 else
9bcb3eef 10834 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10835 json_paths, wide);
98ce9a06 10836 display++;
d62a17ae 10837 }
10838
98ce9a06
DS
10839 if (display) {
10840 output_count++;
10841 if (!use_json)
10842 continue;
10843
625d2931 10844 /* encode prefix */
9bcb3eef 10845 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10846 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10847
1840384b 10848
b54892e0
DS
10849 bgp_fs_nlri_get_string(
10850 (unsigned char *)
9bcb3eef
DS
10851 dest_p->u.prefix_flowspec.ptr,
10852 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10853 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10854 family2afi(dest_p->u
10855 .prefix_flowspec.family));
625d2931 10856 if (first)
b54892e0 10857 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10858 dest_p->u.prefix_flowspec
b54892e0 10859 .prefixlen);
625d2931 10860 else
b54892e0 10861 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10862 dest_p->u.prefix_flowspec
b54892e0 10863 .prefixlen);
625d2931 10864 } else {
625d2931 10865 if (first)
1b78780b 10866 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10867 else
1b78780b 10868 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10869 }
98ce9a06 10870 vty_out(vty, "%s",
f4ec52f7
DA
10871 json_object_to_json_string_ext(
10872 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10873 json_object_free(json_paths);
449feb8e 10874 json_paths = NULL;
98ce9a06 10875 first = 0;
1f83ed02
DS
10876 } else
10877 json_object_free(json_paths);
98ce9a06
DS
10878 }
10879
1ae44dfc
LB
10880 if (output_cum) {
10881 output_count += *output_cum;
10882 *output_cum = output_count;
10883 }
10884 if (total_cum) {
10885 total_count += *total_cum;
10886 *total_cum = total_count;
10887 }
d62a17ae 10888 if (use_json) {
9386b588 10889 if (rd) {
a4d82a8a 10890 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10891 }
10892 if (is_last) {
a4d82a8a
PZ
10893 unsigned long i;
10894 for (i = 0; i < *json_header_depth; ++i)
10895 vty_out(vty, " } ");
96f3485c
MK
10896 if (!all)
10897 vty_out(vty, "\n");
9386b588 10898 }
d62a17ae 10899 } else {
1ae44dfc
LB
10900 if (is_last) {
10901 /* No route is displayed */
10902 if (output_count == 0) {
10903 if (type == bgp_show_type_normal)
10904 vty_out(vty,
10905 "No BGP prefixes displayed, %ld exist\n",
10906 total_count);
10907 } else
d62a17ae 10908 vty_out(vty,
1ae44dfc
LB
10909 "\nDisplayed %ld routes and %ld total paths\n",
10910 output_count, total_count);
10911 }
d62a17ae 10912 }
718e3744 10913
d62a17ae 10914 return CMD_SUCCESS;
718e3744 10915}
10916
1ae44dfc
LB
10917int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10918 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10919 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10920{
9bcb3eef 10921 struct bgp_dest *dest, *next;
1ae44dfc
LB
10922 unsigned long output_cum = 0;
10923 unsigned long total_cum = 0;
9386b588 10924 unsigned long json_header_depth = 0;
67009e22 10925 struct bgp_table *itable;
0136788c 10926 bool show_msg;
96f3485c 10927 uint8_t show_flags = 0;
0136788c
LB
10928
10929 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10930
96f3485c
MK
10931 if (use_json)
10932 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10933
9bcb3eef
DS
10934 for (dest = bgp_table_top(table); dest; dest = next) {
10935 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10936
9bcb3eef
DS
10937 next = bgp_route_next(dest);
10938 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10939 continue;
67009e22 10940
9bcb3eef 10941 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10942 if (itable != NULL) {
1ae44dfc 10943 struct prefix_rd prd;
06b9f471 10944 char rd[RD_ADDRSTRLEN];
1ae44dfc 10945
9bcb3eef 10946 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10947 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10948 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10949 rd, next == NULL, &output_cum,
10950 &total_cum, &json_header_depth,
1e2ce4f1 10951 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
10952 if (next == NULL)
10953 show_msg = false;
1ae44dfc
LB
10954 }
10955 }
0136788c
LB
10956 if (show_msg) {
10957 if (output_cum == 0)
10958 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10959 total_cum);
10960 else
10961 vty_out(vty,
10962 "\nDisplayed %ld routes and %ld total paths\n",
10963 output_cum, total_cum);
10964 }
1ae44dfc
LB
10965 return CMD_SUCCESS;
10966}
d62a17ae 10967static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 10968 enum bgp_show_type type, void *output_arg,
4027d19b 10969 uint8_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 10970{
d62a17ae 10971 struct bgp_table *table;
9386b588 10972 unsigned long json_header_depth = 0;
96f3485c 10973 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10974
d62a17ae 10975 if (bgp == NULL) {
10976 bgp = bgp_get_default();
10977 }
fee0f4c6 10978
d62a17ae 10979 if (bgp == NULL) {
10980 if (!use_json)
10981 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10982 else
10983 vty_out(vty, "{}\n");
d62a17ae 10984 return CMD_WARNING;
10985 }
4dd6177e 10986
1ae44dfc 10987 table = bgp->rib[afi][safi];
d62a17ae 10988 /* use MPLS and ENCAP specific shows until they are merged */
10989 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10990 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10991 output_arg, use_json);
d62a17ae 10992 }
dba3c1d3
PG
10993
10994 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10995 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10996 output_arg, use_json,
10997 1, NULL, NULL);
10998 }
d62a17ae 10999 /* labeled-unicast routes live in the unicast table */
11000 else if (safi == SAFI_LABELED_UNICAST)
11001 safi = SAFI_UNICAST;
fee0f4c6 11002
96f3485c 11003 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11004 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11005 rpki_target_state);
fee0f4c6 11006}
11007
d62a17ae 11008static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 11009 safi_t safi, uint8_t show_flags)
f186de26 11010{
d62a17ae 11011 struct listnode *node, *nnode;
11012 struct bgp *bgp;
11013 int is_first = 1;
9f049418 11014 bool route_output = false;
96f3485c 11015 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11016
d62a17ae 11017 if (use_json)
11018 vty_out(vty, "{\n");
9f689658 11019
d62a17ae 11020 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11021 route_output = true;
d62a17ae 11022 if (use_json) {
11023 if (!is_first)
11024 vty_out(vty, ",\n");
11025 else
11026 is_first = 0;
11027
11028 vty_out(vty, "\"%s\":",
11029 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11030 ? VRF_DEFAULT_NAME
d62a17ae 11031 : bgp->name);
11032 } else {
11033 vty_out(vty, "\nInstance %s:\n",
11034 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11035 ? VRF_DEFAULT_NAME
d62a17ae 11036 : bgp->name);
11037 }
11038 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11039 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11040 }
9f689658 11041
d62a17ae 11042 if (use_json)
11043 vty_out(vty, "}\n");
9f049418
DS
11044 else if (!route_output)
11045 vty_out(vty, "%% BGP instance not found\n");
f186de26 11046}
11047
718e3744 11048/* Header of detailed BGP route information */
d62a17ae 11049void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11050 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11051 afi_t afi, safi_t safi, json_object *json)
11052{
40381db7 11053 struct bgp_path_info *pi;
b54892e0 11054 const struct prefix *p;
d62a17ae 11055 struct peer *peer;
11056 struct listnode *node, *nnode;
06b9f471 11057 char buf1[RD_ADDRSTRLEN];
0291c246 11058 char prefix_str[BUFSIZ];
d62a17ae 11059 int count = 0;
11060 int best = 0;
11061 int suppress = 0;
c5f1e1b2
C
11062 int accept_own = 0;
11063 int route_filter_translated_v4 = 0;
11064 int route_filter_v4 = 0;
11065 int route_filter_translated_v6 = 0;
11066 int route_filter_v6 = 0;
11067 int llgr_stale = 0;
11068 int no_llgr = 0;
11069 int accept_own_nexthop = 0;
11070 int blackhole = 0;
d62a17ae 11071 int no_export = 0;
11072 int no_advertise = 0;
11073 int local_as = 0;
c5f1e1b2 11074 int no_peer = 0;
d62a17ae 11075 int first = 1;
11076 int has_valid_label = 0;
11077 mpls_label_t label = 0;
11078 json_object *json_adv_to = NULL;
9bedbb1e 11079
9bcb3eef
DS
11080 p = bgp_dest_get_prefix(dest);
11081 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11082
11083 if (has_valid_label)
9bcb3eef 11084 label = label_pton(&dest->local_label);
d62a17ae 11085
44c69747 11086 if (safi == SAFI_EVPN) {
d62a17ae 11087
44c69747 11088 if (!json) {
2dbe669b 11089 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11090 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11091 : "",
2dbe669b 11092 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11093 } else {
11094 json_object_string_add(json, "rd",
11095 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11096 "");
11097 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11098 }
11099 } else {
11100 if (!json) {
9119ef3a
DA
11101 vty_out(vty,
11102 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11103 "\n",
d62a17ae 11104 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11105 ? prefix_rd2str(prd, buf1,
11106 sizeof(buf1))
11107 : ""),
9119ef3a
DA
11108 safi == SAFI_MPLS_VPN ? ":" : "", p,
11109 dest->version);
cd1964ff 11110
9119ef3a 11111 } else {
44c69747
LK
11112 json_object_string_add(json, "prefix",
11113 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11114 json_object_int_add(json, "version", dest->version);
11115
11116 }
44c69747
LK
11117 }
11118
11119 if (has_valid_label) {
11120 if (json)
11121 json_object_int_add(json, "localLabel", label);
11122 else
d62a17ae 11123 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11124 }
11125
11126 if (!json)
d62a17ae 11127 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11128 vty_out(vty, "not allocated\n");
718e3744 11129
9bcb3eef 11130 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11131 count++;
40381db7 11132 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11133 best = count;
4056a5f6 11134 if (bgp_path_suppressed(pi))
d62a17ae 11135 suppress = 1;
cee9c031 11136
40381db7 11137 if (pi->attr->community == NULL)
cee9c031
QY
11138 continue;
11139
11140 no_advertise += community_include(
40381db7
DS
11141 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11142 no_export += community_include(pi->attr->community,
cee9c031 11143 COMMUNITY_NO_EXPORT);
40381db7 11144 local_as += community_include(pi->attr->community,
cee9c031 11145 COMMUNITY_LOCAL_AS);
40381db7 11146 accept_own += community_include(pi->attr->community,
cee9c031
QY
11147 COMMUNITY_ACCEPT_OWN);
11148 route_filter_translated_v4 += community_include(
40381db7 11149 pi->attr->community,
cee9c031
QY
11150 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11151 route_filter_translated_v6 += community_include(
40381db7 11152 pi->attr->community,
cee9c031
QY
11153 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11154 route_filter_v4 += community_include(
40381db7 11155 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11156 route_filter_v6 += community_include(
40381db7
DS
11157 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11158 llgr_stale += community_include(pi->attr->community,
cee9c031 11159 COMMUNITY_LLGR_STALE);
40381db7 11160 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11161 COMMUNITY_NO_LLGR);
11162 accept_own_nexthop +=
40381db7 11163 community_include(pi->attr->community,
cee9c031 11164 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11165 blackhole += community_include(pi->attr->community,
cee9c031 11166 COMMUNITY_BLACKHOLE);
40381db7 11167 no_peer += community_include(pi->attr->community,
cee9c031 11168 COMMUNITY_NO_PEER);
d62a17ae 11169 }
718e3744 11170 }
718e3744 11171
d62a17ae 11172 if (!json) {
11173 vty_out(vty, "Paths: (%d available", count);
11174 if (best) {
11175 vty_out(vty, ", best #%d", best);
b84060bb
PG
11176 if (safi == SAFI_UNICAST) {
11177 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11178 vty_out(vty, ", table %s",
11179 VRF_DEFAULT_NAME);
11180 else
11181 vty_out(vty, ", vrf %s",
11182 bgp->name);
11183 }
d62a17ae 11184 } else
11185 vty_out(vty, ", no best path");
11186
c5f1e1b2
C
11187 if (accept_own)
11188 vty_out(vty,
11189 ", accept own local route exported and imported in different VRF");
11190 else if (route_filter_translated_v4)
11191 vty_out(vty,
11192 ", mark translated RTs for VPNv4 route filtering");
11193 else if (route_filter_v4)
11194 vty_out(vty,
11195 ", attach RT as-is for VPNv4 route filtering");
11196 else if (route_filter_translated_v6)
11197 vty_out(vty,
11198 ", mark translated RTs for VPNv6 route filtering");
11199 else if (route_filter_v6)
11200 vty_out(vty,
11201 ", attach RT as-is for VPNv6 route filtering");
11202 else if (llgr_stale)
11203 vty_out(vty,
11204 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11205 else if (no_llgr)
11206 vty_out(vty,
11207 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11208 else if (accept_own_nexthop)
11209 vty_out(vty,
11210 ", accept local nexthop");
11211 else if (blackhole)
11212 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11213 else if (no_export)
11214 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11215 else if (no_advertise)
11216 vty_out(vty, ", not advertised to any peer");
d62a17ae 11217 else if (local_as)
11218 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11219 else if (no_peer)
11220 vty_out(vty,
11221 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11222
11223 if (suppress)
11224 vty_out(vty,
11225 ", Advertisements suppressed by an aggregate.");
11226 vty_out(vty, ")\n");
11227 }
718e3744 11228
d62a17ae 11229 /* If we are not using addpath then we can display Advertised to and
11230 * that will
11231 * show what peers we advertised the bestpath to. If we are using
11232 * addpath
11233 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11234 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11235 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11236 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11237 if (json && !json_adv_to)
11238 json_adv_to = json_object_new_object();
11239
11240 route_vty_out_advertised_to(
11241 vty, peer, &first,
11242 " Advertised to non peer-group peers:\n ",
11243 json_adv_to);
11244 }
11245 }
11246
11247 if (json) {
11248 if (json_adv_to) {
11249 json_object_object_add(json, "advertisedTo",
11250 json_adv_to);
11251 }
11252 } else {
11253 if (first)
11254 vty_out(vty, " Not advertised to any peer");
11255 vty_out(vty, "\n");
11256 }
11257 }
718e3744 11258}
11259
44c69747 11260static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11261 struct bgp_dest *bgp_node, struct vty *vty,
11262 struct bgp *bgp, afi_t afi, safi_t safi,
11263 json_object *json, enum bgp_path_type pathtype,
4027d19b 11264 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11265{
11266 struct bgp_path_info *pi;
11267 int header = 1;
11268 char rdbuf[RD_ADDRSTRLEN];
11269 json_object *json_header = NULL;
11270 json_object *json_paths = NULL;
4933eaaf 11271 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11272
9bcb3eef 11273 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11274 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11275
11276 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11277 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11278 pi->peer, pi->attr, p);
4933eaaf 11279
4027d19b
DS
11280 if (rpki_target_state != RPKI_NOT_BEING_USED
11281 && rpki_curr_state != rpki_target_state)
4933eaaf 11282 continue;
44c69747
LK
11283
11284 if (json && !json_paths) {
11285 /* Instantiate json_paths only if path is valid */
11286 json_paths = json_object_new_array();
11287 if (pfx_rd) {
11288 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11289 json_header = json_object_new_object();
11290 } else
11291 json_header = json;
11292 }
11293
11294 if (header) {
11295 route_vty_out_detail_header(
11296 vty, bgp, bgp_node, pfx_rd,
11297 AFI_IP, safi, json_header);
11298 header = 0;
11299 }
11300 (*display)++;
11301
11302 if (pathtype == BGP_PATH_SHOW_ALL
11303 || (pathtype == BGP_PATH_SHOW_BESTPATH
11304 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11305 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11306 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11307 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11308 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11309 safi, rpki_curr_state, json_paths);
44c69747
LK
11310 }
11311
11312 if (json && json_paths) {
11313 json_object_object_add(json_header, "paths", json_paths);
11314
11315 if (pfx_rd)
11316 json_object_object_add(json, rdbuf, json_header);
11317 }
11318}
11319
718e3744 11320/* Display specified route of BGP table. */
d62a17ae 11321static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11322 struct bgp_table *rib, const char *ip_str,
11323 afi_t afi, safi_t safi,
4027d19b 11324 enum rpki_states rpki_target_state,
d62a17ae 11325 struct prefix_rd *prd, int prefix_check,
9f049418 11326 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11327{
11328 int ret;
d62a17ae 11329 int display = 0;
11330 struct prefix match;
9bcb3eef
DS
11331 struct bgp_dest *dest;
11332 struct bgp_dest *rm;
d62a17ae 11333 struct bgp_table *table;
11334 json_object *json = NULL;
11335 json_object *json_paths = NULL;
11336
11337 /* Check IP address argument. */
11338 ret = str2prefix(ip_str, &match);
11339 if (!ret) {
11340 vty_out(vty, "address is malformed\n");
11341 return CMD_WARNING;
11342 }
718e3744 11343
d62a17ae 11344 match.family = afi2family(afi);
b05a1c8b 11345
44c69747 11346 if (use_json)
d62a17ae 11347 json = json_object_new_object();
718e3744 11348
44c69747 11349 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11350 for (dest = bgp_table_top(rib); dest;
11351 dest = bgp_route_next(dest)) {
11352 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11353
9bcb3eef 11354 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11355 continue;
9bcb3eef 11356 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11357 if (!table)
ea47320b 11358 continue;
d62a17ae 11359
ea47320b
DL
11360 if ((rm = bgp_node_match(table, &match)) == NULL)
11361 continue;
d62a17ae 11362
9bcb3eef 11363 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11364 if (prefix_check
b54892e0 11365 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11366 bgp_dest_unlock_node(rm);
ea47320b
DL
11367 continue;
11368 }
d62a17ae 11369
9bcb3eef 11370 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11371 bgp, afi, safi, json, pathtype,
4027d19b 11372 &display, rpki_target_state);
44c69747 11373
9bcb3eef 11374 bgp_dest_unlock_node(rm);
44c69747
LK
11375 }
11376 } else if (safi == SAFI_EVPN) {
9bcb3eef 11377 struct bgp_dest *longest_pfx;
cded3b72 11378 bool is_exact_pfxlen_match = false;
44c69747 11379
9bcb3eef
DS
11380 for (dest = bgp_table_top(rib); dest;
11381 dest = bgp_route_next(dest)) {
11382 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11383
9bcb3eef 11384 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11385 continue;
9bcb3eef 11386 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11387 if (!table)
11388 continue;
11389
11390 longest_pfx = NULL;
cded3b72 11391 is_exact_pfxlen_match = false;
44c69747
LK
11392 /*
11393 * Search through all the prefixes for a match. The
11394 * pfx's are enumerated in ascending order of pfxlens.
11395 * So, the last pfx match is the longest match. Set
11396 * is_exact_pfxlen_match when we get exact pfxlen match
11397 */
11398 for (rm = bgp_table_top(table); rm;
11399 rm = bgp_route_next(rm)) {
b54892e0 11400 const struct prefix *rm_p =
9bcb3eef 11401 bgp_dest_get_prefix(rm);
44c69747
LK
11402 /*
11403 * Get prefixlen of the ip-prefix within type5
11404 * evpn route
11405 */
b54892e0
DS
11406 if (evpn_type5_prefix_match(rm_p, &match)
11407 && rm->info) {
44c69747
LK
11408 longest_pfx = rm;
11409 int type5_pfxlen =
b54892e0
DS
11410 bgp_evpn_get_type5_prefixlen(
11411 rm_p);
44c69747 11412 if (type5_pfxlen == match.prefixlen) {
cded3b72 11413 is_exact_pfxlen_match = true;
9bcb3eef 11414 bgp_dest_unlock_node(rm);
44c69747
LK
11415 break;
11416 }
d62a17ae 11417 }
11418 }
ea47320b 11419
44c69747
LK
11420 if (!longest_pfx)
11421 continue;
11422
11423 if (prefix_check && !is_exact_pfxlen_match)
11424 continue;
11425
11426 rm = longest_pfx;
9bcb3eef 11427 bgp_dest_lock_node(rm);
44c69747 11428
9bcb3eef 11429 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11430 bgp, afi, safi, json, pathtype,
4027d19b 11431 &display, rpki_target_state);
44c69747 11432
9bcb3eef 11433 bgp_dest_unlock_node(rm);
d62a17ae 11434 }
98a9dbc7 11435 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11436 if (use_json)
11437 json_paths = json_object_new_array();
11438
63a0b7a9
PG
11439 display = bgp_flowspec_display_match_per_ip(afi, rib,
11440 &match, prefix_check,
11441 vty,
11442 use_json,
11443 json_paths);
d5f20468
SP
11444 if (use_json) {
11445 if (display)
11446 json_object_object_add(json, "paths",
11447 json_paths);
11448 else
11449 json_object_free(json_paths);
11450 }
d62a17ae 11451 } else {
9bcb3eef
DS
11452 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11453 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11454 if (!prefix_check
9bcb3eef
DS
11455 || dest_p->prefixlen == match.prefixlen) {
11456 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11457 safi, json, pathtype,
4027d19b 11458 &display, rpki_target_state);
d62a17ae 11459 }
11460
9bcb3eef 11461 bgp_dest_unlock_node(dest);
d62a17ae 11462 }
11463 }
e5eee9af 11464
d62a17ae 11465 if (use_json) {
996c9314 11466 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11467 json, JSON_C_TO_STRING_PRETTY |
11468 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11469 json_object_free(json);
11470 } else {
11471 if (!display) {
11472 vty_out(vty, "%% Network not in table\n");
11473 return CMD_WARNING;
11474 }
11475 }
b05a1c8b 11476
d62a17ae 11477 return CMD_SUCCESS;
718e3744 11478}
11479
fee0f4c6 11480/* Display specified route of Main RIB */
d62a17ae 11481static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11482 afi_t afi, safi_t safi, struct prefix_rd *prd,
11483 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11484 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11485{
9b86009a 11486 if (!bgp) {
d62a17ae 11487 bgp = bgp_get_default();
9b86009a
RW
11488 if (!bgp) {
11489 if (!use_json)
11490 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11491 else
11492 vty_out(vty, "{}\n");
9b86009a
RW
11493 return CMD_WARNING;
11494 }
11495 }
d62a17ae 11496
11497 /* labeled-unicast routes live in the unicast table */
11498 if (safi == SAFI_LABELED_UNICAST)
11499 safi = SAFI_UNICAST;
11500
11501 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11502 afi, safi, rpki_target_state, prd,
8aa22bbb 11503 prefix_check, pathtype, use_json);
d62a17ae 11504}
11505
11506static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11507 struct cmd_token **argv, bool exact, afi_t afi,
11508 safi_t safi, bool uj)
d62a17ae 11509{
11510 struct lcommunity *lcom;
11511 struct buffer *b;
11512 int i;
11513 char *str;
11514 int first = 0;
96f3485c 11515 uint8_t show_flags = 0;
4f28b2b5 11516 int ret;
96f3485c
MK
11517
11518 if (uj)
11519 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11520
11521 b = buffer_new(1024);
11522 for (i = 0; i < argc; i++) {
11523 if (first)
11524 buffer_putc(b, ' ');
11525 else {
11526 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11527 first = 1;
11528 buffer_putstr(b, argv[i]->arg);
11529 }
11530 }
11531 }
11532 buffer_putc(b, '\0');
57d187bc 11533
d62a17ae 11534 str = buffer_getstr(b);
11535 buffer_free(b);
57d187bc 11536
d62a17ae 11537 lcom = lcommunity_str2com(str);
11538 XFREE(MTYPE_TMP, str);
11539 if (!lcom) {
11540 vty_out(vty, "%% Large-community malformed\n");
11541 return CMD_WARNING;
11542 }
57d187bc 11543
4f28b2b5 11544 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11545 (exact ? bgp_show_type_lcommunity_exact
11546 : bgp_show_type_lcommunity),
11547 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11548
11549 lcommunity_free(&lcom);
11550 return ret;
57d187bc
JS
11551}
11552
d62a17ae 11553static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11554 const char *lcom, bool exact, afi_t afi,
11555 safi_t safi, bool uj)
57d187bc 11556{
d62a17ae 11557 struct community_list *list;
96f3485c
MK
11558 uint8_t show_flags = 0;
11559
11560 if (uj)
11561 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11562
57d187bc 11563
e237b0d2 11564 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11565 LARGE_COMMUNITY_LIST_MASTER);
11566 if (list == NULL) {
11567 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11568 lcom);
11569 return CMD_WARNING;
11570 }
57d187bc 11571
36a206db 11572 return bgp_show(vty, bgp, afi, safi,
11573 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11574 : bgp_show_type_lcommunity_list),
1e2ce4f1 11575 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11576}
11577
52951b63
DS
11578DEFUN (show_ip_bgp_large_community_list,
11579 show_ip_bgp_large_community_list_cmd,
36a206db 11580 "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
11581 SHOW_STR
11582 IP_STR
11583 BGP_STR
11584 BGP_INSTANCE_HELP_STR
9bedbb1e 11585 BGP_AFI_HELP_STR
4dd6177e 11586 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11587 "Display routes matching the large-community-list\n"
11588 "large-community-list number\n"
11589 "large-community-list name\n"
36a206db 11590 "Exact match of the large-communities\n"
52951b63
DS
11591 JSON_STR)
11592{
d62a17ae 11593 afi_t afi = AFI_IP6;
11594 safi_t safi = SAFI_UNICAST;
11595 int idx = 0;
36a206db 11596 bool exact_match = 0;
4d678463 11597 struct bgp *bgp = NULL;
9f049418 11598 bool uj = use_json(argc, argv);
d62a17ae 11599
4d678463
KA
11600 if (uj)
11601 argc--;
11602
11603 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11604 &bgp, uj);
11605 if (!idx)
11606 return CMD_WARNING;
d62a17ae 11607
11608 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11609
11610 const char *clist_number_or_name = argv[++idx]->arg;
11611
11612 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11613 exact_match = 1;
11614
11615 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11616 exact_match, afi, safi, uj);
52951b63
DS
11617}
11618DEFUN (show_ip_bgp_large_community,
11619 show_ip_bgp_large_community_cmd,
36a206db 11620 "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
11621 SHOW_STR
11622 IP_STR
11623 BGP_STR
11624 BGP_INSTANCE_HELP_STR
9bedbb1e 11625 BGP_AFI_HELP_STR
4dd6177e 11626 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11627 "Display routes matching the large-communities\n"
11628 "List of large-community numbers\n"
36a206db 11629 "Exact match of the large-communities\n"
52951b63
DS
11630 JSON_STR)
11631{
d62a17ae 11632 afi_t afi = AFI_IP6;
11633 safi_t safi = SAFI_UNICAST;
11634 int idx = 0;
36a206db 11635 bool exact_match = 0;
4d678463 11636 struct bgp *bgp = NULL;
9f049418 11637 bool uj = use_json(argc, argv);
96f3485c 11638 uint8_t show_flags = 0;
d62a17ae 11639
96f3485c
MK
11640 if (uj) {
11641 argc--;
11642 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11643 }
4d678463 11644
96f3485c
MK
11645 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11646 &bgp, uj);
11647 if (!idx)
11648 return CMD_WARNING;
d62a17ae 11649
36a206db 11650 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11651 if (argv_find(argv, argc, "exact-match", &idx))
11652 exact_match = 1;
11653 return bgp_show_lcommunity(vty, bgp, argc, argv,
11654 exact_match, afi, safi, uj);
11655 } else
d62a17ae 11656 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11657 bgp_show_type_lcommunity_all, NULL, show_flags,
11658 RPKI_NOT_BEING_USED);
52951b63
DS
11659}
11660
71f1613a
DA
11661static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11662 safi_t safi, struct json_object *json_array);
d62a17ae 11663static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11664 safi_t safi, struct json_object *json);
e01ca200 11665
7b2ff250 11666
9ab0cf58
PG
11667DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11668 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11669 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11670 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11671{
11672 bool uj = use_json(argc, argv);
11673 struct bgp *bgp = NULL;
ec76a1d1
DA
11674 safi_t safi = SAFI_UNICAST;
11675 afi_t afi = AFI_IP6;
4265b261 11676 int idx = 0;
6c9d22e2
PG
11677 struct json_object *json_all = NULL;
11678 struct json_object *json_afi_safi = NULL;
4265b261
PG
11679
11680 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11681 &bgp, false);
71f1613a 11682 if (!idx)
4265b261 11683 return CMD_WARNING;
6c9d22e2 11684
4265b261 11685 if (uj)
6c9d22e2 11686 json_all = json_object_new_object();
4265b261 11687
9ab0cf58
PG
11688 FOREACH_AFI_SAFI (afi, safi) {
11689 /*
11690 * So limit output to those afi/safi pairs that
11691 * actually have something interesting in them
11692 */
11693 if (strmatch(get_afi_safi_str(afi, safi, true),
11694 "Unknown")) {
11695 continue;
11696 }
11697 if (uj) {
11698 json_afi_safi = json_object_new_array();
11699 json_object_object_add(
11700 json_all,
11701 get_afi_safi_str(afi, safi, true),
11702 json_afi_safi);
11703 } else {
11704 json_afi_safi = NULL;
6c9d22e2 11705 }
9ab0cf58
PG
11706
11707 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11708 }
6c9d22e2
PG
11709
11710 if (uj) {
9ab0cf58
PG
11711 vty_out(vty, "%s",
11712 json_object_to_json_string_ext(
11713 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11714 json_object_free(json_all);
4265b261 11715 }
6c9d22e2 11716
4265b261
PG
11717 return CMD_SUCCESS;
11718}
11719
7b2ff250 11720/* BGP route print out function without JSON */
14718643
PG
11721DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11722 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11723 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11724 SHOW_STR
11725 IP_STR
11726 BGP_STR
11727 BGP_INSTANCE_HELP_STR
11728 L2VPN_HELP_STR
11729 EVPN_HELP_STR
11730 "BGP RIB advertisement statistics\n"
11731 JSON_STR)
11732{
ec76a1d1
DA
11733 afi_t afi = AFI_IP6;
11734 safi_t safi = SAFI_UNICAST;
14718643
PG
11735 struct bgp *bgp = NULL;
11736 int idx = 0, ret;
11737 bool uj = use_json(argc, argv);
11738 struct json_object *json_afi_safi = NULL, *json = NULL;
11739
11740 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11741 &bgp, false);
11742 if (!idx)
11743 return CMD_WARNING;
11744
11745 if (uj)
11746 json_afi_safi = json_object_new_array();
11747 else
11748 json_afi_safi = NULL;
11749
11750 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11751
11752 if (uj) {
11753 json = json_object_new_object();
11754 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11755 json_afi_safi);
11756 vty_out(vty, "%s", json_object_to_json_string_ext(
11757 json, JSON_C_TO_STRING_PRETTY));
11758 json_object_free(json);
11759 }
11760 return ret;
11761}
11762
893cccd0 11763/* BGP route print out function without JSON */
9ab0cf58
PG
11764DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11765 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11766 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11767 "]]\
893cccd0 11768 statistics [json]",
9ab0cf58
PG
11769 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11770 BGP_SAFI_WITH_LABEL_HELP_STR
11771 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11772{
ec76a1d1
DA
11773 afi_t afi = AFI_IP6;
11774 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11775 struct bgp *bgp = NULL;
11776 int idx = 0, ret;
11777 bool uj = use_json(argc, argv);
6c9d22e2 11778 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11779
11780 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11781 &bgp, false);
11782 if (!idx)
11783 return CMD_WARNING;
6c9d22e2 11784
893cccd0 11785 if (uj)
6c9d22e2
PG
11786 json_afi_safi = json_object_new_array();
11787 else
11788 json_afi_safi = NULL;
11789
11790 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11791
11792 if (uj) {
11793 json = json_object_new_object();
11794 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11795 json_afi_safi);
9ab0cf58
PG
11796 vty_out(vty, "%s",
11797 json_object_to_json_string_ext(
11798 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11799 json_object_free(json);
11800 }
11801 return ret;
893cccd0 11802}
7b2ff250
DW
11803
11804/* BGP route print out function without JSON */
96f3485c 11805DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11806 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11807 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11808 "]]\
96f3485c 11809 <[all$all] dampening <parameters>\
7b2ff250
DW
11810 |route-map WORD\
11811 |prefix-list WORD\
11812 |filter-list WORD\
7b2ff250
DW
11813 |community-list <(1-500)|WORD> [exact-match]\
11814 |A.B.C.D/M longer-prefixes\
11815 |X:X::X:X/M longer-prefixes\
893cccd0 11816 >",
9ab0cf58
PG
11817 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11818 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11819 "Display the entries for all address families\n"
9ab0cf58
PG
11820 "Display detailed information about dampening\n"
11821 "Display detail of configured dampening parameters\n"
11822 "Display routes matching the route-map\n"
11823 "A route-map to match on\n"
11824 "Display routes conforming to the prefix-list\n"
11825 "Prefix-list name\n"
11826 "Display routes conforming to the filter-list\n"
11827 "Regular expression access list name\n"
11828 "Display routes matching the community-list\n"
11829 "community-list number\n"
11830 "community-list name\n"
11831 "Exact match of the communities\n"
11832 "IPv4 prefix\n"
11833 "Display route and more specific routes\n"
11834 "IPv6 prefix\n"
11835 "Display route and more specific routes\n")
718e3744 11836{
d62a17ae 11837 afi_t afi = AFI_IP6;
11838 safi_t safi = SAFI_UNICAST;
11839 int exact_match = 0;
d62a17ae 11840 struct bgp *bgp = NULL;
11841 int idx = 0;
96f3485c
MK
11842 uint8_t show_flags = 0;
11843
11844 /* [<ipv4|ipv6> [all]] */
11845 if (all) {
11846 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11847 if (argv_find(argv, argc, "ipv4", &idx))
11848 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11849
11850 if (argv_find(argv, argc, "ipv6", &idx))
11851 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11852 }
d62a17ae 11853
11854 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11855 &bgp, false);
d62a17ae 11856 if (!idx)
11857 return CMD_WARNING;
11858
d62a17ae 11859 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11860 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11861 return bgp_show_dampening_parameters(vty, afi, safi,
11862 show_flags);
d62a17ae 11863 }
c016b6c7 11864
d62a17ae 11865 if (argv_find(argv, argc, "prefix-list", &idx))
11866 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11867 safi, bgp_show_type_prefix_list);
11868
11869 if (argv_find(argv, argc, "filter-list", &idx))
11870 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11871 safi, bgp_show_type_filter_list);
11872
d62a17ae 11873 if (argv_find(argv, argc, "route-map", &idx))
11874 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11875 safi, bgp_show_type_route_map);
11876
d62a17ae 11877 if (argv_find(argv, argc, "community-list", &idx)) {
11878 const char *clist_number_or_name = argv[++idx]->arg;
11879 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11880 exact_match = 1;
11881 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11882 exact_match, afi, safi);
11883 }
11884 /* prefix-longer */
11885 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11886 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11887 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11888 safi,
11889 bgp_show_type_prefix_longer);
11890
7b2ff250
DW
11891 return CMD_WARNING;
11892}
11893
11894/* BGP route print out function with JSON */
ae248832 11895DEFPY (show_ip_bgp_json,
7b2ff250
DW
11896 show_ip_bgp_json_cmd,
11897 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11898 [all$all]\
cf4898bc
QY
11899 [cidr-only\
11900 |dampening <flap-statistics|dampened-paths>\
11901 |community [AA:NN|local-AS|no-advertise|no-export\
11902 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11903 |accept-own|accept-own-nexthop|route-filter-v6\
11904 |route-filter-v4|route-filter-translated-v6\
11905 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 11906 |rpki <invalid|valid|notfound>\
7d3cae70 11907 |version (1-4294967295)\
ae248832 11908 ] [json$uj | wide$wide]",
7b2ff250
DW
11909 SHOW_STR
11910 IP_STR
11911 BGP_STR
11912 BGP_INSTANCE_HELP_STR
11913 BGP_AFI_HELP_STR
11914 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11915 "Display the entries for all address families\n"
7b2ff250
DW
11916 "Display only routes with non-natural netmasks\n"
11917 "Display detailed information about dampening\n"
11918 "Display flap statistics of routes\n"
11919 "Display paths suppressed due to dampening\n"
11920 "Display routes matching the communities\n"
d0086e8e
AD
11921 COMMUNITY_AANN_STR
11922 "Do not send outside local AS (well-known community)\n"
11923 "Do not advertise to any peer (well-known community)\n"
11924 "Do not export to next AS (well-known community)\n"
11925 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11926 "Do not export to any peer (well-known community)\n"
11927 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11928 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11929 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11930 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11931 "Should accept VPN route with local nexthop (well-known community)\n"
11932 "RT VPNv6 route filtering (well-known community)\n"
11933 "RT VPNv4 route filtering (well-known community)\n"
11934 "RT translated VPNv6 route filtering (well-known community)\n"
11935 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11936 "Exact match of the communities\n"
1e2ce4f1
DS
11937 "RPKI route types\n"
11938 "A valid path as determined by rpki\n"
11939 "A invalid path as determined by rpki\n"
11940 "A path that has no rpki data\n"
7d3cae70
DA
11941 "Display prefixes with matching version numbers\n"
11942 "Version number and above\n"
ae248832
MK
11943 JSON_STR
11944 "Increase table width for longer prefixes\n")
7b2ff250
DW
11945{
11946 afi_t afi = AFI_IP6;
11947 safi_t safi = SAFI_UNICAST;
11948 enum bgp_show_type sh_type = bgp_show_type_normal;
11949 struct bgp *bgp = NULL;
11950 int idx = 0;
d0086e8e 11951 int exact_match = 0;
96f3485c 11952 char *community = NULL;
7d3cae70 11953 char *prefix_version = NULL;
96f3485c
MK
11954 bool first = true;
11955 uint8_t show_flags = 0;
4027d19b 11956 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
11957
11958 if (uj) {
9f049418 11959 argc--;
96f3485c
MK
11960 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11961 }
11962
11963 /* [<ipv4|ipv6> [all]] */
11964 if (all) {
11965 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11966
11967 if (argv_find(argv, argc, "ipv4", &idx))
11968 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11969
11970 if (argv_find(argv, argc, "ipv6", &idx))
11971 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11972 }
11973
11974 if (wide)
11975 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11976
11977 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11978 &bgp, uj);
7b2ff250
DW
11979 if (!idx)
11980 return CMD_WARNING;
11981
7b2ff250 11982 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11983 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11984
11985 if (argv_find(argv, argc, "dampening", &idx)) {
11986 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11987 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11988 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11989 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11990 }
11991
11992 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11993 char *maybecomm = NULL;
d0086e8e 11994
79bc257a
RW
11995 if (idx + 1 < argc) {
11996 if (argv[idx + 1]->type == VARIABLE_TKN)
11997 maybecomm = argv[idx + 1]->arg;
11998 else
11999 maybecomm = argv[idx + 1]->text;
12000 }
12001
cf4898bc
QY
12002 if (maybecomm && !strmatch(maybecomm, "json")
12003 && !strmatch(maybecomm, "exact-match"))
12004 community = maybecomm;
d0086e8e 12005
cf4898bc
QY
12006 if (argv_find(argv, argc, "exact-match", &idx))
12007 exact_match = 1;
d0086e8e 12008
96f3485c
MK
12009 if (!community)
12010 sh_type = bgp_show_type_community_all;
12011 }
12012
1e2ce4f1
DS
12013 if (argv_find(argv, argc, "rpki", &idx)) {
12014 sh_type = bgp_show_type_rpki;
12015 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12016 rpki_target_state = RPKI_VALID;
1e2ce4f1 12017 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12018 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12019 }
12020
7d3cae70
DA
12021 /* Display prefixes with matching version numbers */
12022 if (argv_find(argv, argc, "version", &idx)) {
12023 sh_type = bgp_show_type_prefix_version;
12024 prefix_version = argv[idx + 1]->arg;
12025 }
12026
96f3485c
MK
12027 if (!all) {
12028 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12029 if (community)
12030 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12031 exact_match, afi, safi,
12032 show_flags);
7d3cae70
DA
12033 else if (prefix_version)
12034 return bgp_show(vty, bgp, afi, safi, sh_type,
12035 prefix_version, show_flags,
12036 rpki_target_state);
cf4898bc 12037 else
96f3485c 12038 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12039 show_flags, rpki_target_state);
96f3485c
MK
12040 } else {
12041 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12042 * AFI_IP6 */
12043
12044 if (uj)
12045 vty_out(vty, "{\n");
12046
12047 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12048 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12049 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12050 ? AFI_IP
12051 : AFI_IP6;
12052 FOREACH_SAFI (safi) {
96f3485c
MK
12053 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12054 continue;
12055
12056 if (uj) {
12057 if (first)
12058 first = false;
12059 else
12060 vty_out(vty, ",\n");
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);
7d3cae70
DA
12074 else if (prefix_version)
12075 return bgp_show(vty, bgp, afi, safi,
12076 sh_type, prefix_version,
12077 show_flags,
12078 rpki_target_state);
96f3485c
MK
12079 else
12080 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12081 NULL, show_flags,
4027d19b 12082 rpki_target_state);
96f3485c
MK
12083 if (uj)
12084 vty_out(vty, "}\n");
12085 }
12086 } else {
12087 /* show <ip> bgp all: for each AFI and SAFI*/
12088 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12089 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12090 continue;
12091
12092 if (uj) {
12093 if (first)
12094 first = false;
12095 else
12096 vty_out(vty, ",\n");
d0086e8e 12097
96f3485c
MK
12098 vty_out(vty, "\"%s\":{\n",
12099 get_afi_safi_str(afi, safi,
12100 true));
12101 } else
12102 vty_out(vty,
12103 "\nFor address family: %s\n",
12104 get_afi_safi_str(afi, safi,
12105 false));
12106
12107 if (community)
12108 bgp_show_community(vty, bgp, community,
12109 exact_match, afi,
12110 safi, show_flags);
7d3cae70
DA
12111 else if (prefix_version)
12112 return bgp_show(vty, bgp, afi, safi,
12113 sh_type, prefix_version,
12114 show_flags,
12115 rpki_target_state);
96f3485c
MK
12116 else
12117 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12118 NULL, show_flags,
4027d19b 12119 rpki_target_state);
96f3485c
MK
12120 if (uj)
12121 vty_out(vty, "}\n");
12122 }
12123 }
12124 if (uj)
12125 vty_out(vty, "}\n");
12126 }
12127 return CMD_SUCCESS;
a636c635 12128}
47fc97cc 12129
718e3744 12130DEFUN (show_ip_bgp_route,
12131 show_ip_bgp_route_cmd,
8aa22bbb 12132 "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 12133 SHOW_STR
12134 IP_STR
12135 BGP_STR
a636c635 12136 BGP_INSTANCE_HELP_STR
4f280b15 12137 BGP_AFI_HELP_STR
4dd6177e 12138 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12139 "Network in the BGP routing table to display\n"
0c7b1b01 12140 "IPv4 prefix\n"
8c3deaae 12141 "Network in the BGP routing table to display\n"
0c7b1b01 12142 "IPv6 prefix\n"
4092b06c 12143 "Display only the bestpath\n"
b05a1c8b 12144 "Display only multipaths\n"
8aa22bbb
DS
12145 "Display only paths that match the specified rpki state\n"
12146 "A valid path as determined by rpki\n"
12147 "A invalid path as determined by rpki\n"
12148 "A path that has no rpki data\n"
9973d184 12149 JSON_STR)
4092b06c 12150{
d62a17ae 12151 int prefix_check = 0;
ae19d7dd 12152
d62a17ae 12153 afi_t afi = AFI_IP6;
12154 safi_t safi = SAFI_UNICAST;
12155 char *prefix = NULL;
12156 struct bgp *bgp = NULL;
12157 enum bgp_path_type path_type;
9f049418 12158 bool uj = use_json(argc, argv);
b05a1c8b 12159
d62a17ae 12160 int idx = 0;
ae19d7dd 12161
d62a17ae 12162 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12163 &bgp, uj);
d62a17ae 12164 if (!idx)
12165 return CMD_WARNING;
c41247f5 12166
d62a17ae 12167 if (!bgp) {
12168 vty_out(vty,
12169 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12170 return CMD_WARNING;
12171 }
a636c635 12172
d62a17ae 12173 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12174 if (argv_find(argv, argc, "A.B.C.D", &idx)
12175 || argv_find(argv, argc, "X:X::X:X", &idx))
12176 prefix_check = 0;
12177 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12178 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12179 prefix_check = 1;
12180
12181 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12182 && afi != AFI_IP6) {
12183 vty_out(vty,
12184 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12185 return CMD_WARNING;
12186 }
12187 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12188 && afi != AFI_IP) {
12189 vty_out(vty,
12190 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12191 return CMD_WARNING;
12192 }
12193
12194 prefix = argv[idx]->arg;
12195
12196 /* [<bestpath|multipath>] */
12197 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12198 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12199 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12200 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12201 else
360660c6 12202 path_type = BGP_PATH_SHOW_ALL;
a636c635 12203
d62a17ae 12204 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12205 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12206}
12207
8c3deaae
QY
12208DEFUN (show_ip_bgp_regexp,
12209 show_ip_bgp_regexp_cmd,
3e5b31b3 12210 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12211 SHOW_STR
12212 IP_STR
12213 BGP_STR
b00b230a 12214 BGP_INSTANCE_HELP_STR
4f280b15 12215 BGP_AFI_HELP_STR
4dd6177e 12216 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12217 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12218 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12219 JSON_STR)
8c3deaae 12220{
d62a17ae 12221 afi_t afi = AFI_IP6;
12222 safi_t safi = SAFI_UNICAST;
12223 struct bgp *bgp = NULL;
3e5b31b3
DA
12224 bool uj = use_json(argc, argv);
12225 char *regstr = NULL;
8c3deaae 12226
d62a17ae 12227 int idx = 0;
12228 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12229 &bgp, false);
d62a17ae 12230 if (!idx)
12231 return CMD_WARNING;
8c3deaae 12232
d62a17ae 12233 // get index of regex
3e5b31b3
DA
12234 if (argv_find(argv, argc, "REGEX", &idx))
12235 regstr = argv[idx]->arg;
8c3deaae 12236
5f71d11c 12237 assert(regstr);
3e5b31b3
DA
12238 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12239 bgp_show_type_regexp, uj);
8c3deaae
QY
12240}
12241
ae248832 12242DEFPY (show_ip_bgp_instance_all,
a636c635 12243 show_ip_bgp_instance_all_cmd,
ae248832 12244 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12245 SHOW_STR
a636c635 12246 IP_STR
4092b06c 12247 BGP_STR
a636c635 12248 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12249 BGP_AFI_HELP_STR
4dd6177e 12250 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12251 JSON_STR
12252 "Increase table width for longer prefixes\n")
4092b06c 12253{
d62a17ae 12254 afi_t afi = AFI_IP;
12255 safi_t safi = SAFI_UNICAST;
12256 struct bgp *bgp = NULL;
d62a17ae 12257 int idx = 0;
96f3485c 12258 uint8_t show_flags = 0;
ae19d7dd 12259
96f3485c 12260 if (uj) {
d62a17ae 12261 argc--;
96f3485c
MK
12262 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12263 }
12264
12265 if (wide)
12266 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12267
9f049418
DS
12268 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12269 &bgp, uj);
12270 if (!idx)
12271 return CMD_WARNING;
12272
96f3485c 12273 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12274 return CMD_SUCCESS;
e3e29b32
LB
12275}
12276
a4d82a8a 12277static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12278 afi_t afi, safi_t safi, enum bgp_show_type type,
12279 bool use_json)
718e3744 12280{
d62a17ae 12281 regex_t *regex;
12282 int rc;
96f3485c
MK
12283 uint8_t show_flags = 0;
12284
12285 if (use_json)
12286 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12287
c3900853 12288 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12289 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12290 regstr);
12291 return CMD_WARNING_CONFIG_FAILED;
12292 }
12293
d62a17ae 12294 regex = bgp_regcomp(regstr);
12295 if (!regex) {
12296 vty_out(vty, "Can't compile regexp %s\n", regstr);
12297 return CMD_WARNING;
12298 }
a636c635 12299
1e2ce4f1
DS
12300 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12301 RPKI_NOT_BEING_USED);
d62a17ae 12302 bgp_regex_free(regex);
12303 return rc;
e3e29b32
LB
12304}
12305
d62a17ae 12306static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12307 const char *prefix_list_str, afi_t afi,
12308 safi_t safi, enum bgp_show_type type)
e3e29b32 12309{
d62a17ae 12310 struct prefix_list *plist;
96f3485c 12311 uint8_t show_flags = 0;
718e3744 12312
d62a17ae 12313 plist = prefix_list_lookup(afi, prefix_list_str);
12314 if (plist == NULL) {
12315 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12316 prefix_list_str);
12317 return CMD_WARNING;
12318 }
718e3744 12319
1e2ce4f1
DS
12320 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12321 RPKI_NOT_BEING_USED);
4092b06c
DS
12322}
12323
d62a17ae 12324static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12325 const char *filter, afi_t afi, safi_t safi,
12326 enum bgp_show_type type)
4092b06c 12327{
d62a17ae 12328 struct as_list *as_list;
96f3485c 12329 uint8_t show_flags = 0;
718e3744 12330
d62a17ae 12331 as_list = as_list_lookup(filter);
12332 if (as_list == NULL) {
12333 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12334 filter);
12335 return CMD_WARNING;
12336 }
a636c635 12337
1e2ce4f1
DS
12338 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12339 RPKI_NOT_BEING_USED);
718e3744 12340}
12341
d62a17ae 12342static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12343 const char *rmap_str, afi_t afi, safi_t safi,
12344 enum bgp_show_type type)
718e3744 12345{
d62a17ae 12346 struct route_map *rmap;
96f3485c 12347 uint8_t show_flags = 0;
bb46e94f 12348
d62a17ae 12349 rmap = route_map_lookup_by_name(rmap_str);
12350 if (!rmap) {
12351 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12352 return CMD_WARNING;
12353 }
12354
1e2ce4f1
DS
12355 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12356 RPKI_NOT_BEING_USED);
d62a17ae 12357}
12358
7f323236
DW
12359static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12360 const char *comstr, int exact, afi_t afi,
96f3485c 12361 safi_t safi, uint8_t show_flags)
d62a17ae 12362{
12363 struct community *com;
d62a17ae 12364 int ret = 0;
12365
7f323236 12366 com = community_str2com(comstr);
d62a17ae 12367 if (!com) {
7f323236 12368 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12369 return CMD_WARNING;
12370 }
12371
12372 ret = bgp_show(vty, bgp, afi, safi,
12373 (exact ? bgp_show_type_community_exact
12374 : bgp_show_type_community),
1e2ce4f1 12375 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12376 community_free(&com);
46c3ce83 12377
d62a17ae 12378 return ret;
718e3744 12379}
12380
d62a17ae 12381static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12382 const char *com, int exact, afi_t afi,
12383 safi_t safi)
50ef26d4 12384{
d62a17ae 12385 struct community_list *list;
96f3485c 12386 uint8_t show_flags = 0;
50ef26d4 12387
e237b0d2 12388 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12389 if (list == NULL) {
12390 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12391 return CMD_WARNING;
12392 }
718e3744 12393
d62a17ae 12394 return bgp_show(vty, bgp, afi, safi,
12395 (exact ? bgp_show_type_community_list_exact
12396 : bgp_show_type_community_list),
1e2ce4f1 12397 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12398}
12399
d62a17ae 12400static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12401 const char *prefix, afi_t afi, safi_t safi,
12402 enum bgp_show_type type)
718e3744 12403{
d62a17ae 12404 int ret;
12405 struct prefix *p;
96f3485c 12406 uint8_t show_flags = 0;
47fc97cc 12407
d62a17ae 12408 p = prefix_new();
95cbbd2a 12409
d62a17ae 12410 ret = str2prefix(prefix, p);
12411 if (!ret) {
12412 vty_out(vty, "%% Malformed Prefix\n");
12413 return CMD_WARNING;
12414 }
47e9b292 12415
1e2ce4f1
DS
12416 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12417 RPKI_NOT_BEING_USED);
63265b5c 12418 prefix_free(&p);
d62a17ae 12419 return ret;
12420}
12421
d62a17ae 12422enum bgp_stats {
12423 BGP_STATS_MAXBITLEN = 0,
12424 BGP_STATS_RIB,
12425 BGP_STATS_PREFIXES,
12426 BGP_STATS_TOTPLEN,
12427 BGP_STATS_UNAGGREGATEABLE,
12428 BGP_STATS_MAX_AGGREGATEABLE,
12429 BGP_STATS_AGGREGATES,
12430 BGP_STATS_SPACE,
12431 BGP_STATS_ASPATH_COUNT,
12432 BGP_STATS_ASPATH_MAXHOPS,
12433 BGP_STATS_ASPATH_TOTHOPS,
12434 BGP_STATS_ASPATH_MAXSIZE,
12435 BGP_STATS_ASPATH_TOTSIZE,
12436 BGP_STATS_ASN_HIGHEST,
12437 BGP_STATS_MAX,
a636c635 12438};
2815e61f 12439
9ab0cf58 12440#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12441#define TABLE_STATS_IDX_JSON 1
12442
12443static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12444 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12445 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12446 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12447 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12448 "unaggregateablePrefixes"},
12449 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12450 "maximumAggregateablePrefixes"},
12451 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12452 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12453 [BGP_STATS_SPACE] = {"Address space advertised",
12454 "addressSpaceAdvertised"},
9ab0cf58
PG
12455 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12456 "advertisementsWithPaths"},
12457 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12458 "longestAsPath"},
12459 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12460 "largestAsPath"},
12461 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12462 "averageAsPathLengthHops"},
12463 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12464 "averageAsPathSizeBytes"},
12465 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12466 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12467};
2815e61f 12468
d62a17ae 12469struct bgp_table_stats {
12470 struct bgp_table *table;
12471 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12472 double total_space;
ff7924f6
PJ
12473};
12474
9bcb3eef 12475static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12476 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12477{
9bcb3eef 12478 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12479 struct bgp_path_info *pi;
b54892e0 12480 const struct prefix *rn_p;
d62a17ae 12481
9bcb3eef 12482 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12483 return;
d62a17ae 12484
9bcb3eef 12485 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12486 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12487 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12488
9c14ec72 12489 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12490 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12491 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12492
9bcb3eef 12493 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12494 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12495 /* announced address space */
12496 if (space)
b54892e0 12497 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12498 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12499 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12500
9c14ec72 12501
9bcb3eef 12502 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12503 ts->counts[BGP_STATS_RIB]++;
12504
05864da7
DS
12505 if (CHECK_FLAG(pi->attr->flag,
12506 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12507 ts->counts[BGP_STATS_AGGREGATES]++;
12508
12509 /* as-path stats */
05864da7 12510 if (pi->attr->aspath) {
9c14ec72
RW
12511 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12512 unsigned int size = aspath_size(pi->attr->aspath);
12513 as_t highest = aspath_highest(pi->attr->aspath);
12514
12515 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12516
12517 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12518 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12519
12520 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12521 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12522
12523 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12524 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12525 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12526 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12527 }
12528 }
12529}
12530
12531static int bgp_table_stats_walker(struct thread *t)
12532{
9bcb3eef
DS
12533 struct bgp_dest *dest, *ndest;
12534 struct bgp_dest *top;
9c14ec72
RW
12535 struct bgp_table_stats *ts = THREAD_ARG(t);
12536 unsigned int space = 0;
12537
12538 if (!(top = bgp_table_top(ts->table)))
12539 return 0;
12540
12541 switch (ts->table->afi) {
12542 case AFI_IP:
12543 space = IPV4_MAX_BITLEN;
12544 break;
12545 case AFI_IP6:
12546 space = IPV6_MAX_BITLEN;
12547 break;
3ba7b4af
TA
12548 case AFI_L2VPN:
12549 space = EVPN_ROUTE_PREFIXLEN;
12550 break;
9c14ec72
RW
12551 default:
12552 return 0;
12553 }
12554
12555 ts->counts[BGP_STATS_MAXBITLEN] = space;
12556
9bcb3eef 12557 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12558 if (ts->table->safi == SAFI_MPLS_VPN
12559 || ts->table->safi == SAFI_ENCAP
12560 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12561 struct bgp_table *table;
12562
9bcb3eef 12563 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12564 if (!table)
12565 continue;
12566
12567 top = bgp_table_top(table);
9bcb3eef
DS
12568 for (ndest = bgp_table_top(table); ndest;
12569 ndest = bgp_route_next(ndest))
12570 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12571 } else {
9bcb3eef 12572 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12573 }
12574 }
9c14ec72 12575
d62a17ae 12576 return 0;
2815e61f 12577}
ff7924f6 12578
71f1613a
DA
12579static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12580 struct json_object *json_array)
12581{
12582 struct listnode *node, *nnode;
12583 struct bgp *bgp;
12584
12585 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12586 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12587}
12588
12589static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12590 safi_t safi, struct json_object *json_array)
2815e61f 12591{
d62a17ae 12592 struct bgp_table_stats ts;
12593 unsigned int i;
893cccd0
PG
12594 int ret = CMD_SUCCESS;
12595 char temp_buf[20];
6c9d22e2
PG
12596 struct json_object *json = NULL;
12597
12598 if (json_array)
12599 json = json_object_new_object();
019386c2 12600
d62a17ae 12601 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12602 char warning_msg[50];
12603
12604 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12605 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12606 safi);
6c9d22e2
PG
12607
12608 if (!json)
893cccd0
PG
12609 vty_out(vty, "%s\n", warning_msg);
12610 else
9ab0cf58 12611 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12612
893cccd0
PG
12613 ret = CMD_WARNING;
12614 goto end_table_stats;
d62a17ae 12615 }
019386c2 12616
893cccd0 12617 if (!json)
5290ceab
DA
12618 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12619 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12620 else
12621 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12622
d62a17ae 12623 /* labeled-unicast routes live in the unicast table */
12624 if (safi == SAFI_LABELED_UNICAST)
12625 safi = SAFI_UNICAST;
019386c2 12626
d62a17ae 12627 memset(&ts, 0, sizeof(ts));
12628 ts.table = bgp->rib[afi][safi];
12629 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12630
d62a17ae 12631 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12632 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12633 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12634 continue;
12635
12636 switch (i) {
d62a17ae 12637 case BGP_STATS_ASPATH_TOTHOPS:
12638 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12639 if (!json) {
9ab0cf58
PG
12640 snprintf(
12641 temp_buf, sizeof(temp_buf), "%12.2f",
12642 ts.counts[i]
12643 ? (float)ts.counts[i]
12644 / (float)ts.counts
12645 [BGP_STATS_ASPATH_COUNT]
12646 : 0);
893cccd0 12647 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12648 table_stats_strs[i]
12649 [TABLE_STATS_IDX_VTY],
893cccd0 12650 temp_buf);
9ab0cf58
PG
12651 } else {
12652 json_object_double_add(
12653 json,
12654 table_stats_strs[i]
12655 [TABLE_STATS_IDX_JSON],
12656 ts.counts[i]
12657 ? (double)ts.counts[i]
12658 / (double)ts.counts
d62a17ae 12659 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12660 : 0);
12661 }
d62a17ae 12662 break;
12663 case BGP_STATS_TOTPLEN:
6c9d22e2 12664 if (!json) {
9ab0cf58
PG
12665 snprintf(
12666 temp_buf, sizeof(temp_buf), "%12.2f",
12667 ts.counts[i]
12668 ? (float)ts.counts[i]
12669 / (float)ts.counts
12670 [BGP_STATS_PREFIXES]
12671 : 0);
893cccd0 12672 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12673 table_stats_strs[i]
12674 [TABLE_STATS_IDX_VTY],
893cccd0 12675 temp_buf);
9ab0cf58
PG
12676 } else {
12677 json_object_double_add(
12678 json,
12679 table_stats_strs[i]
12680 [TABLE_STATS_IDX_JSON],
12681 ts.counts[i]
12682 ? (double)ts.counts[i]
12683 / (double)ts.counts
d62a17ae 12684 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12685 : 0);
12686 }
d62a17ae 12687 break;
12688 case BGP_STATS_SPACE:
6c9d22e2
PG
12689 if (!json) {
12690 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12691 ts.total_space);
893cccd0 12692 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12693 table_stats_strs[i]
12694 [TABLE_STATS_IDX_VTY],
893cccd0 12695 temp_buf);
9ab0cf58
PG
12696 } else {
12697 json_object_double_add(
12698 json,
12699 table_stats_strs[i]
12700 [TABLE_STATS_IDX_JSON],
12701 (double)ts.total_space);
12702 }
8d0ab76d 12703 if (afi == AFI_IP6) {
6c9d22e2
PG
12704 if (!json) {
12705 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12706 "%12g",
12707 ts.total_space
12708 * pow(2.0, -128 + 32));
6c9d22e2
PG
12709 vty_out(vty, "%30s: %s\n",
12710 "/32 equivalent %s\n",
12711 temp_buf);
9ab0cf58
PG
12712 } else {
12713 json_object_double_add(
12714 json, "/32equivalent",
12715 (double)(ts.total_space
12716 * pow(2.0,
12717 -128 + 32)));
12718 }
6c9d22e2
PG
12719 if (!json) {
12720 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12721 "%12g",
12722 ts.total_space
12723 * pow(2.0, -128 + 48));
6c9d22e2
PG
12724 vty_out(vty, "%30s: %s\n",
12725 "/48 equivalent %s\n",
12726 temp_buf);
9ab0cf58
PG
12727 } else {
12728 json_object_double_add(
12729 json, "/48equivalent",
12730 (double)(ts.total_space
12731 * pow(2.0,
12732 -128 + 48)));
12733 }
8d0ab76d 12734 } else {
6c9d22e2
PG
12735 if (!json) {
12736 snprintf(temp_buf, sizeof(temp_buf),
12737 "%12.2f",
9ab0cf58
PG
12738 ts.total_space * 100.
12739 * pow(2.0, -32));
6c9d22e2 12740 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12741 "% announced ", temp_buf);
12742 } else {
12743 json_object_double_add(
12744 json, "%announced",
12745 (double)(ts.total_space * 100.
12746 * pow(2.0, -32)));
12747 }
6c9d22e2
PG
12748 if (!json) {
12749 snprintf(temp_buf, sizeof(temp_buf),
12750 "%12.2f",
9ab0cf58
PG
12751 ts.total_space
12752 * pow(2.0, -32 + 8));
6c9d22e2
PG
12753 vty_out(vty, "%30s: %s\n",
12754 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12755 } else {
12756 json_object_double_add(
12757 json, "/8equivalent",
12758 (double)(ts.total_space
12759 * pow(2.0, -32 + 8)));
12760 }
6c9d22e2
PG
12761 if (!json) {
12762 snprintf(temp_buf, sizeof(temp_buf),
12763 "%12.2f",
9ab0cf58
PG
12764 ts.total_space
12765 * pow(2.0, -32 + 24));
6c9d22e2 12766 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12767 "/24 equivalent ", temp_buf);
12768 } else {
12769 json_object_double_add(
12770 json, "/24equivalent",
12771 (double)(ts.total_space
12772 * pow(2.0, -32 + 24)));
12773 }
8d0ab76d 12774 }
d62a17ae 12775 break;
12776 default:
6c9d22e2
PG
12777 if (!json) {
12778 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12779 ts.counts[i]);
893cccd0 12780 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12781 table_stats_strs[i]
12782 [TABLE_STATS_IDX_VTY],
12783 temp_buf);
12784 } else {
12785 json_object_int_add(
12786 json,
12787 table_stats_strs[i]
12788 [TABLE_STATS_IDX_JSON],
12789 ts.counts[i]);
12790 }
d62a17ae 12791 }
893cccd0
PG
12792 if (!json)
12793 vty_out(vty, "\n");
d62a17ae 12794 }
9ab0cf58 12795end_table_stats:
6c9d22e2
PG
12796 if (json)
12797 json_object_array_add(json_array, json);
893cccd0 12798 return ret;
d62a17ae 12799}
12800
71f1613a
DA
12801static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12802 safi_t safi, struct json_object *json_array)
12803{
12804 if (!bgp) {
12805 bgp_table_stats_all(vty, afi, safi, json_array);
12806 return CMD_SUCCESS;
12807 }
12808
12809 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12810}
12811
d62a17ae 12812enum bgp_pcounts {
12813 PCOUNT_ADJ_IN = 0,
12814 PCOUNT_DAMPED,
12815 PCOUNT_REMOVED,
12816 PCOUNT_HISTORY,
12817 PCOUNT_STALE,
12818 PCOUNT_VALID,
12819 PCOUNT_ALL,
12820 PCOUNT_COUNTED,
7e3d9632 12821 PCOUNT_BPATH_SELECTED,
d62a17ae 12822 PCOUNT_PFCNT, /* the figure we display to users */
12823 PCOUNT_MAX,
a636c635 12824};
718e3744 12825
2b64873d 12826static const char *const pcount_strs[] = {
9d303b37
DL
12827 [PCOUNT_ADJ_IN] = "Adj-in",
12828 [PCOUNT_DAMPED] = "Damped",
12829 [PCOUNT_REMOVED] = "Removed",
12830 [PCOUNT_HISTORY] = "History",
12831 [PCOUNT_STALE] = "Stale",
12832 [PCOUNT_VALID] = "Valid",
12833 [PCOUNT_ALL] = "All RIB",
12834 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12835 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12836 [PCOUNT_PFCNT] = "Useable",
12837 [PCOUNT_MAX] = NULL,
a636c635 12838};
718e3744 12839
d62a17ae 12840struct peer_pcounts {
12841 unsigned int count[PCOUNT_MAX];
12842 const struct peer *peer;
12843 const struct bgp_table *table;
54317cba 12844 safi_t safi;
a636c635 12845};
47fc97cc 12846
9bcb3eef 12847static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12848{
54317cba
JW
12849 const struct bgp_adj_in *ain;
12850 const struct bgp_path_info *pi;
d62a17ae 12851 const struct peer *peer = pc->peer;
12852
54317cba
JW
12853 for (ain = rn->adj_in; ain; ain = ain->next)
12854 if (ain->peer == peer)
12855 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12856
9bcb3eef 12857 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12858
54317cba
JW
12859 if (pi->peer != peer)
12860 continue;
d62a17ae 12861
54317cba 12862 pc->count[PCOUNT_ALL]++;
d62a17ae 12863
54317cba
JW
12864 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12865 pc->count[PCOUNT_DAMPED]++;
12866 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12867 pc->count[PCOUNT_HISTORY]++;
12868 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12869 pc->count[PCOUNT_REMOVED]++;
12870 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12871 pc->count[PCOUNT_STALE]++;
12872 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12873 pc->count[PCOUNT_VALID]++;
12874 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12875 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12876 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12877 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12878
12879 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12880 pc->count[PCOUNT_COUNTED]++;
12881 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12882 flog_err(
12883 EC_LIB_DEVELOPMENT,
12884 "Attempting to count but flags say it is unusable");
12885 } else {
40381db7 12886 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12887 flog_err(
12888 EC_LIB_DEVELOPMENT,
12889 "Not counted but flags say we should");
d62a17ae 12890 }
12891 }
54317cba
JW
12892}
12893
12894static int bgp_peer_count_walker(struct thread *t)
12895{
9bcb3eef 12896 struct bgp_dest *rn, *rm;
54317cba
JW
12897 const struct bgp_table *table;
12898 struct peer_pcounts *pc = THREAD_ARG(t);
12899
12900 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12901 || pc->safi == SAFI_EVPN) {
12902 /* Special handling for 2-level routing tables. */
12903 for (rn = bgp_table_top(pc->table); rn;
12904 rn = bgp_route_next(rn)) {
9bcb3eef 12905 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12906 if (table != NULL)
12907 for (rm = bgp_table_top(table); rm;
12908 rm = bgp_route_next(rm))
12909 bgp_peer_count_proc(rm, pc);
12910 }
12911 } else
12912 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12913 bgp_peer_count_proc(rn, pc);
12914
d62a17ae 12915 return 0;
718e3744 12916}
12917
d62a17ae 12918static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12919 safi_t safi, bool use_json)
856ca177 12920{
d62a17ae 12921 struct peer_pcounts pcounts = {.peer = peer};
12922 unsigned int i;
12923 json_object *json = NULL;
12924 json_object *json_loop = NULL;
856ca177 12925
d62a17ae 12926 if (use_json) {
12927 json = json_object_new_object();
12928 json_loop = json_object_new_object();
12929 }
718e3744 12930
d62a17ae 12931 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12932 || !peer->bgp->rib[afi][safi]) {
12933 if (use_json) {
12934 json_object_string_add(
12935 json, "warning",
12936 "No such neighbor or address family");
12937 vty_out(vty, "%s\n", json_object_to_json_string(json));
12938 json_object_free(json);
d5f20468 12939 json_object_free(json_loop);
d62a17ae 12940 } else
12941 vty_out(vty, "%% No such neighbor or address family\n");
12942
12943 return CMD_WARNING;
12944 }
2a71e9ce 12945
d62a17ae 12946 memset(&pcounts, 0, sizeof(pcounts));
12947 pcounts.peer = peer;
12948 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12949 pcounts.safi = safi;
d62a17ae 12950
12951 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12952 * stats for the thread-walk (i.e. ensure this can't be blamed on
12953 * on just vty_read()).
12954 */
d62a17ae 12955 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12956
12957 if (use_json) {
12958 json_object_string_add(json, "prefixCountsFor", peer->host);
12959 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12960 get_afi_safi_str(afi, safi, true));
d62a17ae 12961 json_object_int_add(json, "pfxCounter",
12962 peer->pcount[afi][safi]);
12963
12964 for (i = 0; i < PCOUNT_MAX; i++)
12965 json_object_int_add(json_loop, pcount_strs[i],
12966 pcounts.count[i]);
12967
12968 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12969
12970 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12971 json_object_string_add(json, "pfxctDriftFor",
12972 peer->host);
12973 json_object_string_add(
12974 json, "recommended",
12975 "Please report this bug, with the above command output");
12976 }
996c9314
LB
12977 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12978 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12979 json_object_free(json);
12980 } else {
12981
12982 if (peer->hostname
892fedb6 12983 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12984 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12985 peer->hostname, peer->host,
5cb5f4d0 12986 get_afi_safi_str(afi, safi, false));
d62a17ae 12987 } else {
12988 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12989 get_afi_safi_str(afi, safi, false));
d62a17ae 12990 }
12991
6cde4b45 12992 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12993 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12994
12995 for (i = 0; i < PCOUNT_MAX; i++)
12996 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12997 pcounts.count[i]);
12998
12999 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13000 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13001 vty_out(vty,
13002 "Please report this bug, with the above command output\n");
13003 }
13004 }
13005
13006 return CMD_SUCCESS;
718e3744 13007}
13008
a636c635
DW
13009DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13010 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13011 "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 13012 SHOW_STR
13013 IP_STR
13014 BGP_STR
8386ac43 13015 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13016 BGP_AFI_HELP_STR
13017 BGP_SAFI_HELP_STR
0b16f239
DS
13018 "Detailed information on TCP and BGP neighbor connections\n"
13019 "Neighbor to display information about\n"
13020 "Neighbor to display information about\n"
91d37724 13021 "Neighbor on BGP configured interface\n"
a636c635 13022 "Display detailed prefix count information\n"
9973d184 13023 JSON_STR)
0b16f239 13024{
d62a17ae 13025 afi_t afi = AFI_IP6;
13026 safi_t safi = SAFI_UNICAST;
13027 struct peer *peer;
13028 int idx = 0;
13029 struct bgp *bgp = NULL;
9f049418
DS
13030 bool uj = use_json(argc, argv);
13031
13032 if (uj)
13033 argc--;
856ca177 13034
d62a17ae 13035 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13036 &bgp, uj);
d62a17ae 13037 if (!idx)
13038 return CMD_WARNING;
0b16f239 13039
d62a17ae 13040 argv_find(argv, argc, "neighbors", &idx);
13041 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13042 if (!peer)
13043 return CMD_WARNING;
bb46e94f 13044
29c8d9da 13045 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13046}
0b16f239 13047
d6902373
PG
13048#ifdef KEEP_OLD_VPN_COMMANDS
13049DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13050 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13051 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13052 SHOW_STR
13053 IP_STR
13054 BGP_STR
d6902373 13055 BGP_VPNVX_HELP_STR
91d37724 13056 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13057 "Detailed information on TCP and BGP neighbor connections\n"
13058 "Neighbor to display information about\n"
13059 "Neighbor to display information about\n"
91d37724 13060 "Neighbor on BGP configured interface\n"
a636c635 13061 "Display detailed prefix count information\n"
9973d184 13062 JSON_STR)
a636c635 13063{
d62a17ae 13064 int idx_peer = 6;
13065 struct peer *peer;
9f049418 13066 bool uj = use_json(argc, argv);
a636c635 13067
d62a17ae 13068 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13069 if (!peer)
13070 return CMD_WARNING;
13071
13072 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13073}
13074
d6902373
PG
13075DEFUN (show_ip_bgp_vpn_all_route_prefix,
13076 show_ip_bgp_vpn_all_route_prefix_cmd,
13077 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13078 SHOW_STR
13079 IP_STR
13080 BGP_STR
d6902373 13081 BGP_VPNVX_HELP_STR
91d37724
QY
13082 "Display information about all VPNv4 NLRIs\n"
13083 "Network in the BGP routing table to display\n"
3a2d747c 13084 "Network in the BGP routing table to display\n"
9973d184 13085 JSON_STR)
91d37724 13086{
d62a17ae 13087 int idx = 0;
13088 char *network = NULL;
13089 struct bgp *bgp = bgp_get_default();
13090 if (!bgp) {
13091 vty_out(vty, "Can't find default instance\n");
13092 return CMD_WARNING;
13093 }
87e34b58 13094
d62a17ae 13095 if (argv_find(argv, argc, "A.B.C.D", &idx))
13096 network = argv[idx]->arg;
13097 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13098 network = argv[idx]->arg;
13099 else {
13100 vty_out(vty, "Unable to figure out Network\n");
13101 return CMD_WARNING;
13102 }
87e34b58 13103
d62a17ae 13104 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13105 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13106 use_json(argc, argv));
91d37724 13107}
d6902373 13108#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13109
44c69747
LK
13110DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13111 show_bgp_l2vpn_evpn_route_prefix_cmd,
13112 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13113 SHOW_STR
4c63a661
PG
13114 BGP_STR
13115 L2VPN_HELP_STR
13116 EVPN_HELP_STR
44c69747
LK
13117 "Network in the BGP routing table to display\n"
13118 "Network in the BGP routing table to display\n"
4c63a661
PG
13119 "Network in the BGP routing table to display\n"
13120 "Network in the BGP routing table to display\n"
13121 JSON_STR)
13122{
d62a17ae 13123 int idx = 0;
13124 char *network = NULL;
44c69747 13125 int prefix_check = 0;
a636c635 13126
44c69747
LK
13127 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13128 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13129 network = argv[idx]->arg;
44c69747 13130 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13131 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13132 network = argv[idx]->arg;
44c69747
LK
13133 prefix_check = 1;
13134 } else {
d62a17ae 13135 vty_out(vty, "Unable to figure out Network\n");
13136 return CMD_WARNING;
13137 }
44c69747
LK
13138 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13139 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13140 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13141}
13142
2f9bc755
DS
13143static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13144 struct bgp_table *table, int *header1,
13145 int *header2, json_object *json,
13146 json_object *json_scode,
13147 json_object *json_ocode, bool wide)
13148{
13149 uint64_t version = table ? table->version : 0;
23d0a753 13150 char buf[BUFSIZ] = {0};
2f9bc755
DS
13151
13152 if (*header1) {
13153 if (json) {
13154 json_object_int_add(json, "bgpTableVersion", version);
13155 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13156 inet_ntop(AF_INET,
13157 &bgp->router_id, buf,
13158 sizeof(buf)));
2f9bc755
DS
13159 json_object_int_add(json, "defaultLocPrf",
13160 bgp->default_local_pref);
13161 json_object_int_add(json, "localAS", bgp->as);
13162 json_object_object_add(json, "bgpStatusCodes",
13163 json_scode);
13164 json_object_object_add(json, "bgpOriginCodes",
13165 json_ocode);
13166 } else {
13167 vty_out(vty,
23d0a753
DA
13168 "BGP table version is %" PRIu64
13169 ", local router ID is %pI4, vrf id ",
13170 version, &bgp->router_id);
2f9bc755
DS
13171 if (bgp->vrf_id == VRF_UNKNOWN)
13172 vty_out(vty, "%s", VRFID_NONE_STR);
13173 else
13174 vty_out(vty, "%u", bgp->vrf_id);
13175 vty_out(vty, "\n");
13176 vty_out(vty, "Default local pref %u, ",
13177 bgp->default_local_pref);
13178 vty_out(vty, "local AS %u\n", bgp->as);
13179 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13180 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13181 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13182 }
13183 *header1 = 0;
13184 }
13185 if (*header2) {
13186 if (!json)
13187 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13188 : BGP_SHOW_HEADER));
13189 *header2 = 0;
13190 }
13191}
13192
d9478df0
TA
13193static void
13194show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13195 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13196 const char *rmap_name, json_object *json, json_object *json_ar,
13197 json_object *json_scode, json_object *json_ocode,
13198 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13199 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13200{
d62a17ae 13201 struct bgp_adj_in *ain;
13202 struct bgp_adj_out *adj;
9bcb3eef 13203 struct bgp_dest *dest;
d62a17ae 13204 struct bgp *bgp;
d62a17ae 13205 struct attr attr;
13206 int ret;
13207 struct update_subgroup *subgrp;
d62a17ae 13208 struct peer_af *paf;
f99def61 13209 bool route_filtered;
96f3485c
MK
13210 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13211 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13212 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13213 || (safi == SAFI_EVPN))
13214 ? true
13215 : false;
a636c635 13216
d62a17ae 13217 bgp = peer->bgp;
a636c635 13218
d62a17ae 13219 if (!bgp) {
13220 if (use_json) {
13221 json_object_string_add(json, "alert", "no BGP");
13222 vty_out(vty, "%s\n", json_object_to_json_string(json));
13223 json_object_free(json);
13224 } else
13225 vty_out(vty, "%% No bgp\n");
13226 return;
13227 }
a636c635 13228
d62a17ae 13229 subgrp = peer_subgroup(peer, afi, safi);
13230
6392aaa6 13231 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13232 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13233 char buf[BUFSIZ] = {0};
13234
d62a17ae 13235 if (use_json) {
13236 json_object_int_add(json, "bgpTableVersion",
13237 table->version);
13238 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13239 inet_ntop(AF_INET,
13240 &bgp->router_id, buf,
13241 sizeof(buf)));
01eced22
AD
13242 json_object_int_add(json, "defaultLocPrf",
13243 bgp->default_local_pref);
13244 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13245 json_object_object_add(json, "bgpStatusCodes",
13246 json_scode);
13247 json_object_object_add(json, "bgpOriginCodes",
13248 json_ocode);
07d0c4ed
DA
13249 json_object_string_add(
13250 json, "bgpOriginatingDefaultNetwork",
13251 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13252 } else {
23d0a753
DA
13253 vty_out(vty,
13254 "BGP table version is %" PRIu64
13255 ", local router ID is %pI4, vrf id ",
13256 table->version, &bgp->router_id);
9df8b37c
PZ
13257 if (bgp->vrf_id == VRF_UNKNOWN)
13258 vty_out(vty, "%s", VRFID_NONE_STR);
13259 else
13260 vty_out(vty, "%u", bgp->vrf_id);
13261 vty_out(vty, "\n");
01eced22
AD
13262 vty_out(vty, "Default local pref %u, ",
13263 bgp->default_local_pref);
13264 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13265 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13266 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13267 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13268
07d0c4ed
DA
13269 vty_out(vty, "Originating default network %s\n\n",
13270 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13271 }
d9478df0 13272 *header1 = 0;
d62a17ae 13273 }
a636c635 13274
9bcb3eef 13275 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13276 if (type == bgp_show_adj_route_received
13277 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13278 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13279 if (ain->peer != peer)
ea47320b 13280 continue;
6392aaa6 13281
d9478df0
TA
13282 show_adj_route_header(vty, bgp, table, header1,
13283 header2, json, json_scode,
13284 json_ocode, wide);
13285
13286 if ((safi == SAFI_MPLS_VPN)
13287 || (safi == SAFI_ENCAP)
13288 || (safi == SAFI_EVPN)) {
13289 if (use_json)
13290 json_object_string_add(
13291 json_ar, "rd", rd_str);
13292 else if (show_rd && rd_str) {
13293 vty_out(vty,
13294 "Route Distinguisher: %s\n",
13295 rd_str);
13296 show_rd = false;
13297 }
13298 }
6392aaa6 13299
6f4f49b2 13300 attr = *ain->attr;
f99def61
AD
13301 route_filtered = false;
13302
13303 /* Filter prefix using distribute list,
13304 * filter list or prefix list
13305 */
b54892e0 13306 const struct prefix *rn_p =
9bcb3eef 13307 bgp_dest_get_prefix(dest);
b54892e0
DS
13308 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13309 safi))
13310 == FILTER_DENY)
f99def61
AD
13311 route_filtered = true;
13312
13313 /* Filter prefix using route-map */
b54892e0
DS
13314 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13315 safi, rmap_name, NULL,
13316 0, NULL);
6392aaa6 13317
13c8e163
AD
13318 if (type == bgp_show_adj_route_filtered &&
13319 !route_filtered && ret != RMAP_DENY) {
b755861b 13320 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13321 continue;
d62a17ae 13322 }
6392aaa6 13323
d9478df0
TA
13324 if (type == bgp_show_adj_route_received
13325 && (route_filtered || ret == RMAP_DENY))
13326 (*filtered_count)++;
6392aaa6 13327
7d3cae70 13328 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13329 use_json, json_ar, wide);
b755861b 13330 bgp_attr_undup(&attr, ain->attr);
d9478df0 13331 (*output_count)++;
d62a17ae 13332 }
6392aaa6 13333 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13334 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13335 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13336 if (paf->peer != peer || !adj->attr)
924c3f6a 13337 continue;
d62a17ae 13338
d9478df0
TA
13339 show_adj_route_header(vty, bgp, table,
13340 header1, header2,
13341 json, json_scode,
13342 json_ocode, wide);
d62a17ae 13343
b54892e0 13344 const struct prefix *rn_p =
9bcb3eef 13345 bgp_dest_get_prefix(dest);
b54892e0 13346
6f4f49b2 13347 attr = *adj->attr;
b755861b 13348 ret = bgp_output_modifier(
b54892e0 13349 peer, rn_p, &attr, afi, safi,
b755861b 13350 rmap_name);
f46d8e1e 13351
b755861b 13352 if (ret != RMAP_DENY) {
d9478df0
TA
13353 if ((safi == SAFI_MPLS_VPN)
13354 || (safi == SAFI_ENCAP)
13355 || (safi == SAFI_EVPN)) {
13356 if (use_json)
13357 json_object_string_add(
13358 json_ar,
13359 "rd",
13360 rd_str);
13361 else if (show_rd
13362 && rd_str) {
13363 vty_out(vty,
13364 "Route Distinguisher: %s\n",
13365 rd_str);
13366 show_rd = false;
13367 }
13368 }
b54892e0 13369 route_vty_out_tmp(
7d3cae70
DA
13370 vty, dest, rn_p, &attr,
13371 safi, use_json, json_ar,
ae248832 13372 wide);
d9478df0 13373 (*output_count)++;
b755861b 13374 } else {
d9478df0 13375 (*filtered_count)++;
a2addae8 13376 }
b755861b
PM
13377
13378 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13379 }
f20ce998
DS
13380 } else if (type == bgp_show_adj_route_bestpath) {
13381 struct bgp_path_info *pi;
13382
d9478df0
TA
13383 show_adj_route_header(vty, bgp, table, header1, header2,
13384 json, json_scode, json_ocode,
13385 wide);
f20ce998
DS
13386
13387 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13388 pi = pi->next) {
13389 if (pi->peer != peer)
13390 continue;
13391
13392 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13393 continue;
13394
7d3cae70 13395 route_vty_out_tmp(vty, dest,
f20ce998
DS
13396 bgp_dest_get_prefix(dest),
13397 pi->attr, safi, use_json,
13398 json_ar, wide);
d9478df0 13399 (*output_count)++;
f20ce998 13400 }
d62a17ae 13401 }
13402 }
a636c635 13403}
2a71e9ce 13404
d62a17ae 13405static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13406 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13407 const char *rmap_name, uint8_t show_flags)
0b16f239 13408{
d9478df0
TA
13409 struct bgp *bgp;
13410 struct bgp_table *table;
d62a17ae 13411 json_object *json = NULL;
d9478df0
TA
13412 json_object *json_scode = NULL;
13413 json_object *json_ocode = NULL;
13414 json_object *json_ar = NULL;
96f3485c 13415 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13416
d9478df0
TA
13417 /* Init BGP headers here so they're only displayed once
13418 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13419 */
13420 int header1 = 1;
13421 int header2 = 1;
13422
13423 /*
13424 * Initialize variables for each RD
13425 * All prefixes under an RD is aggregated within "json_routes"
13426 */
13427 char rd_str[BUFSIZ] = {0};
13428 json_object *json_routes = NULL;
13429
13430
13431 /* For 2-tier tables, prefix counts need to be
13432 * maintained across multiple runs of show_adj_route()
13433 */
13434 unsigned long output_count_per_rd;
13435 unsigned long filtered_count_per_rd;
13436 unsigned long output_count = 0;
13437 unsigned long filtered_count = 0;
13438
13439 if (use_json) {
d62a17ae 13440 json = json_object_new_object();
d9478df0
TA
13441 json_ar = json_object_new_object();
13442 json_scode = json_object_new_object();
13443 json_ocode = json_object_new_object();
13444
13445 json_object_string_add(json_scode, "suppressed", "s");
13446 json_object_string_add(json_scode, "damped", "d");
13447 json_object_string_add(json_scode, "history", "h");
13448 json_object_string_add(json_scode, "valid", "*");
13449 json_object_string_add(json_scode, "best", ">");
13450 json_object_string_add(json_scode, "multipath", "=");
13451 json_object_string_add(json_scode, "internal", "i");
13452 json_object_string_add(json_scode, "ribFailure", "r");
13453 json_object_string_add(json_scode, "stale", "S");
13454 json_object_string_add(json_scode, "removed", "R");
13455
13456 json_object_string_add(json_ocode, "igp", "i");
13457 json_object_string_add(json_ocode, "egp", "e");
13458 json_object_string_add(json_ocode, "incomplete", "?");
13459 }
0b16f239 13460
d62a17ae 13461 if (!peer || !peer->afc[afi][safi]) {
13462 if (use_json) {
13463 json_object_string_add(
13464 json, "warning",
13465 "No such neighbor or address family");
13466 vty_out(vty, "%s\n", json_object_to_json_string(json));
13467 json_object_free(json);
13468 } else
13469 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13470
d62a17ae 13471 return CMD_WARNING;
13472 }
13473
6392aaa6
PM
13474 if ((type == bgp_show_adj_route_received
13475 || type == bgp_show_adj_route_filtered)
d62a17ae 13476 && !CHECK_FLAG(peer->af_flags[afi][safi],
13477 PEER_FLAG_SOFT_RECONFIG)) {
13478 if (use_json) {
13479 json_object_string_add(
13480 json, "warning",
13481 "Inbound soft reconfiguration not enabled");
13482 vty_out(vty, "%s\n", json_object_to_json_string(json));
13483 json_object_free(json);
13484 } else
13485 vty_out(vty,
13486 "%% Inbound soft reconfiguration not enabled\n");
13487
13488 return CMD_WARNING;
13489 }
0b16f239 13490
d9478df0
TA
13491 bgp = peer->bgp;
13492
13493 /* labeled-unicast routes live in the unicast table */
13494 if (safi == SAFI_LABELED_UNICAST)
13495 table = bgp->rib[afi][SAFI_UNICAST];
13496 else
13497 table = bgp->rib[afi][safi];
13498
13499 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13500 || (safi == SAFI_EVPN)) {
13501
13502 struct bgp_dest *dest;
13503
13504 for (dest = bgp_table_top(table); dest;
13505 dest = bgp_route_next(dest)) {
13506 table = bgp_dest_get_bgp_table_info(dest);
13507 if (!table)
13508 continue;
13509
13510 output_count_per_rd = 0;
13511 filtered_count_per_rd = 0;
13512
13513 if (use_json)
13514 json_routes = json_object_new_object();
13515
13516 const struct prefix_rd *prd;
13517 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13518 dest);
13519
13520 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13521
13522 show_adj_route(vty, peer, table, afi, safi, type,
13523 rmap_name, json, json_routes, json_scode,
13524 json_ocode, show_flags, &header1,
13525 &header2, rd_str, &output_count_per_rd,
13526 &filtered_count_per_rd);
13527
13528 /* Don't include an empty RD in the output! */
13529 if (json_routes && (output_count_per_rd > 0))
13530 json_object_object_add(json_ar, rd_str,
13531 json_routes);
13532
13533 output_count += output_count_per_rd;
13534 filtered_count += filtered_count_per_rd;
13535 }
13536 } else
13537 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13538 json, json_ar, json_scode, json_ocode,
13539 show_flags, &header1, &header2, rd_str,
13540 &output_count, &filtered_count);
13541
13542 if (use_json) {
13543 json_object_object_add(json, "advertisedRoutes", json_ar);
13544 json_object_int_add(json, "totalPrefixCounter", output_count);
13545 json_object_int_add(json, "filteredPrefixCounter",
13546 filtered_count);
13547
13548 vty_out(vty, "%s\n",
13549 json_object_to_json_string_ext(
13550 json, JSON_C_TO_STRING_PRETTY));
13551
13552 if (!output_count && !filtered_count) {
13553 json_object_free(json_scode);
13554 json_object_free(json_ocode);
13555 }
13556
13557 if (json)
13558 json_object_free(json);
13559
13560 } else if (output_count > 0) {
13561 if (filtered_count > 0)
13562 vty_out(vty,
13563 "\nTotal number of prefixes %ld (%ld filtered)\n",
13564 output_count, filtered_count);
13565 else
13566 vty_out(vty, "\nTotal number of prefixes %ld\n",
13567 output_count);
13568 }
0b16f239 13569
d62a17ae 13570 return CMD_SUCCESS;
a636c635 13571}
50ef26d4 13572
f20ce998
DS
13573DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13574 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13575 "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]",
13576 SHOW_STR
13577 IP_STR
13578 BGP_STR
13579 BGP_INSTANCE_HELP_STR
13580 BGP_AFI_HELP_STR
13581 BGP_SAFI_WITH_LABEL_HELP_STR
13582 "Detailed information on TCP and BGP neighbor connections\n"
13583 "Neighbor to display information about\n"
13584 "Neighbor to display information about\n"
13585 "Neighbor on BGP configured interface\n"
13586 "Display the routes selected by best path\n"
13587 JSON_STR
13588 "Increase table width for longer prefixes\n")
13589{
13590 afi_t afi = AFI_IP6;
13591 safi_t safi = SAFI_UNICAST;
13592 char *rmap_name = NULL;
13593 char *peerstr = NULL;
13594 struct bgp *bgp = NULL;
13595 struct peer *peer;
13596 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13597 int idx = 0;
96f3485c
MK
13598 uint8_t show_flags = 0;
13599
13600 if (uj)
13601 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13602
13603 if (wide)
13604 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13605
13606 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13607 &bgp, uj);
13608
13609 if (!idx)
13610 return CMD_WARNING;
13611
13612 argv_find(argv, argc, "neighbors", &idx);
13613 peerstr = argv[++idx]->arg;
13614
13615 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13616 if (!peer)
13617 return CMD_WARNING;
13618
96f3485c
MK
13619 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13620 show_flags);
f20ce998
DS
13621}
13622
ae248832 13623DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13624 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13625 "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 13626 SHOW_STR
13627 IP_STR
13628 BGP_STR
a636c635 13629 BGP_INSTANCE_HELP_STR
7395a2c9 13630 BGP_AFI_HELP_STR
4dd6177e 13631 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13632 "Display the entries for all address families\n"
718e3744 13633 "Detailed information on TCP and BGP neighbor connections\n"
13634 "Neighbor to display information about\n"
13635 "Neighbor to display information about\n"
91d37724 13636 "Neighbor on BGP configured interface\n"
a636c635 13637 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13638 "Display the received routes from neighbor\n"
13639 "Display the filtered routes received from neighbor\n"
a636c635
DW
13640 "Route-map to modify the attributes\n"
13641 "Name of the route map\n"
ae248832
MK
13642 JSON_STR
13643 "Increase table width for longer prefixes\n")
718e3744 13644{
d62a17ae 13645 afi_t afi = AFI_IP6;
13646 safi_t safi = SAFI_UNICAST;
13647 char *rmap_name = NULL;
13648 char *peerstr = NULL;
d62a17ae 13649 struct bgp *bgp = NULL;
13650 struct peer *peer;
6392aaa6 13651 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13652 int idx = 0;
96f3485c
MK
13653 bool first = true;
13654 uint8_t show_flags = 0;
6392aaa6 13655
96f3485c 13656 if (uj) {
d62a17ae 13657 argc--;
96f3485c
MK
13658 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13659 }
13660
13661 if (all) {
13662 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13663 if (argv_find(argv, argc, "ipv4", &idx))
13664 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13665
13666 if (argv_find(argv, argc, "ipv6", &idx))
13667 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13668 }
13669
13670 if (wide)
13671 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13672
9f049418
DS
13673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13674 &bgp, uj);
13675 if (!idx)
13676 return CMD_WARNING;
13677
d62a17ae 13678 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13679 argv_find(argv, argc, "neighbors", &idx);
13680 peerstr = argv[++idx]->arg;
8c3deaae 13681
d62a17ae 13682 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13683 if (!peer)
13684 return CMD_WARNING;
856ca177 13685
d62a17ae 13686 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13687 type = bgp_show_adj_route_advertised;
13688 else if (argv_find(argv, argc, "received-routes", &idx))
13689 type = bgp_show_adj_route_received;
13690 else if (argv_find(argv, argc, "filtered-routes", &idx))
13691 type = bgp_show_adj_route_filtered;
13692
d62a17ae 13693 if (argv_find(argv, argc, "route-map", &idx))
13694 rmap_name = argv[++idx]->arg;
95cbbd2a 13695
96f3485c
MK
13696 if (!all)
13697 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13698 show_flags);
13699 if (uj)
13700 vty_out(vty, "{\n");
13701
13702 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13703 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13704 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13705 : AFI_IP6;
13706 FOREACH_SAFI (safi) {
96f3485c
MK
13707 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13708 continue;
13709
13710 if (uj) {
13711 if (first)
13712 first = false;
13713 else
13714 vty_out(vty, ",\n");
13715 vty_out(vty, "\"%s\":",
13716 get_afi_safi_str(afi, safi, true));
13717 } else
13718 vty_out(vty, "\nFor address family: %s\n",
13719 get_afi_safi_str(afi, safi, false));
13720
13721 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13722 show_flags);
13723 }
13724 } else {
13725 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13726 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13727 continue;
13728
13729 if (uj) {
13730 if (first)
13731 first = false;
13732 else
13733 vty_out(vty, ",\n");
13734 vty_out(vty, "\"%s\":",
13735 get_afi_safi_str(afi, safi, true));
13736 } else
13737 vty_out(vty, "\nFor address family: %s\n",
13738 get_afi_safi_str(afi, safi, false));
13739
13740 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13741 show_flags);
13742 }
13743 }
13744 if (uj)
13745 vty_out(vty, "}\n");
13746
13747 return CMD_SUCCESS;
95cbbd2a
ML
13748}
13749
718e3744 13750DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13751 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13752 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13753 SHOW_STR
13754 IP_STR
13755 BGP_STR
8c3deaae
QY
13756 "Address Family\n"
13757 "Address Family\n"
718e3744 13758 "Address Family modifier\n"
13759 "Detailed information on TCP and BGP neighbor connections\n"
13760 "Neighbor to display information about\n"
13761 "Neighbor to display information about\n"
91d37724 13762 "Neighbor on BGP configured interface\n"
718e3744 13763 "Display information received from a BGP neighbor\n"
856ca177 13764 "Display the prefixlist filter\n"
9973d184 13765 JSON_STR)
718e3744 13766{
d62a17ae 13767 afi_t afi = AFI_IP6;
13768 safi_t safi = SAFI_UNICAST;
13769 char *peerstr = NULL;
13770
13771 char name[BUFSIZ];
13772 union sockunion su;
13773 struct peer *peer;
13774 int count, ret;
13775
13776 int idx = 0;
13777
13778 /* show [ip] bgp */
13779 if (argv_find(argv, argc, "ip", &idx))
13780 afi = AFI_IP;
13781 /* [<ipv4|ipv6> [unicast]] */
13782 if (argv_find(argv, argc, "ipv4", &idx))
13783 afi = AFI_IP;
13784 if (argv_find(argv, argc, "ipv6", &idx))
13785 afi = AFI_IP6;
13786 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13787 argv_find(argv, argc, "neighbors", &idx);
13788 peerstr = argv[++idx]->arg;
13789
9f049418 13790 bool uj = use_json(argc, argv);
d62a17ae 13791
13792 ret = str2sockunion(peerstr, &su);
13793 if (ret < 0) {
13794 peer = peer_lookup_by_conf_if(NULL, peerstr);
13795 if (!peer) {
13796 if (uj)
13797 vty_out(vty, "{}\n");
13798 else
13799 vty_out(vty,
13800 "%% Malformed address or name: %s\n",
13801 peerstr);
13802 return CMD_WARNING;
13803 }
13804 } else {
13805 peer = peer_lookup(NULL, &su);
13806 if (!peer) {
13807 if (uj)
13808 vty_out(vty, "{}\n");
13809 else
13810 vty_out(vty, "No peer\n");
13811 return CMD_WARNING;
13812 }
13813 }
718e3744 13814
4ced1a2c 13815 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13816 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13817 if (count) {
13818 if (!uj)
13819 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13820 get_afi_safi_str(afi, safi, false));
d62a17ae 13821 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13822 } else {
13823 if (uj)
13824 vty_out(vty, "{}\n");
13825 else
13826 vty_out(vty, "No functional output\n");
13827 }
718e3744 13828
d62a17ae 13829 return CMD_SUCCESS;
13830}
13831
13832static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13833 afi_t afi, safi_t safi,
9f049418 13834 enum bgp_show_type type, bool use_json)
d62a17ae 13835{
96f3485c
MK
13836 uint8_t show_flags = 0;
13837
13838 if (use_json)
13839 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13840
d62a17ae 13841 if (!peer || !peer->afc[afi][safi]) {
13842 if (use_json) {
13843 json_object *json_no = NULL;
13844 json_no = json_object_new_object();
13845 json_object_string_add(
13846 json_no, "warning",
13847 "No such neighbor or address family");
13848 vty_out(vty, "%s\n",
13849 json_object_to_json_string(json_no));
13850 json_object_free(json_no);
13851 } else
13852 vty_out(vty, "%% No such neighbor or address family\n");
13853 return CMD_WARNING;
13854 }
47fc97cc 13855
7daf25a3
TA
13856 /* labeled-unicast routes live in the unicast table */
13857 if (safi == SAFI_LABELED_UNICAST)
13858 safi = SAFI_UNICAST;
13859
1e2ce4f1
DS
13860 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
13861 RPKI_NOT_BEING_USED);
718e3744 13862}
13863
dba3c1d3
PG
13864DEFUN (show_ip_bgp_flowspec_routes_detailed,
13865 show_ip_bgp_flowspec_routes_detailed_cmd,
13866 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13867 SHOW_STR
13868 IP_STR
13869 BGP_STR
13870 BGP_INSTANCE_HELP_STR
13871 BGP_AFI_HELP_STR
13872 "SAFI Flowspec\n"
13873 "Detailed information on flowspec entries\n"
13874 JSON_STR)
13875{
13876 afi_t afi = AFI_IP;
13877 safi_t safi = SAFI_UNICAST;
13878 struct bgp *bgp = NULL;
13879 int idx = 0;
9f049418 13880 bool uj = use_json(argc, argv);
96f3485c 13881 uint8_t show_flags = 0;
9f049418 13882
96f3485c 13883 if (uj) {
9f049418 13884 argc--;
96f3485c
MK
13885 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13886 }
dba3c1d3
PG
13887
13888 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13889 &bgp, uj);
dba3c1d3
PG
13890 if (!idx)
13891 return CMD_WARNING;
13892
96f3485c 13893 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 13894 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
13895}
13896
718e3744 13897DEFUN (show_ip_bgp_neighbor_routes,
13898 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13899 "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 13900 SHOW_STR
13901 IP_STR
13902 BGP_STR
8386ac43 13903 BGP_INSTANCE_HELP_STR
4f280b15 13904 BGP_AFI_HELP_STR
4dd6177e 13905 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13906 "Detailed information on TCP and BGP neighbor connections\n"
13907 "Neighbor to display information about\n"
13908 "Neighbor to display information about\n"
91d37724 13909 "Neighbor on BGP configured interface\n"
2525cf39 13910 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13911 "Display the dampened routes received from neighbor\n"
13912 "Display routes learned from neighbor\n"
9973d184 13913 JSON_STR)
718e3744 13914{
d62a17ae 13915 char *peerstr = NULL;
13916 struct bgp *bgp = NULL;
13917 afi_t afi = AFI_IP6;
13918 safi_t safi = SAFI_UNICAST;
13919 struct peer *peer;
13920 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13921 int idx = 0;
9f049418
DS
13922 bool uj = use_json(argc, argv);
13923
13924 if (uj)
13925 argc--;
bb46e94f 13926
d62a17ae 13927 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13928 &bgp, uj);
d62a17ae 13929 if (!idx)
13930 return CMD_WARNING;
c493f2d8 13931
d62a17ae 13932 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13933 argv_find(argv, argc, "neighbors", &idx);
13934 peerstr = argv[++idx]->arg;
8c3deaae 13935
d62a17ae 13936 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13937 if (!peer)
d62a17ae 13938 return CMD_WARNING;
bb46e94f 13939
d62a17ae 13940 if (argv_find(argv, argc, "flap-statistics", &idx))
13941 sh_type = bgp_show_type_flap_neighbor;
13942 else if (argv_find(argv, argc, "dampened-routes", &idx))
13943 sh_type = bgp_show_type_damp_neighbor;
13944 else if (argv_find(argv, argc, "routes", &idx))
13945 sh_type = bgp_show_type_neighbor;
2525cf39 13946
d62a17ae 13947 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13948}
6b0655a2 13949
734b349e 13950struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13951
d62a17ae 13952struct bgp_distance {
13953 /* Distance value for the IP source prefix. */
d7c0a89a 13954 uint8_t distance;
718e3744 13955
d62a17ae 13956 /* Name of the access-list to be matched. */
13957 char *access_list;
718e3744 13958};
13959
4f280b15
LB
13960DEFUN (show_bgp_afi_vpn_rd_route,
13961 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 13962 "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
13963 SHOW_STR
13964 BGP_STR
13965 BGP_AFI_HELP_STR
13966 "Address Family modifier\n"
13967 "Display information for a route distinguisher\n"
13968 "Route Distinguisher\n"
a111dd97 13969 "All Route Distinguishers\n"
7395a2c9
DS
13970 "Network in the BGP routing table to display\n"
13971 "Network in the BGP routing table to display\n"
13972 JSON_STR)
4f280b15 13973{
d62a17ae 13974 int ret;
13975 struct prefix_rd prd;
13976 afi_t afi = AFI_MAX;
13977 int idx = 0;
4f280b15 13978
ff6566f3
DS
13979 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13980 vty_out(vty, "%% Malformed Address Family\n");
13981 return CMD_WARNING;
13982 }
13983
a111dd97
TA
13984 if (!strcmp(argv[5]->arg, "all"))
13985 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
13986 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
13987 RPKI_NOT_BEING_USED,
13988 use_json(argc, argv));
13989
d62a17ae 13990 ret = str2prefix_rd(argv[5]->arg, &prd);
13991 if (!ret) {
13992 vty_out(vty, "%% Malformed Route Distinguisher\n");
13993 return CMD_WARNING;
13994 }
ff6566f3 13995
d62a17ae 13996 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
13997 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13998 use_json(argc, argv));
4f280b15
LB
13999}
14000
d62a17ae 14001static struct bgp_distance *bgp_distance_new(void)
718e3744 14002{
d62a17ae 14003 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14004}
14005
d62a17ae 14006static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14007{
d62a17ae 14008 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14009}
14010
37a87b8f
CS
14011int bgp_distance_set(uint8_t distance, const char *ip_str,
14012 const char *access_list_str, afi_t afi, safi_t safi,
14013 char *errmsg, size_t errmsg_len)
718e3744 14014{
d62a17ae 14015 int ret;
d62a17ae 14016 struct prefix p;
9bcb3eef 14017 struct bgp_dest *dest;
d62a17ae 14018 struct bgp_distance *bdistance;
718e3744 14019
d62a17ae 14020 ret = str2prefix(ip_str, &p);
14021 if (ret == 0) {
37a87b8f 14022 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14023 return CMD_WARNING_CONFIG_FAILED;
14024 }
718e3744 14025
d62a17ae 14026 /* Get BGP distance node. */
9bcb3eef
DS
14027 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14028 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14029 if (bdistance)
9bcb3eef 14030 bgp_dest_unlock_node(dest);
ca2e160d 14031 else {
d62a17ae 14032 bdistance = bgp_distance_new();
9bcb3eef 14033 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14034 }
718e3744 14035
d62a17ae 14036 /* Set distance value. */
14037 bdistance->distance = distance;
718e3744 14038
d62a17ae 14039 /* Reset access-list configuration. */
e1b36e13 14040 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14041 if (access_list_str)
14042 bdistance->access_list =
14043 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14044
d62a17ae 14045 return CMD_SUCCESS;
718e3744 14046}
14047
37a87b8f
CS
14048int bgp_distance_unset(uint8_t distance, const char *ip_str,
14049 const char *access_list_str, afi_t afi, safi_t safi,
14050 char *errmsg, size_t errmsg_len)
718e3744 14051{
d62a17ae 14052 int ret;
d62a17ae 14053 struct prefix p;
9bcb3eef 14054 struct bgp_dest *dest;
d62a17ae 14055 struct bgp_distance *bdistance;
718e3744 14056
d62a17ae 14057 ret = str2prefix(ip_str, &p);
14058 if (ret == 0) {
37a87b8f 14059 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14060 return CMD_WARNING_CONFIG_FAILED;
14061 }
718e3744 14062
9bcb3eef
DS
14063 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14064 if (!dest) {
37a87b8f 14065 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 14066 return CMD_WARNING_CONFIG_FAILED;
14067 }
718e3744 14068
9bcb3eef 14069 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 14070
d62a17ae 14071 if (bdistance->distance != distance) {
37a87b8f
CS
14072 snprintf(errmsg, errmsg_len,
14073 "Distance does not match configured\n");
d62a17ae 14074 return CMD_WARNING_CONFIG_FAILED;
14075 }
718e3744 14076
0a22ddfb 14077 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14078 bgp_distance_free(bdistance);
718e3744 14079
9bcb3eef
DS
14080 bgp_dest_set_bgp_path_info(dest, NULL);
14081 bgp_dest_unlock_node(dest);
14082 bgp_dest_unlock_node(dest);
718e3744 14083
d62a17ae 14084 return CMD_SUCCESS;
718e3744 14085}
14086
718e3744 14087/* Apply BGP information to distance method. */
b8685f9b 14088uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14089 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14090{
9bcb3eef 14091 struct bgp_dest *dest;
801bb996 14092 struct prefix q = {0};
d62a17ae 14093 struct peer *peer;
14094 struct bgp_distance *bdistance;
14095 struct access_list *alist;
14096 struct bgp_static *bgp_static;
14097
14098 if (!bgp)
14099 return 0;
14100
40381db7 14101 peer = pinfo->peer;
d62a17ae 14102
7b7d48e5
DS
14103 if (pinfo->attr->distance)
14104 return pinfo->attr->distance;
14105
801bb996
CS
14106 /* Check source address.
14107 * Note: for aggregate route, peer can have unspec af type.
14108 */
14109 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14110 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14111 return 0;
14112
9bcb3eef
DS
14113 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14114 if (dest) {
14115 bdistance = bgp_dest_get_bgp_distance_info(dest);
14116 bgp_dest_unlock_node(dest);
d62a17ae 14117
14118 if (bdistance->access_list) {
14119 alist = access_list_lookup(afi, bdistance->access_list);
14120 if (alist
14121 && access_list_apply(alist, p) == FILTER_PERMIT)
14122 return bdistance->distance;
14123 } else
14124 return bdistance->distance;
718e3744 14125 }
718e3744 14126
d62a17ae 14127 /* Backdoor check. */
9bcb3eef
DS
14128 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14129 if (dest) {
14130 bgp_static = bgp_dest_get_bgp_static_info(dest);
14131 bgp_dest_unlock_node(dest);
718e3744 14132
d62a17ae 14133 if (bgp_static->backdoor) {
14134 if (bgp->distance_local[afi][safi])
14135 return bgp->distance_local[afi][safi];
14136 else
14137 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14138 }
718e3744 14139 }
718e3744 14140
d62a17ae 14141 if (peer->sort == BGP_PEER_EBGP) {
14142 if (bgp->distance_ebgp[afi][safi])
14143 return bgp->distance_ebgp[afi][safi];
14144 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14145 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14146 if (bgp->distance_ibgp[afi][safi])
14147 return bgp->distance_ibgp[afi][safi];
14148 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14149 } else {
14150 if (bgp->distance_local[afi][safi])
14151 return bgp->distance_local[afi][safi];
14152 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14153 }
718e3744 14154}
14155
a612fb77
DA
14156/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14157 * we should tell ZEBRA update the routes for a specific
14158 * AFI/SAFI to reflect changes in RIB.
14159 */
37a87b8f
CS
14160void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14161 safi_t update_safi)
a612fb77
DA
14162{
14163 afi_t afi;
14164 safi_t safi;
14165
14166 FOREACH_AFI_SAFI (afi, safi) {
14167 if (!bgp_fibupd_safi(safi))
14168 continue;
14169
8b54bc30
DA
14170 if (afi != update_afi && safi != update_safi)
14171 continue;
14172
14173 if (BGP_DEBUG(zebra, ZEBRA))
14174 zlog_debug(
14175 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14176 __func__, afi, safi);
14177 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14178 }
14179}
14180
37a87b8f
CS
14181DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14182 "distance bgp (1-255) (1-255) (1-255)",
14183 "Define an administrative distance\n"
14184 "BGP distance\n"
14185 "Distance for routes external to the AS\n"
14186 "Distance for routes internal to the AS\n"
14187 "Distance for local routes\n")
718e3744 14188{
d62a17ae 14189 int idx_number = 2;
14190 int idx_number_2 = 3;
14191 int idx_number_3 = 4;
14192 afi_t afi;
14193 safi_t safi;
37a87b8f 14194 char xpath[XPATH_MAXLEN];
718e3744 14195
d62a17ae 14196 afi = bgp_node_afi(vty);
14197 safi = bgp_node_safi(vty);
718e3744 14198
37a87b8f
CS
14199 snprintf(
14200 xpath, sizeof(xpath),
14201 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14202 yang_afi_safi_value2identity(afi, safi),
14203 bgp_afi_safi_get_container_str(afi, safi));
14204 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14205 snprintf(
14206 xpath, sizeof(xpath),
14207 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14208 yang_afi_safi_value2identity(afi, safi),
14209 bgp_afi_safi_get_container_str(afi, safi));
14210 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14211 argv[idx_number_2]->arg);
14212 snprintf(
14213 xpath, sizeof(xpath),
14214 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14215 yang_afi_safi_value2identity(afi, safi),
14216 bgp_afi_safi_get_container_str(afi, safi));
14217
14218 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14219 argv[idx_number_3]->arg);
14220
14221 return nb_cli_apply_changes(vty, NULL);
14222}
14223
14224DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14225 "no distance bgp [(1-255) (1-255) (1-255)]",
14226 NO_STR
14227 "Define an administrative distance\n"
14228 "BGP distance\n"
14229 "Distance for routes external to the AS\n"
14230 "Distance for routes internal to the AS\n"
14231 "Distance for local routes\n")
14232{
14233 afi_t afi;
14234 safi_t safi;
14235 char xpath[XPATH_MAXLEN];
14236
14237 afi = bgp_node_afi(vty);
14238 safi = bgp_node_safi(vty);
14239
14240 snprintf(
14241 xpath, sizeof(xpath),
14242 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14243 yang_afi_safi_value2identity(afi, safi),
14244 bgp_afi_safi_get_container_str(afi, safi));
14245 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14246 snprintf(
14247 xpath, sizeof(xpath),
14248 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14249 yang_afi_safi_value2identity(afi, safi),
14250 bgp_afi_safi_get_container_str(afi, safi));
14251 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14252 snprintf(
14253 xpath, sizeof(xpath),
14254 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14255 yang_afi_safi_value2identity(afi, safi),
14256 bgp_afi_safi_get_container_str(afi, safi));
14257
14258 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14259
14260 return nb_cli_apply_changes(vty, NULL);
718e3744 14261}
14262
37a87b8f
CS
14263void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14264 struct lyd_node *dnode,
14265 bool show_defaults)
718e3744 14266{
37a87b8f
CS
14267 uint8_t distance_ebgp, distance_ibgp, distance_local;
14268
14269 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14270 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14271 distance_local = yang_dnode_get_uint8(dnode, "./local");
14272
14273 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14274 distance_local);
14275}
14276
8cc7152a
CS
14277DEFPY_YANG(bgp_distance_source,
14278 bgp_distance_source_cmd,
14279 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14280 NO_STR
14281 "Define an administrative distance\n"
8cc7152a 14282 "Distance value\n"
e12affc1
SW
14283 "IPv4 source prefix\n"
14284 "IPv6 source prefix\n"
37a87b8f 14285 "Access list name\n")
718e3744 14286{
37a87b8f
CS
14287 afi_t afi;
14288 safi_t safi;
14289 char xpath[XPATH_MAXLEN];
14290
14291 afi = bgp_node_afi(vty);
14292 safi = bgp_node_safi(vty);
14293
8cc7152a
CS
14294 if (!no) {
14295 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14296 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14297 distance_str);
14298 if (acl)
14299 nb_cli_enqueue_change(vty,
14300 "./access-list-policy-export",
14301 NB_OP_CREATE, acl);
14302 else
14303 nb_cli_enqueue_change(vty,
14304 "./access-list-policy-export",
14305 NB_OP_DESTROY, NULL);
14306 } else {
14307 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14308 }
37a87b8f
CS
14309
14310 snprintf(
14311 xpath, sizeof(xpath),
14312 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14313 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14314 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14315
14316 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14317}
14318
37a87b8f
CS
14319void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14320 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14321{
14322 vty_out(vty, " distance %d %s %s\n",
14323 yang_dnode_get_uint8(dnode, "./distance"),
14324 yang_dnode_get_string(dnode, "./prefix"),
14325 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14326 ? yang_dnode_get_string(dnode,
14327 "./access-list-policy-export")
14328 : "");
14329}
14330
7c98d487
DA
14331DEFPY_YANG(
14332 bgp_dampening, bgp_dampening_cmd,
14333 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14334 NO_STR
14335 "BGP Specific commands\n"
14336 "Enable route-flap dampening\n"
14337 "Half-life time for the penalty\n"
14338 "Value to start reusing a route\n"
14339 "Value to start suppressing a route\n"
14340 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14341{
14342 afi_t afi;
14343 safi_t safi;
14344 char xpath[XPATH_MAXLEN];
718e3744 14345
37a87b8f
CS
14346 afi = bgp_node_afi(vty);
14347 safi = bgp_node_safi(vty);
14348
d9ce5113
CS
14349 if (!no) {
14350 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14351 if (argc == 6) {
14352 nb_cli_enqueue_change(vty, "./reach-decay",
14353 NB_OP_MODIFY, halflife_str);
14354 nb_cli_enqueue_change(vty, "./reuse-above",
14355 NB_OP_MODIFY, reuse_str);
14356 nb_cli_enqueue_change(vty, "./suppress-above",
14357 NB_OP_MODIFY, suppress_str);
14358 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14359 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14360 } if (argc == 3) {
14361 nb_cli_enqueue_change(vty, "./reach-decay",
14362 NB_OP_MODIFY, halflife_str);
14363 }
14364 } else {
14365 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14366 }
7ebe9748 14367
37a87b8f
CS
14368 snprintf(
14369 xpath, sizeof(xpath),
14370 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14371 yang_afi_safi_value2identity(afi, safi),
14372 bgp_afi_safi_get_container_str(afi, safi));
14373
14374 return nb_cli_apply_changes(vty, xpath);
718e3744 14375}
14376
37a87b8f
CS
14377void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14378 struct lyd_node *dnode,
14379 bool show_defaults)
718e3744 14380{
37a87b8f
CS
14381 if (!yang_dnode_get_bool(dnode, "./enable"))
14382 return;
14383
14384 int half = DEFAULT_HALF_LIFE * 60;
14385 int reuse = DEFAULT_REUSE;
14386 int suppress = DEFAULT_SUPPRESS;
14387 int max;
14388
14389 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14390 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14391 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14392 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14393
14394 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14395 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14396 vty_out(vty, " bgp dampening\n");
14397 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14398 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14399 vty_out(vty, " bgp dampening %u\n", half);
14400 else
14401 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14402 suppress, max);
718e3744 14403}
14404
718e3744 14405/* Display specified route of BGP table. */
d62a17ae 14406static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14407 const char *ip_str, afi_t afi, safi_t safi,
14408 struct prefix_rd *prd, int prefix_check)
14409{
14410 int ret;
14411 struct prefix match;
9bcb3eef
DS
14412 struct bgp_dest *dest;
14413 struct bgp_dest *rm;
40381db7
DS
14414 struct bgp_path_info *pi;
14415 struct bgp_path_info *pi_temp;
d62a17ae 14416 struct bgp *bgp;
14417 struct bgp_table *table;
14418
14419 /* BGP structure lookup. */
14420 if (view_name) {
14421 bgp = bgp_lookup_by_name(view_name);
14422 if (bgp == NULL) {
14423 vty_out(vty, "%% Can't find BGP instance %s\n",
14424 view_name);
14425 return CMD_WARNING;
14426 }
14427 } else {
14428 bgp = bgp_get_default();
14429 if (bgp == NULL) {
14430 vty_out(vty, "%% No BGP process is configured\n");
14431 return CMD_WARNING;
14432 }
718e3744 14433 }
718e3744 14434
d62a17ae 14435 /* Check IP address argument. */
14436 ret = str2prefix(ip_str, &match);
14437 if (!ret) {
14438 vty_out(vty, "%% address is malformed\n");
14439 return CMD_WARNING;
14440 }
718e3744 14441
d62a17ae 14442 match.family = afi2family(afi);
14443
14444 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14445 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14446 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14447 dest = bgp_route_next(dest)) {
14448 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14449
9bcb3eef 14450 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14451 continue;
9bcb3eef 14452 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14453 if (!table)
ea47320b
DL
14454 continue;
14455 if ((rm = bgp_node_match(table, &match)) == NULL)
14456 continue;
d62a17ae 14457
9bcb3eef 14458 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14459
ea47320b 14460 if (!prefix_check
b54892e0 14461 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14462 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14463 while (pi) {
14464 if (pi->extra && pi->extra->damp_info) {
14465 pi_temp = pi->next;
ea47320b 14466 bgp_damp_info_free(
40ec3340
DS
14467 &pi->extra->damp_info,
14468 &bgp->damp[afi][safi],
a935f597 14469 1, afi, safi);
40381db7 14470 pi = pi_temp;
ea47320b 14471 } else
40381db7 14472 pi = pi->next;
d62a17ae 14473 }
ea47320b
DL
14474 }
14475
9bcb3eef 14476 bgp_dest_unlock_node(rm);
d62a17ae 14477 }
14478 } else {
9bcb3eef 14479 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14480 != NULL) {
9bcb3eef 14481 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14482
d62a17ae 14483 if (!prefix_check
9bcb3eef
DS
14484 || dest_p->prefixlen == match.prefixlen) {
14485 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14486 while (pi) {
14487 if (pi->extra && pi->extra->damp_info) {
14488 pi_temp = pi->next;
c8ddbd48 14489 struct bgp_damp_info *bdi =
14490 pi->extra->damp_info;
14491 if (bdi->lastrecord
14492 == BGP_RECORD_UPDATE) {
14493 bgp_aggregate_increment(
14494 bgp,
14495 &bdi->dest->p,
14496 bdi->path,
14497 bdi->afi,
14498 bdi->safi);
14499 bgp_process(bgp,
14500 bdi->dest,
14501 bdi->afi,
14502 bdi->safi);
14503 }
d62a17ae 14504 bgp_damp_info_free(
40ec3340
DS
14505 &pi->extra->damp_info,
14506 &bgp->damp[afi][safi],
a935f597 14507 1, afi, safi);
40381db7 14508 pi = pi_temp;
d62a17ae 14509 } else
40381db7 14510 pi = pi->next;
d62a17ae 14511 }
14512 }
14513
9bcb3eef 14514 bgp_dest_unlock_node(dest);
d62a17ae 14515 }
14516 }
718e3744 14517
d62a17ae 14518 return CMD_SUCCESS;
718e3744 14519}
14520
14521DEFUN (clear_ip_bgp_dampening,
14522 clear_ip_bgp_dampening_cmd,
14523 "clear ip bgp dampening",
14524 CLEAR_STR
14525 IP_STR
14526 BGP_STR
14527 "Clear route flap dampening information\n")
14528{
40ec3340 14529 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14530 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14531 SAFI_UNICAST);
d62a17ae 14532 return CMD_SUCCESS;
718e3744 14533}
14534
14535DEFUN (clear_ip_bgp_dampening_prefix,
14536 clear_ip_bgp_dampening_prefix_cmd,
14537 "clear ip bgp dampening A.B.C.D/M",
14538 CLEAR_STR
14539 IP_STR
14540 BGP_STR
14541 "Clear route flap dampening information\n"
0c7b1b01 14542 "IPv4 prefix\n")
718e3744 14543{
d62a17ae 14544 int idx_ipv4_prefixlen = 4;
14545 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14546 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14547}
14548
14549DEFUN (clear_ip_bgp_dampening_address,
14550 clear_ip_bgp_dampening_address_cmd,
14551 "clear ip bgp dampening A.B.C.D",
14552 CLEAR_STR
14553 IP_STR
14554 BGP_STR
14555 "Clear route flap dampening information\n"
14556 "Network to clear damping information\n")
14557{
d62a17ae 14558 int idx_ipv4 = 4;
14559 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14560 SAFI_UNICAST, NULL, 0);
718e3744 14561}
14562
14563DEFUN (clear_ip_bgp_dampening_address_mask,
14564 clear_ip_bgp_dampening_address_mask_cmd,
14565 "clear ip bgp dampening A.B.C.D A.B.C.D",
14566 CLEAR_STR
14567 IP_STR
14568 BGP_STR
14569 "Clear route flap dampening information\n"
14570 "Network to clear damping information\n"
14571 "Network mask\n")
14572{
d62a17ae 14573 int idx_ipv4 = 4;
14574 int idx_ipv4_2 = 5;
14575 int ret;
14576 char prefix_str[BUFSIZ];
718e3744 14577
d62a17ae 14578 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14579 prefix_str, sizeof(prefix_str));
d62a17ae 14580 if (!ret) {
14581 vty_out(vty, "%% Inconsistent address and mask\n");
14582 return CMD_WARNING;
14583 }
718e3744 14584
d62a17ae 14585 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14586 NULL, 0);
718e3744 14587}
6b0655a2 14588
e3b78da8 14589static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14590{
14591 struct vty *vty = arg;
e3b78da8 14592 struct peer *peer = bucket->data;
825d9834
DS
14593 char buf[SU_ADDRSTRLEN];
14594
14595 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14596 sockunion2str(&peer->su, buf, sizeof(buf)));
14597}
14598
2a0e69ae
DS
14599DEFUN (show_bgp_listeners,
14600 show_bgp_listeners_cmd,
14601 "show bgp listeners",
14602 SHOW_STR
14603 BGP_STR
14604 "Display Listen Sockets and who created them\n")
14605{
14606 bgp_dump_listener_info(vty);
14607
14608 return CMD_SUCCESS;
14609}
14610
825d9834
DS
14611DEFUN (show_bgp_peerhash,
14612 show_bgp_peerhash_cmd,
14613 "show bgp peerhash",
14614 SHOW_STR
14615 BGP_STR
14616 "Display information about the BGP peerhash\n")
14617{
14618 struct list *instances = bm->bgp;
14619 struct listnode *node;
14620 struct bgp *bgp;
14621
14622 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14623 vty_out(vty, "BGP: %s\n", bgp->name);
14624 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14625 vty);
14626 }
14627
14628 return CMD_SUCCESS;
14629}
14630
587ff0fd 14631/* also used for encap safi */
2b791107
DL
14632static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14633 afi_t afi, safi_t safi)
d62a17ae 14634{
9bcb3eef
DS
14635 struct bgp_dest *pdest;
14636 struct bgp_dest *dest;
d62a17ae 14637 struct bgp_table *table;
b54892e0
DS
14638 const struct prefix *p;
14639 const struct prefix_rd *prd;
d62a17ae 14640 struct bgp_static *bgp_static;
14641 mpls_label_t label;
d62a17ae 14642 char rdbuf[RD_ADDRSTRLEN];
14643
14644 /* Network configuration. */
9bcb3eef
DS
14645 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14646 pdest = bgp_route_next(pdest)) {
14647 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14648 if (!table)
ea47320b 14649 continue;
d62a17ae 14650
9bcb3eef
DS
14651 for (dest = bgp_table_top(table); dest;
14652 dest = bgp_route_next(dest)) {
14653 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14654 if (bgp_static == NULL)
ea47320b 14655 continue;
d62a17ae 14656
9bcb3eef
DS
14657 p = bgp_dest_get_prefix(dest);
14658 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14659 pdest);
d62a17ae 14660
ea47320b 14661 /* "network" configuration display. */
06b9f471 14662 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14663 label = decode_label(&bgp_static->label);
14664
8228a9a7 14665 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14666 if (safi == SAFI_MPLS_VPN)
14667 vty_out(vty, " label %u", label);
14668
14669 if (bgp_static->rmap.name)
14670 vty_out(vty, " route-map %s",
14671 bgp_static->rmap.name);
e2a86ad9
DS
14672
14673 if (bgp_static->backdoor)
14674 vty_out(vty, " backdoor");
14675
ea47320b
DL
14676 vty_out(vty, "\n");
14677 }
14678 }
d62a17ae 14679}
14680
2b791107
DL
14681static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14682 afi_t afi, safi_t safi)
d62a17ae 14683{
9bcb3eef
DS
14684 struct bgp_dest *pdest;
14685 struct bgp_dest *dest;
d62a17ae 14686 struct bgp_table *table;
b54892e0
DS
14687 const struct prefix *p;
14688 const struct prefix_rd *prd;
d62a17ae 14689 struct bgp_static *bgp_static;
ff44f570 14690 char buf[PREFIX_STRLEN * 2];
d62a17ae 14691 char buf2[SU_ADDRSTRLEN];
14692 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14693 char esi_buf[ESI_BYTES];
d62a17ae 14694
14695 /* Network configuration. */
9bcb3eef
DS
14696 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14697 pdest = bgp_route_next(pdest)) {
14698 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14699 if (!table)
ea47320b 14700 continue;
d62a17ae 14701
9bcb3eef
DS
14702 for (dest = bgp_table_top(table); dest;
14703 dest = bgp_route_next(dest)) {
14704 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14705 if (bgp_static == NULL)
ea47320b 14706 continue;
d62a17ae 14707
ea47320b 14708 char *macrouter = NULL;
d62a17ae 14709
ea47320b
DL
14710 if (bgp_static->router_mac)
14711 macrouter = prefix_mac2str(
14712 bgp_static->router_mac, NULL, 0);
14713 if (bgp_static->eth_s_id)
0a50c248
AK
14714 esi_to_str(bgp_static->eth_s_id,
14715 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14716 p = bgp_dest_get_prefix(dest);
14717 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14718
ea47320b 14719 /* "network" configuration display. */
06b9f471 14720 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14721 if (p->u.prefix_evpn.route_type == 5) {
14722 char local_buf[PREFIX_STRLEN];
3714a385 14723 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14724 struct prefix_evpn *)p)
14725 ? AF_INET
14726 : AF_INET6;
3714a385 14727 inet_ntop(family,
14728 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14729 local_buf, PREFIX_STRLEN);
772270f3
QY
14730 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14731 p->u.prefix_evpn.prefix_addr
14732 .ip_prefix_length);
197cb530
PG
14733 } else {
14734 prefix2str(p, buf, sizeof(buf));
14735 }
ea47320b 14736
a4d82a8a
PZ
14737 if (bgp_static->gatewayIp.family == AF_INET
14738 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14739 inet_ntop(bgp_static->gatewayIp.family,
14740 &bgp_static->gatewayIp.u.prefix, buf2,
14741 sizeof(buf2));
ea47320b 14742 vty_out(vty,
7bcc8dac 14743 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14744 buf, rdbuf,
14745 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14746 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14747 macrouter);
14748
0a22ddfb 14749 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14750 }
14751 }
3da6fcd5
PG
14752}
14753
718e3744 14754/* Configuration of static route announcement and aggregate
14755 information. */
2b791107
DL
14756void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14757 safi_t safi)
d62a17ae 14758{
9bcb3eef 14759 struct bgp_dest *dest;
b54892e0 14760 const struct prefix *p;
d62a17ae 14761 struct bgp_static *bgp_static;
14762 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14763
2b791107
DL
14764 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14765 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14766 return;
14767 }
d62a17ae 14768
2b791107
DL
14769 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14770 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14771 return;
14772 }
d62a17ae 14773
14774 /* Network configuration. */
9bcb3eef
DS
14775 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14776 dest = bgp_route_next(dest)) {
14777 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14778 if (bgp_static == NULL)
ea47320b 14779 continue;
d62a17ae 14780
9bcb3eef 14781 p = bgp_dest_get_prefix(dest);
d62a17ae 14782
8228a9a7 14783 vty_out(vty, " network %pFX", p);
d62a17ae 14784
ea47320b
DL
14785 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14786 vty_out(vty, " label-index %u",
14787 bgp_static->label_index);
d62a17ae 14788
ea47320b
DL
14789 if (bgp_static->rmap.name)
14790 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14791
14792 if (bgp_static->backdoor)
14793 vty_out(vty, " backdoor");
718e3744 14794
ea47320b
DL
14795 vty_out(vty, "\n");
14796 }
14797
d62a17ae 14798 /* Aggregate-address configuration. */
9bcb3eef
DS
14799 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14800 dest = bgp_route_next(dest)) {
14801 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14802 if (bgp_aggregate == NULL)
ea47320b 14803 continue;
d62a17ae 14804
9bcb3eef 14805 p = bgp_dest_get_prefix(dest);
d62a17ae 14806
8228a9a7 14807 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14808
ea47320b
DL
14809 if (bgp_aggregate->as_set)
14810 vty_out(vty, " as-set");
d62a17ae 14811
ea47320b
DL
14812 if (bgp_aggregate->summary_only)
14813 vty_out(vty, " summary-only");
718e3744 14814
20894f50
DA
14815 if (bgp_aggregate->rmap.name)
14816 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14817
229757f1
DA
14818 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14819 vty_out(vty, " origin %s",
14820 bgp_origin2str(bgp_aggregate->origin));
14821
6aabb15d
RZ
14822 if (bgp_aggregate->match_med)
14823 vty_out(vty, " matching-MED-only");
14824
365ab2e7
RZ
14825 if (bgp_aggregate->suppress_map_name)
14826 vty_out(vty, " suppress-map %s",
14827 bgp_aggregate->suppress_map_name);
14828
ea47320b
DL
14829 vty_out(vty, "\n");
14830 }
d62a17ae 14831}
734b349e 14832
2b791107 14833void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14834 safi_t safi)
d62a17ae 14835{
9bcb3eef 14836 struct bgp_dest *dest;
d62a17ae 14837 struct bgp_distance *bdistance;
14838
14839 /* Distance configuration. */
14840 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14841 && bgp->distance_local[afi][safi]
14842 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14843 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14844 || bgp->distance_local[afi][safi]
14845 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14846 vty_out(vty, " distance bgp %d %d %d\n",
14847 bgp->distance_ebgp[afi][safi],
14848 bgp->distance_ibgp[afi][safi],
14849 bgp->distance_local[afi][safi]);
14850 }
734b349e 14851
9bcb3eef
DS
14852 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14853 dest = bgp_route_next(dest)) {
14854 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14855 if (bdistance != NULL)
56ca3b5b 14856 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14857 bdistance->distance, dest,
d62a17ae 14858 bdistance->access_list ? bdistance->access_list
14859 : "");
ca2e160d 14860 }
718e3744 14861}
14862
14863/* Allocate routing table structure and install commands. */
d62a17ae 14864void bgp_route_init(void)
14865{
14866 afi_t afi;
14867 safi_t safi;
14868
14869 /* Init BGP distance table. */
05c7a1cc 14870 FOREACH_AFI_SAFI (afi, safi)
960035b2 14871 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14872
14873 /* IPv4 BGP commands. */
14874 install_element(BGP_NODE, &bgp_table_map_cmd);
14875 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14876 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14877
554b3b10 14878 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14879
14880 /* IPv4 unicast configuration. */
14881 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14882 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14883 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14884
554b3b10 14885 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14886
14887 /* IPv4 multicast configuration. */
14888 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14889 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14890 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14891 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14892
14893 /* IPv4 labeled-unicast configuration. */
fb985e0c 14894 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14895 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14896
d62a17ae 14897 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14898 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14899 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14900 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14901 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14902 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14903 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14904 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14905
14906 install_element(VIEW_NODE,
14907 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14908 install_element(VIEW_NODE,
14909 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14910 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14911 install_element(VIEW_NODE,
14912 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14913#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14914 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14915#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14916 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14917 install_element(VIEW_NODE,
44c69747 14918 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14919
d62a17ae 14920 /* BGP dampening clear commands */
14921 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14922 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14923
d62a17ae 14924 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14925 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14926
14927 /* prefix count */
14928 install_element(ENABLE_NODE,
14929 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14930#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14931 install_element(ENABLE_NODE,
14932 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14933#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14934
d62a17ae 14935 /* New config IPv6 BGP commands. */
14936 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14937 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14938 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14939
554b3b10 14940 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14941
14942 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14943
fb985e0c
DA
14944 /* IPv6 labeled unicast address family. */
14945 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14946 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14947
d62a17ae 14948 install_element(BGP_NODE, &bgp_distance_cmd);
14949 install_element(BGP_NODE, &no_bgp_distance_cmd);
14950 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14951 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14952 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14953 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14954 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14955 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14956 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14957 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14958 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14959 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14960 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14961 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14962 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14963
ef5f4b23 14964 /* BGP dampening */
d9ce5113
CS
14965 install_element(BGP_NODE, &bgp_dampening_cmd);
14966 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14967 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14968 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14969 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14970 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14971 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14972
14973 /* Large Communities */
14974 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14975 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14976
14977 /* show bgp ipv4 flowspec detailed */
14978 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14979
2a0e69ae 14980 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14981 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14982}
14983
14984void bgp_route_finish(void)
14985{
14986 afi_t afi;
14987 safi_t safi;
14988
05c7a1cc
QY
14989 FOREACH_AFI_SAFI (afi, safi) {
14990 bgp_table_unlock(bgp_distance_table[afi][safi]);
14991 bgp_distance_table[afi][safi] = NULL;
14992 }
228da428 14993}