]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
build, vtysh: extract vtysh commands from .xref
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
70cd87ca 75#include "bgpd/bgp_orr.h"
6401252f 76#include "bgpd/bgp_trace.h"
fdeb5a81 77#include "bgpd/bgp_rpki.h"
718e3744 78
49e5a4a0 79#ifdef ENABLE_BGP_VNC
f8b6f499
LB
80#include "bgpd/rfapi/rfapi_backend.h"
81#include "bgpd/rfapi/vnc_import_bgp.h"
82#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 83#endif
aee875b5
PG
84#include "bgpd/bgp_encap_types.h"
85#include "bgpd/bgp_encap_tlv.h"
684a7227 86#include "bgpd/bgp_evpn.h"
0a50c248 87#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 88#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 89#include "bgpd/bgp_flowspec.h"
98a9dbc7 90#include "bgpd/bgp_flowspec_util.h"
45918cfb 91#include "bgpd/bgp_pbr.h"
65efcfce 92
e2a86ad9 93#include "bgpd/bgp_route_clippy.c"
aee875b5 94
7fd28dd2
PR
95DEFINE_HOOK(bgp_snmp_update_stats,
96 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 97 (rn, pi, added));
7fd28dd2 98
b5b99af8
DS
99DEFINE_HOOK(bgp_rpki_prefix_status,
100 (struct peer *peer, struct attr *attr,
101 const struct prefix *prefix),
8451921b 102 (peer, attr, prefix));
b5b99af8 103
718e3744 104/* Extern from bgp_dump.c */
dde72586
SH
105extern const char *bgp_origin_str[];
106extern const char *bgp_origin_long_str[];
3742de8d 107
b7d08f5a 108/* PMSI strings. */
109#define PMSI_TNLTYPE_STR_NO_INFO "No info"
110#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
111static const struct message bgp_pmsi_tnltype_str[] = {
112 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
113 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
114 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
115 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
116 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
117 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
118 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
119 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 120 {0}
121};
b7d08f5a 122
9df8b37c 123#define VRFID_NONE_STR "-"
46aeabed 124#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 125
4a11bf2c 126DEFINE_HOOK(bgp_process,
9bcb3eef
DS
127 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
128 struct peer *peer, bool withdraw),
8451921b 129 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 130
4056a5f6
RZ
131/** Test if path is suppressed. */
132static bool bgp_path_suppressed(struct bgp_path_info *pi)
133{
134 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
135 return false;
136
137 return listcount(pi->extra->aggr_suppressors) > 0;
138}
4a11bf2c 139
9bcb3eef 140struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 141 safi_t safi, const struct prefix *p,
d62a17ae 142 struct prefix_rd *prd)
143{
9bcb3eef
DS
144 struct bgp_dest *dest;
145 struct bgp_dest *pdest = NULL;
d62a17ae 146
147 assert(table);
d62a17ae 148
149 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
150 || (safi == SAFI_EVPN)) {
9bcb3eef 151 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 152
9bcb3eef
DS
153 if (!bgp_dest_has_bgp_path_info_data(pdest))
154 bgp_dest_set_bgp_table_info(
155 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 156 else
9bcb3eef
DS
157 bgp_dest_unlock_node(pdest);
158 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 159 }
718e3744 160
9bcb3eef 161 dest = bgp_node_get(table, p);
718e3744 162
d62a17ae 163 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
164 || (safi == SAFI_EVPN))
9bcb3eef 165 dest->pdest = pdest;
718e3744 166
9bcb3eef 167 return dest;
718e3744 168}
6b0655a2 169
9bcb3eef 170struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 171 safi_t safi, const struct prefix *p,
d62a17ae 172 struct prefix_rd *prd)
128ea8ab 173{
9bcb3eef
DS
174 struct bgp_dest *dest;
175 struct bgp_dest *pdest = NULL;
128ea8ab 176
d62a17ae 177 if (!table)
178 return NULL;
128ea8ab 179
d62a17ae 180 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
181 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
182 pdest = bgp_node_lookup(table, (struct prefix *)prd);
183 if (!pdest)
d62a17ae 184 return NULL;
128ea8ab 185
9bcb3eef
DS
186 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
187 bgp_dest_unlock_node(pdest);
d62a17ae 188 return NULL;
189 }
128ea8ab 190
9bcb3eef 191 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 192 }
128ea8ab 193
9bcb3eef 194 dest = bgp_node_lookup(table, p);
128ea8ab 195
9bcb3eef 196 return dest;
128ea8ab 197}
198
18ee8310
DS
199/* Allocate bgp_path_info_extra */
200static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 201{
4b7e6066
DS
202 struct bgp_path_info_extra *new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
204 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
205 new->label[0] = MPLS_INVALID_LABEL;
206 new->num_labels = 0;
3e3708cb
PG
207 new->bgp_fs_pbr = NULL;
208 new->bgp_fs_iprule = NULL;
d62a17ae 209 return new;
fb982c25
PJ
210}
211
a2e219fe 212void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 213{
4b7e6066 214 struct bgp_path_info_extra *e;
d62a17ae 215
c93a3b77
DS
216 if (!extra || !*extra)
217 return;
d62a17ae 218
c93a3b77 219 e = *extra;
4538f895 220 if (e->damp_info)
b4f7f45b
IR
221 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
222 e->damp_info->safi);
4538f895 223
c93a3b77
DS
224 e->damp_info = NULL;
225 if (e->parent) {
40381db7 226 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 227
40381db7 228 if (bpi->net) {
0e70e6c8
DL
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
232 *
40381db7
DS
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
0e70e6c8
DL
236 */
237 unsigned refcount;
238
40381db7 239 bpi = bgp_path_info_lock(bpi);
c10e14e9 240 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 241 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 242 if (!refcount)
40381db7
DS
243 bpi->net = NULL;
244 bgp_path_info_unlock(bpi);
0e70e6c8 245 }
18ee8310 246 bgp_path_info_unlock(e->parent);
c93a3b77 247 e->parent = NULL;
d62a17ae 248 }
c93a3b77
DS
249
250 if (e->bgp_orig)
251 bgp_unlock(e->bgp_orig);
c26edcda 252
4cd690ae
PG
253 if (e->peer_orig)
254 peer_unlock(e->peer_orig);
255
ff3bf9a4
DS
256 if (e->aggr_suppressors)
257 list_delete(&e->aggr_suppressors);
258
60605cbc
AK
259 if (e->mh_info)
260 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 261
ce3c0614
PG
262 if ((*extra)->bgp_fs_iprule)
263 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 264 if ((*extra)->bgp_fs_pbr)
6a154c88 265 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 266 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
267}
268
18ee8310
DS
269/* Get bgp_path_info extra information for the given bgp_path_info, lazy
270 * allocated if required.
fb982c25 271 */
40381db7 272struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 273{
40381db7
DS
274 if (!pi->extra)
275 pi->extra = bgp_path_info_extra_new();
276 return pi->extra;
fb982c25
PJ
277}
278
718e3744 279/* Free bgp route information. */
9b6d8fcf 280static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 281{
05864da7 282 bgp_attr_unintern(&path->attr);
fb018d25 283
9b6d8fcf
DS
284 bgp_unlink_nexthop(path);
285 bgp_path_info_extra_free(&path->extra);
286 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
287 if (path->net)
288 bgp_addpath_free_info_data(&path->tx_addpath,
289 &path->net->tx_addpath);
718e3744 290
9b6d8fcf 291 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 292
9b6d8fcf 293 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 294}
295
9b6d8fcf 296struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 297{
9b6d8fcf
DS
298 path->lock++;
299 return path;
200df115 300}
301
9b6d8fcf 302struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 303{
9b6d8fcf
DS
304 assert(path && path->lock > 0);
305 path->lock--;
d62a17ae 306
9b6d8fcf 307 if (path->lock == 0) {
9b6d8fcf 308 bgp_path_info_free(path);
d62a17ae 309 return NULL;
310 }
200df115 311
9b6d8fcf 312 return path;
200df115 313}
314
f009ff26 315/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 316static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 317{
318 struct peer *peer;
319 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 320 bool set_flag = false;
f009ff26 321 struct bgp *bgp = NULL;
322 struct bgp_table *table = NULL;
323 afi_t afi = 0;
324 safi_t safi = 0;
f009ff26 325
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
328 */
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 330 return 0;
331
9bcb3eef 332 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 333 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 334 zlog_debug(
56ca3b5b
DL
335 "Route %pBD is in workqueue and being processed, not deferred.",
336 dest);
b54892e0 337
5f9c1aa2 338 return 0;
339 }
340
9bcb3eef 341 table = bgp_dest_table(dest);
f009ff26 342 if (table) {
343 bgp = table->bgp;
344 afi = table->afi;
345 safi = table->safi;
346 }
347
9bcb3eef 348 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 349 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
351 continue;
352
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
355 */
36235319
QY
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
357 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 358 set_flag = true;
f009ff26 359 } else {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
362 */
363 peer = old_pi->peer;
36235319
QY
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
365 && BGP_PEER_RESTARTING_MODE(peer)
366 && (old_pi
367 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 }
370 }
371 if (set_flag)
372 break;
373 }
374
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
376 * is active
377 */
2ba1fe69 378 if (set_flag && table) {
f009ff26 379 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
380 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
381 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 382 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 383 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
384 zlog_debug("DEFER route %pBD, dest %p", dest,
385 dest);
f009ff26 386 return 0;
387 }
388 }
389 return -1;
390}
391
9bcb3eef 392void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 393{
4b7e6066 394 struct bgp_path_info *top;
718e3744 395
9bcb3eef 396 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 397
6f94b685 398 pi->next = top;
40381db7 399 pi->prev = NULL;
d62a17ae 400 if (top)
40381db7 401 top->prev = pi;
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 403
40381db7 404 bgp_path_info_lock(pi);
9bcb3eef 405 bgp_dest_lock_node(dest);
40381db7 406 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 407 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 408 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 409}
410
d62a17ae 411/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 412 completion callback *only* */
9bcb3eef 413void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 414{
40381db7
DS
415 if (pi->next)
416 pi->next->prev = pi->prev;
417 if (pi->prev)
418 pi->prev->next = pi->next;
d62a17ae 419 else
9bcb3eef 420 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 421
40381db7
DS
422 bgp_path_info_mpath_dequeue(pi);
423 bgp_path_info_unlock(pi);
7fd28dd2 424 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 425 bgp_dest_unlock_node(dest);
718e3744 426}
427
9bcb3eef 428void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 429{
9bcb3eef 430 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 431 /* set of previous already took care of pcount */
40381db7 432 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 433}
434
18ee8310 435/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
436 called when a route is deleted and then quickly re-added before the
437 deletion has been processed */
9bcb3eef 438void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 439{
9bcb3eef 440 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 441 /* unset of previous already took care of pcount */
40381db7 442 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
443}
444
d62a17ae 445/* Adjust pcount as required */
9bcb3eef 446static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 447{
d62a17ae 448 struct bgp_table *table;
67174041 449
9bcb3eef 450 assert(dest && bgp_dest_table(dest));
40381db7 451 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 452
9bcb3eef 453 table = bgp_dest_table(dest);
67174041 454
40381db7 455 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 456 return;
457
40381db7
DS
458 if (!BGP_PATH_COUNTABLE(pi)
459 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 460
40381db7 461 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 462
463 /* slight hack, but more robust against errors. */
40381db7
DS
464 if (pi->peer->pcount[table->afi][table->safi])
465 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 466 else
450971aa 467 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 468 "Asked to decrement 0 prefix count for peer");
40381db7
DS
469 } else if (BGP_PATH_COUNTABLE(pi)
470 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
471 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
472 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 473 }
1a392d46
PJ
474}
475
40381db7
DS
476static int bgp_label_index_differs(struct bgp_path_info *pi1,
477 struct bgp_path_info *pi2)
28d58fd7 478{
40381db7 479 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 480}
1a392d46 481
18ee8310 482/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
483 * This is here primarily to keep prefix-count in check.
484 */
9bcb3eef 485void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 486 uint32_t flag)
1a392d46 487{
40381db7 488 SET_FLAG(pi->flags, flag);
d62a17ae 489
490 /* early bath if we know it's not a flag that changes countability state
491 */
492 if (!CHECK_FLAG(flag,
1defdda8 493 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 494 return;
495
9bcb3eef 496 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
497}
498
9bcb3eef 499void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 500 uint32_t flag)
1a392d46 501{
40381db7 502 UNSET_FLAG(pi->flags, flag);
d62a17ae 503
504 /* early bath if we know it's not a flag that changes countability state
505 */
506 if (!CHECK_FLAG(flag,
1defdda8 507 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 508 return;
509
9bcb3eef 510 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
511}
512
718e3744 513/* Get MED value. If MED value is missing and "bgp bestpath
514 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 515static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 516{
517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
518 return attr->med;
519 else {
892fedb6 520 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 521 return BGP_MED_MAX;
522 else
523 return 0;
524 }
718e3744 525}
526
7533cad7
QY
527void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
528 size_t buf_len)
2ec1e66f 529{
40381db7 530 if (pi->addpath_rx_id)
7533cad7
QY
531 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
532 pi->peer->host, pi->addpath_rx_id);
d62a17ae 533 else
7533cad7 534 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 535}
9fbdd100 536
da0c0ef7
KM
537
538/*
539 * Get the ultimate path info.
540 */
541struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
542{
543 struct bgp_path_info *bpi_ultimate;
544
545 if (info->sub_type != BGP_ROUTE_IMPORTED)
546 return info;
547
548 for (bpi_ultimate = info;
549 bpi_ultimate->extra && bpi_ultimate->extra->parent;
550 bpi_ultimate = bpi_ultimate->extra->parent)
551 ;
552
553 return bpi_ultimate;
554}
555
d62a17ae 556/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
557 */
18ee8310
DS
558static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
559 struct bgp_path_info *exist, int *paths_eq,
560 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
561 char *pfx_buf, afi_t afi, safi_t safi,
562 enum bgp_path_selection_reason *reason)
d62a17ae 563{
5df26422 564 const struct prefix *new_p;
70cd87ca 565 struct prefix exist_p;
d62a17ae 566 struct attr *newattr, *existattr;
3061acc2
DA
567 enum bgp_peer_sort new_sort;
568 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
569 uint32_t new_pref;
570 uint32_t exist_pref;
571 uint32_t new_med;
572 uint32_t exist_med;
573 uint32_t new_weight;
574 uint32_t exist_weight;
d62a17ae 575 uint32_t newm, existm;
576 struct in_addr new_id;
577 struct in_addr exist_id;
578 int new_cluster;
579 int exist_cluster;
580 int internal_as_route;
581 int confed_as_route;
04d14c8b 582 int ret = 0;
ee88563a
JM
583 int igp_metric_ret = 0;
584 int peer_sort_ret = -1;
d62a17ae 585 char new_buf[PATH_ADDPATH_STR_BUFFER];
586 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
587 uint32_t new_mm_seq;
588 uint32_t exist_mm_seq;
6d8c603a 589 int nh_cmp;
d071f237
AK
590 esi_t *exist_esi;
591 esi_t *new_esi;
592 bool same_esi;
593 bool old_proxy;
594 bool new_proxy;
33c6e933 595 bool new_origin, exist_origin;
da0c0ef7 596 struct bgp_path_info *bpi_ultimate;
d62a17ae 597
70cd87ca
MK
598 struct bgp_orr_group *orr_group = NULL;
599 struct listnode *node;
600 struct bgp_orr_igp_metric *igp_metric = NULL;
601 struct list *orr_group_igp_metric_info = NULL;
602
d62a17ae 603 *paths_eq = 0;
604
605 /* 0. Null check. */
606 if (new == NULL) {
fdf81fa0 607 *reason = bgp_path_selection_none;
d62a17ae 608 if (debug)
609 zlog_debug("%s: new is NULL", pfx_buf);
610 return 0;
611 }
2ec1e66f 612
da0c0ef7
KM
613 if (debug) {
614 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
615 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 616 sizeof(new_buf));
da0c0ef7 617 }
718e3744 618
d62a17ae 619 if (exist == NULL) {
fdf81fa0 620 *reason = bgp_path_selection_first;
d62a17ae 621 if (debug)
4378495a
DS
622 zlog_debug("%s(%s): %s is the initial bestpath",
623 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 624 return 1;
625 }
2ec1e66f 626
d62a17ae 627 if (debug) {
da0c0ef7
KM
628 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
629 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 630 sizeof(exist_buf));
4378495a
DS
631 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
632 pfx_buf, bgp->name_pretty, new_buf, new->flags,
633 exist_buf, exist->flags);
d62a17ae 634 }
8ff56318 635
d62a17ae 636 newattr = new->attr;
637 existattr = exist->attr;
638
1479ed2f
DA
639 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
640 * Capability" to a neighbor MUST perform the following upon receiving
641 * a route from that neighbor with the "LLGR_STALE" community, or upon
642 * attaching the "LLGR_STALE" community itself per Section 4.2:
643 *
644 * Treat the route as the least-preferred in route selection (see
645 * below). See the Risks of Depreferencing Routes section (Section 5.2)
646 * for a discussion of potential risks inherent in doing this.
647 */
9a706b42
DA
648 if (bgp_attr_get_community(newattr) &&
649 community_include(bgp_attr_get_community(newattr),
650 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to LLGR_STALE community",
654 pfx_buf, new_buf, exist_buf);
655 return 0;
656 }
657
9a706b42
DA
658 if (bgp_attr_get_community(existattr) &&
659 community_include(bgp_attr_get_community(existattr),
660 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to LLGR_STALE community",
664 pfx_buf, new_buf, exist_buf);
665 return 1;
666 }
667
5df26422
NS
668 new_p = bgp_dest_get_prefix(new->net);
669
d62a17ae 670 /* For EVPN routes, we cannot just go by local vs remote, we have to
671 * look at the MAC mobility sequence number, if present.
672 */
5df26422
NS
673 if ((safi == SAFI_EVPN)
674 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 675 /* This is an error condition described in RFC 7432 Section
676 * 15.2. The RFC
677 * states that in this scenario "the PE MUST alert the operator"
678 * but it
679 * does not state what other action to take. In order to provide
680 * some
681 * consistency in this scenario we are going to prefer the path
682 * with the
683 * sticky flag.
684 */
685 if (newattr->sticky != existattr->sticky) {
686 if (!debug) {
5df26422
NS
687 prefix2str(new_p, pfx_buf,
688 sizeof(*pfx_buf)
689 * PREFIX2STR_BUFFER);
18ee8310 690 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
691 new, new_buf, sizeof(new_buf));
692 bgp_path_info_path_with_addpath_rx_str(
693 exist, exist_buf, sizeof(exist_buf));
d62a17ae 694 }
695
696 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 697 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
698 if (debug)
699 zlog_debug(
700 "%s: %s wins over %s due to sticky MAC flag",
701 pfx_buf, new_buf, exist_buf);
d62a17ae 702 return 1;
703 }
704
705 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 706 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
707 if (debug)
708 zlog_debug(
709 "%s: %s loses to %s due to sticky MAC flag",
710 pfx_buf, new_buf, exist_buf);
d62a17ae 711 return 0;
712 }
713 }
128ea8ab 714
d071f237
AK
715 new_esi = bgp_evpn_attr_get_esi(newattr);
716 exist_esi = bgp_evpn_attr_get_esi(existattr);
717 if (bgp_evpn_is_esi_valid(new_esi) &&
718 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
719 same_esi = true;
720 } else {
721 same_esi = false;
722 }
723
724 /* If both paths have the same non-zero ES and
725 * one path is local it wins.
726 * PS: Note the local path wins even if the remote
727 * has the higher MM seq. The local path's
728 * MM seq will be fixed up to match the highest
729 * rem seq, subsequently.
730 */
731 if (same_esi) {
732 char esi_buf[ESI_STR_LEN];
733
734 if (bgp_evpn_is_path_local(bgp, new)) {
735 *reason = bgp_path_selection_evpn_local_path;
736 if (debug)
737 zlog_debug(
738 "%s: %s wins over %s as ES %s is same and local",
739 pfx_buf, new_buf, exist_buf,
740 esi_to_str(new_esi, esi_buf,
741 sizeof(esi_buf)));
742 return 1;
743 }
744 if (bgp_evpn_is_path_local(bgp, exist)) {
745 *reason = bgp_path_selection_evpn_local_path;
746 if (debug)
747 zlog_debug(
748 "%s: %s loses to %s as ES %s is same and local",
749 pfx_buf, new_buf, exist_buf,
750 esi_to_str(new_esi, esi_buf,
751 sizeof(esi_buf)));
752 return 0;
753 }
754 }
755
d62a17ae 756 new_mm_seq = mac_mobility_seqnum(newattr);
757 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 758
d62a17ae 759 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 760 *reason = bgp_path_selection_evpn_seq;
d62a17ae 761 if (debug)
762 zlog_debug(
763 "%s: %s wins over %s due to MM seq %u > %u",
764 pfx_buf, new_buf, exist_buf, new_mm_seq,
765 exist_mm_seq);
766 return 1;
767 }
8ff56318 768
d62a17ae 769 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 770 *reason = bgp_path_selection_evpn_seq;
d62a17ae 771 if (debug)
772 zlog_debug(
773 "%s: %s loses to %s due to MM seq %u < %u",
774 pfx_buf, new_buf, exist_buf, new_mm_seq,
775 exist_mm_seq);
776 return 0;
777 }
6d8c603a 778
d071f237
AK
779 /* if the sequence numbers and ESI are the same and one path
780 * is non-proxy it wins (over proxy)
781 */
782 new_proxy = bgp_evpn_attr_is_proxy(newattr);
783 old_proxy = bgp_evpn_attr_is_proxy(existattr);
784 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
785 old_proxy != new_proxy) {
786 if (!new_proxy) {
787 *reason = bgp_path_selection_evpn_non_proxy;
788 if (debug)
789 zlog_debug(
790 "%s: %s wins over %s, same seq/es and non-proxy",
791 pfx_buf, new_buf, exist_buf);
792 return 1;
793 }
794
795 *reason = bgp_path_selection_evpn_non_proxy;
796 if (debug)
797 zlog_debug(
798 "%s: %s loses to %s, same seq/es and non-proxy",
799 pfx_buf, new_buf, exist_buf);
800 return 0;
801 }
802
6d8c603a
AK
803 /*
804 * if sequence numbers are the same path with the lowest IP
805 * wins
806 */
807 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
808 if (nh_cmp < 0) {
fdf81fa0 809 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
810 if (debug)
811 zlog_debug(
23d0a753 812 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 813 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 814 &new->attr->nexthop);
6d8c603a
AK
815 return 1;
816 }
817 if (nh_cmp > 0) {
fdf81fa0 818 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
819 if (debug)
820 zlog_debug(
23d0a753 821 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 822 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 823 &new->attr->nexthop);
6d8c603a
AK
824 return 0;
825 }
d62a17ae 826 }
9fbdd100 827
d62a17ae 828 /* 1. Weight check. */
d62a17ae 829 new_weight = newattr->weight;
830 exist_weight = existattr->weight;
8ff56318 831
d62a17ae 832 if (new_weight > exist_weight) {
fdf81fa0 833 *reason = bgp_path_selection_weight;
d62a17ae 834 if (debug)
835 zlog_debug("%s: %s wins over %s due to weight %d > %d",
836 pfx_buf, new_buf, exist_buf, new_weight,
837 exist_weight);
838 return 1;
839 }
718e3744 840
d62a17ae 841 if (new_weight < exist_weight) {
fdf81fa0 842 *reason = bgp_path_selection_weight;
d62a17ae 843 if (debug)
844 zlog_debug("%s: %s loses to %s due to weight %d < %d",
845 pfx_buf, new_buf, exist_buf, new_weight,
846 exist_weight);
847 return 0;
848 }
9fbdd100 849
d62a17ae 850 /* 2. Local preference check. */
851 new_pref = exist_pref = bgp->default_local_pref;
852
853 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
854 new_pref = newattr->local_pref;
855 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
856 exist_pref = existattr->local_pref;
857
858 if (new_pref > exist_pref) {
fdf81fa0 859 *reason = bgp_path_selection_local_pref;
d62a17ae 860 if (debug)
861 zlog_debug(
862 "%s: %s wins over %s due to localpref %d > %d",
863 pfx_buf, new_buf, exist_buf, new_pref,
864 exist_pref);
865 return 1;
866 }
718e3744 867
d62a17ae 868 if (new_pref < exist_pref) {
fdf81fa0 869 *reason = bgp_path_selection_local_pref;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s loses to %s due to localpref %d < %d",
873 pfx_buf, new_buf, exist_buf, new_pref,
874 exist_pref);
875 return 0;
876 }
9fbdd100 877
46dbf9d0
DA
878 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
879 * extensions defined in this document, the following step is inserted
880 * after the LOCAL_PREF comparison step in the BGP decision process:
881 * When comparing a pair of routes for a BGP destination, the
882 * route with the ACCEPT_OWN community attached is preferred over
883 * the route that does not have the community.
884 * This extra step MUST only be invoked during the best path selection
885 * process of VPN-IP routes.
886 */
887 if (safi == SAFI_MPLS_VPN &&
888 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
889 CHECK_FLAG(exist->peer->af_flags[afi][safi],
890 PEER_FLAG_ACCEPT_OWN))) {
891 bool new_accept_own = false;
892 bool exist_accept_own = false;
893 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
894
895 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
896 new_accept_own = community_include(
897 bgp_attr_get_community(newattr), accept_own);
898 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
899 exist_accept_own = community_include(
900 bgp_attr_get_community(existattr), accept_own);
901
902 if (new_accept_own && !exist_accept_own) {
903 *reason = bgp_path_selection_accept_own;
904 if (debug)
905 zlog_debug(
906 "%s: %s wins over %s due to accept-own",
907 pfx_buf, new_buf, exist_buf);
908 return 1;
909 }
910
911 if (!new_accept_own && exist_accept_own) {
912 *reason = bgp_path_selection_accept_own;
913 if (debug)
914 zlog_debug(
915 "%s: %s loses to %s due to accept-own",
916 pfx_buf, new_buf, exist_buf);
917 return 0;
918 }
919 }
920
d62a17ae 921 /* 3. Local route check. We prefer:
922 * - BGP_ROUTE_STATIC
923 * - BGP_ROUTE_AGGREGATE
924 * - BGP_ROUTE_REDISTRIBUTE
925 */
33c6e933
DS
926 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
927 new->sub_type == BGP_ROUTE_IMPORTED);
928 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
929 exist->sub_type == BGP_ROUTE_IMPORTED);
930
931 if (new_origin && !exist_origin) {
fdf81fa0 932 *reason = bgp_path_selection_local_route;
d62a17ae 933 if (debug)
934 zlog_debug(
935 "%s: %s wins over %s due to preferred BGP_ROUTE type",
936 pfx_buf, new_buf, exist_buf);
937 return 1;
938 }
718e3744 939
33c6e933 940 if (!new_origin && exist_origin) {
fdf81fa0 941 *reason = bgp_path_selection_local_route;
d62a17ae 942 if (debug)
943 zlog_debug(
944 "%s: %s loses to %s due to preferred BGP_ROUTE type",
945 pfx_buf, new_buf, exist_buf);
946 return 0;
6811845b 947 }
718e3744 948
da0c0ef7
KM
949 /* Here if these are imported routes then get ultimate pi for
950 * path compare.
951 */
952 new = bgp_get_imported_bpi_ultimate(new);
953 exist = bgp_get_imported_bpi_ultimate(exist);
954 newattr = new->attr;
955 existattr = exist->attr;
956
d62a17ae 957 /* 4. AS path length check. */
892fedb6 958 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 959 int exist_hops = aspath_count_hops(existattr->aspath);
960 int exist_confeds = aspath_count_confeds(existattr->aspath);
961
892fedb6 962 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 963 int aspath_hops;
964
965 aspath_hops = aspath_count_hops(newattr->aspath);
966 aspath_hops += aspath_count_confeds(newattr->aspath);
967
968 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 969 *reason = bgp_path_selection_confed_as_path;
d62a17ae 970 if (debug)
971 zlog_debug(
972 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
973 pfx_buf, new_buf, exist_buf,
974 aspath_hops,
975 (exist_hops + exist_confeds));
976 return 1;
977 }
978
979 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 980 *reason = bgp_path_selection_confed_as_path;
d62a17ae 981 if (debug)
982 zlog_debug(
983 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
984 pfx_buf, new_buf, exist_buf,
985 aspath_hops,
986 (exist_hops + exist_confeds));
987 return 0;
988 }
989 } else {
990 int newhops = aspath_count_hops(newattr->aspath);
991
992 if (newhops < exist_hops) {
fdf81fa0 993 *reason = bgp_path_selection_as_path;
d62a17ae 994 if (debug)
995 zlog_debug(
996 "%s: %s wins over %s due to aspath hopcount %d < %d",
997 pfx_buf, new_buf, exist_buf,
998 newhops, exist_hops);
999 return 1;
1000 }
1001
1002 if (newhops > exist_hops) {
fdf81fa0 1003 *reason = bgp_path_selection_as_path;
d62a17ae 1004 if (debug)
1005 zlog_debug(
1006 "%s: %s loses to %s due to aspath hopcount %d > %d",
1007 pfx_buf, new_buf, exist_buf,
1008 newhops, exist_hops);
1009 return 0;
1010 }
1011 }
1012 }
9fbdd100 1013
d62a17ae 1014 /* 5. Origin check. */
1015 if (newattr->origin < existattr->origin) {
fdf81fa0 1016 *reason = bgp_path_selection_origin;
d62a17ae 1017 if (debug)
1018 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1019 pfx_buf, new_buf, exist_buf,
1020 bgp_origin_long_str[newattr->origin],
1021 bgp_origin_long_str[existattr->origin]);
1022 return 1;
1023 }
718e3744 1024
d62a17ae 1025 if (newattr->origin > existattr->origin) {
fdf81fa0 1026 *reason = bgp_path_selection_origin;
d62a17ae 1027 if (debug)
1028 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1029 pfx_buf, new_buf, exist_buf,
1030 bgp_origin_long_str[newattr->origin],
1031 bgp_origin_long_str[existattr->origin]);
1032 return 0;
1033 }
718e3744 1034
d62a17ae 1035 /* 6. MED check. */
1036 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1037 && aspath_count_hops(existattr->aspath) == 0);
1038 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1039 && aspath_count_confeds(existattr->aspath) > 0
1040 && aspath_count_hops(newattr->aspath) == 0
1041 && aspath_count_hops(existattr->aspath) == 0);
1042
892fedb6
DA
1043 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1044 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1045 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1046 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1047 || internal_as_route) {
1048 new_med = bgp_med_value(new->attr, bgp);
1049 exist_med = bgp_med_value(exist->attr, bgp);
1050
1051 if (new_med < exist_med) {
fdf81fa0 1052 *reason = bgp_path_selection_med;
d62a17ae 1053 if (debug)
1054 zlog_debug(
1055 "%s: %s wins over %s due to MED %d < %d",
1056 pfx_buf, new_buf, exist_buf, new_med,
1057 exist_med);
1058 return 1;
1059 }
8ff56318 1060
d62a17ae 1061 if (new_med > exist_med) {
fdf81fa0 1062 *reason = bgp_path_selection_med;
d62a17ae 1063 if (debug)
1064 zlog_debug(
1065 "%s: %s loses to %s due to MED %d > %d",
1066 pfx_buf, new_buf, exist_buf, new_med,
1067 exist_med);
1068 return 0;
1069 }
1070 }
9fbdd100 1071
d62a17ae 1072 /* 7. Peer type check. */
1073 new_sort = new->peer->sort;
1074 exist_sort = exist->peer->sort;
1075
1076 if (new_sort == BGP_PEER_EBGP
1077 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1078 *reason = bgp_path_selection_peer;
d62a17ae 1079 if (debug)
1080 zlog_debug(
1081 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1082 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1083 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1084 return 1;
1085 peer_sort_ret = 1;
d62a17ae 1086 }
718e3744 1087
d62a17ae 1088 if (exist_sort == BGP_PEER_EBGP
1089 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1090 *reason = bgp_path_selection_peer;
d62a17ae 1091 if (debug)
1092 zlog_debug(
1093 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1094 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1095 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1096 return 0;
1097 peer_sort_ret = 0;
d62a17ae 1098 }
8ff56318 1099
d62a17ae 1100 /* 8. IGP metric check. */
1101 newm = existm = 0;
8ff56318 1102
d62a17ae 1103 if (new->extra)
1104 newm = new->extra->igpmetric;
1105 if (exist->extra)
1106 existm = exist->extra->igpmetric;
9fbdd100 1107
70cd87ca
MK
1108 if (new->peer->orr_group_name[afi][safi]) {
1109 ret = str2prefix(new->peer->host, &exist_p);
1110 orr_group = bgp_orr_group_lookup_by_name(
1111 bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
1112 if (orr_group) {
1113 orr_group_igp_metric_info = orr_group->igp_metric_info;
1114 if (orr_group_igp_metric_info) {
1115 for (ALL_LIST_ELEMENTS_RO(
1116 orr_group_igp_metric_info, node,
1117 igp_metric)) {
1118 if (ret &&
1119 prefix_cmp(&exist_p,
1120 &igp_metric->prefix) ==
1121 0) {
1122 newm = igp_metric->igp_metric;
1123 break;
1124 }
1125 }
1126 }
1127 }
1128 }
1129 if (exist->peer->orr_group_name[afi][safi]) {
1130 ret = str2prefix(exist->peer->host, &exist_p);
1131 orr_group = bgp_orr_group_lookup_by_name(
1132 bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
1133 if (orr_group) {
1134 orr_group_igp_metric_info = orr_group->igp_metric_info;
1135 if (orr_group_igp_metric_info) {
1136 for (ALL_LIST_ELEMENTS_RO(
1137 orr_group_igp_metric_info, node,
1138 igp_metric)) {
1139 if (ret &&
1140 prefix_cmp(&exist_p,
1141 &igp_metric->prefix) ==
1142 0) {
1143 existm = igp_metric->igp_metric;
1144 break;
1145 }
1146 }
1147 }
1148 }
1149 }
1150
d62a17ae 1151 if (newm < existm) {
ee88563a 1152 if (debug && peer_sort_ret < 0)
d62a17ae 1153 zlog_debug(
d588b995 1154 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1155 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1156 igp_metric_ret = 1;
d62a17ae 1157 }
718e3744 1158
d62a17ae 1159 if (newm > existm) {
ee88563a 1160 if (debug && peer_sort_ret < 0)
d62a17ae 1161 zlog_debug(
d588b995 1162 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1163 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1164 igp_metric_ret = 0;
5e242b0d 1165 }
5e242b0d 1166
d62a17ae 1167 /* 9. Same IGP metric. Compare the cluster list length as
1168 representative of IGP hops metric. Rewrite the metric value
1169 pair (newm, existm) with the cluster list length. Prefer the
1170 path with smaller cluster list length. */
1171 if (newm == existm) {
aa53c036
DS
1172 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1173 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1174 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1175 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1176 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1177
1178 if (newm < existm) {
ee88563a 1179 if (debug && peer_sort_ret < 0)
d62a17ae 1180 zlog_debug(
d588b995 1181 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1182 pfx_buf, new_buf, exist_buf,
1183 newm, existm);
ee88563a 1184 igp_metric_ret = 1;
d62a17ae 1185 }
1186
1187 if (newm > existm) {
ee88563a 1188 if (debug && peer_sort_ret < 0)
d62a17ae 1189 zlog_debug(
d588b995 1190 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1191 pfx_buf, new_buf, exist_buf,
1192 newm, existm);
ee88563a 1193 igp_metric_ret = 0;
d62a17ae 1194 }
1195 }
1196 }
31a4638f 1197
d62a17ae 1198 /* 10. confed-external vs. confed-internal */
1199 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1200 if (new_sort == BGP_PEER_CONFED
1201 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1202 *reason = bgp_path_selection_confed;
d62a17ae 1203 if (debug)
1204 zlog_debug(
1205 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1206 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1207 if (!CHECK_FLAG(bgp->flags,
1208 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1209 return 1;
1210 peer_sort_ret = 1;
d62a17ae 1211 }
718e3744 1212
d62a17ae 1213 if (exist_sort == BGP_PEER_CONFED
1214 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1215 *reason = bgp_path_selection_confed;
d62a17ae 1216 if (debug)
1217 zlog_debug(
1218 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1219 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1220 if (!CHECK_FLAG(bgp->flags,
1221 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1222 return 0;
1223 peer_sort_ret = 0;
d62a17ae 1224 }
1225 }
718e3744 1226
d62a17ae 1227 /* 11. Maximum path check. */
1228 if (newm == existm) {
1229 /* If one path has a label but the other does not, do not treat
1230 * them as equals for multipath
1231 */
a4d82a8a 1232 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1233 != (exist->extra
b57ba6d2 1234 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1235 if (debug)
1236 zlog_debug(
1237 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1238 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1239 } else if (CHECK_FLAG(bgp->flags,
1240 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1241
1242 /*
1243 * For the two paths, all comparison steps till IGP
1244 * metric
1245 * have succeeded - including AS_PATH hop count. Since
1246 * 'bgp
1247 * bestpath as-path multipath-relax' knob is on, we
1248 * don't need
1249 * an exact match of AS_PATH. Thus, mark the paths are
1250 * equal.
1251 * That will trigger both these paths to get into the
1252 * multipath
1253 * array.
1254 */
1255 *paths_eq = 1;
1256
1257 if (debug)
1258 zlog_debug(
1259 "%s: %s and %s are equal via multipath-relax",
1260 pfx_buf, new_buf, exist_buf);
1261 } else if (new->peer->sort == BGP_PEER_IBGP) {
1262 if (aspath_cmp(new->attr->aspath,
1263 exist->attr->aspath)) {
1264 *paths_eq = 1;
1265
1266 if (debug)
1267 zlog_debug(
1268 "%s: %s and %s are equal via matching aspaths",
1269 pfx_buf, new_buf, exist_buf);
1270 }
1271 } else if (new->peer->as == exist->peer->as) {
1272 *paths_eq = 1;
1273
1274 if (debug)
1275 zlog_debug(
1276 "%s: %s and %s are equal via same remote-as",
1277 pfx_buf, new_buf, exist_buf);
1278 }
1279 } else {
1280 /*
1281 * TODO: If unequal cost ibgp multipath is enabled we can
1282 * mark the paths as equal here instead of returning
1283 */
ee88563a
JM
1284
1285 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1286 * if either step 7 or 10 (peer type checks) yielded a winner,
1287 * that result was returned immediately. Returning from step 10
1288 * ignored the return value computed in steps 8 and 9 (IGP
1289 * metric checks). In order to preserve that behavior, if
1290 * peer_sort_ret is set, return that rather than igp_metric_ret.
1291 */
1292 ret = peer_sort_ret;
1293 if (peer_sort_ret < 0) {
1294 ret = igp_metric_ret;
1295 if (debug) {
1296 if (ret == 1)
1297 zlog_debug(
1298 "%s: %s wins over %s after IGP metric comparison",
1299 pfx_buf, new_buf, exist_buf);
1300 else
1301 zlog_debug(
1302 "%s: %s loses to %s after IGP metric comparison",
1303 pfx_buf, new_buf, exist_buf);
1304 }
1305 *reason = bgp_path_selection_igp_metric;
d62a17ae 1306 }
1307 return ret;
1308 }
718e3744 1309
ee88563a
JM
1310 /*
1311 * At this point, the decision whether to set *paths_eq = 1 has been
1312 * completed. If we deferred returning because of bestpath peer-type
1313 * relax configuration, return now.
1314 */
1315 if (peer_sort_ret >= 0)
1316 return peer_sort_ret;
1317
d62a17ae 1318 /* 12. If both paths are external, prefer the path that was received
1319 first (the oldest one). This step minimizes route-flap, since a
1320 newer path won't displace an older one, even if it was the
1321 preferred route based on the additional decision criteria below. */
892fedb6 1322 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1323 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1324 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1325 *reason = bgp_path_selection_older;
d62a17ae 1326 if (debug)
1327 zlog_debug(
1328 "%s: %s wins over %s due to oldest external",
1329 pfx_buf, new_buf, exist_buf);
1330 return 1;
1331 }
9fbdd100 1332
1defdda8 1333 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1334 *reason = bgp_path_selection_older;
d62a17ae 1335 if (debug)
1336 zlog_debug(
1337 "%s: %s loses to %s due to oldest external",
1338 pfx_buf, new_buf, exist_buf);
1339 return 0;
1340 }
1341 }
718e3744 1342
ce5002c6 1343 /* 13. Router-ID comparison. */
d62a17ae 1344 /* If one of the paths is "stale", the corresponding peer router-id will
1345 * be 0 and would always win over the other path. If originator id is
ce5002c6 1346 * used for the comparison, it will decide which path is better.
d62a17ae 1347 */
1348 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1349 new_id.s_addr = newattr->originator_id.s_addr;
1350 else
1351 new_id.s_addr = new->peer->remote_id.s_addr;
1352 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1353 exist_id.s_addr = existattr->originator_id.s_addr;
1354 else
1355 exist_id.s_addr = exist->peer->remote_id.s_addr;
1356
1357 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1358 *reason = bgp_path_selection_router_id;
d62a17ae 1359 if (debug)
1360 zlog_debug(
1361 "%s: %s wins over %s due to Router-ID comparison",
1362 pfx_buf, new_buf, exist_buf);
1363 return 1;
1364 }
718e3744 1365
d62a17ae 1366 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1367 *reason = bgp_path_selection_router_id;
d62a17ae 1368 if (debug)
1369 zlog_debug(
1370 "%s: %s loses to %s due to Router-ID comparison",
1371 pfx_buf, new_buf, exist_buf);
1372 return 0;
1373 }
9fbdd100 1374
ce5002c6 1375 /* 14. Cluster length comparison. */
d62a17ae 1376 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1377 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1378
1379 if (new_cluster < exist_cluster) {
fdf81fa0 1380 *reason = bgp_path_selection_cluster_length;
d62a17ae 1381 if (debug)
1382 zlog_debug(
1383 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1384 pfx_buf, new_buf, exist_buf, new_cluster,
1385 exist_cluster);
1386 return 1;
1387 }
718e3744 1388
d62a17ae 1389 if (new_cluster > exist_cluster) {
fdf81fa0 1390 *reason = bgp_path_selection_cluster_length;
d62a17ae 1391 if (debug)
1392 zlog_debug(
1393 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1394 pfx_buf, new_buf, exist_buf, new_cluster,
1395 exist_cluster);
1396 return 0;
1397 }
9fbdd100 1398
ce5002c6 1399 /* 15. Neighbor address comparison. */
d62a17ae 1400 /* Do this only if neither path is "stale" as stale paths do not have
1401 * valid peer information (as the connection may or may not be up).
1402 */
1defdda8 1403 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1404 *reason = bgp_path_selection_stale;
d62a17ae 1405 if (debug)
1406 zlog_debug(
1407 "%s: %s wins over %s due to latter path being STALE",
1408 pfx_buf, new_buf, exist_buf);
1409 return 1;
1410 }
0de5153c 1411
1defdda8 1412 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1413 *reason = bgp_path_selection_stale;
d62a17ae 1414 if (debug)
1415 zlog_debug(
1416 "%s: %s loses to %s due to former path being STALE",
1417 pfx_buf, new_buf, exist_buf);
1418 return 0;
1419 }
718e3744 1420
d62a17ae 1421 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1422 if (new->peer->su_remote == NULL) {
1423 *reason = bgp_path_selection_local_configured;
d62a17ae 1424 return 0;
fdf81fa0
DS
1425 }
1426 if (exist->peer->su_remote == NULL) {
1427 *reason = bgp_path_selection_local_configured;
d62a17ae 1428 return 1;
fdf81fa0 1429 }
9fbdd100 1430
d62a17ae 1431 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1432
1433 if (ret == 1) {
fdf81fa0 1434 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1435 if (debug)
1436 zlog_debug(
1437 "%s: %s loses to %s due to Neighor IP comparison",
1438 pfx_buf, new_buf, exist_buf);
1439 return 0;
1440 }
1441
1442 if (ret == -1) {
fdf81fa0 1443 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1444 if (debug)
1445 zlog_debug(
1446 "%s: %s wins over %s due to Neighor IP comparison",
1447 pfx_buf, new_buf, exist_buf);
1448 return 1;
1449 }
9fbdd100 1450
fdf81fa0 1451 *reason = bgp_path_selection_default;
d62a17ae 1452 if (debug)
1453 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1454 pfx_buf, new_buf, exist_buf);
718e3744 1455
d62a17ae 1456 return 1;
718e3744 1457}
1458
d071f237
AK
1459
1460int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1461 struct bgp_path_info *exist, int *paths_eq)
1462{
1463 enum bgp_path_selection_reason reason;
1464 char pfx_buf[PREFIX2STR_BUFFER];
1465
1466 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1467 AFI_L2VPN, SAFI_EVPN, &reason);
1468}
1469
65efcfce
LB
1470/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1471 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1472 * multipath is enabled
65efcfce 1473 * This version is compatible with */
18ee8310
DS
1474int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1475 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1476 afi_t afi, safi_t safi,
1477 enum bgp_path_selection_reason *reason)
d62a17ae 1478{
1479 int paths_eq;
1480 int ret;
18ee8310 1481 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1482 afi, safi, reason);
d62a17ae 1483
1484 if (paths_eq)
1485 ret = 0;
1486 else {
1487 if (ret == 1)
1488 ret = -1;
1489 else
1490 ret = 1;
1491 }
1492 return ret;
65efcfce
LB
1493}
1494
5a1ae2c2
DS
1495static enum filter_type bgp_input_filter(struct peer *peer,
1496 const struct prefix *p,
d62a17ae 1497 struct attr *attr, afi_t afi,
1498 safi_t safi)
718e3744 1499{
d62a17ae 1500 struct bgp_filter *filter;
6401252f 1501 enum filter_type ret = FILTER_PERMIT;
718e3744 1502
d62a17ae 1503 filter = &peer->filter[afi][safi];
718e3744 1504
d62a17ae 1505#define FILTER_EXIST_WARN(F, f, filter) \
1506 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1507 zlog_debug("%s: Could not find configured input %s-list %s!", \
1508 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1509
1510 if (DISTRIBUTE_IN_NAME(filter)) {
1511 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1512
6401252f
QY
1513 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1514 == FILTER_DENY) {
1515 ret = FILTER_DENY;
1516 goto done;
1517 }
d62a17ae 1518 }
1519
1520 if (PREFIX_LIST_IN_NAME(filter)) {
1521 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1522
6401252f
QY
1523 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1524 == PREFIX_DENY) {
1525 ret = FILTER_DENY;
1526 goto done;
1527 }
d62a17ae 1528 }
1529
1530 if (FILTER_LIST_IN_NAME(filter)) {
1531 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1532
1533 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1534 == AS_FILTER_DENY) {
1535 ret = FILTER_DENY;
1536 goto done;
1537 }
d62a17ae 1538 }
1539
6401252f 1540done:
c7bb4f00 1541 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1542 char pfxprint[PREFIX2STR_BUFFER];
1543
1544 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1545 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1546 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1547 }
1548
1549 return ret;
650f76c2 1550#undef FILTER_EXIST_WARN
718e3744 1551}
1552
b8685f9b
DS
1553static enum filter_type bgp_output_filter(struct peer *peer,
1554 const struct prefix *p,
d62a17ae 1555 struct attr *attr, afi_t afi,
1556 safi_t safi)
718e3744 1557{
d62a17ae 1558 struct bgp_filter *filter;
6401252f 1559 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1560
1561 filter = &peer->filter[afi][safi];
1562
1563#define FILTER_EXIST_WARN(F, f, filter) \
1564 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1565 zlog_debug("%s: Could not find configured output %s-list %s!", \
1566 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1567
d62a17ae 1568 if (DISTRIBUTE_OUT_NAME(filter)) {
1569 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1570
6401252f
QY
1571 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1572 == FILTER_DENY) {
1573 ret = FILTER_DENY;
1574 goto done;
1575 }
d62a17ae 1576 }
1577
1578 if (PREFIX_LIST_OUT_NAME(filter)) {
1579 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1580
d62a17ae 1581 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1582 == PREFIX_DENY) {
1583 ret = FILTER_DENY;
1584 goto done;
1585 }
d62a17ae 1586 }
718e3744 1587
d62a17ae 1588 if (FILTER_LIST_OUT_NAME(filter)) {
1589 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1590
d62a17ae 1591 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1592 == AS_FILTER_DENY) {
1593 ret = FILTER_DENY;
1594 goto done;
1595 }
1596 }
1597
c7bb4f00 1598 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1599 char pfxprint[PREFIX2STR_BUFFER];
1600
1601 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1602 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1603 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1604 }
718e3744 1605
6401252f
QY
1606done:
1607 return ret;
650f76c2 1608#undef FILTER_EXIST_WARN
718e3744 1609}
1610
1611/* If community attribute includes no_export then return 1. */
3dc339cd 1612static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1613{
9a706b42 1614 if (bgp_attr_get_community(attr)) {
d62a17ae 1615 /* NO_ADVERTISE check. */
9a706b42
DA
1616 if (community_include(bgp_attr_get_community(attr),
1617 COMMUNITY_NO_ADVERTISE))
3dc339cd 1618 return true;
d62a17ae 1619
1620 /* NO_EXPORT check. */
9a706b42
DA
1621 if (peer->sort == BGP_PEER_EBGP &&
1622 community_include(bgp_attr_get_community(attr),
1623 COMMUNITY_NO_EXPORT))
3dc339cd 1624 return true;
d62a17ae 1625
1626 /* NO_EXPORT_SUBCONFED check. */
1627 if (peer->sort == BGP_PEER_EBGP
1628 || peer->sort == BGP_PEER_CONFED)
9a706b42 1629 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1630 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1631 return true;
d62a17ae 1632 }
3dc339cd 1633 return false;
718e3744 1634}
1635
1636/* Route reflection loop check. */
3dc339cd 1637static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1638{
d62a17ae 1639 struct in_addr cluster_id;
779fee93 1640 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1641
779fee93 1642 if (cluster) {
d62a17ae 1643 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1644 cluster_id = peer->bgp->cluster_id;
1645 else
1646 cluster_id = peer->bgp->router_id;
1647
779fee93 1648 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1649 return true;
d62a17ae 1650 }
3dc339cd 1651 return false;
718e3744 1652}
6b0655a2 1653
d864dd9e
EB
1654static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1655{
1656 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1657 if (peer->local_role == ROLE_PROVIDER ||
1658 peer->local_role == ROLE_RS_SERVER)
1659 return true;
1660 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1661 return true;
1662 return false;
1663 }
1664 if (peer->local_role == ROLE_CUSTOMER ||
1665 peer->local_role == ROLE_PEER ||
1666 peer->local_role == ROLE_RS_CLIENT) {
1667 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1668 attr->otc = peer->as;
1669 }
1670 return false;
1671}
1672
1673static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1674{
1675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1676 if (peer->local_role == ROLE_CUSTOMER ||
1677 peer->local_role == ROLE_RS_CLIENT ||
1678 peer->local_role == ROLE_PEER)
1679 return true;
1680 return false;
1681 }
1682 if (peer->local_role == ROLE_PROVIDER ||
1683 peer->local_role == ROLE_PEER ||
1684 peer->local_role == ROLE_RS_SERVER) {
1685 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1686 attr->otc = peer->bgp->as;
1687 }
1688 return false;
1689}
1690
5a78f2bc
EB
1691static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1692{
1693 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1694}
1695
5a1ae2c2 1696static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1697 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1698 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1699 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1700{
d62a17ae 1701 struct bgp_filter *filter;
82b692c0
LK
1702 struct bgp_path_info rmap_path = { 0 };
1703 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1704 route_map_result_t ret;
1705 struct route_map *rmap = NULL;
718e3744 1706
d62a17ae 1707 filter = &peer->filter[afi][safi];
718e3744 1708
d62a17ae 1709 /* Apply default weight value. */
1710 if (peer->weight[afi][safi])
1711 attr->weight = peer->weight[afi][safi];
718e3744 1712
d62a17ae 1713 if (rmap_name) {
1714 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1715
d62a17ae 1716 if (rmap == NULL)
1717 return RMAP_DENY;
1718 } else {
1719 if (ROUTE_MAP_IN_NAME(filter)) {
1720 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1721
d62a17ae 1722 if (rmap == NULL)
1723 return RMAP_DENY;
1724 }
1725 }
0b16f239 1726
d62a17ae 1727 /* Route map apply. */
1728 if (rmap) {
6006b807 1729 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1730 /* Duplicate current value to new structure for modification. */
40381db7
DS
1731 rmap_path.peer = peer;
1732 rmap_path.attr = attr;
82b692c0 1733 rmap_path.extra = &extra;
9bcb3eef 1734 rmap_path.net = dest;
196c6b09 1735
82b692c0
LK
1736 extra.num_labels = num_labels;
1737 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1738 memcpy(extra.label, label,
1739 num_labels * sizeof(mpls_label_t));
718e3744 1740
d62a17ae 1741 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1742
d62a17ae 1743 /* Apply BGP route map to the attribute. */
1782514f 1744 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1745
d62a17ae 1746 peer->rmap_type = 0;
0b16f239 1747
1f2263be 1748 if (ret == RMAP_DENYMATCH)
d62a17ae 1749 return RMAP_DENY;
0b16f239 1750 }
d62a17ae 1751 return RMAP_PERMIT;
0b16f239
DS
1752}
1753
5f040085 1754static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1755 struct attr *attr, afi_t afi, safi_t safi,
1756 const char *rmap_name)
0b16f239 1757{
40381db7 1758 struct bgp_path_info rmap_path;
d62a17ae 1759 route_map_result_t ret;
1760 struct route_map *rmap = NULL;
d7c0a89a 1761 uint8_t rmap_type;
0b16f239 1762
b787157a
DS
1763 /*
1764 * So if we get to this point and have no rmap_name
1765 * we want to just show the output as it currently
1766 * exists.
1767 */
1768 if (!rmap_name)
1769 return RMAP_PERMIT;
0b16f239 1770
d62a17ae 1771 /* Apply default weight value. */
1772 if (peer->weight[afi][safi])
1773 attr->weight = peer->weight[afi][safi];
0b16f239 1774
b787157a 1775 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1776
b787157a
DS
1777 /*
1778 * If we have a route map name and we do not find
1779 * the routemap that means we have an implicit
1780 * deny.
1781 */
1782 if (rmap == NULL)
1783 return RMAP_DENY;
0b16f239 1784
6006b807 1785 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1786 /* Route map apply. */
544be979 1787 /* Duplicate current value to new structure for modification. */
40381db7
DS
1788 rmap_path.peer = peer;
1789 rmap_path.attr = attr;
0b16f239 1790
0f672529 1791 rmap_type = peer->rmap_type;
b787157a 1792 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1793
b787157a 1794 /* Apply BGP route map to the attribute. */
1782514f 1795 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1796
0f672529 1797 peer->rmap_type = rmap_type;
b787157a
DS
1798
1799 if (ret == RMAP_DENYMATCH)
1800 /*
1801 * caller has multiple error paths with bgp_attr_flush()
1802 */
1803 return RMAP_DENY;
ac41b2a2 1804
d62a17ae 1805 return RMAP_PERMIT;
718e3744 1806}
6b0655a2 1807
5000f21c 1808/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1809static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1810 struct peer *peer, struct attr *attr)
1811{
1812 if (peer->sort == BGP_PEER_EBGP
1813 && (peer_af_flag_check(peer, afi, safi,
1814 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1815 || peer_af_flag_check(peer, afi, safi,
1816 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1817 || peer_af_flag_check(peer, afi, safi,
1818 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1819 || peer_af_flag_check(peer, afi, safi,
1820 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1821 // Take action on the entire aspath
1822 if (peer_af_flag_check(peer, afi, safi,
1823 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1824 || peer_af_flag_check(peer, afi, safi,
1825 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1826 if (peer_af_flag_check(
1827 peer, afi, safi,
1828 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1829 attr->aspath = aspath_replace_private_asns(
bf26b80e 1830 attr->aspath, bgp->as, peer->as);
d62a17ae 1831
179d5a0e
TA
1832 /*
1833 * Even if the aspath consists of just private ASNs we
1834 * need to walk the AS-Path to maintain all instances
1835 * of the peer's ASN to break possible loops.
1836 */
d62a17ae 1837 else
1838 attr->aspath = aspath_remove_private_asns(
bf26b80e 1839 attr->aspath, peer->as);
d62a17ae 1840 }
1841
1842 // 'all' was not specified so the entire aspath must be private
1843 // ASNs
1844 // for us to do anything
1845 else if (aspath_private_as_check(attr->aspath)) {
1846 if (peer_af_flag_check(
1847 peer, afi, safi,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1849 attr->aspath = aspath_replace_private_asns(
bf26b80e 1850 attr->aspath, bgp->as, peer->as);
d62a17ae 1851 else
179d5a0e
TA
1852 /*
1853 * Walk the aspath to retain any instances of
1854 * the peer_asn
1855 */
1856 attr->aspath = aspath_remove_private_asns(
1857 attr->aspath, peer->as);
d62a17ae 1858 }
1859 }
5000f21c
DS
1860}
1861
c7122e14 1862/* If this is an EBGP peer with as-override */
d62a17ae 1863static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1864 struct peer *peer, struct attr *attr)
1865{
bbe7bc46
DA
1866 struct aspath *aspath;
1867
9bbdb457 1868 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1869 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1870 if (attr->aspath->refcnt)
1871 aspath = aspath_dup(attr->aspath);
1872 else
1873 aspath = attr->aspath;
1874
1875 attr->aspath = aspath_intern(
1876 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1877
1878 aspath_free(aspath);
1879 }
d62a17ae 1880}
1881
1479ed2f
DA
1882void bgp_attr_add_llgr_community(struct attr *attr)
1883{
1884 struct community *old;
1885 struct community *new;
1886 struct community *merge;
1887 struct community *llgr;
1888
9a706b42 1889 old = bgp_attr_get_community(attr);
1479ed2f
DA
1890 llgr = community_str2com("llgr-stale");
1891
1892 assert(llgr);
1893
1894 if (old) {
1895 merge = community_merge(community_dup(old), llgr);
1896
1897 if (old->refcnt == 0)
1898 community_free(&old);
1899
1900 new = community_uniq_sort(merge);
1901 community_free(&merge);
1902 } else {
1903 new = community_dup(llgr);
1904 }
1905
1906 community_free(&llgr);
1907
9a706b42 1908 bgp_attr_set_community(attr, new);
1479ed2f
DA
1909}
1910
7f323236
DW
1911void bgp_attr_add_gshut_community(struct attr *attr)
1912{
1913 struct community *old;
1914 struct community *new;
1915 struct community *merge;
1916 struct community *gshut;
1917
9a706b42 1918 old = bgp_attr_get_community(attr);
7f323236
DW
1919 gshut = community_str2com("graceful-shutdown");
1920
990f4f91 1921 assert(gshut);
1922
7f323236
DW
1923 if (old) {
1924 merge = community_merge(community_dup(old), gshut);
1925
a4d82a8a 1926 if (old->refcnt == 0)
3c1f53de 1927 community_free(&old);
7f323236
DW
1928
1929 new = community_uniq_sort(merge);
3c1f53de 1930 community_free(&merge);
7f323236
DW
1931 } else {
1932 new = community_dup(gshut);
1933 }
1934
3c1f53de 1935 community_free(&gshut);
9a706b42 1936 bgp_attr_set_community(attr, new);
7f323236
DW
1937
1938 /* When we add the graceful-shutdown community we must also
1939 * lower the local-preference */
1940 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1941 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1942}
1943
1944
e73c112e
MK
1945/* Notify BGP Conditional advertisement scanner process. */
1946void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1947{
e73c112e 1948 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1949 afi_t afi = SUBGRP_AFI(subgrp);
1950 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1951 struct bgp_filter *filter = &peer->filter[afi][safi];
1952
1953 if (!ADVERTISE_MAP_NAME(filter))
1954 return;
1955
52979c3b
DS
1956 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1957 return;
e73c112e 1958
52979c3b 1959 peer->advmap_table_change = true;
e73c112e
MK
1960}
1961
1962
f2ee6d5c 1963void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1964{
960035b2 1965 if (family == AF_INET) {
975a328e
DA
1966 attr->nexthop.s_addr = INADDR_ANY;
1967 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1968 }
d62a17ae 1969 if (family == AF_INET6)
1970 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1971 if (family == AF_EVPN)
1972 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1973}
1974
9bcb3eef 1975bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1976 struct update_subgroup *subgrp,
7f7940e6 1977 const struct prefix *p, struct attr *attr,
51c3a7de 1978 struct attr *post_attr)
d62a17ae 1979{
1980 struct bgp_filter *filter;
1981 struct peer *from;
1982 struct peer *peer;
1983 struct peer *onlypeer;
1984 struct bgp *bgp;
40381db7 1985 struct attr *piattr;
b68885f9 1986 route_map_result_t ret;
d62a17ae 1987 int transparent;
1988 int reflect;
1989 afi_t afi;
1990 safi_t safi;
1991 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1992 bool nh_reset = false;
1993 uint64_t cum_bw;
d62a17ae 1994
1995 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1996 return false;
d62a17ae 1997
1998 afi = SUBGRP_AFI(subgrp);
1999 safi = SUBGRP_SAFI(subgrp);
2000 peer = SUBGRP_PEER(subgrp);
2001 onlypeer = NULL;
2002 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2003 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2004
40381db7 2005 from = pi->peer;
d62a17ae 2006 filter = &peer->filter[afi][safi];
2007 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2008 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2009 : pi->attr;
3f9c7369 2010
d0bf49ec
LS
2011 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2012 peer->pmax_out[afi][safi] != 0 &&
2013 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2014 if (BGP_DEBUG(update, UPDATE_OUT) ||
2015 BGP_DEBUG(update, UPDATE_PREFIX)) {
2016 zlog_debug("%s reached maximum prefix to be send (%u)",
2017 peer->host, peer->pmax_out[afi][safi]);
2018 }
2019 return false;
2020 }
2021
49e5a4a0 2022#ifdef ENABLE_BGP_VNC
d62a17ae 2023 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2024 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2025 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2026
2027 /*
2028 * direct and direct_ext type routes originate internally even
2029 * though they can have peer pointers that reference other
2030 * systems
2031 */
8228a9a7
DS
2032 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2033 __func__, p);
d62a17ae 2034 samepeer_safe = 1;
2035 }
65efcfce
LB
2036#endif
2037
ddb5b488
PZ
2038 if (((afi == AFI_IP) || (afi == AFI_IP6))
2039 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2040 && (pi->type == ZEBRA_ROUTE_BGP)
2041 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2042
2043 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2044
2045 samepeer_safe = 1;
2046 }
2047
d62a17ae 2048 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2049 * pi is valid */
2050 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2051 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2052 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2053 return false;
d62a17ae 2054 }
adbac85e 2055
d62a17ae 2056 /* If this is not the bestpath then check to see if there is an enabled
2057 * addpath
2058 * feature that requires us to advertise it */
40381db7 2059 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 2060 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 2061 return false;
d62a17ae 2062 }
2063 }
06370dac 2064
d62a17ae 2065 /* Aggregate-address suppress check. */
4056a5f6
RZ
2066 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2067 return false;
3f9c7369 2068
13b7e7f0
DS
2069 /*
2070 * If we are doing VRF 2 VRF leaking via the import
2071 * statement, we want to prevent the route going
2072 * off box as that the RT and RD created are localy
2073 * significant and globaly useless.
2074 */
40381db7
DS
2075 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2076 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2077 return false;
13b7e7f0 2078
d62a17ae 2079 /* If it's labeled safi, make sure the route has a valid label. */
2080 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2081 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2082 if (!bgp_is_valid_label(&label)) {
2083 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2084 zlog_debug("u%" PRIu64 ":s%" PRIu64
2085 " %pFX is filtered - no label (%p)",
d62a17ae 2086 subgrp->update_group->id, subgrp->id,
8228a9a7 2087 p, &label);
3dc339cd 2088 return false;
d62a17ae 2089 }
2090 }
cd1964ff 2091
d62a17ae 2092 /* Do not send back route to sender. */
2093 if (onlypeer && from == onlypeer) {
3dc339cd 2094 return false;
d62a17ae 2095 }
3f9c7369 2096
d62a17ae 2097 /* Do not send the default route in the BGP table if the neighbor is
2098 * configured for default-originate */
2099 if (CHECK_FLAG(peer->af_flags[afi][safi],
2100 PEER_FLAG_DEFAULT_ORIGINATE)) {
2101 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2102 return false;
d62a17ae 2103 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2104 return false;
d62a17ae 2105 }
4125bb67 2106
d62a17ae 2107 /* Transparency check. */
2108 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2109 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2110 transparent = 1;
2111 else
2112 transparent = 0;
2113
2114 /* If community is not disabled check the no-export and local. */
40381db7 2115 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2116 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2117 zlog_debug("%s: community filter check fail for %pFX",
2118 __func__, p);
3dc339cd 2119 return false;
d62a17ae 2120 }
3f9c7369 2121
d62a17ae 2122 /* If the attribute has originator-id and it is same as remote
2123 peer's id. */
40381db7
DS
2124 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2125 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2126 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2127 zlog_debug(
a9f3f4f5
DA
2128 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2129 onlypeer, p);
3dc339cd 2130 return false;
d62a17ae 2131 }
3f9c7369 2132
d62a17ae 2133 /* ORF prefix-list filter check */
2134 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2135 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2136 || CHECK_FLAG(peer->af_cap[afi][safi],
2137 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2138 if (peer->orf_plist[afi][safi]) {
2139 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2140 == PREFIX_DENY) {
2141 if (bgp_debug_update(NULL, p,
2142 subgrp->update_group, 0))
2143 zlog_debug(
a9f3f4f5
DA
2144 "%pBP [Update:SEND] %pFX is filtered via ORF",
2145 peer, p);
3dc339cd 2146 return false;
d62a17ae 2147 }
2148 }
2149
2150 /* Output filter check. */
40381db7 2151 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2152 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2153 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2154 p);
3dc339cd 2155 return false;
d62a17ae 2156 }
3f9c7369 2157
d62a17ae 2158 /* AS path loop check. */
2b31007c
RZ
2159 if (onlypeer && onlypeer->as_path_loop_detection
2160 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2161 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2162 zlog_debug(
a9f3f4f5
DA
2163 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2164 onlypeer, onlypeer->as);
3dc339cd 2165 return false;
d62a17ae 2166 }
3f9c7369 2167
d62a17ae 2168 /* If we're a CONFED we need to loop check the CONFED ID too */
2169 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2170 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2171 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2172 zlog_debug(
a9f3f4f5
DA
2173 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2174 peer, bgp->confed_id);
3dc339cd 2175 return false;
d62a17ae 2176 }
3f9c7369 2177 }
3f9c7369 2178
d62a17ae 2179 /* Route-Reflect check. */
2180 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2181 reflect = 1;
2182 else
2183 reflect = 0;
2184
2185 /* IBGP reflection check. */
2186 if (reflect && !samepeer_safe) {
2187 /* A route from a Client peer. */
2188 if (CHECK_FLAG(from->af_flags[afi][safi],
2189 PEER_FLAG_REFLECTOR_CLIENT)) {
2190 /* Reflect to all the Non-Client peers and also to the
2191 Client peers other than the originator. Originator
2192 check
2193 is already done. So there is noting to do. */
2194 /* no bgp client-to-client reflection check. */
892fedb6
DA
2195 if (CHECK_FLAG(bgp->flags,
2196 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2197 if (CHECK_FLAG(peer->af_flags[afi][safi],
2198 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2199 return false;
d62a17ae 2200 } else {
2201 /* A route from a Non-client peer. Reflect to all other
2202 clients. */
2203 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2204 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2205 return false;
d62a17ae 2206 }
2207 }
3f9c7369 2208
51c3a7de
DA
2209 /* For modify attribute, copy it to temporary structure.
2210 * post_attr comes from BGP conditional advertisements, where
2211 * attributes are already processed by advertise-map route-map,
2212 * and this needs to be saved instead of overwriting from the
2213 * path attributes.
2214 */
2215 if (post_attr)
2216 *attr = *post_attr;
2217 else
2218 *attr = *piattr;
d62a17ae 2219
2220 /* If local-preference is not set. */
2221 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2222 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2223 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2224 attr->local_pref = bgp->default_local_pref;
3f9c7369 2225 }
3f9c7369 2226
d62a17ae 2227 /* If originator-id is not set and the route is to be reflected,
2228 set the originator id */
2229 if (reflect
2230 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2231 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2232 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2233 }
3f9c7369 2234
d62a17ae 2235 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2236 */
2237 if (peer->sort == BGP_PEER_EBGP
2238 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2239 if (from != bgp->peer_self && !transparent
2240 && !CHECK_FLAG(peer->af_flags[afi][safi],
2241 PEER_FLAG_MED_UNCHANGED))
2242 attr->flag &=
2243 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2244 }
3f9c7369 2245
d62a17ae 2246 /* Since the nexthop attribute can vary per peer, it is not explicitly
2247 * set
2248 * in announce check, only certain flags and length (or number of
2249 * nexthops
2250 * -- for IPv6/MP_REACH) are set here in order to guide the update
2251 * formation
2252 * code in setting the nexthop(s) on a per peer basis in
2253 * reformat_peer().
2254 * Typically, the source nexthop in the attribute is preserved but in
2255 * the
2256 * scenarios where we know it will always be overwritten, we reset the
2257 * nexthop to "0" in an attempt to achieve better Update packing. An
2258 * example of this is when a prefix from each of 2 IBGP peers needs to
2259 * be
2260 * announced to an EBGP peer (and they have the same attributes barring
2261 * their nexthop).
2262 */
2263 if (reflect)
2264 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2265
2266#define NEXTHOP_IS_V6 \
2267 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2268 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2269 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2270 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2271
2272 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2273 * if
2274 * the peer (group) is configured to receive link-local nexthop
2275 * unchanged
c728d027
DA
2276 * and it is available in the prefix OR we're not reflecting the route,
2277 * link-local nexthop address is valid and
d62a17ae 2278 * the peer (group) to whom we're going to announce is on a shared
2279 * network
2280 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2281 * By checking if nexthop LL address is valid we are sure that
2282 * we do not announce LL address as `::`.
d62a17ae 2283 */
2284 if (NEXTHOP_IS_V6) {
2285 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2286 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2287 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2288 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2289 || (!reflect && !transparent
c728d027
DA
2290 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2291 && peer->shared_network
d62a17ae 2292 && (from == bgp->peer_self
2293 || peer->sort == BGP_PEER_EBGP))) {
2294 attr->mp_nexthop_len =
2295 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2296 }
3f9c7369 2297
d62a17ae 2298 /* Clear off link-local nexthop in source, whenever it is not
2299 * needed to
2300 * ensure more prefixes share the same attribute for
2301 * announcement.
2302 */
2303 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2304 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2305 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2306 }
3f9c7369 2307
5a78f2bc
EB
2308 if (bgp_check_role_applicability(afi, safi) &&
2309 bgp_otc_egress(peer, attr))
d864dd9e
EB
2310 return false;
2311
d62a17ae 2312 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2313 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2314
0655090c
QY
2315 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2316 filter->advmap.aname &&
2317 route_map_lookup_by_name(filter->advmap.aname)) {
2318 struct bgp_path_info rmap_path = {0};
2319 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2320 struct attr dummy_attr = *attr;
2321
2322 /* Fill temp path_info */
2323 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2324 pi, peer, &dummy_attr);
2325
2326 struct route_map *amap =
2327 route_map_lookup_by_name(filter->advmap.aname);
2328
2329 ret = route_map_apply(amap, p, &rmap_path);
2330
2331 bgp_attr_flush(&dummy_attr);
2332
2333 /*
2334 * The conditional advertisement mode is Withdraw and this
2335 * prefix is a conditional prefix. Don't advertise it
2336 */
2337 if (ret == RMAP_PERMITMATCH)
2338 return false;
2339 }
2340
d62a17ae 2341 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2342 if (!post_attr &&
2343 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2344 struct bgp_path_info rmap_path = {0};
2345 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2346 struct attr dummy_attr = {0};
d62a17ae 2347
e34291b8 2348 /* Fill temp path_info */
9bcb3eef
DS
2349 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2350 pi, peer, attr);
16f7ce2b 2351
d62a17ae 2352 /* don't confuse inbound and outbound setting */
2353 RESET_FLAG(attr->rmap_change_flags);
2354
2355 /*
2356 * The route reflector is not allowed to modify the attributes
2357 * of the reflected IBGP routes unless explicitly allowed.
2358 */
2359 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2360 && !CHECK_FLAG(bgp->flags,
2361 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2362 dummy_attr = *attr;
40381db7 2363 rmap_path.attr = &dummy_attr;
d62a17ae 2364 }
3f9c7369 2365
d62a17ae 2366 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2367
4056a5f6 2368 if (bgp_path_suppressed(pi))
d62a17ae 2369 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2370 &rmap_path);
d62a17ae 2371 else
2372 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2373 &rmap_path);
d62a17ae 2374
7e7639f5 2375 bgp_attr_flush(&dummy_attr);
d62a17ae 2376 peer->rmap_type = 0;
2377
2378 if (ret == RMAP_DENYMATCH) {
778048bf 2379 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2380 zlog_debug(
a9f3f4f5
DA
2381 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2382 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2383 bgp_attr_flush(rmap_path.attr);
3dc339cd 2384 return false;
d62a17ae 2385 }
3f9c7369 2386 }
3f9c7369 2387
9dac9fc8
DA
2388 /* RFC 8212 to prevent route leaks.
2389 * This specification intends to improve this situation by requiring the
2390 * explicit configuration of both BGP Import and Export Policies for any
2391 * External BGP (EBGP) session such as customers, peers, or
2392 * confederation boundaries for all enabled address families. Through
2393 * codification of the aforementioned requirement, operators will
2394 * benefit from consistent behavior across different BGP
2395 * implementations.
2396 */
1d3fdccf 2397 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2398 if (!bgp_outbound_policy_exists(peer, filter)) {
2399 if (monotime_since(&bgp->ebgprequirespolicywarning,
2400 NULL) > FIFTEENMINUTE2USEC ||
2401 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2402 zlog_warn(
2403 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2404 monotime(&bgp->ebgprequirespolicywarning);
2405 }
3dc339cd 2406 return false;
b17826b7 2407 }
9dac9fc8 2408
fb29348a
DA
2409 /* draft-ietf-idr-deprecate-as-set-confed-set
2410 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2411 * Eventually, This document (if approved) updates RFC 4271
2412 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2413 * and obsoletes RFC 6472.
2414 */
7f972cd8 2415 if (peer->bgp->reject_as_sets)
fb29348a 2416 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2417 return false;
fb29348a 2418
01da2d26
DA
2419 /* If neighbor sso is configured, then check if the route has
2420 * SoO extended community and validate against the configured
2421 * one. If they match, do not announce, to prevent routing
2422 * loops.
2423 */
2424 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2425 peer->soo[afi][safi]) {
2426 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2427 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2428
2429 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2430 ECOMMUNITY_SITE_ORIGIN) ||
2431 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2432 ECOMMUNITY_SITE_ORIGIN)) &&
2433 ecommunity_include(ecomm, ecomm_soo)) {
2434 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2435 zlog_debug(
2436 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2437 peer, p, ecommunity_str(ecomm_soo));
2438 return false;
2439 }
2440 }
2441
33d022bc
DA
2442 /* Codification of AS 0 Processing */
2443 if (aspath_check_as_zero(attr->aspath))
e2369003 2444 return false;
33d022bc 2445
637e5ba4 2446 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2447 if (peer->sort == BGP_PEER_IBGP
2448 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2449 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2450 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2451 } else {
2452 bgp_attr_add_gshut_community(attr);
2453 }
2454 }
2455
1479ed2f
DA
2456 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2457 * Capability" to a neighbor MUST perform the following upon receiving
2458 * a route from that neighbor with the "LLGR_STALE" community, or upon
2459 * attaching the "LLGR_STALE" community itself per Section 4.2:
2460 *
2461 * The route SHOULD NOT be advertised to any neighbor from which the
2462 * Long-lived Graceful Restart Capability has not been received.
2463 */
9a706b42
DA
2464 if (bgp_attr_get_community(attr) &&
2465 community_include(bgp_attr_get_community(attr),
2466 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2467 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2468 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2469 return false;
2470
d62a17ae 2471 /* After route-map has been applied, we check to see if the nexthop to
2472 * be carried in the attribute (that is used for the announcement) can
2473 * be cleared off or not. We do this in all cases where we would be
2474 * setting the nexthop to "ourselves". For IPv6, we only need to
2475 * consider
2476 * the global nexthop here; the link-local nexthop would have been
2477 * cleared
2478 * already, and if not, it is required by the update formation code.
2479 * Also see earlier comments in this function.
2480 */
2481 /*
2482 * If route-map has performed some operation on the nexthop or the peer
2483 * configuration says to pass it unchanged, we cannot reset the nexthop
2484 * here, so only attempt to do it if these aren't true. Note that the
2485 * route-map handler itself might have cleared the nexthop, if for
2486 * example,
2487 * it is configured as 'peer-address'.
2488 */
2489 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2490 piattr->rmap_change_flags)
d62a17ae 2491 && !transparent
2492 && !CHECK_FLAG(peer->af_flags[afi][safi],
2493 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2494 /* We can reset the nexthop, if setting (or forcing) it to
2495 * 'self' */
2496 if (CHECK_FLAG(peer->af_flags[afi][safi],
2497 PEER_FLAG_NEXTHOP_SELF)
2498 || CHECK_FLAG(peer->af_flags[afi][safi],
2499 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2500 if (!reflect
2501 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2502 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2503 subgroup_announce_reset_nhop(
2504 (peer_cap_enhe(peer, afi, safi)
2505 ? AF_INET6
2506 : p->family),
2507 attr);
7b651a32 2508 nh_reset = true;
2509 }
d62a17ae 2510 } else if (peer->sort == BGP_PEER_EBGP) {
2511 /* Can also reset the nexthop if announcing to EBGP, but
2512 * only if
2513 * no peer in the subgroup is on a shared subnet.
2514 * Note: 3rd party nexthop currently implemented for
2515 * IPv4 only.
2516 */
737af885
BS
2517 if ((p->family == AF_INET) &&
2518 (!bgp_subgrp_multiaccess_check_v4(
2519 piattr->nexthop,
7b651a32 2520 subgrp, from))) {
d62a17ae 2521 subgroup_announce_reset_nhop(
2522 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2523 ? AF_INET6
2524 : p->family),
737af885 2525 attr);
7b651a32 2526 nh_reset = true;
2527 }
737af885
BS
2528
2529 if ((p->family == AF_INET6) &&
2530 (!bgp_subgrp_multiaccess_check_v6(
2531 piattr->mp_nexthop_global,
7b651a32 2532 subgrp, from))) {
737af885
BS
2533 subgroup_announce_reset_nhop(
2534 (peer_cap_enhe(peer, afi, safi)
2535 ? AF_INET6
2536 : p->family),
2537 attr);
7b651a32 2538 nh_reset = true;
2539 }
737af885
BS
2540
2541
2542
40381db7 2543 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2544 /*
2545 * This flag is used for leaked vpn-vrf routes
2546 */
2547 int family = p->family;
2548
2549 if (peer_cap_enhe(peer, afi, safi))
2550 family = AF_INET6;
2551
2552 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2553 zlog_debug(
1defdda8 2554 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2555 __func__, family2str(family));
2556 subgroup_announce_reset_nhop(family, attr);
7b651a32 2557 nh_reset = true;
d62a17ae 2558 }
63696f1d 2559 }
960035b2 2560
63696f1d 2561 /* If IPv6/MP and nexthop does not have any override and happens
2562 * to
2563 * be a link-local address, reset it so that we don't pass along
2564 * the
2565 * source's link-local IPv6 address to recipients who may not be
2566 * on
2567 * the same interface.
2568 */
2569 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2570 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2571 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2572 nh_reset = true;
2573 }
d62a17ae 2574 }
3f9c7369 2575
7b27cf7b
DA
2576 /* If this is an iBGP, send Origin Validation State (OVS)
2577 * extended community (rfc8097).
2578 */
2579 if (peer->sort == BGP_PEER_IBGP) {
2580 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2581
2582 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2583
2584 if (rpki_state != RPKI_NOT_BEING_USED)
2585 bgp_attr_set_ecommunity(
2586 attr, ecommunity_add_origin_validation_state(
2587 rpki_state,
2588 bgp_attr_get_ecommunity(attr)));
2589 }
2590
7b651a32 2591 /*
2592 * When the next hop is set to ourselves, if all multipaths have
2593 * link-bandwidth announce the cumulative bandwidth as that makes
2594 * the most sense. However, don't modify if the link-bandwidth has
2595 * been explicitly set by user policy.
2596 */
2597 if (nh_reset &&
f7e1c681 2598 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2599 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2600 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2601 bgp_attr_set_ecommunity(
2602 attr,
2603 ecommunity_replace_linkbw(
2604 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2605 CHECK_FLAG(
2606 peer->flags,
2607 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2608
3dc339cd 2609 return true;
3f9c7369
DS
2610}
2611
cc9f21da 2612static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2613{
2614 struct afi_safi_info *info;
2615 afi_t afi;
2616 safi_t safi;
2617 struct bgp *bgp;
2618
2619 info = THREAD_ARG(thread);
2620 afi = info->afi;
2621 safi = info->safi;
2622 bgp = info->bgp;
2623
2624 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2625 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2626 safi);
f009ff26 2627
2628 bgp->gr_info[afi][safi].t_route_select = NULL;
2629
2630 XFREE(MTYPE_TMP, info);
2631
2632 /* Best path selection */
cc9f21da 2633 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2634}
2635
9bcb3eef 2636void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2637 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2638 struct bgp_path_info_pair *result, afi_t afi,
2639 safi_t safi)
2640{
2641 struct bgp_path_info *new_select;
2642 struct bgp_path_info *old_select;
40381db7
DS
2643 struct bgp_path_info *pi;
2644 struct bgp_path_info *pi1;
2645 struct bgp_path_info *pi2;
2646 struct bgp_path_info *nextpi = NULL;
d62a17ae 2647 int paths_eq, do_mpath, debug;
2648 struct list mp_list;
2649 char pfx_buf[PREFIX2STR_BUFFER];
2650 char path_buf[PATH_ADDPATH_STR_BUFFER];
2651
2652 bgp_mp_list_init(&mp_list);
2653 do_mpath =
2654 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2655
9bcb3eef 2656 debug = bgp_debug_bestpath(dest);
d62a17ae 2657
2658 if (debug)
9bcb3eef 2659 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2660
9bcb3eef 2661 dest->reason = bgp_path_selection_none;
d62a17ae 2662 /* bgp deterministic-med */
2663 new_select = NULL;
892fedb6 2664 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2665
1defdda8 2666 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2667 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2668 pi1 = pi1->next)
9bcb3eef 2669 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2670 BGP_PATH_DMED_SELECTED);
d62a17ae 2671
9bcb3eef 2672 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2673 pi1 = pi1->next) {
40381db7 2674 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2675 continue;
40381db7 2676 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2677 continue;
ea8b2282 2678 if (pi1->peer != bgp->peer_self)
feb17238 2679 if (!peer_established(pi1->peer))
d62a17ae 2680 continue;
2681
40381db7
DS
2682 new_select = pi1;
2683 if (pi1->next) {
2684 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2685 if (CHECK_FLAG(pi2->flags,
1defdda8 2686 BGP_PATH_DMED_CHECK))
d62a17ae 2687 continue;
40381db7 2688 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2689 continue;
ea8b2282 2690 if (pi2->peer != bgp->peer_self
d62a17ae 2691 && !CHECK_FLAG(
ea8b2282
DS
2692 pi2->peer->sflags,
2693 PEER_STATUS_NSF_WAIT))
40381db7 2694 if (pi2->peer->status
d62a17ae 2695 != Established)
2696 continue;
2697
121e245d
DS
2698 if (!aspath_cmp_left(pi1->attr->aspath,
2699 pi2->attr->aspath)
2700 && !aspath_cmp_left_confed(
40381db7 2701 pi1->attr->aspath,
121e245d
DS
2702 pi2->attr->aspath))
2703 continue;
d62a17ae 2704
121e245d
DS
2705 if (bgp_path_info_cmp(
2706 bgp, pi2, new_select,
2707 &paths_eq, mpath_cfg, debug,
fdf81fa0 2708 pfx_buf, afi, safi,
9bcb3eef 2709 &dest->reason)) {
121e245d 2710 bgp_path_info_unset_flag(
9bcb3eef 2711 dest, new_select,
121e245d
DS
2712 BGP_PATH_DMED_SELECTED);
2713 new_select = pi2;
d62a17ae 2714 }
121e245d
DS
2715
2716 bgp_path_info_set_flag(
9bcb3eef 2717 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2718 }
2719 }
9bcb3eef 2720 bgp_path_info_set_flag(dest, new_select,
18ee8310 2721 BGP_PATH_DMED_CHECK);
9bcb3eef 2722 bgp_path_info_set_flag(dest, new_select,
18ee8310 2723 BGP_PATH_DMED_SELECTED);
d62a17ae 2724
2725 if (debug) {
18ee8310 2726 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2727 new_select, path_buf, sizeof(path_buf));
8228a9a7 2728 zlog_debug(
4378495a
DS
2729 "%pBD(%s): %s is the bestpath from AS %u",
2730 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2731 aspath_get_first_as(
2732 new_select->attr->aspath));
d62a17ae 2733 }
2734 }
2735 }
96450faf 2736
d62a17ae 2737 /* Check old selected route and new selected route. */
2738 old_select = NULL;
2739 new_select = NULL;
9bcb3eef 2740 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2741 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2742 enum bgp_path_selection_reason reason;
2743
40381db7
DS
2744 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2745 old_select = pi;
d62a17ae 2746
40381db7 2747 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2748 /* reap REMOVED routes, if needs be
2749 * selected route must stay for a while longer though
2750 */
40381db7
DS
2751 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2752 && (pi != old_select))
9bcb3eef 2753 bgp_path_info_reap(dest, pi);
d62a17ae 2754
ddb5b488 2755 if (debug)
40381db7
DS
2756 zlog_debug("%s: pi %p in holddown", __func__,
2757 pi);
ddb5b488 2758
d62a17ae 2759 continue;
2760 }
96450faf 2761
40381db7
DS
2762 if (pi->peer && pi->peer != bgp->peer_self
2763 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2764 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2765
2766 if (debug)
2767 zlog_debug(
40381db7
DS
2768 "%s: pi %p non self peer %s not estab state",
2769 __func__, pi, pi->peer->host);
ddb5b488 2770
d62a17ae 2771 continue;
ddb5b488 2772 }
9fbdd100 2773
892fedb6 2774 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2775 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2776 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2777 if (debug)
40381db7 2778 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2779 continue;
2780 }
9fbdd100 2781
9bcb3eef 2782 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2783
9bcb3eef 2784 reason = dest->reason;
40381db7 2785 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2786 debug, pfx_buf, afi, safi,
2787 &dest->reason)) {
19ea4cec
DS
2788 if (new_select == NULL &&
2789 reason != bgp_path_selection_none)
9bcb3eef 2790 dest->reason = reason;
40381db7 2791 new_select = pi;
d62a17ae 2792 }
2793 }
718e3744 2794
d62a17ae 2795 /* Now that we know which path is the bestpath see if any of the other
2796 * paths
2797 * qualify as multipaths
2798 */
2799 if (debug) {
2800 if (new_select)
7533cad7
QY
2801 bgp_path_info_path_with_addpath_rx_str(
2802 new_select, path_buf, sizeof(path_buf));
d62a17ae 2803 else
772270f3 2804 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2805 zlog_debug(
4378495a
DS
2806 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2807 dest, bgp->name_pretty, path_buf,
d62a17ae 2808 old_select ? old_select->peer->host : "NONE");
96450faf 2809 }
9fbdd100 2810
d62a17ae 2811 if (do_mpath && new_select) {
9bcb3eef 2812 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2813 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2814
2815 if (debug)
18ee8310 2816 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2817 pi, path_buf, sizeof(path_buf));
d62a17ae 2818
40381db7 2819 if (pi == new_select) {
d62a17ae 2820 if (debug)
2821 zlog_debug(
4378495a
DS
2822 "%pBD(%s): %s is the bestpath, add to the multipath list",
2823 dest, bgp->name_pretty,
2824 path_buf);
40381db7 2825 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2826 continue;
2827 }
2828
40381db7 2829 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2830 continue;
2831
40381db7
DS
2832 if (pi->peer && pi->peer != bgp->peer_self
2833 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2834 PEER_STATUS_NSF_WAIT))
feb17238 2835 if (!peer_established(pi->peer))
d62a17ae 2836 continue;
2837
40381db7 2838 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2839 if (debug)
2840 zlog_debug(
8228a9a7
DS
2841 "%pBD: %s has the same nexthop as the bestpath, skip it",
2842 dest, path_buf);
d62a17ae 2843 continue;
2844 }
2845
40381db7 2846 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2847 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2848 &dest->reason);
d62a17ae 2849
2850 if (paths_eq) {
2851 if (debug)
2852 zlog_debug(
8228a9a7
DS
2853 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2854 dest, path_buf);
40381db7 2855 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2856 }
2857 }
2858 }
fee0f4c6 2859
4378495a 2860 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2861 mpath_cfg);
2862 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2863 bgp_mp_list_clear(&mp_list);
96450faf 2864
9bcb3eef 2865 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2866
d62a17ae 2867 result->old = old_select;
2868 result->new = new_select;
96450faf 2869
d62a17ae 2870 return;
fee0f4c6 2871}
2872
3f9c7369
DS
2873/*
2874 * A new route/change in bestpath of an existing route. Evaluate the path
2875 * for advertisement to the subgroup.
2876 */
3dc339cd
DA
2877void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2878 struct bgp_path_info *selected,
9bcb3eef 2879 struct bgp_dest *dest,
3dc339cd 2880 uint32_t addpath_tx_id)
d62a17ae 2881{
b54892e0 2882 const struct prefix *p;
d62a17ae 2883 struct peer *onlypeer;
2884 struct attr attr;
2885 afi_t afi;
2886 safi_t safi;
a77e2f4b
S
2887 struct bgp *bgp;
2888 bool advertise;
adbac85e 2889
9bcb3eef 2890 p = bgp_dest_get_prefix(dest);
d62a17ae 2891 afi = SUBGRP_AFI(subgrp);
2892 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2893 bgp = SUBGRP_INST(subgrp);
d62a17ae 2894 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2895 : NULL);
2896
2dbe669b
DA
2897 if (BGP_DEBUG(update, UPDATE_OUT))
2898 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2899
d62a17ae 2900 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2901 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2902 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2903 return;
d62a17ae 2904
6006b807 2905 memset(&attr, 0, sizeof(attr));
d62a17ae 2906 /* It's initialized in bgp_announce_check() */
2907
a77e2f4b
S
2908 /* Announcement to the subgroup. If the route is filtered withdraw it.
2909 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2910 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2911 * route
d62a17ae 2912 */
a77e2f4b
S
2913 advertise = bgp_check_advertise(bgp, dest);
2914
d62a17ae 2915 if (selected) {
7f7940e6 2916 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2917 NULL)) {
a77e2f4b
S
2918 /* Route is selected, if the route is already installed
2919 * in FIB, then it is advertised
2920 */
be785e35
DS
2921 if (advertise) {
2922 if (!bgp_check_withdrawal(bgp, dest))
2923 bgp_adj_out_set_subgroup(
2924 dest, subgrp, &attr, selected);
2925 else
2926 bgp_adj_out_unset_subgroup(
2927 dest, subgrp, 1, addpath_tx_id);
2928 }
a77e2f4b 2929 } else
9bcb3eef 2930 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2931 addpath_tx_id);
d62a17ae 2932 }
2933
2934 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2935 else {
9bcb3eef 2936 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2937 }
200df115 2938}
fee0f4c6 2939
3064bf43 2940/*
e1072051 2941 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2942 * This is called at the end of route processing.
3064bf43 2943 */
9bcb3eef 2944void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2945{
40381db7 2946 struct bgp_path_info *pi;
3064bf43 2947
9bcb3eef 2948 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2949 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2950 continue;
40381db7
DS
2951 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2952 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2953 }
3064bf43 2954}
2955
2956/*
2957 * Has the route changed from the RIB's perspective? This is invoked only
2958 * if the route selection returns the same best route as earlier - to
2959 * determine if we need to update zebra or not.
2960 */
9bcb3eef 2961bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2962{
4b7e6066 2963 struct bgp_path_info *mpinfo;
d62a17ae 2964
2bb9eff4
DS
2965 /* If this is multipath, check all selected paths for any nexthop
2966 * change or attribute change. Some attribute changes (e.g., community)
2967 * aren't of relevance to the RIB, but we'll update zebra to ensure
2968 * we handle the case of BGP nexthop change. This is the behavior
2969 * when the best path has an attribute change anyway.
d62a17ae 2970 */
1defdda8 2971 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2972 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2973 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2974 return true;
d62a17ae 2975
2bb9eff4
DS
2976 /*
2977 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2978 */
18ee8310
DS
2979 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2980 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2981 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2982 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2983 return true;
d62a17ae 2984 }
3064bf43 2985
d62a17ae 2986 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2987 return false;
3064bf43 2988}
2989
d62a17ae 2990struct bgp_process_queue {
2991 struct bgp *bgp;
9bcb3eef 2992 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2993#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2994 unsigned int flags;
2995 unsigned int queued;
200df115 2996};
2997
3b0c17e1 2998static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2999 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3000 struct bgp_path_info *new_select,
3001 struct bgp_path_info *old_select)
3002{
9bcb3eef 3003 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3004
3005 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3006 return;
3007
3008 if (advertise_type5_routes(bgp, afi) && new_select
3009 && is_route_injectable_into_evpn(new_select)) {
3010
3011 /* apply the route-map */
3012 if (bgp->adv_cmd_rmap[afi][safi].map) {
3013 route_map_result_t ret;
3014 struct bgp_path_info rmap_path;
3015 struct bgp_path_info_extra rmap_path_extra;
3016 struct attr dummy_attr;
3017
3018 dummy_attr = *new_select->attr;
3019
3020 /* Fill temp path_info */
9bcb3eef 3021 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3022 new_select, new_select->peer,
3023 &dummy_attr);
3024
3025 RESET_FLAG(dummy_attr.rmap_change_flags);
3026
3027 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3028 p, &rmap_path);
3b0c17e1 3029
3030 if (ret == RMAP_DENYMATCH) {
3031 bgp_attr_flush(&dummy_attr);
3032 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3033 safi);
3034 } else
3035 bgp_evpn_advertise_type5_route(
3036 bgp, p, &dummy_attr, afi, safi);
3037 } else {
3038 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3039 afi, safi);
3040 }
3041 } else if (advertise_type5_routes(bgp, afi) && old_select
3042 && is_route_injectable_into_evpn(old_select))
3043 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3044}
3045
bb2ca692
MS
3046/*
3047 * Utility to determine whether a particular path_info should use
3048 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3049 * in a path where we basically _know_ this is a BGP-LU route.
3050 */
3051static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3052{
3053 /* Certain types get imp null; so do paths where the nexthop is
3054 * not labeled.
3055 */
3056 if (new_select->sub_type == BGP_ROUTE_STATIC
3057 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3058 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3059 return true;
3060 else if (new_select->extra == NULL ||
3061 !bgp_is_valid_label(&new_select->extra->label[0]))
3062 /* TODO -- should be configurable? */
3063 return true;
3064 else
3065 return false;
3066}
3067
3103e8d2
DS
3068/*
3069 * old_select = The old best path
3070 * new_select = the new best path
3071 *
3072 * if (!old_select && new_select)
3073 * We are sending new information on.
3074 *
3075 * if (old_select && new_select) {
3076 * if (new_select != old_select)
3077 * We have a new best path send a change
3078 * else
3079 * We've received a update with new attributes that needs
3080 * to be passed on.
3081 * }
3082 *
3083 * if (old_select && !new_select)
3084 * We have no eligible route that we can announce or the rn
3085 * is being removed.
3086 */
9bcb3eef 3087static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3088 afi_t afi, safi_t safi)
d62a17ae 3089{
4b7e6066
DS
3090 struct bgp_path_info *new_select;
3091 struct bgp_path_info *old_select;
3092 struct bgp_path_info_pair old_and_new;
ddb5b488 3093 int debug = 0;
d62a17ae 3094
892fedb6 3095 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3096 if (dest)
3097 debug = bgp_debug_bestpath(dest);
b54892e0 3098 if (debug)
f4c713ae 3099 zlog_debug(
56ca3b5b 3100 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3101 __func__, dest);
f4c713ae
LB
3102 return;
3103 }
d62a17ae 3104 /* Is it end of initial update? (after startup) */
9bcb3eef 3105 if (!dest) {
e36f61b5
DS
3106 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3107 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3108
3109 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3110 FOREACH_AFI_SAFI (afi, safi) {
3111 if (bgp_fibupd_safi(safi))
3112 bgp_zebra_announce_table(bgp, afi, safi);
3113 }
d62a17ae 3114 bgp->main_peers_update_hold = 0;
3115
3116 bgp_start_routeadv(bgp);
aac24838 3117 return;
d62a17ae 3118 }
cb1faec9 3119
9bcb3eef 3120 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3121
9bcb3eef 3122 debug = bgp_debug_bestpath(dest);
b54892e0 3123 if (debug)
4378495a
DS
3124 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3125 dest, bgp->name_pretty, afi2str(afi),
3126 safi2str(safi));
ddb5b488 3127
f009ff26 3128 /* The best path calculation for the route is deferred if
3129 * BGP_NODE_SELECT_DEFER is set
3130 */
9bcb3eef 3131 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3132 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3133 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3134 return;
3135 }
3136
d62a17ae 3137 /* Best path selection. */
9bcb3eef 3138 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3139 afi, safi);
3140 old_select = old_and_new.old;
3141 new_select = old_and_new.new;
3142
3143 /* Do we need to allocate or free labels?
3144 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3145 * necessary to do this upon changes to best path. Exceptions:
3146 * - label index has changed -> recalculate resulting label
3147 * - path_info sub_type changed -> switch to/from implicit-null
3148 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3149 */
318cac96 3150 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3151 if (new_select) {
3152 if (!old_select
3153 || bgp_label_index_differs(new_select, old_select)
57592a53 3154 || new_select->sub_type != old_select->sub_type
9bcb3eef 3155 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3156 /* Enforced penultimate hop popping:
3157 * implicit-null for local routes, aggregate
3158 * and redistributed routes
3159 */
bb2ca692 3160 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3161 if (CHECK_FLAG(
9bcb3eef 3162 dest->flags,
992dd67e
PR
3163 BGP_NODE_REGISTERED_FOR_LABEL)
3164 || CHECK_FLAG(
3165 dest->flags,
3166 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3167 bgp_unregister_for_label(dest);
67f67ba4
DA
3168 dest->local_label = mpls_lse_encode(
3169 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3170 1);
9bcb3eef 3171 bgp_set_valid_label(&dest->local_label);
d62a17ae 3172 } else
9bcb3eef
DS
3173 bgp_register_for_label(dest,
3174 new_select);
d62a17ae 3175 }
9bcb3eef 3176 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3177 BGP_NODE_REGISTERED_FOR_LABEL)
3178 || CHECK_FLAG(dest->flags,
3179 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3180 bgp_unregister_for_label(dest);
318cac96 3181 }
992dd67e
PR
3182 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3183 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3184 bgp_unregister_for_label(dest);
d62a17ae 3185 }
cd1964ff 3186
b54892e0 3187 if (debug)
ddb5b488 3188 zlog_debug(
4378495a
DS
3189 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3190 __func__, dest, bgp->name_pretty, afi2str(afi),
3191 safi2str(safi), old_select, new_select);
ddb5b488 3192
d62a17ae 3193 /* If best route remains the same and this is not due to user-initiated
3194 * clear, see exactly what needs to be done.
3195 */
d62a17ae 3196 if (old_select && old_select == new_select
9bcb3eef 3197 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3198 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3199 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3200 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3201#ifdef ENABLE_BGP_VNC
d62a17ae 3202 vnc_import_bgp_add_route(bgp, p, old_select);
3203 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3204#endif
bb744275 3205 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3206 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3207
be785e35
DS
3208 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3209 && new_select->sub_type == BGP_ROUTE_NORMAL)
3210 SET_FLAG(dest->flags,
3211 BGP_NODE_FIB_INSTALL_PENDING);
3212
ddb5b488
PZ
3213 if (new_select->type == ZEBRA_ROUTE_BGP
3214 && (new_select->sub_type == BGP_ROUTE_NORMAL
3215 || new_select->sub_type
3216 == BGP_ROUTE_IMPORTED))
3217
9bcb3eef 3218 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3219 bgp, afi, safi);
3220 }
d62a17ae 3221 }
d62a17ae 3222
3223 /* If there is a change of interest to peers, reannounce the
3224 * route. */
1defdda8 3225 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3226 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3227 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3228 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3229
3230 /* unicast routes must also be annouced to
3231 * labeled-unicast update-groups */
3232 if (safi == SAFI_UNICAST)
3233 group_announce_route(bgp, afi,
9bcb3eef 3234 SAFI_LABELED_UNICAST, dest,
d62a17ae 3235 new_select);
3236
1defdda8 3237 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3238 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3239 }
fee0f4c6 3240
3b0c17e1 3241 /* advertise/withdraw type-5 routes */
3242 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3243 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3244 bgp_process_evpn_route_injection(
9bcb3eef 3245 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3246
b1875e65 3247 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3248 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3249 bgp_zebra_clear_route_change_flags(dest);
3250 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3251 return;
d62a17ae 3252 }
8ad7271d 3253
d62a17ae 3254 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3255 */
9bcb3eef 3256 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3257
3258 /* bestpath has changed; bump version */
3259 if (old_select || new_select) {
9bcb3eef 3260 bgp_bump_version(dest);
d62a17ae 3261
3262 if (!bgp->t_rmap_def_originate_eval) {
3263 bgp_lock(bgp);
3264 thread_add_timer(
3265 bm->master,
3266 update_group_refresh_default_originate_route_map,
3267 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3268 &bgp->t_rmap_def_originate_eval);
3269 }
3270 }
3f9c7369 3271
d62a17ae 3272 if (old_select)
9bcb3eef 3273 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3274 if (new_select) {
ddb5b488
PZ
3275 if (debug)
3276 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3277 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3278 bgp_path_info_unset_flag(dest, new_select,
3279 BGP_PATH_ATTR_CHANGED);
1defdda8 3280 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3281 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3282 }
338b3424 3283
49e5a4a0 3284#ifdef ENABLE_BGP_VNC
d62a17ae 3285 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3286 if (old_select != new_select) {
3287 if (old_select) {
3288 vnc_import_bgp_exterior_del_route(bgp, p,
3289 old_select);
3290 vnc_import_bgp_del_route(bgp, p, old_select);
3291 }
3292 if (new_select) {
3293 vnc_import_bgp_exterior_add_route(bgp, p,
3294 new_select);
3295 vnc_import_bgp_add_route(bgp, p, new_select);
3296 }
3297 }
3298 }
65efcfce
LB
3299#endif
3300
9bcb3eef 3301 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3302
3303 /* unicast routes must also be annouced to labeled-unicast update-groups
3304 */
3305 if (safi == SAFI_UNICAST)
9bcb3eef 3306 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3307 new_select);
3308
3309 /* FIB update. */
3310 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3311 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3312
d62a17ae 3313 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3314 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3315 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3316 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3317
be785e35
DS
3318 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3319 SET_FLAG(dest->flags,
3320 BGP_NODE_FIB_INSTALL_PENDING);
3321
2b659f33
MK
3322 /* if this is an evpn imported type-5 prefix,
3323 * we need to withdraw the route first to clear
3324 * the nh neigh and the RMAC entry.
3325 */
3326 if (old_select &&
3327 is_route_parent_evpn(old_select))
3328 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3329
9bcb3eef 3330 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3331 } else {
d62a17ae 3332 /* Withdraw the route from the kernel. */
3333 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3334 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3335 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3336 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3337
568e10ca 3338 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3339 }
718e3744 3340 }
3064bf43 3341
9bcb3eef 3342 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3343 old_select);
5424b7ba 3344
d62a17ae 3345 /* Clear any route change flags. */
9bcb3eef 3346 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3347
18ee8310 3348 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3349 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3350 bgp_path_info_reap(dest, old_select);
d62a17ae 3351
9bcb3eef 3352 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3353 return;
718e3744 3354}
3355
f009ff26 3356/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3357void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3358{
9bcb3eef 3359 struct bgp_dest *dest;
f009ff26 3360 int cnt = 0;
3361 struct afi_safi_info *thread_info;
f009ff26 3362
56c226e7
DS
3363 if (bgp->gr_info[afi][safi].t_route_select) {
3364 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3365
3366 thread_info = THREAD_ARG(t);
3367 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3368 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3369 }
f009ff26 3370
3371 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3372 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3373 get_afi_safi_str(afi, safi, false),
26742171 3374 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3375 }
3376
3377 /* Process the route list */
6338d242 3378 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3379 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3380 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3381 dest = bgp_route_next(dest)) {
3382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3383 continue;
3384
3385 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3386 bgp->gr_info[afi][safi].gr_deferred--;
3387 bgp_process_main_one(bgp, dest, afi, safi);
3388 cnt++;
067ea165
CB
3389 }
3390 /* If iteration stopped before the entire table was traversed then the
3391 * node needs to be unlocked.
3392 */
3393 if (dest) {
3394 bgp_dest_unlock_node(dest);
3395 dest = NULL;
f009ff26 3396 }
3397
9e3b51a7 3398 /* Send EOR message when all routes are processed */
6338d242 3399 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3400 bgp_send_delayed_eor(bgp);
8c48b3b6 3401 /* Send route processing complete message to RIB */
3402 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3403 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3404 return;
9e3b51a7 3405 }
f009ff26 3406
3407 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3408
3409 thread_info->afi = afi;
3410 thread_info->safi = safi;
3411 thread_info->bgp = bgp;
3412
3413 /* If there are more routes to be processed, start the
3414 * selection timer
3415 */
3416 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3417 BGP_ROUTE_SELECT_DELAY,
3418 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3419}
3420
aac24838 3421static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3422{
aac24838
JB
3423 struct bgp_process_queue *pqnode = data;
3424 struct bgp *bgp = pqnode->bgp;
d62a17ae 3425 struct bgp_table *table;
9bcb3eef 3426 struct bgp_dest *dest;
aac24838
JB
3427
3428 /* eoiu marker */
3429 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3430 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3431 /* should always have dedicated wq call */
3432 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3433 return WQ_SUCCESS;
3434 }
3435
ac021f40 3436 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3437 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3438 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3439 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3440 table = bgp_dest_table(dest);
3441 /* note, new DESTs may be added as part of processing */
3442 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3443
9bcb3eef 3444 bgp_dest_unlock_node(dest);
d62a17ae 3445 bgp_table_unlock(table);
3446 }
aac24838
JB
3447
3448 return WQ_SUCCESS;
3449}
3450
3451static void bgp_processq_del(struct work_queue *wq, void *data)
3452{
3453 struct bgp_process_queue *pqnode = data;
3454
3455 bgp_unlock(pqnode->bgp);
3456
3457 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3458}
3459
b6c386bb 3460void bgp_process_queue_init(struct bgp *bgp)
200df115 3461{
b6c386bb
DS
3462 if (!bgp->process_queue) {
3463 char name[BUFSIZ];
3464
3465 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3466 bgp->process_queue = work_queue_new(bm->master, name);
3467 }
3468
3469 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3470 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3471 bgp->process_queue->spec.max_retries = 0;
3472 bgp->process_queue->spec.hold = 50;
d62a17ae 3473 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3474 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3475}
3476
cfe8d15a 3477static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3478{
3479 struct bgp_process_queue *pqnode;
3480
a4d82a8a
PZ
3481 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3482 sizeof(struct bgp_process_queue));
aac24838
JB
3483
3484 /* unlocked in bgp_processq_del */
3485 pqnode->bgp = bgp_lock(bgp);
3486 STAILQ_INIT(&pqnode->pqueue);
3487
aac24838
JB
3488 return pqnode;
3489}
3490
9bcb3eef 3491void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3492{
aac24838 3493#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3494 struct work_queue *wq = bgp->process_queue;
d62a17ae 3495 struct bgp_process_queue *pqnode;
cfe8d15a 3496 int pqnode_reuse = 0;
495f0b13 3497
d62a17ae 3498 /* already scheduled for processing? */
9bcb3eef 3499 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3500 return;
2e02b9b2 3501
f009ff26 3502 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3503 * the workqueue
3504 */
9bcb3eef 3505 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3506 if (BGP_DEBUG(update, UPDATE_OUT))
3507 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3508 dest);
f009ff26 3509 return;
3510 }
3511
46aeabed
LS
3512 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3513 if (BGP_DEBUG(update, UPDATE_OUT))
3514 zlog_debug(
3515 "Soft reconfigure table in progress for route %p",
3516 dest);
3517 return;
3518 }
3519
aac24838 3520 if (wq == NULL)
d62a17ae 3521 return;
3522
aac24838 3523 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3524 limit only if is from the same BGP view and it's not an EOIU marker
3525 */
aac24838
JB
3526 if (work_queue_item_count(wq)) {
3527 struct work_queue_item *item = work_queue_last_item(wq);
3528 pqnode = item->data;
228da428 3529
a4d82a8a
PZ
3530 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3531 || pqnode->bgp != bgp
3532 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3533 pqnode = bgp_processq_alloc(bgp);
3534 else
3535 pqnode_reuse = 1;
aac24838 3536 } else
cfe8d15a 3537 pqnode = bgp_processq_alloc(bgp);
aac24838 3538 /* all unlocked in bgp_process_wq */
9bcb3eef 3539 bgp_table_lock(bgp_dest_table(dest));
aac24838 3540
9bcb3eef
DS
3541 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3542 bgp_dest_lock_node(dest);
aac24838 3543
60466a63 3544 /* can't be enqueued twice */
9bcb3eef
DS
3545 assert(STAILQ_NEXT(dest, pq) == NULL);
3546 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3547 pqnode->queued++;
3548
cfe8d15a
LB
3549 if (!pqnode_reuse)
3550 work_queue_add(wq, pqnode);
3551
d62a17ae 3552 return;
fee0f4c6 3553}
0a486e5f 3554
d62a17ae 3555void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3556{
d62a17ae 3557 struct bgp_process_queue *pqnode;
cb1faec9 3558
b6c386bb 3559 if (bgp->process_queue == NULL)
d62a17ae 3560 return;
2e02b9b2 3561
cfe8d15a 3562 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3563
aac24838 3564 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3565 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3566}
3567
cc9f21da 3568static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3569{
d62a17ae 3570 struct peer *peer;
0a486e5f 3571
d62a17ae 3572 peer = THREAD_ARG(thread);
3573 peer->t_pmax_restart = NULL;
0a486e5f 3574
d62a17ae 3575 if (bgp_debug_neighbor_events(peer))
3576 zlog_debug(
3577 "%s Maximum-prefix restart timer expired, restore peering",
3578 peer->host);
0a486e5f 3579
a9bafa95 3580 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3581 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3582}
3583
9cbd06e0
DA
3584static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3585 safi_t safi)
3586{
3587 uint32_t count = 0;
f41b0459 3588 bool filtered = false;
9cbd06e0
DA
3589 struct bgp_dest *dest;
3590 struct bgp_adj_in *ain;
40bb2ccf 3591 struct attr attr = {};
9cbd06e0
DA
3592 struct bgp_table *table = peer->bgp->rib[afi][safi];
3593
3594 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3595 for (ain = dest->adj_in; ain; ain = ain->next) {
3596 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3597
3598 attr = *ain->attr;
9cbd06e0
DA
3599
3600 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3601 == FILTER_DENY)
f41b0459
DA
3602 filtered = true;
3603
3604 if (bgp_input_modifier(
3605 peer, rn_p, &attr, afi, safi,
3606 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3607 NULL, 0, NULL)
3608 == RMAP_DENY)
3609 filtered = true;
3610
3611 if (filtered)
9cbd06e0 3612 count++;
f41b0459 3613
d498917e 3614 bgp_attr_flush(&attr);
9cbd06e0
DA
3615 }
3616 }
3617
3618 return count;
3619}
3620
3dc339cd
DA
3621bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3622 int always)
718e3744 3623{
d62a17ae 3624 iana_afi_t pkt_afi;
5c525538 3625 iana_safi_t pkt_safi;
9cbd06e0
DA
3626 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3627 PEER_FLAG_MAX_PREFIX_FORCE))
3628 ? bgp_filtered_routes_count(peer, afi, safi)
3629 + peer->pcount[afi][safi]
3630 : peer->pcount[afi][safi];
9cabb64b 3631
d62a17ae 3632 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3633 return false;
e0701b79 3634
9cbd06e0 3635 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3636 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3637 PEER_STATUS_PREFIX_LIMIT)
3638 && !always)
3dc339cd 3639 return false;
e0701b79 3640
d62a17ae 3641 zlog_info(
f70c91dc
DA
3642 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3643 get_afi_safi_str(afi, safi, false), peer, pcount,
3644 peer->pmax[afi][safi]);
d62a17ae 3645 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3646
3647 if (CHECK_FLAG(peer->af_flags[afi][safi],
3648 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3649 return false;
d62a17ae 3650
3651 /* Convert AFI, SAFI to values for packet. */
3652 pkt_afi = afi_int2iana(afi);
3653 pkt_safi = safi_int2iana(safi);
3654 {
d7c0a89a 3655 uint8_t ndata[7];
d62a17ae 3656
3657 ndata[0] = (pkt_afi >> 8);
3658 ndata[1] = pkt_afi;
3659 ndata[2] = pkt_safi;
3660 ndata[3] = (peer->pmax[afi][safi] >> 24);
3661 ndata[4] = (peer->pmax[afi][safi] >> 16);
3662 ndata[5] = (peer->pmax[afi][safi] >> 8);
3663 ndata[6] = (peer->pmax[afi][safi]);
3664
3665 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3666 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3667 BGP_NOTIFY_CEASE_MAX_PREFIX,
3668 ndata, 7);
3669 }
3670
3671 /* Dynamic peers will just close their connection. */
3672 if (peer_dynamic_neighbor(peer))
3dc339cd 3673 return true;
d62a17ae 3674
3675 /* restart timer start */
3676 if (peer->pmax_restart[afi][safi]) {
3677 peer->v_pmax_restart =
3678 peer->pmax_restart[afi][safi] * 60;
3679
3680 if (bgp_debug_neighbor_events(peer))
3681 zlog_debug(
f70c91dc
DA
3682 "%pBP Maximum-prefix restart timer started for %d secs",
3683 peer, peer->v_pmax_restart);
d62a17ae 3684
3685 BGP_TIMER_ON(peer->t_pmax_restart,
3686 bgp_maximum_prefix_restart_timer,
3687 peer->v_pmax_restart);
3688 }
3689
3dc339cd 3690 return true;
d62a17ae 3691 } else
3692 UNSET_FLAG(peer->af_sflags[afi][safi],
3693 PEER_STATUS_PREFIX_LIMIT);
3694
b1823b69
DS
3695 if (pcount
3696 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3697 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3698 PEER_STATUS_PREFIX_THRESHOLD)
3699 && !always)
3dc339cd 3700 return false;
d62a17ae 3701
3702 zlog_info(
f70c91dc
DA
3703 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3704 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3705 peer->pmax[afi][safi]);
d62a17ae 3706 SET_FLAG(peer->af_sflags[afi][safi],
3707 PEER_STATUS_PREFIX_THRESHOLD);
3708 } else
3709 UNSET_FLAG(peer->af_sflags[afi][safi],
3710 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3711 return false;
718e3744 3712}
3713
b40d939b 3714/* Unconditionally remove the route from the RIB, without taking
3715 * damping into consideration (eg, because the session went down)
3716 */
9bcb3eef 3717void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3718 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3719{
f009ff26 3720
3721 struct bgp *bgp = NULL;
3722 bool delete_route = false;
3723
9bcb3eef
DS
3724 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3725 safi);
d62a17ae 3726
f009ff26 3727 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3728 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3729
f009ff26 3730 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3731 * flag
3732 */
3733 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3734 delete_route = true;
9bcb3eef 3735 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3736 delete_route = true;
f009ff26 3737 if (delete_route) {
9bcb3eef
DS
3738 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3739 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3740 bgp = pi->peer->bgp;
26742171 3741 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3742 }
3743 }
3744 }
4a11bf2c 3745
9bcb3eef
DS
3746 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3747 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3748}
3749
9bcb3eef 3750static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3751 struct peer *peer, afi_t afi, safi_t safi,
3752 struct prefix_rd *prd)
3753{
9bcb3eef 3754 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3755
d62a17ae 3756 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3757 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3758 */
b4f7f45b
IR
3759 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3760 && peer->sort == BGP_PEER_EBGP)
3761 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3762 == BGP_DAMP_SUPPRESSED) {
3763 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3764 safi);
3765 return;
d62a17ae 3766 }
3767
49e5a4a0 3768#ifdef ENABLE_BGP_VNC
d62a17ae 3769 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3770 struct bgp_dest *pdest = NULL;
d62a17ae 3771 struct bgp_table *table = NULL;
3772
9bcb3eef
DS
3773 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3774 (struct prefix *)prd);
3775 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3776 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3777
3778 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3779 peer->bgp, prd, table, p, pi);
d62a17ae 3780 }
9bcb3eef 3781 bgp_dest_unlock_node(pdest);
d62a17ae 3782 }
3783 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3784 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3785
b54892e0
DS
3786 vnc_import_bgp_del_route(peer->bgp, p, pi);
3787 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3788 }
65efcfce 3789 }
d62a17ae 3790#endif
128ea8ab 3791
d62a17ae 3792 /* If this is an EVPN route, process for un-import. */
3793 if (safi == SAFI_EVPN)
b54892e0 3794 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3795
9bcb3eef 3796 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3797}
3798
4b7e6066
DS
3799struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3800 struct peer *peer, struct attr *attr,
9bcb3eef 3801 struct bgp_dest *dest)
fb018d25 3802{
4b7e6066 3803 struct bgp_path_info *new;
fb018d25 3804
d62a17ae 3805 /* Make new BGP info. */
4b7e6066 3806 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3807 new->type = type;
3808 new->instance = instance;
3809 new->sub_type = sub_type;
3810 new->peer = peer;
3811 new->attr = attr;
083ec940 3812 new->uptime = monotime(NULL);
9bcb3eef 3813 new->net = dest;
d62a17ae 3814 return new;
fb018d25
DS
3815}
3816
c265ee22 3817/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3818bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3819 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3820 struct bgp_dest *dest)
d62a17ae 3821{
2dbe3fa9 3822 bool ret = false;
b099a5c8
DA
3823 bool is_bgp_static_route =
3824 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3825 : false;
d62a17ae 3826
e8442016
DS
3827 /*
3828 * Only validated for unicast and multicast currently.
3829 * Also valid for EVPN where the nexthop is an IP address.
3830 * If we are a bgp static route being checked then there is
3831 * no need to check to see if the nexthop is martian as
3832 * that it should be ok.
3833 */
3834 if (is_bgp_static_route ||
3835 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3836 return false;
d62a17ae 3837
3838 /* If NEXT_HOP is present, validate it. */
3839 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3840 if (attr->nexthop.s_addr == INADDR_ANY ||
3841 !ipv4_unicast_valid(&attr->nexthop) ||
3842 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3843 return true;
d62a17ae 3844 }
c265ee22 3845
d62a17ae 3846 /* If MP_NEXTHOP is present, validate it. */
3847 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3848 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3849 * it is not an IPv6 link-local address.
0355b41d
DA
3850 *
3851 * If we receive an UPDATE with nexthop length set to 32 bytes
3852 * we shouldn't discard an UPDATE if it's set to (::).
3853 * The link-local (2st) is validated along the code path later.
d62a17ae 3854 */
3855 if (attr->mp_nexthop_len) {
3856 switch (attr->mp_nexthop_len) {
3857 case BGP_ATTR_NHLEN_IPV4:
3858 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3859 ret = (attr->mp_nexthop_global_in.s_addr ==
3860 INADDR_ANY ||
3861 !ipv4_unicast_valid(
3862 &attr->mp_nexthop_global_in) ||
3863 bgp_nexthop_self(bgp, afi, type, stype, attr,
3864 dest));
d62a17ae 3865 break;
3866
3867 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3868 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3869 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3870 &attr->mp_nexthop_global)
d62a17ae 3871 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3872 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3873 &attr->mp_nexthop_global)
3874 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3875 dest));
d62a17ae 3876 break;
0355b41d
DA
3877 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3878 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3879 || IN6_IS_ADDR_MULTICAST(
3880 &attr->mp_nexthop_global)
3881 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3882 dest));
0355b41d 3883 break;
d62a17ae 3884
3885 default:
3dc339cd 3886 ret = true;
d62a17ae 3887 break;
3888 }
3889 }
c265ee22 3890
d62a17ae 3891 return ret;
3892}
3893
aade37d7 3894static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3895{
3896 struct community *old;
3897 struct community *new;
3898 struct community *merge;
aade37d7 3899 struct community *no_export;
2721dd61 3900
9a706b42 3901 old = bgp_attr_get_community(attr);
aade37d7 3902 no_export = community_str2com("no-export");
2721dd61 3903
b4efa101
DA
3904 assert(no_export);
3905
2721dd61 3906 if (old) {
aade37d7 3907 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3908
3909 if (!old->refcnt)
3910 community_free(&old);
3911
3912 new = community_uniq_sort(merge);
3913 community_free(&merge);
3914 } else {
aade37d7 3915 new = community_dup(no_export);
2721dd61
DA
3916 }
3917
aade37d7 3918 community_free(&no_export);
2721dd61 3919
9a706b42 3920 bgp_attr_set_community(attr, new);
2721dd61
DA
3921}
3922
46dbf9d0
DA
3923static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3924 struct attr *attr, const struct prefix *prefix,
3925 int *sub_type)
3926{
3927 struct listnode *node, *nnode;
3928 struct bgp *bgp;
3929 bool accept_own_found = false;
3930
3931 if (safi != SAFI_MPLS_VPN)
3932 return false;
3933
3934 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3935 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3936 return false;
3937
3938 /* The route in question carries the ACCEPT_OWN community */
3939 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3940 struct community *comm = bgp_attr_get_community(attr);
3941
3942 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3943 accept_own_found = true;
3944 }
3945
3946 /* The route in question is targeted to one or more destination VRFs
3947 * on the router (as determined by inspecting the Route Target(s)).
3948 */
3949 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3950 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3951 continue;
3952
3953 if (accept_own_found &&
3954 ecommunity_include(
3955 bgp->vpn_policy[afi]
3956 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3957 bgp_attr_get_ecommunity(attr))) {
3958 if (bgp_debug_update(peer, prefix, NULL, 1))
3959 zlog_debug(
3960 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3961 peer, prefix);
3962
3963 /* Treat this route as imported, because it's leaked
3964 * already from another VRF, and we got an updated
3965 * version from route-reflector with ACCEPT_OWN
3966 * community.
3967 */
3968 *sub_type = BGP_ROUTE_IMPORTED;
3969
3970 return true;
3971 }
3972 }
3973
3974 return false;
3975}
3976
5a1ae2c2 3977int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3978 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3979 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3980 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3981 struct bgp_route_evpn *evpn)
d62a17ae 3982{
3983 int ret;
3984 int aspath_loop_count = 0;
9bcb3eef 3985 struct bgp_dest *dest;
d62a17ae 3986 struct bgp *bgp;
3987 struct attr new_attr;
3988 struct attr *attr_new;
40381db7 3989 struct bgp_path_info *pi;
4b7e6066
DS
3990 struct bgp_path_info *new;
3991 struct bgp_path_info_extra *extra;
d62a17ae 3992 const char *reason;
3993 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3994 int connected = 0;
3995 int do_loop_check = 1;
3996 int has_valid_label = 0;
7c312383 3997 afi_t nh_afi;
9146341f 3998 bool force_evpn_import = false;
907707db 3999 safi_t orig_safi = safi;
a486300b 4000 bool leak_success = true;
949b0f24 4001
c7bb4f00 4002 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4003 char pfxprint[PREFIX2STR_BUFFER];
4004
4005 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4006 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4007 afi, safi, attr);
6401252f
QY
4008 }
4009
49e5a4a0 4010#ifdef ENABLE_BGP_VNC
d62a17ae 4011 int vnc_implicit_withdraw = 0;
65efcfce 4012#endif
d62a17ae 4013 int same_attr = 0;
718e3744 4014
907707db
MS
4015 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4016 if (orig_safi == SAFI_LABELED_UNICAST)
4017 safi = SAFI_UNICAST;
4018
6006b807 4019 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4020 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4021 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4022
d62a17ae 4023 bgp = peer->bgp;
9bcb3eef 4024 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4025 /* TODO: Check to see if we can get rid of "is_valid_label" */
4026 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4027 has_valid_label = (num_labels > 0) ? 1 : 0;
4028 else
4029 has_valid_label = bgp_is_valid_label(label);
718e3744 4030
28f66de2
MS
4031 if (has_valid_label)
4032 assert(label != NULL);
4033
66ff6089
AD
4034 /* Update overlay index of the attribute */
4035 if (afi == AFI_L2VPN && evpn)
4036 memcpy(&attr->evpn_overlay, evpn,
4037 sizeof(struct bgp_route_evpn));
4038
d62a17ae 4039 /* When peer's soft reconfiguration enabled. Record input packet in
4040 Adj-RIBs-In. */
4041 if (!soft_reconfig
4042 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4043 && peer != bgp->peer_self)
9bcb3eef 4044 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4045
4046 /* Check previously received route. */
9bcb3eef 4047 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4048 if (pi->peer == peer && pi->type == type
4049 && pi->sub_type == sub_type
4050 && pi->addpath_rx_id == addpath_id)
d62a17ae 4051 break;
4052
4053 /* AS path local-as loop check. */
4054 if (peer->change_local_as) {
c4368918
DW
4055 if (peer->allowas_in[afi][safi])
4056 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
4057 else if (!CHECK_FLAG(peer->flags,
4058 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4059 aspath_loop_count = 1;
4060
4061 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4062 > aspath_loop_count) {
b4d46cc9 4063 peer->stat_pfx_aspath_loop++;
692174a1 4064 reason = "as-path contains our own AS;";
d62a17ae 4065 goto filtered;
4066 }
718e3744 4067 }
718e3744 4068
d62a17ae 4069 /* If the peer is configured for "allowas-in origin" and the last ASN in
4070 * the
4071 * as-path is our ASN then we do not need to call aspath_loop_check
4072 */
4073 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4074 if (aspath_get_last_as(attr->aspath) == bgp->as)
4075 do_loop_check = 0;
4076
4077 /* AS path loop check. */
4078 if (do_loop_check) {
4079 if (aspath_loop_check(attr->aspath, bgp->as)
4080 > peer->allowas_in[afi][safi]
4081 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
4082 && aspath_loop_check(attr->aspath, bgp->confed_id)
4083 > peer->allowas_in[afi][safi])) {
b4d46cc9 4084 peer->stat_pfx_aspath_loop++;
d62a17ae 4085 reason = "as-path contains our own AS;";
4086 goto filtered;
4087 }
4088 }
aac9ef6c 4089
46dbf9d0
DA
4090 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4091 * enabled, then take care of that too.
4092 */
4093 bool accept_own = false;
4094
d62a17ae 4095 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4096 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4097 accept_own =
4098 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4099 if (!accept_own) {
4100 peer->stat_pfx_originator_loop++;
4101 reason = "originator is us;";
4102 goto filtered;
4103 }
d62a17ae 4104 }
718e3744 4105
d62a17ae 4106 /* Route reflector cluster ID check. */
4107 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4108 peer->stat_pfx_cluster_loop++;
d62a17ae 4109 reason = "reflected from the same cluster;";
4110 goto filtered;
4111 }
718e3744 4112
d62a17ae 4113 /* Apply incoming filter. */
907707db 4114 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4115 peer->stat_pfx_filter++;
d62a17ae 4116 reason = "filter;";
4117 goto filtered;
4118 }
718e3744 4119
a8b72dc6
DA
4120 /* RFC 8212 to prevent route leaks.
4121 * This specification intends to improve this situation by requiring the
4122 * explicit configuration of both BGP Import and Export Policies for any
4123 * External BGP (EBGP) session such as customers, peers, or
4124 * confederation boundaries for all enabled address families. Through
4125 * codification of the aforementioned requirement, operators will
4126 * benefit from consistent behavior across different BGP
4127 * implementations.
4128 */
1d3fdccf 4129 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4130 if (!bgp_inbound_policy_exists(peer,
4131 &peer->filter[afi][safi])) {
4132 reason = "inbound policy missing";
b17826b7
DS
4133 if (monotime_since(&bgp->ebgprequirespolicywarning,
4134 NULL) > FIFTEENMINUTE2USEC ||
4135 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4136 zlog_warn(
4137 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4138 monotime(&bgp->ebgprequirespolicywarning);
4139 }
a8b72dc6
DA
4140 goto filtered;
4141 }
4142
fb29348a
DA
4143 /* draft-ietf-idr-deprecate-as-set-confed-set
4144 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4145 * Eventually, This document (if approved) updates RFC 4271
4146 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4147 * and obsoletes RFC 6472.
4148 */
7f972cd8 4149 if (peer->bgp->reject_as_sets)
fb29348a
DA
4150 if (aspath_check_as_sets(attr->aspath)) {
4151 reason =
4152 "as-path contains AS_SET or AS_CONFED_SET type;";
4153 goto filtered;
4154 }
4155
6f4f49b2 4156 new_attr = *attr;
d62a17ae 4157
4158 /* Apply incoming route-map.
4159 * NB: new_attr may now contain newly allocated values from route-map
4160 * "set"
4161 * commands, so we need bgp_attr_flush in the error paths, until we
4162 * intern
4163 * the attr (which takes over the memory references) */
907707db 4164 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4165 num_labels, dest)
4166 == RMAP_DENY) {
b4d46cc9 4167 peer->stat_pfx_filter++;
d62a17ae 4168 reason = "route-map;";
4169 bgp_attr_flush(&new_attr);
4170 goto filtered;
4171 }
718e3744 4172
05864da7 4173 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4174 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4175 /* remove from RIB previous entry */
4176 bgp_zebra_withdraw(p, pi, bgp, safi);
4177 }
4178
7f323236
DW
4179 if (peer->sort == BGP_PEER_EBGP) {
4180
2721dd61
DA
4181 /* rfc7999:
4182 * A BGP speaker receiving an announcement tagged with the
4183 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4184 * NO_EXPORT community as defined in RFC1997, or a
4185 * similar community, to prevent propagation of the
4186 * prefix outside the local AS. The community to prevent
4187 * propagation SHOULD be chosen according to the operator's
4188 * routing policy.
4189 */
9a706b42
DA
4190 if (bgp_attr_get_community(&new_attr) &&
4191 community_include(bgp_attr_get_community(&new_attr),
4192 COMMUNITY_BLACKHOLE))
aade37d7 4193 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4194
a4d82a8a
PZ
4195 /* If we receive the graceful-shutdown community from an eBGP
4196 * peer we must lower local-preference */
9a706b42
DA
4197 if (bgp_attr_get_community(&new_attr) &&
4198 community_include(bgp_attr_get_community(&new_attr),
4199 COMMUNITY_GSHUT)) {
7f323236
DW
4200 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4201 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4202
a4d82a8a
PZ
4203 /* If graceful-shutdown is configured then add the GSHUT
4204 * community to all paths received from eBGP peers */
637e5ba4 4205 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4206 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4207 }
4208
d62a17ae 4209 /* next hop check. */
860ad3f9
DS
4210 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4211 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4212 &new_attr, dest)) {
b4d46cc9 4213 peer->stat_pfx_nh_invalid++;
d62a17ae 4214 reason = "martian or self next-hop;";
4215 bgp_attr_flush(&new_attr);
4216 goto filtered;
4217 }
718e3744 4218
5c14a191 4219 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4220 peer->stat_pfx_nh_invalid++;
4e802e66 4221 reason = "self mac;";
4dbf2038 4222 bgp_attr_flush(&new_attr);
4e802e66
DS
4223 goto filtered;
4224 }
4225
5a78f2bc
EB
4226 if (bgp_check_role_applicability(afi, safi) &&
4227 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4228 reason = "failing otc validation";
4229 bgp_attr_flush(&new_attr);
4230 goto filtered;
4231 }
a1b773e2
DS
4232 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4233 * condition :
4234 * Suppress fib is enabled
4235 * BGP_OPT_NO_FIB is not enabled
4236 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4237 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4238 */
4239 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4240 && (sub_type == BGP_ROUTE_NORMAL)
4241 && (!bgp_option_check(BGP_OPT_NO_FIB))
4242 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4243 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4244
9cbd06e0
DA
4245 /* If maximum prefix count is configured and current prefix
4246 * count exeed it.
4247 */
4dbf2038
IR
4248 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4249 bgp_attr_flush(&new_attr);
9cbd06e0 4250 return -1;
4dbf2038
IR
4251 }
4252
01da2d26
DA
4253 /* If neighbor soo is configured, tag all incoming routes with
4254 * this SoO tag and then filter out advertisements in
4255 * subgroup_announce_check() if it matches the configured SoO
4256 * on the other peer.
4257 */
4258 if (peer->soo[afi][safi]) {
4259 struct ecommunity *old_ecomm =
4260 bgp_attr_get_ecommunity(&new_attr);
4261 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4262 struct ecommunity *new_ecomm;
4263
4264 if (old_ecomm) {
4265 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4266 ecomm_soo);
4267
4268 if (!old_ecomm->refcnt)
4269 ecommunity_free(&old_ecomm);
4270 } else {
4271 new_ecomm = ecommunity_dup(ecomm_soo);
4272 }
4273
4274 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4275 }
4276
4dbf2038 4277 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4278
d62a17ae 4279 /* If the update is implicit withdraw. */
40381db7 4280 if (pi) {
083ec940 4281 pi->uptime = monotime(NULL);
40381db7 4282 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4283
9bcb3eef 4284 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4285
d62a17ae 4286 /* Same attribute comes in. */
40381db7 4287 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4288 && same_attr
d62a17ae 4289 && (!has_valid_label
40381db7 4290 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4291 num_labels * sizeof(mpls_label_t))
66ff6089 4292 == 0)) {
b4f7f45b
IR
4293 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4294 BGP_CONFIG_DAMPENING)
d62a17ae 4295 && peer->sort == BGP_PEER_EBGP
40381db7 4296 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4297 if (bgp_debug_update(peer, p, NULL, 1)) {
4298 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4299 afi, safi, prd, p, label,
4300 num_labels, addpath_id ? 1 : 0,
66ff6089 4301 addpath_id, evpn, pfx_buf,
a4d82a8a 4302 sizeof(pfx_buf));
f70c91dc 4303 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4304 pfx_buf);
4305 }
4306
9bcb3eef 4307 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4308 != BGP_DAMP_SUPPRESSED) {
40381db7 4309 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4310 safi);
9bcb3eef 4311 bgp_process(bgp, dest, afi, safi);
d62a17ae 4312 }
4313 } else /* Duplicate - odd */
4314 {
4315 if (bgp_debug_update(peer, p, NULL, 1)) {
4316 if (!peer->rcvd_attr_printed) {
4317 zlog_debug(
f70c91dc
DA
4318 "%pBP rcvd UPDATE w/ attr: %s",
4319 peer,
d62a17ae 4320 peer->rcvd_attr_str);
4321 peer->rcvd_attr_printed = 1;
4322 }
4323
4324 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4325 afi, safi, prd, p, label,
4326 num_labels, addpath_id ? 1 : 0,
66ff6089 4327 addpath_id, evpn, pfx_buf,
a4d82a8a 4328 sizeof(pfx_buf));
d62a17ae 4329 zlog_debug(
f70c91dc
DA
4330 "%pBP rcvd %s...duplicate ignored",
4331 peer, pfx_buf);
d62a17ae 4332 }
4333
4334 /* graceful restart STALE flag unset. */
40381db7 4335 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4336 bgp_path_info_unset_flag(
9bcb3eef
DS
4337 dest, pi, BGP_PATH_STALE);
4338 bgp_dest_set_defer_flag(dest, false);
4339 bgp_process(bgp, dest, afi, safi);
d62a17ae 4340 }
4341 }
4342
9bcb3eef 4343 bgp_dest_unlock_node(dest);
d62a17ae 4344 bgp_attr_unintern(&attr_new);
4345
4346 return 0;
4347 }
718e3744 4348
d62a17ae 4349 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4350 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4351 if (bgp_debug_update(peer, p, NULL, 1)) {
4352 bgp_debug_rdpfxpath2str(
a4d82a8a 4353 afi, safi, prd, p, label, num_labels,
66ff6089 4354 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4355 pfx_buf, sizeof(pfx_buf));
d62a17ae 4356 zlog_debug(
f70c91dc
DA
4357 "%pBP rcvd %s, flapped quicker than processing",
4358 peer, pfx_buf);
d62a17ae 4359 }
4360
9bcb3eef 4361 bgp_path_info_restore(dest, pi);
9146341f 4362
4363 /*
4364 * If the BGP_PATH_REMOVED flag is set, then EVPN
4365 * routes would have been unimported already when a
4366 * prior BGP withdraw processing happened. Such routes
4367 * need to be imported again, so flag accordingly.
4368 */
4369 force_evpn_import = true;
d62a17ae 4370 }
718e3744 4371
d62a17ae 4372 /* Received Logging. */
4373 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4374 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4375 num_labels, addpath_id ? 1 : 0,
66ff6089 4376 addpath_id, evpn, pfx_buf,
a4d82a8a 4377 sizeof(pfx_buf));
f70c91dc 4378 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4379 }
718e3744 4380
d62a17ae 4381 /* graceful restart STALE flag unset. */
f009ff26 4382 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4383 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4384 bgp_dest_set_defer_flag(dest, false);
f009ff26 4385 }
d62a17ae 4386
4387 /* The attribute is changed. */
9bcb3eef 4388 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4389
4390 /* implicit withdraw, decrement aggregate and pcount here.
4391 * only if update is accepted, they'll increment below.
4392 */
40381db7 4393 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4394
4395 /* Update bgp route dampening information. */
b4f7f45b 4396 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4397 && peer->sort == BGP_PEER_EBGP) {
4398 /* This is implicit withdraw so we should update
b4f7f45b
IR
4399 dampening
4400 information. */
40381db7 4401 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4402 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4403 }
49e5a4a0 4404#ifdef ENABLE_BGP_VNC
d62a17ae 4405 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4406 struct bgp_dest *pdest = NULL;
d62a17ae 4407 struct bgp_table *table = NULL;
4408
9bcb3eef
DS
4409 pdest = bgp_node_get(bgp->rib[afi][safi],
4410 (struct prefix *)prd);
4411 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4412 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4413
4414 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4415 bgp, prd, table, p, pi);
d62a17ae 4416 }
9bcb3eef 4417 bgp_dest_unlock_node(pdest);
d62a17ae 4418 }
4419 if ((afi == AFI_IP || afi == AFI_IP6)
4420 && (safi == SAFI_UNICAST)) {
40381db7 4421 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4422 /*
4423 * Implicit withdraw case.
4424 */
4425 ++vnc_implicit_withdraw;
40381db7
DS
4426 vnc_import_bgp_del_route(bgp, p, pi);
4427 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4428 }
4429 }
65efcfce 4430#endif
128ea8ab 4431
d62a17ae 4432 /* Special handling for EVPN update of an existing route. If the
4433 * extended community attribute has changed, we need to
4434 * un-import
4435 * the route using its existing extended community. It will be
4436 * subsequently processed for import with the new extended
4437 * community.
4438 */
6f8c9c11
PR
4439 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4440 && !same_attr) {
40381db7 4441 if ((pi->attr->flag
d62a17ae 4442 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4443 && (attr_new->flag
4444 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4445 int cmp;
4446
b53e67a3
DA
4447 cmp = ecommunity_cmp(
4448 bgp_attr_get_ecommunity(pi->attr),
4449 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4450 if (!cmp) {
4451 if (bgp_debug_update(peer, p, NULL, 1))
4452 zlog_debug(
4453 "Change in EXT-COMM, existing %s new %s",
4454 ecommunity_str(
b53e67a3
DA
4455 bgp_attr_get_ecommunity(
4456 pi->attr)),
d62a17ae 4457 ecommunity_str(
b53e67a3
DA
4458 bgp_attr_get_ecommunity(
4459 attr_new)));
6f8c9c11
PR
4460 if (safi == SAFI_EVPN)
4461 bgp_evpn_unimport_route(
4462 bgp, afi, safi, p, pi);
4463 else /* SAFI_MPLS_VPN */
4464 vpn_leak_to_vrf_withdraw(bgp,
4465 pi);
d62a17ae 4466 }
4467 }
4468 }
718e3744 4469
d62a17ae 4470 /* Update to new attribute. */
40381db7
DS
4471 bgp_attr_unintern(&pi->attr);
4472 pi->attr = attr_new;
d62a17ae 4473
4474 /* Update MPLS label */
4475 if (has_valid_label) {
40381db7 4476 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4477 if (extra->label != label) {
4478 memcpy(&extra->label, label,
dbd587da 4479 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4480 extra->num_labels = num_labels;
4481 }
b57ba6d2
MK
4482 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4483 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4484 }
718e3744 4485
e496b420
HS
4486 /* Update SRv6 SID */
4487 if (attr->srv6_l3vpn) {
4488 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4489 if (sid_diff(&extra->sid[0].sid,
4490 &attr->srv6_l3vpn->sid)) {
4491 sid_copy(&extra->sid[0].sid,
e496b420
HS
4492 &attr->srv6_l3vpn->sid);
4493 extra->num_sids = 1;
cc8f05df 4494
16f3db2d
RS
4495 extra->sid[0].loc_block_len = 0;
4496 extra->sid[0].loc_node_len = 0;
4497 extra->sid[0].func_len = 0;
4498 extra->sid[0].arg_len = 0;
ea7cd161
RS
4499 extra->sid[0].transposition_len = 0;
4500 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4501
4502 if (attr->srv6_l3vpn->loc_block_len != 0) {
4503 extra->sid[0].loc_block_len =
4504 attr->srv6_l3vpn->loc_block_len;
4505 extra->sid[0].loc_node_len =
4506 attr->srv6_l3vpn->loc_node_len;
4507 extra->sid[0].func_len =
4508 attr->srv6_l3vpn->func_len;
4509 extra->sid[0].arg_len =
4510 attr->srv6_l3vpn->arg_len;
ea7cd161 4511 extra->sid[0].transposition_len =
cc8f05df 4512 attr->srv6_l3vpn
ea7cd161
RS
4513 ->transposition_len;
4514 extra->sid[0].transposition_offset =
cc8f05df 4515 attr->srv6_l3vpn
ea7cd161
RS
4516 ->transposition_offset;
4517 }
e496b420
HS
4518 }
4519 } else if (attr->srv6_vpn) {
4520 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4521 if (sid_diff(&extra->sid[0].sid,
4522 &attr->srv6_vpn->sid)) {
4523 sid_copy(&extra->sid[0].sid,
4524 &attr->srv6_vpn->sid);
e496b420
HS
4525 extra->num_sids = 1;
4526 }
4527 }
4528
49e5a4a0 4529#ifdef ENABLE_BGP_VNC
d62a17ae 4530 if ((afi == AFI_IP || afi == AFI_IP6)
4531 && (safi == SAFI_UNICAST)) {
4532 if (vnc_implicit_withdraw) {
4533 /*
4534 * Add back the route with its new attributes
4535 * (e.g., nexthop).
4536 * The route is still selected, until the route
4537 * selection
4538 * queued by bgp_process actually runs. We have
4539 * to make this
4540 * update to the VNC side immediately to avoid
4541 * racing against
4542 * configuration changes (e.g., route-map
4543 * changes) which
4544 * trigger re-importation of the entire RIB.
4545 */
40381db7
DS
4546 vnc_import_bgp_add_route(bgp, p, pi);
4547 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4548 }
4549 }
65efcfce
LB
4550#endif
4551
d62a17ae 4552 /* Update bgp route dampening information. */
b4f7f45b 4553 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4554 && peer->sort == BGP_PEER_EBGP) {
4555 /* Now we do normal update dampening. */
9bcb3eef 4556 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4557 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4558 bgp_dest_unlock_node(dest);
d62a17ae 4559 return 0;
4560 }
4561 }
128ea8ab 4562
d62a17ae 4563 /* Nexthop reachability check - for unicast and
4564 * labeled-unicast.. */
7c312383
AD
4565 if (((afi == AFI_IP || afi == AFI_IP6)
4566 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4567 || (safi == SAFI_EVPN &&
4568 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4569 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4570 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4571 && !CHECK_FLAG(peer->flags,
4572 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4573 && !CHECK_FLAG(bgp->flags,
4574 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4575 connected = 1;
4576 else
4577 connected = 0;
4578
960035b2
PZ
4579 struct bgp *bgp_nexthop = bgp;
4580
40381db7
DS
4581 if (pi->extra && pi->extra->bgp_orig)
4582 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4583
7c312383
AD
4584 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4585
4586 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4587 safi, pi, NULL, connected,
4588 p)
a4d82a8a 4589 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4590 bgp_path_info_set_flag(dest, pi,
4591 BGP_PATH_VALID);
d62a17ae 4592 else {
4593 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4594 zlog_debug("%s(%pI4): NH unresolved",
4595 __func__,
4596 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4597 }
9bcb3eef 4598 bgp_path_info_unset_flag(dest, pi,
18ee8310 4599 BGP_PATH_VALID);
d62a17ae 4600 }
46dbf9d0
DA
4601 } else {
4602 if (accept_own)
4603 bgp_path_info_set_flag(dest, pi,
4604 BGP_PATH_ACCEPT_OWN);
4605
9bcb3eef 4606 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4607 }
d62a17ae 4608
49e5a4a0 4609#ifdef ENABLE_BGP_VNC
d62a17ae 4610 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4611 struct bgp_dest *pdest = NULL;
d62a17ae 4612 struct bgp_table *table = NULL;
4613
9bcb3eef
DS
4614 pdest = bgp_node_get(bgp->rib[afi][safi],
4615 (struct prefix *)prd);
4616 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4617 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4618
4619 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4620 bgp, prd, table, p, pi);
d62a17ae 4621 }
9bcb3eef 4622 bgp_dest_unlock_node(pdest);
d62a17ae 4623 }
4624#endif
718e3744 4625
d62a17ae 4626 /* If this is an EVPN route and some attribute has changed,
9146341f 4627 * or we are explicitly told to perform a route import, process
d62a17ae 4628 * route for import. If the extended community has changed, we
4629 * would
4630 * have done the un-import earlier and the import would result
4631 * in the
4632 * route getting injected into appropriate L2 VNIs. If it is
4633 * just
4634 * some other attribute change, the import will result in
4635 * updating
4636 * the attributes for the route in the VNI(s).
4637 */
9146341f 4638 if (safi == SAFI_EVPN &&
4639 (!same_attr || force_evpn_import) &&
7c312383 4640 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4641 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4642
4643 /* Process change. */
40381db7 4644 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4645
9bcb3eef
DS
4646 bgp_process(bgp, dest, afi, safi);
4647 bgp_dest_unlock_node(dest);
558d1fec 4648
ddb5b488
PZ
4649 if (SAFI_UNICAST == safi
4650 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4651 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4652
40381db7 4653 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4654 }
4655 if ((SAFI_MPLS_VPN == safi)
4656 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4657 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4658 }
4659
49e5a4a0 4660#ifdef ENABLE_BGP_VNC
d62a17ae 4661 if (SAFI_MPLS_VPN == safi) {
4662 mpls_label_t label_decoded = decode_label(label);
28070ee3 4663
d62a17ae 4664 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4665 type, sub_type, &label_decoded);
4666 }
4667 if (SAFI_ENCAP == safi) {
4668 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4669 type, sub_type, NULL);
4670 }
28070ee3 4671#endif
a486300b
PG
4672 if ((safi == SAFI_MPLS_VPN) &&
4673 !CHECK_FLAG(bgp->af_flags[afi][safi],
4674 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4675 !leak_success) {
4676 bgp_unlink_nexthop(pi);
4677 bgp_path_info_delete(dest, pi);
4678 }
d62a17ae 4679 return 0;
4680 } // End of implicit withdraw
718e3744 4681
d62a17ae 4682 /* Received Logging. */
4683 if (bgp_debug_update(peer, p, NULL, 1)) {
4684 if (!peer->rcvd_attr_printed) {
f70c91dc 4685 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4686 peer->rcvd_attr_str);
4687 peer->rcvd_attr_printed = 1;
4688 }
718e3744 4689
a4d82a8a 4690 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4691 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4692 pfx_buf, sizeof(pfx_buf));
f70c91dc 4693 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4694 }
718e3744 4695
d62a17ae 4696 /* Make new BGP info. */
9bcb3eef 4697 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4698
d62a17ae 4699 /* Update MPLS label */
4700 if (has_valid_label) {
18ee8310 4701 extra = bgp_path_info_extra_get(new);
8ba71050 4702 if (extra->label != label) {
dbd587da
QY
4703 memcpy(&extra->label, label,
4704 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4705 extra->num_labels = num_labels;
4706 }
b57ba6d2
MK
4707 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4708 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4709 }
718e3744 4710
e496b420
HS
4711 /* Update SRv6 SID */
4712 if (safi == SAFI_MPLS_VPN) {
4713 extra = bgp_path_info_extra_get(new);
4714 if (attr->srv6_l3vpn) {
16f3db2d 4715 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4716 extra->num_sids = 1;
cc8f05df 4717
16f3db2d
RS
4718 extra->sid[0].loc_block_len =
4719 attr->srv6_l3vpn->loc_block_len;
4720 extra->sid[0].loc_node_len =
4721 attr->srv6_l3vpn->loc_node_len;
4722 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4723 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4724 extra->sid[0].transposition_len =
4725 attr->srv6_l3vpn->transposition_len;
4726 extra->sid[0].transposition_offset =
4727 attr->srv6_l3vpn->transposition_offset;
e496b420 4728 } else if (attr->srv6_vpn) {
16f3db2d 4729 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4730 extra->num_sids = 1;
4731 }
4732 }
4733
d62a17ae 4734 /* Nexthop reachability check. */
7c312383
AD
4735 if (((afi == AFI_IP || afi == AFI_IP6)
4736 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4737 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4738 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4739 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4740 && !CHECK_FLAG(peer->flags,
4741 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4742 && !CHECK_FLAG(bgp->flags,
4743 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4744 connected = 1;
4745 else
4746 connected = 0;
4747
7c312383
AD
4748 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4749
4053e952 4750 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4751 connected, p)
a4d82a8a 4752 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4753 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4754 else {
4755 if (BGP_DEBUG(nht, NHT)) {
4756 char buf1[INET6_ADDRSTRLEN];
4757 inet_ntop(AF_INET,
4758 (const void *)&attr_new->nexthop,
4759 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4760 zlog_debug("%s(%s): NH unresolved", __func__,
4761 buf1);
d62a17ae 4762 }
9bcb3eef 4763 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4764 }
46dbf9d0
DA
4765 } else {
4766 if (accept_own)
4767 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4768
9bcb3eef 4769 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4770 }
a82478b9 4771
d62a17ae 4772 /* Addpath ID */
4773 new->addpath_rx_id = addpath_id;
4774
4775 /* Increment prefix */
4776 bgp_aggregate_increment(bgp, p, new, afi, safi);
4777
4778 /* Register new BGP information. */
9bcb3eef 4779 bgp_path_info_add(dest, new);
d62a17ae 4780
4781 /* route_node_get lock */
9bcb3eef 4782 bgp_dest_unlock_node(dest);
558d1fec 4783
49e5a4a0 4784#ifdef ENABLE_BGP_VNC
d62a17ae 4785 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4786 struct bgp_dest *pdest = NULL;
d62a17ae 4787 struct bgp_table *table = NULL;
4788
9bcb3eef
DS
4789 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4790 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4791 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4792
4793 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4794 bgp, prd, table, p, new);
4795 }
9bcb3eef 4796 bgp_dest_unlock_node(pdest);
d62a17ae 4797 }
65efcfce
LB
4798#endif
4799
d62a17ae 4800 /* If this is an EVPN route, process for import. */
7c312383 4801 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4802 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4803
9bcb3eef 4804 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4805
d62a17ae 4806 /* Process change. */
9bcb3eef 4807 bgp_process(bgp, dest, afi, safi);
718e3744 4808
ddb5b488
PZ
4809 if (SAFI_UNICAST == safi
4810 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4811 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4812 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4813 }
4814 if ((SAFI_MPLS_VPN == safi)
4815 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4816 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4817 }
49e5a4a0 4818#ifdef ENABLE_BGP_VNC
d62a17ae 4819 if (SAFI_MPLS_VPN == safi) {
4820 mpls_label_t label_decoded = decode_label(label);
28070ee3 4821
d62a17ae 4822 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4823 sub_type, &label_decoded);
4824 }
4825 if (SAFI_ENCAP == safi) {
4826 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4827 sub_type, NULL);
4828 }
28070ee3 4829#endif
a486300b
PG
4830 if ((safi == SAFI_MPLS_VPN) &&
4831 !CHECK_FLAG(bgp->af_flags[afi][safi],
4832 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4833 !leak_success) {
4834 bgp_unlink_nexthop(new);
4835 bgp_path_info_delete(dest, new);
4836 }
28070ee3 4837
d62a17ae 4838 return 0;
718e3744 4839
d62a17ae 4840/* This BGP update is filtered. Log the reason then update BGP
4841 entry. */
4842filtered:
9bcb3eef 4843 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4844
d62a17ae 4845 if (bgp_debug_update(peer, p, NULL, 1)) {
4846 if (!peer->rcvd_attr_printed) {
f70c91dc 4847 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4848 peer->rcvd_attr_str);
4849 peer->rcvd_attr_printed = 1;
4850 }
718e3744 4851
a4d82a8a 4852 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4853 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4854 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4855 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4856 peer, pfx_buf, reason);
d62a17ae 4857 }
128ea8ab 4858
40381db7 4859 if (pi) {
d62a17ae 4860 /* If this is an EVPN route, un-import it as it is now filtered.
4861 */
4862 if (safi == SAFI_EVPN)
40381db7 4863 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4864
ddb5b488
PZ
4865 if (SAFI_UNICAST == safi
4866 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4867 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4868
40381db7 4869 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4870 }
4871 if ((SAFI_MPLS_VPN == safi)
4872 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4873
40381db7 4874 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4875 }
4876
9bcb3eef 4877 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4878 }
4879
9bcb3eef 4880 bgp_dest_unlock_node(dest);
558d1fec 4881
49e5a4a0 4882#ifdef ENABLE_BGP_VNC
d62a17ae 4883 /*
4884 * Filtered update is treated as an implicit withdrawal (see
4885 * bgp_rib_remove()
4886 * a few lines above)
4887 */
4888 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4889 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4890 0);
4891 }
97736e32
PZ
4892#endif
4893
d62a17ae 4894 return 0;
718e3744 4895}
4896
26a3ffd6 4897int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4898 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4899 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4900 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4901{
d62a17ae 4902 struct bgp *bgp;
4903 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4904 struct bgp_dest *dest;
40381db7 4905 struct bgp_path_info *pi;
718e3744 4906
49e5a4a0 4907#ifdef ENABLE_BGP_VNC
d62a17ae 4908 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4909 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4910 0);
4911 }
28070ee3
PZ
4912#endif
4913
d62a17ae 4914 bgp = peer->bgp;
4915
4916 /* Lookup node. */
9bcb3eef 4917 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4918
4919 /* If peer is soft reconfiguration enabled. Record input packet for
4920 * further calculation.
4921 *
4922 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4923 * routes that are filtered. This tanks out Quagga RS pretty badly due
4924 * to
4925 * the iteration over all RS clients.
4926 * Since we need to remove the entry from adj_in anyway, do that first
4927 * and
4928 * if there was no entry, we don't need to do anything more.
4929 */
4930 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4931 && peer != bgp->peer_self)
9bcb3eef 4932 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4933 peer->stat_pfx_dup_withdraw++;
4934
d62a17ae 4935 if (bgp_debug_update(peer, p, NULL, 1)) {
4936 bgp_debug_rdpfxpath2str(
a4d82a8a 4937 afi, safi, prd, p, label, num_labels,
6c995628
AD
4938 addpath_id ? 1 : 0, addpath_id, NULL,
4939 pfx_buf, sizeof(pfx_buf));
d62a17ae 4940 zlog_debug(
4941 "%s withdrawing route %s not in adj-in",
4942 peer->host, pfx_buf);
4943 }
9bcb3eef 4944 bgp_dest_unlock_node(dest);
d62a17ae 4945 return 0;
4946 }
cd808e74 4947
d62a17ae 4948 /* Lookup withdrawn route. */
9bcb3eef 4949 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4950 if (pi->peer == peer && pi->type == type
4951 && pi->sub_type == sub_type
4952 && pi->addpath_rx_id == addpath_id)
d62a17ae 4953 break;
4954
4955 /* Logging. */
4956 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4957 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4958 addpath_id ? 1 : 0, addpath_id, NULL,
4959 pfx_buf, sizeof(pfx_buf));
f70c91dc 4960 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4961 pfx_buf);
4962 }
718e3744 4963
d62a17ae 4964 /* Withdraw specified route from routing table. */
40381db7 4965 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4966 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4967 if (SAFI_UNICAST == safi
4968 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4969 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4970 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4971 }
4972 if ((SAFI_MPLS_VPN == safi)
4973 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4974
40381db7 4975 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4976 }
4977 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4978 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4979 addpath_id ? 1 : 0, addpath_id, NULL,
4980 pfx_buf, sizeof(pfx_buf));
d62a17ae 4981 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4982 }
718e3744 4983
d62a17ae 4984 /* Unlock bgp_node_get() lock. */
9bcb3eef 4985 bgp_dest_unlock_node(dest);
d62a17ae 4986
4987 return 0;
718e3744 4988}
6b0655a2 4989
d62a17ae 4990void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4991 int withdraw)
718e3744 4992{
d62a17ae 4993 struct update_subgroup *subgrp;
4994 subgrp = peer_subgroup(peer, afi, safi);
4995 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4996}
6182d65b 4997
718e3744 4998
3f9c7369
DS
4999/*
5000 * bgp_stop_announce_route_timer
5001 */
d62a17ae 5002void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5003{
d62a17ae 5004 if (!paf->t_announce_route)
5005 return;
5006
c3aaa89a 5007 THREAD_OFF(paf->t_announce_route);
718e3744 5008}
6b0655a2 5009
3f9c7369
DS
5010/*
5011 * bgp_announce_route_timer_expired
5012 *
5013 * Callback that is invoked when the route announcement timer for a
5014 * peer_af expires.
5015 */
cc9f21da 5016static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5017{
d62a17ae 5018 struct peer_af *paf;
5019 struct peer *peer;
558d1fec 5020
d62a17ae 5021 paf = THREAD_ARG(t);
5022 peer = paf->peer;
718e3744 5023
feb17238 5024 if (!peer_established(peer))
cc9f21da 5025 return;
3f9c7369 5026
d62a17ae 5027 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5028 return;
3f9c7369 5029
d62a17ae 5030 peer_af_announce_route(paf, 1);
c5aec50b
MK
5031
5032 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5033 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5034}
5035
3f9c7369
DS
5036/*
5037 * bgp_announce_route
5038 *
5039 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5040 *
5041 * if force is true we will force an update even if the update
5042 * limiting code is attempted to kick in.
3f9c7369 5043 */
e1a32ec1 5044void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5045{
5046 struct peer_af *paf;
5047 struct update_subgroup *subgrp;
5048
5049 paf = peer_af_find(peer, afi, safi);
5050 if (!paf)
5051 return;
5052 subgrp = PAF_SUBGRP(paf);
5053
5054 /*
5055 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5056 * or a refresh has already been triggered.
5057 */
5058 if (!subgrp || paf->t_announce_route)
5059 return;
5060
e1a32ec1
DS
5061 if (force)
5062 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5063
d62a17ae 5064 /*
5065 * Start a timer to stagger/delay the announce. This serves
5066 * two purposes - announcement can potentially be combined for
5067 * multiple peers and the announcement doesn't happen in the
5068 * vty context.
5069 */
5070 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5071 (subgrp->peer_count == 1)
5072 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5073 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5074 &paf->t_announce_route);
3f9c7369
DS
5075}
5076
5077/*
5078 * Announce routes from all AF tables to a peer.
5079 *
5080 * This should ONLY be called when there is a need to refresh the
5081 * routes to the peer based on a policy change for this peer alone
5082 * or a route refresh request received from the peer.
5083 * The operation will result in splitting the peer from its existing
5084 * subgroups and putting it in new subgroups.
5085 */
d62a17ae 5086void bgp_announce_route_all(struct peer *peer)
718e3744 5087{
d62a17ae 5088 afi_t afi;
5089 safi_t safi;
5090
05c7a1cc 5091 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5092 bgp_announce_route(peer, afi, safi, false);
718e3744 5093}
6b0655a2 5094
46aeabed
LS
5095/* Flag or unflag bgp_dest to determine whether it should be treated by
5096 * bgp_soft_reconfig_table_task.
5097 * Flag if flag is true. Unflag if flag is false.
5098 */
5099static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5100{
5101 struct bgp_dest *dest;
5102 struct bgp_adj_in *ain;
5103
5104 if (!table)
5105 return;
5106
5107 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5108 for (ain = dest->adj_in; ain; ain = ain->next) {
5109 if (ain->peer != NULL)
5110 break;
5111 }
5112 if (flag && ain != NULL && ain->peer != NULL)
5113 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5114 else
5115 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5116 }
5117}
5118
5119static int bgp_soft_reconfig_table_update(struct peer *peer,
5120 struct bgp_dest *dest,
5121 struct bgp_adj_in *ain, afi_t afi,
5122 safi_t safi, struct prefix_rd *prd)
5123{
5124 struct bgp_path_info *pi;
5125 uint32_t num_labels = 0;
5126 mpls_label_t *label_pnt = NULL;
5127 struct bgp_route_evpn evpn;
5128
5129 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5130 if (pi->peer == peer)
5131 break;
5132
5133 if (pi && pi->extra)
5134 num_labels = pi->extra->num_labels;
5135 if (num_labels)
5136 label_pnt = &pi->extra->label[0];
5137 if (pi)
5138 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5139 sizeof(evpn));
5140 else
5141 memset(&evpn, 0, sizeof(evpn));
5142
5143 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5144 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
5145 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
5146 &evpn);
5147}
5148
d62a17ae 5149static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5150 struct bgp_table *table,
5151 struct prefix_rd *prd)
718e3744 5152{
d62a17ae 5153 int ret;
9bcb3eef 5154 struct bgp_dest *dest;
d62a17ae 5155 struct bgp_adj_in *ain;
718e3744 5156
d62a17ae 5157 if (!table)
5158 table = peer->bgp->rib[afi][safi];
718e3744 5159
9bcb3eef
DS
5160 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5161 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5162 if (ain->peer != peer)
5163 continue;
8692c506 5164
46aeabed
LS
5165 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5166 afi, safi, prd);
ea47320b
DL
5167
5168 if (ret < 0) {
9bcb3eef 5169 bgp_dest_unlock_node(dest);
ea47320b 5170 return;
d62a17ae 5171 }
5172 }
718e3744 5173}
5174
46aeabed
LS
5175/* Do soft reconfig table per bgp table.
5176 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5177 * when BGP_NODE_SOFT_RECONFIG is set,
5178 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5179 * Schedule a new thread to continue the job.
5180 * Without splitting the full job into several part,
5181 * vtysh waits for the job to finish before responding to a BGP command
5182 */
cc9f21da 5183static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5184{
5185 uint32_t iter, max_iter;
5186 int ret;
5187 struct bgp_dest *dest;
5188 struct bgp_adj_in *ain;
5189 struct peer *peer;
5190 struct bgp_table *table;
5191 struct prefix_rd *prd;
5192 struct listnode *node, *nnode;
5193
5194 table = THREAD_ARG(thread);
5195 prd = NULL;
5196
5197 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5198 if (table->soft_reconfig_init) {
5199 /* first call of the function with a new srta structure.
5200 * Don't do any treatment this time on nodes
5201 * in order vtysh to respond quickly
5202 */
5203 max_iter = 0;
5204 }
5205
5206 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5207 dest = bgp_route_next(dest)) {
5208 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5209 continue;
5210
5211 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5212
5213 for (ain = dest->adj_in; ain; ain = ain->next) {
5214 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5215 nnode, peer)) {
5216 if (ain->peer != peer)
5217 continue;
5218
5219 ret = bgp_soft_reconfig_table_update(
5220 peer, dest, ain, table->afi,
5221 table->safi, prd);
5222 iter++;
5223
5224 if (ret < 0) {
5225 bgp_dest_unlock_node(dest);
5226 listnode_delete(
5227 table->soft_reconfig_peers,
5228 peer);
5229 bgp_announce_route(peer, table->afi,
e1a32ec1 5230 table->safi, false);
46aeabed
LS
5231 if (list_isempty(
5232 table->soft_reconfig_peers)) {
5233 list_delete(
5234 &table->soft_reconfig_peers);
5235 bgp_soft_reconfig_table_flag(
5236 table, false);
cc9f21da 5237 return;
46aeabed
LS
5238 }
5239 }
5240 }
5241 }
5242 }
5243
5244 /* we're either starting the initial iteration,
5245 * or we're going to continue an ongoing iteration
5246 */
5247 if (dest || table->soft_reconfig_init) {
5248 table->soft_reconfig_init = false;
5249 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5250 table, 0, &table->soft_reconfig_thread);
cc9f21da 5251 return;
46aeabed
LS
5252 }
5253 /* we're done, clean up the background iteration context info and
5254 schedule route annoucement
5255 */
5256 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5257 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5258 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5259 }
5260
5261 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5262}
5263
5264
5265/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5266 * and peer.
5267 * - bgp cannot be NULL
5268 * - if table and peer are NULL, cancel all threads within the bgp instance
5269 * - if table is NULL and peer is not,
5270 * remove peer in all threads within the bgp instance
5271 * - if peer is NULL, cancel all threads matching table within the bgp instance
5272 */
5273void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5274 const struct bgp_table *table,
5275 const struct peer *peer)
5276{
5277 struct peer *npeer;
5278 struct listnode *node, *nnode;
5279 int afi, safi;
5280 struct bgp_table *ntable;
5281
5282 if (!bgp)
5283 return;
5284
5285 FOREACH_AFI_SAFI (afi, safi) {
5286 ntable = bgp->rib[afi][safi];
5287 if (!ntable)
5288 continue;
5289 if (table && table != ntable)
5290 continue;
5291
5292 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5293 npeer)) {
5294 if (peer && peer != npeer)
5295 continue;
5296 listnode_delete(ntable->soft_reconfig_peers, npeer);
5297 }
5298
5299 if (!ntable->soft_reconfig_peers
5300 || !list_isempty(ntable->soft_reconfig_peers))
5301 continue;
5302
5303 list_delete(&ntable->soft_reconfig_peers);
5304 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5305 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5306 }
5307}
5308
d62a17ae 5309void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5310{
9bcb3eef 5311 struct bgp_dest *dest;
d62a17ae 5312 struct bgp_table *table;
46aeabed
LS
5313 struct listnode *node, *nnode;
5314 struct peer *npeer;
5315 struct peer_af *paf;
718e3744 5316
feb17238 5317 if (!peer_established(peer))
d62a17ae 5318 return;
718e3744 5319
d62a17ae 5320 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5321 && (safi != SAFI_EVPN)) {
5322 table = peer->bgp->rib[afi][safi];
5323 if (!table)
5324 return;
5325
5326 table->soft_reconfig_init = true;
5327
5328 if (!table->soft_reconfig_peers)
5329 table->soft_reconfig_peers = list_new();
5330 npeer = NULL;
5331 /* add peer to the table soft_reconfig_peers if not already
5332 * there
5333 */
5334 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5335 npeer)) {
5336 if (peer == npeer)
5337 break;
5338 }
5339 if (peer != npeer)
5340 listnode_add(table->soft_reconfig_peers, peer);
5341
5342 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5343 * on table would start back at the beginning.
5344 */
5345 bgp_soft_reconfig_table_flag(table, true);
5346
5347 if (!table->soft_reconfig_thread)
5348 thread_add_event(bm->master,
5349 bgp_soft_reconfig_table_task, table, 0,
5350 &table->soft_reconfig_thread);
5351 /* Cancel bgp_announce_route_timer_expired threads.
5352 * bgp_announce_route_timer_expired threads have been scheduled
5353 * to announce routes as soon as the soft_reconfigure process
5354 * finishes.
5355 * In this case, soft_reconfigure is also scheduled by using
5356 * a thread but is planned after the
5357 * bgp_announce_route_timer_expired threads. It means that,
5358 * without cancelling the threads, the route announcement task
5359 * would run before the soft reconfiguration one. That would
5360 * useless and would block vtysh during several seconds. Route
5361 * announcements are rescheduled as soon as the soft_reconfigure
5362 * process finishes.
5363 */
5364 paf = peer_af_find(peer, afi, safi);
5365 if (paf)
5366 bgp_stop_announce_route_timer(paf);
5367 } else
9bcb3eef
DS
5368 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5369 dest = bgp_route_next(dest)) {
5370 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5371
b54892e0
DS
5372 if (table == NULL)
5373 continue;
8692c506 5374
9bcb3eef 5375 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5376 struct prefix_rd prd;
5377
5378 prd.family = AF_UNSPEC;
5379 prd.prefixlen = 64;
5380 memcpy(&prd.val, p->u.val, 8);
5381
5382 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5383 }
718e3744 5384}
6b0655a2 5385
228da428 5386
d62a17ae 5387struct bgp_clear_node_queue {
9bcb3eef 5388 struct bgp_dest *dest;
228da428
CC
5389};
5390
d62a17ae 5391static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5392{
d62a17ae 5393 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5394 struct bgp_dest *dest = cnq->dest;
d62a17ae 5395 struct peer *peer = wq->spec.data;
40381db7 5396 struct bgp_path_info *pi;
3103e8d2 5397 struct bgp *bgp;
9bcb3eef
DS
5398 afi_t afi = bgp_dest_table(dest)->afi;
5399 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5400
9bcb3eef 5401 assert(dest && peer);
3103e8d2 5402 bgp = peer->bgp;
d62a17ae 5403
5404 /* It is possible that we have multiple paths for a prefix from a peer
5405 * if that peer is using AddPath.
5406 */
9bcb3eef 5407 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5408 if (pi->peer != peer)
ea47320b
DL
5409 continue;
5410
5411 /* graceful restart STALE flag set. */
9af52ccf
DA
5412 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5413 && peer->nsf[afi][safi])
5414 || CHECK_FLAG(peer->af_sflags[afi][safi],
5415 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5416 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5417 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5418 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5419 else {
5420 /* If this is an EVPN route, process for
5421 * un-import. */
5422 if (safi == SAFI_EVPN)
9bcb3eef
DS
5423 bgp_evpn_unimport_route(
5424 bgp, afi, safi,
5425 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5426 /* Handle withdraw for VRF route-leaking and L3VPN */
5427 if (SAFI_UNICAST == safi
5428 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5429 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5430 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5431 bgp, pi);
960035b2 5432 }
3103e8d2 5433 if (SAFI_MPLS_VPN == safi &&
960035b2 5434 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5435 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5436 }
3103e8d2 5437
9bcb3eef 5438 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5439 }
ea47320b 5440 }
d62a17ae 5441 return WQ_SUCCESS;
200df115 5442}
5443
d62a17ae 5444static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5445{
d62a17ae 5446 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5447 struct bgp_dest *dest = cnq->dest;
5448 struct bgp_table *table = bgp_dest_table(dest);
228da428 5449
9bcb3eef 5450 bgp_dest_unlock_node(dest);
d62a17ae 5451 bgp_table_unlock(table);
5452 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5453}
5454
d62a17ae 5455static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5456{
d62a17ae 5457 struct peer *peer = wq->spec.data;
64e580a7 5458
d62a17ae 5459 /* Tickle FSM to start moving again */
5460 BGP_EVENT_ADD(peer, Clearing_Completed);
5461
5462 peer_unlock(peer); /* bgp_clear_route */
200df115 5463}
718e3744 5464
d62a17ae 5465static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5466{
d62a17ae 5467 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5468
5469 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5470#undef CLEAR_QUEUE_NAME_LEN
5471
0ce1ca80 5472 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5473 peer->clear_node_queue->spec.hold = 10;
5474 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5475 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5476 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5477 peer->clear_node_queue->spec.max_retries = 0;
5478
5479 /* we only 'lock' this peer reference when the queue is actually active
5480 */
5481 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5482}
5483
d62a17ae 5484static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5485 struct bgp_table *table)
65ca75e0 5486{
9bcb3eef 5487 struct bgp_dest *dest;
b6c386bb 5488 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5489
d62a17ae 5490 if (!table)
5491 table = peer->bgp->rib[afi][safi];
dc83d712 5492
d62a17ae 5493 /* If still no table => afi/safi isn't configured at all or smth. */
5494 if (!table)
5495 return;
dc83d712 5496
9bcb3eef 5497 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5498 struct bgp_path_info *pi, *next;
d62a17ae 5499 struct bgp_adj_in *ain;
5500 struct bgp_adj_in *ain_next;
5501
5502 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5503 * queued for every clearing peer, regardless of whether it is
5504 * relevant to the peer at hand.
5505 *
5506 * Overview: There are 3 different indices which need to be
5507 * scrubbed, potentially, when a peer is removed:
5508 *
5509 * 1 peer's routes visible via the RIB (ie accepted routes)
5510 * 2 peer's routes visible by the (optional) peer's adj-in index
5511 * 3 other routes visible by the peer's adj-out index
5512 *
5513 * 3 there is no hurry in scrubbing, once the struct peer is
5514 * removed from bgp->peer, we could just GC such deleted peer's
5515 * adj-outs at our leisure.
5516 *
5517 * 1 and 2 must be 'scrubbed' in some way, at least made
5518 * invisible via RIB index before peer session is allowed to be
5519 * brought back up. So one needs to know when such a 'search' is
5520 * complete.
5521 *
5522 * Ideally:
5523 *
5524 * - there'd be a single global queue or a single RIB walker
5525 * - rather than tracking which route_nodes still need to be
5526 * examined on a peer basis, we'd track which peers still
5527 * aren't cleared
5528 *
5529 * Given that our per-peer prefix-counts now should be reliable,
5530 * this may actually be achievable. It doesn't seem to be a huge
5531 * problem at this time,
5532 *
5533 * It is possible that we have multiple paths for a prefix from
5534 * a peer
5535 * if that peer is using AddPath.
5536 */
9bcb3eef 5537 ain = dest->adj_in;
d62a17ae 5538 while (ain) {
5539 ain_next = ain->next;
5540
6a840fd9 5541 if (ain->peer == peer)
9bcb3eef 5542 bgp_adj_in_remove(dest, ain);
d62a17ae 5543
5544 ain = ain_next;
5545 }
5546
9bcb3eef 5547 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5548 next = pi->next;
5549 if (pi->peer != peer)
d62a17ae 5550 continue;
5551
5552 if (force)
9bcb3eef 5553 bgp_path_info_reap(dest, pi);
d62a17ae 5554 else {
5555 struct bgp_clear_node_queue *cnq;
5556
5557 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5558 bgp_table_lock(bgp_dest_table(dest));
5559 bgp_dest_lock_node(dest);
d62a17ae 5560 cnq = XCALLOC(
5561 MTYPE_BGP_CLEAR_NODE_QUEUE,
5562 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5563 cnq->dest = dest;
d62a17ae 5564 work_queue_add(peer->clear_node_queue, cnq);
5565 break;
5566 }
5567 }
5568 }
5569 return;
5570}
5571
5572void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5573{
9bcb3eef 5574 struct bgp_dest *dest;
d62a17ae 5575 struct bgp_table *table;
5576
5577 if (peer->clear_node_queue == NULL)
5578 bgp_clear_node_queue_init(peer);
5579
5580 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5581 * Idle until it receives a Clearing_Completed event. This protects
5582 * against peers which flap faster than we can we clear, which could
5583 * lead to:
5584 *
5585 * a) race with routes from the new session being installed before
5586 * clear_route_node visits the node (to delete the route of that
5587 * peer)
5588 * b) resource exhaustion, clear_route_node likely leads to an entry
5589 * on the process_main queue. Fast-flapping could cause that queue
5590 * to grow and grow.
5591 */
5592
5593 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5594 * the unlock will happen upon work-queue completion; other wise, the
5595 * unlock happens at the end of this function.
5596 */
5597 if (!peer->clear_node_queue->thread)
5598 peer_lock(peer);
5599
5600 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5601 bgp_clear_route_table(peer, afi, safi, NULL);
5602 else
9bcb3eef
DS
5603 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5604 dest = bgp_route_next(dest)) {
5605 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5606 if (!table)
5607 continue;
5608
5609 bgp_clear_route_table(peer, afi, safi, table);
5610 }
d62a17ae 5611
5612 /* unlock if no nodes got added to the clear-node-queue. */
5613 if (!peer->clear_node_queue->thread)
5614 peer_unlock(peer);
718e3744 5615}
d62a17ae 5616
5617void bgp_clear_route_all(struct peer *peer)
718e3744 5618{
d62a17ae 5619 afi_t afi;
5620 safi_t safi;
718e3744 5621
05c7a1cc
QY
5622 FOREACH_AFI_SAFI (afi, safi)
5623 bgp_clear_route(peer, afi, safi);
65efcfce 5624
49e5a4a0 5625#ifdef ENABLE_BGP_VNC
d62a17ae 5626 rfapiProcessPeerDown(peer);
65efcfce 5627#endif
718e3744 5628}
5629
d62a17ae 5630void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5631{
d62a17ae 5632 struct bgp_table *table;
9bcb3eef 5633 struct bgp_dest *dest;
d62a17ae 5634 struct bgp_adj_in *ain;
5635 struct bgp_adj_in *ain_next;
718e3744 5636
d62a17ae 5637 table = peer->bgp->rib[afi][safi];
718e3744 5638
d62a17ae 5639 /* It is possible that we have multiple paths for a prefix from a peer
5640 * if that peer is using AddPath.
5641 */
9bcb3eef
DS
5642 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5643 ain = dest->adj_in;
43143c8f 5644
d62a17ae 5645 while (ain) {
5646 ain_next = ain->next;
43143c8f 5647
6a840fd9 5648 if (ain->peer == peer)
9bcb3eef 5649 bgp_adj_in_remove(dest, ain);
43143c8f 5650
d62a17ae 5651 ain = ain_next;
5652 }
5653 }
718e3744 5654}
93406d87 5655
1479ed2f
DA
5656/* If any of the routes from the peer have been marked with the NO_LLGR
5657 * community, either as sent by the peer, or as the result of a configured
5658 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5659 * operation of [RFC4271].
5660 */
d62a17ae 5661void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5662{
9bcb3eef 5663 struct bgp_dest *dest;
40381db7 5664 struct bgp_path_info *pi;
d62a17ae 5665 struct bgp_table *table;
5666
9af52ccf 5667 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5668 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5669 dest = bgp_route_next(dest)) {
5670 struct bgp_dest *rm;
d62a17ae 5671
5672 /* look for neighbor in tables */
9bcb3eef 5673 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5674 if (!table)
ea47320b
DL
5675 continue;
5676
5677 for (rm = bgp_table_top(table); rm;
5678 rm = bgp_route_next(rm))
9bcb3eef 5679 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5680 pi = pi->next) {
40381db7 5681 if (pi->peer != peer)
ea47320b 5682 continue;
1479ed2f
DA
5683 if (CHECK_FLAG(
5684 peer->af_sflags[afi][safi],
5685 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5686 bgp_attr_get_community(pi->attr) &&
1479ed2f 5687 !community_include(
9a706b42
DA
5688 bgp_attr_get_community(
5689 pi->attr),
1479ed2f 5690 COMMUNITY_NO_LLGR))
e3015d91 5691 continue;
40381db7 5692 if (!CHECK_FLAG(pi->flags,
1defdda8 5693 BGP_PATH_STALE))
e3015d91 5694 continue;
ea47320b 5695
641065d4
KM
5696 /*
5697 * If this is VRF leaked route
5698 * process for withdraw.
5699 */
5700 if (pi->sub_type ==
5701 BGP_ROUTE_IMPORTED &&
5702 peer->bgp->inst_type ==
5703 BGP_INSTANCE_TYPE_DEFAULT)
5704 vpn_leak_to_vrf_withdraw(
5705 peer->bgp, pi);
5706
40381db7 5707 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5708 break;
5709 }
d62a17ae 5710 }
5711 } else {
9bcb3eef
DS
5712 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5713 dest = bgp_route_next(dest))
5714 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5715 pi = pi->next) {
40381db7 5716 if (pi->peer != peer)
ea47320b 5717 continue;
1479ed2f
DA
5718 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5719 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5720 bgp_attr_get_community(pi->attr) &&
5721 !community_include(
5722 bgp_attr_get_community(pi->attr),
5723 COMMUNITY_NO_LLGR))
e3015d91 5724 continue;
40381db7 5725 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5726 continue;
641065d4
KM
5727 if (safi == SAFI_UNICAST &&
5728 (peer->bgp->inst_type ==
5729 BGP_INSTANCE_TYPE_VRF ||
5730 peer->bgp->inst_type ==
5731 BGP_INSTANCE_TYPE_DEFAULT))
5732 vpn_leak_from_vrf_withdraw(
5733 bgp_get_default(), peer->bgp,
5734 pi);
5735
9bcb3eef 5736 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5737 break;
5738 }
d62a17ae 5739 }
93406d87 5740}
6b0655a2 5741
9af52ccf
DA
5742void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5743{
5744 struct bgp_dest *dest, *ndest;
5745 struct bgp_path_info *pi;
5746 struct bgp_table *table;
5747
5748 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5749 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5750 dest = bgp_route_next(dest)) {
5751 table = bgp_dest_get_bgp_table_info(dest);
5752 if (!table)
5753 continue;
5754
5755 for (ndest = bgp_table_top(table); ndest;
5756 ndest = bgp_route_next(ndest)) {
5757 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5758 pi = pi->next) {
5759 if (pi->peer != peer)
5760 continue;
5761
5762 if ((CHECK_FLAG(
5763 peer->af_sflags[afi][safi],
5764 PEER_STATUS_ENHANCED_REFRESH))
5765 && !CHECK_FLAG(pi->flags,
5766 BGP_PATH_STALE)
5767 && !CHECK_FLAG(
5768 pi->flags,
5769 BGP_PATH_UNUSEABLE)) {
5770 if (bgp_debug_neighbor_events(
5771 peer))
5772 zlog_debug(
58e111f6
DA
5773 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5774 peer,
9af52ccf
DA
5775 afi2str(afi),
5776 safi2str(safi),
5777 bgp_dest_get_prefix(
5778 ndest));
5779
5780 bgp_path_info_set_flag(
5781 ndest, pi,
5782 BGP_PATH_STALE);
5783 }
5784 }
5785 }
5786 }
5787 } else {
5788 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5789 dest = bgp_route_next(dest)) {
5790 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5791 pi = pi->next) {
5792 if (pi->peer != peer)
5793 continue;
5794
5795 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5796 PEER_STATUS_ENHANCED_REFRESH))
5797 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5798 && !CHECK_FLAG(pi->flags,
5799 BGP_PATH_UNUSEABLE)) {
5800 if (bgp_debug_neighbor_events(peer))
5801 zlog_debug(
58e111f6
DA
5802 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5803 peer, afi2str(afi),
9af52ccf
DA
5804 safi2str(safi),
5805 bgp_dest_get_prefix(
5806 dest));
5807
5808 bgp_path_info_set_flag(dest, pi,
5809 BGP_PATH_STALE);
5810 }
5811 }
5812 }
5813 }
5814}
5815
3dc339cd 5816bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5817{
e0df4c04 5818 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5819 return true;
e0df4c04 5820
9dac9fc8
DA
5821 if (peer->sort == BGP_PEER_EBGP
5822 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5823 || FILTER_LIST_OUT_NAME(filter)
5824 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5825 return true;
5826 return false;
9dac9fc8
DA
5827}
5828
3dc339cd 5829bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5830{
e0df4c04 5831 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5832 return true;
e0df4c04 5833
9dac9fc8
DA
5834 if (peer->sort == BGP_PEER_EBGP
5835 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5836 || FILTER_LIST_IN_NAME(filter)
5837 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5838 return true;
5839 return false;
9dac9fc8
DA
5840}
5841
568e10ca 5842static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5843 safi_t safi)
bb86c601 5844{
9bcb3eef 5845 struct bgp_dest *dest;
40381db7 5846 struct bgp_path_info *pi;
4b7e6066 5847 struct bgp_path_info *next;
bb86c601 5848
9bcb3eef
DS
5849 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5850 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5851 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5852
40381db7 5853 next = pi->next;
1b7bb747
CS
5854
5855 /* Unimport EVPN routes from VRFs */
5856 if (safi == SAFI_EVPN)
5857 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5858 SAFI_EVPN, p, pi);
1b7bb747 5859
40381db7
DS
5860 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5861 && pi->type == ZEBRA_ROUTE_BGP
5862 && (pi->sub_type == BGP_ROUTE_NORMAL
5863 || pi->sub_type == BGP_ROUTE_AGGREGATE
5864 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5865
d62a17ae 5866 if (bgp_fibupd_safi(safi))
b54892e0 5867 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5868 }
9514b37d 5869
9bcb3eef 5870 bgp_path_info_reap(dest, pi);
d62a17ae 5871 }
bb86c601
LB
5872}
5873
718e3744 5874/* Delete all kernel routes. */
d62a17ae 5875void bgp_cleanup_routes(struct bgp *bgp)
5876{
5877 afi_t afi;
9bcb3eef 5878 struct bgp_dest *dest;
67009e22 5879 struct bgp_table *table;
d62a17ae 5880
5881 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5882 if (afi == AFI_L2VPN)
5883 continue;
568e10ca 5884 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5885 SAFI_UNICAST);
d62a17ae 5886 /*
5887 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5888 */
5889 if (afi != AFI_L2VPN) {
5890 safi_t safi;
5891 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5892 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5893 dest = bgp_route_next(dest)) {
5894 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5895 if (table != NULL) {
5896 bgp_cleanup_table(bgp, table, safi);
5897 bgp_table_finish(&table);
9bcb3eef
DS
5898 bgp_dest_set_bgp_table_info(dest, NULL);
5899 bgp_dest_unlock_node(dest);
d62a17ae 5900 }
5901 }
5902 safi = SAFI_ENCAP;
9bcb3eef
DS
5903 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5904 dest = bgp_route_next(dest)) {
5905 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5906 if (table != NULL) {
5907 bgp_cleanup_table(bgp, table, safi);
5908 bgp_table_finish(&table);
9bcb3eef
DS
5909 bgp_dest_set_bgp_table_info(dest, NULL);
5910 bgp_dest_unlock_node(dest);
d62a17ae 5911 }
5912 }
5913 }
5914 }
9bcb3eef
DS
5915 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5916 dest = bgp_route_next(dest)) {
5917 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5918 if (table != NULL) {
5919 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5920 bgp_table_finish(&table);
9bcb3eef
DS
5921 bgp_dest_set_bgp_table_info(dest, NULL);
5922 bgp_dest_unlock_node(dest);
d62a17ae 5923 }
bb86c601 5924 }
718e3744 5925}
5926
d62a17ae 5927void bgp_reset(void)
718e3744 5928{
d62a17ae 5929 vty_reset();
5930 bgp_zclient_reset();
5931 access_list_reset();
5932 prefix_list_reset();
718e3744 5933}
6b0655a2 5934
be92fc9f 5935bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5936{
d62a17ae 5937 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5938 && CHECK_FLAG(peer->af_cap[afi][safi],
5939 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5940}
5941
718e3744 5942/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5943 value. */
d62a17ae 5944int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5945 struct bgp_nlri *packet)
5946{
d7c0a89a
QY
5947 uint8_t *pnt;
5948 uint8_t *lim;
d62a17ae 5949 struct prefix p;
5950 int psize;
5951 int ret;
5952 afi_t afi;
5953 safi_t safi;
be92fc9f 5954 bool addpath_capable;
d7c0a89a 5955 uint32_t addpath_id;
d62a17ae 5956
d62a17ae 5957 pnt = packet->nlri;
5958 lim = pnt + packet->length;
5959 afi = packet->afi;
5960 safi = packet->safi;
5961 addpath_id = 0;
be92fc9f 5962 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5963
5964 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5965 syntactic validity. If the field is syntactically incorrect,
5966 then the Error Subcode is set to Invalid Network Field. */
5967 for (; pnt < lim; pnt += psize) {
5968 /* Clear prefix structure. */
6006b807 5969 memset(&p, 0, sizeof(p));
d62a17ae 5970
be92fc9f 5971 if (addpath_capable) {
d62a17ae 5972
5973 /* When packet overflow occurs return immediately. */
761ed665 5974 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5975 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5976
a3a850a1 5977 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5978 addpath_id = ntohl(addpath_id);
d62a17ae 5979 pnt += BGP_ADDPATH_ID_LEN;
5980 }
718e3744 5981
d62a17ae 5982 /* Fetch prefix length. */
5983 p.prefixlen = *pnt++;
5984 /* afi/safi validity already verified by caller,
5985 * bgp_update_receive */
5986 p.family = afi2family(afi);
5987
5988 /* Prefix length check. */
5989 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5990 flog_err(
e50f7cfd 5991 EC_BGP_UPDATE_RCV,
14454c9f 5992 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5993 peer->host, p.prefixlen, packet->afi);
513386b5 5994 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5995 }
6b0655a2 5996
d62a17ae 5997 /* Packet size overflow check. */
5998 psize = PSIZE(p.prefixlen);
5999
6000 /* When packet overflow occur return immediately. */
6001 if (pnt + psize > lim) {
af4c2728 6002 flog_err(
e50f7cfd 6003 EC_BGP_UPDATE_RCV,
d62a17ae 6004 "%s [Error] Update packet error (prefix length %d overflows packet)",
6005 peer->host, p.prefixlen);
513386b5 6006 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6007 }
6008
6009 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6010 * prefix for the v4 and v6 afi's and unicast/multicast */
6011 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6012 flog_err(
e50f7cfd 6013 EC_BGP_UPDATE_RCV,
d62a17ae 6014 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6015 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6016 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6017 }
6018
6019 /* Fetch prefix from NLRI packet. */
a85297a7 6020 memcpy(p.u.val, pnt, psize);
d62a17ae 6021
6022 /* Check address. */
6023 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6024 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6025 /* From RFC4271 Section 6.3:
6026 *
6027 * If a prefix in the NLRI field is semantically
6028 * incorrect
6029 * (e.g., an unexpected multicast IP address),
6030 * an error SHOULD
6031 * be logged locally, and the prefix SHOULD be
6032 * ignored.
a4d82a8a 6033 */
af4c2728 6034 flog_err(
e50f7cfd 6035 EC_BGP_UPDATE_RCV,
23d0a753
DA
6036 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6037 peer->host, &p.u.prefix4);
d62a17ae 6038 continue;
6039 }
6040 }
6041
6042 /* Check address. */
6043 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6044 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6045 flog_err(
e50f7cfd 6046 EC_BGP_UPDATE_RCV,
c0d72166
DS
6047 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6048 peer->host, &p.u.prefix6);
d62a17ae 6049
6050 continue;
6051 }
6052 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6053 flog_err(
e50f7cfd 6054 EC_BGP_UPDATE_RCV,
c0d72166
DS
6055 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6056 peer->host, &p.u.prefix6);
d62a17ae 6057
6058 continue;
6059 }
6060 }
6061
6062 /* Normal process. */
6063 if (attr)
6064 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
6065 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 6066 NULL, NULL, 0, 0, NULL);
d62a17ae 6067 else
6068 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
6069 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
6070 BGP_ROUTE_NORMAL, NULL, NULL, 0,
6071 NULL);
d62a17ae 6072
513386b5
DA
6073 /* Do not send BGP notification twice when maximum-prefix count
6074 * overflow. */
6075 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6076 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6077
6078 /* Address family configuration mismatch. */
d62a17ae 6079 if (ret < 0)
513386b5 6080 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 6081 }
6082
6083 /* Packet length consistency check. */
6084 if (pnt != lim) {
af4c2728 6085 flog_err(
e50f7cfd 6086 EC_BGP_UPDATE_RCV,
d62a17ae 6087 "%s [Error] Update packet error (prefix length mismatch with total length)",
6088 peer->host);
513386b5 6089 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6090 }
6b0655a2 6091
513386b5 6092 return BGP_NLRI_PARSE_OK;
718e3744 6093}
6094
d62a17ae 6095static struct bgp_static *bgp_static_new(void)
718e3744 6096{
d62a17ae 6097 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6098}
6099
d62a17ae 6100static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6101{
0a22ddfb 6102 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6103 route_map_counter_decrement(bgp_static->rmap.map);
6104
0a22ddfb 6105 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6106 XFREE(MTYPE_BGP_STATIC, bgp_static);
6107}
6108
5f040085 6109void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6110 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6111{
9bcb3eef 6112 struct bgp_dest *dest;
40381db7 6113 struct bgp_path_info *pi;
4b7e6066 6114 struct bgp_path_info *new;
40381db7 6115 struct bgp_path_info rmap_path;
d62a17ae 6116 struct attr attr;
6117 struct attr *attr_new;
b68885f9 6118 route_map_result_t ret;
49e5a4a0 6119#ifdef ENABLE_BGP_VNC
d62a17ae 6120 int vnc_implicit_withdraw = 0;
65efcfce 6121#endif
fee0f4c6 6122
d62a17ae 6123 assert(bgp_static);
dd8103a9 6124
9bcb3eef 6125 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6126
0f05ea43 6127 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6128
d62a17ae 6129 attr.nexthop = bgp_static->igpnexthop;
6130 attr.med = bgp_static->igpmetric;
6131 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6132
7226bc40
TA
6133 if (afi == AFI_IP)
6134 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6135
d62a17ae 6136 if (bgp_static->atomic)
6137 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6138
d62a17ae 6139 /* Store label index, if required. */
6140 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6141 attr.label_index = bgp_static->label_index;
6142 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6143 }
718e3744 6144
d62a17ae 6145 /* Apply route-map. */
6146 if (bgp_static->rmap.name) {
6147 struct attr attr_tmp = attr;
80ced710 6148
6006b807 6149 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6150 rmap_path.peer = bgp->peer_self;
6151 rmap_path.attr = &attr_tmp;
fee0f4c6 6152
d62a17ae 6153 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6154
1782514f 6155 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6156
d62a17ae 6157 bgp->peer_self->rmap_type = 0;
718e3744 6158
d62a17ae 6159 if (ret == RMAP_DENYMATCH) {
6160 /* Free uninterned attribute. */
6161 bgp_attr_flush(&attr_tmp);
718e3744 6162
d62a17ae 6163 /* Unintern original. */
6164 aspath_unintern(&attr.aspath);
6165 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6166 bgp_dest_unlock_node(dest);
d62a17ae 6167 return;
6168 }
7f323236 6169
637e5ba4 6170 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6171 bgp_attr_add_gshut_community(&attr_tmp);
6172
d62a17ae 6173 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6174 } else {
6175
637e5ba4 6176 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6177 bgp_attr_add_gshut_community(&attr);
6178
d62a17ae 6179 attr_new = bgp_attr_intern(&attr);
7f323236 6180 }
718e3744 6181
9bcb3eef 6182 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6183 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6184 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6185 break;
6186
40381db7
DS
6187 if (pi) {
6188 if (attrhash_cmp(pi->attr, attr_new)
6189 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6190 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6191 bgp_dest_unlock_node(dest);
d62a17ae 6192 bgp_attr_unintern(&attr_new);
6193 aspath_unintern(&attr.aspath);
6194 return;
6195 } else {
6196 /* The attribute is changed. */
9bcb3eef 6197 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6198
6199 /* Rewrite BGP route information. */
40381db7 6200 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6201 bgp_path_info_restore(dest, pi);
d62a17ae 6202 else
40381db7 6203 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6204#ifdef ENABLE_BGP_VNC
d62a17ae 6205 if ((afi == AFI_IP || afi == AFI_IP6)
6206 && (safi == SAFI_UNICAST)) {
40381db7 6207 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6208 /*
6209 * Implicit withdraw case.
40381db7 6210 * We have to do this before pi is
d62a17ae 6211 * changed
6212 */
6213 ++vnc_implicit_withdraw;
40381db7 6214 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6215 vnc_import_bgp_exterior_del_route(
40381db7 6216 bgp, p, pi);
d62a17ae 6217 }
6218 }
65efcfce 6219#endif
40381db7
DS
6220 bgp_attr_unintern(&pi->attr);
6221 pi->attr = attr_new;
083ec940 6222 pi->uptime = monotime(NULL);
49e5a4a0 6223#ifdef ENABLE_BGP_VNC
d62a17ae 6224 if ((afi == AFI_IP || afi == AFI_IP6)
6225 && (safi == SAFI_UNICAST)) {
6226 if (vnc_implicit_withdraw) {
40381db7 6227 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6228 vnc_import_bgp_exterior_add_route(
40381db7 6229 bgp, p, pi);
d62a17ae 6230 }
6231 }
65efcfce 6232#endif
718e3744 6233
d62a17ae 6234 /* Nexthop reachability check. */
892fedb6 6235 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6236 && (safi == SAFI_UNICAST
6237 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6238
6239 struct bgp *bgp_nexthop = bgp;
6240
40381db7
DS
6241 if (pi->extra && pi->extra->bgp_orig)
6242 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6243
6244 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6245 afi, safi, pi, NULL,
654a5978 6246 0, p))
9bcb3eef 6247 bgp_path_info_set_flag(dest, pi,
18ee8310 6248 BGP_PATH_VALID);
d62a17ae 6249 else {
6250 if (BGP_DEBUG(nht, NHT)) {
6251 char buf1[INET6_ADDRSTRLEN];
6252 inet_ntop(p->family,
6253 &p->u.prefix, buf1,
6254 INET6_ADDRSTRLEN);
6255 zlog_debug(
6256 "%s(%s): Route not in table, not advertising",
15569c58 6257 __func__, buf1);
d62a17ae 6258 }
18ee8310 6259 bgp_path_info_unset_flag(
9bcb3eef 6260 dest, pi, BGP_PATH_VALID);
d62a17ae 6261 }
6262 } else {
6263 /* Delete the NHT structure if any, if we're
6264 * toggling between
6265 * enabling/disabling import check. We
6266 * deregister the route
6267 * from NHT to avoid overloading NHT and the
6268 * process interaction
6269 */
40381db7 6270 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6271 bgp_path_info_set_flag(dest, pi,
6272 BGP_PATH_VALID);
d62a17ae 6273 }
6274 /* Process change. */
40381db7 6275 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6276 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6277
6278 if (SAFI_UNICAST == safi
6279 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6280 || bgp->inst_type
6281 == BGP_INSTANCE_TYPE_DEFAULT)) {
6282 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6283 pi);
ddb5b488
PZ
6284 }
6285
9bcb3eef 6286 bgp_dest_unlock_node(dest);
d62a17ae 6287 aspath_unintern(&attr.aspath);
6288 return;
6289 }
718e3744 6290 }
718e3744 6291
d62a17ae 6292 /* Make new BGP info. */
6293 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6294 attr_new, dest);
d62a17ae 6295 /* Nexthop reachability check. */
892fedb6 6296 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6297 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6298 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6299 p))
9bcb3eef 6300 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6301 else {
6302 if (BGP_DEBUG(nht, NHT)) {
6303 char buf1[INET6_ADDRSTRLEN];
6304 inet_ntop(p->family, &p->u.prefix, buf1,
6305 INET6_ADDRSTRLEN);
6306 zlog_debug(
6307 "%s(%s): Route not in table, not advertising",
15569c58 6308 __func__, buf1);
d62a17ae 6309 }
9bcb3eef 6310 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6311 }
6312 } else {
6313 /* Delete the NHT structure if any, if we're toggling between
6314 * enabling/disabling import check. We deregister the route
6315 * from NHT to avoid overloading NHT and the process interaction
6316 */
6317 bgp_unlink_nexthop(new);
6318
9bcb3eef 6319 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6320 }
078430f6 6321
d62a17ae 6322 /* Aggregate address increment. */
6323 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6324
d62a17ae 6325 /* Register new BGP information. */
9bcb3eef 6326 bgp_path_info_add(dest, new);
718e3744 6327
d62a17ae 6328 /* route_node_get lock */
9bcb3eef 6329 bgp_dest_unlock_node(dest);
d62a17ae 6330
6331 /* Process change. */
9bcb3eef 6332 bgp_process(bgp, dest, afi, safi);
d62a17ae 6333
ddb5b488
PZ
6334 if (SAFI_UNICAST == safi
6335 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6336 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6337 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6338 }
6339
d62a17ae 6340 /* Unintern original. */
6341 aspath_unintern(&attr.aspath);
718e3744 6342}
6343
5f040085 6344void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6345 safi_t safi)
718e3744 6346{
9bcb3eef 6347 struct bgp_dest *dest;
40381db7 6348 struct bgp_path_info *pi;
718e3744 6349
9bcb3eef 6350 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6351
d62a17ae 6352 /* Check selected route and self inserted route. */
9bcb3eef 6353 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6354 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6355 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6356 break;
6357
6358 /* Withdraw static BGP route from routing table. */
40381db7 6359 if (pi) {
ddb5b488
PZ
6360 if (SAFI_UNICAST == safi
6361 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6362 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6363 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6364 }
40381db7
DS
6365 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6366 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6367 bgp_path_info_delete(dest, pi);
6368 bgp_process(bgp, dest, afi, safi);
d62a17ae 6369 }
718e3744 6370
d62a17ae 6371 /* Unlock bgp_node_lookup. */
9bcb3eef 6372 bgp_dest_unlock_node(dest);
718e3744 6373}
6374
137446f9
LB
6375/*
6376 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6377 */
5f040085 6378static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6379 afi_t afi, safi_t safi,
6380 struct prefix_rd *prd)
718e3744 6381{
9bcb3eef 6382 struct bgp_dest *dest;
40381db7 6383 struct bgp_path_info *pi;
718e3744 6384
9bcb3eef 6385 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6386
d62a17ae 6387 /* Check selected route and self inserted route. */
9bcb3eef 6388 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6389 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6390 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6391 break;
718e3744 6392
d62a17ae 6393 /* Withdraw static BGP route from routing table. */
40381db7 6394 if (pi) {
49e5a4a0 6395#ifdef ENABLE_BGP_VNC
d62a17ae 6396 rfapiProcessWithdraw(
40381db7 6397 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6398 1); /* Kill, since it is an administrative change */
65efcfce 6399#endif
ddb5b488
PZ
6400 if (SAFI_MPLS_VPN == safi
6401 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6402 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6403 }
40381db7 6404 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6405 bgp_path_info_delete(dest, pi);
6406 bgp_process(bgp, dest, afi, safi);
d62a17ae 6407 }
718e3744 6408
d62a17ae 6409 /* Unlock bgp_node_lookup. */
9bcb3eef 6410 bgp_dest_unlock_node(dest);
718e3744 6411}
6412
5f040085 6413static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6414 struct bgp_static *bgp_static, afi_t afi,
6415 safi_t safi)
137446f9 6416{
9bcb3eef 6417 struct bgp_dest *dest;
4b7e6066 6418 struct bgp_path_info *new;
d62a17ae 6419 struct attr *attr_new;
6420 struct attr attr = {0};
40381db7 6421 struct bgp_path_info *pi;
49e5a4a0 6422#ifdef ENABLE_BGP_VNC
d62a17ae 6423 mpls_label_t label = 0;
65efcfce 6424#endif
d7c0a89a 6425 uint32_t num_labels = 0;
137446f9 6426
d62a17ae 6427 assert(bgp_static);
137446f9 6428
b57ba6d2
MK
6429 if (bgp_static->label != MPLS_INVALID_LABEL)
6430 num_labels = 1;
9bcb3eef
DS
6431 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6432 &bgp_static->prd);
137446f9 6433
0f05ea43 6434 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6435
d62a17ae 6436 attr.nexthop = bgp_static->igpnexthop;
6437 attr.med = bgp_static->igpmetric;
6438 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6439
d62a17ae 6440 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6441 || (safi == SAFI_ENCAP)) {
6442 if (afi == AFI_IP) {
6443 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6444 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6445 }
6446 }
6447 if (afi == AFI_L2VPN) {
b04c1e99
IR
6448 if (bgp_static->gatewayIp.family == AF_INET) {
6449 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6450 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6451 &bgp_static->gatewayIp.u.prefix4,
6452 IPV4_MAX_BYTELEN);
b04c1e99
IR
6453 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6454 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6455 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6456 &bgp_static->gatewayIp.u.prefix6,
6457 IPV6_MAX_BYTELEN);
b04c1e99 6458 }
0a50c248 6459 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6460 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6461 struct bgp_encap_type_vxlan bet;
6006b807 6462 memset(&bet, 0, sizeof(bet));
3714a385 6463 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6464 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6465 }
6466 if (bgp_static->router_mac) {
6467 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6468 }
6469 }
6470 /* Apply route-map. */
6471 if (bgp_static->rmap.name) {
6472 struct attr attr_tmp = attr;
40381db7 6473 struct bgp_path_info rmap_path;
b68885f9 6474 route_map_result_t ret;
137446f9 6475
40381db7
DS
6476 rmap_path.peer = bgp->peer_self;
6477 rmap_path.attr = &attr_tmp;
137446f9 6478
d62a17ae 6479 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6480
1782514f 6481 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6482
d62a17ae 6483 bgp->peer_self->rmap_type = 0;
137446f9 6484
d62a17ae 6485 if (ret == RMAP_DENYMATCH) {
6486 /* Free uninterned attribute. */
6487 bgp_attr_flush(&attr_tmp);
137446f9 6488
d62a17ae 6489 /* Unintern original. */
6490 aspath_unintern(&attr.aspath);
6491 bgp_static_withdraw_safi(bgp, p, afi, safi,
6492 &bgp_static->prd);
bbc52106 6493 bgp_dest_unlock_node(dest);
d62a17ae 6494 return;
6495 }
137446f9 6496
d62a17ae 6497 attr_new = bgp_attr_intern(&attr_tmp);
6498 } else {
6499 attr_new = bgp_attr_intern(&attr);
6500 }
137446f9 6501
9bcb3eef 6502 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6503 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6504 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6505 break;
6506
40381db7 6507 if (pi) {
40381db7 6508 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6509 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6510 bgp_dest_unlock_node(dest);
d62a17ae 6511 bgp_attr_unintern(&attr_new);
6512 aspath_unintern(&attr.aspath);
6513 return;
6514 } else {
6515 /* The attribute is changed. */
9bcb3eef 6516 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6517
6518 /* Rewrite BGP route information. */
40381db7 6519 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6520 bgp_path_info_restore(dest, pi);
d62a17ae 6521 else
40381db7
DS
6522 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6523 bgp_attr_unintern(&pi->attr);
6524 pi->attr = attr_new;
083ec940 6525 pi->uptime = monotime(NULL);
49e5a4a0 6526#ifdef ENABLE_BGP_VNC
40381db7
DS
6527 if (pi->extra)
6528 label = decode_label(&pi->extra->label[0]);
65efcfce 6529#endif
137446f9 6530
d62a17ae 6531 /* Process change. */
40381db7 6532 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6533 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6534
6535 if (SAFI_MPLS_VPN == safi
6536 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6537 vpn_leak_to_vrf_update(bgp, pi,
6538 &bgp_static->prd);
ddb5b488 6539 }
49e5a4a0 6540#ifdef ENABLE_BGP_VNC
40381db7
DS
6541 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6542 pi->attr, afi, safi, pi->type,
6543 pi->sub_type, &label);
65efcfce 6544#endif
9bcb3eef 6545 bgp_dest_unlock_node(dest);
d62a17ae 6546 aspath_unintern(&attr.aspath);
6547 return;
6548 }
6549 }
137446f9
LB
6550
6551
d62a17ae 6552 /* Make new BGP info. */
6553 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6554 attr_new, dest);
1defdda8 6555 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6556 bgp_path_info_extra_get(new);
b57ba6d2
MK
6557 if (num_labels) {
6558 new->extra->label[0] = bgp_static->label;
6559 new->extra->num_labels = num_labels;
6560 }
49e5a4a0 6561#ifdef ENABLE_BGP_VNC
d62a17ae 6562 label = decode_label(&bgp_static->label);
65efcfce 6563#endif
137446f9 6564
d62a17ae 6565 /* Aggregate address increment. */
6566 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6567
d62a17ae 6568 /* Register new BGP information. */
9bcb3eef 6569 bgp_path_info_add(dest, new);
d62a17ae 6570 /* route_node_get lock */
9bcb3eef 6571 bgp_dest_unlock_node(dest);
137446f9 6572
d62a17ae 6573 /* Process change. */
9bcb3eef 6574 bgp_process(bgp, dest, afi, safi);
137446f9 6575
ddb5b488
PZ
6576 if (SAFI_MPLS_VPN == safi
6577 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6578 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6579 }
49e5a4a0 6580#ifdef ENABLE_BGP_VNC
d62a17ae 6581 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6582 safi, new->type, new->sub_type, &label);
65efcfce
LB
6583#endif
6584
d62a17ae 6585 /* Unintern original. */
6586 aspath_unintern(&attr.aspath);
137446f9
LB
6587}
6588
718e3744 6589/* Configure static BGP network. When user don't run zebra, static
6590 route should be installed as valid. */
585f1adc
IR
6591static int bgp_static_set(struct vty *vty, const char *negate,
6592 const char *ip_str, afi_t afi, safi_t safi,
6593 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6594{
585f1adc
IR
6595 VTY_DECLVAR_CONTEXT(bgp, bgp);
6596 int ret;
d62a17ae 6597 struct prefix p;
6598 struct bgp_static *bgp_static;
9bcb3eef 6599 struct bgp_dest *dest;
d7c0a89a 6600 uint8_t need_update = 0;
d62a17ae 6601
585f1adc
IR
6602 /* Convert IP prefix string to struct prefix. */
6603 ret = str2prefix(ip_str, &p);
6604 if (!ret) {
6605 vty_out(vty, "%% Malformed prefix\n");
6606 return CMD_WARNING_CONFIG_FAILED;
6607 }
6608 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6609 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6610 return CMD_WARNING_CONFIG_FAILED;
6611 }
6612
d62a17ae 6613 apply_mask(&p);
718e3744 6614
e2a86ad9 6615 if (negate) {
718e3744 6616
e2a86ad9 6617 /* Set BGP static route configuration. */
9bcb3eef 6618 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6619
9bcb3eef 6620 if (!dest) {
585f1adc
IR
6621 vty_out(vty, "%% Can't find static route specified\n");
6622 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6623 }
6624
9bcb3eef 6625 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6626
e2a86ad9
DS
6627 if ((label_index != BGP_INVALID_LABEL_INDEX)
6628 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6629 vty_out(vty,
6630 "%% label-index doesn't match static route\n");
70d9b134 6631 bgp_dest_unlock_node(dest);
585f1adc 6632 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6633 }
d62a17ae 6634
e2a86ad9
DS
6635 if ((rmap && bgp_static->rmap.name)
6636 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6637 vty_out(vty,
6638 "%% route-map name doesn't match static route\n");
70d9b134 6639 bgp_dest_unlock_node(dest);
585f1adc 6640 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6641 }
718e3744 6642
e2a86ad9
DS
6643 /* Update BGP RIB. */
6644 if (!bgp_static->backdoor)
6645 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6646
e2a86ad9
DS
6647 /* Clear configuration. */
6648 bgp_static_free(bgp_static);
9bcb3eef
DS
6649 bgp_dest_set_bgp_static_info(dest, NULL);
6650 bgp_dest_unlock_node(dest);
6651 bgp_dest_unlock_node(dest);
e2a86ad9 6652 } else {
718e3744 6653
e2a86ad9 6654 /* Set BGP static route configuration. */
9bcb3eef
DS
6655 dest = bgp_node_get(bgp->route[afi][safi], &p);
6656 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6657 if (bgp_static) {
e2a86ad9 6658 /* Configuration change. */
e2a86ad9
DS
6659 /* Label index cannot be changed. */
6660 if (bgp_static->label_index != label_index) {
585f1adc 6661 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6662 bgp_dest_unlock_node(dest);
585f1adc 6663 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6664 }
d62a17ae 6665
e2a86ad9 6666 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6667 if (bgp_static->valid
6668 && bgp_static->backdoor != backdoor)
e2a86ad9 6669 need_update = 1;
718e3744 6670
e2a86ad9 6671 bgp_static->backdoor = backdoor;
718e3744 6672
e2a86ad9 6673 if (rmap) {
0a22ddfb
QY
6674 XFREE(MTYPE_ROUTE_MAP_NAME,
6675 bgp_static->rmap.name);
b4897fa5 6676 route_map_counter_decrement(
6677 bgp_static->rmap.map);
e2a86ad9
DS
6678 bgp_static->rmap.name =
6679 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6680 bgp_static->rmap.map =
6681 route_map_lookup_by_name(rmap);
b4897fa5 6682 route_map_counter_increment(
6683 bgp_static->rmap.map);
e2a86ad9 6684 } else {
0a22ddfb
QY
6685 XFREE(MTYPE_ROUTE_MAP_NAME,
6686 bgp_static->rmap.name);
b4897fa5 6687 route_map_counter_decrement(
6688 bgp_static->rmap.map);
e2a86ad9
DS
6689 bgp_static->rmap.map = NULL;
6690 bgp_static->valid = 0;
6691 }
9bcb3eef 6692 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6693 } else {
6694 /* New configuration. */
6695 bgp_static = bgp_static_new();
6696 bgp_static->backdoor = backdoor;
6697 bgp_static->valid = 0;
6698 bgp_static->igpmetric = 0;
975a328e 6699 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6700 bgp_static->label_index = label_index;
718e3744 6701
e2a86ad9 6702 if (rmap) {
0a22ddfb
QY
6703 XFREE(MTYPE_ROUTE_MAP_NAME,
6704 bgp_static->rmap.name);
b4897fa5 6705 route_map_counter_decrement(
6706 bgp_static->rmap.map);
e2a86ad9
DS
6707 bgp_static->rmap.name =
6708 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6709 bgp_static->rmap.map =
6710 route_map_lookup_by_name(rmap);
b4897fa5 6711 route_map_counter_increment(
6712 bgp_static->rmap.map);
e2a86ad9 6713 }
9bcb3eef 6714 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6715 }
d62a17ae 6716
e2a86ad9
DS
6717 bgp_static->valid = 1;
6718 if (need_update)
6719 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6720
e2a86ad9
DS
6721 if (!bgp_static->backdoor)
6722 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6723 }
d62a17ae 6724
585f1adc 6725 return CMD_SUCCESS;
d62a17ae 6726}
6727
6728void bgp_static_add(struct bgp *bgp)
6729{
6730 afi_t afi;
6731 safi_t safi;
9bcb3eef
DS
6732 struct bgp_dest *dest;
6733 struct bgp_dest *rm;
d62a17ae 6734 struct bgp_table *table;
6735 struct bgp_static *bgp_static;
6736
47fc6261 6737 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6738 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6739 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6740 dest = bgp_route_next(dest)) {
6741 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6742 continue;
ea47320b 6743
05c7a1cc
QY
6744 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6745 || (safi == SAFI_EVPN)) {
9bcb3eef 6746 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6747
6748 for (rm = bgp_table_top(table); rm;
6749 rm = bgp_route_next(rm)) {
a78beeb5 6750 bgp_static =
9bcb3eef 6751 bgp_dest_get_bgp_static_info(
5a8ba9fc 6752 rm);
9bcb3eef
DS
6753 bgp_static_update_safi(
6754 bgp, bgp_dest_get_prefix(rm),
6755 bgp_static, afi, safi);
d62a17ae 6756 }
05c7a1cc 6757 } else {
5a8ba9fc 6758 bgp_static_update(
9bcb3eef
DS
6759 bgp, bgp_dest_get_prefix(dest),
6760 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6761 safi);
ea47320b 6762 }
05c7a1cc 6763 }
47fc6261 6764 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6765}
6766
718e3744 6767/* Called from bgp_delete(). Delete all static routes from the BGP
6768 instance. */
d62a17ae 6769void bgp_static_delete(struct bgp *bgp)
6770{
6771 afi_t afi;
6772 safi_t safi;
9bcb3eef
DS
6773 struct bgp_dest *dest;
6774 struct bgp_dest *rm;
d62a17ae 6775 struct bgp_table *table;
6776 struct bgp_static *bgp_static;
6777
05c7a1cc 6778 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6779 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6780 dest = bgp_route_next(dest)) {
6781 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6782 continue;
ea47320b 6783
05c7a1cc
QY
6784 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6785 || (safi == SAFI_EVPN)) {
9bcb3eef 6786 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6787
6788 for (rm = bgp_table_top(table); rm;
6789 rm = bgp_route_next(rm)) {
a78beeb5 6790 bgp_static =
9bcb3eef 6791 bgp_dest_get_bgp_static_info(
5a8ba9fc 6792 rm);
c7d14ba6
PG
6793 if (!bgp_static)
6794 continue;
6795
05c7a1cc 6796 bgp_static_withdraw_safi(
9bcb3eef 6797 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6798 AFI_IP, safi,
6799 (struct prefix_rd *)
9bcb3eef
DS
6800 bgp_dest_get_prefix(
6801 dest));
ea47320b 6802 bgp_static_free(bgp_static);
811c6797 6803 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6804 NULL);
811c6797 6805 bgp_dest_unlock_node(rm);
d62a17ae 6806 }
05c7a1cc 6807 } else {
9bcb3eef 6808 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6809 bgp_static_withdraw(bgp,
9bcb3eef 6810 bgp_dest_get_prefix(dest),
b54892e0 6811 afi, safi);
05c7a1cc 6812 bgp_static_free(bgp_static);
9bcb3eef
DS
6813 bgp_dest_set_bgp_static_info(dest, NULL);
6814 bgp_dest_unlock_node(dest);
ea47320b 6815 }
05c7a1cc 6816 }
d62a17ae 6817}
6818
6819void bgp_static_redo_import_check(struct bgp *bgp)
6820{
6821 afi_t afi;
6822 safi_t safi;
9bcb3eef
DS
6823 struct bgp_dest *dest;
6824 struct bgp_dest *rm;
d62a17ae 6825 struct bgp_table *table;
6826 struct bgp_static *bgp_static;
6827
6828 /* Use this flag to force reprocessing of the route */
892fedb6 6829 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6830 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6831 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6832 dest = bgp_route_next(dest)) {
6833 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6834 continue;
ea47320b 6835
05c7a1cc
QY
6836 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6837 || (safi == SAFI_EVPN)) {
9bcb3eef 6838 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6839
6840 for (rm = bgp_table_top(table); rm;
6841 rm = bgp_route_next(rm)) {
a78beeb5 6842 bgp_static =
9bcb3eef 6843 bgp_dest_get_bgp_static_info(
5a8ba9fc 6844 rm);
9bcb3eef
DS
6845 bgp_static_update_safi(
6846 bgp, bgp_dest_get_prefix(rm),
6847 bgp_static, afi, safi);
d62a17ae 6848 }
05c7a1cc 6849 } else {
9bcb3eef
DS
6850 bgp_static = bgp_dest_get_bgp_static_info(dest);
6851 bgp_static_update(bgp,
6852 bgp_dest_get_prefix(dest),
6853 bgp_static, afi, safi);
ea47320b 6854 }
05c7a1cc
QY
6855 }
6856 }
892fedb6 6857 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6858}
6859
6860static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6861 safi_t safi)
6862{
6863 struct bgp_table *table;
9bcb3eef 6864 struct bgp_dest *dest;
40381db7 6865 struct bgp_path_info *pi;
d62a17ae 6866
dfb6fd1d
NT
6867 /* Do not install the aggregate route if BGP is in the
6868 * process of termination.
6869 */
892fedb6
DA
6870 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6871 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6872 return;
6873
d62a17ae 6874 table = bgp->rib[afi][safi];
9bcb3eef
DS
6875 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6876 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6877 if (pi->peer == bgp->peer_self
6878 && ((pi->type == ZEBRA_ROUTE_BGP
6879 && pi->sub_type == BGP_ROUTE_STATIC)
6880 || (pi->type != ZEBRA_ROUTE_BGP
6881 && pi->sub_type
d62a17ae 6882 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6883 bgp_aggregate_decrement(
6884 bgp, bgp_dest_get_prefix(dest), pi, afi,
6885 safi);
40381db7 6886 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6887 bgp_path_info_delete(dest, pi);
6888 bgp_process(bgp, dest, afi, safi);
d62a17ae 6889 }
6890 }
6891 }
ad4cbda1 6892}
6893
6894/*
6895 * Purge all networks and redistributed routes from routing table.
6896 * Invoked upon the instance going down.
6897 */
d62a17ae 6898void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6899{
d62a17ae 6900 afi_t afi;
6901 safi_t safi;
ad4cbda1 6902
05c7a1cc
QY
6903 FOREACH_AFI_SAFI (afi, safi)
6904 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6905}
6906
137446f9
LB
6907/*
6908 * gpz 110624
6909 * Currently this is used to set static routes for VPN and ENCAP.
6910 * I think it can probably be factored with bgp_static_set.
6911 */
d62a17ae 6912int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6913 const char *ip_str, const char *rd_str,
6914 const char *label_str, const char *rmap_str,
6915 int evpn_type, const char *esi, const char *gwip,
6916 const char *ethtag, const char *routermac)
6917{
6918 VTY_DECLVAR_CONTEXT(bgp, bgp);
6919 int ret;
6920 struct prefix p;
6921 struct prefix_rd prd;
9bcb3eef
DS
6922 struct bgp_dest *pdest;
6923 struct bgp_dest *dest;
d62a17ae 6924 struct bgp_table *table;
6925 struct bgp_static *bgp_static;
6926 mpls_label_t label = MPLS_INVALID_LABEL;
6927 struct prefix gw_ip;
6928
6929 /* validate ip prefix */
6930 ret = str2prefix(ip_str, &p);
6931 if (!ret) {
6932 vty_out(vty, "%% Malformed prefix\n");
6933 return CMD_WARNING_CONFIG_FAILED;
6934 }
6935 apply_mask(&p);
6936 if ((afi == AFI_L2VPN)
6937 && (bgp_build_evpn_prefix(evpn_type,
6938 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6939 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6940 return CMD_WARNING_CONFIG_FAILED;
6941 }
718e3744 6942
d62a17ae 6943 ret = str2prefix_rd(rd_str, &prd);
6944 if (!ret) {
6945 vty_out(vty, "%% Malformed rd\n");
6946 return CMD_WARNING_CONFIG_FAILED;
6947 }
718e3744 6948
d62a17ae 6949 if (label_str) {
6950 unsigned long label_val;
6951 label_val = strtoul(label_str, NULL, 10);
6952 encode_label(label_val, &label);
6953 }
9bedbb1e 6954
d62a17ae 6955 if (safi == SAFI_EVPN) {
6956 if (esi && str2esi(esi, NULL) == 0) {
6957 vty_out(vty, "%% Malformed ESI\n");
6958 return CMD_WARNING_CONFIG_FAILED;
6959 }
6960 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6961 vty_out(vty, "%% Malformed Router MAC\n");
6962 return CMD_WARNING_CONFIG_FAILED;
6963 }
6964 if (gwip) {
6006b807 6965 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6966 ret = str2prefix(gwip, &gw_ip);
6967 if (!ret) {
6968 vty_out(vty, "%% Malformed GatewayIp\n");
6969 return CMD_WARNING_CONFIG_FAILED;
6970 }
6971 if ((gw_ip.family == AF_INET
3714a385 6972 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6973 (struct prefix_evpn *)&p))
6974 || (gw_ip.family == AF_INET6
3714a385 6975 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6976 (struct prefix_evpn *)&p))) {
6977 vty_out(vty,
6978 "%% GatewayIp family differs with IP prefix\n");
6979 return CMD_WARNING_CONFIG_FAILED;
6980 }
6981 }
6982 }
9bcb3eef
DS
6983 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6984 if (!bgp_dest_has_bgp_path_info_data(pdest))
6985 bgp_dest_set_bgp_table_info(pdest,
67009e22 6986 bgp_table_init(bgp, afi, safi));
9bcb3eef 6987 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6988
9bcb3eef 6989 dest = bgp_node_get(table, &p);
d62a17ae 6990
9bcb3eef 6991 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6992 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6993 bgp_dest_unlock_node(dest);
d62a17ae 6994 } else {
6995 /* New configuration. */
6996 bgp_static = bgp_static_new();
6997 bgp_static->backdoor = 0;
6998 bgp_static->valid = 0;
6999 bgp_static->igpmetric = 0;
975a328e 7000 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7001 bgp_static->label = label;
7002 bgp_static->prd = prd;
7003
7004 if (rmap_str) {
0a22ddfb 7005 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7006 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7007 bgp_static->rmap.name =
7008 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7009 bgp_static->rmap.map =
7010 route_map_lookup_by_name(rmap_str);
b4897fa5 7011 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7012 }
718e3744 7013
d62a17ae 7014 if (safi == SAFI_EVPN) {
7015 if (esi) {
7016 bgp_static->eth_s_id =
7017 XCALLOC(MTYPE_ATTR,
0a50c248 7018 sizeof(esi_t));
d62a17ae 7019 str2esi(esi, bgp_static->eth_s_id);
7020 }
7021 if (routermac) {
7022 bgp_static->router_mac =
28328ea9 7023 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7024 (void)prefix_str2mac(routermac,
7025 bgp_static->router_mac);
d62a17ae 7026 }
7027 if (gwip)
7028 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7029 }
9bcb3eef 7030 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7031
d62a17ae 7032 bgp_static->valid = 1;
7033 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7034 }
718e3744 7035
d62a17ae 7036 return CMD_SUCCESS;
718e3744 7037}
7038
7039/* Configure static BGP network. */
d62a17ae 7040int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7041 const char *ip_str, const char *rd_str,
7042 const char *label_str, int evpn_type, const char *esi,
7043 const char *gwip, const char *ethtag)
7044{
7045 VTY_DECLVAR_CONTEXT(bgp, bgp);
7046 int ret;
7047 struct prefix p;
7048 struct prefix_rd prd;
9bcb3eef
DS
7049 struct bgp_dest *pdest;
7050 struct bgp_dest *dest;
d62a17ae 7051 struct bgp_table *table;
7052 struct bgp_static *bgp_static;
7053 mpls_label_t label = MPLS_INVALID_LABEL;
7054
7055 /* Convert IP prefix string to struct prefix. */
7056 ret = str2prefix(ip_str, &p);
7057 if (!ret) {
7058 vty_out(vty, "%% Malformed prefix\n");
7059 return CMD_WARNING_CONFIG_FAILED;
7060 }
7061 apply_mask(&p);
7062 if ((afi == AFI_L2VPN)
7063 && (bgp_build_evpn_prefix(evpn_type,
7064 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7065 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7066 return CMD_WARNING_CONFIG_FAILED;
7067 }
7068 ret = str2prefix_rd(rd_str, &prd);
7069 if (!ret) {
7070 vty_out(vty, "%% Malformed rd\n");
7071 return CMD_WARNING_CONFIG_FAILED;
7072 }
718e3744 7073
d62a17ae 7074 if (label_str) {
7075 unsigned long label_val;
7076 label_val = strtoul(label_str, NULL, 10);
7077 encode_label(label_val, &label);
7078 }
718e3744 7079
9bcb3eef
DS
7080 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7081 if (!bgp_dest_has_bgp_path_info_data(pdest))
7082 bgp_dest_set_bgp_table_info(pdest,
67009e22 7083 bgp_table_init(bgp, afi, safi));
d62a17ae 7084 else
9bcb3eef
DS
7085 bgp_dest_unlock_node(pdest);
7086 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7087
9bcb3eef 7088 dest = bgp_node_lookup(table, &p);
6b0655a2 7089
9bcb3eef 7090 if (dest) {
d62a17ae 7091 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7092
9bcb3eef 7093 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7094 bgp_static_free(bgp_static);
9bcb3eef
DS
7095 bgp_dest_set_bgp_static_info(dest, NULL);
7096 bgp_dest_unlock_node(dest);
7097 bgp_dest_unlock_node(dest);
d62a17ae 7098 } else
7099 vty_out(vty, "%% Can't find the route\n");
7100
7101 return CMD_SUCCESS;
7102}
7103
7104static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7105 const char *rmap_name)
7106{
7107 VTY_DECLVAR_CONTEXT(bgp, bgp);
7108 struct bgp_rmap *rmap;
7109
7110 rmap = &bgp->table_map[afi][safi];
7111 if (rmap_name) {
0a22ddfb 7112 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7113 route_map_counter_decrement(rmap->map);
d62a17ae 7114 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7115 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7116 route_map_counter_increment(rmap->map);
d62a17ae 7117 } else {
0a22ddfb 7118 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7119 route_map_counter_decrement(rmap->map);
d62a17ae 7120 rmap->map = NULL;
7121 }
73ac8160 7122
d62a17ae 7123 if (bgp_fibupd_safi(safi))
7124 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7125
d62a17ae 7126 return CMD_SUCCESS;
73ac8160
DS
7127}
7128
d62a17ae 7129static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7130 const char *rmap_name)
73ac8160 7131{
d62a17ae 7132 VTY_DECLVAR_CONTEXT(bgp, bgp);
7133 struct bgp_rmap *rmap;
73ac8160 7134
d62a17ae 7135 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7136 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7137 route_map_counter_decrement(rmap->map);
d62a17ae 7138 rmap->map = NULL;
73ac8160 7139
d62a17ae 7140 if (bgp_fibupd_safi(safi))
7141 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7142
d62a17ae 7143 return CMD_SUCCESS;
73ac8160
DS
7144}
7145
2b791107 7146void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7147 safi_t safi)
73ac8160 7148{
d62a17ae 7149 if (bgp->table_map[afi][safi].name) {
d62a17ae 7150 vty_out(vty, " table-map %s\n",
7151 bgp->table_map[afi][safi].name);
7152 }
73ac8160
DS
7153}
7154
73ac8160
DS
7155DEFUN (bgp_table_map,
7156 bgp_table_map_cmd,
7157 "table-map WORD",
7158 "BGP table to RIB route download filter\n"
7159 "Name of the route map\n")
7160{
d62a17ae 7161 int idx_word = 1;
7162 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7163 argv[idx_word]->arg);
73ac8160
DS
7164}
7165DEFUN (no_bgp_table_map,
7166 no_bgp_table_map_cmd,
7167 "no table-map WORD",
3a2d747c 7168 NO_STR
73ac8160
DS
7169 "BGP table to RIB route download filter\n"
7170 "Name of the route map\n")
7171{
d62a17ae 7172 int idx_word = 2;
7173 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7174 argv[idx_word]->arg);
73ac8160
DS
7175}
7176
585f1adc
IR
7177DEFPY(bgp_network,
7178 bgp_network_cmd,
7179 "[no] network \
7180 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7181 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7182 backdoor$backdoor}]",
7183 NO_STR
7184 "Specify a network to announce via BGP\n"
7185 "IPv4 prefix\n"
7186 "Network number\n"
7187 "Network mask\n"
7188 "Network mask\n"
7189 "Route-map to modify the attributes\n"
7190 "Name of the route map\n"
7191 "Label index to associate with the prefix\n"
7192 "Label index value\n"
7193 "Specify a BGP backdoor route\n")
7194{
7195 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7196
7197 if (address_str) {
7198 int ret;
718e3744 7199
e2a86ad9 7200 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7201 addr_prefix_str,
7202 sizeof(addr_prefix_str));
e2a86ad9
DS
7203 if (!ret) {
7204 vty_out(vty, "%% Inconsistent address and mask\n");
7205 return CMD_WARNING_CONFIG_FAILED;
7206 }
d62a17ae 7207 }
718e3744 7208
585f1adc
IR
7209 return bgp_static_set(
7210 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7211 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7212 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7213}
7214
585f1adc
IR
7215DEFPY(ipv6_bgp_network,
7216 ipv6_bgp_network_cmd,
7217 "[no] network X:X::X:X/M$prefix \
70dd370f 7218 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7219 NO_STR
7220 "Specify a network to announce via BGP\n"
7221 "IPv6 prefix\n"
7222 "Route-map to modify the attributes\n"
7223 "Name of the route map\n"
7224 "Label index to associate with the prefix\n"
7225 "Label index value\n")
37a87b8f 7226{
585f1adc
IR
7227 return bgp_static_set(
7228 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7229 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7230}
7231
d62a17ae 7232static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7233{
d62a17ae 7234 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7235}
7236
d62a17ae 7237static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7238{
365ab2e7
RZ
7239 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7240 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7241 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7242 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7243 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7244}
718e3744 7245
365ab2e7
RZ
7246/**
7247 * Helper function to avoid repeated code: prepare variables for a
7248 * `route_map_apply` call.
7249 *
7250 * \returns `true` on route map match, otherwise `false`.
7251 */
7252static bool aggr_suppress_map_test(struct bgp *bgp,
7253 struct bgp_aggregate *aggregate,
7254 struct bgp_path_info *pi)
7255{
7256 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7257 route_map_result_t rmr = RMAP_DENYMATCH;
7258 struct bgp_path_info rmap_path = {};
7259 struct attr attr = {};
7260
7261 /* No route map entries created, just don't match. */
7262 if (aggregate->suppress_map == NULL)
7263 return false;
7264
7265 /* Call route map matching and return result. */
7266 attr.aspath = aspath_empty();
7267 rmap_path.peer = bgp->peer_self;
7268 rmap_path.attr = &attr;
7269
7270 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7271 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7272 bgp->peer_self->rmap_type = 0;
7273
7274 bgp_attr_flush(&attr);
afb254d7 7275 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7276
7277 return rmr == RMAP_PERMITMATCH;
7278}
7279
4056a5f6
RZ
7280/** Test whether the aggregation has suppressed this path or not. */
7281static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7282 struct bgp_path_info *pi)
7283{
7284 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7285 return false;
7286
7287 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7288}
7289
7290/**
7291 * Suppress this path and keep the reference.
7292 *
7293 * \returns `true` if needs processing otherwise `false`.
7294 */
7295static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7296 struct bgp_path_info *pi)
7297{
7298 struct bgp_path_info_extra *pie;
7299
7300 /* Path is already suppressed by this aggregation. */
7301 if (aggr_suppress_exists(aggregate, pi))
7302 return false;
7303
7304 pie = bgp_path_info_extra_get(pi);
7305
7306 /* This is the first suppression, allocate memory and list it. */
7307 if (pie->aggr_suppressors == NULL)
7308 pie->aggr_suppressors = list_new();
7309
7310 listnode_add(pie->aggr_suppressors, aggregate);
7311
7312 /* Only mark for processing if suppressed. */
7313 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7314 if (BGP_DEBUG(update, UPDATE_OUT))
7315 zlog_debug("aggregate-address suppressing: %pFX",
7316 bgp_dest_get_prefix(pi->net));
7317
4056a5f6
RZ
7318 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7319 return true;
7320 }
7321
7322 return false;
7323}
7324
7325/**
7326 * Unsuppress this path and remove the reference.
7327 *
7328 * \returns `true` if needs processing otherwise `false`.
7329 */
7330static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7331 struct bgp_path_info *pi)
7332{
7333 /* Path wasn't suppressed. */
7334 if (!aggr_suppress_exists(aggregate, pi))
7335 return false;
7336
7337 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7338
7339 /* Unsuppress and free extra memory if last item. */
7340 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7341 if (BGP_DEBUG(update, UPDATE_OUT))
7342 zlog_debug("aggregate-address unsuppressing: %pFX",
7343 bgp_dest_get_prefix(pi->net));
7344
4056a5f6
RZ
7345 list_delete(&pi->extra->aggr_suppressors);
7346 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7347 return true;
7348 }
7349
7350 return false;
7351}
7352
3dc339cd
DA
7353static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7354 struct aspath *aspath,
7355 struct community *comm,
7356 struct ecommunity *ecomm,
7357 struct lcommunity *lcomm)
eaaf8adb
DS
7358{
7359 static struct aspath *ae = NULL;
7360
7361 if (!ae)
7362 ae = aspath_empty();
7363
40381db7 7364 if (!pi)
3dc339cd 7365 return false;
eaaf8adb 7366
40381db7 7367 if (origin != pi->attr->origin)
3dc339cd 7368 return false;
eaaf8adb 7369
40381db7 7370 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7371 return false;
29f7d023 7372
9a706b42 7373 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7374 return false;
eaaf8adb 7375
b53e67a3 7376 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7377 return false;
eaaf8adb 7378
1bcf3a96 7379 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7380 return false;
dd18c5a9 7381
40381db7 7382 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7383 return false;
7ce8a8e0 7384
3dc339cd 7385 return true;
eaaf8adb
DS
7386}
7387
5f040085
DS
7388static void bgp_aggregate_install(
7389 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7390 uint8_t origin, struct aspath *aspath, struct community *community,
7391 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7392 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7393{
9bcb3eef 7394 struct bgp_dest *dest;
c701010e 7395 struct bgp_table *table;
6f94b685 7396 struct bgp_path_info *pi, *orig, *new;
20894f50 7397 struct attr *attr;
c701010e
DS
7398
7399 table = bgp->rib[afi][safi];
7400
9bcb3eef 7401 dest = bgp_node_get(table, p);
eaaf8adb 7402
9bcb3eef 7403 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7404 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7405 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7406 break;
7407
6aabb15d
RZ
7408 /*
7409 * If we have paths with different MEDs, then don't install
7410 * (or uninstall) the aggregate route.
7411 */
7412 if (aggregate->match_med && aggregate->med_mismatched)
7413 goto uninstall_aggregate_route;
7414
c701010e 7415 if (aggregate->count > 0) {
eaaf8adb
DS
7416 /*
7417 * If the aggregate information has not changed
7418 * no need to re-install it again.
7419 */
6f94b685 7420 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7421 ecommunity, lcommunity)) {
9bcb3eef 7422 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7423
7424 if (aspath)
7425 aspath_free(aspath);
7426 if (community)
3c1f53de 7427 community_free(&community);
3da2cc32
DS
7428 if (ecommunity)
7429 ecommunity_free(&ecommunity);
dd18c5a9
DS
7430 if (lcommunity)
7431 lcommunity_free(&lcommunity);
eaaf8adb
DS
7432
7433 return;
7434 }
7435
7436 /*
7437 * Mark the old as unusable
7438 */
40381db7 7439 if (pi)
9bcb3eef 7440 bgp_path_info_delete(dest, pi);
eaaf8adb 7441
20894f50
DA
7442 attr = bgp_attr_aggregate_intern(
7443 bgp, origin, aspath, community, ecommunity, lcommunity,
7444 aggregate, atomic_aggregate, p);
7445
7446 if (!attr) {
8c0044f3 7447 bgp_dest_unlock_node(dest);
20894f50 7448 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7449 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7450 zlog_debug("%s: %pFX null attribute", __func__,
7451 p);
20894f50
DA
7452 return;
7453 }
7454
3da2cc32 7455 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7456 bgp->peer_self, attr, dest);
20894f50 7457
1defdda8 7458 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7459
9bcb3eef
DS
7460 bgp_path_info_add(dest, new);
7461 bgp_process(bgp, dest, afi, safi);
c701010e 7462 } else {
6aabb15d 7463 uninstall_aggregate_route:
6f94b685 7464 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7465 if (pi->peer == bgp->peer_self
7466 && pi->type == ZEBRA_ROUTE_BGP
7467 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7468 break;
7469
7470 /* Withdraw static BGP route from routing table. */
40381db7 7471 if (pi) {
9bcb3eef
DS
7472 bgp_path_info_delete(dest, pi);
7473 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7474 }
7475 }
7476
9bcb3eef 7477 bgp_dest_unlock_node(dest);
c701010e
DS
7478}
7479
6aabb15d
RZ
7480/**
7481 * Check if the current path has different MED than other known paths.
7482 *
7483 * \returns `true` if the MED matched the others else `false`.
7484 */
7485static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7486 struct bgp *bgp, struct bgp_path_info *pi)
7487{
7488 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7489
7490 /* This is the first route being analyzed. */
7491 if (!aggregate->med_initialized) {
7492 aggregate->med_initialized = true;
7493 aggregate->med_mismatched = false;
7494 aggregate->med_matched_value = cur_med;
7495 } else {
7496 /* Check if routes with different MED showed up. */
7497 if (cur_med != aggregate->med_matched_value)
7498 aggregate->med_mismatched = true;
7499 }
7500
7501 return !aggregate->med_mismatched;
7502}
7503
7504/**
7505 * Initializes and tests all routes in the aggregate address path for MED
7506 * values.
7507 *
7508 * \returns `true` if all MEDs are the same otherwise `false`.
7509 */
7510static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7511 struct bgp *bgp, const struct prefix *p,
7512 afi_t afi, safi_t safi)
7513{
7514 struct bgp_table *table = bgp->rib[afi][safi];
7515 const struct prefix *dest_p;
7516 struct bgp_dest *dest, *top;
7517 struct bgp_path_info *pi;
7518 bool med_matched = true;
7519
7520 aggregate->med_initialized = false;
7521
7522 top = bgp_node_get(table, p);
7523 for (dest = bgp_node_get(table, p); dest;
7524 dest = bgp_route_next_until(dest, top)) {
7525 dest_p = bgp_dest_get_prefix(dest);
7526 if (dest_p->prefixlen <= p->prefixlen)
7527 continue;
7528
7529 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7530 if (BGP_PATH_HOLDDOWN(pi))
7531 continue;
7532 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7533 continue;
7534 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7535 med_matched = false;
7536 break;
7537 }
7538 }
7539 if (!med_matched)
7540 break;
7541 }
7542 bgp_dest_unlock_node(top);
7543
7544 return med_matched;
7545}
7546
7547/**
7548 * Toggles the route suppression status for this aggregate address
7549 * configuration.
7550 */
4056a5f6
RZ
7551void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7552 struct bgp *bgp, const struct prefix *p,
7553 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7554{
7555 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7556 const struct prefix *dest_p;
7557 struct bgp_dest *dest, *top;
7558 struct bgp_path_info *pi;
7559 bool toggle_suppression;
7560
7561 /* We've found a different MED we must revert any suppressed routes. */
7562 top = bgp_node_get(table, p);
7563 for (dest = bgp_node_get(table, p); dest;
7564 dest = bgp_route_next_until(dest, top)) {
7565 dest_p = bgp_dest_get_prefix(dest);
7566 if (dest_p->prefixlen <= p->prefixlen)
7567 continue;
7568
7569 toggle_suppression = false;
7570 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7571 if (BGP_PATH_HOLDDOWN(pi))
7572 continue;
7573 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7574 continue;
7575
6aabb15d
RZ
7576 /* We are toggling suppression back. */
7577 if (suppress) {
6aabb15d 7578 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7579 if (aggr_suppress_path(aggregate, pi))
7580 toggle_suppression = true;
6aabb15d
RZ
7581 continue;
7582 }
7583
6aabb15d 7584 /* Install route if there is no more suppression. */
4056a5f6 7585 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7586 toggle_suppression = true;
6aabb15d
RZ
7587 }
7588
7589 if (toggle_suppression)
7590 bgp_process(bgp, dest, afi, safi);
7591 }
7592 bgp_dest_unlock_node(top);
7593}
7594
7595/**
7596 * Aggregate address MED matching incremental test: this function is called
7597 * when the initial aggregation occurred and we are only testing a single
7598 * new path.
7599 *
7600 * In addition to testing and setting the MED validity it also installs back
7601 * suppressed routes (if summary is configured).
7602 *
7603 * Must not be called in `bgp_aggregate_route`.
7604 */
7605static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7606 struct bgp *bgp, const struct prefix *p,
7607 afi_t afi, safi_t safi,
f66624f5 7608 struct bgp_path_info *pi)
6aabb15d
RZ
7609{
7610 /* MED matching disabled. */
7611 if (!aggregate->match_med)
7612 return;
7613
f66624f5
DA
7614 /* Aggregation with different MED, recheck if we have got equal MEDs
7615 * now.
6aabb15d 7616 */
f66624f5
DA
7617 if (aggregate->med_mismatched &&
7618 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7619 aggregate->summary_only)
7620 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7621 true);
7622 else
6aabb15d
RZ
7623 bgp_aggregate_med_match(aggregate, bgp, pi);
7624
7625 /* No mismatches, just quit. */
7626 if (!aggregate->med_mismatched)
7627 return;
7628
7629 /* Route summarization is disabled. */
7630 if (!aggregate->summary_only)
7631 return;
7632
7633 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7634}
7635
b5d58c32 7636/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7637void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7638 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7639{
7640 struct bgp_table *table;
9bcb3eef
DS
7641 struct bgp_dest *top;
7642 struct bgp_dest *dest;
d7c0a89a 7643 uint8_t origin;
d62a17ae 7644 struct aspath *aspath = NULL;
d62a17ae 7645 struct community *community = NULL;
3da2cc32 7646 struct ecommunity *ecommunity = NULL;
dd18c5a9 7647 struct lcommunity *lcommunity = NULL;
40381db7 7648 struct bgp_path_info *pi;
d62a17ae 7649 unsigned long match = 0;
d7c0a89a 7650 uint8_t atomic_aggregate = 0;
d62a17ae 7651
9f822fa2
S
7652 /* If the bgp instance is being deleted or self peer is deleted
7653 * then do not create aggregate route
7654 */
892fedb6
DA
7655 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7656 || (bgp->peer_self == NULL))
9f822fa2
S
7657 return;
7658
6aabb15d
RZ
7659 /* Initialize and test routes for MED difference. */
7660 if (aggregate->match_med)
7661 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7662
4056a5f6
RZ
7663 /*
7664 * Reset aggregate count: we might've been called from route map
7665 * update so in that case we must retest all more specific routes.
7666 *
7667 * \see `bgp_route_map_process_update`.
7668 */
7669 aggregate->count = 0;
7670 aggregate->incomplete_origin_count = 0;
7671 aggregate->incomplete_origin_count = 0;
7672 aggregate->egp_origin_count = 0;
7673
d62a17ae 7674 /* ORIGIN attribute: If at least one route among routes that are
7675 aggregated has ORIGIN with the value INCOMPLETE, then the
7676 aggregated route must have the ORIGIN attribute with the value
7677 INCOMPLETE. Otherwise, if at least one route among routes that
7678 are aggregated has ORIGIN with the value EGP, then the aggregated
7679 route must have the origin attribute with the value EGP. In all
7680 other case the value of the ORIGIN attribute of the aggregated
7681 route is INTERNAL. */
7682 origin = BGP_ORIGIN_IGP;
718e3744 7683
d62a17ae 7684 table = bgp->rib[afi][safi];
718e3744 7685
d62a17ae 7686 top = bgp_node_get(table, p);
9bcb3eef
DS
7687 for (dest = bgp_node_get(table, p); dest;
7688 dest = bgp_route_next_until(dest, top)) {
7689 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7690
9bcb3eef 7691 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7692 continue;
d62a17ae 7693
a77e2f4b
S
7694 /* If suppress fib is enabled and route not installed
7695 * in FIB, skip the route
7696 */
7697 if (!bgp_check_advertise(bgp, dest))
7698 continue;
7699
c2ff8b3e 7700 match = 0;
d62a17ae 7701
9bcb3eef 7702 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7703 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7704 continue;
718e3744 7705
40381db7 7706 if (pi->attr->flag
c2ff8b3e
DS
7707 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7708 atomic_aggregate = 1;
d62a17ae 7709
40381db7 7710 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7711 continue;
d62a17ae 7712
f273fef1
DS
7713 /*
7714 * summary-only aggregate route suppress
7715 * aggregated route announcements.
6aabb15d
RZ
7716 *
7717 * MED matching:
7718 * Don't create summaries if MED didn't match
7719 * otherwise neither the specific routes and the
7720 * aggregation will be announced.
f273fef1 7721 */
6aabb15d
RZ
7722 if (aggregate->summary_only
7723 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7724 if (aggr_suppress_path(aggregate, pi))
7725 match++;
d62a17ae 7726 }
c2ff8b3e 7727
365ab2e7
RZ
7728 /*
7729 * Suppress more specific routes that match the route
7730 * map results.
7731 *
7732 * MED matching:
7733 * Don't suppress routes if MED matching is enabled and
7734 * it mismatched otherwise we might end up with no
7735 * routes for this path.
7736 */
7737 if (aggregate->suppress_map_name
7738 && AGGREGATE_MED_VALID(aggregate)
7739 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7740 if (aggr_suppress_path(aggregate, pi))
7741 match++;
d62a17ae 7742 }
c2ff8b3e
DS
7743
7744 aggregate->count++;
7745
f273fef1
DS
7746 /*
7747 * If at least one route among routes that are
7748 * aggregated has ORIGIN with the value INCOMPLETE,
7749 * then the aggregated route MUST have the ORIGIN
7750 * attribute with the value INCOMPLETE. Otherwise, if
7751 * at least one route among routes that are aggregated
7752 * has ORIGIN with the value EGP, then the aggregated
7753 * route MUST have the ORIGIN attribute with the value
7754 * EGP.
7755 */
fc968841
NT
7756 switch (pi->attr->origin) {
7757 case BGP_ORIGIN_INCOMPLETE:
7758 aggregate->incomplete_origin_count++;
7759 break;
7760 case BGP_ORIGIN_EGP:
7761 aggregate->egp_origin_count++;
7762 break;
7763 default:
7764 /*Do nothing.
7765 */
7766 break;
7767 }
c2ff8b3e
DS
7768
7769 if (!aggregate->as_set)
7770 continue;
7771
f273fef1
DS
7772 /*
7773 * as-set aggregate route generate origin, as path,
7774 * and community aggregation.
7775 */
fc968841
NT
7776 /* Compute aggregate route's as-path.
7777 */
ef51a7d8 7778 bgp_compute_aggregate_aspath_hash(aggregate,
7779 pi->attr->aspath);
c2ff8b3e 7780
fc968841
NT
7781 /* Compute aggregate route's community.
7782 */
9a706b42 7783 if (bgp_attr_get_community(pi->attr))
21fec674 7784 bgp_compute_aggregate_community_hash(
9a706b42
DA
7785 aggregate,
7786 bgp_attr_get_community(pi->attr));
dd18c5a9 7787
fc968841
NT
7788 /* Compute aggregate route's extended community.
7789 */
b53e67a3 7790 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7791 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7792 aggregate,
7793 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7794
7795 /* Compute aggregate route's large community.
7796 */
1bcf3a96 7797 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7798 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7799 aggregate,
7800 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7801 }
c2ff8b3e 7802 if (match)
9bcb3eef 7803 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7804 }
21fec674 7805 if (aggregate->as_set) {
ef51a7d8 7806 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7807 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7808 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7809 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7810 }
7811
f1eb1f05 7812
9bcb3eef 7813 bgp_dest_unlock_node(top);
718e3744 7814
718e3744 7815
fc968841
NT
7816 if (aggregate->incomplete_origin_count > 0)
7817 origin = BGP_ORIGIN_INCOMPLETE;
7818 else if (aggregate->egp_origin_count > 0)
7819 origin = BGP_ORIGIN_EGP;
d62a17ae 7820
229757f1
DA
7821 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7822 origin = aggregate->origin;
7823
fc968841
NT
7824 if (aggregate->as_set) {
7825 if (aggregate->aspath)
7826 /* Retrieve aggregate route's as-path.
7827 */
7828 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7829
fc968841
NT
7830 if (aggregate->community)
7831 /* Retrieve aggregate route's community.
7832 */
7833 community = community_dup(aggregate->community);
3da2cc32 7834
fc968841
NT
7835 if (aggregate->ecommunity)
7836 /* Retrieve aggregate route's ecommunity.
7837 */
7838 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7839
fc968841
NT
7840 if (aggregate->lcommunity)
7841 /* Retrieve aggregate route's lcommunity.
7842 */
7843 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7844 }
718e3744 7845
c701010e 7846 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7847 ecommunity, lcommunity, atomic_aggregate,
7848 aggregate);
718e3744 7849}
7850
5f040085
DS
7851void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7852 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7853{
7854 struct bgp_table *table;
9bcb3eef
DS
7855 struct bgp_dest *top;
7856 struct bgp_dest *dest;
40381db7 7857 struct bgp_path_info *pi;
3b7db173
DS
7858 unsigned long match;
7859
7860 table = bgp->rib[afi][safi];
7861
7862 /* If routes exists below this node, generate aggregate routes. */
7863 top = bgp_node_get(table, p);
9bcb3eef
DS
7864 for (dest = bgp_node_get(table, p); dest;
7865 dest = bgp_route_next_until(dest, top)) {
7866 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7867
9bcb3eef 7868 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7869 continue;
7870 match = 0;
7871
9bcb3eef 7872 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7873 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7874 continue;
7875
40381db7 7876 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7877 continue;
7878
92b175bd
RZ
7879 /*
7880 * This route is suppressed: attempt to unsuppress it.
7881 *
7882 * `aggr_unsuppress_path` will fail if this particular
7883 * aggregate route was not the suppressor.
7884 */
7885 if (pi->extra && pi->extra->aggr_suppressors &&
7886 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7887 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7888 match++;
3b7db173 7889 }
365ab2e7 7890
3b7db173 7891 aggregate->count--;
fc968841
NT
7892
7893 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7894 aggregate->incomplete_origin_count--;
7895 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7896 aggregate->egp_origin_count--;
7897
7898 if (aggregate->as_set) {
7899 /* Remove as-path from aggregate.
7900 */
ef51a7d8 7901 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7902 aggregate,
7903 pi->attr->aspath);
7904
9a706b42 7905 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7906 /* Remove community from aggregate.
7907 */
21fec674 7908 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7909 aggregate,
7910 bgp_attr_get_community(
7911 pi->attr));
fc968841 7912
b53e67a3 7913 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7914 /* Remove ecommunity from aggregate.
7915 */
4edd83f9 7916 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7917 aggregate,
7918 bgp_attr_get_ecommunity(
7919 pi->attr));
fc968841 7920
1bcf3a96 7921 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7922 /* Remove lcommunity from aggregate.
7923 */
f1eb1f05 7924 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7925 aggregate,
7926 bgp_attr_get_lcommunity(
7927 pi->attr));
fc968841 7928 }
3b7db173
DS
7929 }
7930
7931 /* If this node was suppressed, process the change. */
7932 if (match)
9bcb3eef 7933 bgp_process(bgp, dest, afi, safi);
3b7db173 7934 }
f1eb1f05 7935 if (aggregate->as_set) {
ef51a7d8 7936 aspath_free(aggregate->aspath);
7937 aggregate->aspath = NULL;
21fec674 7938 if (aggregate->community)
7939 community_free(&aggregate->community);
4edd83f9 7940 if (aggregate->ecommunity)
7941 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7942 if (aggregate->lcommunity)
7943 lcommunity_free(&aggregate->lcommunity);
7944 }
7945
9bcb3eef 7946 bgp_dest_unlock_node(top);
3b7db173 7947}
718e3744 7948
5f040085
DS
7949static void bgp_add_route_to_aggregate(struct bgp *bgp,
7950 const struct prefix *aggr_p,
fc968841
NT
7951 struct bgp_path_info *pinew, afi_t afi,
7952 safi_t safi,
7953 struct bgp_aggregate *aggregate)
7954{
7955 uint8_t origin;
7956 struct aspath *aspath = NULL;
7957 uint8_t atomic_aggregate = 0;
7958 struct community *community = NULL;
7959 struct ecommunity *ecommunity = NULL;
7960 struct lcommunity *lcommunity = NULL;
7961
a4559740 7962 /* If the bgp instance is being deleted or self peer is deleted
7963 * then do not create aggregate route
7964 */
7965 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7966 || (bgp->peer_self == NULL))
7967 return;
7968
fc968841
NT
7969 /* ORIGIN attribute: If at least one route among routes that are
7970 * aggregated has ORIGIN with the value INCOMPLETE, then the
7971 * aggregated route must have the ORIGIN attribute with the value
7972 * INCOMPLETE. Otherwise, if at least one route among routes that
7973 * are aggregated has ORIGIN with the value EGP, then the aggregated
7974 * route must have the origin attribute with the value EGP. In all
7975 * other case the value of the ORIGIN attribute of the aggregated
7976 * route is INTERNAL.
7977 */
7978 origin = BGP_ORIGIN_IGP;
7979
7980 aggregate->count++;
7981
6aabb15d
RZ
7982 /*
7983 * This must be called before `summary` check to avoid
7984 * "suppressing" twice.
7985 */
7986 if (aggregate->match_med)
7987 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 7988 pinew);
6aabb15d
RZ
7989
7990 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7991 aggr_suppress_path(aggregate, pinew);
fc968841 7992
365ab2e7
RZ
7993 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7994 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7995 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7996
7997 switch (pinew->attr->origin) {
7998 case BGP_ORIGIN_INCOMPLETE:
7999 aggregate->incomplete_origin_count++;
8000 break;
8001 case BGP_ORIGIN_EGP:
8002 aggregate->egp_origin_count++;
8003 break;
8004 default:
8005 /* Do nothing.
8006 */
8007 break;
8008 }
8009
8010 if (aggregate->incomplete_origin_count > 0)
8011 origin = BGP_ORIGIN_INCOMPLETE;
8012 else if (aggregate->egp_origin_count > 0)
8013 origin = BGP_ORIGIN_EGP;
8014
229757f1
DA
8015 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8016 origin = aggregate->origin;
8017
fc968841
NT
8018 if (aggregate->as_set) {
8019 /* Compute aggregate route's as-path.
8020 */
8021 bgp_compute_aggregate_aspath(aggregate,
8022 pinew->attr->aspath);
8023
8024 /* Compute aggregate route's community.
8025 */
9a706b42 8026 if (bgp_attr_get_community(pinew->attr))
fc968841 8027 bgp_compute_aggregate_community(
9a706b42 8028 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8029
8030 /* Compute aggregate route's extended community.
8031 */
b53e67a3 8032 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8033 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8034 aggregate,
8035 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8036
8037 /* Compute aggregate route's large community.
8038 */
1bcf3a96 8039 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8040 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8041 aggregate,
8042 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8043
8044 /* Retrieve aggregate route's as-path.
8045 */
8046 if (aggregate->aspath)
8047 aspath = aspath_dup(aggregate->aspath);
8048
8049 /* Retrieve aggregate route's community.
8050 */
8051 if (aggregate->community)
8052 community = community_dup(aggregate->community);
8053
8054 /* Retrieve aggregate route's ecommunity.
8055 */
8056 if (aggregate->ecommunity)
8057 ecommunity = ecommunity_dup(aggregate->ecommunity);
8058
8059 /* Retrieve aggregate route's lcommunity.
8060 */
8061 if (aggregate->lcommunity)
8062 lcommunity = lcommunity_dup(aggregate->lcommunity);
8063 }
8064
8065 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8066 aspath, community, ecommunity,
8067 lcommunity, atomic_aggregate, aggregate);
8068}
8069
8070static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8071 safi_t safi,
8072 struct bgp_path_info *pi,
8073 struct bgp_aggregate *aggregate,
5f040085 8074 const struct prefix *aggr_p)
fc968841
NT
8075{
8076 uint8_t origin;
8077 struct aspath *aspath = NULL;
8078 uint8_t atomic_aggregate = 0;
8079 struct community *community = NULL;
8080 struct ecommunity *ecommunity = NULL;
8081 struct lcommunity *lcommunity = NULL;
8082 unsigned long match = 0;
8083
a4559740 8084 /* If the bgp instance is being deleted or self peer is deleted
8085 * then do not create aggregate route
8086 */
8087 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8088 || (bgp->peer_self == NULL))
8089 return;
8090
fc968841
NT
8091 if (BGP_PATH_HOLDDOWN(pi))
8092 return;
8093
8094 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8095 return;
8096
4056a5f6
RZ
8097 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8098 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8099 match++;
fc968841 8100
365ab2e7 8101 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8102 && aggr_suppress_map_test(bgp, aggregate, pi))
8103 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8104 match++;
fc968841 8105
6aabb15d 8106 /*
365ab2e7 8107 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8108 * "unsuppressing" twice.
8109 */
8110 if (aggregate->match_med)
f66624f5 8111 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8112
fc968841
NT
8113 if (aggregate->count > 0)
8114 aggregate->count--;
8115
8116 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8117 aggregate->incomplete_origin_count--;
8118 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8119 aggregate->egp_origin_count--;
8120
8121 if (aggregate->as_set) {
8122 /* Remove as-path from aggregate.
8123 */
8124 bgp_remove_aspath_from_aggregate(aggregate,
8125 pi->attr->aspath);
8126
9a706b42 8127 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8128 /* Remove community from aggregate.
8129 */
8130 bgp_remove_community_from_aggregate(
9a706b42 8131 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8132
b53e67a3 8133 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8134 /* Remove ecommunity from aggregate.
8135 */
8136 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8137 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8138
1bcf3a96 8139 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8140 /* Remove lcommunity from aggregate.
8141 */
8142 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8143 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8144 }
8145
8146 /* If this node was suppressed, process the change. */
8147 if (match)
8148 bgp_process(bgp, pi->net, afi, safi);
8149
8150 origin = BGP_ORIGIN_IGP;
8151 if (aggregate->incomplete_origin_count > 0)
8152 origin = BGP_ORIGIN_INCOMPLETE;
8153 else if (aggregate->egp_origin_count > 0)
8154 origin = BGP_ORIGIN_EGP;
8155
229757f1
DA
8156 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8157 origin = aggregate->origin;
8158
fc968841
NT
8159 if (aggregate->as_set) {
8160 /* Retrieve aggregate route's as-path.
8161 */
8162 if (aggregate->aspath)
8163 aspath = aspath_dup(aggregate->aspath);
8164
8165 /* Retrieve aggregate route's community.
8166 */
8167 if (aggregate->community)
8168 community = community_dup(aggregate->community);
8169
8170 /* Retrieve aggregate route's ecommunity.
8171 */
8172 if (aggregate->ecommunity)
8173 ecommunity = ecommunity_dup(aggregate->ecommunity);
8174
8175 /* Retrieve aggregate route's lcommunity.
8176 */
8177 if (aggregate->lcommunity)
8178 lcommunity = lcommunity_dup(aggregate->lcommunity);
8179 }
8180
8181 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8182 aspath, community, ecommunity,
8183 lcommunity, atomic_aggregate, aggregate);
8184}
8185
5a1ae2c2 8186void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8187 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8188{
9bcb3eef
DS
8189 struct bgp_dest *child;
8190 struct bgp_dest *dest;
d62a17ae 8191 struct bgp_aggregate *aggregate;
8192 struct bgp_table *table;
718e3744 8193
d62a17ae 8194 table = bgp->aggregate[afi][safi];
f018db83 8195
d62a17ae 8196 /* No aggregates configured. */
8197 if (bgp_table_top_nolock(table) == NULL)
8198 return;
f018db83 8199
d62a17ae 8200 if (p->prefixlen == 0)
8201 return;
718e3744 8202
40381db7 8203 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8204 return;
718e3744 8205
a77e2f4b
S
8206 /* If suppress fib is enabled and route not installed
8207 * in FIB, do not update the aggregate route
8208 */
8209 if (!bgp_check_advertise(bgp, pi->net))
8210 return;
8211
d62a17ae 8212 child = bgp_node_get(table, p);
718e3744 8213
d62a17ae 8214 /* Aggregate address configuration check. */
9bcb3eef
DS
8215 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8216 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8217
9bcb3eef
DS
8218 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8219 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8220 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8221 aggregate);
d62a17ae 8222 }
b1e62edd 8223 }
9bcb3eef 8224 bgp_dest_unlock_node(child);
718e3744 8225}
8226
5a1ae2c2 8227void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8228 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8229{
9bcb3eef
DS
8230 struct bgp_dest *child;
8231 struct bgp_dest *dest;
d62a17ae 8232 struct bgp_aggregate *aggregate;
8233 struct bgp_table *table;
718e3744 8234
d62a17ae 8235 table = bgp->aggregate[afi][safi];
718e3744 8236
d62a17ae 8237 /* No aggregates configured. */
8238 if (bgp_table_top_nolock(table) == NULL)
8239 return;
718e3744 8240
d62a17ae 8241 if (p->prefixlen == 0)
8242 return;
718e3744 8243
d62a17ae 8244 child = bgp_node_get(table, p);
718e3744 8245
d62a17ae 8246 /* Aggregate address configuration check. */
9bcb3eef
DS
8247 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8248 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8249
9bcb3eef
DS
8250 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8251 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8252 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8253 aggregate, dest_p);
d62a17ae 8254 }
b1e62edd 8255 }
9bcb3eef 8256 bgp_dest_unlock_node(child);
d62a17ae 8257}
718e3744 8258
718e3744 8259/* Aggregate route attribute. */
8260#define AGGREGATE_SUMMARY_ONLY 1
8261#define AGGREGATE_AS_SET 1
fb29348a 8262#define AGGREGATE_AS_UNSET 0
718e3744 8263
229757f1
DA
8264static const char *bgp_origin2str(uint8_t origin)
8265{
8266 switch (origin) {
8267 case BGP_ORIGIN_IGP:
8268 return "igp";
8269 case BGP_ORIGIN_EGP:
8270 return "egp";
8271 case BGP_ORIGIN_INCOMPLETE:
8272 return "incomplete";
8273 }
8274 return "n/a";
8275}
8276
fdeb5a81 8277static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8278{
8279 switch (v_state) {
fdeb5a81
DS
8280 case RPKI_NOT_BEING_USED:
8281 return "not used";
8282 case RPKI_VALID:
b5b99af8 8283 return "valid";
fdeb5a81 8284 case RPKI_NOTFOUND:
b5b99af8 8285 return "not found";
fdeb5a81 8286 case RPKI_INVALID:
b5b99af8 8287 return "invalid";
b5b99af8 8288 }
fdeb5a81
DS
8289
8290 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8291 return "ERROR";
8292}
8293
585f1adc
IR
8294static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8295 afi_t afi, safi_t safi)
718e3744 8296{
585f1adc
IR
8297 VTY_DECLVAR_CONTEXT(bgp, bgp);
8298 int ret;
8299 struct prefix p;
9bcb3eef 8300 struct bgp_dest *dest;
d62a17ae 8301 struct bgp_aggregate *aggregate;
718e3744 8302
585f1adc
IR
8303 /* Convert string to prefix structure. */
8304 ret = str2prefix(prefix_str, &p);
8305 if (!ret) {
8306 vty_out(vty, "Malformed prefix\n");
8307 return CMD_WARNING_CONFIG_FAILED;
8308 }
8309 apply_mask(&p);
a4559740 8310
d62a17ae 8311 /* Old configuration check. */
585f1adc 8312 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8313 if (!dest) {
585f1adc
IR
8314 vty_out(vty,
8315 "%% There is no aggregate-address configuration.\n");
8316 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8317 }
f6269b4f 8318
9bcb3eef 8319 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8320 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8321 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8322 NULL, NULL, 0, aggregate);
d62a17ae 8323
8324 /* Unlock aggregate address configuration. */
9bcb3eef 8325 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8326
8327 if (aggregate->community)
8328 community_free(&aggregate->community);
8329
8330 if (aggregate->community_hash) {
8331 /* Delete all communities in the hash.
8332 */
8333 hash_clean(aggregate->community_hash,
8334 bgp_aggr_community_remove);
8335 /* Free up the community_hash.
8336 */
8337 hash_free(aggregate->community_hash);
8338 }
8339
8340 if (aggregate->ecommunity)
8341 ecommunity_free(&aggregate->ecommunity);
8342
8343 if (aggregate->ecommunity_hash) {
8344 /* Delete all ecommunities in the hash.
8345 */
8346 hash_clean(aggregate->ecommunity_hash,
8347 bgp_aggr_ecommunity_remove);
8348 /* Free up the ecommunity_hash.
8349 */
8350 hash_free(aggregate->ecommunity_hash);
8351 }
8352
8353 if (aggregate->lcommunity)
8354 lcommunity_free(&aggregate->lcommunity);
8355
8356 if (aggregate->lcommunity_hash) {
8357 /* Delete all lcommunities in the hash.
8358 */
8359 hash_clean(aggregate->lcommunity_hash,
8360 bgp_aggr_lcommunity_remove);
8361 /* Free up the lcommunity_hash.
8362 */
8363 hash_free(aggregate->lcommunity_hash);
8364 }
8365
8366 if (aggregate->aspath)
8367 aspath_free(aggregate->aspath);
8368
8369 if (aggregate->aspath_hash) {
8370 /* Delete all as-paths in the hash.
8371 */
8372 hash_clean(aggregate->aspath_hash,
8373 bgp_aggr_aspath_remove);
8374 /* Free up the aspath_hash.
8375 */
8376 hash_free(aggregate->aspath_hash);
8377 }
8378
d62a17ae 8379 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8380 bgp_dest_unlock_node(dest);
8381 bgp_dest_unlock_node(dest);
d62a17ae 8382
585f1adc 8383 return CMD_SUCCESS;
d62a17ae 8384}
8385
585f1adc
IR
8386static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8387 safi_t safi, const char *rmap,
8388 uint8_t summary_only, uint8_t as_set,
8389 uint8_t origin, bool match_med,
8390 const char *suppress_map)
d62a17ae 8391{
585f1adc 8392 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8393 int ret;
585f1adc 8394 struct prefix p;
9bcb3eef 8395 struct bgp_dest *dest;
d62a17ae 8396 struct bgp_aggregate *aggregate;
fb29348a 8397 uint8_t as_set_new = as_set;
d62a17ae 8398
365ab2e7 8399 if (suppress_map && summary_only) {
585f1adc 8400 vty_out(vty,
365ab2e7 8401 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8402 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8403 }
8404
585f1adc
IR
8405 /* Convert string to prefix structure. */
8406 ret = str2prefix(prefix_str, &p);
8407 if (!ret) {
8408 vty_out(vty, "Malformed prefix\n");
8409 return CMD_WARNING_CONFIG_FAILED;
8410 }
8411 apply_mask(&p);
d62a17ae 8412
585f1adc
IR
8413 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8414 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8415 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8416 prefix_str);
8417 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8418 }
8419
d62a17ae 8420 /* Old configuration check. */
585f1adc 8421 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8422 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8423
20894f50 8424 if (aggregate) {
585f1adc 8425 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8426 /* try to remove the old entry */
585f1adc 8427 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8428 if (ret) {
585f1adc 8429 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8430 bgp_dest_unlock_node(dest);
585f1adc 8431 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8432 }
8433 }
718e3744 8434
d62a17ae 8435 /* Make aggregate address structure. */
8436 aggregate = bgp_aggregate_new();
8437 aggregate->summary_only = summary_only;
6aabb15d 8438 aggregate->match_med = match_med;
fb29348a
DA
8439
8440 /* Network operators MUST NOT locally generate any new
8441 * announcements containing AS_SET or AS_CONFED_SET. If they have
8442 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8443 * SHOULD withdraw those routes and re-announce routes for the
8444 * aggregate or component prefixes (i.e., the more-specific routes
8445 * subsumed by the previously aggregated route) without AS_SET
8446 * or AS_CONFED_SET in the updates.
8447 */
7f972cd8 8448 if (bgp->reject_as_sets) {
fb29348a
DA
8449 if (as_set == AGGREGATE_AS_SET) {
8450 as_set_new = AGGREGATE_AS_UNSET;
8451 zlog_warn(
63efca0e 8452 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8453 __func__);
585f1adc 8454 vty_out(vty,
fb29348a
DA
8455 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8456 }
8457 }
8458
8459 aggregate->as_set = as_set_new;
d62a17ae 8460 aggregate->safi = safi;
229757f1
DA
8461 /* Override ORIGIN attribute if defined.
8462 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8463 * to IGP which is not what rfc4271 says.
8464 * This enables the same behavior, optionally.
8465 */
8466 aggregate->origin = origin;
20894f50
DA
8467
8468 if (rmap) {
8469 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8470 route_map_counter_decrement(aggregate->rmap.map);
8471 aggregate->rmap.name =
8472 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8473 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8474 route_map_counter_increment(aggregate->rmap.map);
8475 }
365ab2e7
RZ
8476
8477 if (suppress_map) {
8478 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8479 route_map_counter_decrement(aggregate->suppress_map);
8480
8481 aggregate->suppress_map_name =
8482 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8483 aggregate->suppress_map =
8484 route_map_lookup_by_name(aggregate->suppress_map_name);
8485 route_map_counter_increment(aggregate->suppress_map);
8486 }
8487
9bcb3eef 8488 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8489
d62a17ae 8490 /* Aggregate address insert into BGP routing table. */
585f1adc 8491 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8492
585f1adc 8493 return CMD_SUCCESS;
718e3744 8494}
8495
585f1adc
IR
8496DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8497 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8498 "as-set$as_set_s"
8499 "|summary-only$summary_only"
cacba915 8500 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8501 "|origin <egp|igp|incomplete>$origin_s"
8502 "|matching-MED-only$match_med"
cacba915 8503 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8504 "}]",
8505 NO_STR
8506 "Configure BGP aggregate entries\n"
764402fe
DA
8507 "Aggregate prefix\n"
8508 "Aggregate address\n"
8509 "Aggregate mask\n"
585f1adc
IR
8510 "Generate AS set path information\n"
8511 "Filter more specific routes from updates\n"
8512 "Apply route map to aggregate network\n"
8513 "Route map name\n"
8514 "BGP origin code\n"
8515 "Remote EGP\n"
8516 "Local IGP\n"
8517 "Unknown heritage\n"
8518 "Only aggregate routes with matching MED\n"
8519 "Suppress the selected more specific routes\n"
8520 "Route map with the route selectors\n")
8521{
8522 const char *prefix_s = NULL;
554b3b10 8523 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8524 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8525 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8526 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8527
554b3b10 8528 if (addr_str) {
7533cad7
QY
8529 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8530 sizeof(prefix_buf))
554b3b10
RZ
8531 == 0) {
8532 vty_out(vty, "%% Inconsistent address and mask\n");
8533 return CMD_WARNING_CONFIG_FAILED;
8534 }
585f1adc
IR
8535 prefix_s = prefix_buf;
8536 } else
8537 prefix_s = prefix_str;
37a87b8f 8538
585f1adc
IR
8539 if (origin_s) {
8540 if (strcmp(origin_s, "egp") == 0)
8541 origin = BGP_ORIGIN_EGP;
8542 else if (strcmp(origin_s, "igp") == 0)
8543 origin = BGP_ORIGIN_IGP;
8544 else if (strcmp(origin_s, "incomplete") == 0)
8545 origin = BGP_ORIGIN_INCOMPLETE;
8546 }
90e21f35 8547
585f1adc
IR
8548 if (as_set_s)
8549 as_set = AGGREGATE_AS_SET;
554b3b10 8550
585f1adc 8551 /* Handle configuration removal, otherwise installation. */
554b3b10 8552 if (no)
585f1adc
IR
8553 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8554
8555 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8556 summary_only != NULL, as_set, origin,
8557 match_med != NULL, suppress_map);
8558}
8559
8560DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8561 "[no] aggregate-address X:X::X:X/M$prefix [{"
8562 "as-set$as_set_s"
8563 "|summary-only$summary_only"
cacba915 8564 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8565 "|origin <egp|igp|incomplete>$origin_s"
8566 "|matching-MED-only$match_med"
cacba915 8567 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8568 "}]",
8569 NO_STR
8570 "Configure BGP aggregate entries\n"
8571 "Aggregate prefix\n"
8572 "Generate AS set path information\n"
8573 "Filter more specific routes from updates\n"
8574 "Apply route map to aggregate network\n"
8575 "Route map name\n"
8576 "BGP origin code\n"
8577 "Remote EGP\n"
8578 "Local IGP\n"
8579 "Unknown heritage\n"
8580 "Only aggregate routes with matching MED\n"
8581 "Suppress the selected more specific routes\n"
8582 "Route map with the route selectors\n")
8583{
8584 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8585 int as_set = AGGREGATE_AS_UNSET;
8586
8587 if (origin_s) {
8588 if (strcmp(origin_s, "egp") == 0)
8589 origin = BGP_ORIGIN_EGP;
8590 else if (strcmp(origin_s, "igp") == 0)
8591 origin = BGP_ORIGIN_IGP;
8592 else if (strcmp(origin_s, "incomplete") == 0)
8593 origin = BGP_ORIGIN_INCOMPLETE;
8594 }
8595
8596 if (as_set_s)
8597 as_set = AGGREGATE_AS_SET;
8598
8599 /* Handle configuration removal, otherwise installation. */
554b3b10 8600 if (no)
585f1adc
IR
8601 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8602 SAFI_UNICAST);
554b3b10 8603
585f1adc
IR
8604 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8605 rmap_name, summary_only != NULL, as_set,
8606 origin, match_med != NULL, suppress_map);
718e3744 8607}
8608
718e3744 8609/* Redistribute route treatment. */
d62a17ae 8610void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8611 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8612 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8613 enum blackhole_type bhtype, uint32_t metric,
8614 uint8_t type, unsigned short instance,
8615 route_tag_t tag)
d62a17ae 8616{
4b7e6066 8617 struct bgp_path_info *new;
40381db7
DS
8618 struct bgp_path_info *bpi;
8619 struct bgp_path_info rmap_path;
9bcb3eef 8620 struct bgp_dest *bn;
d62a17ae 8621 struct attr attr;
8622 struct attr *new_attr;
8623 afi_t afi;
b68885f9 8624 route_map_result_t ret;
d62a17ae 8625 struct bgp_redist *red;
8626
8627 /* Make default attribute. */
0f05ea43 8628 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8629 /*
8630 * This must not be NULL to satisfy Coverity SA
8631 */
8632 assert(attr.aspath);
9de1f7ff 8633
a4d82a8a 8634 switch (nhtype) {
9de1f7ff 8635 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8636 switch (p->family) {
8637 case AF_INET:
8638 attr.nexthop.s_addr = INADDR_ANY;
8639 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8640 break;
8641 case AF_INET6:
8642 memset(&attr.mp_nexthop_global, 0,
8643 sizeof(attr.mp_nexthop_global));
8644 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8645 break;
8646 }
9de1f7ff
DS
8647 break;
8648 case NEXTHOP_TYPE_IPV4:
8649 case NEXTHOP_TYPE_IPV4_IFINDEX:
8650 attr.nexthop = nexthop->ipv4;
7226bc40 8651 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8652 break;
8653 case NEXTHOP_TYPE_IPV6:
8654 case NEXTHOP_TYPE_IPV6_IFINDEX:
8655 attr.mp_nexthop_global = nexthop->ipv6;
8656 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8657 break;
8658 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8659 switch (p->family) {
8660 case AF_INET:
9de1f7ff 8661 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8662 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8663 break;
8664 case AF_INET6:
9de1f7ff
DS
8665 memset(&attr.mp_nexthop_global, 0,
8666 sizeof(attr.mp_nexthop_global));
74489921 8667 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8668 break;
74489921 8669 }
0789eb69 8670 attr.bh_type = bhtype;
9de1f7ff 8671 break;
d62a17ae 8672 }
0789eb69 8673 attr.nh_type = nhtype;
74489921 8674 attr.nh_ifindex = ifindex;
f04a80a5 8675
d62a17ae 8676 attr.med = metric;
957f74c3 8677 attr.distance = distance;
d62a17ae 8678 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8679 attr.tag = tag;
718e3744 8680
d62a17ae 8681 afi = family2afi(p->family);
6aeb9e78 8682
d62a17ae 8683 red = bgp_redist_lookup(bgp, afi, type, instance);
8684 if (red) {
8685 struct attr attr_new;
718e3744 8686
d62a17ae 8687 /* Copy attribute for modification. */
6f4f49b2 8688 attr_new = attr;
718e3744 8689
d62a17ae 8690 if (red->redist_metric_flag)
8691 attr_new.med = red->redist_metric;
718e3744 8692
d62a17ae 8693 /* Apply route-map. */
8694 if (red->rmap.name) {
6006b807 8695 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8696 rmap_path.peer = bgp->peer_self;
8697 rmap_path.attr = &attr_new;
718e3744 8698
d62a17ae 8699 SET_FLAG(bgp->peer_self->rmap_type,
8700 PEER_RMAP_TYPE_REDISTRIBUTE);
8701
1782514f 8702 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8703
8704 bgp->peer_self->rmap_type = 0;
8705
8706 if (ret == RMAP_DENYMATCH) {
8707 /* Free uninterned attribute. */
8708 bgp_attr_flush(&attr_new);
8709
8710 /* Unintern original. */
8711 aspath_unintern(&attr.aspath);
8712 bgp_redistribute_delete(bgp, p, type, instance);
8713 return;
8714 }
8715 }
8716
637e5ba4 8717 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8718 bgp_attr_add_gshut_community(&attr_new);
8719
d62a17ae 8720 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8721 SAFI_UNICAST, p, NULL);
8722
8723 new_attr = bgp_attr_intern(&attr_new);
8724
9bcb3eef 8725 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8726 if (bpi->peer == bgp->peer_self
8727 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8728 break;
8729
40381db7 8730 if (bpi) {
d62a17ae 8731 /* Ensure the (source route) type is updated. */
40381db7
DS
8732 bpi->type = type;
8733 if (attrhash_cmp(bpi->attr, new_attr)
8734 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8735 bgp_attr_unintern(&new_attr);
8736 aspath_unintern(&attr.aspath);
9bcb3eef 8737 bgp_dest_unlock_node(bn);
d62a17ae 8738 return;
8739 } else {
8740 /* The attribute is changed. */
40381db7 8741 bgp_path_info_set_flag(bn, bpi,
18ee8310 8742 BGP_PATH_ATTR_CHANGED);
d62a17ae 8743
8744 /* Rewrite BGP route information. */
40381db7
DS
8745 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8746 bgp_path_info_restore(bn, bpi);
d62a17ae 8747 else
40381db7
DS
8748 bgp_aggregate_decrement(
8749 bgp, p, bpi, afi, SAFI_UNICAST);
8750 bgp_attr_unintern(&bpi->attr);
8751 bpi->attr = new_attr;
083ec940 8752 bpi->uptime = monotime(NULL);
d62a17ae 8753
8754 /* Process change. */
40381db7 8755 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8756 SAFI_UNICAST);
8757 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8758 bgp_dest_unlock_node(bn);
d62a17ae 8759 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8760
8761 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8762 || (bgp->inst_type
8763 == BGP_INSTANCE_TYPE_DEFAULT)) {
8764
8765 vpn_leak_from_vrf_update(
40381db7 8766 bgp_get_default(), bgp, bpi);
ddb5b488 8767 }
d62a17ae 8768 return;
8769 }
8770 }
8771
8772 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8773 bgp->peer_self, new_attr, bn);
1defdda8 8774 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8775
8776 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8777 bgp_path_info_add(bn, new);
9bcb3eef 8778 bgp_dest_unlock_node(bn);
be785e35 8779 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8780 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8781
8782 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8783 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8784
8785 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8786 }
d62a17ae 8787 }
8788
8789 /* Unintern original. */
8790 aspath_unintern(&attr.aspath);
718e3744 8791}
8792
d7c0a89a
QY
8793void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8794 unsigned short instance)
718e3744 8795{
d62a17ae 8796 afi_t afi;
9bcb3eef 8797 struct bgp_dest *dest;
40381db7 8798 struct bgp_path_info *pi;
d62a17ae 8799 struct bgp_redist *red;
718e3744 8800
d62a17ae 8801 afi = family2afi(p->family);
718e3744 8802
d62a17ae 8803 red = bgp_redist_lookup(bgp, afi, type, instance);
8804 if (red) {
9bcb3eef
DS
8805 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8806 SAFI_UNICAST, p, NULL);
d62a17ae 8807
9bcb3eef 8808 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8809 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8810 break;
8811
40381db7 8812 if (pi) {
ddb5b488
PZ
8813 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8814 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8815
8816 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8817 bgp, pi);
ddb5b488 8818 }
40381db7 8819 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8820 bgp_path_info_delete(dest, pi);
8821 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8822 }
9bcb3eef 8823 bgp_dest_unlock_node(dest);
d62a17ae 8824 }
8825}
8826
8827/* Withdraw specified route type's route. */
8828void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8829 unsigned short instance)
d62a17ae 8830{
9bcb3eef 8831 struct bgp_dest *dest;
40381db7 8832 struct bgp_path_info *pi;
d62a17ae 8833 struct bgp_table *table;
8834
8835 table = bgp->rib[afi][SAFI_UNICAST];
8836
9bcb3eef
DS
8837 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8838 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8839 if (pi->peer == bgp->peer_self && pi->type == type
8840 && pi->instance == instance)
d62a17ae 8841 break;
8842
40381db7 8843 if (pi) {
ddb5b488
PZ
8844 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8845 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8846
8847 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8848 bgp, pi);
ddb5b488 8849 }
9bcb3eef 8850 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8851 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8852 bgp_path_info_delete(dest, pi);
8853 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8854 }
718e3744 8855 }
718e3744 8856}
6b0655a2 8857
718e3744 8858/* Static function to display route. */
7d3cae70
DA
8859static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8860 struct vty *vty, json_object *json, bool wide)
718e3744 8861{
be054588 8862 int len = 0;
d62a17ae 8863 char buf[BUFSIZ];
718e3744 8864
d62a17ae 8865 if (p->family == AF_INET) {
c6462ff4 8866 if (!json) {
8228a9a7 8867 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8868 } else {
8869 json_object_string_add(json, "prefix",
8870 inet_ntop(p->family,
8871 &p->u.prefix, buf,
8872 BUFSIZ));
8873 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8874 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8875 json_object_int_add(json, "version", dest->version);
c6462ff4 8876 }
d62a17ae 8877 } else if (p->family == AF_ETHERNET) {
8228a9a7 8878 len = vty_out(vty, "%pFX", p);
b03b8898 8879 } else if (p->family == AF_EVPN) {
57f7feb6 8880 if (!json)
2dbe669b 8881 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8882 else
60466a63 8883 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8884 } else if (p->family == AF_FLOWSPEC) {
8885 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8886 json ?
8887 NLRI_STRING_FORMAT_JSON_SIMPLE :
8888 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8889 } else {
c6462ff4 8890 if (!json)
8228a9a7 8891 len = vty_out(vty, "%pFX", p);
50e05855
AD
8892 else {
8893 json_object_string_add(json, "prefix",
8894 inet_ntop(p->family,
8895 &p->u.prefix, buf,
8896 BUFSIZ));
8897 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8898 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8899 json_object_int_add(json, "version", dest->version);
37d4e0df 8900 }
9c92b5f7 8901 }
d62a17ae 8902
9c92b5f7 8903 if (!json) {
ae248832 8904 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8905 if (len < 1)
8906 vty_out(vty, "\n%*s", 20, " ");
8907 else
8908 vty_out(vty, "%*s", len, " ");
8909 }
718e3744 8910}
8911
d62a17ae 8912enum bgp_display_type {
8913 normal_list,
718e3744 8914};
8915
1d7260a1 8916const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8917{
8918 switch (reason) {
8919 case bgp_path_selection_none:
8920 return "Nothing to Select";
8921 case bgp_path_selection_first:
8922 return "First path received";
8923 case bgp_path_selection_evpn_sticky_mac:
8924 return "EVPN Sticky Mac";
8925 case bgp_path_selection_evpn_seq:
8926 return "EVPN sequence number";
8927 case bgp_path_selection_evpn_lower_ip:
8928 return "EVPN lower IP";
8929 case bgp_path_selection_evpn_local_path:
8930 return "EVPN local ES path";
8931 case bgp_path_selection_evpn_non_proxy:
8932 return "EVPN non proxy";
8933 case bgp_path_selection_weight:
8934 return "Weight";
8935 case bgp_path_selection_local_pref:
8936 return "Local Pref";
46dbf9d0
DA
8937 case bgp_path_selection_accept_own:
8938 return "Accept Own";
bbb46eb5
DA
8939 case bgp_path_selection_local_route:
8940 return "Local Route";
8941 case bgp_path_selection_confed_as_path:
8942 return "Confederation based AS Path";
8943 case bgp_path_selection_as_path:
8944 return "AS Path";
8945 case bgp_path_selection_origin:
8946 return "Origin";
8947 case bgp_path_selection_med:
8948 return "MED";
8949 case bgp_path_selection_peer:
8950 return "Peer Type";
8951 case bgp_path_selection_confed:
8952 return "Confed Peer Type";
8953 case bgp_path_selection_igp_metric:
8954 return "IGP Metric";
8955 case bgp_path_selection_older:
8956 return "Older Path";
8957 case bgp_path_selection_router_id:
8958 return "Router ID";
8959 case bgp_path_selection_cluster_length:
bcab253c 8960 return "Cluster length";
bbb46eb5
DA
8961 case bgp_path_selection_stale:
8962 return "Path Staleness";
8963 case bgp_path_selection_local_configured:
8964 return "Locally configured route";
8965 case bgp_path_selection_neighbor_ip:
8966 return "Neighbor IP";
8967 case bgp_path_selection_default:
8968 return "Nothing left to compare";
8969 }
8970 return "Invalid (internal error)";
8971}
8972
18ee8310 8973/* Print the short form route status for a bgp_path_info */
4b7e6066 8974static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8975 struct bgp_path_info *path,
82c298be 8976 const struct prefix *p,
d62a17ae 8977 json_object *json_path)
718e3744 8978{
82c298be
DA
8979 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8980
d62a17ae 8981 if (json_path) {
b05a1c8b 8982
d62a17ae 8983 /* Route status display. */
9b6d8fcf 8984 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8985 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8986
9b6d8fcf 8987 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8988 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8989
4056a5f6 8990 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8991 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8992
9b6d8fcf
DS
8993 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8994 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8995 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8996
d62a17ae 8997 /* Selected */
9b6d8fcf 8998 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8999 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9000
9b6d8fcf 9001 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9002 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9003
bbb46eb5 9004 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9005 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9006 json_object_string_add(json_path, "selectionReason",
9007 bgp_path_selection_reason2str(
9008 path->net->reason));
9009 }
b05a1c8b 9010
9b6d8fcf 9011 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9012 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9013
d62a17ae 9014 /* Internal route. */
9b6d8fcf
DS
9015 if ((path->peer->as)
9016 && (path->peer->as == path->peer->local_as))
d62a17ae 9017 json_object_string_add(json_path, "pathFrom",
9018 "internal");
9019 else
9020 json_object_string_add(json_path, "pathFrom",
9021 "external");
b05a1c8b 9022
d62a17ae 9023 return;
9024 }
b05a1c8b 9025
82c298be
DA
9026 /* RPKI validation state */
9027 rpki_state =
9028 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9029
9030 if (rpki_state == RPKI_VALID)
9031 vty_out(vty, "V");
9032 else if (rpki_state == RPKI_INVALID)
9033 vty_out(vty, "I");
9034 else if (rpki_state == RPKI_NOTFOUND)
9035 vty_out(vty, "N");
9036
d62a17ae 9037 /* Route status display. */
9b6d8fcf 9038 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9039 vty_out(vty, "R");
9b6d8fcf 9040 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9041 vty_out(vty, "S");
4056a5f6 9042 else if (bgp_path_suppressed(path))
d62a17ae 9043 vty_out(vty, "s");
9b6d8fcf
DS
9044 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9045 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9046 vty_out(vty, "*");
9047 else
9048 vty_out(vty, " ");
9049
9050 /* Selected */
9b6d8fcf 9051 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9052 vty_out(vty, "h");
9b6d8fcf 9053 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9054 vty_out(vty, "d");
9b6d8fcf 9055 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9056 vty_out(vty, ">");
9b6d8fcf 9057 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9058 vty_out(vty, "=");
9059 else
9060 vty_out(vty, " ");
718e3744 9061
d62a17ae 9062 /* Internal route. */
9b6d8fcf
DS
9063 if (path->peer && (path->peer->as)
9064 && (path->peer->as == path->peer->local_as))
d62a17ae 9065 vty_out(vty, "i");
9066 else
9067 vty_out(vty, " ");
b40d939b 9068}
9069
2ba93fd6
DA
9070static char *bgp_nexthop_hostname(struct peer *peer,
9071 struct bgp_nexthop_cache *bnc)
25b5da8d 9072{
892fedb6 9073 if (peer->hostname
aef999a2 9074 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9075 return peer->hostname;
9076 return NULL;
9077}
9078
b40d939b 9079/* called from terminal list command */
bd494ec5 9080void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9081 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9082 json_object *json_paths, bool wide)
d62a17ae 9083{
aef999a2 9084 int len;
515c2602 9085 struct attr *attr = path->attr;
d62a17ae 9086 json_object *json_path = NULL;
9087 json_object *json_nexthops = NULL;
9088 json_object *json_nexthop_global = NULL;
9089 json_object *json_nexthop_ll = NULL;
6f214dd3 9090 json_object *json_ext_community = NULL;
9df8b37c 9091 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9092 bool nexthop_self =
9b6d8fcf 9093 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9094 bool nexthop_othervrf = false;
43089216 9095 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9096 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9097 char *nexthop_hostname =
9098 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9099 char esi_buf[ESI_STR_LEN];
d62a17ae 9100
9101 if (json_paths)
9102 json_path = json_object_new_object();
9103
9104 /* short status lead text */
82c298be 9105 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9106
9107 if (!json_paths) {
9108 /* print prefix and mask */
9109 if (!display)
7d3cae70 9110 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9111 else
ae248832 9112 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9113 } else {
7d3cae70 9114 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9115 }
47fc97cc 9116
9df8b37c
PZ
9117 /*
9118 * If vrf id of nexthop is different from that of prefix,
9119 * set up printable string to append
9120 */
9b6d8fcf 9121 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9122 const char *self = "";
9123
9124 if (nexthop_self)
9125 self = "<";
9126
9127 nexthop_othervrf = true;
9b6d8fcf 9128 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9129
9b6d8fcf 9130 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9131 snprintf(vrf_id_str, sizeof(vrf_id_str),
9132 "@%s%s", VRFID_NONE_STR, self);
9133 else
9134 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9135 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9136
9b6d8fcf
DS
9137 if (path->extra->bgp_orig->inst_type
9138 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9139
9b6d8fcf 9140 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9141 } else {
9142 const char *self = "";
9143
9144 if (nexthop_self)
9145 self = "<";
9146
9147 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9148 }
9149
445c2480
DS
9150 /*
9151 * For ENCAP and EVPN routes, nexthop address family is not
9152 * neccessarily the same as the prefix address family.
9153 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9154 * EVPN routes are also exchanged with a MP nexthop. Currently,
9155 * this
9156 * is only IPv4, the value will be present in either
9157 * attr->nexthop or
9158 * attr->mp_nexthop_global_in
9159 */
9160 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9161 char buf[BUFSIZ];
9162 char nexthop[128];
9163 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9164
9165 switch (af) {
9166 case AF_INET:
772270f3
QY
9167 snprintf(nexthop, sizeof(nexthop), "%s",
9168 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
9169 BUFSIZ));
445c2480
DS
9170 break;
9171 case AF_INET6:
772270f3
QY
9172 snprintf(nexthop, sizeof(nexthop), "%s",
9173 inet_ntop(af, &attr->mp_nexthop_global, buf,
9174 BUFSIZ));
445c2480
DS
9175 break;
9176 default:
772270f3 9177 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9178 break;
d62a17ae 9179 }
d62a17ae 9180
445c2480
DS
9181 if (json_paths) {
9182 json_nexthop_global = json_object_new_object();
9183
515c2602
DA
9184 json_object_string_add(json_nexthop_global, "ip",
9185 nexthop);
9186
939a97f4 9187 if (path->peer->hostname)
515c2602
DA
9188 json_object_string_add(json_nexthop_global,
9189 "hostname",
939a97f4 9190 path->peer->hostname);
515c2602
DA
9191
9192 json_object_string_add(json_nexthop_global, "afi",
9193 (af == AF_INET) ? "ipv4"
9194 : "ipv6");
445c2480
DS
9195 json_object_boolean_true_add(json_nexthop_global,
9196 "used");
aef999a2
DA
9197 } else {
9198 if (nexthop_hostname)
9199 len = vty_out(vty, "%s(%s)%s", nexthop,
9200 nexthop_hostname, vrf_id_str);
9201 else
9202 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9203
ae248832 9204 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9205 if (len < 1)
9206 vty_out(vty, "\n%*s", 36, " ");
9207 else
9208 vty_out(vty, "%*s", len, " ");
9209 }
445c2480
DS
9210 } else if (safi == SAFI_EVPN) {
9211 if (json_paths) {
9212 json_nexthop_global = json_object_new_object();
9213
c949c771 9214 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9215 "%pI4",
9216 &attr->mp_nexthop_global_in);
515c2602 9217
939a97f4 9218 if (path->peer->hostname)
515c2602
DA
9219 json_object_string_add(json_nexthop_global,
9220 "hostname",
939a97f4 9221 path->peer->hostname);
515c2602 9222
a4d82a8a
PZ
9223 json_object_string_add(json_nexthop_global, "afi",
9224 "ipv4");
445c2480
DS
9225 json_object_boolean_true_add(json_nexthop_global,
9226 "used");
aef999a2
DA
9227 } else {
9228 if (nexthop_hostname)
7226bc40
TA
9229 len = vty_out(vty, "%pI4(%s)%s",
9230 &attr->mp_nexthop_global_in,
aef999a2
DA
9231 nexthop_hostname, vrf_id_str);
9232 else
7226bc40
TA
9233 len = vty_out(vty, "%pI4%s",
9234 &attr->mp_nexthop_global_in,
aef999a2
DA
9235 vrf_id_str);
9236
ae248832 9237 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9238 if (len < 1)
9239 vty_out(vty, "\n%*s", 36, " ");
9240 else
9241 vty_out(vty, "%*s", len, " ");
9242 }
d33fc23b 9243 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9244 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9245 if (json_paths) {
9246 json_nexthop_global = json_object_new_object();
515c2602 9247
026b914a
PG
9248 json_object_string_add(json_nexthop_global,
9249 "afi", "ipv4");
c949c771
DA
9250 json_object_string_addf(json_nexthop_global,
9251 "ip", "%pI4",
9252 &attr->nexthop);
515c2602 9253
939a97f4 9254 if (path->peer->hostname)
515c2602
DA
9255 json_object_string_add(
9256 json_nexthop_global, "hostname",
939a97f4 9257 path->peer->hostname);
515c2602 9258
50e05855
AD
9259 json_object_boolean_true_add(
9260 json_nexthop_global,
026b914a
PG
9261 "used");
9262 } else {
aef999a2
DA
9263 if (nexthop_hostname)
9264 len = vty_out(vty, "%pI4(%s)%s",
9265 &attr->nexthop,
9266 nexthop_hostname,
9267 vrf_id_str);
9268 else
9269 len = vty_out(vty, "%pI4%s",
9270 &attr->nexthop,
9271 vrf_id_str);
9272
ae248832 9273 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9274 if (len < 1)
9275 vty_out(vty, "\n%*s", 36, " ");
9276 else
9277 vty_out(vty, "%*s", len, " ");
026b914a
PG
9278 }
9279 }
7226bc40 9280 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9281 if (json_paths) {
9282 json_nexthop_global = json_object_new_object();
d62a17ae 9283
c949c771
DA
9284 json_object_string_addf(json_nexthop_global, "ip",
9285 "%pI4", &attr->nexthop);
515c2602 9286
939a97f4 9287 if (path->peer->hostname)
515c2602
DA
9288 json_object_string_add(json_nexthop_global,
9289 "hostname",
939a97f4 9290 path->peer->hostname);
445c2480 9291
a4d82a8a
PZ
9292 json_object_string_add(json_nexthop_global, "afi",
9293 "ipv4");
445c2480
DS
9294 json_object_boolean_true_add(json_nexthop_global,
9295 "used");
9296 } else {
aef999a2
DA
9297 if (nexthop_hostname)
9298 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9299 nexthop_hostname, vrf_id_str);
9300 else
9301 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9302 vrf_id_str);
9df8b37c 9303
ae248832 9304 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9305 if (len < 1)
9306 vty_out(vty, "\n%*s", 36, " ");
9307 else
9308 vty_out(vty, "%*s", len, " ");
d62a17ae 9309 }
445c2480 9310 }
b05a1c8b 9311
445c2480 9312 /* IPv6 Next Hop */
7226bc40 9313 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9314 if (json_paths) {
9315 json_nexthop_global = json_object_new_object();
c949c771
DA
9316 json_object_string_addf(json_nexthop_global, "ip",
9317 "%pI6",
9318 &attr->mp_nexthop_global);
515c2602 9319
939a97f4 9320 if (path->peer->hostname)
515c2602
DA
9321 json_object_string_add(json_nexthop_global,
9322 "hostname",
939a97f4 9323 path->peer->hostname);
515c2602 9324
a4d82a8a
PZ
9325 json_object_string_add(json_nexthop_global, "afi",
9326 "ipv6");
9327 json_object_string_add(json_nexthop_global, "scope",
9328 "global");
445c2480
DS
9329
9330 /* We display both LL & GL if both have been
9331 * received */
0606039c
DA
9332 if ((attr->mp_nexthop_len
9333 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9334 || (path->peer->conf_if)) {
a4d82a8a 9335 json_nexthop_ll = json_object_new_object();
c949c771
DA
9336 json_object_string_addf(
9337 json_nexthop_ll, "ip", "%pI6",
9338 &attr->mp_nexthop_local);
515c2602 9339
939a97f4 9340 if (path->peer->hostname)
515c2602
DA
9341 json_object_string_add(
9342 json_nexthop_ll, "hostname",
939a97f4 9343 path->peer->hostname);
515c2602 9344
a4d82a8a
PZ
9345 json_object_string_add(json_nexthop_ll, "afi",
9346 "ipv6");
9347 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9348 "link-local");
d62a17ae 9349
a4d82a8a
PZ
9350 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9351 &attr->mp_nexthop_local)
445c2480
DS
9352 != 0)
9353 && !attr->mp_nexthop_prefer_global)
d62a17ae 9354 json_object_boolean_true_add(
a4d82a8a 9355 json_nexthop_ll, "used");
445c2480
DS
9356 else
9357 json_object_boolean_true_add(
a4d82a8a 9358 json_nexthop_global, "used");
445c2480
DS
9359 } else
9360 json_object_boolean_true_add(
9361 json_nexthop_global, "used");
9362 } else {
9363 /* Display LL if LL/Global both in table unless
9364 * prefer-global is set */
0606039c
DA
9365 if (((attr->mp_nexthop_len
9366 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9367 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9368 || (path->peer->conf_if)) {
9369 if (path->peer->conf_if) {
a4d82a8a 9370 len = vty_out(vty, "%s",
9b6d8fcf 9371 path->peer->conf_if);
ae248832
MK
9372 /* len of IPv6 addr + max len of def
9373 * ifname */
9374 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9375
9376 if (len < 1)
a4d82a8a 9377 vty_out(vty, "\n%*s", 36, " ");
445c2480 9378 else
a4d82a8a 9379 vty_out(vty, "%*s", len, " ");
d62a17ae 9380 } else {
aef999a2
DA
9381 if (nexthop_hostname)
9382 len = vty_out(
9383 vty, "%pI6(%s)%s",
9384 &attr->mp_nexthop_local,
9385 nexthop_hostname,
9386 vrf_id_str);
9387 else
9388 len = vty_out(
9389 vty, "%pI6%s",
9390 &attr->mp_nexthop_local,
9391 vrf_id_str);
9392
ae248832 9393 len = wide ? (41 - len) : (16 - len);
d62a17ae 9394
9395 if (len < 1)
a4d82a8a 9396 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9397 else
a4d82a8a 9398 vty_out(vty, "%*s", len, " ");
d62a17ae 9399 }
445c2480 9400 } else {
aef999a2
DA
9401 if (nexthop_hostname)
9402 len = vty_out(vty, "%pI6(%s)%s",
9403 &attr->mp_nexthop_global,
9404 nexthop_hostname,
9405 vrf_id_str);
9406 else
9407 len = vty_out(vty, "%pI6%s",
9408 &attr->mp_nexthop_global,
9409 vrf_id_str);
9410
ae248832 9411 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9412
9413 if (len < 1)
9414 vty_out(vty, "\n%*s", 36, " ");
9415 else
9416 vty_out(vty, "%*s", len, " ");
d62a17ae 9417 }
9418 }
445c2480 9419 }
718e3744 9420
445c2480
DS
9421 /* MED/Metric */
9422 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9423 if (json_paths)
50e05855 9424 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9425 else if (wide)
9426 vty_out(vty, "%7u", attr->med);
0fbac0b4 9427 else
445c2480 9428 vty_out(vty, "%10u", attr->med);
ae248832
MK
9429 else if (!json_paths) {
9430 if (wide)
9431 vty_out(vty, "%*s", 7, " ");
9432 else
9433 vty_out(vty, "%*s", 10, " ");
9434 }
d62a17ae 9435
445c2480
DS
9436 /* Local Pref */
9437 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9438 if (json_paths)
50e05855 9439 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9440 attr->local_pref);
9441 else
445c2480
DS
9442 vty_out(vty, "%7u", attr->local_pref);
9443 else if (!json_paths)
9444 vty_out(vty, " ");
d62a17ae 9445
445c2480
DS
9446 if (json_paths)
9447 json_object_int_add(json_path, "weight", attr->weight);
9448 else
9449 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9450
47e12884
DA
9451 if (json_paths)
9452 json_object_string_addf(json_path, "peerId", "%pSU",
9453 &path->peer->su);
b05a1c8b 9454
445c2480
DS
9455 /* Print aspath */
9456 if (attr->aspath) {
0fbac0b4 9457 if (json_paths)
50e05855 9458 json_object_string_add(json_path, "path",
0fbac0b4
DA
9459 attr->aspath->str);
9460 else
445c2480 9461 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9462 }
f1aa5d8a 9463
445c2480
DS
9464 /* Print origin */
9465 if (json_paths)
a4d82a8a
PZ
9466 json_object_string_add(json_path, "origin",
9467 bgp_origin_long_str[attr->origin]);
445c2480
DS
9468 else
9469 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9470
9df8b37c 9471 if (json_paths) {
d071f237 9472 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9473 json_object_string_add(json_path, "esi",
9474 esi_to_str(&attr->esi,
9475 esi_buf, sizeof(esi_buf)));
9476 }
6f214dd3
CS
9477 if (safi == SAFI_EVPN &&
9478 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9479 json_ext_community = json_object_new_object();
b53e67a3
DA
9480 json_object_string_add(
9481 json_ext_community, "string",
9482 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9483 json_object_object_add(json_path,
9484 "extendedCommunity",
9485 json_ext_community);
9486 }
9487
9df8b37c
PZ
9488 if (nexthop_self)
9489 json_object_boolean_true_add(json_path,
9490 "announceNexthopSelf");
9491 if (nexthop_othervrf) {
9492 json_object_string_add(json_path, "nhVrfName",
9493 nexthop_vrfname);
9494
9495 json_object_int_add(json_path, "nhVrfId",
9496 ((nexthop_vrfid == VRF_UNKNOWN)
9497 ? -1
9498 : (int)nexthop_vrfid));
9499 }
9500 }
9501
d62a17ae 9502 if (json_paths) {
9503 if (json_nexthop_global || json_nexthop_ll) {
9504 json_nexthops = json_object_new_array();
f1aa5d8a 9505
d62a17ae 9506 if (json_nexthop_global)
9507 json_object_array_add(json_nexthops,
9508 json_nexthop_global);
f1aa5d8a 9509
d62a17ae 9510 if (json_nexthop_ll)
9511 json_object_array_add(json_nexthops,
9512 json_nexthop_ll);
f1aa5d8a 9513
d62a17ae 9514 json_object_object_add(json_path, "nexthops",
9515 json_nexthops);
9516 }
9517
9518 json_object_array_add(json_paths, json_path);
9519 } else {
9520 vty_out(vty, "\n");
6f214dd3 9521
b5e140c8 9522 if (safi == SAFI_EVPN) {
d071f237 9523 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9524 /* XXX - add these params to the json out */
b5e140c8 9525 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9526 vty_out(vty, "ESI:%s",
9527 esi_to_str(&attr->esi, esi_buf,
9528 sizeof(esi_buf)));
60605cbc 9529
229587fb 9530 vty_out(vty, "\n");
b5e140c8
AK
9531 }
9532 if (attr->flag &
9533 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9534 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9535 vty_out(vty, "%s\n",
9536 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9537 }
6f214dd3
CS
9538 }
9539
49e5a4a0 9540#ifdef ENABLE_BGP_VNC
d62a17ae 9541 /* prints an additional line, indented, with VNC info, if
9542 * present */
9543 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9544 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9545#endif
d62a17ae 9546 }
9547}
718e3744 9548
9549/* called from terminal list command */
7d3cae70
DA
9550void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9551 const struct prefix *p, struct attr *attr, safi_t safi,
9552 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9553{
9554 json_object *json_status = NULL;
9555 json_object *json_net = NULL;
aef999a2 9556 int len;
d62a17ae 9557 char buff[BUFSIZ];
dc387b0f 9558
d62a17ae 9559 /* Route status display. */
9560 if (use_json) {
9561 json_status = json_object_new_object();
9562 json_net = json_object_new_object();
9563 } else {
9564 vty_out(vty, "*");
9565 vty_out(vty, ">");
9566 vty_out(vty, " ");
9567 }
718e3744 9568
d62a17ae 9569 /* print prefix and mask */
50e05855 9570 if (use_json) {
dc387b0f
LK
9571 if (safi == SAFI_EVPN)
9572 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9573 else if (p->family == AF_INET || p->family == AF_INET6) {
9574 json_object_string_add(
9575 json_net, "addrPrefix",
9576 inet_ntop(p->family, &p->u.prefix, buff,
9577 BUFSIZ));
9578 json_object_int_add(json_net, "prefixLen",
9579 p->prefixlen);
67d7e256 9580 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9581 }
50e05855 9582 } else
7d3cae70 9583 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9584
9585 /* Print attribute */
9586 if (attr) {
9587 if (use_json) {
7226bc40
TA
9588 if (p->family == AF_INET &&
9589 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9590 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9591 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9592 json_object_string_addf(
9593 json_net, "nextHop", "%pI4",
9594 &attr->mp_nexthop_global_in);
d62a17ae 9595 else
c949c771
DA
9596 json_object_string_addf(
9597 json_net, "nextHop", "%pI4",
9598 &attr->nexthop);
7226bc40
TA
9599 } else if (p->family == AF_INET6 ||
9600 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9601 json_object_string_addf(
9602 json_net, "nextHopGlobal", "%pI6",
9603 &attr->mp_nexthop_global);
7226bc40
TA
9604 } else if (p->family == AF_EVPN &&
9605 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9606 json_object_string_addf(
9607 json_net, "nextHop", "%pI4",
9608 &attr->mp_nexthop_global_in);
23d0a753 9609 }
d62a17ae 9610
9611 if (attr->flag
9612 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9613 json_object_int_add(json_net, "metric",
9614 attr->med);
9615
0fbac0b4 9616 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9617 json_object_int_add(json_net, "locPrf",
0fbac0b4 9618 attr->local_pref);
d62a17ae 9619
9620 json_object_int_add(json_net, "weight", attr->weight);
9621
9622 /* Print aspath */
0fbac0b4 9623 if (attr->aspath)
50e05855 9624 json_object_string_add(json_net, "path",
0fbac0b4 9625 attr->aspath->str);
d62a17ae 9626
9627 /* Print origin */
9628 json_object_string_add(json_net, "bgpOriginCode",
9629 bgp_origin_str[attr->origin]);
9630 } else {
7226bc40
TA
9631 if (p->family == AF_INET &&
9632 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9633 safi == SAFI_EVPN ||
9634 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9635 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9636 || safi == SAFI_EVPN)
23d0a753
DA
9637 vty_out(vty, "%-16pI4",
9638 &attr->mp_nexthop_global_in);
ae248832 9639 else if (wide)
23d0a753 9640 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9641 else
23d0a753 9642 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9643 } else if (p->family == AF_INET6 ||
9644 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9645 char buf[BUFSIZ];
9646
9647 len = vty_out(
9648 vty, "%s",
9649 inet_ntop(AF_INET6,
9650 &attr->mp_nexthop_global, buf,
9651 BUFSIZ));
ae248832 9652 len = wide ? (41 - len) : (16 - len);
d62a17ae 9653 if (len < 1)
9654 vty_out(vty, "\n%*s", 36, " ");
9655 else
9656 vty_out(vty, "%*s", len, " ");
9657 }
9658 if (attr->flag
9659 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9660 if (wide)
9661 vty_out(vty, "%7u", attr->med);
9662 else
9663 vty_out(vty, "%10u", attr->med);
9664 else if (wide)
9665 vty_out(vty, " ");
d62a17ae 9666 else
9667 vty_out(vty, " ");
718e3744 9668
d62a17ae 9669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9670 vty_out(vty, "%7u", attr->local_pref);
9671 else
9672 vty_out(vty, " ");
9673
9674 vty_out(vty, "%7u ", attr->weight);
9675
9676 /* Print aspath */
9677 if (attr->aspath)
9678 aspath_print_vty(vty, "%s", attr->aspath, " ");
9679
9680 /* Print origin */
9681 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9682 }
9683 }
9684 if (use_json) {
9685 json_object_boolean_true_add(json_status, "*");
9686 json_object_boolean_true_add(json_status, ">");
9687 json_object_object_add(json_net, "appliedStatusSymbols",
9688 json_status);
511211bf 9689 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9690 } else
9691 vty_out(vty, "\n");
9692}
9693
bd494ec5 9694void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9695 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9696 json_object *json)
9697{
9698 json_object *json_out = NULL;
9699 struct attr *attr;
9700 mpls_label_t label = MPLS_INVALID_LABEL;
9701
9b6d8fcf 9702 if (!path->extra)
d62a17ae 9703 return;
9704
9705 if (json)
9706 json_out = json_object_new_object();
9707
9708 /* short status lead text */
82c298be 9709 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9710
9711 /* print prefix and mask */
9712 if (json == NULL) {
9713 if (!display)
7d3cae70 9714 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9715 else
9716 vty_out(vty, "%*s", 17, " ");
9717 }
9718
9719 /* Print attribute */
9b6d8fcf 9720 attr = path->attr;
7226bc40
TA
9721 if (((p->family == AF_INET) &&
9722 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9723 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9724 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9725 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9726 || safi == SAFI_EVPN) {
9727 if (json)
c949c771
DA
9728 json_object_string_addf(
9729 json_out, "mpNexthopGlobalIn", "%pI4",
9730 &attr->mp_nexthop_global_in);
05864da7 9731 else
23d0a753
DA
9732 vty_out(vty, "%-16pI4",
9733 &attr->mp_nexthop_global_in);
05864da7
DS
9734 } else {
9735 if (json)
c949c771
DA
9736 json_object_string_addf(json_out, "nexthop",
9737 "%pI4", &attr->nexthop);
05864da7 9738 else
23d0a753 9739 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9740 }
7226bc40
TA
9741 } else if (((p->family == AF_INET6) &&
9742 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9743 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9744 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9745 char buf_a[512];
9746
9747 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9748 if (json)
c949c771
DA
9749 json_object_string_addf(
9750 json_out, "mpNexthopGlobalIn", "%pI6",
9751 &attr->mp_nexthop_global);
05864da7
DS
9752 else
9753 vty_out(vty, "%s",
9754 inet_ntop(AF_INET6,
9755 &attr->mp_nexthop_global,
9756 buf_a, sizeof(buf_a)));
9757 } else if (attr->mp_nexthop_len
9758 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9759 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9760 &attr->mp_nexthop_global,
9761 &attr->mp_nexthop_local);
9762 if (json)
9763 json_object_string_add(json_out,
9764 "mpNexthopGlobalLocal",
9765 buf_a);
9766 else
9767 vty_out(vty, "%s", buf_a);
d62a17ae 9768 }
9769 }
9770
9b6d8fcf 9771 label = decode_label(&path->extra->label[0]);
d62a17ae 9772
9773 if (bgp_is_valid_label(&label)) {
9774 if (json) {
9775 json_object_int_add(json_out, "notag", label);
9776 json_object_array_add(json, json_out);
9777 } else {
9778 vty_out(vty, "notag/%d", label);
9779 vty_out(vty, "\n");
9780 }
700ddfed
PG
9781 } else if (!json)
9782 vty_out(vty, "\n");
d62a17ae 9783}
718e3744 9784
bd494ec5 9785void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9786 struct bgp_path_info *path, int display,
d62a17ae 9787 json_object *json_paths)
718e3744 9788{
d62a17ae 9789 struct attr *attr;
d62a17ae 9790 json_object *json_path = NULL;
14f51eba
LK
9791 json_object *json_nexthop = NULL;
9792 json_object *json_overlay = NULL;
856ca177 9793
9b6d8fcf 9794 if (!path->extra)
d62a17ae 9795 return;
718e3744 9796
14f51eba
LK
9797 if (json_paths) {
9798 json_path = json_object_new_object();
9799 json_overlay = json_object_new_object();
9800 json_nexthop = json_object_new_object();
9801 }
9802
d62a17ae 9803 /* short status lead text */
82c298be 9804 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9805
d62a17ae 9806 /* print prefix and mask */
9807 if (!display)
7d3cae70 9808 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9809 else
9810 vty_out(vty, "%*s", 17, " ");
9811
9812 /* Print attribute */
9b6d8fcf 9813 attr = path->attr;
05864da7 9814 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9815
05864da7
DS
9816 switch (af) {
9817 case AF_INET:
05864da7 9818 if (!json_path) {
db66cf7c 9819 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9820 } else {
db66cf7c
DA
9821 json_object_string_addf(json_nexthop, "ip", "%pI4",
9822 &attr->mp_nexthop_global_in);
14f51eba 9823
05864da7 9824 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9825
05864da7
DS
9826 json_object_object_add(json_path, "nexthop",
9827 json_nexthop);
9828 }
9829 break;
9830 case AF_INET6:
05864da7 9831 if (!json_path) {
db66cf7c
DA
9832 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9833 &attr->mp_nexthop_local);
05864da7 9834 } else {
db66cf7c
DA
9835 json_object_string_addf(json_nexthop, "ipv6Global",
9836 "%pI6",
9837 &attr->mp_nexthop_global);
14f51eba 9838
db66cf7c
DA
9839 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9840 "%pI6",
9841 &attr->mp_nexthop_local);
14f51eba 9842
05864da7 9843 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9844
05864da7
DS
9845 json_object_object_add(json_path, "nexthop",
9846 json_nexthop);
9847 }
9848 break;
9849 default:
9850 if (!json_path) {
9851 vty_out(vty, "?");
9852 } else {
9853 json_object_string_add(json_nexthop, "Error",
9854 "Unsupported address-family");
77a2f8e5
DA
9855 json_object_string_add(json_nexthop, "error",
9856 "Unsupported address-family");
d62a17ae 9857 }
05864da7 9858 }
988258b4 9859
6c924775
DS
9860 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9861
05864da7 9862 if (!json_path)
db66cf7c 9863 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9864 else
db66cf7c 9865 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9866
b53e67a3 9867 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9868 char *mac = NULL;
9869 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9870 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9871 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9872
9873 if (routermac)
9874 mac = ecom_mac2str((char *)routermac->val);
9875 if (mac) {
9876 if (!json_path) {
c4efd0f4 9877 vty_out(vty, "/%s", mac);
05864da7
DS
9878 } else {
9879 json_object_string_add(json_overlay, "rmac",
9880 mac);
988258b4 9881 }
05864da7 9882 XFREE(MTYPE_TMP, mac);
988258b4 9883 }
05864da7 9884 }
718e3744 9885
05864da7
DS
9886 if (!json_path) {
9887 vty_out(vty, "\n");
9888 } else {
9889 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9890
05864da7 9891 json_object_array_add(json_paths, json_path);
14f51eba 9892 }
d62a17ae 9893}
718e3744 9894
d62a17ae 9895/* dampening route */
5f040085
DS
9896static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9897 struct bgp_path_info *path, int display,
9898 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9899 json_object *json_paths)
d62a17ae 9900{
e5be8c1d 9901 struct attr *attr = path->attr;
d62a17ae 9902 int len;
9903 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9904 json_object *json_path = NULL;
9905
9906 if (use_json)
9907 json_path = json_object_new_object();
d62a17ae 9908
9909 /* short status lead text */
e5be8c1d 9910 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9911
9912 /* print prefix and mask */
9913 if (!use_json) {
9914 if (!display)
7d3cae70 9915 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9916 else
9917 vty_out(vty, "%*s", 17, " ");
d62a17ae 9918
e5be8c1d
DA
9919 len = vty_out(vty, "%s", path->peer->host);
9920 len = 17 - len;
9921
9922 if (len < 1)
d62a17ae 9923 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9924 else
9925 vty_out(vty, "%*s", len, " ");
d62a17ae 9926
9b6d8fcf
DS
9927 vty_out(vty, "%s ",
9928 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9929 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9930 use_json, NULL));
d62a17ae 9931
e5be8c1d 9932 if (attr->aspath)
05864da7 9933 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9934
05864da7
DS
9935 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9936
d62a17ae 9937 vty_out(vty, "\n");
e5be8c1d
DA
9938 } else {
9939 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9940 safi, use_json, json_path);
9941
9942 if (attr->aspath)
9943 json_object_string_add(json_path, "asPath",
9944 attr->aspath->str);
9945
9946 json_object_string_add(json_path, "origin",
9947 bgp_origin_str[attr->origin]);
9948 json_object_string_add(json_path, "peerHost", path->peer->host);
9949
9950 json_object_array_add(json_paths, json_path);
9951 }
d62a17ae 9952}
718e3744 9953
d62a17ae 9954/* flap route */
5f040085
DS
9955static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9956 struct bgp_path_info *path, int display,
9957 afi_t afi, safi_t safi, bool use_json,
31258046 9958 json_object *json_paths)
784d3a42 9959{
31258046 9960 struct attr *attr = path->attr;
d62a17ae 9961 struct bgp_damp_info *bdi;
9962 char timebuf[BGP_UPTIME_LEN];
9963 int len;
31258046 9964 json_object *json_path = NULL;
784d3a42 9965
9b6d8fcf 9966 if (!path->extra)
d62a17ae 9967 return;
784d3a42 9968
31258046
DA
9969 if (use_json)
9970 json_path = json_object_new_object();
9971
9b6d8fcf 9972 bdi = path->extra->damp_info;
784d3a42 9973
d62a17ae 9974 /* short status lead text */
31258046 9975 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9976
d62a17ae 9977 if (!use_json) {
9978 if (!display)
7d3cae70 9979 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9980 else
9981 vty_out(vty, "%*s", 17, " ");
784d3a42 9982
31258046
DA
9983 len = vty_out(vty, "%s", path->peer->host);
9984 len = 16 - len;
9985 if (len < 1)
d62a17ae 9986 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9987 else
9988 vty_out(vty, "%*s", len, " ");
784d3a42 9989
31258046
DA
9990 len = vty_out(vty, "%d", bdi->flap);
9991 len = 5 - len;
9992 if (len < 1)
d62a17ae 9993 vty_out(vty, " ");
d62a17ae 9994 else
9995 vty_out(vty, "%*s", len, " ");
d62a17ae 9996
996c9314
LB
9997 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9998 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9999
31258046
DA
10000 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10001 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10002 vty_out(vty, "%s ",
9b6d8fcf 10003 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10004 BGP_UPTIME_LEN, afi,
31258046
DA
10005 safi, use_json, NULL));
10006 else
d62a17ae 10007 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10008
31258046 10009 if (attr->aspath)
05864da7 10010 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10011
05864da7
DS
10012 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10013
d62a17ae 10014 vty_out(vty, "\n");
31258046
DA
10015 } else {
10016 json_object_string_add(json_path, "peerHost", path->peer->host);
10017 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10018
10019 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10020 json_path);
10021
10022 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10023 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10024 bgp_damp_reuse_time_vty(vty, path, timebuf,
10025 BGP_UPTIME_LEN, afi, safi,
10026 use_json, json_path);
10027
10028 if (attr->aspath)
10029 json_object_string_add(json_path, "asPath",
10030 attr->aspath->str);
10031
10032 json_object_string_add(json_path, "origin",
10033 bgp_origin_str[attr->origin]);
10034
10035 json_object_array_add(json_paths, json_path);
10036 }
d62a17ae 10037}
10038
10039static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10040 int *first, const char *header,
10041 json_object *json_adv_to)
10042{
d62a17ae 10043 json_object *json_peer = NULL;
10044
10045 if (json_adv_to) {
10046 /* 'advertised-to' is a dictionary of peers we have advertised
10047 * this
10048 * prefix too. The key is the peer's IP or swpX, the value is
10049 * the
10050 * hostname if we know it and "" if not.
10051 */
10052 json_peer = json_object_new_object();
10053
10054 if (peer->hostname)
10055 json_object_string_add(json_peer, "hostname",
10056 peer->hostname);
10057
10058 if (peer->conf_if)
10059 json_object_object_add(json_adv_to, peer->conf_if,
10060 json_peer);
10061 else
47e12884
DA
10062 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10063 &peer->su);
d62a17ae 10064 } else {
10065 if (*first) {
10066 vty_out(vty, "%s", header);
10067 *first = 0;
10068 }
10069
10070 if (peer->hostname
892fedb6 10071 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10072 if (peer->conf_if)
10073 vty_out(vty, " %s(%s)", peer->hostname,
10074 peer->conf_if);
10075 else
47e12884
DA
10076 vty_out(vty, " %s(%pSU)", peer->hostname,
10077 &peer->su);
d62a17ae 10078 } else {
10079 if (peer->conf_if)
10080 vty_out(vty, " %s", peer->conf_if);
10081 else
47e12884 10082 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10083 }
10084 }
784d3a42
PG
10085}
10086
dcc68b5e
MS
10087static void route_vty_out_tx_ids(struct vty *vty,
10088 struct bgp_addpath_info_data *d)
10089{
10090 int i;
10091
10092 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10093 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10094 d->addpath_tx_id[i],
10095 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10096 }
10097}
10098
5e4d4c8a 10099static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10100 struct bgp_path_info *pi,
10101 struct attr *attr,
10102 json_object *json_path)
5e4d4c8a
AK
10103{
10104 char esi_buf[ESI_STR_LEN];
10105 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10106 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10107 ATTR_ES_PEER_ROUTER);
10108 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10109 ATTR_ES_PEER_ACTIVE);
10110 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10111 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10112 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10113 if (json_path) {
10114 json_object *json_es_info = NULL;
10115
10116 json_object_string_add(
10117 json_path, "esi",
10118 esi_buf);
10119 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10120 json_es_info = json_object_new_object();
10121 if (es_local)
10122 json_object_boolean_true_add(
10123 json_es_info, "localEs");
10124 if (peer_active)
10125 json_object_boolean_true_add(
10126 json_es_info, "peerActive");
10127 if (peer_proxy)
10128 json_object_boolean_true_add(
10129 json_es_info, "peerProxy");
10130 if (peer_router)
10131 json_object_boolean_true_add(
10132 json_es_info, "peerRouter");
10133 if (attr->mm_sync_seqnum)
10134 json_object_int_add(
10135 json_es_info, "peerSeq",
10136 attr->mm_sync_seqnum);
10137 json_object_object_add(
10138 json_path, "es_info",
10139 json_es_info);
10140 }
10141 } else {
10142 if (bgp_evpn_attr_is_sync(attr))
10143 vty_out(vty,
10144 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10145 esi_buf,
10146 es_local ? "local-es":"",
10147 peer_proxy ? "proxy " : "",
10148 peer_active ? "active ":"",
10149 peer_router ? "router ":"",
10150 attr->mm_sync_seqnum);
10151 else
10152 vty_out(vty, " ESI %s %s\n",
10153 esi_buf,
10154 es_local ? "local-es":"");
10155 }
10156}
10157
4933eaaf
DS
10158void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
10159 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
10160 enum rpki_states rpki_curr_state,
10161 json_object *json_paths)
d62a17ae 10162{
10163 char buf[INET6_ADDRSTRLEN];
10164 char buf1[BUFSIZ];
515c2602 10165 struct attr *attr = path->attr;
d62a17ae 10166 time_t tbuf;
10167 json_object *json_bestpath = NULL;
10168 json_object *json_cluster_list = NULL;
10169 json_object *json_cluster_list_list = NULL;
10170 json_object *json_ext_community = NULL;
10171 json_object *json_last_update = NULL;
7fd077aa 10172 json_object *json_pmsi = NULL;
d62a17ae 10173 json_object *json_nexthop_global = NULL;
10174 json_object *json_nexthop_ll = NULL;
10175 json_object *json_nexthops = NULL;
10176 json_object *json_path = NULL;
10177 json_object *json_peer = NULL;
10178 json_object *json_string = NULL;
10179 json_object *json_adv_to = NULL;
10180 int first = 0;
10181 struct listnode *node, *nnode;
10182 struct peer *peer;
be92fc9f 10183 bool addpath_capable;
d62a17ae 10184 int has_adj;
10185 unsigned int first_as;
1defdda8 10186 bool nexthop_self =
9b6d8fcf 10187 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10188 int i;
2ba93fd6
DA
10189 char *nexthop_hostname =
10190 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10191 uint32_t ttl = 0;
10192 uint32_t bos = 0;
10193 uint32_t exp = 0;
10194 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 10195
10196 if (json_paths) {
10197 json_path = json_object_new_object();
10198 json_peer = json_object_new_object();
10199 json_nexthop_global = json_object_new_object();
10200 }
10201
8304dabf
AD
10202 if (safi == SAFI_EVPN) {
10203 if (!json_paths)
10204 vty_out(vty, " Route %pRN", bn);
10205 }
10206
44c69747 10207 if (path->extra) {
b57ba6d2 10208 char tag_buf[30];
d62a17ae 10209
d62a17ae 10210 tag_buf[0] = '\0';
9b6d8fcf
DS
10211 if (path->extra && path->extra->num_labels) {
10212 bgp_evpn_label2str(path->extra->label,
10213 path->extra->num_labels, tag_buf,
a4d82a8a 10214 sizeof(tag_buf));
d62a17ae 10215 }
d7325ee7 10216 if (safi == SAFI_EVPN) {
44c69747 10217 if (!json_paths) {
44c69747
LK
10218 if (tag_buf[0] != '\0')
10219 vty_out(vty, " VNI %s", tag_buf);
44c69747 10220 } else {
77a2f8e5 10221 if (tag_buf[0]) {
44c69747
LK
10222 json_object_string_add(json_path, "VNI",
10223 tag_buf);
77a2f8e5
DA
10224 json_object_string_add(json_path, "vni",
10225 tag_buf);
10226 }
44c69747 10227 }
d7325ee7
DD
10228 }
10229
44c69747 10230 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10231 struct bgp_path_info *parent_ri;
9bcb3eef 10232 struct bgp_dest *dest, *pdest;
d62a17ae 10233
9b6d8fcf 10234 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10235 dest = parent_ri->net;
10236 if (dest && dest->pdest) {
10237 pdest = dest->pdest;
d7325ee7 10238 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10239 vty_out(vty,
c4f64ea9
DA
10240 " Imported from %pRD:%pFX, VNI %s",
10241 (struct prefix_rd *)
10242 bgp_dest_get_prefix(
10243 pdest),
2dbe669b
DA
10244 (struct prefix_evpn *)
10245 bgp_dest_get_prefix(
10246 dest),
10247 tag_buf);
58bff4d1
AK
10248 if (attr->es_flags & ATTR_ES_L3_NHG)
10249 vty_out(vty, ", L3NHG %s",
10250 (attr->es_flags
10251 & ATTR_ES_L3_NHG_ACTIVE)
10252 ? "active"
10253 : "inactive");
10254 vty_out(vty, "\n");
10255
d7325ee7 10256 } else
2dbe669b 10257 vty_out(vty,
c4f64ea9
DA
10258 " Imported from %pRD:%pFX\n",
10259 (struct prefix_rd *)
10260 bgp_dest_get_prefix(
10261 pdest),
2dbe669b
DA
10262 (struct prefix_evpn *)
10263 bgp_dest_get_prefix(
10264 dest));
d62a17ae 10265 }
10266 }
10267 }
d62a17ae 10268
8304dabf
AD
10269 if (safi == SAFI_EVPN
10270 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10271 char gwip_buf[INET6_ADDRSTRLEN];
10272
860e740b
IR
10273 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10274 sizeof(gwip_buf));
8304dabf
AD
10275
10276 if (json_paths)
10277 json_object_string_add(json_path, "gatewayIP",
10278 gwip_buf);
10279 else
10280 vty_out(vty, " Gateway IP %s", gwip_buf);
10281 }
10282
2bf9780b 10283 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10284 vty_out(vty, "\n");
10285
05864da7
DS
10286 /* Line1 display AS-path, Aggregator */
10287 if (attr->aspath) {
10288 if (json_paths) {
10289 if (!attr->aspath->json)
10290 aspath_str_update(attr->aspath, true);
10291 json_object_lock(attr->aspath->json);
10292 json_object_object_add(json_path, "aspath",
10293 attr->aspath->json);
10294 } else {
10295 if (attr->aspath->segments)
10296 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10297 else
05864da7 10298 vty_out(vty, " Local");
d62a17ae 10299 }
05864da7 10300 }
d62a17ae 10301
05864da7
DS
10302 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10303 if (json_paths)
10304 json_object_boolean_true_add(json_path, "removed");
10305 else
10306 vty_out(vty, ", (removed)");
10307 }
d62a17ae 10308
05864da7
DS
10309 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10310 if (json_paths)
10311 json_object_boolean_true_add(json_path, "stale");
10312 else
10313 vty_out(vty, ", (stale)");
10314 }
d62a17ae 10315
05864da7
DS
10316 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10317 if (json_paths) {
10318 json_object_int_add(json_path, "aggregatorAs",
10319 attr->aggregator_as);
c949c771
DA
10320 json_object_string_addf(json_path, "aggregatorId",
10321 "%pI4", &attr->aggregator_addr);
05864da7 10322 } else {
88d495a9
DA
10323 vty_out(vty, ", (aggregated by %u %pI4)",
10324 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10325 }
05864da7 10326 }
d62a17ae 10327
05864da7
DS
10328 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10329 PEER_FLAG_REFLECTOR_CLIENT)) {
10330 if (json_paths)
10331 json_object_boolean_true_add(json_path,
10332 "rxedFromRrClient");
10333 else
10334 vty_out(vty, ", (Received from a RR-client)");
10335 }
d62a17ae 10336
05864da7
DS
10337 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10338 PEER_FLAG_RSERVER_CLIENT)) {
10339 if (json_paths)
10340 json_object_boolean_true_add(json_path,
10341 "rxedFromRsClient");
10342 else
10343 vty_out(vty, ", (Received from a RS-client)");
10344 }
d62a17ae 10345
05864da7
DS
10346 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10347 if (json_paths)
10348 json_object_boolean_true_add(json_path,
10349 "dampeningHistoryEntry");
10350 else
10351 vty_out(vty, ", (history entry)");
10352 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10353 if (json_paths)
10354 json_object_boolean_true_add(json_path,
10355 "dampeningSuppressed");
10356 else
10357 vty_out(vty, ", (suppressed due to dampening)");
10358 }
d62a17ae 10359
05864da7
DS
10360 if (!json_paths)
10361 vty_out(vty, "\n");
d62a17ae 10362
05864da7
DS
10363 /* Line2 display Next-hop, Neighbor, Router-id */
10364 /* Display the nexthop */
9bcb3eef 10365 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10366
7226bc40
TA
10367 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10368 bn_p->family == AF_EVPN) &&
10369 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10370 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10371 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10372 || safi == SAFI_EVPN) {
515c2602 10373 if (json_paths) {
c949c771
DA
10374 json_object_string_addf(
10375 json_nexthop_global, "ip", "%pI4",
10376 &attr->mp_nexthop_global_in);
515c2602 10377
939a97f4 10378 if (path->peer->hostname)
515c2602
DA
10379 json_object_string_add(
10380 json_nexthop_global, "hostname",
939a97f4 10381 path->peer->hostname);
aef999a2
DA
10382 } else {
10383 if (nexthop_hostname)
10384 vty_out(vty, " %pI4(%s)",
10385 &attr->mp_nexthop_global_in,
10386 nexthop_hostname);
10387 else
10388 vty_out(vty, " %pI4",
10389 &attr->mp_nexthop_global_in);
10390 }
d62a17ae 10391 } else {
515c2602 10392 if (json_paths) {
c949c771
DA
10393 json_object_string_addf(json_nexthop_global,
10394 "ip", "%pI4",
10395 &attr->nexthop);
515c2602 10396
939a97f4 10397 if (path->peer->hostname)
515c2602
DA
10398 json_object_string_add(
10399 json_nexthop_global, "hostname",
939a97f4 10400 path->peer->hostname);
aef999a2
DA
10401 } else {
10402 if (nexthop_hostname)
10403 vty_out(vty, " %pI4(%s)",
10404 &attr->nexthop,
10405 nexthop_hostname);
10406 else
10407 vty_out(vty, " %pI4",
10408 &attr->nexthop);
10409 }
d62a17ae 10410 }
10411
05864da7
DS
10412 if (json_paths)
10413 json_object_string_add(json_nexthop_global, "afi",
10414 "ipv4");
10415 } else {
10416 if (json_paths) {
c949c771
DA
10417 json_object_string_addf(json_nexthop_global, "ip",
10418 "%pI6",
10419 &attr->mp_nexthop_global);
515c2602 10420
939a97f4 10421 if (path->peer->hostname)
515c2602
DA
10422 json_object_string_add(json_nexthop_global,
10423 "hostname",
939a97f4 10424 path->peer->hostname);
515c2602 10425
05864da7
DS
10426 json_object_string_add(json_nexthop_global, "afi",
10427 "ipv6");
10428 json_object_string_add(json_nexthop_global, "scope",
10429 "global");
10430 } else {
aef999a2
DA
10431 if (nexthop_hostname)
10432 vty_out(vty, " %pI6(%s)",
10433 &attr->mp_nexthop_global,
10434 nexthop_hostname);
10435 else
10436 vty_out(vty, " %pI6",
10437 &attr->mp_nexthop_global);
d62a17ae 10438 }
05864da7 10439 }
d62a17ae 10440
05864da7
DS
10441 /* Display the IGP cost or 'inaccessible' */
10442 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10443 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10444
10445 if (json_paths) {
05864da7
DS
10446 json_object_boolean_false_add(json_nexthop_global,
10447 "accessible");
95ba22d5
DA
10448 json_object_boolean_add(json_nexthop_global,
10449 "importCheckEnabled", import);
10450 } else {
10451 vty_out(vty, " (inaccessible%s)",
10452 import ? ", import-check enabled" : "");
10453 }
05864da7
DS
10454 } else {
10455 if (path->extra && path->extra->igpmetric) {
d62a17ae 10456 if (json_paths)
05864da7
DS
10457 json_object_int_add(json_nexthop_global,
10458 "metric",
10459 path->extra->igpmetric);
d62a17ae 10460 else
05864da7
DS
10461 vty_out(vty, " (metric %u)",
10462 path->extra->igpmetric);
d62a17ae 10463 }
10464
05864da7 10465 /* IGP cost is 0, display this only for json */
d62a17ae 10466 else {
d62a17ae 10467 if (json_paths)
05864da7
DS
10468 json_object_int_add(json_nexthop_global,
10469 "metric", 0);
d62a17ae 10470 }
d62a17ae 10471
05864da7
DS
10472 if (json_paths)
10473 json_object_boolean_true_add(json_nexthop_global,
10474 "accessible");
10475 }
d62a17ae 10476
05864da7
DS
10477 /* Display peer "from" output */
10478 /* This path was originated locally */
10479 if (path->peer == bgp->peer_self) {
d62a17ae 10480
7226bc40
TA
10481 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10482 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10483 if (json_paths)
05864da7
DS
10484 json_object_string_add(json_peer, "peerId",
10485 "0.0.0.0");
d62a17ae 10486 else
05864da7
DS
10487 vty_out(vty, " from 0.0.0.0 ");
10488 } else {
d62a17ae 10489 if (json_paths)
05864da7
DS
10490 json_object_string_add(json_peer, "peerId",
10491 "::");
d62a17ae 10492 else
05864da7 10493 vty_out(vty, " from :: ");
d62a17ae 10494 }
d62a17ae 10495
4e9a9863 10496 if (json_paths)
c949c771
DA
10497 json_object_string_addf(json_peer, "routerId", "%pI4",
10498 &bgp->router_id);
4e9a9863 10499 else
23d0a753 10500 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10501 }
d62a17ae 10502
05864da7
DS
10503 /* We RXed this path from one of our peers */
10504 else {
10505
10506 if (json_paths) {
47e12884
DA
10507 json_object_string_addf(json_peer, "peerId", "%pSU",
10508 &path->peer->su);
c949c771
DA
10509 json_object_string_addf(json_peer, "routerId", "%pI4",
10510 &path->peer->remote_id);
05864da7
DS
10511
10512 if (path->peer->hostname)
10513 json_object_string_add(json_peer, "hostname",
10514 path->peer->hostname);
10515
10516 if (path->peer->domainname)
10517 json_object_string_add(json_peer, "domainname",
10518 path->peer->domainname);
10519
10520 if (path->peer->conf_if)
10521 json_object_string_add(json_peer, "interface",
10522 path->peer->conf_if);
10523 } else {
10524 if (path->peer->conf_if) {
10525 if (path->peer->hostname
892fedb6
DA
10526 && CHECK_FLAG(path->peer->bgp->flags,
10527 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10528 vty_out(vty, " from %s(%s)",
10529 path->peer->hostname,
10530 path->peer->conf_if);
d62a17ae 10531 else
05864da7 10532 vty_out(vty, " from %s",
9b6d8fcf 10533 path->peer->conf_if);
d62a17ae 10534 } else {
05864da7 10535 if (path->peer->hostname
892fedb6
DA
10536 && CHECK_FLAG(path->peer->bgp->flags,
10537 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10538 vty_out(vty, " from %s(%s)",
10539 path->peer->hostname,
10540 path->peer->host);
d62a17ae 10541 else
47e12884
DA
10542 vty_out(vty, " from %pSU",
10543 &path->peer->su);
d62a17ae 10544 }
d62a17ae 10545
05864da7 10546 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10547 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10548 else
10549 vty_out(vty, " (%s)",
10550 inet_ntop(AF_INET,
10551 &path->peer->remote_id, buf1,
10552 sizeof(buf1)));
d62a17ae 10553 }
05864da7 10554 }
9df8b37c 10555
05864da7
DS
10556 /*
10557 * Note when vrfid of nexthop is different from that of prefix
10558 */
10559 if (path->extra && path->extra->bgp_orig) {
10560 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10561
05864da7
DS
10562 if (json_paths) {
10563 const char *vn;
9df8b37c 10564
05864da7
DS
10565 if (path->extra->bgp_orig->inst_type
10566 == BGP_INSTANCE_TYPE_DEFAULT)
10567 vn = VRF_DEFAULT_NAME;
10568 else
10569 vn = path->extra->bgp_orig->name;
9df8b37c 10570
05864da7 10571 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10572
05864da7
DS
10573 if (nexthop_vrfid == VRF_UNKNOWN) {
10574 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10575 } else {
05864da7
DS
10576 json_object_int_add(json_path, "nhVrfId",
10577 (int)nexthop_vrfid);
9df8b37c 10578 }
05864da7
DS
10579 } else {
10580 if (nexthop_vrfid == VRF_UNKNOWN)
10581 vty_out(vty, " vrf ?");
137147c6
DS
10582 else {
10583 struct vrf *vrf;
10584
10585 vrf = vrf_lookup_by_id(nexthop_vrfid);
10586 vty_out(vty, " vrf %s(%u)",
10587 VRF_LOGNAME(vrf), nexthop_vrfid);
10588 }
9df8b37c 10589 }
05864da7 10590 }
9df8b37c 10591
05864da7
DS
10592 if (nexthop_self) {
10593 if (json_paths) {
10594 json_object_boolean_true_add(json_path,
10595 "announceNexthopSelf");
10596 } else {
10597 vty_out(vty, " announce-nh-self");
9df8b37c 10598 }
05864da7 10599 }
9df8b37c 10600
05864da7
DS
10601 if (!json_paths)
10602 vty_out(vty, "\n");
d62a17ae 10603
05864da7
DS
10604 /* display the link-local nexthop */
10605 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10606 if (json_paths) {
10607 json_nexthop_ll = json_object_new_object();
c949c771
DA
10608 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10609 &attr->mp_nexthop_local);
515c2602 10610
939a97f4 10611 if (path->peer->hostname)
515c2602
DA
10612 json_object_string_add(json_nexthop_ll,
10613 "hostname",
939a97f4 10614 path->peer->hostname);
515c2602 10615
05864da7
DS
10616 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10617 json_object_string_add(json_nexthop_ll, "scope",
10618 "link-local");
d62a17ae 10619
05864da7
DS
10620 json_object_boolean_true_add(json_nexthop_ll,
10621 "accessible");
d62a17ae 10622
05864da7 10623 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10624 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10625 "used");
10626 else
10627 json_object_boolean_true_add(
10628 json_nexthop_global, "used");
10629 } else {
10630 vty_out(vty, " (%s) %s\n",
10631 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10632 buf, INET6_ADDRSTRLEN),
10633 attr->mp_nexthop_prefer_global
10634 ? "(prefer-global)"
10635 : "(used)");
d62a17ae 10636 }
05864da7
DS
10637 }
10638 /* If we do not have a link-local nexthop then we must flag the
10639 global as "used" */
10640 else {
10641 if (json_paths)
10642 json_object_boolean_true_add(json_nexthop_global,
10643 "used");
10644 }
d62a17ae 10645
b5e140c8 10646 if (safi == SAFI_EVPN &&
5e4d4c8a 10647 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10648 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10649 }
10650
05864da7
DS
10651 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10652 * Int/Ext/Local, Atomic, best */
10653 if (json_paths)
10654 json_object_string_add(json_path, "origin",
10655 bgp_origin_long_str[attr->origin]);
10656 else
10657 vty_out(vty, " Origin %s",
10658 bgp_origin_long_str[attr->origin]);
9df8b37c 10659
05864da7 10660 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10661 if (json_paths)
05864da7 10662 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10663 else
05864da7
DS
10664 vty_out(vty, ", metric %u", attr->med);
10665 }
9df8b37c 10666
05864da7
DS
10667 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10668 if (json_paths)
0fbac0b4 10669 json_object_int_add(json_path, "locPrf",
05864da7
DS
10670 attr->local_pref);
10671 else
10672 vty_out(vty, ", localpref %u", attr->local_pref);
10673 }
9df8b37c 10674
05864da7
DS
10675 if (attr->weight != 0) {
10676 if (json_paths)
10677 json_object_int_add(json_path, "weight", attr->weight);
10678 else
10679 vty_out(vty, ", weight %u", attr->weight);
10680 }
9df8b37c 10681
05864da7
DS
10682 if (attr->tag != 0) {
10683 if (json_paths)
10684 json_object_int_add(json_path, "tag", attr->tag);
10685 else
10686 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10687 }
9df8b37c 10688
05864da7
DS
10689 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10690 if (json_paths)
10691 json_object_boolean_false_add(json_path, "valid");
10692 else
10693 vty_out(vty, ", invalid");
10694 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10695 if (json_paths)
10696 json_object_boolean_true_add(json_path, "valid");
10697 else
10698 vty_out(vty, ", valid");
10699 }
9df8b37c 10700
7d3cae70
DA
10701 if (json_paths)
10702 json_object_int_add(json_path, "version", bn->version);
10703
05864da7
DS
10704 if (path->peer != bgp->peer_self) {
10705 if (path->peer->as == path->peer->local_as) {
10706 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10707 if (json_paths)
10708 json_object_string_add(
10709 json_peer, "type",
10710 "confed-internal");
d62a17ae 10711 else
05864da7 10712 vty_out(vty, ", confed-internal");
d62a17ae 10713 } else {
05864da7
DS
10714 if (json_paths)
10715 json_object_string_add(
10716 json_peer, "type", "internal");
10717 else
10718 vty_out(vty, ", internal");
9df8b37c 10719 }
05864da7
DS
10720 } else {
10721 if (bgp_confederation_peers_check(bgp,
10722 path->peer->as)) {
10723 if (json_paths)
10724 json_object_string_add(
10725 json_peer, "type",
10726 "confed-external");
d62a17ae 10727 else
05864da7 10728 vty_out(vty, ", confed-external");
d62a17ae 10729 } else {
05864da7
DS
10730 if (json_paths)
10731 json_object_string_add(
10732 json_peer, "type", "external");
10733 else
10734 vty_out(vty, ", external");
d62a17ae 10735 }
10736 }
05864da7
DS
10737 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10738 if (json_paths) {
10739 json_object_boolean_true_add(json_path, "aggregated");
10740 json_object_boolean_true_add(json_path, "local");
10741 } else {
10742 vty_out(vty, ", aggregated, local");
10743 }
10744 } else if (path->type != ZEBRA_ROUTE_BGP) {
10745 if (json_paths)
10746 json_object_boolean_true_add(json_path, "sourced");
10747 else
10748 vty_out(vty, ", sourced");
10749 } else {
10750 if (json_paths) {
10751 json_object_boolean_true_add(json_path, "sourced");
10752 json_object_boolean_true_add(json_path, "local");
10753 } else {
10754 vty_out(vty, ", sourced, local");
d62a17ae 10755 }
05864da7 10756 }
718e3744 10757
05864da7 10758 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10759 if (json_paths)
05864da7
DS
10760 json_object_boolean_true_add(json_path,
10761 "atomicAggregate");
d62a17ae 10762 else
05864da7
DS
10763 vty_out(vty, ", atomic-aggregate");
10764 }
d62a17ae 10765
d864dd9e
EB
10766 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10767 if (json_paths)
10768 json_object_int_add(json_path, "otc", attr->otc);
10769 else
10770 vty_out(vty, ", otc %u", attr->otc);
10771 }
10772
05864da7
DS
10773 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10774 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10775 && bgp_path_info_mpath_count(path))) {
10776 if (json_paths)
10777 json_object_boolean_true_add(json_path, "multipath");
10778 else
10779 vty_out(vty, ", multipath");
10780 }
50e05855 10781
05864da7
DS
10782 // Mark the bestpath(s)
10783 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10784 first_as = aspath_get_first_as(attr->aspath);
718e3744 10785
05864da7
DS
10786 if (json_paths) {
10787 if (!json_bestpath)
10788 json_bestpath = json_object_new_object();
10789 json_object_int_add(json_bestpath, "bestpathFromAs",
10790 first_as);
10791 } else {
10792 if (first_as)
10793 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10794 else
05864da7 10795 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10796 }
05864da7 10797 }
718e3744 10798
05864da7
DS
10799 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10800 if (json_paths) {
10801 if (!json_bestpath)
10802 json_bestpath = json_object_new_object();
10803 json_object_boolean_true_add(json_bestpath, "overall");
10804 json_object_string_add(
10805 json_bestpath, "selectionReason",
10806 bgp_path_selection_reason2str(bn->reason));
10807 } else {
10808 vty_out(vty, ", best");
10809 vty_out(vty, " (%s)",
10810 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10811 }
05864da7 10812 }
718e3744 10813
4027d19b 10814 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10815 if (json_paths)
10816 json_object_string_add(
10817 json_path, "rpkiValidationState",
4027d19b 10818 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10819 else
1d327209 10820 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10821 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10822 }
10823
05864da7
DS
10824 if (json_bestpath)
10825 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10826
05864da7
DS
10827 if (!json_paths)
10828 vty_out(vty, "\n");
10829
10830 /* Line 4 display Community */
29e72930 10831 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10832 if (json_paths) {
9a706b42
DA
10833 if (!bgp_attr_get_community(attr)->json)
10834 community_str(bgp_attr_get_community(attr),
c0945b78 10835 true, true);
9a706b42
DA
10836 json_object_lock(bgp_attr_get_community(attr)->json);
10837 json_object_object_add(
10838 json_path, "community",
10839 bgp_attr_get_community(attr)->json);
05864da7
DS
10840 } else {
10841 vty_out(vty, " Community: %s\n",
9a706b42 10842 bgp_attr_get_community(attr)->str);
d62a17ae 10843 }
05864da7 10844 }
718e3744 10845
05864da7
DS
10846 /* Line 5 display Extended-community */
10847 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10848 if (json_paths) {
10849 json_ext_community = json_object_new_object();
b53e67a3
DA
10850 json_object_string_add(
10851 json_ext_community, "string",
10852 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10853 json_object_object_add(json_path, "extendedCommunity",
10854 json_ext_community);
d62a17ae 10855 } else {
05864da7 10856 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10857 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10858 }
05864da7 10859 }
718e3744 10860
05864da7
DS
10861 /* Line 6 display Large community */
10862 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10863 if (json_paths) {
1bcf3a96
DA
10864 if (!bgp_attr_get_lcommunity(attr)->json)
10865 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10866 true, true);
1bcf3a96
DA
10867 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10868 json_object_object_add(
10869 json_path, "largeCommunity",
10870 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10871 } else {
10872 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10873 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10874 }
05864da7 10875 }
718e3744 10876
05864da7
DS
10877 /* Line 7 display Originator, Cluster-id */
10878 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10879 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10880 char buf[BUFSIZ] = {0};
10881
05864da7 10882 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10883 if (json_paths)
c949c771
DA
10884 json_object_string_addf(json_path,
10885 "originatorId", "%pI4",
10886 &attr->originator_id);
d62a17ae 10887 else
23d0a753
DA
10888 vty_out(vty, " Originator: %pI4",
10889 &attr->originator_id);
d62a17ae 10890 }
856ca177 10891
05864da7 10892 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10893 struct cluster_list *cluster =
10894 bgp_attr_get_cluster(attr);
05864da7 10895 int i;
d62a17ae 10896
10897 if (json_paths) {
05864da7
DS
10898 json_cluster_list = json_object_new_object();
10899 json_cluster_list_list =
10900 json_object_new_array();
10901
779fee93 10902 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10903 json_string = json_object_new_string(
779fee93
DS
10904 inet_ntop(AF_INET,
10905 &cluster->list[i],
10906 buf, sizeof(buf)));
05864da7
DS
10907 json_object_array_add(
10908 json_cluster_list_list,
10909 json_string);
10910 }
718e3744 10911
05864da7
DS
10912 /*
10913 * struct cluster_list does not have
10914 * "str" variable like aspath and community
10915 * do. Add this someday if someone asks
10916 * for it.
10917 * json_object_string_add(json_cluster_list,
779fee93 10918 * "string", cluster->str);
05864da7
DS
10919 */
10920 json_object_object_add(json_cluster_list,
10921 "list",
10922 json_cluster_list_list);
10923 json_object_object_add(json_path, "clusterList",
10924 json_cluster_list);
0dc8ee70 10925 } else {
05864da7
DS
10926 vty_out(vty, ", Cluster list: ");
10927
779fee93 10928 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10929 vty_out(vty, "%pI4 ",
779fee93 10930 &cluster->list[i]);
05864da7 10931 }
0dc8ee70 10932 }
d62a17ae 10933 }
718e3744 10934
d62a17ae 10935 if (!json_paths)
10936 vty_out(vty, "\n");
05864da7 10937 }
d62a17ae 10938
05864da7 10939 if (path->extra && path->extra->damp_info)
b4f7f45b 10940 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10941
05864da7
DS
10942 /* Remote Label */
10943 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10944 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10945 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10946 &bos);
d62a17ae 10947
05864da7
DS
10948 if (json_paths)
10949 json_object_int_add(json_path, "remoteLabel", label);
10950 else
10951 vty_out(vty, " Remote label: %d\n", label);
10952 }
d62a17ae 10953
e496b420
HS
10954 /* Remote SID */
10955 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10956 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10957 if (json_paths)
10958 json_object_string_add(json_path, "remoteSid", buf);
10959 else
10960 vty_out(vty, " Remote SID: %s\n", buf);
10961 }
10962
05864da7
DS
10963 /* Label Index */
10964 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10965 if (json_paths)
10966 json_object_int_add(json_path, "labelIndex",
10967 attr->label_index);
10968 else
10969 vty_out(vty, " Label Index: %d\n",
10970 attr->label_index);
10971 }
d62a17ae 10972
05864da7
DS
10973 /* Line 8 display Addpath IDs */
10974 if (path->addpath_rx_id
10975 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10976 if (json_paths) {
10977 json_object_int_add(json_path, "addpathRxId",
10978 path->addpath_rx_id);
d62a17ae 10979
05864da7
DS
10980 /* Keep backwards compatibility with the old API
10981 * by putting TX All's ID in the old field
10982 */
10983 json_object_int_add(
10984 json_path, "addpathTxId",
10985 path->tx_addpath
10986 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10987
05864da7
DS
10988 /* ... but create a specific field for each
10989 * strategy
10990 */
10991 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10992 json_object_int_add(
10993 json_path,
10994 bgp_addpath_names(i)->id_json_name,
10995 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10996 }
05864da7
DS
10997 } else {
10998 vty_out(vty, " AddPath ID: RX %u, ",
10999 path->addpath_rx_id);
d62a17ae 11000
05864da7 11001 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11002 }
05864da7 11003 }
520d5d76 11004
05864da7
DS
11005 /* If we used addpath to TX a non-bestpath we need to display
11006 * "Advertised to" on a path-by-path basis
11007 */
11008 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11009 first = 1;
dcc68b5e 11010
05864da7
DS
11011 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11012 addpath_capable =
11013 bgp_addpath_encode_tx(peer, afi, safi);
11014 has_adj = bgp_adj_out_lookup(
11015 peer, path->net,
11016 bgp_addpath_id_for_peer(peer, afi, safi,
11017 &path->tx_addpath));
11018
11019 if ((addpath_capable && has_adj)
11020 || (!addpath_capable && has_adj
11021 && CHECK_FLAG(path->flags,
11022 BGP_PATH_SELECTED))) {
11023 if (json_path && !json_adv_to)
11024 json_adv_to = json_object_new_object();
dcc68b5e 11025
05864da7
DS
11026 route_vty_out_advertised_to(
11027 vty, peer, &first,
11028 " Advertised to:", json_adv_to);
d62a17ae 11029 }
11030 }
718e3744 11031
05864da7
DS
11032 if (json_path) {
11033 if (json_adv_to) {
11034 json_object_object_add(
11035 json_path, "advertisedTo", json_adv_to);
d62a17ae 11036 }
05864da7
DS
11037 } else {
11038 if (!first) {
11039 vty_out(vty, "\n");
d62a17ae 11040 }
11041 }
05864da7 11042 }
b05a1c8b 11043
05864da7 11044 /* Line 9 display Uptime */
083ec940 11045 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11046 if (json_paths) {
11047 json_last_update = json_object_new_object();
11048 json_object_int_add(json_last_update, "epoch", tbuf);
11049 json_object_string_add(json_last_update, "string",
11050 ctime(&tbuf));
11051 json_object_object_add(json_path, "lastUpdate",
11052 json_last_update);
11053 } else
11054 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11055
05864da7
DS
11056 /* Line 10 display PMSI tunnel attribute, if present */
11057 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11058 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11059 bgp_attr_get_pmsi_tnl_type(attr),
11060 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11061
05864da7
DS
11062 if (json_paths) {
11063 json_pmsi = json_object_new_object();
11064 json_object_string_add(json_pmsi, "tunnelType", str);
11065 json_object_int_add(json_pmsi, "label",
11066 label2vni(&attr->label));
11067 json_object_object_add(json_path, "pmsi", json_pmsi);
11068 } else
11069 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11070 str, label2vni(&attr->label));
d62a17ae 11071 }
f1aa5d8a 11072
848e8cf6
DA
11073 if (path->peer->t_gr_restart &&
11074 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11075 unsigned long gr_remaining =
11076 thread_timer_remain_second(path->peer->t_gr_restart);
11077
11078 if (json_paths) {
11079 json_object_int_add(json_path,
11080 "gracefulRestartSecondsRemaining",
11081 gr_remaining);
11082 } else
11083 vty_out(vty,
11084 " Time until Graceful Restart stale route deleted: %lu\n",
11085 gr_remaining);
11086 }
11087
9a706b42
DA
11088 if (path->peer->t_llgr_stale[afi][safi] &&
11089 bgp_attr_get_community(attr) &&
11090 community_include(bgp_attr_get_community(attr),
11091 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11092 unsigned long llgr_remaining = thread_timer_remain_second(
11093 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11094
48ebba04
DA
11095 if (json_paths) {
11096 json_object_int_add(json_path, "llgrSecondsRemaining",
11097 llgr_remaining);
11098 } else
11099 vty_out(vty,
11100 " Time until Long-lived stale route deleted: %lu\n",
11101 llgr_remaining);
11102 }
11103
92269aa2
DS
11104 /* Output some debug about internal state of the dest flags */
11105 if (json_paths) {
11106 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11107 json_object_boolean_true_add(json_path, "processScheduled");
11108 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11109 json_object_boolean_true_add(json_path, "userCleared");
11110 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11111 json_object_boolean_true_add(json_path, "labelChanged");
11112 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11113 json_object_boolean_true_add(json_path, "registeredForLabel");
11114 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11115 json_object_boolean_true_add(json_path, "selectDefered");
11116 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11117 json_object_boolean_true_add(json_path, "fibInstalled");
11118 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11119 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11120
d62a17ae 11121 if (json_nexthop_global || json_nexthop_ll) {
11122 json_nexthops = json_object_new_array();
f1aa5d8a 11123
d62a17ae 11124 if (json_nexthop_global)
11125 json_object_array_add(json_nexthops,
11126 json_nexthop_global);
f1aa5d8a 11127
d62a17ae 11128 if (json_nexthop_ll)
11129 json_object_array_add(json_nexthops,
11130 json_nexthop_ll);
f1aa5d8a 11131
d62a17ae 11132 json_object_object_add(json_path, "nexthops",
11133 json_nexthops);
11134 }
11135
11136 json_object_object_add(json_path, "peer", json_peer);
11137 json_object_array_add(json_paths, json_path);
05864da7 11138 }
b366b518
BB
11139}
11140
96ade3ed 11141#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11142#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11143#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11144
a4d82a8a 11145static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11146 afi_t afi, safi_t safi, enum bgp_show_type type,
11147 bool use_json);
7f323236
DW
11148static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11149 const char *comstr, int exact, afi_t afi,
96c81f66 11150 safi_t safi, uint16_t show_flags);
d62a17ae 11151
1ae44dfc 11152static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11153 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11154 void *output_arg, const char *rd, int is_last,
96f3485c 11155 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11156 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11157 enum rpki_states rpki_target_state)
d62a17ae 11158{
40381db7 11159 struct bgp_path_info *pi;
9bcb3eef 11160 struct bgp_dest *dest;
2aad8c42
MS
11161 bool header = true;
11162 bool json_detail_header = false;
d62a17ae 11163 int display;
1ae44dfc
LB
11164 unsigned long output_count = 0;
11165 unsigned long total_count = 0;
d62a17ae 11166 struct prefix *p;
d62a17ae 11167 json_object *json_paths = NULL;
11168 int first = 1;
96f3485c
MK
11169 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11170 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11171 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11172
1ae44dfc 11173 if (output_cum && *output_cum != 0)
2aad8c42 11174 header = false;
1ae44dfc 11175
9386b588 11176 if (use_json && !*json_header_depth) {
96f3485c
MK
11177 if (all)
11178 *json_header_depth = 1;
11179 else {
11180 vty_out(vty, "{\n");
11181 *json_header_depth = 2;
11182 }
11183
d62a17ae 11184 vty_out(vty,
23d0a753
DA
11185 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11186 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11187 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11188 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11189 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11190 ? VRF_DEFAULT_NAME
11191 : bgp->name,
11192 table->version, &bgp->router_id,
01eced22 11193 bgp->default_local_pref, bgp->as);
9386b588 11194 if (rd) {
445c2480 11195 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11196 ++*json_header_depth;
11197 }
d62a17ae 11198 }
718e3744 11199
445c2480
DS
11200 if (use_json && rd) {
11201 vty_out(vty, " \"%s\" : { ", rd);
11202 }
11203
2aad8c42
MS
11204 /* Check for 'json detail', where we need header output once per dest */
11205 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11206 type != bgp_show_type_dampend_paths &&
11207 type != bgp_show_type_damp_neighbor &&
11208 type != bgp_show_type_flap_statistics &&
11209 type != bgp_show_type_flap_neighbor)
11210 json_detail_header = true;
11211
d62a17ae 11212 /* Start processing of routes. */
9bcb3eef
DS
11213 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11214 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11215 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11216 bool json_detail = json_detail_header;
b54892e0 11217
9bcb3eef 11218 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11219 if (pi == NULL)
98ce9a06 11220 continue;
d62a17ae 11221
98ce9a06 11222 display = 0;
98ce9a06
DS
11223 if (use_json)
11224 json_paths = json_object_new_array();
11225 else
11226 json_paths = NULL;
d62a17ae 11227
6f94b685 11228 for (; pi; pi = pi->next) {
9a706b42
DA
11229 struct community *picomm = NULL;
11230
11231 picomm = bgp_attr_get_community(pi->attr);
11232
98ce9a06 11233 total_count++;
1e2ce4f1 11234
7d3cae70
DA
11235 if (type == bgp_show_type_prefix_version) {
11236 uint32_t version =
11237 strtoul(output_arg, NULL, 10);
11238 if (dest->version < version)
11239 continue;
11240 }
11241
a70a28a5
DA
11242 if (type == bgp_show_type_community_alias) {
11243 char *alias = output_arg;
11244 char **communities;
11245 int num;
11246 bool found = false;
11247
9a706b42
DA
11248 if (picomm) {
11249 frrstr_split(picomm->str, " ",
11250 &communities, &num);
a70a28a5
DA
11251 for (int i = 0; i < num; i++) {
11252 const char *com2alias =
11253 bgp_community2alias(
11254 communities[i]);
cd9cc0e6
IR
11255 if (!found
11256 && strcmp(alias, com2alias)
11257 == 0)
a70a28a5 11258 found = true;
cd9cc0e6
IR
11259 XFREE(MTYPE_TMP,
11260 communities[i]);
a70a28a5 11261 }
cd9cc0e6 11262 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11263 }
11264
1bcf3a96
DA
11265 if (!found &&
11266 bgp_attr_get_lcommunity(pi->attr)) {
11267 frrstr_split(bgp_attr_get_lcommunity(
11268 pi->attr)
11269 ->str,
a70a28a5
DA
11270 " ", &communities, &num);
11271 for (int i = 0; i < num; i++) {
11272 const char *com2alias =
11273 bgp_community2alias(
11274 communities[i]);
cd9cc0e6
IR
11275 if (!found
11276 && strcmp(alias, com2alias)
11277 == 0)
a70a28a5 11278 found = true;
cd9cc0e6
IR
11279 XFREE(MTYPE_TMP,
11280 communities[i]);
a70a28a5 11281 }
cd9cc0e6 11282 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11283 }
11284
11285 if (!found)
11286 continue;
11287 }
11288
1e2ce4f1
DS
11289 if (type == bgp_show_type_rpki) {
11290 if (dest_p->family == AF_INET
11291 || dest_p->family == AF_INET6)
4027d19b 11292 rpki_curr_state = hook_call(
1e2ce4f1
DS
11293 bgp_rpki_prefix_status,
11294 pi->peer, pi->attr, dest_p);
4027d19b
DS
11295 if (rpki_target_state != RPKI_NOT_BEING_USED
11296 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11297 continue;
11298 }
11299
98ce9a06
DS
11300 if (type == bgp_show_type_flap_statistics
11301 || type == bgp_show_type_flap_neighbor
11302 || type == bgp_show_type_dampend_paths
11303 || type == bgp_show_type_damp_neighbor) {
40381db7 11304 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11305 continue;
11306 }
11307 if (type == bgp_show_type_regexp) {
11308 regex_t *regex = output_arg;
d62a17ae 11309
40381db7 11310 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11311 == REG_NOMATCH)
11312 continue;
11313 }
11314 if (type == bgp_show_type_prefix_list) {
11315 struct prefix_list *plist = output_arg;
d62a17ae 11316
9bcb3eef 11317 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11318 != PREFIX_PERMIT)
11319 continue;
11320 }
ed126382
DA
11321 if (type == bgp_show_type_access_list) {
11322 struct access_list *alist = output_arg;
11323
11324 if (access_list_apply(alist, dest_p) !=
11325 FILTER_PERMIT)
11326 continue;
11327 }
98ce9a06
DS
11328 if (type == bgp_show_type_filter_list) {
11329 struct as_list *as_list = output_arg;
d62a17ae 11330
40381db7 11331 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11332 != AS_FILTER_PERMIT)
11333 continue;
11334 }
11335 if (type == bgp_show_type_route_map) {
11336 struct route_map *rmap = output_arg;
9b6d8fcf 11337 struct bgp_path_info path;
636632c3
DA
11338 struct bgp_path_info_extra extra;
11339 struct attr dummy_attr = {};
b68885f9 11340 route_map_result_t ret;
d62a17ae 11341
6f4f49b2 11342 dummy_attr = *pi->attr;
d62a17ae 11343
636632c3
DA
11344 prep_for_rmap_apply(&path, &extra, dest, pi,
11345 pi->peer, &dummy_attr);
d62a17ae 11346
1782514f 11347 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11348 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11349 if (ret == RMAP_DENYMATCH)
11350 continue;
11351 }
11352 if (type == bgp_show_type_neighbor
11353 || type == bgp_show_type_flap_neighbor
11354 || type == bgp_show_type_damp_neighbor) {
11355 union sockunion *su = output_arg;
11356
40381db7
DS
11357 if (pi->peer == NULL
11358 || pi->peer->su_remote == NULL
11359 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11360 continue;
11361 }
11362 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11363 uint32_t destination;
d62a17ae 11364
9bcb3eef 11365 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11366 if (IN_CLASSC(destination)
9bcb3eef 11367 && dest_p->prefixlen == 24)
98ce9a06
DS
11368 continue;
11369 if (IN_CLASSB(destination)
9bcb3eef 11370 && dest_p->prefixlen == 16)
98ce9a06
DS
11371 continue;
11372 if (IN_CLASSA(destination)
9bcb3eef 11373 && dest_p->prefixlen == 8)
98ce9a06
DS
11374 continue;
11375 }
11376 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11377 p = output_arg;
9bcb3eef 11378 if (!prefix_match(p, dest_p))
98ce9a06
DS
11379 continue;
11380 }
11381 if (type == bgp_show_type_community_all) {
9a706b42 11382 if (!picomm)
98ce9a06
DS
11383 continue;
11384 }
11385 if (type == bgp_show_type_community) {
11386 struct community *com = output_arg;
d62a17ae 11387
9a706b42 11388 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11389 continue;
11390 }
11391 if (type == bgp_show_type_community_exact) {
11392 struct community *com = output_arg;
d62a17ae 11393
9a706b42 11394 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11395 continue;
11396 }
11397 if (type == bgp_show_type_community_list) {
11398 struct community_list *list = output_arg;
d62a17ae 11399
9a706b42 11400 if (!community_list_match(picomm, list))
98ce9a06
DS
11401 continue;
11402 }
a4d82a8a 11403 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11404 struct community_list *list = output_arg;
d62a17ae 11405
9a706b42 11406 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11407 continue;
11408 }
11409 if (type == bgp_show_type_lcommunity) {
11410 struct lcommunity *lcom = output_arg;
d62a17ae 11411
1bcf3a96
DA
11412 if (!bgp_attr_get_lcommunity(pi->attr) ||
11413 !lcommunity_match(
11414 bgp_attr_get_lcommunity(pi->attr),
11415 lcom))
98ce9a06
DS
11416 continue;
11417 }
36a206db 11418
11419 if (type == bgp_show_type_lcommunity_exact) {
11420 struct lcommunity *lcom = output_arg;
11421
1bcf3a96
DA
11422 if (!bgp_attr_get_lcommunity(pi->attr) ||
11423 !lcommunity_cmp(
11424 bgp_attr_get_lcommunity(pi->attr),
11425 lcom))
36a206db 11426 continue;
11427 }
98ce9a06
DS
11428 if (type == bgp_show_type_lcommunity_list) {
11429 struct community_list *list = output_arg;
d62a17ae 11430
1bcf3a96
DA
11431 if (!lcommunity_list_match(
11432 bgp_attr_get_lcommunity(pi->attr),
11433 list))
98ce9a06
DS
11434 continue;
11435 }
36a206db 11436 if (type
11437 == bgp_show_type_lcommunity_list_exact) {
11438 struct community_list *list = output_arg;
11439
11440 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11441 bgp_attr_get_lcommunity(pi->attr),
11442 list))
36a206db 11443 continue;
11444 }
98ce9a06 11445 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11446 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11447 continue;
11448 }
11449 if (type == bgp_show_type_dampend_paths
11450 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11451 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11452 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11453 continue;
11454 }
11455
11456 if (!use_json && header) {
23d0a753
DA
11457 vty_out(vty,
11458 "BGP table version is %" PRIu64
11459 ", local router ID is %pI4, vrf id ",
11460 table->version, &bgp->router_id);
9df8b37c
PZ
11461 if (bgp->vrf_id == VRF_UNKNOWN)
11462 vty_out(vty, "%s", VRFID_NONE_STR);
11463 else
11464 vty_out(vty, "%u", bgp->vrf_id);
11465 vty_out(vty, "\n");
01eced22
AD
11466 vty_out(vty, "Default local pref %u, ",
11467 bgp->default_local_pref);
11468 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11469 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11470 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11471 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11472 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11473 if (type == bgp_show_type_dampend_paths
11474 || type == bgp_show_type_damp_neighbor)
98ce9a06 11475 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11476 else if (type == bgp_show_type_flap_statistics
11477 || type == bgp_show_type_flap_neighbor)
98ce9a06 11478 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11479 else
ae248832
MK
11480 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11481 : BGP_SHOW_HEADER));
2aad8c42
MS
11482 header = false;
11483
11484 } else if (json_detail && json_paths != NULL) {
11485 const struct prefix_rd *prd;
11486 json_object *jtemp;
11487
11488 /* Use common detail header, for most types;
11489 * need a json 'object'.
11490 */
11491
11492 jtemp = json_object_new_object();
11493 prd = bgp_rd_from_dest(dest, safi);
11494
11495 route_vty_out_detail_header(
11496 vty, bgp, dest, prd, table->afi,
11497 safi, jtemp);
11498
11499 json_object_array_add(json_paths, jtemp);
11500
11501 json_detail = false;
d62a17ae 11502 }
2aad8c42 11503
98ce9a06
DS
11504 if (rd != NULL && !display && !output_count) {
11505 if (!use_json)
11506 vty_out(vty,
11507 "Route Distinguisher: %s\n",
11508 rd);
d62a17ae 11509 }
98ce9a06
DS
11510 if (type == bgp_show_type_dampend_paths
11511 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11512 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11513 AFI_IP, safi, use_json,
11514 json_paths);
98ce9a06
DS
11515 else if (type == bgp_show_type_flap_statistics
11516 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11517 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11518 AFI_IP, safi, use_json,
11519 json_paths);
f280c93b
DA
11520 else {
11521 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11522 route_vty_out_detail(
11523 vty, bgp, dest, pi,
11524 family2afi(dest_p->family),
11525 safi, RPKI_NOT_BEING_USED,
11526 json_paths);
11527 else
11528 route_vty_out(vty, dest_p, pi, display,
11529 safi, json_paths, wide);
11530 }
98ce9a06 11531 display++;
d62a17ae 11532 }
11533
98ce9a06
DS
11534 if (display) {
11535 output_count++;
11536 if (!use_json)
11537 continue;
11538
625d2931 11539 /* encode prefix */
9bcb3eef 11540 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11541 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11542
1840384b 11543
b54892e0
DS
11544 bgp_fs_nlri_get_string(
11545 (unsigned char *)
9bcb3eef
DS
11546 dest_p->u.prefix_flowspec.ptr,
11547 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11548 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11549 family2afi(dest_p->u
11550 .prefix_flowspec.family));
625d2931 11551 if (first)
b54892e0 11552 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11553 dest_p->u.prefix_flowspec
b54892e0 11554 .prefixlen);
625d2931 11555 else
b54892e0 11556 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11557 dest_p->u.prefix_flowspec
b54892e0 11558 .prefixlen);
625d2931 11559 } else {
625d2931 11560 if (first)
1b78780b 11561 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11562 else
1b78780b 11563 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11564 }
3757f964 11565 vty_json(vty, json_paths);
449feb8e 11566 json_paths = NULL;
98ce9a06 11567 first = 0;
1f83ed02
DS
11568 } else
11569 json_object_free(json_paths);
98ce9a06
DS
11570 }
11571
1ae44dfc
LB
11572 if (output_cum) {
11573 output_count += *output_cum;
11574 *output_cum = output_count;
11575 }
11576 if (total_cum) {
11577 total_count += *total_cum;
11578 *total_cum = total_count;
11579 }
d62a17ae 11580 if (use_json) {
9386b588 11581 if (rd) {
a4d82a8a 11582 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11583 }
11584 if (is_last) {
a4d82a8a
PZ
11585 unsigned long i;
11586 for (i = 0; i < *json_header_depth; ++i)
11587 vty_out(vty, " } ");
96f3485c
MK
11588 if (!all)
11589 vty_out(vty, "\n");
9386b588 11590 }
d62a17ae 11591 } else {
1ae44dfc
LB
11592 if (is_last) {
11593 /* No route is displayed */
11594 if (output_count == 0) {
11595 if (type == bgp_show_type_normal)
11596 vty_out(vty,
11597 "No BGP prefixes displayed, %ld exist\n",
11598 total_count);
11599 } else
d62a17ae 11600 vty_out(vty,
1ae44dfc
LB
11601 "\nDisplayed %ld routes and %ld total paths\n",
11602 output_count, total_count);
11603 }
d62a17ae 11604 }
718e3744 11605
d62a17ae 11606 return CMD_SUCCESS;
718e3744 11607}
11608
1ae44dfc
LB
11609int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11610 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11611 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11612{
9bcb3eef 11613 struct bgp_dest *dest, *next;
1ae44dfc
LB
11614 unsigned long output_cum = 0;
11615 unsigned long total_cum = 0;
9386b588 11616 unsigned long json_header_depth = 0;
67009e22 11617 struct bgp_table *itable;
0136788c 11618 bool show_msg;
96c81f66 11619 uint16_t show_flags = 0;
0136788c
LB
11620
11621 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11622
96f3485c
MK
11623 if (use_json)
11624 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11625
9bcb3eef
DS
11626 for (dest = bgp_table_top(table); dest; dest = next) {
11627 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11628
9bcb3eef
DS
11629 next = bgp_route_next(dest);
11630 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11631 continue;
67009e22 11632
9bcb3eef 11633 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11634 if (itable != NULL) {
1ae44dfc 11635 struct prefix_rd prd;
06b9f471 11636 char rd[RD_ADDRSTRLEN];
1ae44dfc 11637
9bcb3eef 11638 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11639 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11640 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11641 rd, next == NULL, &output_cum,
11642 &total_cum, &json_header_depth,
1e2ce4f1 11643 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11644 if (next == NULL)
11645 show_msg = false;
1ae44dfc
LB
11646 }
11647 }
0136788c
LB
11648 if (show_msg) {
11649 if (output_cum == 0)
11650 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11651 total_cum);
11652 else
11653 vty_out(vty,
11654 "\nDisplayed %ld routes and %ld total paths\n",
11655 output_cum, total_cum);
11656 }
1ae44dfc
LB
11657 return CMD_SUCCESS;
11658}
2aad8c42 11659
d62a17ae 11660static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11661 enum bgp_show_type type, void *output_arg,
96c81f66 11662 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11663{
d62a17ae 11664 struct bgp_table *table;
9386b588 11665 unsigned long json_header_depth = 0;
96f3485c 11666 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11667
d62a17ae 11668 if (bgp == NULL) {
11669 bgp = bgp_get_default();
11670 }
fee0f4c6 11671
d62a17ae 11672 if (bgp == NULL) {
11673 if (!use_json)
11674 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11675 else
11676 vty_out(vty, "{}\n");
d62a17ae 11677 return CMD_WARNING;
11678 }
4dd6177e 11679
cd8c2a27
MS
11680 /* Labeled-unicast routes live in the unicast table. */
11681 if (safi == SAFI_LABELED_UNICAST)
11682 safi = SAFI_UNICAST;
11683
1ae44dfc 11684 table = bgp->rib[afi][safi];
d62a17ae 11685 /* use MPLS and ENCAP specific shows until they are merged */
11686 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11687 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11688 output_arg, use_json);
d62a17ae 11689 }
dba3c1d3
PG
11690
11691 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11692 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11693 output_arg, use_json,
11694 1, NULL, NULL);
11695 }
fee0f4c6 11696
96f3485c 11697 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11698 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11699 rpki_target_state);
fee0f4c6 11700}
11701
d62a17ae 11702static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11703 safi_t safi, uint16_t show_flags)
f186de26 11704{
d62a17ae 11705 struct listnode *node, *nnode;
11706 struct bgp *bgp;
11707 int is_first = 1;
9f049418 11708 bool route_output = false;
96f3485c 11709 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11710
d62a17ae 11711 if (use_json)
11712 vty_out(vty, "{\n");
9f689658 11713
d62a17ae 11714 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11715 route_output = true;
d62a17ae 11716 if (use_json) {
11717 if (!is_first)
11718 vty_out(vty, ",\n");
11719 else
11720 is_first = 0;
11721
11722 vty_out(vty, "\"%s\":",
11723 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11724 ? VRF_DEFAULT_NAME
d62a17ae 11725 : bgp->name);
11726 } else {
11727 vty_out(vty, "\nInstance %s:\n",
11728 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11729 ? VRF_DEFAULT_NAME
d62a17ae 11730 : bgp->name);
11731 }
11732 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11733 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11734 }
9f689658 11735
d62a17ae 11736 if (use_json)
11737 vty_out(vty, "}\n");
9f049418
DS
11738 else if (!route_output)
11739 vty_out(vty, "%% BGP instance not found\n");
f186de26 11740}
11741
718e3744 11742/* Header of detailed BGP route information */
d62a17ae 11743void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11744 struct bgp_dest *dest,
11745 const struct prefix_rd *prd,
d62a17ae 11746 afi_t afi, safi_t safi, json_object *json)
11747{
40381db7 11748 struct bgp_path_info *pi;
b54892e0 11749 const struct prefix *p;
d62a17ae 11750 struct peer *peer;
11751 struct listnode *node, *nnode;
06b9f471 11752 char buf1[RD_ADDRSTRLEN];
d62a17ae 11753 int count = 0;
11754 int best = 0;
11755 int suppress = 0;
c5f1e1b2
C
11756 int accept_own = 0;
11757 int route_filter_translated_v4 = 0;
11758 int route_filter_v4 = 0;
11759 int route_filter_translated_v6 = 0;
11760 int route_filter_v6 = 0;
11761 int llgr_stale = 0;
11762 int no_llgr = 0;
11763 int accept_own_nexthop = 0;
11764 int blackhole = 0;
d62a17ae 11765 int no_export = 0;
11766 int no_advertise = 0;
11767 int local_as = 0;
c5f1e1b2 11768 int no_peer = 0;
d62a17ae 11769 int first = 1;
11770 int has_valid_label = 0;
11771 mpls_label_t label = 0;
11772 json_object *json_adv_to = NULL;
67f67ba4
DA
11773 uint32_t ttl = 0;
11774 uint32_t bos = 0;
11775 uint32_t exp = 0;
9bedbb1e 11776
67f67ba4 11777 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11778
67f67ba4
DA
11779 p = bgp_dest_get_prefix(dest);
11780 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11781
44c69747 11782 if (safi == SAFI_EVPN) {
44c69747 11783 if (!json) {
2dbe669b 11784 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11785 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11786 : "",
2dbe669b 11787 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11788 } else {
11789 json_object_string_add(json, "rd",
11790 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11791 "");
11792 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11793 }
11794 } else {
11795 if (!json) {
9119ef3a
DA
11796 vty_out(vty,
11797 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11798 "\n",
d62a17ae 11799 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11800 ? prefix_rd2str(prd, buf1,
11801 sizeof(buf1))
11802 : ""),
9119ef3a
DA
11803 safi == SAFI_MPLS_VPN ? ":" : "", p,
11804 dest->version);
cd1964ff 11805
9119ef3a 11806 } else {
67d7e256 11807 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11808 json_object_int_add(json, "version", dest->version);
11809
11810 }
44c69747
LK
11811 }
11812
11813 if (has_valid_label) {
11814 if (json)
11815 json_object_int_add(json, "localLabel", label);
11816 else
d62a17ae 11817 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11818 }
11819
11820 if (!json)
d62a17ae 11821 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11822 vty_out(vty, "not allocated\n");
718e3744 11823
9bcb3eef 11824 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11825 struct community *picomm = NULL;
11826
11827 picomm = bgp_attr_get_community(pi->attr);
11828
d62a17ae 11829 count++;
40381db7 11830 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11831 best = count;
4056a5f6 11832 if (bgp_path_suppressed(pi))
d62a17ae 11833 suppress = 1;
cee9c031 11834
9a706b42 11835 if (!picomm)
cee9c031
QY
11836 continue;
11837
11838 no_advertise += community_include(
9a706b42
DA
11839 picomm, COMMUNITY_NO_ADVERTISE);
11840 no_export +=
11841 community_include(picomm, COMMUNITY_NO_EXPORT);
11842 local_as +=
11843 community_include(picomm, COMMUNITY_LOCAL_AS);
11844 accept_own +=
11845 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11846 route_filter_translated_v4 += community_include(
9a706b42 11847 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11848 route_filter_translated_v6 += community_include(
9a706b42 11849 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11850 route_filter_v4 += community_include(
9a706b42 11851 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11852 route_filter_v6 += community_include(
9a706b42
DA
11853 picomm, COMMUNITY_ROUTE_FILTER_v6);
11854 llgr_stale +=
11855 community_include(picomm, COMMUNITY_LLGR_STALE);
11856 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11857 accept_own_nexthop += community_include(
11858 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11859 blackhole +=
11860 community_include(picomm, COMMUNITY_BLACKHOLE);
11861 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11862 }
718e3744 11863 }
718e3744 11864
d62a17ae 11865 if (!json) {
11866 vty_out(vty, "Paths: (%d available", count);
11867 if (best) {
11868 vty_out(vty, ", best #%d", best);
b84060bb
PG
11869 if (safi == SAFI_UNICAST) {
11870 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11871 vty_out(vty, ", table %s",
11872 VRF_DEFAULT_NAME);
11873 else
11874 vty_out(vty, ", vrf %s",
11875 bgp->name);
11876 }
d62a17ae 11877 } else
11878 vty_out(vty, ", no best path");
11879
c5f1e1b2
C
11880 if (accept_own)
11881 vty_out(vty,
11882 ", accept own local route exported and imported in different VRF");
11883 else if (route_filter_translated_v4)
11884 vty_out(vty,
11885 ", mark translated RTs for VPNv4 route filtering");
11886 else if (route_filter_v4)
11887 vty_out(vty,
11888 ", attach RT as-is for VPNv4 route filtering");
11889 else if (route_filter_translated_v6)
11890 vty_out(vty,
11891 ", mark translated RTs for VPNv6 route filtering");
11892 else if (route_filter_v6)
11893 vty_out(vty,
11894 ", attach RT as-is for VPNv6 route filtering");
11895 else if (llgr_stale)
11896 vty_out(vty,
1479ed2f 11897 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11898 else if (no_llgr)
11899 vty_out(vty,
11900 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11901 else if (accept_own_nexthop)
11902 vty_out(vty,
11903 ", accept local nexthop");
11904 else if (blackhole)
11905 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11906 else if (no_export)
11907 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11908 else if (no_advertise)
11909 vty_out(vty, ", not advertised to any peer");
d62a17ae 11910 else if (local_as)
11911 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11912 else if (no_peer)
11913 vty_out(vty,
11914 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11915
11916 if (suppress)
11917 vty_out(vty,
11918 ", Advertisements suppressed by an aggregate.");
11919 vty_out(vty, ")\n");
11920 }
718e3744 11921
d62a17ae 11922 /* If we are not using addpath then we can display Advertised to and
11923 * that will
11924 * show what peers we advertised the bestpath to. If we are using
11925 * addpath
11926 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11927 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11928 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11929 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11930 if (json && !json_adv_to)
11931 json_adv_to = json_object_new_object();
11932
11933 route_vty_out_advertised_to(
11934 vty, peer, &first,
11935 " Advertised to non peer-group peers:\n ",
11936 json_adv_to);
11937 }
11938 }
11939
11940 if (json) {
11941 if (json_adv_to) {
11942 json_object_object_add(json, "advertisedTo",
11943 json_adv_to);
11944 }
11945 } else {
11946 if (first)
11947 vty_out(vty, " Not advertised to any peer");
11948 vty_out(vty, "\n");
11949 }
11950 }
718e3744 11951}
11952
edfee30d 11953static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11954 struct bgp_dest *bgp_node, struct vty *vty,
11955 struct bgp *bgp, afi_t afi, safi_t safi,
11956 json_object *json, enum bgp_path_type pathtype,
4027d19b 11957 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11958{
11959 struct bgp_path_info *pi;
11960 int header = 1;
44c69747
LK
11961 json_object *json_header = NULL;
11962 json_object *json_paths = NULL;
4933eaaf 11963 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11964
9bcb3eef 11965 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11966 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11967
11968 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11969 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11970 pi->peer, pi->attr, p);
4933eaaf 11971
4027d19b
DS
11972 if (rpki_target_state != RPKI_NOT_BEING_USED
11973 && rpki_curr_state != rpki_target_state)
4933eaaf 11974 continue;
44c69747
LK
11975
11976 if (json && !json_paths) {
11977 /* Instantiate json_paths only if path is valid */
11978 json_paths = json_object_new_array();
c4f64ea9 11979 if (pfx_rd)
44c69747 11980 json_header = json_object_new_object();
c4f64ea9 11981 else
44c69747
LK
11982 json_header = json;
11983 }
11984
11985 if (header) {
11986 route_vty_out_detail_header(
11987 vty, bgp, bgp_node, pfx_rd,
11988 AFI_IP, safi, json_header);
11989 header = 0;
11990 }
11991 (*display)++;
11992
11993 if (pathtype == BGP_PATH_SHOW_ALL
11994 || (pathtype == BGP_PATH_SHOW_BESTPATH
11995 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11996 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11997 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11998 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11999 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 12000 safi, rpki_curr_state, json_paths);
44c69747
LK
12001 }
12002
12003 if (json && json_paths) {
12004 json_object_object_add(json_header, "paths", json_paths);
12005
12006 if (pfx_rd)
c4f64ea9
DA
12007 json_object_object_addf(json, json_header, "%pRD",
12008 pfx_rd);
44c69747
LK
12009 }
12010}
12011
2aad8c42
MS
12012/*
12013 * Return rd based on safi
12014 */
46dbf9d0
DA
12015const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12016 safi_t safi)
2aad8c42
MS
12017{
12018 switch (safi) {
12019 case SAFI_MPLS_VPN:
12020 case SAFI_ENCAP:
12021 case SAFI_EVPN:
12022 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12023 default:
12024 return NULL;
2aad8c42
MS
12025 }
12026}
12027
718e3744 12028/* Display specified route of BGP table. */
d62a17ae 12029static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12030 struct bgp_table *rib, const char *ip_str,
12031 afi_t afi, safi_t safi,
4027d19b 12032 enum rpki_states rpki_target_state,
d62a17ae 12033 struct prefix_rd *prd, int prefix_check,
9f049418 12034 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12035{
12036 int ret;
d62a17ae 12037 int display = 0;
12038 struct prefix match;
9bcb3eef
DS
12039 struct bgp_dest *dest;
12040 struct bgp_dest *rm;
d62a17ae 12041 struct bgp_table *table;
12042 json_object *json = NULL;
12043 json_object *json_paths = NULL;
12044
12045 /* Check IP address argument. */
12046 ret = str2prefix(ip_str, &match);
12047 if (!ret) {
12048 vty_out(vty, "address is malformed\n");
12049 return CMD_WARNING;
12050 }
718e3744 12051
d62a17ae 12052 match.family = afi2family(afi);
b05a1c8b 12053
44c69747 12054 if (use_json)
d62a17ae 12055 json = json_object_new_object();
718e3744 12056
44c69747 12057 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12058 for (dest = bgp_table_top(rib); dest;
12059 dest = bgp_route_next(dest)) {
12060 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12061
9bcb3eef 12062 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12063 continue;
9bcb3eef 12064 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12065 if (!table)
ea47320b 12066 continue;
d62a17ae 12067
4953391b
DA
12068 rm = bgp_node_match(table, &match);
12069 if (rm == NULL)
ea47320b 12070 continue;
d62a17ae 12071
9bcb3eef 12072 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12073 if (prefix_check
b54892e0 12074 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12075 bgp_dest_unlock_node(rm);
ea47320b
DL
12076 continue;
12077 }
d62a17ae 12078
9bcb3eef 12079 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12080 bgp, afi, safi, json, pathtype,
4027d19b 12081 &display, rpki_target_state);
44c69747 12082
9bcb3eef 12083 bgp_dest_unlock_node(rm);
44c69747
LK
12084 }
12085 } else if (safi == SAFI_EVPN) {
9bcb3eef 12086 struct bgp_dest *longest_pfx;
cded3b72 12087 bool is_exact_pfxlen_match = false;
44c69747 12088
9bcb3eef
DS
12089 for (dest = bgp_table_top(rib); dest;
12090 dest = bgp_route_next(dest)) {
12091 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12092
9bcb3eef 12093 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12094 continue;
9bcb3eef 12095 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12096 if (!table)
12097 continue;
12098
12099 longest_pfx = NULL;
cded3b72 12100 is_exact_pfxlen_match = false;
44c69747
LK
12101 /*
12102 * Search through all the prefixes for a match. The
12103 * pfx's are enumerated in ascending order of pfxlens.
12104 * So, the last pfx match is the longest match. Set
12105 * is_exact_pfxlen_match when we get exact pfxlen match
12106 */
12107 for (rm = bgp_table_top(table); rm;
12108 rm = bgp_route_next(rm)) {
b54892e0 12109 const struct prefix *rm_p =
9bcb3eef 12110 bgp_dest_get_prefix(rm);
44c69747
LK
12111 /*
12112 * Get prefixlen of the ip-prefix within type5
12113 * evpn route
12114 */
b54892e0
DS
12115 if (evpn_type5_prefix_match(rm_p, &match)
12116 && rm->info) {
44c69747
LK
12117 longest_pfx = rm;
12118 int type5_pfxlen =
b54892e0
DS
12119 bgp_evpn_get_type5_prefixlen(
12120 rm_p);
44c69747 12121 if (type5_pfxlen == match.prefixlen) {
cded3b72 12122 is_exact_pfxlen_match = true;
9bcb3eef 12123 bgp_dest_unlock_node(rm);
44c69747
LK
12124 break;
12125 }
d62a17ae 12126 }
12127 }
ea47320b 12128
44c69747
LK
12129 if (!longest_pfx)
12130 continue;
12131
12132 if (prefix_check && !is_exact_pfxlen_match)
12133 continue;
12134
12135 rm = longest_pfx;
9bcb3eef 12136 bgp_dest_lock_node(rm);
44c69747 12137
9bcb3eef 12138 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12139 bgp, afi, safi, json, pathtype,
4027d19b 12140 &display, rpki_target_state);
44c69747 12141
9bcb3eef 12142 bgp_dest_unlock_node(rm);
d62a17ae 12143 }
98a9dbc7 12144 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12145 if (use_json)
12146 json_paths = json_object_new_array();
12147
63a0b7a9
PG
12148 display = bgp_flowspec_display_match_per_ip(afi, rib,
12149 &match, prefix_check,
12150 vty,
12151 use_json,
12152 json_paths);
d5f20468
SP
12153 if (use_json) {
12154 if (display)
12155 json_object_object_add(json, "paths",
12156 json_paths);
12157 else
12158 json_object_free(json_paths);
12159 }
d62a17ae 12160 } else {
4953391b
DA
12161 dest = bgp_node_match(rib, &match);
12162 if (dest != NULL) {
9bcb3eef 12163 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12164 if (!prefix_check
9bcb3eef
DS
12165 || dest_p->prefixlen == match.prefixlen) {
12166 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12167 safi, json, pathtype,
4027d19b 12168 &display, rpki_target_state);
d62a17ae 12169 }
12170
9bcb3eef 12171 bgp_dest_unlock_node(dest);
d62a17ae 12172 }
12173 }
e5eee9af 12174
d62a17ae 12175 if (use_json) {
75eeda93 12176 vty_json(vty, json);
d62a17ae 12177 } else {
12178 if (!display) {
12179 vty_out(vty, "%% Network not in table\n");
12180 return CMD_WARNING;
12181 }
12182 }
b05a1c8b 12183
d62a17ae 12184 return CMD_SUCCESS;
718e3744 12185}
12186
fee0f4c6 12187/* Display specified route of Main RIB */
d62a17ae 12188static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12189 afi_t afi, safi_t safi, struct prefix_rd *prd,
12190 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12191 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12192{
9b86009a 12193 if (!bgp) {
d62a17ae 12194 bgp = bgp_get_default();
9b86009a
RW
12195 if (!bgp) {
12196 if (!use_json)
12197 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12198 else
12199 vty_out(vty, "{}\n");
9b86009a
RW
12200 return CMD_WARNING;
12201 }
12202 }
d62a17ae 12203
12204 /* labeled-unicast routes live in the unicast table */
12205 if (safi == SAFI_LABELED_UNICAST)
12206 safi = SAFI_UNICAST;
12207
12208 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12209 afi, safi, rpki_target_state, prd,
8aa22bbb 12210 prefix_check, pathtype, use_json);
d62a17ae 12211}
12212
12213static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12214 struct cmd_token **argv, bool exact, afi_t afi,
12215 safi_t safi, bool uj)
d62a17ae 12216{
12217 struct lcommunity *lcom;
12218 struct buffer *b;
12219 int i;
12220 char *str;
12221 int first = 0;
96c81f66 12222 uint16_t show_flags = 0;
4f28b2b5 12223 int ret;
96f3485c
MK
12224
12225 if (uj)
12226 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12227
12228 b = buffer_new(1024);
12229 for (i = 0; i < argc; i++) {
12230 if (first)
12231 buffer_putc(b, ' ');
12232 else {
12233 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12234 first = 1;
12235 buffer_putstr(b, argv[i]->arg);
12236 }
12237 }
12238 }
12239 buffer_putc(b, '\0');
57d187bc 12240
d62a17ae 12241 str = buffer_getstr(b);
12242 buffer_free(b);
57d187bc 12243
d62a17ae 12244 lcom = lcommunity_str2com(str);
12245 XFREE(MTYPE_TMP, str);
12246 if (!lcom) {
12247 vty_out(vty, "%% Large-community malformed\n");
12248 return CMD_WARNING;
12249 }
57d187bc 12250
4f28b2b5 12251 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12252 (exact ? bgp_show_type_lcommunity_exact
12253 : bgp_show_type_lcommunity),
12254 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12255
12256 lcommunity_free(&lcom);
12257 return ret;
57d187bc
JS
12258}
12259
d62a17ae 12260static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12261 const char *lcom, bool exact, afi_t afi,
12262 safi_t safi, bool uj)
57d187bc 12263{
d62a17ae 12264 struct community_list *list;
96c81f66 12265 uint16_t show_flags = 0;
96f3485c
MK
12266
12267 if (uj)
12268 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12269
57d187bc 12270
e237b0d2 12271 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12272 LARGE_COMMUNITY_LIST_MASTER);
12273 if (list == NULL) {
12274 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12275 lcom);
12276 return CMD_WARNING;
12277 }
57d187bc 12278
36a206db 12279 return bgp_show(vty, bgp, afi, safi,
12280 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12281 : bgp_show_type_lcommunity_list),
1e2ce4f1 12282 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12283}
12284
52951b63
DS
12285DEFUN (show_ip_bgp_large_community_list,
12286 show_ip_bgp_large_community_list_cmd,
77a3a95e 12287 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
52951b63
DS
12288 SHOW_STR
12289 IP_STR
12290 BGP_STR
12291 BGP_INSTANCE_HELP_STR
9bedbb1e 12292 BGP_AFI_HELP_STR
4dd6177e 12293 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12294 "Display routes matching the large-community-list\n"
12295 "large-community-list number\n"
12296 "large-community-list name\n"
36a206db 12297 "Exact match of the large-communities\n"
52951b63
DS
12298 JSON_STR)
12299{
d62a17ae 12300 afi_t afi = AFI_IP6;
12301 safi_t safi = SAFI_UNICAST;
12302 int idx = 0;
36a206db 12303 bool exact_match = 0;
4d678463 12304 struct bgp *bgp = NULL;
9f049418 12305 bool uj = use_json(argc, argv);
d62a17ae 12306
ef3364f0
DA
12307 if (uj)
12308 argc--;
4d678463 12309
ef3364f0
DA
12310 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12311 &bgp, uj);
12312 if (!idx)
12313 return CMD_WARNING;
d62a17ae 12314
12315 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12316
12317 const char *clist_number_or_name = argv[++idx]->arg;
12318
12319 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12320 exact_match = 1;
12321
12322 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12323 exact_match, afi, safi, uj);
52951b63
DS
12324}
12325DEFUN (show_ip_bgp_large_community,
12326 show_ip_bgp_large_community_cmd,
36a206db 12327 "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
12328 SHOW_STR
12329 IP_STR
12330 BGP_STR
12331 BGP_INSTANCE_HELP_STR
9bedbb1e 12332 BGP_AFI_HELP_STR
4dd6177e 12333 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12334 "Display routes matching the large-communities\n"
12335 "List of large-community numbers\n"
36a206db 12336 "Exact match of the large-communities\n"
52951b63
DS
12337 JSON_STR)
12338{
d62a17ae 12339 afi_t afi = AFI_IP6;
12340 safi_t safi = SAFI_UNICAST;
12341 int idx = 0;
36a206db 12342 bool exact_match = 0;
4d678463 12343 struct bgp *bgp = NULL;
9f049418 12344 bool uj = use_json(argc, argv);
96c81f66 12345 uint16_t show_flags = 0;
d62a17ae 12346
96f3485c
MK
12347 if (uj) {
12348 argc--;
12349 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12350 }
4d678463 12351
96f3485c
MK
12352 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12353 &bgp, uj);
12354 if (!idx)
12355 return CMD_WARNING;
d62a17ae 12356
36a206db 12357 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12358 if (argv_find(argv, argc, "exact-match", &idx)) {
12359 argc--;
36a206db 12360 exact_match = 1;
1857760c 12361 }
36a206db 12362 return bgp_show_lcommunity(vty, bgp, argc, argv,
12363 exact_match, afi, safi, uj);
12364 } else
d62a17ae 12365 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12366 bgp_show_type_lcommunity_all, NULL, show_flags,
12367 RPKI_NOT_BEING_USED);
52951b63
DS
12368}
12369
71f1613a
DA
12370static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12371 safi_t safi, struct json_object *json_array);
d62a17ae 12372static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12373 safi_t safi, struct json_object *json);
e01ca200 12374
7b2ff250 12375
9ab0cf58
PG
12376DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12377 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12378 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12379 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12380{
12381 bool uj = use_json(argc, argv);
12382 struct bgp *bgp = NULL;
ec76a1d1
DA
12383 safi_t safi = SAFI_UNICAST;
12384 afi_t afi = AFI_IP6;
4265b261 12385 int idx = 0;
6c9d22e2
PG
12386 struct json_object *json_all = NULL;
12387 struct json_object *json_afi_safi = NULL;
4265b261
PG
12388
12389 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12390 &bgp, false);
71f1613a 12391 if (!idx)
4265b261 12392 return CMD_WARNING;
6c9d22e2 12393
4265b261 12394 if (uj)
6c9d22e2 12395 json_all = json_object_new_object();
4265b261 12396
9ab0cf58
PG
12397 FOREACH_AFI_SAFI (afi, safi) {
12398 /*
12399 * So limit output to those afi/safi pairs that
12400 * actually have something interesting in them
12401 */
12402 if (strmatch(get_afi_safi_str(afi, safi, true),
12403 "Unknown")) {
12404 continue;
12405 }
12406 if (uj) {
12407 json_afi_safi = json_object_new_array();
12408 json_object_object_add(
12409 json_all,
12410 get_afi_safi_str(afi, safi, true),
12411 json_afi_safi);
12412 } else {
12413 json_afi_safi = NULL;
6c9d22e2 12414 }
9ab0cf58
PG
12415
12416 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12417 }
6c9d22e2 12418
3757f964
DA
12419 if (uj)
12420 vty_json(vty, json_all);
6c9d22e2 12421
4265b261
PG
12422 return CMD_SUCCESS;
12423}
12424
7b2ff250 12425/* BGP route print out function without JSON */
14718643
PG
12426DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12427 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12428 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12429 SHOW_STR
12430 IP_STR
12431 BGP_STR
12432 BGP_INSTANCE_HELP_STR
12433 L2VPN_HELP_STR
12434 EVPN_HELP_STR
12435 "BGP RIB advertisement statistics\n"
12436 JSON_STR)
12437{
ec76a1d1
DA
12438 afi_t afi = AFI_IP6;
12439 safi_t safi = SAFI_UNICAST;
14718643
PG
12440 struct bgp *bgp = NULL;
12441 int idx = 0, ret;
12442 bool uj = use_json(argc, argv);
12443 struct json_object *json_afi_safi = NULL, *json = NULL;
12444
12445 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12446 &bgp, false);
12447 if (!idx)
12448 return CMD_WARNING;
12449
12450 if (uj)
12451 json_afi_safi = json_object_new_array();
12452 else
12453 json_afi_safi = NULL;
12454
12455 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12456
12457 if (uj) {
12458 json = json_object_new_object();
12459 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12460 json_afi_safi);
3757f964 12461 vty_json(vty, json);
14718643
PG
12462 }
12463 return ret;
12464}
12465
893cccd0 12466/* BGP route print out function without JSON */
9ab0cf58
PG
12467DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12468 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12469 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12470 "]]\
893cccd0 12471 statistics [json]",
9ab0cf58
PG
12472 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12473 BGP_SAFI_WITH_LABEL_HELP_STR
12474 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12475{
ec76a1d1
DA
12476 afi_t afi = AFI_IP6;
12477 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12478 struct bgp *bgp = NULL;
12479 int idx = 0, ret;
12480 bool uj = use_json(argc, argv);
6c9d22e2 12481 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12482
12483 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12484 &bgp, false);
12485 if (!idx)
12486 return CMD_WARNING;
6c9d22e2 12487
893cccd0 12488 if (uj)
6c9d22e2
PG
12489 json_afi_safi = json_object_new_array();
12490 else
12491 json_afi_safi = NULL;
12492
12493 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12494
12495 if (uj) {
12496 json = json_object_new_object();
12497 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12498 json_afi_safi);
3757f964 12499 vty_json(vty, json);
893cccd0
PG
12500 }
12501 return ret;
893cccd0 12502}
7b2ff250 12503
fe0f234d 12504DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12505 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12506 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12507 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12508 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12509 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12510 "Display the entries for all address families\n"
9ab0cf58
PG
12511 "Display detailed information about dampening\n"
12512 "Display detail of configured dampening parameters\n"
fe0f234d 12513 JSON_STR)
718e3744 12514{
d62a17ae 12515 afi_t afi = AFI_IP6;
12516 safi_t safi = SAFI_UNICAST;
d62a17ae 12517 struct bgp *bgp = NULL;
12518 int idx = 0;
96c81f66 12519 uint16_t show_flags = 0;
fe0f234d
RW
12520 bool uj = use_json(argc, argv);
12521
12522 if (uj) {
12523 argc--;
12524 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12525 }
96f3485c
MK
12526
12527 /* [<ipv4|ipv6> [all]] */
12528 if (all) {
12529 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12530 if (argv_find(argv, argc, "ipv4", &idx))
12531 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12532
12533 if (argv_find(argv, argc, "ipv6", &idx))
12534 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12535 }
d62a17ae 12536
12537 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12538 &bgp, false);
d62a17ae 12539 if (!idx)
12540 return CMD_WARNING;
12541
fe0f234d 12542 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12543}
12544
fe0f234d
RW
12545/* BGP route print out function */
12546DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12547 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12548 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12549 "]]\
96f3485c 12550 [all$all]\
cf4898bc
QY
12551 [cidr-only\
12552 |dampening <flap-statistics|dampened-paths>\
12553 |community [AA:NN|local-AS|no-advertise|no-export\
12554 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12555 |accept-own|accept-own-nexthop|route-filter-v6\
12556 |route-filter-v4|route-filter-translated-v6\
12557 |route-filter-translated-v4] [exact-match]\
70799983 12558 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12559 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12560 |prefix-list WORD\
ed126382 12561 |access-list ACCESSLIST_NAME\
70dd370f 12562 |route-map RMAP_NAME\
1e2ce4f1 12563 |rpki <invalid|valid|notfound>\
7d3cae70 12564 |version (1-4294967295)\
b4ad2fae 12565 |alias ALIAS_NAME\
39c3c736
RW
12566 |A.B.C.D/M longer-prefixes\
12567 |X:X::X:X/M longer-prefixes\
70cd87ca 12568 |optimal-route-reflection [WORD$orr_group_name]\
f280c93b 12569 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12570 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12571 BGP_SAFI_WITH_LABEL_HELP_STR
12572 "Display the entries for all address families\n"
12573 "Display only routes with non-natural netmasks\n"
12574 "Display detailed information about dampening\n"
12575 "Display flap statistics of routes\n"
12576 "Display paths suppressed due to dampening\n"
12577 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12578 "Do not send outside local AS (well-known community)\n"
12579 "Do not advertise to any peer (well-known community)\n"
12580 "Do not export to next AS (well-known community)\n"
12581 "Graceful shutdown (well-known community)\n"
12582 "Do not export to any peer (well-known community)\n"
12583 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12584 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12585 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12586 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12587 "Should accept VPN route with local nexthop (well-known community)\n"
12588 "RT VPNv6 route filtering (well-known community)\n"
12589 "RT VPNv4 route filtering (well-known community)\n"
12590 "RT translated VPNv6 route filtering (well-known community)\n"
12591 "RT translated VPNv4 route filtering (well-known community)\n"
12592 "Exact match of the communities\n"
70799983
RW
12593 "Community-list number\n"
12594 "Community-list name\n"
12595 "Display routes matching the community-list\n"
12596 "Exact match of the communities\n"
a7129347
RW
12597 "Display routes conforming to the filter-list\n"
12598 "Regular expression access list name\n"
6deaf579
RW
12599 "Display routes conforming to the prefix-list\n"
12600 "Prefix-list name\n"
ed126382
DA
12601 "Display routes conforming to the access-list\n"
12602 "Access-list name\n"
bf1a944a
RW
12603 "Display routes matching the route-map\n"
12604 "A route-map to match on\n"
a70a28a5
DA
12605 "RPKI route types\n"
12606 "A valid path as determined by rpki\n"
12607 "A invalid path as determined by rpki\n"
12608 "A path that has no rpki data\n"
12609 "Display prefixes with matching version numbers\n"
12610 "Version number and above\n"
12611 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12612 "BGP community alias\n"
12613 "IPv4 prefix\n"
12614 "Display route and more specific routes\n"
12615 "IPv6 prefix\n"
12616 "Display route and more specific routes\n"
70cd87ca
MK
12617 "Display Optimal Route Reflection RR Clients\n"
12618 "ORR Group name\n"
39c3c736 12619 JSON_STR
a70a28a5
DA
12620 "Display detailed version of JSON output\n"
12621 "Increase table width for longer prefixes\n")
7b2ff250
DW
12622{
12623 afi_t afi = AFI_IP6;
12624 safi_t safi = SAFI_UNICAST;
12625 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12626 void *output_arg = NULL;
7b2ff250
DW
12627 struct bgp *bgp = NULL;
12628 int idx = 0;
d0086e8e 12629 int exact_match = 0;
96f3485c
MK
12630 char *community = NULL;
12631 bool first = true;
96c81f66 12632 uint16_t show_flags = 0;
4027d19b 12633 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12634 struct prefix p;
70cd87ca 12635 bool orr_group = false;
96f3485c
MK
12636
12637 if (uj) {
9f049418 12638 argc--;
96f3485c
MK
12639 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12640 }
12641
f280c93b
DA
12642 if (detail)
12643 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12644
96f3485c
MK
12645 /* [<ipv4|ipv6> [all]] */
12646 if (all) {
12647 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12648
12649 if (argv_find(argv, argc, "ipv4", &idx))
12650 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12651
12652 if (argv_find(argv, argc, "ipv6", &idx))
12653 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12654 }
12655
12656 if (wide)
12657 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12658
12659 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12660 &bgp, uj);
7b2ff250
DW
12661 if (!idx)
12662 return CMD_WARNING;
12663
7b2ff250 12664 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12665 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12666
12667 if (argv_find(argv, argc, "dampening", &idx)) {
12668 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12669 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12670 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12671 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12672 }
12673
12674 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12675 char *maybecomm = NULL;
d0086e8e 12676
79bc257a
RW
12677 if (idx + 1 < argc) {
12678 if (argv[idx + 1]->type == VARIABLE_TKN)
12679 maybecomm = argv[idx + 1]->arg;
12680 else
12681 maybecomm = argv[idx + 1]->text;
12682 }
12683
cf4898bc
QY
12684 if (maybecomm && !strmatch(maybecomm, "json")
12685 && !strmatch(maybecomm, "exact-match"))
12686 community = maybecomm;
d0086e8e 12687
cf4898bc
QY
12688 if (argv_find(argv, argc, "exact-match", &idx))
12689 exact_match = 1;
d0086e8e 12690
96f3485c
MK
12691 if (!community)
12692 sh_type = bgp_show_type_community_all;
12693 }
12694
70799983
RW
12695 if (argv_find(argv, argc, "community-list", &idx)) {
12696 const char *clist_number_or_name = argv[++idx]->arg;
12697 struct community_list *list;
12698
12699 if (argv_find(argv, argc, "exact-match", &idx))
12700 exact_match = 1;
12701
12702 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12703 COMMUNITY_LIST_MASTER);
12704 if (list == NULL) {
606d49a4 12705 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12706 clist_number_or_name);
12707 return CMD_WARNING;
12708 }
12709
12710 if (exact_match)
12711 sh_type = bgp_show_type_community_list_exact;
12712 else
12713 sh_type = bgp_show_type_community_list;
12714 output_arg = list;
12715 }
12716
a7129347
RW
12717 if (argv_find(argv, argc, "filter-list", &idx)) {
12718 const char *filter = argv[++idx]->arg;
12719 struct as_list *as_list;
12720
12721 as_list = as_list_lookup(filter);
12722 if (as_list == NULL) {
606d49a4 12723 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12724 filter);
12725 return CMD_WARNING;
12726 }
12727
12728 sh_type = bgp_show_type_filter_list;
12729 output_arg = as_list;
12730 }
12731
6deaf579
RW
12732 if (argv_find(argv, argc, "prefix-list", &idx)) {
12733 const char *prefix_list_str = argv[++idx]->arg;
12734 struct prefix_list *plist;
12735
12736 plist = prefix_list_lookup(afi, prefix_list_str);
12737 if (plist == NULL) {
606d49a4 12738 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12739 prefix_list_str);
12740 return CMD_WARNING;
12741 }
12742
12743 sh_type = bgp_show_type_prefix_list;
12744 output_arg = plist;
12745 }
12746
ed126382
DA
12747 if (argv_find(argv, argc, "access-list", &idx)) {
12748 const char *access_list_str = argv[++idx]->arg;
12749 struct access_list *alist;
12750
12751 alist = access_list_lookup(afi, access_list_str);
12752 if (!alist) {
606d49a4 12753 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12754 access_list_str);
12755 return CMD_WARNING;
12756 }
12757
12758 sh_type = bgp_show_type_access_list;
12759 output_arg = alist;
12760 }
12761
bf1a944a
RW
12762 if (argv_find(argv, argc, "route-map", &idx)) {
12763 const char *rmap_str = argv[++idx]->arg;
12764 struct route_map *rmap;
12765
12766 rmap = route_map_lookup_by_name(rmap_str);
12767 if (!rmap) {
606d49a4 12768 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12769 return CMD_WARNING;
12770 }
12771
12772 sh_type = bgp_show_type_route_map;
12773 output_arg = rmap;
12774 }
12775
1e2ce4f1
DS
12776 if (argv_find(argv, argc, "rpki", &idx)) {
12777 sh_type = bgp_show_type_rpki;
12778 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12779 rpki_target_state = RPKI_VALID;
1e2ce4f1 12780 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12781 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12782 }
12783
7d3cae70
DA
12784 /* Display prefixes with matching version numbers */
12785 if (argv_find(argv, argc, "version", &idx)) {
12786 sh_type = bgp_show_type_prefix_version;
2391833e 12787 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12788 }
12789
a70a28a5
DA
12790 /* Display prefixes with matching BGP community alias */
12791 if (argv_find(argv, argc, "alias", &idx)) {
12792 sh_type = bgp_show_type_community_alias;
2391833e 12793 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12794 }
12795
39c3c736
RW
12796 /* prefix-longer */
12797 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12798 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12799 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12800
12801 if (!str2prefix(prefix_str, &p)) {
12802 vty_out(vty, "%% Malformed Prefix\n");
12803 return CMD_WARNING;
12804 }
12805
12806 sh_type = bgp_show_type_prefix_longer;
12807 output_arg = &p;
a70a28a5
DA
12808 }
12809
70cd87ca
MK
12810 if (argv_find(argv, argc, "optimal-route-reflection", &idx))
12811 orr_group = true;
12812
96f3485c
MK
12813 if (!all) {
12814 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12815 if (community)
12816 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12817 exact_match, afi, safi,
12818 show_flags);
70cd87ca
MK
12819 else if (orr_group)
12820 return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
12821 show_flags);
2391833e 12822 else
a70a28a5 12823 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12824 output_arg, show_flags,
a70a28a5 12825 rpki_target_state);
96f3485c 12826 } else {
fa5ac378
DA
12827 struct listnode *node;
12828 struct bgp *abgp;
96f3485c
MK
12829 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12830 * AFI_IP6 */
12831
12832 if (uj)
12833 vty_out(vty, "{\n");
12834
12835 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12836 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12837 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12838 ? AFI_IP
12839 : AFI_IP6;
fa5ac378
DA
12840 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12841 FOREACH_SAFI (safi) {
12842 if (!bgp_afi_safi_peer_exists(abgp, afi,
12843 safi))
12844 continue;
96f3485c 12845
fa5ac378
DA
12846 if (uj) {
12847 if (first)
12848 first = false;
12849 else
12850 vty_out(vty, ",\n");
12851 vty_out(vty, "\"%s\":{\n",
12852 get_afi_safi_str(afi,
12853 safi,
12854 true));
12855 } else
12856 vty_out(vty,
12857 "\nFor address family: %s\n",
12858 get_afi_safi_str(
12859 afi, safi,
12860 false));
12861
12862 if (community)
12863 bgp_show_community(
12864 vty, abgp, community,
12865 exact_match, afi, safi,
12866 show_flags);
70cd87ca
MK
12867 else if (orr_group)
12868 bgp_show_orr(vty, bgp, afi,
12869 safi,
12870 orr_group_name,
12871 show_flags);
96f3485c 12872 else
fa5ac378
DA
12873 bgp_show(vty, abgp, afi, safi,
12874 sh_type, output_arg,
12875 show_flags,
12876 rpki_target_state);
12877 if (uj)
12878 vty_out(vty, "}\n");
12879 }
96f3485c
MK
12880 }
12881 } else {
12882 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12883 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12884 FOREACH_AFI_SAFI (afi, safi) {
12885 if (!bgp_afi_safi_peer_exists(abgp, afi,
12886 safi))
12887 continue;
96f3485c 12888
fa5ac378
DA
12889 if (uj) {
12890 if (first)
12891 first = false;
12892 else
12893 vty_out(vty, ",\n");
12894
12895 vty_out(vty, "\"%s\":{\n",
12896 get_afi_safi_str(afi,
12897 safi,
12898 true));
12899 } else
12900 vty_out(vty,
12901 "\nFor address family: %s\n",
12902 get_afi_safi_str(
12903 afi, safi,
12904 false));
12905
12906 if (community)
12907 bgp_show_community(
12908 vty, abgp, community,
12909 exact_match, afi, safi,
12910 show_flags);
70cd87ca
MK
12911 else if (orr_group)
12912 bgp_show_orr(vty, bgp, afi,
12913 safi,
12914 orr_group_name,
12915 show_flags);
96f3485c 12916 else
fa5ac378
DA
12917 bgp_show(vty, abgp, afi, safi,
12918 sh_type, output_arg,
12919 show_flags,
12920 rpki_target_state);
12921 if (uj)
12922 vty_out(vty, "}\n");
12923 }
96f3485c
MK
12924 }
12925 }
12926 if (uj)
12927 vty_out(vty, "}\n");
12928 }
12929 return CMD_SUCCESS;
a636c635 12930}
47fc97cc 12931
718e3744 12932DEFUN (show_ip_bgp_route,
12933 show_ip_bgp_route_cmd,
8aa22bbb 12934 "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 12935 SHOW_STR
12936 IP_STR
12937 BGP_STR
a636c635 12938 BGP_INSTANCE_HELP_STR
4f280b15 12939 BGP_AFI_HELP_STR
4dd6177e 12940 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12941 "Network in the BGP routing table to display\n"
0c7b1b01 12942 "IPv4 prefix\n"
8c3deaae 12943 "Network in the BGP routing table to display\n"
0c7b1b01 12944 "IPv6 prefix\n"
4092b06c 12945 "Display only the bestpath\n"
b05a1c8b 12946 "Display only multipaths\n"
8aa22bbb
DS
12947 "Display only paths that match the specified rpki state\n"
12948 "A valid path as determined by rpki\n"
12949 "A invalid path as determined by rpki\n"
12950 "A path that has no rpki data\n"
9973d184 12951 JSON_STR)
4092b06c 12952{
d62a17ae 12953 int prefix_check = 0;
ae19d7dd 12954
d62a17ae 12955 afi_t afi = AFI_IP6;
12956 safi_t safi = SAFI_UNICAST;
12957 char *prefix = NULL;
12958 struct bgp *bgp = NULL;
12959 enum bgp_path_type path_type;
9f049418 12960 bool uj = use_json(argc, argv);
b05a1c8b 12961
d62a17ae 12962 int idx = 0;
ae19d7dd 12963
d62a17ae 12964 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12965 &bgp, uj);
d62a17ae 12966 if (!idx)
12967 return CMD_WARNING;
c41247f5 12968
d62a17ae 12969 if (!bgp) {
12970 vty_out(vty,
12971 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12972 return CMD_WARNING;
12973 }
a636c635 12974
d62a17ae 12975 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12976 if (argv_find(argv, argc, "A.B.C.D", &idx)
12977 || argv_find(argv, argc, "X:X::X:X", &idx))
12978 prefix_check = 0;
12979 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12980 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12981 prefix_check = 1;
12982
12983 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12984 && afi != AFI_IP6) {
12985 vty_out(vty,
12986 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12987 return CMD_WARNING;
12988 }
12989 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12990 && afi != AFI_IP) {
12991 vty_out(vty,
12992 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12993 return CMD_WARNING;
12994 }
12995
12996 prefix = argv[idx]->arg;
12997
12998 /* [<bestpath|multipath>] */
12999 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13000 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13001 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13002 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13003 else
360660c6 13004 path_type = BGP_PATH_SHOW_ALL;
a636c635 13005
d62a17ae 13006 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13007 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13008}
13009
8c3deaae
QY
13010DEFUN (show_ip_bgp_regexp,
13011 show_ip_bgp_regexp_cmd,
3e5b31b3 13012 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13013 SHOW_STR
13014 IP_STR
13015 BGP_STR
b00b230a 13016 BGP_INSTANCE_HELP_STR
4f280b15 13017 BGP_AFI_HELP_STR
4dd6177e 13018 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13019 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13020 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13021 JSON_STR)
8c3deaae 13022{
d62a17ae 13023 afi_t afi = AFI_IP6;
13024 safi_t safi = SAFI_UNICAST;
13025 struct bgp *bgp = NULL;
3e5b31b3
DA
13026 bool uj = use_json(argc, argv);
13027 char *regstr = NULL;
8c3deaae 13028
d62a17ae 13029 int idx = 0;
13030 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13031 &bgp, false);
d62a17ae 13032 if (!idx)
13033 return CMD_WARNING;
8c3deaae 13034
d62a17ae 13035 // get index of regex
3e5b31b3
DA
13036 if (argv_find(argv, argc, "REGEX", &idx))
13037 regstr = argv[idx]->arg;
8c3deaae 13038
5f71d11c 13039 assert(regstr);
3e5b31b3
DA
13040 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13041 bgp_show_type_regexp, uj);
8c3deaae
QY
13042}
13043
ae248832 13044DEFPY (show_ip_bgp_instance_all,
a636c635 13045 show_ip_bgp_instance_all_cmd,
ae248832 13046 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13047 SHOW_STR
a636c635 13048 IP_STR
4092b06c 13049 BGP_STR
a636c635 13050 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13051 BGP_AFI_HELP_STR
4dd6177e 13052 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13053 JSON_STR
13054 "Increase table width for longer prefixes\n")
4092b06c 13055{
54d05dea 13056 afi_t afi = AFI_IP6;
d62a17ae 13057 safi_t safi = SAFI_UNICAST;
13058 struct bgp *bgp = NULL;
d62a17ae 13059 int idx = 0;
96c81f66 13060 uint16_t show_flags = 0;
ae19d7dd 13061
96f3485c 13062 if (uj) {
d62a17ae 13063 argc--;
96f3485c
MK
13064 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13065 }
13066
13067 if (wide)
13068 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13069
9f049418
DS
13070 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13071 &bgp, uj);
13072 if (!idx)
13073 return CMD_WARNING;
13074
96f3485c 13075 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13076 return CMD_SUCCESS;
e3e29b32
LB
13077}
13078
a4d82a8a 13079static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13080 afi_t afi, safi_t safi, enum bgp_show_type type,
13081 bool use_json)
718e3744 13082{
d62a17ae 13083 regex_t *regex;
13084 int rc;
96c81f66 13085 uint16_t show_flags = 0;
96f3485c
MK
13086
13087 if (use_json)
13088 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13089
c3900853 13090 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13091 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13092 regstr);
13093 return CMD_WARNING_CONFIG_FAILED;
13094 }
13095
d62a17ae 13096 regex = bgp_regcomp(regstr);
13097 if (!regex) {
13098 vty_out(vty, "Can't compile regexp %s\n", regstr);
13099 return CMD_WARNING;
13100 }
a636c635 13101
1e2ce4f1
DS
13102 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13103 RPKI_NOT_BEING_USED);
d62a17ae 13104 bgp_regex_free(regex);
13105 return rc;
e3e29b32
LB
13106}
13107
7f323236
DW
13108static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13109 const char *comstr, int exact, afi_t afi,
96c81f66 13110 safi_t safi, uint16_t show_flags)
d62a17ae 13111{
13112 struct community *com;
d62a17ae 13113 int ret = 0;
13114
7f323236 13115 com = community_str2com(comstr);
d62a17ae 13116 if (!com) {
7f323236 13117 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13118 return CMD_WARNING;
13119 }
13120
13121 ret = bgp_show(vty, bgp, afi, safi,
13122 (exact ? bgp_show_type_community_exact
13123 : bgp_show_type_community),
1e2ce4f1 13124 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13125 community_free(&com);
46c3ce83 13126
d62a17ae 13127 return ret;
718e3744 13128}
13129
d62a17ae 13130enum bgp_stats {
13131 BGP_STATS_MAXBITLEN = 0,
13132 BGP_STATS_RIB,
13133 BGP_STATS_PREFIXES,
13134 BGP_STATS_TOTPLEN,
13135 BGP_STATS_UNAGGREGATEABLE,
13136 BGP_STATS_MAX_AGGREGATEABLE,
13137 BGP_STATS_AGGREGATES,
13138 BGP_STATS_SPACE,
13139 BGP_STATS_ASPATH_COUNT,
13140 BGP_STATS_ASPATH_MAXHOPS,
13141 BGP_STATS_ASPATH_TOTHOPS,
13142 BGP_STATS_ASPATH_MAXSIZE,
13143 BGP_STATS_ASPATH_TOTSIZE,
13144 BGP_STATS_ASN_HIGHEST,
13145 BGP_STATS_MAX,
a636c635 13146};
2815e61f 13147
9ab0cf58 13148#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13149#define TABLE_STATS_IDX_JSON 1
13150
13151static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13152 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13153 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13154 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13155 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13156 "unaggregateablePrefixes"},
13157 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13158 "maximumAggregateablePrefixes"},
13159 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13160 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13161 [BGP_STATS_SPACE] = {"Address space advertised",
13162 "addressSpaceAdvertised"},
9ab0cf58
PG
13163 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13164 "advertisementsWithPaths"},
13165 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13166 "longestAsPath"},
13167 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13168 "largestAsPath"},
13169 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13170 "averageAsPathLengthHops"},
13171 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13172 "averageAsPathSizeBytes"},
13173 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13174 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13175};
2815e61f 13176
d62a17ae 13177struct bgp_table_stats {
13178 struct bgp_table *table;
13179 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13180
13181 unsigned long long
13182 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13183 1];
13184
8d0ab76d 13185 double total_space;
ff7924f6
PJ
13186};
13187
9bcb3eef 13188static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13189 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13190{
9bcb3eef 13191 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13192 struct bgp_path_info *pi;
b54892e0 13193 const struct prefix *rn_p;
d62a17ae 13194
9bcb3eef 13195 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13196 return;
d62a17ae 13197
9bcb3eef 13198 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13199 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13200 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13201
0747643e 13202 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13203 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13204 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13205 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13206
9bcb3eef 13207 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13208 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13209 /* announced address space */
13210 if (space)
b54892e0 13211 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13212 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13213 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13214
9c14ec72 13215
9bcb3eef 13216 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13217 ts->counts[BGP_STATS_RIB]++;
13218
05864da7
DS
13219 if (CHECK_FLAG(pi->attr->flag,
13220 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13221 ts->counts[BGP_STATS_AGGREGATES]++;
13222
13223 /* as-path stats */
05864da7 13224 if (pi->attr->aspath) {
9c14ec72
RW
13225 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13226 unsigned int size = aspath_size(pi->attr->aspath);
13227 as_t highest = aspath_highest(pi->attr->aspath);
13228
13229 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13230
13231 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13232 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13233
13234 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13235 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13236
13237 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13238 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13239 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13240 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13241 }
13242 }
13243}
13244
cc9f21da 13245static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13246{
9bcb3eef
DS
13247 struct bgp_dest *dest, *ndest;
13248 struct bgp_dest *top;
9c14ec72
RW
13249 struct bgp_table_stats *ts = THREAD_ARG(t);
13250 unsigned int space = 0;
13251
13252 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13253 return;
9c14ec72
RW
13254
13255 switch (ts->table->afi) {
13256 case AFI_IP:
13257 space = IPV4_MAX_BITLEN;
13258 break;
13259 case AFI_IP6:
13260 space = IPV6_MAX_BITLEN;
13261 break;
3ba7b4af
TA
13262 case AFI_L2VPN:
13263 space = EVPN_ROUTE_PREFIXLEN;
13264 break;
9c14ec72 13265 default:
cc9f21da 13266 return;
9c14ec72
RW
13267 }
13268
13269 ts->counts[BGP_STATS_MAXBITLEN] = space;
13270
9bcb3eef 13271 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13272 if (ts->table->safi == SAFI_MPLS_VPN
13273 || ts->table->safi == SAFI_ENCAP
13274 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13275 struct bgp_table *table;
13276
9bcb3eef 13277 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13278 if (!table)
13279 continue;
13280
13281 top = bgp_table_top(table);
9bcb3eef
DS
13282 for (ndest = bgp_table_top(table); ndest;
13283 ndest = bgp_route_next(ndest))
13284 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13285 } else {
9bcb3eef 13286 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13287 }
13288 }
2815e61f 13289}
ff7924f6 13290
71f1613a
DA
13291static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13292 struct json_object *json_array)
13293{
13294 struct listnode *node, *nnode;
13295 struct bgp *bgp;
13296
13297 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13298 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13299}
13300
13301static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13302 safi_t safi, struct json_object *json_array)
2815e61f 13303{
d62a17ae 13304 struct bgp_table_stats ts;
13305 unsigned int i;
893cccd0
PG
13306 int ret = CMD_SUCCESS;
13307 char temp_buf[20];
6c9d22e2 13308 struct json_object *json = NULL;
0747643e
AQ
13309 uint32_t bitlen = 0;
13310 struct json_object *json_bitlen;
6c9d22e2
PG
13311
13312 if (json_array)
13313 json = json_object_new_object();
019386c2 13314
d62a17ae 13315 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13316 char warning_msg[50];
13317
13318 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13319 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13320 safi);
6c9d22e2
PG
13321
13322 if (!json)
893cccd0
PG
13323 vty_out(vty, "%s\n", warning_msg);
13324 else
9ab0cf58 13325 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13326
893cccd0
PG
13327 ret = CMD_WARNING;
13328 goto end_table_stats;
d62a17ae 13329 }
019386c2 13330
893cccd0 13331 if (!json)
5290ceab
DA
13332 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13333 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13334 else
13335 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13336
d62a17ae 13337 /* labeled-unicast routes live in the unicast table */
13338 if (safi == SAFI_LABELED_UNICAST)
13339 safi = SAFI_UNICAST;
019386c2 13340
d62a17ae 13341 memset(&ts, 0, sizeof(ts));
13342 ts.table = bgp->rib[afi][safi];
13343 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13344
d62a17ae 13345 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13346 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13347 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13348 continue;
13349
13350 switch (i) {
d62a17ae 13351 case BGP_STATS_ASPATH_TOTHOPS:
13352 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13353 if (!json) {
9ab0cf58
PG
13354 snprintf(
13355 temp_buf, sizeof(temp_buf), "%12.2f",
13356 ts.counts[i]
13357 ? (float)ts.counts[i]
13358 / (float)ts.counts
13359 [BGP_STATS_ASPATH_COUNT]
13360 : 0);
893cccd0 13361 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13362 table_stats_strs[i]
13363 [TABLE_STATS_IDX_VTY],
893cccd0 13364 temp_buf);
9ab0cf58
PG
13365 } else {
13366 json_object_double_add(
13367 json,
13368 table_stats_strs[i]
13369 [TABLE_STATS_IDX_JSON],
13370 ts.counts[i]
13371 ? (double)ts.counts[i]
13372 / (double)ts.counts
d62a17ae 13373 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13374 : 0);
13375 }
d62a17ae 13376 break;
13377 case BGP_STATS_TOTPLEN:
6c9d22e2 13378 if (!json) {
9ab0cf58
PG
13379 snprintf(
13380 temp_buf, sizeof(temp_buf), "%12.2f",
13381 ts.counts[i]
13382 ? (float)ts.counts[i]
13383 / (float)ts.counts
13384 [BGP_STATS_PREFIXES]
13385 : 0);
893cccd0 13386 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13387 table_stats_strs[i]
13388 [TABLE_STATS_IDX_VTY],
893cccd0 13389 temp_buf);
9ab0cf58
PG
13390 } else {
13391 json_object_double_add(
13392 json,
13393 table_stats_strs[i]
13394 [TABLE_STATS_IDX_JSON],
13395 ts.counts[i]
13396 ? (double)ts.counts[i]
13397 / (double)ts.counts
d62a17ae 13398 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13399 : 0);
13400 }
d62a17ae 13401 break;
13402 case BGP_STATS_SPACE:
6c9d22e2
PG
13403 if (!json) {
13404 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13405 ts.total_space);
893cccd0 13406 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13407 table_stats_strs[i]
13408 [TABLE_STATS_IDX_VTY],
893cccd0 13409 temp_buf);
9ab0cf58
PG
13410 } else {
13411 json_object_double_add(
13412 json,
13413 table_stats_strs[i]
13414 [TABLE_STATS_IDX_JSON],
13415 (double)ts.total_space);
13416 }
8d0ab76d 13417 if (afi == AFI_IP6) {
6c9d22e2
PG
13418 if (!json) {
13419 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13420 "%12g",
13421 ts.total_space
13422 * pow(2.0, -128 + 32));
6c9d22e2
PG
13423 vty_out(vty, "%30s: %s\n",
13424 "/32 equivalent %s\n",
13425 temp_buf);
9ab0cf58
PG
13426 } else {
13427 json_object_double_add(
13428 json, "/32equivalent",
13429 (double)(ts.total_space
13430 * pow(2.0,
13431 -128 + 32)));
13432 }
6c9d22e2
PG
13433 if (!json) {
13434 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13435 "%12g",
13436 ts.total_space
13437 * pow(2.0, -128 + 48));
6c9d22e2
PG
13438 vty_out(vty, "%30s: %s\n",
13439 "/48 equivalent %s\n",
13440 temp_buf);
9ab0cf58
PG
13441 } else {
13442 json_object_double_add(
13443 json, "/48equivalent",
13444 (double)(ts.total_space
13445 * pow(2.0,
13446 -128 + 48)));
13447 }
8d0ab76d 13448 } else {
6c9d22e2
PG
13449 if (!json) {
13450 snprintf(temp_buf, sizeof(temp_buf),
13451 "%12.2f",
9ab0cf58
PG
13452 ts.total_space * 100.
13453 * pow(2.0, -32));
6c9d22e2 13454 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13455 "% announced ", temp_buf);
13456 } else {
13457 json_object_double_add(
13458 json, "%announced",
13459 (double)(ts.total_space * 100.
13460 * pow(2.0, -32)));
13461 }
6c9d22e2
PG
13462 if (!json) {
13463 snprintf(temp_buf, sizeof(temp_buf),
13464 "%12.2f",
9ab0cf58
PG
13465 ts.total_space
13466 * pow(2.0, -32 + 8));
6c9d22e2
PG
13467 vty_out(vty, "%30s: %s\n",
13468 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13469 } else {
13470 json_object_double_add(
13471 json, "/8equivalent",
13472 (double)(ts.total_space
13473 * pow(2.0, -32 + 8)));
13474 }
6c9d22e2
PG
13475 if (!json) {
13476 snprintf(temp_buf, sizeof(temp_buf),
13477 "%12.2f",
9ab0cf58
PG
13478 ts.total_space
13479 * pow(2.0, -32 + 24));
6c9d22e2 13480 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13481 "/24 equivalent ", temp_buf);
13482 } else {
13483 json_object_double_add(
13484 json, "/24equivalent",
13485 (double)(ts.total_space
13486 * pow(2.0, -32 + 24)));
13487 }
8d0ab76d 13488 }
d62a17ae 13489 break;
13490 default:
6c9d22e2
PG
13491 if (!json) {
13492 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13493 ts.counts[i]);
893cccd0 13494 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13495 table_stats_strs[i]
13496 [TABLE_STATS_IDX_VTY],
13497 temp_buf);
13498 } else {
13499 json_object_int_add(
13500 json,
13501 table_stats_strs[i]
13502 [TABLE_STATS_IDX_JSON],
13503 ts.counts[i]);
13504 }
d62a17ae 13505 }
893cccd0
PG
13506 if (!json)
13507 vty_out(vty, "\n");
d62a17ae 13508 }
0747643e
AQ
13509
13510 switch (afi) {
13511 case AFI_IP:
13512 bitlen = IPV4_MAX_BITLEN;
13513 break;
13514 case AFI_IP6:
13515 bitlen = IPV6_MAX_BITLEN;
13516 break;
13517 case AFI_L2VPN:
13518 bitlen = EVPN_ROUTE_PREFIXLEN;
13519 break;
13520 default:
13521 break;
13522 }
13523
13524 if (json) {
13525 json_bitlen = json_object_new_array();
13526
13527 for (i = 0; i <= bitlen; i++) {
13528 struct json_object *ind_bit = json_object_new_object();
13529
13530 if (!ts.prefix_len_count[i])
13531 continue;
13532
13533 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13534 json_object_int_add(ind_bit, temp_buf,
13535 ts.prefix_len_count[i]);
13536 json_object_array_add(json_bitlen, ind_bit);
13537 }
13538 json_object_object_add(json, "prefixLength", json_bitlen);
13539 }
13540
9ab0cf58 13541end_table_stats:
6c9d22e2
PG
13542 if (json)
13543 json_object_array_add(json_array, json);
893cccd0 13544 return ret;
d62a17ae 13545}
13546
71f1613a
DA
13547static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13548 safi_t safi, struct json_object *json_array)
13549{
13550 if (!bgp) {
13551 bgp_table_stats_all(vty, afi, safi, json_array);
13552 return CMD_SUCCESS;
13553 }
13554
13555 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13556}
13557
d62a17ae 13558enum bgp_pcounts {
13559 PCOUNT_ADJ_IN = 0,
13560 PCOUNT_DAMPED,
13561 PCOUNT_REMOVED,
13562 PCOUNT_HISTORY,
13563 PCOUNT_STALE,
13564 PCOUNT_VALID,
13565 PCOUNT_ALL,
13566 PCOUNT_COUNTED,
7e3d9632 13567 PCOUNT_BPATH_SELECTED,
d62a17ae 13568 PCOUNT_PFCNT, /* the figure we display to users */
13569 PCOUNT_MAX,
a636c635 13570};
718e3744 13571
2b64873d 13572static const char *const pcount_strs[] = {
9d303b37
DL
13573 [PCOUNT_ADJ_IN] = "Adj-in",
13574 [PCOUNT_DAMPED] = "Damped",
13575 [PCOUNT_REMOVED] = "Removed",
13576 [PCOUNT_HISTORY] = "History",
13577 [PCOUNT_STALE] = "Stale",
13578 [PCOUNT_VALID] = "Valid",
13579 [PCOUNT_ALL] = "All RIB",
13580 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13581 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13582 [PCOUNT_PFCNT] = "Useable",
13583 [PCOUNT_MAX] = NULL,
a636c635 13584};
718e3744 13585
d62a17ae 13586struct peer_pcounts {
13587 unsigned int count[PCOUNT_MAX];
13588 const struct peer *peer;
13589 const struct bgp_table *table;
54317cba 13590 safi_t safi;
a636c635 13591};
47fc97cc 13592
9bcb3eef 13593static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13594{
54317cba
JW
13595 const struct bgp_adj_in *ain;
13596 const struct bgp_path_info *pi;
d62a17ae 13597 const struct peer *peer = pc->peer;
13598
54317cba
JW
13599 for (ain = rn->adj_in; ain; ain = ain->next)
13600 if (ain->peer == peer)
13601 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13602
9bcb3eef 13603 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13604
54317cba
JW
13605 if (pi->peer != peer)
13606 continue;
d62a17ae 13607
54317cba 13608 pc->count[PCOUNT_ALL]++;
d62a17ae 13609
54317cba
JW
13610 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13611 pc->count[PCOUNT_DAMPED]++;
13612 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13613 pc->count[PCOUNT_HISTORY]++;
13614 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13615 pc->count[PCOUNT_REMOVED]++;
13616 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13617 pc->count[PCOUNT_STALE]++;
13618 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13619 pc->count[PCOUNT_VALID]++;
13620 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13621 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13622 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13623 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13624
13625 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13626 pc->count[PCOUNT_COUNTED]++;
13627 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13628 flog_err(
13629 EC_LIB_DEVELOPMENT,
13630 "Attempting to count but flags say it is unusable");
13631 } else {
40381db7 13632 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13633 flog_err(
13634 EC_LIB_DEVELOPMENT,
13635 "Not counted but flags say we should");
d62a17ae 13636 }
13637 }
54317cba
JW
13638}
13639
cc9f21da 13640static void bgp_peer_count_walker(struct thread *t)
54317cba 13641{
9bcb3eef 13642 struct bgp_dest *rn, *rm;
54317cba
JW
13643 const struct bgp_table *table;
13644 struct peer_pcounts *pc = THREAD_ARG(t);
13645
13646 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13647 || pc->safi == SAFI_EVPN) {
13648 /* Special handling for 2-level routing tables. */
13649 for (rn = bgp_table_top(pc->table); rn;
13650 rn = bgp_route_next(rn)) {
9bcb3eef 13651 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13652 if (table != NULL)
13653 for (rm = bgp_table_top(table); rm;
13654 rm = bgp_route_next(rm))
13655 bgp_peer_count_proc(rm, pc);
13656 }
13657 } else
13658 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13659 bgp_peer_count_proc(rn, pc);
718e3744 13660}
13661
d62a17ae 13662static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13663 safi_t safi, bool use_json)
856ca177 13664{
d62a17ae 13665 struct peer_pcounts pcounts = {.peer = peer};
13666 unsigned int i;
13667 json_object *json = NULL;
13668 json_object *json_loop = NULL;
856ca177 13669
d62a17ae 13670 if (use_json) {
13671 json = json_object_new_object();
13672 json_loop = json_object_new_object();
13673 }
718e3744 13674
d62a17ae 13675 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13676 || !peer->bgp->rib[afi][safi]) {
13677 if (use_json) {
13678 json_object_string_add(
13679 json, "warning",
13680 "No such neighbor or address family");
13681 vty_out(vty, "%s\n", json_object_to_json_string(json));
13682 json_object_free(json);
d5f20468 13683 json_object_free(json_loop);
d62a17ae 13684 } else
13685 vty_out(vty, "%% No such neighbor or address family\n");
13686
13687 return CMD_WARNING;
13688 }
2a71e9ce 13689
d62a17ae 13690 memset(&pcounts, 0, sizeof(pcounts));
13691 pcounts.peer = peer;
13692 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13693 pcounts.safi = safi;
d62a17ae 13694
13695 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13696 * stats for the thread-walk (i.e. ensure this can't be blamed on
13697 * on just vty_read()).
13698 */
d62a17ae 13699 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13700
13701 if (use_json) {
13702 json_object_string_add(json, "prefixCountsFor", peer->host);
13703 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13704 get_afi_safi_str(afi, safi, true));
d62a17ae 13705 json_object_int_add(json, "pfxCounter",
13706 peer->pcount[afi][safi]);
13707
13708 for (i = 0; i < PCOUNT_MAX; i++)
13709 json_object_int_add(json_loop, pcount_strs[i],
13710 pcounts.count[i]);
13711
13712 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13713
13714 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13715 json_object_string_add(json, "pfxctDriftFor",
13716 peer->host);
13717 json_object_string_add(
13718 json, "recommended",
13719 "Please report this bug, with the above command output");
13720 }
75eeda93 13721 vty_json(vty, json);
d62a17ae 13722 } else {
13723
13724 if (peer->hostname
892fedb6 13725 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13726 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13727 peer->hostname, peer->host,
5cb5f4d0 13728 get_afi_safi_str(afi, safi, false));
d62a17ae 13729 } else {
13730 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13731 get_afi_safi_str(afi, safi, false));
d62a17ae 13732 }
13733
6cde4b45 13734 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13735 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13736
13737 for (i = 0; i < PCOUNT_MAX; i++)
13738 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13739 pcounts.count[i]);
13740
13741 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13742 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13743 vty_out(vty,
13744 "Please report this bug, with the above command output\n");
13745 }
13746 }
13747
13748 return CMD_SUCCESS;
718e3744 13749}
13750
a636c635
DW
13751DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13752 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13753 "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 13754 SHOW_STR
13755 IP_STR
13756 BGP_STR
8386ac43 13757 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13758 BGP_AFI_HELP_STR
13759 BGP_SAFI_HELP_STR
0b16f239
DS
13760 "Detailed information on TCP and BGP neighbor connections\n"
13761 "Neighbor to display information about\n"
13762 "Neighbor to display information about\n"
91d37724 13763 "Neighbor on BGP configured interface\n"
a636c635 13764 "Display detailed prefix count information\n"
9973d184 13765 JSON_STR)
0b16f239 13766{
d62a17ae 13767 afi_t afi = AFI_IP6;
13768 safi_t safi = SAFI_UNICAST;
13769 struct peer *peer;
13770 int idx = 0;
13771 struct bgp *bgp = NULL;
9f049418
DS
13772 bool uj = use_json(argc, argv);
13773
13774 if (uj)
13775 argc--;
856ca177 13776
d62a17ae 13777 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13778 &bgp, uj);
d62a17ae 13779 if (!idx)
13780 return CMD_WARNING;
0b16f239 13781
d62a17ae 13782 argv_find(argv, argc, "neighbors", &idx);
13783 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13784 if (!peer)
13785 return CMD_WARNING;
bb46e94f 13786
29c8d9da 13787 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13788}
0b16f239 13789
d6902373
PG
13790#ifdef KEEP_OLD_VPN_COMMANDS
13791DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13792 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13793 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13794 SHOW_STR
13795 IP_STR
13796 BGP_STR
d6902373 13797 BGP_VPNVX_HELP_STR
91d37724 13798 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13799 "Detailed information on TCP and BGP neighbor connections\n"
13800 "Neighbor to display information about\n"
13801 "Neighbor to display information about\n"
91d37724 13802 "Neighbor on BGP configured interface\n"
a636c635 13803 "Display detailed prefix count information\n"
9973d184 13804 JSON_STR)
a636c635 13805{
d62a17ae 13806 int idx_peer = 6;
13807 struct peer *peer;
9f049418 13808 bool uj = use_json(argc, argv);
a636c635 13809
d62a17ae 13810 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13811 if (!peer)
13812 return CMD_WARNING;
13813
13814 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13815}
13816
d6902373
PG
13817DEFUN (show_ip_bgp_vpn_all_route_prefix,
13818 show_ip_bgp_vpn_all_route_prefix_cmd,
13819 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13820 SHOW_STR
13821 IP_STR
13822 BGP_STR
d6902373 13823 BGP_VPNVX_HELP_STR
91d37724
QY
13824 "Display information about all VPNv4 NLRIs\n"
13825 "Network in the BGP routing table to display\n"
3a2d747c 13826 "Network in the BGP routing table to display\n"
9973d184 13827 JSON_STR)
91d37724 13828{
d62a17ae 13829 int idx = 0;
13830 char *network = NULL;
13831 struct bgp *bgp = bgp_get_default();
13832 if (!bgp) {
13833 vty_out(vty, "Can't find default instance\n");
13834 return CMD_WARNING;
13835 }
87e34b58 13836
d62a17ae 13837 if (argv_find(argv, argc, "A.B.C.D", &idx))
13838 network = argv[idx]->arg;
13839 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13840 network = argv[idx]->arg;
13841 else {
13842 vty_out(vty, "Unable to figure out Network\n");
13843 return CMD_WARNING;
13844 }
87e34b58 13845
d62a17ae 13846 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13847 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13848 use_json(argc, argv));
91d37724 13849}
d6902373 13850#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13851
44c69747
LK
13852DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13853 show_bgp_l2vpn_evpn_route_prefix_cmd,
13854 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13855 SHOW_STR
4c63a661
PG
13856 BGP_STR
13857 L2VPN_HELP_STR
13858 EVPN_HELP_STR
44c69747
LK
13859 "Network in the BGP routing table to display\n"
13860 "Network in the BGP routing table to display\n"
4c63a661
PG
13861 "Network in the BGP routing table to display\n"
13862 "Network in the BGP routing table to display\n"
13863 JSON_STR)
13864{
d62a17ae 13865 int idx = 0;
13866 char *network = NULL;
44c69747 13867 int prefix_check = 0;
a636c635 13868
44c69747
LK
13869 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13870 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13871 network = argv[idx]->arg;
44c69747 13872 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13873 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13874 network = argv[idx]->arg;
44c69747
LK
13875 prefix_check = 1;
13876 } else {
d62a17ae 13877 vty_out(vty, "Unable to figure out Network\n");
13878 return CMD_WARNING;
13879 }
44c69747
LK
13880 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13881 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13882 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13883}
13884
114fc229 13885static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13886 struct bgp_table *table, int *header1,
13887 int *header2, json_object *json,
13888 json_object *json_scode,
13889 json_object *json_ocode, bool wide)
13890{
13891 uint64_t version = table ? table->version : 0;
13892
13893 if (*header1) {
13894 if (json) {
13895 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13896 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13897 "%pI4", &peer->bgp->router_id);
2f9bc755 13898 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13899 peer->bgp->default_local_pref);
13900 json_object_int_add(json, "localAS",
13901 peer->change_local_as
13902 ? peer->change_local_as
13903 : peer->local_as);
2f9bc755
DS
13904 json_object_object_add(json, "bgpStatusCodes",
13905 json_scode);
13906 json_object_object_add(json, "bgpOriginCodes",
13907 json_ocode);
13908 } else {
13909 vty_out(vty,
23d0a753
DA
13910 "BGP table version is %" PRIu64
13911 ", local router ID is %pI4, vrf id ",
114fc229
DA
13912 version, &peer->bgp->router_id);
13913 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13914 vty_out(vty, "%s", VRFID_NONE_STR);
13915 else
114fc229 13916 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13917 vty_out(vty, "\n");
13918 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13919 peer->bgp->default_local_pref);
13920 vty_out(vty, "local AS %u\n",
13921 peer->change_local_as ? peer->change_local_as
13922 : peer->local_as);
2f9bc755
DS
13923 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13924 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13925 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13926 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13927 }
13928 *header1 = 0;
13929 }
13930 if (*header2) {
13931 if (!json)
13932 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13933 : BGP_SHOW_HEADER));
13934 *header2 = 0;
13935 }
13936}
13937
d9478df0
TA
13938static void
13939show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13940 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13941 const char *rmap_name, json_object *json, json_object *json_ar,
13942 json_object *json_scode, json_object *json_ocode,
96c81f66 13943 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13944 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13945{
d62a17ae 13946 struct bgp_adj_in *ain;
13947 struct bgp_adj_out *adj;
9bcb3eef 13948 struct bgp_dest *dest;
d62a17ae 13949 struct bgp *bgp;
d62a17ae 13950 struct attr attr;
13951 int ret;
13952 struct update_subgroup *subgrp;
d62a17ae 13953 struct peer_af *paf;
f99def61 13954 bool route_filtered;
96f3485c
MK
13955 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13956 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13957 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13958 || (safi == SAFI_EVPN))
13959 ? true
13960 : false;
a636c635 13961
d62a17ae 13962 bgp = peer->bgp;
a636c635 13963
d62a17ae 13964 subgrp = peer_subgroup(peer, afi, safi);
13965
6392aaa6 13966 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13967 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13968 if (use_json) {
13969 json_object_int_add(json, "bgpTableVersion",
13970 table->version);
c949c771
DA
13971 json_object_string_addf(json, "bgpLocalRouterId",
13972 "%pI4", &bgp->router_id);
01eced22
AD
13973 json_object_int_add(json, "defaultLocPrf",
13974 bgp->default_local_pref);
114fc229
DA
13975 json_object_int_add(json, "localAS",
13976 peer->change_local_as
13977 ? peer->change_local_as
13978 : peer->local_as);
d62a17ae 13979 json_object_object_add(json, "bgpStatusCodes",
13980 json_scode);
13981 json_object_object_add(json, "bgpOriginCodes",
13982 json_ocode);
07d0c4ed
DA
13983 json_object_string_add(
13984 json, "bgpOriginatingDefaultNetwork",
13985 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13986 } else {
23d0a753
DA
13987 vty_out(vty,
13988 "BGP table version is %" PRIu64
13989 ", local router ID is %pI4, vrf id ",
13990 table->version, &bgp->router_id);
9df8b37c
PZ
13991 if (bgp->vrf_id == VRF_UNKNOWN)
13992 vty_out(vty, "%s", VRFID_NONE_STR);
13993 else
13994 vty_out(vty, "%u", bgp->vrf_id);
13995 vty_out(vty, "\n");
01eced22
AD
13996 vty_out(vty, "Default local pref %u, ",
13997 bgp->default_local_pref);
114fc229
DA
13998 vty_out(vty, "local AS %u\n",
13999 peer->change_local_as ? peer->change_local_as
14000 : peer->local_as);
d62a17ae 14001 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 14002 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 14003 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14004 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 14005
07d0c4ed
DA
14006 vty_out(vty, "Originating default network %s\n\n",
14007 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14008 }
d9478df0 14009 *header1 = 0;
d62a17ae 14010 }
a636c635 14011
9bcb3eef 14012 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14013 if (type == bgp_show_adj_route_received
14014 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14015 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14016 if (ain->peer != peer)
ea47320b 14017 continue;
6392aaa6 14018
114fc229 14019 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
14020 header2, json, json_scode,
14021 json_ocode, wide);
14022
14023 if ((safi == SAFI_MPLS_VPN)
14024 || (safi == SAFI_ENCAP)
14025 || (safi == SAFI_EVPN)) {
14026 if (use_json)
14027 json_object_string_add(
14028 json_ar, "rd", rd_str);
14029 else if (show_rd && rd_str) {
14030 vty_out(vty,
14031 "Route Distinguisher: %s\n",
14032 rd_str);
14033 show_rd = false;
14034 }
14035 }
6392aaa6 14036
6f4f49b2 14037 attr = *ain->attr;
f99def61
AD
14038 route_filtered = false;
14039
14040 /* Filter prefix using distribute list,
14041 * filter list or prefix list
14042 */
b54892e0 14043 const struct prefix *rn_p =
9bcb3eef 14044 bgp_dest_get_prefix(dest);
b54892e0
DS
14045 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14046 safi))
14047 == FILTER_DENY)
f99def61
AD
14048 route_filtered = true;
14049
14050 /* Filter prefix using route-map */
b54892e0
DS
14051 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14052 safi, rmap_name, NULL,
14053 0, NULL);
6392aaa6 14054
13c8e163
AD
14055 if (type == bgp_show_adj_route_filtered &&
14056 !route_filtered && ret != RMAP_DENY) {
d498917e 14057 bgp_attr_flush(&attr);
6392aaa6 14058 continue;
d62a17ae 14059 }
6392aaa6 14060
d9478df0
TA
14061 if (type == bgp_show_adj_route_received
14062 && (route_filtered || ret == RMAP_DENY))
14063 (*filtered_count)++;
6392aaa6 14064
7d3cae70 14065 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 14066 use_json, json_ar, wide);
d498917e 14067 bgp_attr_flush(&attr);
d9478df0 14068 (*output_count)++;
d62a17ae 14069 }
6392aaa6 14070 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14071 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14072 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14073 if (paf->peer != peer || !adj->attr)
924c3f6a 14074 continue;
d62a17ae 14075
114fc229 14076 show_adj_route_header(vty, peer, table,
d9478df0
TA
14077 header1, header2,
14078 json, json_scode,
14079 json_ocode, wide);
d62a17ae 14080
b54892e0 14081 const struct prefix *rn_p =
9bcb3eef 14082 bgp_dest_get_prefix(dest);
b54892e0 14083
6f4f49b2 14084 attr = *adj->attr;
b755861b 14085 ret = bgp_output_modifier(
b54892e0 14086 peer, rn_p, &attr, afi, safi,
b755861b 14087 rmap_name);
f46d8e1e 14088
b755861b 14089 if (ret != RMAP_DENY) {
d9478df0
TA
14090 if ((safi == SAFI_MPLS_VPN)
14091 || (safi == SAFI_ENCAP)
14092 || (safi == SAFI_EVPN)) {
14093 if (use_json)
14094 json_object_string_add(
14095 json_ar,
14096 "rd",
14097 rd_str);
14098 else if (show_rd
14099 && rd_str) {
14100 vty_out(vty,
14101 "Route Distinguisher: %s\n",
14102 rd_str);
14103 show_rd = false;
14104 }
14105 }
b54892e0 14106 route_vty_out_tmp(
7d3cae70
DA
14107 vty, dest, rn_p, &attr,
14108 safi, use_json, json_ar,
ae248832 14109 wide);
d9478df0 14110 (*output_count)++;
b755861b 14111 } else {
d9478df0 14112 (*filtered_count)++;
a2addae8 14113 }
b755861b 14114
d498917e 14115 bgp_attr_flush(&attr);
924c3f6a 14116 }
f20ce998
DS
14117 } else if (type == bgp_show_adj_route_bestpath) {
14118 struct bgp_path_info *pi;
14119
114fc229
DA
14120 show_adj_route_header(vty, peer, table, header1,
14121 header2, json, json_scode,
14122 json_ocode, wide);
f20ce998
DS
14123
14124 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14125 pi = pi->next) {
14126 if (pi->peer != peer)
14127 continue;
14128
14129 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14130 continue;
14131
7d3cae70 14132 route_vty_out_tmp(vty, dest,
f20ce998
DS
14133 bgp_dest_get_prefix(dest),
14134 pi->attr, safi, use_json,
14135 json_ar, wide);
d9478df0 14136 (*output_count)++;
f20ce998 14137 }
d62a17ae 14138 }
14139 }
a636c635 14140}
2a71e9ce 14141
d62a17ae 14142static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14143 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14144 const char *rmap_name, uint16_t show_flags)
0b16f239 14145{
d9478df0
TA
14146 struct bgp *bgp;
14147 struct bgp_table *table;
d62a17ae 14148 json_object *json = NULL;
d9478df0
TA
14149 json_object *json_scode = NULL;
14150 json_object *json_ocode = NULL;
14151 json_object *json_ar = NULL;
96f3485c 14152 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14153
d9478df0
TA
14154 /* Init BGP headers here so they're only displayed once
14155 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14156 */
14157 int header1 = 1;
14158 int header2 = 1;
14159
14160 /*
14161 * Initialize variables for each RD
14162 * All prefixes under an RD is aggregated within "json_routes"
14163 */
14164 char rd_str[BUFSIZ] = {0};
14165 json_object *json_routes = NULL;
14166
14167
14168 /* For 2-tier tables, prefix counts need to be
14169 * maintained across multiple runs of show_adj_route()
14170 */
14171 unsigned long output_count_per_rd;
14172 unsigned long filtered_count_per_rd;
14173 unsigned long output_count = 0;
14174 unsigned long filtered_count = 0;
14175
14176 if (use_json) {
d62a17ae 14177 json = json_object_new_object();
d9478df0
TA
14178 json_ar = json_object_new_object();
14179 json_scode = json_object_new_object();
14180 json_ocode = json_object_new_object();
14181
14182 json_object_string_add(json_scode, "suppressed", "s");
14183 json_object_string_add(json_scode, "damped", "d");
14184 json_object_string_add(json_scode, "history", "h");
14185 json_object_string_add(json_scode, "valid", "*");
14186 json_object_string_add(json_scode, "best", ">");
14187 json_object_string_add(json_scode, "multipath", "=");
14188 json_object_string_add(json_scode, "internal", "i");
14189 json_object_string_add(json_scode, "ribFailure", "r");
14190 json_object_string_add(json_scode, "stale", "S");
14191 json_object_string_add(json_scode, "removed", "R");
14192
14193 json_object_string_add(json_ocode, "igp", "i");
14194 json_object_string_add(json_ocode, "egp", "e");
14195 json_object_string_add(json_ocode, "incomplete", "?");
14196 }
0b16f239 14197
d62a17ae 14198 if (!peer || !peer->afc[afi][safi]) {
14199 if (use_json) {
14200 json_object_string_add(
14201 json, "warning",
14202 "No such neighbor or address family");
14203 vty_out(vty, "%s\n", json_object_to_json_string(json));
14204 json_object_free(json);
690c3134
MW
14205 json_object_free(json_ar);
14206 json_object_free(json_scode);
14207 json_object_free(json_ocode);
d62a17ae 14208 } else
14209 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14210
d62a17ae 14211 return CMD_WARNING;
14212 }
14213
6392aaa6
PM
14214 if ((type == bgp_show_adj_route_received
14215 || type == bgp_show_adj_route_filtered)
d62a17ae 14216 && !CHECK_FLAG(peer->af_flags[afi][safi],
14217 PEER_FLAG_SOFT_RECONFIG)) {
14218 if (use_json) {
14219 json_object_string_add(
14220 json, "warning",
14221 "Inbound soft reconfiguration not enabled");
14222 vty_out(vty, "%s\n", json_object_to_json_string(json));
14223 json_object_free(json);
690c3134
MW
14224 json_object_free(json_ar);
14225 json_object_free(json_scode);
14226 json_object_free(json_ocode);
d62a17ae 14227 } else
14228 vty_out(vty,
14229 "%% Inbound soft reconfiguration not enabled\n");
14230
14231 return CMD_WARNING;
14232 }
0b16f239 14233
d9478df0
TA
14234 bgp = peer->bgp;
14235
14236 /* labeled-unicast routes live in the unicast table */
14237 if (safi == SAFI_LABELED_UNICAST)
14238 table = bgp->rib[afi][SAFI_UNICAST];
14239 else
14240 table = bgp->rib[afi][safi];
14241
14242 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14243 || (safi == SAFI_EVPN)) {
14244
14245 struct bgp_dest *dest;
14246
14247 for (dest = bgp_table_top(table); dest;
14248 dest = bgp_route_next(dest)) {
14249 table = bgp_dest_get_bgp_table_info(dest);
14250 if (!table)
14251 continue;
14252
14253 output_count_per_rd = 0;
14254 filtered_count_per_rd = 0;
14255
14256 if (use_json)
14257 json_routes = json_object_new_object();
14258
14259 const struct prefix_rd *prd;
14260 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14261 dest);
14262
14263 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14264
14265 show_adj_route(vty, peer, table, afi, safi, type,
14266 rmap_name, json, json_routes, json_scode,
14267 json_ocode, show_flags, &header1,
14268 &header2, rd_str, &output_count_per_rd,
14269 &filtered_count_per_rd);
14270
14271 /* Don't include an empty RD in the output! */
14272 if (json_routes && (output_count_per_rd > 0))
14273 json_object_object_add(json_ar, rd_str,
14274 json_routes);
14275
14276 output_count += output_count_per_rd;
14277 filtered_count += filtered_count_per_rd;
14278 }
14279 } else
14280 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14281 json, json_ar, json_scode, json_ocode,
14282 show_flags, &header1, &header2, rd_str,
14283 &output_count, &filtered_count);
14284
14285 if (use_json) {
c1984955
TA
14286 if (type == bgp_show_adj_route_advertised)
14287 json_object_object_add(json, "advertisedRoutes",
14288 json_ar);
14289 else
14290 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14291 json_object_int_add(json, "totalPrefixCounter", output_count);
14292 json_object_int_add(json, "filteredPrefixCounter",
14293 filtered_count);
14294
690c3134
MW
14295 /*
14296 * These fields only give up ownership to `json` when `header1`
14297 * is used (set to zero). See code in `show_adj_route` and
14298 * `show_adj_route_header`.
14299 */
14300 if (header1 == 1) {
d9478df0
TA
14301 json_object_free(json_scode);
14302 json_object_free(json_ocode);
14303 }
14304
75eeda93 14305 vty_json(vty, json);
d9478df0
TA
14306 } else if (output_count > 0) {
14307 if (filtered_count > 0)
14308 vty_out(vty,
14309 "\nTotal number of prefixes %ld (%ld filtered)\n",
14310 output_count, filtered_count);
14311 else
14312 vty_out(vty, "\nTotal number of prefixes %ld\n",
14313 output_count);
14314 }
0b16f239 14315
d62a17ae 14316 return CMD_SUCCESS;
a636c635 14317}
50ef26d4 14318
f20ce998
DS
14319DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14320 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14321 "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]",
14322 SHOW_STR
14323 IP_STR
14324 BGP_STR
14325 BGP_INSTANCE_HELP_STR
14326 BGP_AFI_HELP_STR
14327 BGP_SAFI_WITH_LABEL_HELP_STR
14328 "Detailed information on TCP and BGP neighbor connections\n"
14329 "Neighbor to display information about\n"
14330 "Neighbor to display information about\n"
14331 "Neighbor on BGP configured interface\n"
14332 "Display the routes selected by best path\n"
14333 JSON_STR
14334 "Increase table width for longer prefixes\n")
14335{
14336 afi_t afi = AFI_IP6;
14337 safi_t safi = SAFI_UNICAST;
14338 char *rmap_name = NULL;
14339 char *peerstr = NULL;
14340 struct bgp *bgp = NULL;
14341 struct peer *peer;
14342 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14343 int idx = 0;
96c81f66 14344 uint16_t show_flags = 0;
96f3485c
MK
14345
14346 if (uj)
14347 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14348
14349 if (wide)
14350 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14351
14352 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14353 &bgp, uj);
14354
14355 if (!idx)
14356 return CMD_WARNING;
14357
14358 argv_find(argv, argc, "neighbors", &idx);
14359 peerstr = argv[++idx]->arg;
14360
14361 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14362 if (!peer)
14363 return CMD_WARNING;
14364
96f3485c
MK
14365 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14366 show_flags);
f20ce998
DS
14367}
14368
ae248832 14369DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14370 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14371 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [json$uj | wide$wide]",
718e3744 14372 SHOW_STR
14373 IP_STR
14374 BGP_STR
a636c635 14375 BGP_INSTANCE_HELP_STR
7395a2c9 14376 BGP_AFI_HELP_STR
4dd6177e 14377 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14378 "Display the entries for all address families\n"
718e3744 14379 "Detailed information on TCP and BGP neighbor connections\n"
14380 "Neighbor to display information about\n"
14381 "Neighbor to display information about\n"
91d37724 14382 "Neighbor on BGP configured interface\n"
a636c635 14383 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14384 "Display the received routes from neighbor\n"
14385 "Display the filtered routes received from neighbor\n"
a636c635
DW
14386 "Route-map to modify the attributes\n"
14387 "Name of the route map\n"
ae248832
MK
14388 JSON_STR
14389 "Increase table width for longer prefixes\n")
718e3744 14390{
d62a17ae 14391 afi_t afi = AFI_IP6;
14392 safi_t safi = SAFI_UNICAST;
d62a17ae 14393 char *peerstr = NULL;
d62a17ae 14394 struct bgp *bgp = NULL;
14395 struct peer *peer;
6392aaa6 14396 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14397 int idx = 0;
96f3485c 14398 bool first = true;
96c81f66 14399 uint16_t show_flags = 0;
75ce3b14
DA
14400 struct listnode *node;
14401 struct bgp *abgp;
6392aaa6 14402
96f3485c 14403 if (uj) {
d62a17ae 14404 argc--;
96f3485c
MK
14405 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14406 }
14407
14408 if (all) {
14409 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14410 if (argv_find(argv, argc, "ipv4", &idx))
14411 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14412
14413 if (argv_find(argv, argc, "ipv6", &idx))
14414 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14415 }
14416
14417 if (wide)
14418 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14419
9f049418
DS
14420 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14421 &bgp, uj);
14422 if (!idx)
14423 return CMD_WARNING;
14424
d62a17ae 14425 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14426 argv_find(argv, argc, "neighbors", &idx);
14427 peerstr = argv[++idx]->arg;
8c3deaae 14428
d62a17ae 14429 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14430 if (!peer)
14431 return CMD_WARNING;
856ca177 14432
d62a17ae 14433 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14434 type = bgp_show_adj_route_advertised;
14435 else if (argv_find(argv, argc, "received-routes", &idx))
14436 type = bgp_show_adj_route_received;
14437 else if (argv_find(argv, argc, "filtered-routes", &idx))
14438 type = bgp_show_adj_route_filtered;
14439
96f3485c 14440 if (!all)
70dd370f 14441 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14442 show_flags);
14443 if (uj)
14444 vty_out(vty, "{\n");
14445
14446 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14447 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14448 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14449 : AFI_IP6;
75ce3b14
DA
14450 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14451 FOREACH_SAFI (safi) {
14452 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14453 continue;
96f3485c 14454
75ce3b14
DA
14455 if (uj) {
14456 if (first)
14457 first = false;
14458 else
14459 vty_out(vty, ",\n");
14460 vty_out(vty, "\"%s\":",
14461 get_afi_safi_str(afi, safi,
14462 true));
14463 } else
14464 vty_out(vty,
14465 "\nFor address family: %s\n",
14466 get_afi_safi_str(afi, safi,
14467 false));
96f3485c 14468
75ce3b14 14469 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14470 route_map, show_flags);
75ce3b14 14471 }
96f3485c
MK
14472 }
14473 } else {
75ce3b14
DA
14474 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14475 FOREACH_AFI_SAFI (afi, safi) {
14476 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14477 continue;
96f3485c 14478
75ce3b14
DA
14479 if (uj) {
14480 if (first)
14481 first = false;
14482 else
14483 vty_out(vty, ",\n");
14484 vty_out(vty, "\"%s\":",
14485 get_afi_safi_str(afi, safi,
14486 true));
14487 } else
14488 vty_out(vty,
14489 "\nFor address family: %s\n",
14490 get_afi_safi_str(afi, safi,
14491 false));
96f3485c 14492
75ce3b14 14493 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14494 route_map, show_flags);
75ce3b14 14495 }
96f3485c
MK
14496 }
14497 }
14498 if (uj)
14499 vty_out(vty, "}\n");
14500
14501 return CMD_SUCCESS;
95cbbd2a
ML
14502}
14503
718e3744 14504DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14505 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14506 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14507 SHOW_STR
14508 IP_STR
14509 BGP_STR
d3120452 14510 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14511 BGP_AF_STR
14512 BGP_AF_STR
14513 BGP_AF_MODIFIER_STR
718e3744 14514 "Detailed information on TCP and BGP neighbor connections\n"
14515 "Neighbor to display information about\n"
14516 "Neighbor to display information about\n"
91d37724 14517 "Neighbor on BGP configured interface\n"
718e3744 14518 "Display information received from a BGP neighbor\n"
856ca177 14519 "Display the prefixlist filter\n"
9973d184 14520 JSON_STR)
718e3744 14521{
d62a17ae 14522 afi_t afi = AFI_IP6;
14523 safi_t safi = SAFI_UNICAST;
14524 char *peerstr = NULL;
d62a17ae 14525 char name[BUFSIZ];
d62a17ae 14526 struct peer *peer;
d3120452 14527 int count;
d62a17ae 14528 int idx = 0;
d3120452
IR
14529 struct bgp *bgp = NULL;
14530 bool uj = use_json(argc, argv);
14531
14532 if (uj)
14533 argc--;
14534
14535 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14536 &bgp, uj);
14537 if (!idx)
14538 return CMD_WARNING;
d62a17ae 14539
d62a17ae 14540 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14541 argv_find(argv, argc, "neighbors", &idx);
14542 peerstr = argv[++idx]->arg;
14543
d3120452
IR
14544 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14545 if (!peer)
14546 return CMD_WARNING;
718e3744 14547
4ced1a2c 14548 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14549 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14550 if (count) {
14551 if (!uj)
14552 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14553 get_afi_safi_str(afi, safi, false));
d62a17ae 14554 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14555 } else {
14556 if (uj)
14557 vty_out(vty, "{}\n");
14558 else
14559 vty_out(vty, "No functional output\n");
14560 }
718e3744 14561
d62a17ae 14562 return CMD_SUCCESS;
14563}
14564
14565static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14566 afi_t afi, safi_t safi,
9f049418 14567 enum bgp_show_type type, bool use_json)
d62a17ae 14568{
96c81f66 14569 uint16_t show_flags = 0;
96f3485c
MK
14570
14571 if (use_json)
14572 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14573
d62a17ae 14574 if (!peer || !peer->afc[afi][safi]) {
14575 if (use_json) {
14576 json_object *json_no = NULL;
14577 json_no = json_object_new_object();
14578 json_object_string_add(
14579 json_no, "warning",
14580 "No such neighbor or address family");
14581 vty_out(vty, "%s\n",
14582 json_object_to_json_string(json_no));
14583 json_object_free(json_no);
14584 } else
14585 vty_out(vty, "%% No such neighbor or address family\n");
14586 return CMD_WARNING;
14587 }
47fc97cc 14588
7daf25a3
TA
14589 /* labeled-unicast routes live in the unicast table */
14590 if (safi == SAFI_LABELED_UNICAST)
14591 safi = SAFI_UNICAST;
14592
1e2ce4f1
DS
14593 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14594 RPKI_NOT_BEING_USED);
718e3744 14595}
14596
dba3c1d3
PG
14597DEFUN (show_ip_bgp_flowspec_routes_detailed,
14598 show_ip_bgp_flowspec_routes_detailed_cmd,
14599 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14600 SHOW_STR
14601 IP_STR
14602 BGP_STR
14603 BGP_INSTANCE_HELP_STR
14604 BGP_AFI_HELP_STR
14605 "SAFI Flowspec\n"
14606 "Detailed information on flowspec entries\n"
14607 JSON_STR)
14608{
458c1475 14609 afi_t afi = AFI_IP6;
dba3c1d3
PG
14610 safi_t safi = SAFI_UNICAST;
14611 struct bgp *bgp = NULL;
14612 int idx = 0;
9f049418 14613 bool uj = use_json(argc, argv);
5be6fa9b 14614 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14615
96f3485c 14616 if (uj) {
9f049418 14617 argc--;
96f3485c
MK
14618 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14619 }
dba3c1d3
PG
14620
14621 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14622 &bgp, uj);
dba3c1d3
PG
14623 if (!idx)
14624 return CMD_WARNING;
14625
96f3485c 14626 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14627 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14628}
14629
718e3744 14630DEFUN (show_ip_bgp_neighbor_routes,
14631 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14632 "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 14633 SHOW_STR
14634 IP_STR
14635 BGP_STR
8386ac43 14636 BGP_INSTANCE_HELP_STR
4f280b15 14637 BGP_AFI_HELP_STR
4dd6177e 14638 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14639 "Detailed information on TCP and BGP neighbor connections\n"
14640 "Neighbor to display information about\n"
14641 "Neighbor to display information about\n"
91d37724 14642 "Neighbor on BGP configured interface\n"
2525cf39 14643 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14644 "Display the dampened routes received from neighbor\n"
14645 "Display routes learned from neighbor\n"
9973d184 14646 JSON_STR)
718e3744 14647{
d62a17ae 14648 char *peerstr = NULL;
14649 struct bgp *bgp = NULL;
14650 afi_t afi = AFI_IP6;
14651 safi_t safi = SAFI_UNICAST;
14652 struct peer *peer;
14653 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14654 int idx = 0;
9f049418
DS
14655 bool uj = use_json(argc, argv);
14656
14657 if (uj)
14658 argc--;
bb46e94f 14659
d62a17ae 14660 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14661 &bgp, uj);
d62a17ae 14662 if (!idx)
14663 return CMD_WARNING;
c493f2d8 14664
d62a17ae 14665 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14666 argv_find(argv, argc, "neighbors", &idx);
14667 peerstr = argv[++idx]->arg;
8c3deaae 14668
d62a17ae 14669 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14670 if (!peer)
d62a17ae 14671 return CMD_WARNING;
bb46e94f 14672
d62a17ae 14673 if (argv_find(argv, argc, "flap-statistics", &idx))
14674 sh_type = bgp_show_type_flap_neighbor;
14675 else if (argv_find(argv, argc, "dampened-routes", &idx))
14676 sh_type = bgp_show_type_damp_neighbor;
14677 else if (argv_find(argv, argc, "routes", &idx))
14678 sh_type = bgp_show_type_neighbor;
2525cf39 14679
d62a17ae 14680 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14681}
6b0655a2 14682
734b349e 14683struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14684
d62a17ae 14685struct bgp_distance {
14686 /* Distance value for the IP source prefix. */
d7c0a89a 14687 uint8_t distance;
718e3744 14688
d62a17ae 14689 /* Name of the access-list to be matched. */
14690 char *access_list;
718e3744 14691};
14692
4f280b15
LB
14693DEFUN (show_bgp_afi_vpn_rd_route,
14694 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14695 "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
14696 SHOW_STR
14697 BGP_STR
14698 BGP_AFI_HELP_STR
00e6edb9 14699 BGP_AF_MODIFIER_STR
4f280b15
LB
14700 "Display information for a route distinguisher\n"
14701 "Route Distinguisher\n"
a111dd97 14702 "All Route Distinguishers\n"
7395a2c9
DS
14703 "Network in the BGP routing table to display\n"
14704 "Network in the BGP routing table to display\n"
14705 JSON_STR)
4f280b15 14706{
d62a17ae 14707 int ret;
14708 struct prefix_rd prd;
14709 afi_t afi = AFI_MAX;
14710 int idx = 0;
4f280b15 14711
ff6566f3
DS
14712 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14713 vty_out(vty, "%% Malformed Address Family\n");
14714 return CMD_WARNING;
14715 }
14716
a111dd97
TA
14717 if (!strcmp(argv[5]->arg, "all"))
14718 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14719 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14720 RPKI_NOT_BEING_USED,
14721 use_json(argc, argv));
14722
d62a17ae 14723 ret = str2prefix_rd(argv[5]->arg, &prd);
14724 if (!ret) {
14725 vty_out(vty, "%% Malformed Route Distinguisher\n");
14726 return CMD_WARNING;
14727 }
ff6566f3 14728
d62a17ae 14729 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14730 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14731 use_json(argc, argv));
4f280b15
LB
14732}
14733
d62a17ae 14734static struct bgp_distance *bgp_distance_new(void)
718e3744 14735{
d62a17ae 14736 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14737}
14738
d62a17ae 14739static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14740{
d62a17ae 14741 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14742}
14743
585f1adc
IR
14744static int bgp_distance_set(struct vty *vty, const char *distance_str,
14745 const char *ip_str, const char *access_list_str)
718e3744 14746{
d62a17ae 14747 int ret;
585f1adc
IR
14748 afi_t afi;
14749 safi_t safi;
d62a17ae 14750 struct prefix p;
585f1adc 14751 uint8_t distance;
9bcb3eef 14752 struct bgp_dest *dest;
d62a17ae 14753 struct bgp_distance *bdistance;
718e3744 14754
585f1adc
IR
14755 afi = bgp_node_afi(vty);
14756 safi = bgp_node_safi(vty);
14757
d62a17ae 14758 ret = str2prefix(ip_str, &p);
14759 if (ret == 0) {
585f1adc 14760 vty_out(vty, "Malformed prefix\n");
d62a17ae 14761 return CMD_WARNING_CONFIG_FAILED;
14762 }
718e3744 14763
585f1adc
IR
14764 distance = atoi(distance_str);
14765
d62a17ae 14766 /* Get BGP distance node. */
9bcb3eef
DS
14767 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14768 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14769 if (bdistance)
9bcb3eef 14770 bgp_dest_unlock_node(dest);
ca2e160d 14771 else {
d62a17ae 14772 bdistance = bgp_distance_new();
9bcb3eef 14773 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14774 }
718e3744 14775
d62a17ae 14776 /* Set distance value. */
14777 bdistance->distance = distance;
718e3744 14778
d62a17ae 14779 /* Reset access-list configuration. */
e1b36e13 14780 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14781 if (access_list_str)
14782 bdistance->access_list =
14783 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14784
d62a17ae 14785 return CMD_SUCCESS;
718e3744 14786}
14787
585f1adc
IR
14788static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14789 const char *ip_str, const char *access_list_str)
718e3744 14790{
d62a17ae 14791 int ret;
585f1adc
IR
14792 afi_t afi;
14793 safi_t safi;
d62a17ae 14794 struct prefix p;
585f1adc 14795 int distance;
9bcb3eef 14796 struct bgp_dest *dest;
d62a17ae 14797 struct bgp_distance *bdistance;
718e3744 14798
585f1adc
IR
14799 afi = bgp_node_afi(vty);
14800 safi = bgp_node_safi(vty);
14801
d62a17ae 14802 ret = str2prefix(ip_str, &p);
14803 if (ret == 0) {
585f1adc 14804 vty_out(vty, "Malformed prefix\n");
d62a17ae 14805 return CMD_WARNING_CONFIG_FAILED;
14806 }
718e3744 14807
9bcb3eef
DS
14808 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14809 if (!dest) {
585f1adc 14810 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14811 return CMD_WARNING_CONFIG_FAILED;
14812 }
718e3744 14813
9bcb3eef 14814 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14815 distance = atoi(distance_str);
1f9a9fff 14816
d62a17ae 14817 if (bdistance->distance != distance) {
585f1adc 14818 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14819 bgp_dest_unlock_node(dest);
d62a17ae 14820 return CMD_WARNING_CONFIG_FAILED;
14821 }
718e3744 14822
0a22ddfb 14823 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14824 bgp_distance_free(bdistance);
718e3744 14825
9bcb3eef
DS
14826 bgp_dest_set_bgp_path_info(dest, NULL);
14827 bgp_dest_unlock_node(dest);
14828 bgp_dest_unlock_node(dest);
718e3744 14829
d62a17ae 14830 return CMD_SUCCESS;
718e3744 14831}
14832
718e3744 14833/* Apply BGP information to distance method. */
b8685f9b 14834uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14835 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14836{
9bcb3eef 14837 struct bgp_dest *dest;
801bb996 14838 struct prefix q = {0};
d62a17ae 14839 struct peer *peer;
14840 struct bgp_distance *bdistance;
14841 struct access_list *alist;
14842 struct bgp_static *bgp_static;
14843
14844 if (!bgp)
14845 return 0;
14846
40381db7 14847 peer = pinfo->peer;
d62a17ae 14848
7b7d48e5
DS
14849 if (pinfo->attr->distance)
14850 return pinfo->attr->distance;
14851
801bb996
CS
14852 /* Check source address.
14853 * Note: for aggregate route, peer can have unspec af type.
14854 */
14855 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14856 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14857 return 0;
14858
9bcb3eef
DS
14859 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14860 if (dest) {
14861 bdistance = bgp_dest_get_bgp_distance_info(dest);
14862 bgp_dest_unlock_node(dest);
d62a17ae 14863
14864 if (bdistance->access_list) {
14865 alist = access_list_lookup(afi, bdistance->access_list);
14866 if (alist
14867 && access_list_apply(alist, p) == FILTER_PERMIT)
14868 return bdistance->distance;
14869 } else
14870 return bdistance->distance;
718e3744 14871 }
718e3744 14872
d62a17ae 14873 /* Backdoor check. */
9bcb3eef
DS
14874 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14875 if (dest) {
14876 bgp_static = bgp_dest_get_bgp_static_info(dest);
14877 bgp_dest_unlock_node(dest);
718e3744 14878
d62a17ae 14879 if (bgp_static->backdoor) {
14880 if (bgp->distance_local[afi][safi])
14881 return bgp->distance_local[afi][safi];
14882 else
14883 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14884 }
718e3744 14885 }
718e3744 14886
d62a17ae 14887 if (peer->sort == BGP_PEER_EBGP) {
14888 if (bgp->distance_ebgp[afi][safi])
14889 return bgp->distance_ebgp[afi][safi];
14890 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14891 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14892 if (bgp->distance_ibgp[afi][safi])
14893 return bgp->distance_ibgp[afi][safi];
14894 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14895 } else {
14896 if (bgp->distance_local[afi][safi])
14897 return bgp->distance_local[afi][safi];
14898 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14899 }
718e3744 14900}
14901
a612fb77
DA
14902/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14903 * we should tell ZEBRA update the routes for a specific
14904 * AFI/SAFI to reflect changes in RIB.
14905 */
585f1adc
IR
14906static void bgp_announce_routes_distance_update(struct bgp *bgp,
14907 afi_t update_afi,
14908 safi_t update_safi)
a612fb77
DA
14909{
14910 afi_t afi;
14911 safi_t safi;
14912
14913 FOREACH_AFI_SAFI (afi, safi) {
14914 if (!bgp_fibupd_safi(safi))
14915 continue;
14916
8b54bc30
DA
14917 if (afi != update_afi && safi != update_safi)
14918 continue;
14919
14920 if (BGP_DEBUG(zebra, ZEBRA))
14921 zlog_debug(
14922 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14923 __func__, afi, safi);
14924 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14925 }
14926}
14927
585f1adc
IR
14928DEFUN (bgp_distance,
14929 bgp_distance_cmd,
14930 "distance bgp (1-255) (1-255) (1-255)",
14931 "Define an administrative distance\n"
14932 "BGP distance\n"
14933 "Distance for routes external to the AS\n"
14934 "Distance for routes internal to the AS\n"
14935 "Distance for local routes\n")
718e3744 14936{
585f1adc 14937 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14938 int idx_number = 2;
14939 int idx_number_2 = 3;
14940 int idx_number_3 = 4;
585f1adc
IR
14941 int distance_ebgp = atoi(argv[idx_number]->arg);
14942 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14943 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14944 afi_t afi;
14945 safi_t safi;
718e3744 14946
d62a17ae 14947 afi = bgp_node_afi(vty);
14948 safi = bgp_node_safi(vty);
718e3744 14949
585f1adc
IR
14950 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14951 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14952 || bgp->distance_local[afi][safi] != distance_local) {
14953 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14954 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14955 bgp->distance_local[afi][safi] = distance_local;
14956 bgp_announce_routes_distance_update(bgp, afi, safi);
14957 }
14958 return CMD_SUCCESS;
14959}
37a87b8f 14960
585f1adc
IR
14961DEFUN (no_bgp_distance,
14962 no_bgp_distance_cmd,
14963 "no distance bgp [(1-255) (1-255) (1-255)]",
14964 NO_STR
14965 "Define an administrative distance\n"
14966 "BGP distance\n"
14967 "Distance for routes external to the AS\n"
14968 "Distance for routes internal to the AS\n"
14969 "Distance for local routes\n")
718e3744 14970{
585f1adc 14971 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14972 afi_t afi;
14973 safi_t safi;
37a87b8f
CS
14974
14975 afi = bgp_node_afi(vty);
14976 safi = bgp_node_safi(vty);
14977
585f1adc
IR
14978 if (bgp->distance_ebgp[afi][safi] != 0
14979 || bgp->distance_ibgp[afi][safi] != 0
14980 || bgp->distance_local[afi][safi] != 0) {
14981 bgp->distance_ebgp[afi][safi] = 0;
14982 bgp->distance_ibgp[afi][safi] = 0;
14983 bgp->distance_local[afi][safi] = 0;
14984 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14985 }
585f1adc
IR
14986 return CMD_SUCCESS;
14987}
37a87b8f 14988
37a87b8f 14989
585f1adc
IR
14990DEFUN (bgp_distance_source,
14991 bgp_distance_source_cmd,
14992 "distance (1-255) A.B.C.D/M",
14993 "Define an administrative distance\n"
14994 "Administrative distance\n"
14995 "IP source prefix\n")
14996{
14997 int idx_number = 1;
14998 int idx_ipv4_prefixlen = 2;
14999 bgp_distance_set(vty, argv[idx_number]->arg,
15000 argv[idx_ipv4_prefixlen]->arg, NULL);
15001 return CMD_SUCCESS;
734b349e
MZ
15002}
15003
585f1adc
IR
15004DEFUN (no_bgp_distance_source,
15005 no_bgp_distance_source_cmd,
15006 "no distance (1-255) A.B.C.D/M",
15007 NO_STR
15008 "Define an administrative distance\n"
15009 "Administrative distance\n"
15010 "IP source prefix\n")
37a87b8f 15011{
585f1adc
IR
15012 int idx_number = 2;
15013 int idx_ipv4_prefixlen = 3;
15014 bgp_distance_unset(vty, argv[idx_number]->arg,
15015 argv[idx_ipv4_prefixlen]->arg, NULL);
15016 return CMD_SUCCESS;
37a87b8f
CS
15017}
15018
585f1adc
IR
15019DEFUN (bgp_distance_source_access_list,
15020 bgp_distance_source_access_list_cmd,
15021 "distance (1-255) A.B.C.D/M WORD",
15022 "Define an administrative distance\n"
15023 "Administrative distance\n"
15024 "IP source prefix\n"
15025 "Access list name\n")
37a87b8f 15026{
585f1adc
IR
15027 int idx_number = 1;
15028 int idx_ipv4_prefixlen = 2;
15029 int idx_word = 3;
15030 bgp_distance_set(vty, argv[idx_number]->arg,
15031 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15032 return CMD_SUCCESS;
15033}
718e3744 15034
585f1adc
IR
15035DEFUN (no_bgp_distance_source_access_list,
15036 no_bgp_distance_source_access_list_cmd,
15037 "no distance (1-255) A.B.C.D/M WORD",
15038 NO_STR
15039 "Define an administrative distance\n"
15040 "Administrative distance\n"
15041 "IP source prefix\n"
15042 "Access list name\n")
15043{
15044 int idx_number = 2;
15045 int idx_ipv4_prefixlen = 3;
15046 int idx_word = 4;
15047 bgp_distance_unset(vty, argv[idx_number]->arg,
15048 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15049 return CMD_SUCCESS;
15050}
37a87b8f 15051
585f1adc
IR
15052DEFUN (ipv6_bgp_distance_source,
15053 ipv6_bgp_distance_source_cmd,
15054 "distance (1-255) X:X::X:X/M",
15055 "Define an administrative distance\n"
15056 "Administrative distance\n"
15057 "IP source prefix\n")
15058{
15059 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15060 return CMD_SUCCESS;
15061}
7ebe9748 15062
585f1adc
IR
15063DEFUN (no_ipv6_bgp_distance_source,
15064 no_ipv6_bgp_distance_source_cmd,
15065 "no distance (1-255) X:X::X:X/M",
15066 NO_STR
15067 "Define an administrative distance\n"
15068 "Administrative distance\n"
15069 "IP source prefix\n")
15070{
15071 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15072 return CMD_SUCCESS;
15073}
37a87b8f 15074
585f1adc
IR
15075DEFUN (ipv6_bgp_distance_source_access_list,
15076 ipv6_bgp_distance_source_access_list_cmd,
15077 "distance (1-255) X:X::X:X/M WORD",
15078 "Define an administrative distance\n"
15079 "Administrative distance\n"
15080 "IP source prefix\n"
15081 "Access list name\n")
15082{
15083 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15084 return CMD_SUCCESS;
718e3744 15085}
15086
585f1adc
IR
15087DEFUN (no_ipv6_bgp_distance_source_access_list,
15088 no_ipv6_bgp_distance_source_access_list_cmd,
15089 "no distance (1-255) X:X::X:X/M WORD",
15090 NO_STR
15091 "Define an administrative distance\n"
15092 "Administrative distance\n"
15093 "IP source prefix\n"
15094 "Access list name\n")
718e3744 15095{
585f1adc
IR
15096 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15097 return CMD_SUCCESS;
15098}
37a87b8f 15099
585f1adc
IR
15100DEFUN (bgp_damp_set,
15101 bgp_damp_set_cmd,
a30fec23 15102 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15103 "BGP Specific commands\n"
15104 "Enable route-flap dampening\n"
15105 "Half-life time for the penalty\n"
15106 "Value to start reusing a route\n"
15107 "Value to start suppressing a route\n"
15108 "Maximum duration to suppress a stable route\n")
15109{
15110 VTY_DECLVAR_CONTEXT(bgp, bgp);
15111 int idx_half_life = 2;
15112 int idx_reuse = 3;
15113 int idx_suppress = 4;
15114 int idx_max_suppress = 5;
37a87b8f
CS
15115 int half = DEFAULT_HALF_LIFE * 60;
15116 int reuse = DEFAULT_REUSE;
15117 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15118 int max = 4 * half;
15119
15120 if (argc == 6) {
15121 half = atoi(argv[idx_half_life]->arg) * 60;
15122 reuse = atoi(argv[idx_reuse]->arg);
15123 suppress = atoi(argv[idx_suppress]->arg);
15124 max = atoi(argv[idx_max_suppress]->arg) * 60;
15125 } else if (argc == 3) {
15126 half = atoi(argv[idx_half_life]->arg) * 60;
15127 max = 4 * half;
15128 }
15129
15130 /*
15131 * These can't be 0 but our SA doesn't understand the
15132 * way our cli is constructed
15133 */
15134 assert(reuse);
15135 assert(half);
15136 if (suppress < reuse) {
15137 vty_out(vty,
15138 "Suppress value cannot be less than reuse value \n");
15139 return 0;
15140 }
15141
15142 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15143 reuse, suppress, max);
15144}
15145
15146DEFUN (bgp_damp_unset,
15147 bgp_damp_unset_cmd,
a30fec23 15148 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15149 NO_STR
15150 "BGP Specific commands\n"
15151 "Enable route-flap dampening\n"
15152 "Half-life time for the penalty\n"
15153 "Value to start reusing a route\n"
15154 "Value to start suppressing a route\n"
15155 "Maximum duration to suppress a stable route\n")
15156{
15157 VTY_DECLVAR_CONTEXT(bgp, bgp);
15158 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15159}
15160
718e3744 15161/* Display specified route of BGP table. */
d62a17ae 15162static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15163 const char *ip_str, afi_t afi, safi_t safi,
15164 struct prefix_rd *prd, int prefix_check)
15165{
15166 int ret;
15167 struct prefix match;
9bcb3eef
DS
15168 struct bgp_dest *dest;
15169 struct bgp_dest *rm;
40381db7
DS
15170 struct bgp_path_info *pi;
15171 struct bgp_path_info *pi_temp;
d62a17ae 15172 struct bgp *bgp;
15173 struct bgp_table *table;
15174
15175 /* BGP structure lookup. */
15176 if (view_name) {
15177 bgp = bgp_lookup_by_name(view_name);
15178 if (bgp == NULL) {
15179 vty_out(vty, "%% Can't find BGP instance %s\n",
15180 view_name);
15181 return CMD_WARNING;
15182 }
15183 } else {
15184 bgp = bgp_get_default();
15185 if (bgp == NULL) {
15186 vty_out(vty, "%% No BGP process is configured\n");
15187 return CMD_WARNING;
15188 }
718e3744 15189 }
718e3744 15190
d62a17ae 15191 /* Check IP address argument. */
15192 ret = str2prefix(ip_str, &match);
15193 if (!ret) {
15194 vty_out(vty, "%% address is malformed\n");
15195 return CMD_WARNING;
15196 }
718e3744 15197
d62a17ae 15198 match.family = afi2family(afi);
15199
15200 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15201 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15202 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15203 dest = bgp_route_next(dest)) {
15204 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15205
9bcb3eef 15206 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15207 continue;
9bcb3eef 15208 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15209 if (!table)
ea47320b 15210 continue;
4953391b
DA
15211 rm = bgp_node_match(table, &match);
15212 if (rm == NULL)
ea47320b 15213 continue;
d62a17ae 15214
9bcb3eef 15215 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15216
ea47320b 15217 if (!prefix_check
b54892e0 15218 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15219 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15220 while (pi) {
15221 if (pi->extra && pi->extra->damp_info) {
15222 pi_temp = pi->next;
ea47320b 15223 bgp_damp_info_free(
19971c9a 15224 pi->extra->damp_info,
5c8846f6 15225 1, afi, safi);
40381db7 15226 pi = pi_temp;
ea47320b 15227 } else
40381db7 15228 pi = pi->next;
d62a17ae 15229 }
ea47320b
DL
15230 }
15231
9bcb3eef 15232 bgp_dest_unlock_node(rm);
d62a17ae 15233 }
15234 } else {
4953391b
DA
15235 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15236 if (dest != NULL) {
9bcb3eef 15237 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15238
d62a17ae 15239 if (!prefix_check
9bcb3eef
DS
15240 || dest_p->prefixlen == match.prefixlen) {
15241 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15242 while (pi) {
15243 if (pi->extra && pi->extra->damp_info) {
15244 pi_temp = pi->next;
d62a17ae 15245 bgp_damp_info_free(
19971c9a 15246 pi->extra->damp_info,
5c8846f6 15247 1, afi, safi);
40381db7 15248 pi = pi_temp;
d62a17ae 15249 } else
40381db7 15250 pi = pi->next;
d62a17ae 15251 }
15252 }
15253
9bcb3eef 15254 bgp_dest_unlock_node(dest);
d62a17ae 15255 }
15256 }
718e3744 15257
d62a17ae 15258 return CMD_SUCCESS;
718e3744 15259}
15260
15261DEFUN (clear_ip_bgp_dampening,
15262 clear_ip_bgp_dampening_cmd,
15263 "clear ip bgp dampening",
15264 CLEAR_STR
15265 IP_STR
15266 BGP_STR
15267 "Clear route flap dampening information\n")
15268{
b4f7f45b 15269 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15270 return CMD_SUCCESS;
718e3744 15271}
15272
15273DEFUN (clear_ip_bgp_dampening_prefix,
15274 clear_ip_bgp_dampening_prefix_cmd,
15275 "clear ip bgp dampening A.B.C.D/M",
15276 CLEAR_STR
15277 IP_STR
15278 BGP_STR
15279 "Clear route flap dampening information\n"
0c7b1b01 15280 "IPv4 prefix\n")
718e3744 15281{
d62a17ae 15282 int idx_ipv4_prefixlen = 4;
15283 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15284 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15285}
15286
15287DEFUN (clear_ip_bgp_dampening_address,
15288 clear_ip_bgp_dampening_address_cmd,
15289 "clear ip bgp dampening A.B.C.D",
15290 CLEAR_STR
15291 IP_STR
15292 BGP_STR
15293 "Clear route flap dampening information\n"
15294 "Network to clear damping information\n")
15295{
d62a17ae 15296 int idx_ipv4 = 4;
15297 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15298 SAFI_UNICAST, NULL, 0);
718e3744 15299}
15300
15301DEFUN (clear_ip_bgp_dampening_address_mask,
15302 clear_ip_bgp_dampening_address_mask_cmd,
15303 "clear ip bgp dampening A.B.C.D A.B.C.D",
15304 CLEAR_STR
15305 IP_STR
15306 BGP_STR
15307 "Clear route flap dampening information\n"
15308 "Network to clear damping information\n"
15309 "Network mask\n")
15310{
d62a17ae 15311 int idx_ipv4 = 4;
15312 int idx_ipv4_2 = 5;
15313 int ret;
15314 char prefix_str[BUFSIZ];
718e3744 15315
d62a17ae 15316 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15317 prefix_str, sizeof(prefix_str));
d62a17ae 15318 if (!ret) {
15319 vty_out(vty, "%% Inconsistent address and mask\n");
15320 return CMD_WARNING;
15321 }
718e3744 15322
d62a17ae 15323 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15324 NULL, 0);
718e3744 15325}
6b0655a2 15326
e3b78da8 15327static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15328{
15329 struct vty *vty = arg;
e3b78da8 15330 struct peer *peer = bucket->data;
825d9834 15331
47e12884 15332 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15333}
15334
2a0e69ae
DS
15335DEFUN (show_bgp_listeners,
15336 show_bgp_listeners_cmd,
15337 "show bgp listeners",
15338 SHOW_STR
15339 BGP_STR
15340 "Display Listen Sockets and who created them\n")
15341{
15342 bgp_dump_listener_info(vty);
15343
15344 return CMD_SUCCESS;
15345}
15346
825d9834
DS
15347DEFUN (show_bgp_peerhash,
15348 show_bgp_peerhash_cmd,
15349 "show bgp peerhash",
15350 SHOW_STR
15351 BGP_STR
15352 "Display information about the BGP peerhash\n")
15353{
15354 struct list *instances = bm->bgp;
15355 struct listnode *node;
15356 struct bgp *bgp;
15357
15358 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15359 vty_out(vty, "BGP: %s\n", bgp->name);
15360 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15361 vty);
15362 }
15363
15364 return CMD_SUCCESS;
15365}
15366
587ff0fd 15367/* also used for encap safi */
2b791107
DL
15368static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15369 afi_t afi, safi_t safi)
d62a17ae 15370{
9bcb3eef
DS
15371 struct bgp_dest *pdest;
15372 struct bgp_dest *dest;
d62a17ae 15373 struct bgp_table *table;
b54892e0
DS
15374 const struct prefix *p;
15375 const struct prefix_rd *prd;
d62a17ae 15376 struct bgp_static *bgp_static;
15377 mpls_label_t label;
d62a17ae 15378
15379 /* Network configuration. */
9bcb3eef
DS
15380 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15381 pdest = bgp_route_next(pdest)) {
15382 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15383 if (!table)
ea47320b 15384 continue;
d62a17ae 15385
9bcb3eef
DS
15386 for (dest = bgp_table_top(table); dest;
15387 dest = bgp_route_next(dest)) {
15388 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15389 if (bgp_static == NULL)
ea47320b 15390 continue;
d62a17ae 15391
9bcb3eef
DS
15392 p = bgp_dest_get_prefix(dest);
15393 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15394 pdest);
d62a17ae 15395
ea47320b 15396 /* "network" configuration display. */
ea47320b
DL
15397 label = decode_label(&bgp_static->label);
15398
c4f64ea9 15399 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15400 if (safi == SAFI_MPLS_VPN)
15401 vty_out(vty, " label %u", label);
15402
15403 if (bgp_static->rmap.name)
15404 vty_out(vty, " route-map %s",
15405 bgp_static->rmap.name);
e2a86ad9
DS
15406
15407 if (bgp_static->backdoor)
15408 vty_out(vty, " backdoor");
15409
ea47320b
DL
15410 vty_out(vty, "\n");
15411 }
15412 }
d62a17ae 15413}
15414
2b791107
DL
15415static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15416 afi_t afi, safi_t safi)
d62a17ae 15417{
9bcb3eef
DS
15418 struct bgp_dest *pdest;
15419 struct bgp_dest *dest;
d62a17ae 15420 struct bgp_table *table;
b54892e0
DS
15421 const struct prefix *p;
15422 const struct prefix_rd *prd;
d62a17ae 15423 struct bgp_static *bgp_static;
ff44f570 15424 char buf[PREFIX_STRLEN * 2];
d62a17ae 15425 char buf2[SU_ADDRSTRLEN];
5f933e1e 15426 char esi_buf[ESI_STR_LEN];
d62a17ae 15427
15428 /* Network configuration. */
9bcb3eef
DS
15429 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15430 pdest = bgp_route_next(pdest)) {
15431 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15432 if (!table)
ea47320b 15433 continue;
d62a17ae 15434
9bcb3eef
DS
15435 for (dest = bgp_table_top(table); dest;
15436 dest = bgp_route_next(dest)) {
15437 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15438 if (bgp_static == NULL)
ea47320b 15439 continue;
d62a17ae 15440
ea47320b 15441 char *macrouter = NULL;
d62a17ae 15442
ea47320b
DL
15443 if (bgp_static->router_mac)
15444 macrouter = prefix_mac2str(
15445 bgp_static->router_mac, NULL, 0);
15446 if (bgp_static->eth_s_id)
0a50c248
AK
15447 esi_to_str(bgp_static->eth_s_id,
15448 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15449 p = bgp_dest_get_prefix(dest);
15450 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15451
ea47320b 15452 /* "network" configuration display. */
197cb530
PG
15453 if (p->u.prefix_evpn.route_type == 5) {
15454 char local_buf[PREFIX_STRLEN];
3714a385 15455 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15456 struct prefix_evpn *)p)
15457 ? AF_INET
15458 : AF_INET6;
3714a385 15459 inet_ntop(family,
15460 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15461 local_buf, PREFIX_STRLEN);
772270f3
QY
15462 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15463 p->u.prefix_evpn.prefix_addr
15464 .ip_prefix_length);
197cb530
PG
15465 } else {
15466 prefix2str(p, buf, sizeof(buf));
15467 }
ea47320b 15468
a4d82a8a
PZ
15469 if (bgp_static->gatewayIp.family == AF_INET
15470 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15471 inet_ntop(bgp_static->gatewayIp.family,
15472 &bgp_static->gatewayIp.u.prefix, buf2,
15473 sizeof(buf2));
ea47320b 15474 vty_out(vty,
c4f64ea9
DA
15475 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15476 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15477 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15478 macrouter);
15479
0a22ddfb 15480 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15481 }
15482 }
3da6fcd5
PG
15483}
15484
718e3744 15485/* Configuration of static route announcement and aggregate
15486 information. */
2b791107
DL
15487void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15488 safi_t safi)
d62a17ae 15489{
9bcb3eef 15490 struct bgp_dest *dest;
b54892e0 15491 const struct prefix *p;
d62a17ae 15492 struct bgp_static *bgp_static;
15493 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15494
2b791107
DL
15495 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15496 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15497 return;
15498 }
d62a17ae 15499
2b791107
DL
15500 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15501 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15502 return;
15503 }
d62a17ae 15504
15505 /* Network configuration. */
9bcb3eef
DS
15506 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15507 dest = bgp_route_next(dest)) {
15508 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15509 if (bgp_static == NULL)
ea47320b 15510 continue;
d62a17ae 15511
9bcb3eef 15512 p = bgp_dest_get_prefix(dest);
d62a17ae 15513
8228a9a7 15514 vty_out(vty, " network %pFX", p);
d62a17ae 15515
ea47320b
DL
15516 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15517 vty_out(vty, " label-index %u",
15518 bgp_static->label_index);
d62a17ae 15519
ea47320b
DL
15520 if (bgp_static->rmap.name)
15521 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15522
15523 if (bgp_static->backdoor)
15524 vty_out(vty, " backdoor");
718e3744 15525
ea47320b
DL
15526 vty_out(vty, "\n");
15527 }
15528
d62a17ae 15529 /* Aggregate-address configuration. */
9bcb3eef
DS
15530 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15531 dest = bgp_route_next(dest)) {
15532 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15533 if (bgp_aggregate == NULL)
ea47320b 15534 continue;
d62a17ae 15535
9bcb3eef 15536 p = bgp_dest_get_prefix(dest);
d62a17ae 15537
8228a9a7 15538 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15539
ea47320b
DL
15540 if (bgp_aggregate->as_set)
15541 vty_out(vty, " as-set");
d62a17ae 15542
ea47320b
DL
15543 if (bgp_aggregate->summary_only)
15544 vty_out(vty, " summary-only");
718e3744 15545
20894f50
DA
15546 if (bgp_aggregate->rmap.name)
15547 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15548
229757f1
DA
15549 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15550 vty_out(vty, " origin %s",
15551 bgp_origin2str(bgp_aggregate->origin));
15552
6aabb15d
RZ
15553 if (bgp_aggregate->match_med)
15554 vty_out(vty, " matching-MED-only");
15555
365ab2e7
RZ
15556 if (bgp_aggregate->suppress_map_name)
15557 vty_out(vty, " suppress-map %s",
15558 bgp_aggregate->suppress_map_name);
15559
ea47320b
DL
15560 vty_out(vty, "\n");
15561 }
d62a17ae 15562}
734b349e 15563
2b791107 15564void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15565 safi_t safi)
d62a17ae 15566{
9bcb3eef 15567 struct bgp_dest *dest;
d62a17ae 15568 struct bgp_distance *bdistance;
15569
15570 /* Distance configuration. */
15571 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15572 && bgp->distance_local[afi][safi]
15573 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15574 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15575 || bgp->distance_local[afi][safi]
15576 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15577 vty_out(vty, " distance bgp %d %d %d\n",
15578 bgp->distance_ebgp[afi][safi],
15579 bgp->distance_ibgp[afi][safi],
15580 bgp->distance_local[afi][safi]);
15581 }
734b349e 15582
9bcb3eef
DS
15583 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15584 dest = bgp_route_next(dest)) {
15585 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15586 if (bdistance != NULL)
56ca3b5b 15587 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15588 bdistance->distance, dest,
d62a17ae 15589 bdistance->access_list ? bdistance->access_list
15590 : "");
ca2e160d 15591 }
718e3744 15592}
15593
15594/* Allocate routing table structure and install commands. */
d62a17ae 15595void bgp_route_init(void)
15596{
15597 afi_t afi;
15598 safi_t safi;
15599
15600 /* Init BGP distance table. */
05c7a1cc 15601 FOREACH_AFI_SAFI (afi, safi)
960035b2 15602 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15603
15604 /* IPv4 BGP commands. */
15605 install_element(BGP_NODE, &bgp_table_map_cmd);
15606 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15607 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15608
554b3b10 15609 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15610
15611 /* IPv4 unicast configuration. */
15612 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15613 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15614 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15615
554b3b10 15616 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15617
15618 /* IPv4 multicast configuration. */
15619 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15620 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15621 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15622 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15623
15624 /* IPv4 labeled-unicast configuration. */
fb985e0c 15625 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15626 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15627
d62a17ae 15628 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15629 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15630 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15631 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15632 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15633 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15634 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15635 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15636
15637 install_element(VIEW_NODE,
15638 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15639 install_element(VIEW_NODE,
15640 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15641 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15642 install_element(VIEW_NODE,
15643 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15644#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15645 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15646#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15647 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15648 install_element(VIEW_NODE,
44c69747 15649 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15650
d62a17ae 15651 /* BGP dampening clear commands */
15652 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15653 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15654
d62a17ae 15655 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15656 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15657
15658 /* prefix count */
15659 install_element(ENABLE_NODE,
15660 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15661#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15662 install_element(ENABLE_NODE,
15663 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15664#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15665
d62a17ae 15666 /* New config IPv6 BGP commands. */
15667 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15668 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15669 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15670
554b3b10 15671 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15672
15673 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15674
fb985e0c
DA
15675 /* IPv6 labeled unicast address family. */
15676 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15677 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15678
d62a17ae 15679 install_element(BGP_NODE, &bgp_distance_cmd);
15680 install_element(BGP_NODE, &no_bgp_distance_cmd);
15681 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15682 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15683 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15684 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15685 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15686 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15687 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15688 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15689 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15690 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15691 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15692 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15693 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15694 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15695 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15696 install_element(BGP_IPV4M_NODE,
15697 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15698 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15699 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15700 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15701 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15702 install_element(BGP_IPV6_NODE,
15703 &ipv6_bgp_distance_source_access_list_cmd);
15704 install_element(BGP_IPV6_NODE,
15705 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15706 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15707 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15708 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15709 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15710 install_element(BGP_IPV6M_NODE,
15711 &ipv6_bgp_distance_source_access_list_cmd);
15712 install_element(BGP_IPV6M_NODE,
15713 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15714
ef5f4b23 15715 /* BGP dampening */
585f1adc
IR
15716 install_element(BGP_NODE, &bgp_damp_set_cmd);
15717 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15718 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15719 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15720 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15721 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15722 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15723 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15724 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15725 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15726 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15727 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15728 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15729 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15730
15731 /* Large Communities */
15732 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15733 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15734
15735 /* show bgp ipv4 flowspec detailed */
15736 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15737
2a0e69ae 15738 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15739 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15740}
15741
15742void bgp_route_finish(void)
15743{
15744 afi_t afi;
15745 safi_t safi;
15746
05c7a1cc
QY
15747 FOREACH_AFI_SAFI (afi, safi) {
15748 bgp_table_unlock(bgp_distance_table[afi][safi]);
15749 bgp_distance_table[afi][safi] = NULL;
15750 }
228da428 15751}