]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #12259 from opensourcerouting/fix/show_rtt_always
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
70cd87ca 75#include "bgpd/bgp_orr.h"
6401252f 76#include "bgpd/bgp_trace.h"
fdeb5a81 77#include "bgpd/bgp_rpki.h"
718e3744 78
49e5a4a0 79#ifdef ENABLE_BGP_VNC
f8b6f499
LB
80#include "bgpd/rfapi/rfapi_backend.h"
81#include "bgpd/rfapi/vnc_import_bgp.h"
82#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 83#endif
aee875b5
PG
84#include "bgpd/bgp_encap_types.h"
85#include "bgpd/bgp_encap_tlv.h"
684a7227 86#include "bgpd/bgp_evpn.h"
0a50c248 87#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 88#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 89#include "bgpd/bgp_flowspec.h"
98a9dbc7 90#include "bgpd/bgp_flowspec_util.h"
45918cfb 91#include "bgpd/bgp_pbr.h"
65efcfce 92
e2a86ad9 93#include "bgpd/bgp_route_clippy.c"
aee875b5 94
7fd28dd2
PR
95DEFINE_HOOK(bgp_snmp_update_stats,
96 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 97 (rn, pi, added));
7fd28dd2 98
b5b99af8
DS
99DEFINE_HOOK(bgp_rpki_prefix_status,
100 (struct peer *peer, struct attr *attr,
101 const struct prefix *prefix),
8451921b 102 (peer, attr, prefix));
b5b99af8 103
718e3744 104/* Extern from bgp_dump.c */
dde72586
SH
105extern const char *bgp_origin_str[];
106extern const char *bgp_origin_long_str[];
3742de8d 107
b7d08f5a 108/* PMSI strings. */
109#define PMSI_TNLTYPE_STR_NO_INFO "No info"
110#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
111static const struct message bgp_pmsi_tnltype_str[] = {
112 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
113 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
114 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
115 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
116 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
117 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
118 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
119 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 120 {0}
121};
b7d08f5a 122
9df8b37c 123#define VRFID_NONE_STR "-"
46aeabed 124#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 125
4a11bf2c 126DEFINE_HOOK(bgp_process,
9bcb3eef
DS
127 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
128 struct peer *peer, bool withdraw),
8451921b 129 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 130
4056a5f6
RZ
131/** Test if path is suppressed. */
132static bool bgp_path_suppressed(struct bgp_path_info *pi)
133{
134 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
135 return false;
136
137 return listcount(pi->extra->aggr_suppressors) > 0;
138}
4a11bf2c 139
9bcb3eef 140struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 141 safi_t safi, const struct prefix *p,
d62a17ae 142 struct prefix_rd *prd)
143{
9bcb3eef
DS
144 struct bgp_dest *dest;
145 struct bgp_dest *pdest = NULL;
d62a17ae 146
147 assert(table);
d62a17ae 148
149 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
150 || (safi == SAFI_EVPN)) {
9bcb3eef 151 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 152
9bcb3eef
DS
153 if (!bgp_dest_has_bgp_path_info_data(pdest))
154 bgp_dest_set_bgp_table_info(
155 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 156 else
9bcb3eef
DS
157 bgp_dest_unlock_node(pdest);
158 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 159 }
718e3744 160
9bcb3eef 161 dest = bgp_node_get(table, p);
718e3744 162
d62a17ae 163 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
164 || (safi == SAFI_EVPN))
9bcb3eef 165 dest->pdest = pdest;
718e3744 166
9bcb3eef 167 return dest;
718e3744 168}
6b0655a2 169
9bcb3eef 170struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 171 safi_t safi, const struct prefix *p,
d62a17ae 172 struct prefix_rd *prd)
128ea8ab 173{
9bcb3eef
DS
174 struct bgp_dest *dest;
175 struct bgp_dest *pdest = NULL;
128ea8ab 176
d62a17ae 177 if (!table)
178 return NULL;
128ea8ab 179
d62a17ae 180 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
181 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
182 pdest = bgp_node_lookup(table, (struct prefix *)prd);
183 if (!pdest)
d62a17ae 184 return NULL;
128ea8ab 185
9bcb3eef
DS
186 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
187 bgp_dest_unlock_node(pdest);
d62a17ae 188 return NULL;
189 }
128ea8ab 190
9bcb3eef 191 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 192 }
128ea8ab 193
9bcb3eef 194 dest = bgp_node_lookup(table, p);
128ea8ab 195
9bcb3eef 196 return dest;
128ea8ab 197}
198
18ee8310
DS
199/* Allocate bgp_path_info_extra */
200static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 201{
4b7e6066
DS
202 struct bgp_path_info_extra *new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
204 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
205 new->label[0] = MPLS_INVALID_LABEL;
206 new->num_labels = 0;
3e3708cb
PG
207 new->bgp_fs_pbr = NULL;
208 new->bgp_fs_iprule = NULL;
d62a17ae 209 return new;
fb982c25
PJ
210}
211
a2e219fe 212void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 213{
4b7e6066 214 struct bgp_path_info_extra *e;
d62a17ae 215
c93a3b77
DS
216 if (!extra || !*extra)
217 return;
d62a17ae 218
c93a3b77 219 e = *extra;
4538f895 220 if (e->damp_info)
b4f7f45b
IR
221 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
222 e->damp_info->safi);
4538f895 223
c93a3b77
DS
224 e->damp_info = NULL;
225 if (e->parent) {
40381db7 226 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 227
40381db7 228 if (bpi->net) {
0e70e6c8
DL
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
232 *
40381db7
DS
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
0e70e6c8
DL
236 */
237 unsigned refcount;
238
40381db7 239 bpi = bgp_path_info_lock(bpi);
c10e14e9 240 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 241 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 242 if (!refcount)
40381db7
DS
243 bpi->net = NULL;
244 bgp_path_info_unlock(bpi);
0e70e6c8 245 }
18ee8310 246 bgp_path_info_unlock(e->parent);
c93a3b77 247 e->parent = NULL;
d62a17ae 248 }
c93a3b77
DS
249
250 if (e->bgp_orig)
251 bgp_unlock(e->bgp_orig);
c26edcda 252
4cd690ae
PG
253 if (e->peer_orig)
254 peer_unlock(e->peer_orig);
255
ff3bf9a4
DS
256 if (e->aggr_suppressors)
257 list_delete(&e->aggr_suppressors);
258
60605cbc
AK
259 if (e->mh_info)
260 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 261
ce3c0614
PG
262 if ((*extra)->bgp_fs_iprule)
263 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 264 if ((*extra)->bgp_fs_pbr)
6a154c88 265 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 266 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
267}
268
18ee8310
DS
269/* Get bgp_path_info extra information for the given bgp_path_info, lazy
270 * allocated if required.
fb982c25 271 */
40381db7 272struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 273{
40381db7
DS
274 if (!pi->extra)
275 pi->extra = bgp_path_info_extra_new();
276 return pi->extra;
fb982c25
PJ
277}
278
718e3744 279/* Free bgp route information. */
9b6d8fcf 280static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 281{
05864da7 282 bgp_attr_unintern(&path->attr);
fb018d25 283
9b6d8fcf
DS
284 bgp_unlink_nexthop(path);
285 bgp_path_info_extra_free(&path->extra);
286 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
287 if (path->net)
288 bgp_addpath_free_info_data(&path->tx_addpath,
289 &path->net->tx_addpath);
718e3744 290
9b6d8fcf 291 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 292
9b6d8fcf 293 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 294}
295
9b6d8fcf 296struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 297{
9b6d8fcf
DS
298 path->lock++;
299 return path;
200df115 300}
301
9b6d8fcf 302struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 303{
9b6d8fcf
DS
304 assert(path && path->lock > 0);
305 path->lock--;
d62a17ae 306
9b6d8fcf 307 if (path->lock == 0) {
9b6d8fcf 308 bgp_path_info_free(path);
d62a17ae 309 return NULL;
310 }
200df115 311
9b6d8fcf 312 return path;
200df115 313}
314
f009ff26 315/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 316static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 317{
318 struct peer *peer;
319 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 320 bool set_flag = false;
f009ff26 321 struct bgp *bgp = NULL;
322 struct bgp_table *table = NULL;
323 afi_t afi = 0;
324 safi_t safi = 0;
f009ff26 325
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
328 */
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 330 return 0;
331
9bcb3eef 332 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 333 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 334 zlog_debug(
56ca3b5b
DL
335 "Route %pBD is in workqueue and being processed, not deferred.",
336 dest);
b54892e0 337
5f9c1aa2 338 return 0;
339 }
340
9bcb3eef 341 table = bgp_dest_table(dest);
f009ff26 342 if (table) {
343 bgp = table->bgp;
344 afi = table->afi;
345 safi = table->safi;
346 }
347
9bcb3eef 348 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 349 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
351 continue;
352
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
355 */
36235319
QY
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
357 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 358 set_flag = true;
f009ff26 359 } else {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
362 */
363 peer = old_pi->peer;
36235319
QY
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
365 && BGP_PEER_RESTARTING_MODE(peer)
366 && (old_pi
367 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 }
370 }
371 if (set_flag)
372 break;
373 }
374
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
376 * is active
377 */
2ba1fe69 378 if (set_flag && table) {
f009ff26 379 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
380 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
381 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 382 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 383 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
384 zlog_debug("DEFER route %pBD, dest %p", dest,
385 dest);
f009ff26 386 return 0;
387 }
388 }
389 return -1;
390}
391
9bcb3eef 392void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 393{
4b7e6066 394 struct bgp_path_info *top;
718e3744 395
9bcb3eef 396 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 397
6f94b685 398 pi->next = top;
40381db7 399 pi->prev = NULL;
d62a17ae 400 if (top)
40381db7 401 top->prev = pi;
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 403
40381db7 404 bgp_path_info_lock(pi);
9bcb3eef 405 bgp_dest_lock_node(dest);
40381db7 406 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 407 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 408 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 409}
410
d62a17ae 411/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 412 completion callback *only* */
9bcb3eef 413void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 414{
40381db7
DS
415 if (pi->next)
416 pi->next->prev = pi->prev;
417 if (pi->prev)
418 pi->prev->next = pi->next;
d62a17ae 419 else
9bcb3eef 420 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 421
40381db7
DS
422 bgp_path_info_mpath_dequeue(pi);
423 bgp_path_info_unlock(pi);
7fd28dd2 424 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 425 bgp_dest_unlock_node(dest);
718e3744 426}
427
9bcb3eef 428void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 429{
9bcb3eef 430 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 431 /* set of previous already took care of pcount */
40381db7 432 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 433}
434
18ee8310 435/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
436 called when a route is deleted and then quickly re-added before the
437 deletion has been processed */
9bcb3eef 438void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 439{
9bcb3eef 440 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 441 /* unset of previous already took care of pcount */
40381db7 442 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
443}
444
d62a17ae 445/* Adjust pcount as required */
9bcb3eef 446static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 447{
d62a17ae 448 struct bgp_table *table;
67174041 449
9bcb3eef 450 assert(dest && bgp_dest_table(dest));
40381db7 451 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 452
9bcb3eef 453 table = bgp_dest_table(dest);
67174041 454
40381db7 455 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 456 return;
457
40381db7
DS
458 if (!BGP_PATH_COUNTABLE(pi)
459 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 460
40381db7 461 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 462
463 /* slight hack, but more robust against errors. */
40381db7
DS
464 if (pi->peer->pcount[table->afi][table->safi])
465 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 466 else
450971aa 467 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 468 "Asked to decrement 0 prefix count for peer");
40381db7
DS
469 } else if (BGP_PATH_COUNTABLE(pi)
470 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
471 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
472 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 473 }
1a392d46
PJ
474}
475
40381db7
DS
476static int bgp_label_index_differs(struct bgp_path_info *pi1,
477 struct bgp_path_info *pi2)
28d58fd7 478{
40381db7 479 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 480}
1a392d46 481
18ee8310 482/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
483 * This is here primarily to keep prefix-count in check.
484 */
9bcb3eef 485void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 486 uint32_t flag)
1a392d46 487{
40381db7 488 SET_FLAG(pi->flags, flag);
d62a17ae 489
490 /* early bath if we know it's not a flag that changes countability state
491 */
492 if (!CHECK_FLAG(flag,
1defdda8 493 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 494 return;
495
9bcb3eef 496 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
497}
498
9bcb3eef 499void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 500 uint32_t flag)
1a392d46 501{
40381db7 502 UNSET_FLAG(pi->flags, flag);
d62a17ae 503
504 /* early bath if we know it's not a flag that changes countability state
505 */
506 if (!CHECK_FLAG(flag,
1defdda8 507 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 508 return;
509
9bcb3eef 510 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
511}
512
718e3744 513/* Get MED value. If MED value is missing and "bgp bestpath
514 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 515static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 516{
517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
518 return attr->med;
519 else {
892fedb6 520 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 521 return BGP_MED_MAX;
522 else
523 return 0;
524 }
718e3744 525}
526
7533cad7
QY
527void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
528 size_t buf_len)
2ec1e66f 529{
40381db7 530 if (pi->addpath_rx_id)
7533cad7
QY
531 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
532 pi->peer->host, pi->addpath_rx_id);
d62a17ae 533 else
7533cad7 534 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 535}
9fbdd100 536
da0c0ef7
KM
537
538/*
539 * Get the ultimate path info.
540 */
541struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
542{
543 struct bgp_path_info *bpi_ultimate;
544
545 if (info->sub_type != BGP_ROUTE_IMPORTED)
546 return info;
547
548 for (bpi_ultimate = info;
549 bpi_ultimate->extra && bpi_ultimate->extra->parent;
550 bpi_ultimate = bpi_ultimate->extra->parent)
551 ;
552
553 return bpi_ultimate;
554}
555
d62a17ae 556/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
557 */
18ee8310
DS
558static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
559 struct bgp_path_info *exist, int *paths_eq,
560 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
561 char *pfx_buf, afi_t afi, safi_t safi,
562 enum bgp_path_selection_reason *reason)
d62a17ae 563{
5df26422 564 const struct prefix *new_p;
70cd87ca 565 struct prefix exist_p;
d62a17ae 566 struct attr *newattr, *existattr;
3061acc2
DA
567 enum bgp_peer_sort new_sort;
568 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
569 uint32_t new_pref;
570 uint32_t exist_pref;
571 uint32_t new_med;
572 uint32_t exist_med;
573 uint32_t new_weight;
574 uint32_t exist_weight;
d62a17ae 575 uint32_t newm, existm;
576 struct in_addr new_id;
577 struct in_addr exist_id;
578 int new_cluster;
579 int exist_cluster;
580 int internal_as_route;
581 int confed_as_route;
04d14c8b 582 int ret = 0;
ee88563a
JM
583 int igp_metric_ret = 0;
584 int peer_sort_ret = -1;
d62a17ae 585 char new_buf[PATH_ADDPATH_STR_BUFFER];
586 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
587 uint32_t new_mm_seq;
588 uint32_t exist_mm_seq;
6d8c603a 589 int nh_cmp;
d071f237
AK
590 esi_t *exist_esi;
591 esi_t *new_esi;
592 bool same_esi;
593 bool old_proxy;
594 bool new_proxy;
33c6e933 595 bool new_origin, exist_origin;
da0c0ef7 596 struct bgp_path_info *bpi_ultimate;
d62a17ae 597
70cd87ca
MK
598 struct bgp_orr_group *orr_group = NULL;
599 struct listnode *node;
600 struct bgp_orr_igp_metric *igp_metric = NULL;
601 struct list *orr_group_igp_metric_info = NULL;
602
d62a17ae 603 *paths_eq = 0;
604
605 /* 0. Null check. */
606 if (new == NULL) {
fdf81fa0 607 *reason = bgp_path_selection_none;
d62a17ae 608 if (debug)
609 zlog_debug("%s: new is NULL", pfx_buf);
610 return 0;
611 }
2ec1e66f 612
da0c0ef7
KM
613 if (debug) {
614 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
615 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 616 sizeof(new_buf));
da0c0ef7 617 }
718e3744 618
d62a17ae 619 if (exist == NULL) {
fdf81fa0 620 *reason = bgp_path_selection_first;
d62a17ae 621 if (debug)
4378495a
DS
622 zlog_debug("%s(%s): %s is the initial bestpath",
623 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 624 return 1;
625 }
2ec1e66f 626
d62a17ae 627 if (debug) {
da0c0ef7
KM
628 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
629 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 630 sizeof(exist_buf));
4378495a
DS
631 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
632 pfx_buf, bgp->name_pretty, new_buf, new->flags,
633 exist_buf, exist->flags);
d62a17ae 634 }
8ff56318 635
d62a17ae 636 newattr = new->attr;
637 existattr = exist->attr;
638
1479ed2f
DA
639 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
640 * Capability" to a neighbor MUST perform the following upon receiving
641 * a route from that neighbor with the "LLGR_STALE" community, or upon
642 * attaching the "LLGR_STALE" community itself per Section 4.2:
643 *
644 * Treat the route as the least-preferred in route selection (see
645 * below). See the Risks of Depreferencing Routes section (Section 5.2)
646 * for a discussion of potential risks inherent in doing this.
647 */
9a706b42
DA
648 if (bgp_attr_get_community(newattr) &&
649 community_include(bgp_attr_get_community(newattr),
650 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
651 if (debug)
652 zlog_debug(
653 "%s: %s wins over %s due to LLGR_STALE community",
654 pfx_buf, new_buf, exist_buf);
655 return 0;
656 }
657
9a706b42
DA
658 if (bgp_attr_get_community(existattr) &&
659 community_include(bgp_attr_get_community(existattr),
660 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
661 if (debug)
662 zlog_debug(
663 "%s: %s loses to %s due to LLGR_STALE community",
664 pfx_buf, new_buf, exist_buf);
665 return 1;
666 }
667
5df26422
NS
668 new_p = bgp_dest_get_prefix(new->net);
669
d62a17ae 670 /* For EVPN routes, we cannot just go by local vs remote, we have to
671 * look at the MAC mobility sequence number, if present.
672 */
5df26422
NS
673 if ((safi == SAFI_EVPN)
674 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 675 /* This is an error condition described in RFC 7432 Section
676 * 15.2. The RFC
677 * states that in this scenario "the PE MUST alert the operator"
678 * but it
679 * does not state what other action to take. In order to provide
680 * some
681 * consistency in this scenario we are going to prefer the path
682 * with the
683 * sticky flag.
684 */
685 if (newattr->sticky != existattr->sticky) {
686 if (!debug) {
5df26422
NS
687 prefix2str(new_p, pfx_buf,
688 sizeof(*pfx_buf)
689 * PREFIX2STR_BUFFER);
18ee8310 690 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
691 new, new_buf, sizeof(new_buf));
692 bgp_path_info_path_with_addpath_rx_str(
693 exist, exist_buf, sizeof(exist_buf));
d62a17ae 694 }
695
696 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 697 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
698 if (debug)
699 zlog_debug(
700 "%s: %s wins over %s due to sticky MAC flag",
701 pfx_buf, new_buf, exist_buf);
d62a17ae 702 return 1;
703 }
704
705 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 706 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
707 if (debug)
708 zlog_debug(
709 "%s: %s loses to %s due to sticky MAC flag",
710 pfx_buf, new_buf, exist_buf);
d62a17ae 711 return 0;
712 }
713 }
128ea8ab 714
d071f237
AK
715 new_esi = bgp_evpn_attr_get_esi(newattr);
716 exist_esi = bgp_evpn_attr_get_esi(existattr);
717 if (bgp_evpn_is_esi_valid(new_esi) &&
718 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
719 same_esi = true;
720 } else {
721 same_esi = false;
722 }
723
724 /* If both paths have the same non-zero ES and
725 * one path is local it wins.
726 * PS: Note the local path wins even if the remote
727 * has the higher MM seq. The local path's
728 * MM seq will be fixed up to match the highest
729 * rem seq, subsequently.
730 */
731 if (same_esi) {
732 char esi_buf[ESI_STR_LEN];
733
734 if (bgp_evpn_is_path_local(bgp, new)) {
735 *reason = bgp_path_selection_evpn_local_path;
736 if (debug)
737 zlog_debug(
738 "%s: %s wins over %s as ES %s is same and local",
739 pfx_buf, new_buf, exist_buf,
740 esi_to_str(new_esi, esi_buf,
741 sizeof(esi_buf)));
742 return 1;
743 }
744 if (bgp_evpn_is_path_local(bgp, exist)) {
745 *reason = bgp_path_selection_evpn_local_path;
746 if (debug)
747 zlog_debug(
748 "%s: %s loses to %s as ES %s is same and local",
749 pfx_buf, new_buf, exist_buf,
750 esi_to_str(new_esi, esi_buf,
751 sizeof(esi_buf)));
752 return 0;
753 }
754 }
755
d62a17ae 756 new_mm_seq = mac_mobility_seqnum(newattr);
757 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 758
d62a17ae 759 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 760 *reason = bgp_path_selection_evpn_seq;
d62a17ae 761 if (debug)
762 zlog_debug(
763 "%s: %s wins over %s due to MM seq %u > %u",
764 pfx_buf, new_buf, exist_buf, new_mm_seq,
765 exist_mm_seq);
766 return 1;
767 }
8ff56318 768
d62a17ae 769 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 770 *reason = bgp_path_selection_evpn_seq;
d62a17ae 771 if (debug)
772 zlog_debug(
773 "%s: %s loses to %s due to MM seq %u < %u",
774 pfx_buf, new_buf, exist_buf, new_mm_seq,
775 exist_mm_seq);
776 return 0;
777 }
6d8c603a 778
d071f237
AK
779 /* if the sequence numbers and ESI are the same and one path
780 * is non-proxy it wins (over proxy)
781 */
782 new_proxy = bgp_evpn_attr_is_proxy(newattr);
783 old_proxy = bgp_evpn_attr_is_proxy(existattr);
784 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
785 old_proxy != new_proxy) {
786 if (!new_proxy) {
787 *reason = bgp_path_selection_evpn_non_proxy;
788 if (debug)
789 zlog_debug(
790 "%s: %s wins over %s, same seq/es and non-proxy",
791 pfx_buf, new_buf, exist_buf);
792 return 1;
793 }
794
795 *reason = bgp_path_selection_evpn_non_proxy;
796 if (debug)
797 zlog_debug(
798 "%s: %s loses to %s, same seq/es and non-proxy",
799 pfx_buf, new_buf, exist_buf);
800 return 0;
801 }
802
6d8c603a
AK
803 /*
804 * if sequence numbers are the same path with the lowest IP
805 * wins
806 */
807 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
808 if (nh_cmp < 0) {
fdf81fa0 809 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
810 if (debug)
811 zlog_debug(
23d0a753 812 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 813 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 814 &new->attr->nexthop);
6d8c603a
AK
815 return 1;
816 }
817 if (nh_cmp > 0) {
fdf81fa0 818 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
819 if (debug)
820 zlog_debug(
23d0a753 821 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 822 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 823 &new->attr->nexthop);
6d8c603a
AK
824 return 0;
825 }
d62a17ae 826 }
9fbdd100 827
d62a17ae 828 /* 1. Weight check. */
d62a17ae 829 new_weight = newattr->weight;
830 exist_weight = existattr->weight;
8ff56318 831
d62a17ae 832 if (new_weight > exist_weight) {
fdf81fa0 833 *reason = bgp_path_selection_weight;
d62a17ae 834 if (debug)
835 zlog_debug("%s: %s wins over %s due to weight %d > %d",
836 pfx_buf, new_buf, exist_buf, new_weight,
837 exist_weight);
838 return 1;
839 }
718e3744 840
d62a17ae 841 if (new_weight < exist_weight) {
fdf81fa0 842 *reason = bgp_path_selection_weight;
d62a17ae 843 if (debug)
844 zlog_debug("%s: %s loses to %s due to weight %d < %d",
845 pfx_buf, new_buf, exist_buf, new_weight,
846 exist_weight);
847 return 0;
848 }
9fbdd100 849
d62a17ae 850 /* 2. Local preference check. */
851 new_pref = exist_pref = bgp->default_local_pref;
852
853 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
854 new_pref = newattr->local_pref;
855 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
856 exist_pref = existattr->local_pref;
857
858 if (new_pref > exist_pref) {
fdf81fa0 859 *reason = bgp_path_selection_local_pref;
d62a17ae 860 if (debug)
861 zlog_debug(
862 "%s: %s wins over %s due to localpref %d > %d",
863 pfx_buf, new_buf, exist_buf, new_pref,
864 exist_pref);
865 return 1;
866 }
718e3744 867
d62a17ae 868 if (new_pref < exist_pref) {
fdf81fa0 869 *reason = bgp_path_selection_local_pref;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s loses to %s due to localpref %d < %d",
873 pfx_buf, new_buf, exist_buf, new_pref,
874 exist_pref);
875 return 0;
876 }
9fbdd100 877
46dbf9d0
DA
878 /* If a BGP speaker supports ACCEPT_OWN and is configured for the
879 * extensions defined in this document, the following step is inserted
880 * after the LOCAL_PREF comparison step in the BGP decision process:
881 * When comparing a pair of routes for a BGP destination, the
882 * route with the ACCEPT_OWN community attached is preferred over
883 * the route that does not have the community.
884 * This extra step MUST only be invoked during the best path selection
885 * process of VPN-IP routes.
886 */
887 if (safi == SAFI_MPLS_VPN &&
888 (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
889 CHECK_FLAG(exist->peer->af_flags[afi][safi],
890 PEER_FLAG_ACCEPT_OWN))) {
891 bool new_accept_own = false;
892 bool exist_accept_own = false;
893 uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
894
895 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
896 new_accept_own = community_include(
897 bgp_attr_get_community(newattr), accept_own);
898 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
899 exist_accept_own = community_include(
900 bgp_attr_get_community(existattr), accept_own);
901
902 if (new_accept_own && !exist_accept_own) {
903 *reason = bgp_path_selection_accept_own;
904 if (debug)
905 zlog_debug(
906 "%s: %s wins over %s due to accept-own",
907 pfx_buf, new_buf, exist_buf);
908 return 1;
909 }
910
911 if (!new_accept_own && exist_accept_own) {
912 *reason = bgp_path_selection_accept_own;
913 if (debug)
914 zlog_debug(
915 "%s: %s loses to %s due to accept-own",
916 pfx_buf, new_buf, exist_buf);
917 return 0;
918 }
919 }
920
97a52c82
DA
921 /* Tie-breaker - AIGP (Metric TLV) attribute */
922 if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
923 CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
924 CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
925 uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
926 uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
927
928 if (new_aigp < exist_aigp) {
929 *reason = bgp_path_selection_aigp;
930 if (debug)
931 zlog_debug(
932 "%s: %s wins over %s due to AIGP %" PRIu64
933 " < %" PRIu64,
934 pfx_buf, new_buf, exist_buf, new_aigp,
935 exist_aigp);
936 return 1;
937 }
938
939 if (new_aigp > exist_aigp) {
940 *reason = bgp_path_selection_aigp;
941 if (debug)
942 zlog_debug(
943 "%s: %s loses to %s due to AIGP %" PRIu64
944 " > %" PRIu64,
945 pfx_buf, new_buf, exist_buf, new_aigp,
946 exist_aigp);
947 return 0;
948 }
949 }
950
d62a17ae 951 /* 3. Local route check. We prefer:
952 * - BGP_ROUTE_STATIC
953 * - BGP_ROUTE_AGGREGATE
954 * - BGP_ROUTE_REDISTRIBUTE
955 */
33c6e933
DS
956 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
957 new->sub_type == BGP_ROUTE_IMPORTED);
958 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
959 exist->sub_type == BGP_ROUTE_IMPORTED);
960
961 if (new_origin && !exist_origin) {
fdf81fa0 962 *reason = bgp_path_selection_local_route;
d62a17ae 963 if (debug)
964 zlog_debug(
965 "%s: %s wins over %s due to preferred BGP_ROUTE type",
966 pfx_buf, new_buf, exist_buf);
967 return 1;
968 }
718e3744 969
33c6e933 970 if (!new_origin && exist_origin) {
fdf81fa0 971 *reason = bgp_path_selection_local_route;
d62a17ae 972 if (debug)
973 zlog_debug(
974 "%s: %s loses to %s due to preferred BGP_ROUTE type",
975 pfx_buf, new_buf, exist_buf);
976 return 0;
6811845b 977 }
718e3744 978
da0c0ef7
KM
979 /* Here if these are imported routes then get ultimate pi for
980 * path compare.
981 */
982 new = bgp_get_imported_bpi_ultimate(new);
983 exist = bgp_get_imported_bpi_ultimate(exist);
984 newattr = new->attr;
985 existattr = exist->attr;
986
d62a17ae 987 /* 4. AS path length check. */
892fedb6 988 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 989 int exist_hops = aspath_count_hops(existattr->aspath);
990 int exist_confeds = aspath_count_confeds(existattr->aspath);
991
892fedb6 992 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 993 int aspath_hops;
994
995 aspath_hops = aspath_count_hops(newattr->aspath);
996 aspath_hops += aspath_count_confeds(newattr->aspath);
997
998 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 999 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1000 if (debug)
1001 zlog_debug(
1002 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1003 pfx_buf, new_buf, exist_buf,
1004 aspath_hops,
1005 (exist_hops + exist_confeds));
1006 return 1;
1007 }
1008
1009 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 1010 *reason = bgp_path_selection_confed_as_path;
d62a17ae 1011 if (debug)
1012 zlog_debug(
1013 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1014 pfx_buf, new_buf, exist_buf,
1015 aspath_hops,
1016 (exist_hops + exist_confeds));
1017 return 0;
1018 }
1019 } else {
1020 int newhops = aspath_count_hops(newattr->aspath);
1021
1022 if (newhops < exist_hops) {
fdf81fa0 1023 *reason = bgp_path_selection_as_path;
d62a17ae 1024 if (debug)
1025 zlog_debug(
1026 "%s: %s wins over %s due to aspath hopcount %d < %d",
1027 pfx_buf, new_buf, exist_buf,
1028 newhops, exist_hops);
1029 return 1;
1030 }
1031
1032 if (newhops > exist_hops) {
fdf81fa0 1033 *reason = bgp_path_selection_as_path;
d62a17ae 1034 if (debug)
1035 zlog_debug(
1036 "%s: %s loses to %s due to aspath hopcount %d > %d",
1037 pfx_buf, new_buf, exist_buf,
1038 newhops, exist_hops);
1039 return 0;
1040 }
1041 }
1042 }
9fbdd100 1043
d62a17ae 1044 /* 5. Origin check. */
1045 if (newattr->origin < existattr->origin) {
fdf81fa0 1046 *reason = bgp_path_selection_origin;
d62a17ae 1047 if (debug)
1048 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1049 pfx_buf, new_buf, exist_buf,
1050 bgp_origin_long_str[newattr->origin],
1051 bgp_origin_long_str[existattr->origin]);
1052 return 1;
1053 }
718e3744 1054
d62a17ae 1055 if (newattr->origin > existattr->origin) {
fdf81fa0 1056 *reason = bgp_path_selection_origin;
d62a17ae 1057 if (debug)
1058 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1059 pfx_buf, new_buf, exist_buf,
1060 bgp_origin_long_str[newattr->origin],
1061 bgp_origin_long_str[existattr->origin]);
1062 return 0;
1063 }
718e3744 1064
d62a17ae 1065 /* 6. MED check. */
1066 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1067 && aspath_count_hops(existattr->aspath) == 0);
1068 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1069 && aspath_count_confeds(existattr->aspath) > 0
1070 && aspath_count_hops(newattr->aspath) == 0
1071 && aspath_count_hops(existattr->aspath) == 0);
1072
892fedb6
DA
1073 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1074 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1075 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1076 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1077 || internal_as_route) {
1078 new_med = bgp_med_value(new->attr, bgp);
1079 exist_med = bgp_med_value(exist->attr, bgp);
1080
1081 if (new_med < exist_med) {
fdf81fa0 1082 *reason = bgp_path_selection_med;
d62a17ae 1083 if (debug)
1084 zlog_debug(
1085 "%s: %s wins over %s due to MED %d < %d",
1086 pfx_buf, new_buf, exist_buf, new_med,
1087 exist_med);
1088 return 1;
1089 }
8ff56318 1090
d62a17ae 1091 if (new_med > exist_med) {
fdf81fa0 1092 *reason = bgp_path_selection_med;
d62a17ae 1093 if (debug)
1094 zlog_debug(
1095 "%s: %s loses to %s due to MED %d > %d",
1096 pfx_buf, new_buf, exist_buf, new_med,
1097 exist_med);
1098 return 0;
1099 }
1100 }
9fbdd100 1101
d62a17ae 1102 /* 7. Peer type check. */
1103 new_sort = new->peer->sort;
1104 exist_sort = exist->peer->sort;
1105
1106 if (new_sort == BGP_PEER_EBGP
1107 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1108 *reason = bgp_path_selection_peer;
d62a17ae 1109 if (debug)
1110 zlog_debug(
1111 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1112 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1113 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1114 return 1;
1115 peer_sort_ret = 1;
d62a17ae 1116 }
718e3744 1117
d62a17ae 1118 if (exist_sort == BGP_PEER_EBGP
1119 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1120 *reason = bgp_path_selection_peer;
d62a17ae 1121 if (debug)
1122 zlog_debug(
1123 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1124 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1125 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1126 return 0;
1127 peer_sort_ret = 0;
d62a17ae 1128 }
8ff56318 1129
d62a17ae 1130 /* 8. IGP metric check. */
1131 newm = existm = 0;
8ff56318 1132
d62a17ae 1133 if (new->extra)
1134 newm = new->extra->igpmetric;
1135 if (exist->extra)
1136 existm = exist->extra->igpmetric;
9fbdd100 1137
70cd87ca
MK
1138 if (new->peer->orr_group_name[afi][safi]) {
1139 ret = str2prefix(new->peer->host, &exist_p);
1140 orr_group = bgp_orr_group_lookup_by_name(
1141 bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
1142 if (orr_group) {
1143 orr_group_igp_metric_info = orr_group->igp_metric_info;
1144 if (orr_group_igp_metric_info) {
1145 for (ALL_LIST_ELEMENTS_RO(
1146 orr_group_igp_metric_info, node,
1147 igp_metric)) {
1148 if (ret &&
1149 prefix_cmp(&exist_p,
1150 &igp_metric->prefix) ==
1151 0) {
1152 newm = igp_metric->igp_metric;
1153 break;
1154 }
1155 }
1156 }
1157 }
1158 }
1159 if (exist->peer->orr_group_name[afi][safi]) {
1160 ret = str2prefix(exist->peer->host, &exist_p);
1161 orr_group = bgp_orr_group_lookup_by_name(
1162 bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
1163 if (orr_group) {
1164 orr_group_igp_metric_info = orr_group->igp_metric_info;
1165 if (orr_group_igp_metric_info) {
1166 for (ALL_LIST_ELEMENTS_RO(
1167 orr_group_igp_metric_info, node,
1168 igp_metric)) {
1169 if (ret &&
1170 prefix_cmp(&exist_p,
1171 &igp_metric->prefix) ==
1172 0) {
1173 existm = igp_metric->igp_metric;
1174 break;
1175 }
1176 }
1177 }
1178 }
1179 }
1180
d62a17ae 1181 if (newm < existm) {
ee88563a 1182 if (debug && peer_sort_ret < 0)
d62a17ae 1183 zlog_debug(
d588b995 1184 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1185 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1186 igp_metric_ret = 1;
d62a17ae 1187 }
718e3744 1188
d62a17ae 1189 if (newm > existm) {
ee88563a 1190 if (debug && peer_sort_ret < 0)
d62a17ae 1191 zlog_debug(
d588b995 1192 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1193 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1194 igp_metric_ret = 0;
5e242b0d 1195 }
5e242b0d 1196
d62a17ae 1197 /* 9. Same IGP metric. Compare the cluster list length as
1198 representative of IGP hops metric. Rewrite the metric value
1199 pair (newm, existm) with the cluster list length. Prefer the
1200 path with smaller cluster list length. */
1201 if (newm == existm) {
aa53c036
DS
1202 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1203 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1204 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1205 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1206 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1207
1208 if (newm < existm) {
ee88563a 1209 if (debug && peer_sort_ret < 0)
d62a17ae 1210 zlog_debug(
d588b995 1211 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1212 pfx_buf, new_buf, exist_buf,
1213 newm, existm);
ee88563a 1214 igp_metric_ret = 1;
d62a17ae 1215 }
1216
1217 if (newm > existm) {
ee88563a 1218 if (debug && peer_sort_ret < 0)
d62a17ae 1219 zlog_debug(
d588b995 1220 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1221 pfx_buf, new_buf, exist_buf,
1222 newm, existm);
ee88563a 1223 igp_metric_ret = 0;
d62a17ae 1224 }
1225 }
1226 }
31a4638f 1227
d62a17ae 1228 /* 10. confed-external vs. confed-internal */
1229 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1230 if (new_sort == BGP_PEER_CONFED
1231 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1232 *reason = bgp_path_selection_confed;
d62a17ae 1233 if (debug)
1234 zlog_debug(
1235 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1236 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1237 if (!CHECK_FLAG(bgp->flags,
1238 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1239 return 1;
1240 peer_sort_ret = 1;
d62a17ae 1241 }
718e3744 1242
d62a17ae 1243 if (exist_sort == BGP_PEER_CONFED
1244 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1245 *reason = bgp_path_selection_confed;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1249 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1250 if (!CHECK_FLAG(bgp->flags,
1251 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1252 return 0;
1253 peer_sort_ret = 0;
d62a17ae 1254 }
1255 }
718e3744 1256
d62a17ae 1257 /* 11. Maximum path check. */
1258 if (newm == existm) {
1259 /* If one path has a label but the other does not, do not treat
1260 * them as equals for multipath
1261 */
a4d82a8a 1262 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1263 != (exist->extra
b57ba6d2 1264 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1265 if (debug)
1266 zlog_debug(
1267 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1268 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1269 } else if (CHECK_FLAG(bgp->flags,
1270 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1271
1272 /*
1273 * For the two paths, all comparison steps till IGP
1274 * metric
1275 * have succeeded - including AS_PATH hop count. Since
1276 * 'bgp
1277 * bestpath as-path multipath-relax' knob is on, we
1278 * don't need
1279 * an exact match of AS_PATH. Thus, mark the paths are
1280 * equal.
1281 * That will trigger both these paths to get into the
1282 * multipath
1283 * array.
1284 */
1285 *paths_eq = 1;
1286
1287 if (debug)
1288 zlog_debug(
1289 "%s: %s and %s are equal via multipath-relax",
1290 pfx_buf, new_buf, exist_buf);
1291 } else if (new->peer->sort == BGP_PEER_IBGP) {
1292 if (aspath_cmp(new->attr->aspath,
1293 exist->attr->aspath)) {
1294 *paths_eq = 1;
1295
1296 if (debug)
1297 zlog_debug(
1298 "%s: %s and %s are equal via matching aspaths",
1299 pfx_buf, new_buf, exist_buf);
1300 }
1301 } else if (new->peer->as == exist->peer->as) {
1302 *paths_eq = 1;
1303
1304 if (debug)
1305 zlog_debug(
1306 "%s: %s and %s are equal via same remote-as",
1307 pfx_buf, new_buf, exist_buf);
1308 }
1309 } else {
1310 /*
1311 * TODO: If unequal cost ibgp multipath is enabled we can
1312 * mark the paths as equal here instead of returning
1313 */
ee88563a
JM
1314
1315 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1316 * if either step 7 or 10 (peer type checks) yielded a winner,
1317 * that result was returned immediately. Returning from step 10
1318 * ignored the return value computed in steps 8 and 9 (IGP
1319 * metric checks). In order to preserve that behavior, if
1320 * peer_sort_ret is set, return that rather than igp_metric_ret.
1321 */
1322 ret = peer_sort_ret;
1323 if (peer_sort_ret < 0) {
1324 ret = igp_metric_ret;
1325 if (debug) {
1326 if (ret == 1)
1327 zlog_debug(
1328 "%s: %s wins over %s after IGP metric comparison",
1329 pfx_buf, new_buf, exist_buf);
1330 else
1331 zlog_debug(
1332 "%s: %s loses to %s after IGP metric comparison",
1333 pfx_buf, new_buf, exist_buf);
1334 }
1335 *reason = bgp_path_selection_igp_metric;
d62a17ae 1336 }
1337 return ret;
1338 }
718e3744 1339
ee88563a
JM
1340 /*
1341 * At this point, the decision whether to set *paths_eq = 1 has been
1342 * completed. If we deferred returning because of bestpath peer-type
1343 * relax configuration, return now.
1344 */
1345 if (peer_sort_ret >= 0)
1346 return peer_sort_ret;
1347
d62a17ae 1348 /* 12. If both paths are external, prefer the path that was received
1349 first (the oldest one). This step minimizes route-flap, since a
1350 newer path won't displace an older one, even if it was the
1351 preferred route based on the additional decision criteria below. */
892fedb6 1352 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1353 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1354 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1355 *reason = bgp_path_selection_older;
d62a17ae 1356 if (debug)
1357 zlog_debug(
1358 "%s: %s wins over %s due to oldest external",
1359 pfx_buf, new_buf, exist_buf);
1360 return 1;
1361 }
9fbdd100 1362
1defdda8 1363 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1364 *reason = bgp_path_selection_older;
d62a17ae 1365 if (debug)
1366 zlog_debug(
1367 "%s: %s loses to %s due to oldest external",
1368 pfx_buf, new_buf, exist_buf);
1369 return 0;
1370 }
1371 }
718e3744 1372
ce5002c6 1373 /* 13. Router-ID comparison. */
d62a17ae 1374 /* If one of the paths is "stale", the corresponding peer router-id will
1375 * be 0 and would always win over the other path. If originator id is
ce5002c6 1376 * used for the comparison, it will decide which path is better.
d62a17ae 1377 */
1378 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1379 new_id.s_addr = newattr->originator_id.s_addr;
1380 else
1381 new_id.s_addr = new->peer->remote_id.s_addr;
1382 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1383 exist_id.s_addr = existattr->originator_id.s_addr;
1384 else
1385 exist_id.s_addr = exist->peer->remote_id.s_addr;
1386
1387 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1388 *reason = bgp_path_selection_router_id;
d62a17ae 1389 if (debug)
1390 zlog_debug(
1391 "%s: %s wins over %s due to Router-ID comparison",
1392 pfx_buf, new_buf, exist_buf);
1393 return 1;
1394 }
718e3744 1395
d62a17ae 1396 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1397 *reason = bgp_path_selection_router_id;
d62a17ae 1398 if (debug)
1399 zlog_debug(
1400 "%s: %s loses to %s due to Router-ID comparison",
1401 pfx_buf, new_buf, exist_buf);
1402 return 0;
1403 }
9fbdd100 1404
ce5002c6 1405 /* 14. Cluster length comparison. */
d62a17ae 1406 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1407 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1408
1409 if (new_cluster < exist_cluster) {
fdf81fa0 1410 *reason = bgp_path_selection_cluster_length;
d62a17ae 1411 if (debug)
1412 zlog_debug(
1413 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1414 pfx_buf, new_buf, exist_buf, new_cluster,
1415 exist_cluster);
1416 return 1;
1417 }
718e3744 1418
d62a17ae 1419 if (new_cluster > exist_cluster) {
fdf81fa0 1420 *reason = bgp_path_selection_cluster_length;
d62a17ae 1421 if (debug)
1422 zlog_debug(
1423 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1424 pfx_buf, new_buf, exist_buf, new_cluster,
1425 exist_cluster);
1426 return 0;
1427 }
9fbdd100 1428
ce5002c6 1429 /* 15. Neighbor address comparison. */
d62a17ae 1430 /* Do this only if neither path is "stale" as stale paths do not have
1431 * valid peer information (as the connection may or may not be up).
1432 */
1defdda8 1433 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1434 *reason = bgp_path_selection_stale;
d62a17ae 1435 if (debug)
1436 zlog_debug(
1437 "%s: %s wins over %s due to latter path being STALE",
1438 pfx_buf, new_buf, exist_buf);
1439 return 1;
1440 }
0de5153c 1441
1defdda8 1442 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1443 *reason = bgp_path_selection_stale;
d62a17ae 1444 if (debug)
1445 zlog_debug(
1446 "%s: %s loses to %s due to former path being STALE",
1447 pfx_buf, new_buf, exist_buf);
1448 return 0;
1449 }
718e3744 1450
d62a17ae 1451 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1452 if (new->peer->su_remote == NULL) {
1453 *reason = bgp_path_selection_local_configured;
d62a17ae 1454 return 0;
fdf81fa0
DS
1455 }
1456 if (exist->peer->su_remote == NULL) {
1457 *reason = bgp_path_selection_local_configured;
d62a17ae 1458 return 1;
fdf81fa0 1459 }
9fbdd100 1460
d62a17ae 1461 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1462
1463 if (ret == 1) {
fdf81fa0 1464 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1465 if (debug)
1466 zlog_debug(
1467 "%s: %s loses to %s due to Neighor IP comparison",
1468 pfx_buf, new_buf, exist_buf);
1469 return 0;
1470 }
1471
1472 if (ret == -1) {
fdf81fa0 1473 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1474 if (debug)
1475 zlog_debug(
1476 "%s: %s wins over %s due to Neighor IP comparison",
1477 pfx_buf, new_buf, exist_buf);
1478 return 1;
1479 }
9fbdd100 1480
fdf81fa0 1481 *reason = bgp_path_selection_default;
d62a17ae 1482 if (debug)
1483 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1484 pfx_buf, new_buf, exist_buf);
718e3744 1485
d62a17ae 1486 return 1;
718e3744 1487}
1488
d071f237
AK
1489
1490int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1491 struct bgp_path_info *exist, int *paths_eq)
1492{
1493 enum bgp_path_selection_reason reason;
1494 char pfx_buf[PREFIX2STR_BUFFER];
1495
1496 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1497 AFI_L2VPN, SAFI_EVPN, &reason);
1498}
1499
65efcfce
LB
1500/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1501 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1502 * multipath is enabled
65efcfce 1503 * This version is compatible with */
18ee8310
DS
1504int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1505 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1506 afi_t afi, safi_t safi,
1507 enum bgp_path_selection_reason *reason)
d62a17ae 1508{
1509 int paths_eq;
1510 int ret;
18ee8310 1511 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1512 afi, safi, reason);
d62a17ae 1513
1514 if (paths_eq)
1515 ret = 0;
1516 else {
1517 if (ret == 1)
1518 ret = -1;
1519 else
1520 ret = 1;
1521 }
1522 return ret;
65efcfce
LB
1523}
1524
5a1ae2c2
DS
1525static enum filter_type bgp_input_filter(struct peer *peer,
1526 const struct prefix *p,
d62a17ae 1527 struct attr *attr, afi_t afi,
1528 safi_t safi)
718e3744 1529{
d62a17ae 1530 struct bgp_filter *filter;
6401252f 1531 enum filter_type ret = FILTER_PERMIT;
718e3744 1532
d62a17ae 1533 filter = &peer->filter[afi][safi];
718e3744 1534
d62a17ae 1535#define FILTER_EXIST_WARN(F, f, filter) \
1536 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1537 zlog_debug("%s: Could not find configured input %s-list %s!", \
1538 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1539
1540 if (DISTRIBUTE_IN_NAME(filter)) {
1541 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1542
6401252f
QY
1543 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1544 == FILTER_DENY) {
1545 ret = FILTER_DENY;
1546 goto done;
1547 }
d62a17ae 1548 }
1549
1550 if (PREFIX_LIST_IN_NAME(filter)) {
1551 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1552
6401252f
QY
1553 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1554 == PREFIX_DENY) {
1555 ret = FILTER_DENY;
1556 goto done;
1557 }
d62a17ae 1558 }
1559
1560 if (FILTER_LIST_IN_NAME(filter)) {
1561 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1562
1563 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1564 == AS_FILTER_DENY) {
1565 ret = FILTER_DENY;
1566 goto done;
1567 }
d62a17ae 1568 }
1569
6401252f 1570done:
c7bb4f00 1571 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1572 char pfxprint[PREFIX2STR_BUFFER];
1573
1574 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1575 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1576 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1577 }
1578
1579 return ret;
650f76c2 1580#undef FILTER_EXIST_WARN
718e3744 1581}
1582
b8685f9b
DS
1583static enum filter_type bgp_output_filter(struct peer *peer,
1584 const struct prefix *p,
d62a17ae 1585 struct attr *attr, afi_t afi,
1586 safi_t safi)
718e3744 1587{
d62a17ae 1588 struct bgp_filter *filter;
6401252f 1589 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1590
1591 filter = &peer->filter[afi][safi];
1592
1593#define FILTER_EXIST_WARN(F, f, filter) \
1594 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1595 zlog_debug("%s: Could not find configured output %s-list %s!", \
1596 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1597
d62a17ae 1598 if (DISTRIBUTE_OUT_NAME(filter)) {
1599 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1600
6401252f
QY
1601 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1602 == FILTER_DENY) {
1603 ret = FILTER_DENY;
1604 goto done;
1605 }
d62a17ae 1606 }
1607
1608 if (PREFIX_LIST_OUT_NAME(filter)) {
1609 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1610
d62a17ae 1611 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1612 == PREFIX_DENY) {
1613 ret = FILTER_DENY;
1614 goto done;
1615 }
d62a17ae 1616 }
718e3744 1617
d62a17ae 1618 if (FILTER_LIST_OUT_NAME(filter)) {
1619 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1620
d62a17ae 1621 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1622 == AS_FILTER_DENY) {
1623 ret = FILTER_DENY;
1624 goto done;
1625 }
1626 }
1627
c7bb4f00 1628 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1629 char pfxprint[PREFIX2STR_BUFFER];
1630
1631 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1632 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1633 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1634 }
718e3744 1635
6401252f
QY
1636done:
1637 return ret;
650f76c2 1638#undef FILTER_EXIST_WARN
718e3744 1639}
1640
1641/* If community attribute includes no_export then return 1. */
3dc339cd 1642static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1643{
9a706b42 1644 if (bgp_attr_get_community(attr)) {
d62a17ae 1645 /* NO_ADVERTISE check. */
9a706b42
DA
1646 if (community_include(bgp_attr_get_community(attr),
1647 COMMUNITY_NO_ADVERTISE))
3dc339cd 1648 return true;
d62a17ae 1649
1650 /* NO_EXPORT check. */
9a706b42
DA
1651 if (peer->sort == BGP_PEER_EBGP &&
1652 community_include(bgp_attr_get_community(attr),
1653 COMMUNITY_NO_EXPORT))
3dc339cd 1654 return true;
d62a17ae 1655
1656 /* NO_EXPORT_SUBCONFED check. */
1657 if (peer->sort == BGP_PEER_EBGP
1658 || peer->sort == BGP_PEER_CONFED)
9a706b42 1659 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1660 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1661 return true;
d62a17ae 1662 }
3dc339cd 1663 return false;
718e3744 1664}
1665
1666/* Route reflection loop check. */
3dc339cd 1667static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1668{
d62a17ae 1669 struct in_addr cluster_id;
779fee93 1670 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1671
779fee93 1672 if (cluster) {
d62a17ae 1673 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1674 cluster_id = peer->bgp->cluster_id;
1675 else
1676 cluster_id = peer->bgp->router_id;
1677
779fee93 1678 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1679 return true;
d62a17ae 1680 }
3dc339cd 1681 return false;
718e3744 1682}
6b0655a2 1683
d864dd9e
EB
1684static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1685{
1686 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1687 if (peer->local_role == ROLE_PROVIDER ||
1688 peer->local_role == ROLE_RS_SERVER)
1689 return true;
1690 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1691 return true;
1692 return false;
1693 }
1694 if (peer->local_role == ROLE_CUSTOMER ||
1695 peer->local_role == ROLE_PEER ||
1696 peer->local_role == ROLE_RS_CLIENT) {
1697 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1698 attr->otc = peer->as;
1699 }
1700 return false;
1701}
1702
1703static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1704{
1705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1706 if (peer->local_role == ROLE_CUSTOMER ||
1707 peer->local_role == ROLE_RS_CLIENT ||
1708 peer->local_role == ROLE_PEER)
1709 return true;
1710 return false;
1711 }
1712 if (peer->local_role == ROLE_PROVIDER ||
1713 peer->local_role == ROLE_PEER ||
1714 peer->local_role == ROLE_RS_SERVER) {
1715 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1716 attr->otc = peer->bgp->as;
1717 }
1718 return false;
1719}
1720
5a78f2bc
EB
1721static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1722{
1723 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1724}
1725
5a1ae2c2 1726static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1727 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1728 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1729 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1730{
d62a17ae 1731 struct bgp_filter *filter;
82b692c0
LK
1732 struct bgp_path_info rmap_path = { 0 };
1733 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1734 route_map_result_t ret;
1735 struct route_map *rmap = NULL;
718e3744 1736
d62a17ae 1737 filter = &peer->filter[afi][safi];
718e3744 1738
d62a17ae 1739 /* Apply default weight value. */
1740 if (peer->weight[afi][safi])
1741 attr->weight = peer->weight[afi][safi];
718e3744 1742
d62a17ae 1743 if (rmap_name) {
1744 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1745
d62a17ae 1746 if (rmap == NULL)
1747 return RMAP_DENY;
1748 } else {
1749 if (ROUTE_MAP_IN_NAME(filter)) {
1750 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1751
d62a17ae 1752 if (rmap == NULL)
1753 return RMAP_DENY;
1754 }
1755 }
0b16f239 1756
d62a17ae 1757 /* Route map apply. */
1758 if (rmap) {
6006b807 1759 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1760 /* Duplicate current value to new structure for modification. */
40381db7
DS
1761 rmap_path.peer = peer;
1762 rmap_path.attr = attr;
82b692c0 1763 rmap_path.extra = &extra;
9bcb3eef 1764 rmap_path.net = dest;
196c6b09 1765
82b692c0
LK
1766 extra.num_labels = num_labels;
1767 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1768 memcpy(extra.label, label,
1769 num_labels * sizeof(mpls_label_t));
718e3744 1770
d62a17ae 1771 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1772
d62a17ae 1773 /* Apply BGP route map to the attribute. */
1782514f 1774 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1775
d62a17ae 1776 peer->rmap_type = 0;
0b16f239 1777
1f2263be 1778 if (ret == RMAP_DENYMATCH)
d62a17ae 1779 return RMAP_DENY;
0b16f239 1780 }
d62a17ae 1781 return RMAP_PERMIT;
0b16f239
DS
1782}
1783
5f040085 1784static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1785 struct attr *attr, afi_t afi, safi_t safi,
1786 const char *rmap_name)
0b16f239 1787{
40381db7 1788 struct bgp_path_info rmap_path;
d62a17ae 1789 route_map_result_t ret;
1790 struct route_map *rmap = NULL;
d7c0a89a 1791 uint8_t rmap_type;
0b16f239 1792
b787157a
DS
1793 /*
1794 * So if we get to this point and have no rmap_name
1795 * we want to just show the output as it currently
1796 * exists.
1797 */
1798 if (!rmap_name)
1799 return RMAP_PERMIT;
0b16f239 1800
d62a17ae 1801 /* Apply default weight value. */
1802 if (peer->weight[afi][safi])
1803 attr->weight = peer->weight[afi][safi];
0b16f239 1804
b787157a 1805 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1806
b787157a
DS
1807 /*
1808 * If we have a route map name and we do not find
1809 * the routemap that means we have an implicit
1810 * deny.
1811 */
1812 if (rmap == NULL)
1813 return RMAP_DENY;
0b16f239 1814
6006b807 1815 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1816 /* Route map apply. */
544be979 1817 /* Duplicate current value to new structure for modification. */
40381db7
DS
1818 rmap_path.peer = peer;
1819 rmap_path.attr = attr;
0b16f239 1820
0f672529 1821 rmap_type = peer->rmap_type;
b787157a 1822 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1823
b787157a 1824 /* Apply BGP route map to the attribute. */
1782514f 1825 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1826
0f672529 1827 peer->rmap_type = rmap_type;
b787157a
DS
1828
1829 if (ret == RMAP_DENYMATCH)
1830 /*
1831 * caller has multiple error paths with bgp_attr_flush()
1832 */
1833 return RMAP_DENY;
ac41b2a2 1834
d62a17ae 1835 return RMAP_PERMIT;
718e3744 1836}
6b0655a2 1837
5000f21c 1838/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1839static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1840 struct peer *peer, struct attr *attr)
1841{
1842 if (peer->sort == BGP_PEER_EBGP
1843 && (peer_af_flag_check(peer, afi, safi,
1844 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1845 || peer_af_flag_check(peer, afi, safi,
1846 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1847 || peer_af_flag_check(peer, afi, safi,
1848 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1849 || peer_af_flag_check(peer, afi, safi,
1850 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1851 // Take action on the entire aspath
1852 if (peer_af_flag_check(peer, afi, safi,
1853 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1854 || peer_af_flag_check(peer, afi, safi,
1855 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1856 if (peer_af_flag_check(
1857 peer, afi, safi,
1858 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1859 attr->aspath = aspath_replace_private_asns(
bf26b80e 1860 attr->aspath, bgp->as, peer->as);
d62a17ae 1861
179d5a0e
TA
1862 /*
1863 * Even if the aspath consists of just private ASNs we
1864 * need to walk the AS-Path to maintain all instances
1865 * of the peer's ASN to break possible loops.
1866 */
d62a17ae 1867 else
1868 attr->aspath = aspath_remove_private_asns(
bf26b80e 1869 attr->aspath, peer->as);
d62a17ae 1870 }
1871
1872 // 'all' was not specified so the entire aspath must be private
1873 // ASNs
1874 // for us to do anything
1875 else if (aspath_private_as_check(attr->aspath)) {
1876 if (peer_af_flag_check(
1877 peer, afi, safi,
1878 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1879 attr->aspath = aspath_replace_private_asns(
bf26b80e 1880 attr->aspath, bgp->as, peer->as);
d62a17ae 1881 else
179d5a0e
TA
1882 /*
1883 * Walk the aspath to retain any instances of
1884 * the peer_asn
1885 */
1886 attr->aspath = aspath_remove_private_asns(
1887 attr->aspath, peer->as);
d62a17ae 1888 }
1889 }
5000f21c
DS
1890}
1891
c7122e14 1892/* If this is an EBGP peer with as-override */
d62a17ae 1893static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1894 struct peer *peer, struct attr *attr)
1895{
bbe7bc46
DA
1896 struct aspath *aspath;
1897
9bbdb457 1898 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1899 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1900 if (attr->aspath->refcnt)
1901 aspath = aspath_dup(attr->aspath);
1902 else
1903 aspath = attr->aspath;
1904
1905 attr->aspath = aspath_intern(
1906 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1907
1908 aspath_free(aspath);
1909 }
d62a17ae 1910}
1911
1479ed2f
DA
1912void bgp_attr_add_llgr_community(struct attr *attr)
1913{
1914 struct community *old;
1915 struct community *new;
1916 struct community *merge;
1917 struct community *llgr;
1918
9a706b42 1919 old = bgp_attr_get_community(attr);
1479ed2f
DA
1920 llgr = community_str2com("llgr-stale");
1921
1922 assert(llgr);
1923
1924 if (old) {
1925 merge = community_merge(community_dup(old), llgr);
1926
1927 if (old->refcnt == 0)
1928 community_free(&old);
1929
1930 new = community_uniq_sort(merge);
1931 community_free(&merge);
1932 } else {
1933 new = community_dup(llgr);
1934 }
1935
1936 community_free(&llgr);
1937
9a706b42 1938 bgp_attr_set_community(attr, new);
1479ed2f
DA
1939}
1940
7f323236
DW
1941void bgp_attr_add_gshut_community(struct attr *attr)
1942{
1943 struct community *old;
1944 struct community *new;
1945 struct community *merge;
1946 struct community *gshut;
1947
9a706b42 1948 old = bgp_attr_get_community(attr);
7f323236
DW
1949 gshut = community_str2com("graceful-shutdown");
1950
990f4f91 1951 assert(gshut);
1952
7f323236
DW
1953 if (old) {
1954 merge = community_merge(community_dup(old), gshut);
1955
a4d82a8a 1956 if (old->refcnt == 0)
3c1f53de 1957 community_free(&old);
7f323236
DW
1958
1959 new = community_uniq_sort(merge);
3c1f53de 1960 community_free(&merge);
7f323236
DW
1961 } else {
1962 new = community_dup(gshut);
1963 }
1964
3c1f53de 1965 community_free(&gshut);
9a706b42 1966 bgp_attr_set_community(attr, new);
7f323236
DW
1967
1968 /* When we add the graceful-shutdown community we must also
1969 * lower the local-preference */
1970 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1971 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1972}
1973
1974
e73c112e
MK
1975/* Notify BGP Conditional advertisement scanner process. */
1976void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1977{
e73c112e 1978 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1979 afi_t afi = SUBGRP_AFI(subgrp);
1980 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1981 struct bgp_filter *filter = &peer->filter[afi][safi];
1982
1983 if (!ADVERTISE_MAP_NAME(filter))
1984 return;
1985
52979c3b
DS
1986 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1987 return;
e73c112e 1988
52979c3b 1989 peer->advmap_table_change = true;
e73c112e
MK
1990}
1991
1992
f2ee6d5c 1993void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1994{
960035b2 1995 if (family == AF_INET) {
975a328e
DA
1996 attr->nexthop.s_addr = INADDR_ANY;
1997 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1998 }
d62a17ae 1999 if (family == AF_INET6)
2000 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
2001 if (family == AF_EVPN)
2002 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
2003}
2004
9bcb3eef 2005bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 2006 struct update_subgroup *subgrp,
7f7940e6 2007 const struct prefix *p, struct attr *attr,
51c3a7de 2008 struct attr *post_attr)
d62a17ae 2009{
2010 struct bgp_filter *filter;
2011 struct peer *from;
2012 struct peer *peer;
2013 struct peer *onlypeer;
2014 struct bgp *bgp;
40381db7 2015 struct attr *piattr;
b68885f9 2016 route_map_result_t ret;
d62a17ae 2017 int transparent;
2018 int reflect;
2019 afi_t afi;
2020 safi_t safi;
2021 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 2022 bool nh_reset = false;
2023 uint64_t cum_bw;
d62a17ae 2024
2025 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 2026 return false;
d62a17ae 2027
2028 afi = SUBGRP_AFI(subgrp);
2029 safi = SUBGRP_SAFI(subgrp);
2030 peer = SUBGRP_PEER(subgrp);
2031 onlypeer = NULL;
2032 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
2033 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
2034
40381db7 2035 from = pi->peer;
d62a17ae 2036 filter = &peer->filter[afi][safi];
2037 bgp = SUBGRP_INST(subgrp);
40381db7
DS
2038 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
2039 : pi->attr;
3f9c7369 2040
d0bf49ec
LS
2041 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
2042 peer->pmax_out[afi][safi] != 0 &&
2043 subgrp->pscount >= peer->pmax_out[afi][safi]) {
2044 if (BGP_DEBUG(update, UPDATE_OUT) ||
2045 BGP_DEBUG(update, UPDATE_PREFIX)) {
2046 zlog_debug("%s reached maximum prefix to be send (%u)",
2047 peer->host, peer->pmax_out[afi][safi]);
2048 }
2049 return false;
2050 }
2051
49e5a4a0 2052#ifdef ENABLE_BGP_VNC
d62a17ae 2053 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
2054 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2055 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 2056
2057 /*
2058 * direct and direct_ext type routes originate internally even
2059 * though they can have peer pointers that reference other
2060 * systems
2061 */
8228a9a7
DS
2062 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2063 __func__, p);
d62a17ae 2064 samepeer_safe = 1;
2065 }
65efcfce
LB
2066#endif
2067
ddb5b488
PZ
2068 if (((afi == AFI_IP) || (afi == AFI_IP6))
2069 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
2070 && (pi->type == ZEBRA_ROUTE_BGP)
2071 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
2072
2073 /* Applies to routes leaked vpn->vrf and vrf->vpn */
2074
2075 samepeer_safe = 1;
2076 }
2077
d62a17ae 2078 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
2079 * pi is valid */
2080 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2081 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2082 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 2083 return false;
d62a17ae 2084 }
adbac85e 2085
d62a17ae 2086 /* If this is not the bestpath then check to see if there is an enabled
2087 * addpath
2088 * feature that requires us to advertise it */
40381db7 2089 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 2090 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 2091 return false;
d62a17ae 2092 }
2093 }
06370dac 2094
d62a17ae 2095 /* Aggregate-address suppress check. */
4056a5f6
RZ
2096 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2097 return false;
3f9c7369 2098
13b7e7f0
DS
2099 /*
2100 * If we are doing VRF 2 VRF leaking via the import
2101 * statement, we want to prevent the route going
2102 * off box as that the RT and RD created are localy
2103 * significant and globaly useless.
2104 */
40381db7
DS
2105 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2106 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 2107 return false;
13b7e7f0 2108
d62a17ae 2109 /* If it's labeled safi, make sure the route has a valid label. */
2110 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 2111 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 2112 if (!bgp_is_valid_label(&label)) {
2113 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2114 zlog_debug("u%" PRIu64 ":s%" PRIu64
2115 " %pFX is filtered - no label (%p)",
d62a17ae 2116 subgrp->update_group->id, subgrp->id,
8228a9a7 2117 p, &label);
3dc339cd 2118 return false;
d62a17ae 2119 }
2120 }
cd1964ff 2121
d62a17ae 2122 /* Do not send back route to sender. */
2123 if (onlypeer && from == onlypeer) {
3dc339cd 2124 return false;
d62a17ae 2125 }
3f9c7369 2126
d62a17ae 2127 /* Do not send the default route in the BGP table if the neighbor is
2128 * configured for default-originate */
2129 if (CHECK_FLAG(peer->af_flags[afi][safi],
2130 PEER_FLAG_DEFAULT_ORIGINATE)) {
2131 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2132 return false;
d62a17ae 2133 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2134 return false;
d62a17ae 2135 }
4125bb67 2136
d62a17ae 2137 /* Transparency check. */
2138 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2139 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2140 transparent = 1;
2141 else
2142 transparent = 0;
2143
2144 /* If community is not disabled check the no-export and local. */
40381db7 2145 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2146 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2147 zlog_debug("%s: community filter check fail for %pFX",
2148 __func__, p);
3dc339cd 2149 return false;
d62a17ae 2150 }
3f9c7369 2151
d62a17ae 2152 /* If the attribute has originator-id and it is same as remote
2153 peer's id. */
40381db7
DS
2154 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2155 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2156 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2157 zlog_debug(
a9f3f4f5
DA
2158 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2159 onlypeer, p);
3dc339cd 2160 return false;
d62a17ae 2161 }
3f9c7369 2162
d62a17ae 2163 /* ORF prefix-list filter check */
2164 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2165 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2166 || CHECK_FLAG(peer->af_cap[afi][safi],
2167 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2168 if (peer->orf_plist[afi][safi]) {
2169 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2170 == PREFIX_DENY) {
2171 if (bgp_debug_update(NULL, p,
2172 subgrp->update_group, 0))
2173 zlog_debug(
a9f3f4f5
DA
2174 "%pBP [Update:SEND] %pFX is filtered via ORF",
2175 peer, p);
3dc339cd 2176 return false;
d62a17ae 2177 }
2178 }
2179
2180 /* Output filter check. */
40381db7 2181 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2182 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2183 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2184 p);
3dc339cd 2185 return false;
d62a17ae 2186 }
3f9c7369 2187
d62a17ae 2188 /* AS path loop check. */
2b31007c
RZ
2189 if (onlypeer && onlypeer->as_path_loop_detection
2190 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2191 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2192 zlog_debug(
a9f3f4f5
DA
2193 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2194 onlypeer, onlypeer->as);
3dc339cd 2195 return false;
d62a17ae 2196 }
3f9c7369 2197
d62a17ae 2198 /* If we're a CONFED we need to loop check the CONFED ID too */
2199 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2200 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2201 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2202 zlog_debug(
a9f3f4f5
DA
2203 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2204 peer, bgp->confed_id);
3dc339cd 2205 return false;
d62a17ae 2206 }
3f9c7369 2207 }
3f9c7369 2208
d62a17ae 2209 /* Route-Reflect check. */
2210 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2211 reflect = 1;
2212 else
2213 reflect = 0;
2214
2215 /* IBGP reflection check. */
2216 if (reflect && !samepeer_safe) {
2217 /* A route from a Client peer. */
2218 if (CHECK_FLAG(from->af_flags[afi][safi],
2219 PEER_FLAG_REFLECTOR_CLIENT)) {
2220 /* Reflect to all the Non-Client peers and also to the
2221 Client peers other than the originator. Originator
2222 check
2223 is already done. So there is noting to do. */
2224 /* no bgp client-to-client reflection check. */
892fedb6
DA
2225 if (CHECK_FLAG(bgp->flags,
2226 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2227 if (CHECK_FLAG(peer->af_flags[afi][safi],
2228 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2229 return false;
d62a17ae 2230 } else {
2231 /* A route from a Non-client peer. Reflect to all other
2232 clients. */
2233 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2234 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2235 return false;
d62a17ae 2236 }
2237 }
3f9c7369 2238
51c3a7de
DA
2239 /* For modify attribute, copy it to temporary structure.
2240 * post_attr comes from BGP conditional advertisements, where
2241 * attributes are already processed by advertise-map route-map,
2242 * and this needs to be saved instead of overwriting from the
2243 * path attributes.
2244 */
2245 if (post_attr)
2246 *attr = *post_attr;
2247 else
2248 *attr = *piattr;
d62a17ae 2249
2250 /* If local-preference is not set. */
2251 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2252 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2253 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2254 attr->local_pref = bgp->default_local_pref;
3f9c7369 2255 }
3f9c7369 2256
d62a17ae 2257 /* If originator-id is not set and the route is to be reflected,
2258 set the originator id */
2259 if (reflect
2260 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2261 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2262 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2263 }
3f9c7369 2264
d62a17ae 2265 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2266 */
2267 if (peer->sort == BGP_PEER_EBGP
2268 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2269 if (from != bgp->peer_self && !transparent
2270 && !CHECK_FLAG(peer->af_flags[afi][safi],
2271 PEER_FLAG_MED_UNCHANGED))
2272 attr->flag &=
2273 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2274 }
3f9c7369 2275
d62a17ae 2276 /* Since the nexthop attribute can vary per peer, it is not explicitly
2277 * set
2278 * in announce check, only certain flags and length (or number of
2279 * nexthops
2280 * -- for IPv6/MP_REACH) are set here in order to guide the update
2281 * formation
2282 * code in setting the nexthop(s) on a per peer basis in
2283 * reformat_peer().
2284 * Typically, the source nexthop in the attribute is preserved but in
2285 * the
2286 * scenarios where we know it will always be overwritten, we reset the
2287 * nexthop to "0" in an attempt to achieve better Update packing. An
2288 * example of this is when a prefix from each of 2 IBGP peers needs to
2289 * be
2290 * announced to an EBGP peer (and they have the same attributes barring
2291 * their nexthop).
2292 */
2293 if (reflect)
2294 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2295
2296#define NEXTHOP_IS_V6 \
2297 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2298 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2299 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2300 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2301
2302 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2303 * if
2304 * the peer (group) is configured to receive link-local nexthop
2305 * unchanged
c728d027
DA
2306 * and it is available in the prefix OR we're not reflecting the route,
2307 * link-local nexthop address is valid and
d62a17ae 2308 * the peer (group) to whom we're going to announce is on a shared
2309 * network
2310 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2311 * By checking if nexthop LL address is valid we are sure that
2312 * we do not announce LL address as `::`.
d62a17ae 2313 */
2314 if (NEXTHOP_IS_V6) {
2315 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2316 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2317 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2318 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2319 || (!reflect && !transparent
c728d027
DA
2320 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2321 && peer->shared_network
d62a17ae 2322 && (from == bgp->peer_self
2323 || peer->sort == BGP_PEER_EBGP))) {
2324 attr->mp_nexthop_len =
2325 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2326 }
3f9c7369 2327
d62a17ae 2328 /* Clear off link-local nexthop in source, whenever it is not
2329 * needed to
2330 * ensure more prefixes share the same attribute for
2331 * announcement.
2332 */
2333 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2334 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2335 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2336 }
3f9c7369 2337
5a78f2bc
EB
2338 if (bgp_check_role_applicability(afi, safi) &&
2339 bgp_otc_egress(peer, attr))
d864dd9e
EB
2340 return false;
2341
d62a17ae 2342 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2343 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2344
0655090c
QY
2345 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2346 filter->advmap.aname &&
2347 route_map_lookup_by_name(filter->advmap.aname)) {
2348 struct bgp_path_info rmap_path = {0};
2349 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2350 struct attr dummy_attr = *attr;
2351
2352 /* Fill temp path_info */
2353 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2354 pi, peer, &dummy_attr);
2355
2356 struct route_map *amap =
2357 route_map_lookup_by_name(filter->advmap.aname);
2358
2359 ret = route_map_apply(amap, p, &rmap_path);
2360
2361 bgp_attr_flush(&dummy_attr);
2362
2363 /*
2364 * The conditional advertisement mode is Withdraw and this
2365 * prefix is a conditional prefix. Don't advertise it
2366 */
2367 if (ret == RMAP_PERMITMATCH)
2368 return false;
2369 }
2370
d62a17ae 2371 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2372 if (!post_attr &&
2373 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2374 struct bgp_path_info rmap_path = {0};
2375 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2376 struct attr dummy_attr = {0};
d62a17ae 2377
e34291b8 2378 /* Fill temp path_info */
9bcb3eef
DS
2379 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2380 pi, peer, attr);
16f7ce2b 2381
d62a17ae 2382 /* don't confuse inbound and outbound setting */
2383 RESET_FLAG(attr->rmap_change_flags);
2384
2385 /*
2386 * The route reflector is not allowed to modify the attributes
2387 * of the reflected IBGP routes unless explicitly allowed.
2388 */
2389 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2390 && !CHECK_FLAG(bgp->flags,
2391 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2392 dummy_attr = *attr;
40381db7 2393 rmap_path.attr = &dummy_attr;
d62a17ae 2394 }
3f9c7369 2395
d62a17ae 2396 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2397
4056a5f6 2398 if (bgp_path_suppressed(pi))
d62a17ae 2399 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2400 &rmap_path);
d62a17ae 2401 else
2402 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2403 &rmap_path);
d62a17ae 2404
7e7639f5 2405 bgp_attr_flush(&dummy_attr);
d62a17ae 2406 peer->rmap_type = 0;
2407
2408 if (ret == RMAP_DENYMATCH) {
778048bf 2409 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2410 zlog_debug(
a9f3f4f5
DA
2411 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2412 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2413 bgp_attr_flush(rmap_path.attr);
3dc339cd 2414 return false;
d62a17ae 2415 }
3f9c7369 2416 }
3f9c7369 2417
9dac9fc8
DA
2418 /* RFC 8212 to prevent route leaks.
2419 * This specification intends to improve this situation by requiring the
2420 * explicit configuration of both BGP Import and Export Policies for any
2421 * External BGP (EBGP) session such as customers, peers, or
2422 * confederation boundaries for all enabled address families. Through
2423 * codification of the aforementioned requirement, operators will
2424 * benefit from consistent behavior across different BGP
2425 * implementations.
2426 */
1d3fdccf 2427 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2428 if (!bgp_outbound_policy_exists(peer, filter)) {
2429 if (monotime_since(&bgp->ebgprequirespolicywarning,
2430 NULL) > FIFTEENMINUTE2USEC ||
2431 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2432 zlog_warn(
2433 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2434 monotime(&bgp->ebgprequirespolicywarning);
2435 }
3dc339cd 2436 return false;
b17826b7 2437 }
9dac9fc8 2438
fb29348a
DA
2439 /* draft-ietf-idr-deprecate-as-set-confed-set
2440 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2441 * Eventually, This document (if approved) updates RFC 4271
2442 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2443 * and obsoletes RFC 6472.
2444 */
7f972cd8 2445 if (peer->bgp->reject_as_sets)
fb29348a 2446 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2447 return false;
fb29348a 2448
8c4d4624 2449 /* If neighbor soo is configured, then check if the route has
01da2d26
DA
2450 * SoO extended community and validate against the configured
2451 * one. If they match, do not announce, to prevent routing
2452 * loops.
2453 */
2454 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2455 peer->soo[afi][safi]) {
2456 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2457 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2458
2459 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2460 ECOMMUNITY_SITE_ORIGIN) ||
2461 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
8c4d4624
TA
2462 ECOMMUNITY_SITE_ORIGIN) ||
2463 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
01da2d26
DA
2464 ECOMMUNITY_SITE_ORIGIN)) &&
2465 ecommunity_include(ecomm, ecomm_soo)) {
2466 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2467 zlog_debug(
2468 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2469 peer, p, ecommunity_str(ecomm_soo));
2470 return false;
2471 }
2472 }
2473
33d022bc
DA
2474 /* Codification of AS 0 Processing */
2475 if (aspath_check_as_zero(attr->aspath))
e2369003 2476 return false;
33d022bc 2477
637e5ba4 2478 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2479 if (peer->sort == BGP_PEER_IBGP
2480 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2481 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2482 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2483 } else {
2484 bgp_attr_add_gshut_community(attr);
2485 }
2486 }
2487
1479ed2f
DA
2488 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2489 * Capability" to a neighbor MUST perform the following upon receiving
2490 * a route from that neighbor with the "LLGR_STALE" community, or upon
2491 * attaching the "LLGR_STALE" community itself per Section 4.2:
2492 *
2493 * The route SHOULD NOT be advertised to any neighbor from which the
2494 * Long-lived Graceful Restart Capability has not been received.
2495 */
9a706b42
DA
2496 if (bgp_attr_get_community(attr) &&
2497 community_include(bgp_attr_get_community(attr),
2498 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2499 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2500 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2501 return false;
2502
d62a17ae 2503 /* After route-map has been applied, we check to see if the nexthop to
2504 * be carried in the attribute (that is used for the announcement) can
2505 * be cleared off or not. We do this in all cases where we would be
2506 * setting the nexthop to "ourselves". For IPv6, we only need to
2507 * consider
2508 * the global nexthop here; the link-local nexthop would have been
2509 * cleared
2510 * already, and if not, it is required by the update formation code.
2511 * Also see earlier comments in this function.
2512 */
2513 /*
2514 * If route-map has performed some operation on the nexthop or the peer
2515 * configuration says to pass it unchanged, we cannot reset the nexthop
2516 * here, so only attempt to do it if these aren't true. Note that the
2517 * route-map handler itself might have cleared the nexthop, if for
2518 * example,
2519 * it is configured as 'peer-address'.
2520 */
2521 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2522 piattr->rmap_change_flags)
d62a17ae 2523 && !transparent
2524 && !CHECK_FLAG(peer->af_flags[afi][safi],
2525 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2526 /* We can reset the nexthop, if setting (or forcing) it to
2527 * 'self' */
2528 if (CHECK_FLAG(peer->af_flags[afi][safi],
2529 PEER_FLAG_NEXTHOP_SELF)
2530 || CHECK_FLAG(peer->af_flags[afi][safi],
2531 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2532 if (!reflect
2533 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2534 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2535 subgroup_announce_reset_nhop(
2536 (peer_cap_enhe(peer, afi, safi)
2537 ? AF_INET6
2538 : p->family),
2539 attr);
7b651a32 2540 nh_reset = true;
2541 }
d62a17ae 2542 } else if (peer->sort == BGP_PEER_EBGP) {
2543 /* Can also reset the nexthop if announcing to EBGP, but
2544 * only if
2545 * no peer in the subgroup is on a shared subnet.
2546 * Note: 3rd party nexthop currently implemented for
2547 * IPv4 only.
2548 */
737af885
BS
2549 if ((p->family == AF_INET) &&
2550 (!bgp_subgrp_multiaccess_check_v4(
2551 piattr->nexthop,
7b651a32 2552 subgrp, from))) {
d62a17ae 2553 subgroup_announce_reset_nhop(
2554 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2555 ? AF_INET6
2556 : p->family),
737af885 2557 attr);
7b651a32 2558 nh_reset = true;
2559 }
737af885
BS
2560
2561 if ((p->family == AF_INET6) &&
2562 (!bgp_subgrp_multiaccess_check_v6(
2563 piattr->mp_nexthop_global,
7b651a32 2564 subgrp, from))) {
737af885
BS
2565 subgroup_announce_reset_nhop(
2566 (peer_cap_enhe(peer, afi, safi)
2567 ? AF_INET6
2568 : p->family),
2569 attr);
7b651a32 2570 nh_reset = true;
2571 }
737af885
BS
2572
2573
2574
40381db7 2575 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2576 /*
2577 * This flag is used for leaked vpn-vrf routes
2578 */
2579 int family = p->family;
2580
2581 if (peer_cap_enhe(peer, afi, safi))
2582 family = AF_INET6;
2583
2584 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2585 zlog_debug(
1defdda8 2586 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2587 __func__, family2str(family));
2588 subgroup_announce_reset_nhop(family, attr);
7b651a32 2589 nh_reset = true;
d62a17ae 2590 }
63696f1d 2591 }
960035b2 2592
63696f1d 2593 /* If IPv6/MP and nexthop does not have any override and happens
2594 * to
2595 * be a link-local address, reset it so that we don't pass along
2596 * the
2597 * source's link-local IPv6 address to recipients who may not be
2598 * on
2599 * the same interface.
2600 */
2601 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2602 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2603 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2604 nh_reset = true;
2605 }
d62a17ae 2606 }
3f9c7369 2607
7b27cf7b
DA
2608 /* If this is an iBGP, send Origin Validation State (OVS)
2609 * extended community (rfc8097).
2610 */
2611 if (peer->sort == BGP_PEER_IBGP) {
2612 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2613
2614 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2615
2616 if (rpki_state != RPKI_NOT_BEING_USED)
2617 bgp_attr_set_ecommunity(
2618 attr, ecommunity_add_origin_validation_state(
2619 rpki_state,
2620 bgp_attr_get_ecommunity(attr)));
2621 }
2622
7b651a32 2623 /*
2624 * When the next hop is set to ourselves, if all multipaths have
2625 * link-bandwidth announce the cumulative bandwidth as that makes
2626 * the most sense. However, don't modify if the link-bandwidth has
2627 * been explicitly set by user policy.
2628 */
2629 if (nh_reset &&
f7e1c681 2630 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2631 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2632 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2633 bgp_attr_set_ecommunity(
2634 attr,
2635 ecommunity_replace_linkbw(
2636 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2637 CHECK_FLAG(
2638 peer->flags,
2639 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2640
3dc339cd 2641 return true;
3f9c7369
DS
2642}
2643
cc9f21da 2644static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2645{
2646 struct afi_safi_info *info;
2647 afi_t afi;
2648 safi_t safi;
2649 struct bgp *bgp;
2650
2651 info = THREAD_ARG(thread);
2652 afi = info->afi;
2653 safi = info->safi;
2654 bgp = info->bgp;
2655
2656 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2657 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2658 safi);
f009ff26 2659
2660 bgp->gr_info[afi][safi].t_route_select = NULL;
2661
2662 XFREE(MTYPE_TMP, info);
2663
2664 /* Best path selection */
cc9f21da 2665 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2666}
2667
9bcb3eef 2668void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2669 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2670 struct bgp_path_info_pair *result, afi_t afi,
2671 safi_t safi)
2672{
2673 struct bgp_path_info *new_select;
2674 struct bgp_path_info *old_select;
40381db7
DS
2675 struct bgp_path_info *pi;
2676 struct bgp_path_info *pi1;
2677 struct bgp_path_info *pi2;
2678 struct bgp_path_info *nextpi = NULL;
d62a17ae 2679 int paths_eq, do_mpath, debug;
2680 struct list mp_list;
2681 char pfx_buf[PREFIX2STR_BUFFER];
2682 char path_buf[PATH_ADDPATH_STR_BUFFER];
2683
2684 bgp_mp_list_init(&mp_list);
2685 do_mpath =
2686 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2687
9bcb3eef 2688 debug = bgp_debug_bestpath(dest);
d62a17ae 2689
2690 if (debug)
9bcb3eef 2691 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2692
9bcb3eef 2693 dest->reason = bgp_path_selection_none;
d62a17ae 2694 /* bgp deterministic-med */
2695 new_select = NULL;
892fedb6 2696 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2697
1defdda8 2698 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2699 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2700 pi1 = pi1->next)
9bcb3eef 2701 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2702 BGP_PATH_DMED_SELECTED);
d62a17ae 2703
9bcb3eef 2704 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2705 pi1 = pi1->next) {
40381db7 2706 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2707 continue;
40381db7 2708 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2709 continue;
ea8b2282 2710 if (pi1->peer != bgp->peer_self)
feb17238 2711 if (!peer_established(pi1->peer))
d62a17ae 2712 continue;
2713
40381db7
DS
2714 new_select = pi1;
2715 if (pi1->next) {
2716 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2717 if (CHECK_FLAG(pi2->flags,
1defdda8 2718 BGP_PATH_DMED_CHECK))
d62a17ae 2719 continue;
40381db7 2720 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2721 continue;
ea8b2282 2722 if (pi2->peer != bgp->peer_self
d62a17ae 2723 && !CHECK_FLAG(
ea8b2282
DS
2724 pi2->peer->sflags,
2725 PEER_STATUS_NSF_WAIT))
40381db7 2726 if (pi2->peer->status
d62a17ae 2727 != Established)
2728 continue;
2729
121e245d
DS
2730 if (!aspath_cmp_left(pi1->attr->aspath,
2731 pi2->attr->aspath)
2732 && !aspath_cmp_left_confed(
40381db7 2733 pi1->attr->aspath,
121e245d
DS
2734 pi2->attr->aspath))
2735 continue;
d62a17ae 2736
121e245d
DS
2737 if (bgp_path_info_cmp(
2738 bgp, pi2, new_select,
2739 &paths_eq, mpath_cfg, debug,
fdf81fa0 2740 pfx_buf, afi, safi,
9bcb3eef 2741 &dest->reason)) {
121e245d 2742 bgp_path_info_unset_flag(
9bcb3eef 2743 dest, new_select,
121e245d
DS
2744 BGP_PATH_DMED_SELECTED);
2745 new_select = pi2;
d62a17ae 2746 }
121e245d
DS
2747
2748 bgp_path_info_set_flag(
9bcb3eef 2749 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2750 }
2751 }
9bcb3eef 2752 bgp_path_info_set_flag(dest, new_select,
18ee8310 2753 BGP_PATH_DMED_CHECK);
9bcb3eef 2754 bgp_path_info_set_flag(dest, new_select,
18ee8310 2755 BGP_PATH_DMED_SELECTED);
d62a17ae 2756
2757 if (debug) {
18ee8310 2758 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2759 new_select, path_buf, sizeof(path_buf));
8228a9a7 2760 zlog_debug(
4378495a
DS
2761 "%pBD(%s): %s is the bestpath from AS %u",
2762 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2763 aspath_get_first_as(
2764 new_select->attr->aspath));
d62a17ae 2765 }
2766 }
2767 }
96450faf 2768
d62a17ae 2769 /* Check old selected route and new selected route. */
2770 old_select = NULL;
2771 new_select = NULL;
9bcb3eef 2772 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2773 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2774 enum bgp_path_selection_reason reason;
2775
40381db7
DS
2776 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2777 old_select = pi;
d62a17ae 2778
40381db7 2779 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2780 /* reap REMOVED routes, if needs be
2781 * selected route must stay for a while longer though
2782 */
40381db7
DS
2783 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2784 && (pi != old_select))
9bcb3eef 2785 bgp_path_info_reap(dest, pi);
d62a17ae 2786
ddb5b488 2787 if (debug)
40381db7
DS
2788 zlog_debug("%s: pi %p in holddown", __func__,
2789 pi);
ddb5b488 2790
d62a17ae 2791 continue;
2792 }
96450faf 2793
40381db7
DS
2794 if (pi->peer && pi->peer != bgp->peer_self
2795 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2796 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2797
2798 if (debug)
2799 zlog_debug(
40381db7
DS
2800 "%s: pi %p non self peer %s not estab state",
2801 __func__, pi, pi->peer->host);
ddb5b488 2802
d62a17ae 2803 continue;
ddb5b488 2804 }
9fbdd100 2805
892fedb6 2806 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2807 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2808 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2809 if (debug)
40381db7 2810 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2811 continue;
2812 }
9fbdd100 2813
9bcb3eef 2814 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2815
9bcb3eef 2816 reason = dest->reason;
40381db7 2817 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2818 debug, pfx_buf, afi, safi,
2819 &dest->reason)) {
19ea4cec
DS
2820 if (new_select == NULL &&
2821 reason != bgp_path_selection_none)
9bcb3eef 2822 dest->reason = reason;
40381db7 2823 new_select = pi;
d62a17ae 2824 }
2825 }
718e3744 2826
d62a17ae 2827 /* Now that we know which path is the bestpath see if any of the other
2828 * paths
2829 * qualify as multipaths
2830 */
2831 if (debug) {
2832 if (new_select)
7533cad7
QY
2833 bgp_path_info_path_with_addpath_rx_str(
2834 new_select, path_buf, sizeof(path_buf));
d62a17ae 2835 else
772270f3 2836 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2837 zlog_debug(
4378495a
DS
2838 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2839 dest, bgp->name_pretty, path_buf,
d62a17ae 2840 old_select ? old_select->peer->host : "NONE");
96450faf 2841 }
9fbdd100 2842
d62a17ae 2843 if (do_mpath && new_select) {
9bcb3eef 2844 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2845 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2846
2847 if (debug)
18ee8310 2848 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2849 pi, path_buf, sizeof(path_buf));
d62a17ae 2850
40381db7 2851 if (pi == new_select) {
d62a17ae 2852 if (debug)
2853 zlog_debug(
4378495a
DS
2854 "%pBD(%s): %s is the bestpath, add to the multipath list",
2855 dest, bgp->name_pretty,
2856 path_buf);
40381db7 2857 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2858 continue;
2859 }
2860
40381db7 2861 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2862 continue;
2863
40381db7
DS
2864 if (pi->peer && pi->peer != bgp->peer_self
2865 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2866 PEER_STATUS_NSF_WAIT))
feb17238 2867 if (!peer_established(pi->peer))
d62a17ae 2868 continue;
2869
40381db7 2870 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2871 if (debug)
2872 zlog_debug(
8228a9a7
DS
2873 "%pBD: %s has the same nexthop as the bestpath, skip it",
2874 dest, path_buf);
d62a17ae 2875 continue;
2876 }
2877
40381db7 2878 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2879 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2880 &dest->reason);
d62a17ae 2881
2882 if (paths_eq) {
2883 if (debug)
2884 zlog_debug(
8228a9a7
DS
2885 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2886 dest, path_buf);
40381db7 2887 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2888 }
2889 }
2890 }
fee0f4c6 2891
4378495a 2892 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2893 mpath_cfg);
2894 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2895 bgp_mp_list_clear(&mp_list);
96450faf 2896
9bcb3eef 2897 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2898
d62a17ae 2899 result->old = old_select;
2900 result->new = new_select;
96450faf 2901
d62a17ae 2902 return;
fee0f4c6 2903}
2904
3f9c7369
DS
2905/*
2906 * A new route/change in bestpath of an existing route. Evaluate the path
2907 * for advertisement to the subgroup.
2908 */
3dc339cd
DA
2909void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2910 struct bgp_path_info *selected,
9bcb3eef 2911 struct bgp_dest *dest,
3dc339cd 2912 uint32_t addpath_tx_id)
d62a17ae 2913{
b54892e0 2914 const struct prefix *p;
d62a17ae 2915 struct peer *onlypeer;
2916 struct attr attr;
2917 afi_t afi;
2918 safi_t safi;
a77e2f4b
S
2919 struct bgp *bgp;
2920 bool advertise;
adbac85e 2921
9bcb3eef 2922 p = bgp_dest_get_prefix(dest);
d62a17ae 2923 afi = SUBGRP_AFI(subgrp);
2924 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2925 bgp = SUBGRP_INST(subgrp);
d62a17ae 2926 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2927 : NULL);
2928
2dbe669b
DA
2929 if (BGP_DEBUG(update, UPDATE_OUT))
2930 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2931
d62a17ae 2932 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2933 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2934 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2935 return;
d62a17ae 2936
6006b807 2937 memset(&attr, 0, sizeof(attr));
d62a17ae 2938 /* It's initialized in bgp_announce_check() */
2939
a77e2f4b
S
2940 /* Announcement to the subgroup. If the route is filtered withdraw it.
2941 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2942 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2943 * route
d62a17ae 2944 */
a77e2f4b
S
2945 advertise = bgp_check_advertise(bgp, dest);
2946
d62a17ae 2947 if (selected) {
7f7940e6 2948 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2949 NULL)) {
a77e2f4b
S
2950 /* Route is selected, if the route is already installed
2951 * in FIB, then it is advertised
2952 */
be785e35
DS
2953 if (advertise) {
2954 if (!bgp_check_withdrawal(bgp, dest))
2955 bgp_adj_out_set_subgroup(
2956 dest, subgrp, &attr, selected);
2957 else
2958 bgp_adj_out_unset_subgroup(
2959 dest, subgrp, 1, addpath_tx_id);
2960 }
a77e2f4b 2961 } else
9bcb3eef 2962 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2963 addpath_tx_id);
d62a17ae 2964 }
2965
2966 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2967 else {
9bcb3eef 2968 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2969 }
200df115 2970}
fee0f4c6 2971
3064bf43 2972/*
e1072051 2973 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2974 * This is called at the end of route processing.
3064bf43 2975 */
9bcb3eef 2976void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2977{
40381db7 2978 struct bgp_path_info *pi;
3064bf43 2979
9bcb3eef 2980 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2981 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2982 continue;
40381db7
DS
2983 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2984 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2985 }
3064bf43 2986}
2987
2988/*
2989 * Has the route changed from the RIB's perspective? This is invoked only
2990 * if the route selection returns the same best route as earlier - to
2991 * determine if we need to update zebra or not.
2992 */
9bcb3eef 2993bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2994{
4b7e6066 2995 struct bgp_path_info *mpinfo;
d62a17ae 2996
2bb9eff4
DS
2997 /* If this is multipath, check all selected paths for any nexthop
2998 * change or attribute change. Some attribute changes (e.g., community)
2999 * aren't of relevance to the RIB, but we'll update zebra to ensure
3000 * we handle the case of BGP nexthop change. This is the behavior
3001 * when the best path has an attribute change anyway.
d62a17ae 3002 */
1defdda8 3003 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 3004 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
3005 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 3006 return true;
d62a17ae 3007
2bb9eff4
DS
3008 /*
3009 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 3010 */
18ee8310
DS
3011 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
3012 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
3013 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
3014 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 3015 return true;
d62a17ae 3016 }
3064bf43 3017
d62a17ae 3018 /* Nothing has changed from the RIB's perspective. */
3dc339cd 3019 return false;
3064bf43 3020}
3021
d62a17ae 3022struct bgp_process_queue {
3023 struct bgp *bgp;
9bcb3eef 3024 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
3025#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
3026 unsigned int flags;
3027 unsigned int queued;
200df115 3028};
3029
3b0c17e1 3030static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 3031 safi_t safi, struct bgp_dest *dest,
3b0c17e1 3032 struct bgp_path_info *new_select,
3033 struct bgp_path_info *old_select)
3034{
9bcb3eef 3035 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 3036
3037 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
3038 return;
3039
3040 if (advertise_type5_routes(bgp, afi) && new_select
3041 && is_route_injectable_into_evpn(new_select)) {
3042
3043 /* apply the route-map */
3044 if (bgp->adv_cmd_rmap[afi][safi].map) {
3045 route_map_result_t ret;
3046 struct bgp_path_info rmap_path;
3047 struct bgp_path_info_extra rmap_path_extra;
3048 struct attr dummy_attr;
3049
3050 dummy_attr = *new_select->attr;
3051
3052 /* Fill temp path_info */
9bcb3eef 3053 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 3054 new_select, new_select->peer,
3055 &dummy_attr);
3056
3057 RESET_FLAG(dummy_attr.rmap_change_flags);
3058
3059 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 3060 p, &rmap_path);
3b0c17e1 3061
3062 if (ret == RMAP_DENYMATCH) {
3063 bgp_attr_flush(&dummy_attr);
3064 bgp_evpn_withdraw_type5_route(bgp, p, afi,
3065 safi);
3066 } else
3067 bgp_evpn_advertise_type5_route(
3068 bgp, p, &dummy_attr, afi, safi);
3069 } else {
3070 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3071 afi, safi);
3072 }
3073 } else if (advertise_type5_routes(bgp, afi) && old_select
3074 && is_route_injectable_into_evpn(old_select))
3075 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3076}
3077
bb2ca692
MS
3078/*
3079 * Utility to determine whether a particular path_info should use
3080 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3081 * in a path where we basically _know_ this is a BGP-LU route.
3082 */
3083static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3084{
3085 /* Certain types get imp null; so do paths where the nexthop is
3086 * not labeled.
3087 */
3088 if (new_select->sub_type == BGP_ROUTE_STATIC
3089 || new_select->sub_type == BGP_ROUTE_AGGREGATE
3090 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3091 return true;
3092 else if (new_select->extra == NULL ||
3093 !bgp_is_valid_label(&new_select->extra->label[0]))
3094 /* TODO -- should be configurable? */
3095 return true;
3096 else
3097 return false;
3098}
3099
3103e8d2
DS
3100/*
3101 * old_select = The old best path
3102 * new_select = the new best path
3103 *
3104 * if (!old_select && new_select)
3105 * We are sending new information on.
3106 *
3107 * if (old_select && new_select) {
3108 * if (new_select != old_select)
3109 * We have a new best path send a change
3110 * else
3111 * We've received a update with new attributes that needs
3112 * to be passed on.
3113 * }
3114 *
3115 * if (old_select && !new_select)
3116 * We have no eligible route that we can announce or the rn
3117 * is being removed.
3118 */
9bcb3eef 3119static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3120 afi_t afi, safi_t safi)
d62a17ae 3121{
4b7e6066
DS
3122 struct bgp_path_info *new_select;
3123 struct bgp_path_info *old_select;
3124 struct bgp_path_info_pair old_and_new;
ddb5b488 3125 int debug = 0;
d62a17ae 3126
892fedb6 3127 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3128 if (dest)
3129 debug = bgp_debug_bestpath(dest);
b54892e0 3130 if (debug)
f4c713ae 3131 zlog_debug(
56ca3b5b 3132 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3133 __func__, dest);
f4c713ae
LB
3134 return;
3135 }
d62a17ae 3136 /* Is it end of initial update? (after startup) */
9bcb3eef 3137 if (!dest) {
e36f61b5
DS
3138 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3139 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3140
3141 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3142 FOREACH_AFI_SAFI (afi, safi) {
3143 if (bgp_fibupd_safi(safi))
3144 bgp_zebra_announce_table(bgp, afi, safi);
3145 }
d62a17ae 3146 bgp->main_peers_update_hold = 0;
3147
3148 bgp_start_routeadv(bgp);
aac24838 3149 return;
d62a17ae 3150 }
cb1faec9 3151
9bcb3eef 3152 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3153
9bcb3eef 3154 debug = bgp_debug_bestpath(dest);
b54892e0 3155 if (debug)
4378495a
DS
3156 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3157 dest, bgp->name_pretty, afi2str(afi),
3158 safi2str(safi));
ddb5b488 3159
f009ff26 3160 /* The best path calculation for the route is deferred if
3161 * BGP_NODE_SELECT_DEFER is set
3162 */
9bcb3eef 3163 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3164 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3165 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3166 return;
3167 }
3168
d62a17ae 3169 /* Best path selection. */
9bcb3eef 3170 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3171 afi, safi);
3172 old_select = old_and_new.old;
3173 new_select = old_and_new.new;
3174
3175 /* Do we need to allocate or free labels?
3176 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3177 * necessary to do this upon changes to best path. Exceptions:
3178 * - label index has changed -> recalculate resulting label
3179 * - path_info sub_type changed -> switch to/from implicit-null
3180 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3181 */
318cac96 3182 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3183 if (new_select) {
3184 if (!old_select
3185 || bgp_label_index_differs(new_select, old_select)
57592a53 3186 || new_select->sub_type != old_select->sub_type
9bcb3eef 3187 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3188 /* Enforced penultimate hop popping:
3189 * implicit-null for local routes, aggregate
3190 * and redistributed routes
3191 */
bb2ca692 3192 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3193 if (CHECK_FLAG(
9bcb3eef 3194 dest->flags,
992dd67e
PR
3195 BGP_NODE_REGISTERED_FOR_LABEL)
3196 || CHECK_FLAG(
3197 dest->flags,
3198 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3199 bgp_unregister_for_label(dest);
67f67ba4
DA
3200 dest->local_label = mpls_lse_encode(
3201 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3202 1);
9bcb3eef 3203 bgp_set_valid_label(&dest->local_label);
d62a17ae 3204 } else
9bcb3eef
DS
3205 bgp_register_for_label(dest,
3206 new_select);
d62a17ae 3207 }
9bcb3eef 3208 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3209 BGP_NODE_REGISTERED_FOR_LABEL)
3210 || CHECK_FLAG(dest->flags,
3211 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3212 bgp_unregister_for_label(dest);
318cac96 3213 }
992dd67e
PR
3214 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3215 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3216 bgp_unregister_for_label(dest);
d62a17ae 3217 }
cd1964ff 3218
b54892e0 3219 if (debug)
ddb5b488 3220 zlog_debug(
4378495a
DS
3221 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3222 __func__, dest, bgp->name_pretty, afi2str(afi),
3223 safi2str(safi), old_select, new_select);
ddb5b488 3224
d62a17ae 3225 /* If best route remains the same and this is not due to user-initiated
3226 * clear, see exactly what needs to be done.
3227 */
d62a17ae 3228 if (old_select && old_select == new_select
9bcb3eef 3229 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3230 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3231 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3232 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3233#ifdef ENABLE_BGP_VNC
d62a17ae 3234 vnc_import_bgp_add_route(bgp, p, old_select);
3235 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3236#endif
bb744275 3237 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3238 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3239
be785e35
DS
3240 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3241 && new_select->sub_type == BGP_ROUTE_NORMAL)
3242 SET_FLAG(dest->flags,
3243 BGP_NODE_FIB_INSTALL_PENDING);
3244
ddb5b488
PZ
3245 if (new_select->type == ZEBRA_ROUTE_BGP
3246 && (new_select->sub_type == BGP_ROUTE_NORMAL
3247 || new_select->sub_type
3248 == BGP_ROUTE_IMPORTED))
3249
9bcb3eef 3250 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3251 bgp, afi, safi);
3252 }
d62a17ae 3253 }
d62a17ae 3254
3255 /* If there is a change of interest to peers, reannounce the
3256 * route. */
1defdda8 3257 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3258 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3259 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3260 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3261
3262 /* unicast routes must also be annouced to
3263 * labeled-unicast update-groups */
3264 if (safi == SAFI_UNICAST)
3265 group_announce_route(bgp, afi,
9bcb3eef 3266 SAFI_LABELED_UNICAST, dest,
d62a17ae 3267 new_select);
3268
1defdda8 3269 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3270 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3271 }
fee0f4c6 3272
3b0c17e1 3273 /* advertise/withdraw type-5 routes */
3274 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3275 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3276 bgp_process_evpn_route_injection(
9bcb3eef 3277 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3278
b1875e65 3279 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3280 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3281 bgp_zebra_clear_route_change_flags(dest);
3282 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3283 return;
d62a17ae 3284 }
8ad7271d 3285
d62a17ae 3286 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3287 */
9bcb3eef 3288 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3289
3290 /* bestpath has changed; bump version */
3291 if (old_select || new_select) {
9bcb3eef 3292 bgp_bump_version(dest);
d62a17ae 3293
3294 if (!bgp->t_rmap_def_originate_eval) {
3295 bgp_lock(bgp);
3296 thread_add_timer(
3297 bm->master,
3298 update_group_refresh_default_originate_route_map,
3299 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3300 &bgp->t_rmap_def_originate_eval);
3301 }
3302 }
3f9c7369 3303
d62a17ae 3304 if (old_select)
9bcb3eef 3305 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3306 if (new_select) {
ddb5b488
PZ
3307 if (debug)
3308 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3309 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3310 bgp_path_info_unset_flag(dest, new_select,
3311 BGP_PATH_ATTR_CHANGED);
1defdda8 3312 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3313 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3314 }
338b3424 3315
49e5a4a0 3316#ifdef ENABLE_BGP_VNC
d62a17ae 3317 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3318 if (old_select != new_select) {
3319 if (old_select) {
3320 vnc_import_bgp_exterior_del_route(bgp, p,
3321 old_select);
3322 vnc_import_bgp_del_route(bgp, p, old_select);
3323 }
3324 if (new_select) {
3325 vnc_import_bgp_exterior_add_route(bgp, p,
3326 new_select);
3327 vnc_import_bgp_add_route(bgp, p, new_select);
3328 }
3329 }
3330 }
65efcfce
LB
3331#endif
3332
9bcb3eef 3333 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3334
3335 /* unicast routes must also be annouced to labeled-unicast update-groups
3336 */
3337 if (safi == SAFI_UNICAST)
9bcb3eef 3338 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3339 new_select);
3340
3341 /* FIB update. */
3342 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3343 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3344
d62a17ae 3345 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3346 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3347 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3348 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3349
be785e35
DS
3350 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3351 SET_FLAG(dest->flags,
3352 BGP_NODE_FIB_INSTALL_PENDING);
3353
2b659f33
MK
3354 /* if this is an evpn imported type-5 prefix,
3355 * we need to withdraw the route first to clear
3356 * the nh neigh and the RMAC entry.
3357 */
3358 if (old_select &&
3359 is_route_parent_evpn(old_select))
3360 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3361
9bcb3eef 3362 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3363 } else {
d62a17ae 3364 /* Withdraw the route from the kernel. */
3365 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3366 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3367 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3368 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3369
568e10ca 3370 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3371 }
718e3744 3372 }
3064bf43 3373
9bcb3eef 3374 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3375 old_select);
5424b7ba 3376
d62a17ae 3377 /* Clear any route change flags. */
9bcb3eef 3378 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3379
18ee8310 3380 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3381 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3382 bgp_path_info_reap(dest, old_select);
d62a17ae 3383
9bcb3eef 3384 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3385 return;
718e3744 3386}
3387
f009ff26 3388/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3389void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3390{
9bcb3eef 3391 struct bgp_dest *dest;
f009ff26 3392 int cnt = 0;
3393 struct afi_safi_info *thread_info;
f009ff26 3394
56c226e7
DS
3395 if (bgp->gr_info[afi][safi].t_route_select) {
3396 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3397
3398 thread_info = THREAD_ARG(t);
3399 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3400 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3401 }
f009ff26 3402
3403 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3404 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3405 get_afi_safi_str(afi, safi, false),
26742171 3406 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3407 }
3408
3409 /* Process the route list */
6338d242 3410 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3411 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3412 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3413 dest = bgp_route_next(dest)) {
3414 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3415 continue;
3416
3417 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3418 bgp->gr_info[afi][safi].gr_deferred--;
3419 bgp_process_main_one(bgp, dest, afi, safi);
3420 cnt++;
067ea165
CB
3421 }
3422 /* If iteration stopped before the entire table was traversed then the
3423 * node needs to be unlocked.
3424 */
3425 if (dest) {
3426 bgp_dest_unlock_node(dest);
3427 dest = NULL;
f009ff26 3428 }
3429
9e3b51a7 3430 /* Send EOR message when all routes are processed */
6338d242 3431 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3432 bgp_send_delayed_eor(bgp);
8c48b3b6 3433 /* Send route processing complete message to RIB */
3434 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3435 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3436 return;
9e3b51a7 3437 }
f009ff26 3438
3439 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3440
3441 thread_info->afi = afi;
3442 thread_info->safi = safi;
3443 thread_info->bgp = bgp;
3444
3445 /* If there are more routes to be processed, start the
3446 * selection timer
3447 */
3448 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3449 BGP_ROUTE_SELECT_DELAY,
3450 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3451}
3452
aac24838 3453static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3454{
aac24838
JB
3455 struct bgp_process_queue *pqnode = data;
3456 struct bgp *bgp = pqnode->bgp;
d62a17ae 3457 struct bgp_table *table;
9bcb3eef 3458 struct bgp_dest *dest;
aac24838
JB
3459
3460 /* eoiu marker */
3461 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3462 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3463 /* should always have dedicated wq call */
3464 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3465 return WQ_SUCCESS;
3466 }
3467
ac021f40 3468 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3469 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3470 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3471 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3472 table = bgp_dest_table(dest);
3473 /* note, new DESTs may be added as part of processing */
3474 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3475
9bcb3eef 3476 bgp_dest_unlock_node(dest);
d62a17ae 3477 bgp_table_unlock(table);
3478 }
aac24838
JB
3479
3480 return WQ_SUCCESS;
3481}
3482
3483static void bgp_processq_del(struct work_queue *wq, void *data)
3484{
3485 struct bgp_process_queue *pqnode = data;
3486
3487 bgp_unlock(pqnode->bgp);
3488
3489 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3490}
3491
b6c386bb 3492void bgp_process_queue_init(struct bgp *bgp)
200df115 3493{
b6c386bb
DS
3494 if (!bgp->process_queue) {
3495 char name[BUFSIZ];
3496
3497 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3498 bgp->process_queue = work_queue_new(bm->master, name);
3499 }
3500
3501 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3502 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3503 bgp->process_queue->spec.max_retries = 0;
3504 bgp->process_queue->spec.hold = 50;
d62a17ae 3505 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3506 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3507}
3508
cfe8d15a 3509static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3510{
3511 struct bgp_process_queue *pqnode;
3512
a4d82a8a
PZ
3513 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3514 sizeof(struct bgp_process_queue));
aac24838
JB
3515
3516 /* unlocked in bgp_processq_del */
3517 pqnode->bgp = bgp_lock(bgp);
3518 STAILQ_INIT(&pqnode->pqueue);
3519
aac24838
JB
3520 return pqnode;
3521}
3522
9bcb3eef 3523void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3524{
aac24838 3525#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3526 struct work_queue *wq = bgp->process_queue;
d62a17ae 3527 struct bgp_process_queue *pqnode;
cfe8d15a 3528 int pqnode_reuse = 0;
495f0b13 3529
d62a17ae 3530 /* already scheduled for processing? */
9bcb3eef 3531 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3532 return;
2e02b9b2 3533
f009ff26 3534 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3535 * the workqueue
3536 */
9bcb3eef 3537 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3538 if (BGP_DEBUG(update, UPDATE_OUT))
3539 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3540 dest);
f009ff26 3541 return;
3542 }
3543
46aeabed
LS
3544 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3545 if (BGP_DEBUG(update, UPDATE_OUT))
3546 zlog_debug(
3547 "Soft reconfigure table in progress for route %p",
3548 dest);
3549 return;
3550 }
3551
aac24838 3552 if (wq == NULL)
d62a17ae 3553 return;
3554
aac24838 3555 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3556 limit only if is from the same BGP view and it's not an EOIU marker
3557 */
aac24838
JB
3558 if (work_queue_item_count(wq)) {
3559 struct work_queue_item *item = work_queue_last_item(wq);
3560 pqnode = item->data;
228da428 3561
a4d82a8a
PZ
3562 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3563 || pqnode->bgp != bgp
3564 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3565 pqnode = bgp_processq_alloc(bgp);
3566 else
3567 pqnode_reuse = 1;
aac24838 3568 } else
cfe8d15a 3569 pqnode = bgp_processq_alloc(bgp);
aac24838 3570 /* all unlocked in bgp_process_wq */
9bcb3eef 3571 bgp_table_lock(bgp_dest_table(dest));
aac24838 3572
9bcb3eef
DS
3573 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3574 bgp_dest_lock_node(dest);
aac24838 3575
60466a63 3576 /* can't be enqueued twice */
9bcb3eef
DS
3577 assert(STAILQ_NEXT(dest, pq) == NULL);
3578 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3579 pqnode->queued++;
3580
cfe8d15a
LB
3581 if (!pqnode_reuse)
3582 work_queue_add(wq, pqnode);
3583
d62a17ae 3584 return;
fee0f4c6 3585}
0a486e5f 3586
d62a17ae 3587void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3588{
d62a17ae 3589 struct bgp_process_queue *pqnode;
cb1faec9 3590
b6c386bb 3591 if (bgp->process_queue == NULL)
d62a17ae 3592 return;
2e02b9b2 3593
cfe8d15a 3594 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3595
aac24838 3596 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3597 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3598}
3599
cc9f21da 3600static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3601{
d62a17ae 3602 struct peer *peer;
0a486e5f 3603
d62a17ae 3604 peer = THREAD_ARG(thread);
3605 peer->t_pmax_restart = NULL;
0a486e5f 3606
d62a17ae 3607 if (bgp_debug_neighbor_events(peer))
3608 zlog_debug(
3609 "%s Maximum-prefix restart timer expired, restore peering",
3610 peer->host);
0a486e5f 3611
a9bafa95 3612 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3613 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3614}
3615
9cbd06e0
DA
3616static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3617 safi_t safi)
3618{
3619 uint32_t count = 0;
f41b0459 3620 bool filtered = false;
9cbd06e0
DA
3621 struct bgp_dest *dest;
3622 struct bgp_adj_in *ain;
40bb2ccf 3623 struct attr attr = {};
9cbd06e0
DA
3624 struct bgp_table *table = peer->bgp->rib[afi][safi];
3625
3626 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3627 for (ain = dest->adj_in; ain; ain = ain->next) {
3628 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3629
3630 attr = *ain->attr;
9cbd06e0
DA
3631
3632 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3633 == FILTER_DENY)
f41b0459
DA
3634 filtered = true;
3635
3636 if (bgp_input_modifier(
3637 peer, rn_p, &attr, afi, safi,
3638 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3639 NULL, 0, NULL)
3640 == RMAP_DENY)
3641 filtered = true;
3642
3643 if (filtered)
9cbd06e0 3644 count++;
f41b0459 3645
d498917e 3646 bgp_attr_flush(&attr);
9cbd06e0
DA
3647 }
3648 }
3649
3650 return count;
3651}
3652
3dc339cd
DA
3653bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3654 int always)
718e3744 3655{
d62a17ae 3656 iana_afi_t pkt_afi;
5c525538 3657 iana_safi_t pkt_safi;
9cbd06e0
DA
3658 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3659 PEER_FLAG_MAX_PREFIX_FORCE))
3660 ? bgp_filtered_routes_count(peer, afi, safi)
3661 + peer->pcount[afi][safi]
3662 : peer->pcount[afi][safi];
9cabb64b 3663
d62a17ae 3664 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3665 return false;
e0701b79 3666
9cbd06e0 3667 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3668 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3669 PEER_STATUS_PREFIX_LIMIT)
3670 && !always)
3dc339cd 3671 return false;
e0701b79 3672
d62a17ae 3673 zlog_info(
f70c91dc
DA
3674 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3675 get_afi_safi_str(afi, safi, false), peer, pcount,
3676 peer->pmax[afi][safi]);
d62a17ae 3677 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3678
3679 if (CHECK_FLAG(peer->af_flags[afi][safi],
3680 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3681 return false;
d62a17ae 3682
3683 /* Convert AFI, SAFI to values for packet. */
3684 pkt_afi = afi_int2iana(afi);
3685 pkt_safi = safi_int2iana(safi);
3686 {
d7c0a89a 3687 uint8_t ndata[7];
d62a17ae 3688
3689 ndata[0] = (pkt_afi >> 8);
3690 ndata[1] = pkt_afi;
3691 ndata[2] = pkt_safi;
3692 ndata[3] = (peer->pmax[afi][safi] >> 24);
3693 ndata[4] = (peer->pmax[afi][safi] >> 16);
3694 ndata[5] = (peer->pmax[afi][safi] >> 8);
3695 ndata[6] = (peer->pmax[afi][safi]);
3696
3697 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3698 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3699 BGP_NOTIFY_CEASE_MAX_PREFIX,
3700 ndata, 7);
3701 }
3702
3703 /* Dynamic peers will just close their connection. */
3704 if (peer_dynamic_neighbor(peer))
3dc339cd 3705 return true;
d62a17ae 3706
3707 /* restart timer start */
3708 if (peer->pmax_restart[afi][safi]) {
3709 peer->v_pmax_restart =
3710 peer->pmax_restart[afi][safi] * 60;
3711
3712 if (bgp_debug_neighbor_events(peer))
3713 zlog_debug(
f70c91dc
DA
3714 "%pBP Maximum-prefix restart timer started for %d secs",
3715 peer, peer->v_pmax_restart);
d62a17ae 3716
3717 BGP_TIMER_ON(peer->t_pmax_restart,
3718 bgp_maximum_prefix_restart_timer,
3719 peer->v_pmax_restart);
3720 }
3721
3dc339cd 3722 return true;
d62a17ae 3723 } else
3724 UNSET_FLAG(peer->af_sflags[afi][safi],
3725 PEER_STATUS_PREFIX_LIMIT);
3726
b1823b69
DS
3727 if (pcount
3728 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3729 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3730 PEER_STATUS_PREFIX_THRESHOLD)
3731 && !always)
3dc339cd 3732 return false;
d62a17ae 3733
3734 zlog_info(
f70c91dc
DA
3735 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3736 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3737 peer->pmax[afi][safi]);
d62a17ae 3738 SET_FLAG(peer->af_sflags[afi][safi],
3739 PEER_STATUS_PREFIX_THRESHOLD);
3740 } else
3741 UNSET_FLAG(peer->af_sflags[afi][safi],
3742 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3743 return false;
718e3744 3744}
3745
b40d939b 3746/* Unconditionally remove the route from the RIB, without taking
3747 * damping into consideration (eg, because the session went down)
3748 */
9bcb3eef 3749void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3750 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3751{
f009ff26 3752
3753 struct bgp *bgp = NULL;
3754 bool delete_route = false;
3755
9bcb3eef
DS
3756 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3757 safi);
d62a17ae 3758
f009ff26 3759 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3760 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3761
f009ff26 3762 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3763 * flag
3764 */
3765 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3766 delete_route = true;
9bcb3eef 3767 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3768 delete_route = true;
f009ff26 3769 if (delete_route) {
9bcb3eef
DS
3770 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3771 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3772 bgp = pi->peer->bgp;
26742171 3773 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3774 }
3775 }
3776 }
4a11bf2c 3777
9bcb3eef
DS
3778 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3779 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3780}
3781
9bcb3eef 3782static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3783 struct peer *peer, afi_t afi, safi_t safi,
3784 struct prefix_rd *prd)
3785{
9bcb3eef 3786 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3787
d62a17ae 3788 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3789 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3790 */
b4f7f45b
IR
3791 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3792 && peer->sort == BGP_PEER_EBGP)
3793 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3794 == BGP_DAMP_SUPPRESSED) {
3795 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3796 safi);
3797 return;
d62a17ae 3798 }
3799
49e5a4a0 3800#ifdef ENABLE_BGP_VNC
d62a17ae 3801 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3802 struct bgp_dest *pdest = NULL;
d62a17ae 3803 struct bgp_table *table = NULL;
3804
9bcb3eef
DS
3805 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3806 (struct prefix *)prd);
3807 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3808 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3809
3810 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3811 peer->bgp, prd, table, p, pi);
d62a17ae 3812 }
9bcb3eef 3813 bgp_dest_unlock_node(pdest);
d62a17ae 3814 }
3815 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3816 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3817
b54892e0
DS
3818 vnc_import_bgp_del_route(peer->bgp, p, pi);
3819 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3820 }
65efcfce 3821 }
d62a17ae 3822#endif
128ea8ab 3823
d62a17ae 3824 /* If this is an EVPN route, process for un-import. */
3825 if (safi == SAFI_EVPN)
b54892e0 3826 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3827
9bcb3eef 3828 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3829}
3830
4b7e6066
DS
3831struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3832 struct peer *peer, struct attr *attr,
9bcb3eef 3833 struct bgp_dest *dest)
fb018d25 3834{
4b7e6066 3835 struct bgp_path_info *new;
fb018d25 3836
d62a17ae 3837 /* Make new BGP info. */
4b7e6066 3838 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3839 new->type = type;
3840 new->instance = instance;
3841 new->sub_type = sub_type;
3842 new->peer = peer;
3843 new->attr = attr;
083ec940 3844 new->uptime = monotime(NULL);
9bcb3eef 3845 new->net = dest;
d62a17ae 3846 return new;
fb018d25
DS
3847}
3848
c265ee22 3849/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3850bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3851 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3852 struct bgp_dest *dest)
d62a17ae 3853{
2dbe3fa9 3854 bool ret = false;
b099a5c8
DA
3855 bool is_bgp_static_route =
3856 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3857 : false;
d62a17ae 3858
e8442016
DS
3859 /*
3860 * Only validated for unicast and multicast currently.
3861 * Also valid for EVPN where the nexthop is an IP address.
3862 * If we are a bgp static route being checked then there is
3863 * no need to check to see if the nexthop is martian as
3864 * that it should be ok.
3865 */
3866 if (is_bgp_static_route ||
3867 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3868 return false;
d62a17ae 3869
3870 /* If NEXT_HOP is present, validate it. */
3871 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3872 if (attr->nexthop.s_addr == INADDR_ANY ||
3873 !ipv4_unicast_valid(&attr->nexthop) ||
3874 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3875 return true;
d62a17ae 3876 }
c265ee22 3877
d62a17ae 3878 /* If MP_NEXTHOP is present, validate it. */
3879 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3880 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3881 * it is not an IPv6 link-local address.
0355b41d
DA
3882 *
3883 * If we receive an UPDATE with nexthop length set to 32 bytes
3884 * we shouldn't discard an UPDATE if it's set to (::).
3885 * The link-local (2st) is validated along the code path later.
d62a17ae 3886 */
3887 if (attr->mp_nexthop_len) {
3888 switch (attr->mp_nexthop_len) {
3889 case BGP_ATTR_NHLEN_IPV4:
3890 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3891 ret = (attr->mp_nexthop_global_in.s_addr ==
3892 INADDR_ANY ||
3893 !ipv4_unicast_valid(
3894 &attr->mp_nexthop_global_in) ||
3895 bgp_nexthop_self(bgp, afi, type, stype, attr,
3896 dest));
d62a17ae 3897 break;
3898
3899 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3900 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3901 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3902 &attr->mp_nexthop_global)
d62a17ae 3903 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3904 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3905 &attr->mp_nexthop_global)
3906 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3907 dest));
d62a17ae 3908 break;
0355b41d
DA
3909 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3910 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3911 || IN6_IS_ADDR_MULTICAST(
3912 &attr->mp_nexthop_global)
3913 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3914 dest));
0355b41d 3915 break;
d62a17ae 3916
3917 default:
3dc339cd 3918 ret = true;
d62a17ae 3919 break;
3920 }
3921 }
c265ee22 3922
d62a17ae 3923 return ret;
3924}
3925
aade37d7 3926static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3927{
3928 struct community *old;
3929 struct community *new;
3930 struct community *merge;
aade37d7 3931 struct community *no_export;
2721dd61 3932
9a706b42 3933 old = bgp_attr_get_community(attr);
aade37d7 3934 no_export = community_str2com("no-export");
2721dd61 3935
b4efa101
DA
3936 assert(no_export);
3937
2721dd61 3938 if (old) {
aade37d7 3939 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3940
3941 if (!old->refcnt)
3942 community_free(&old);
3943
3944 new = community_uniq_sort(merge);
3945 community_free(&merge);
3946 } else {
aade37d7 3947 new = community_dup(no_export);
2721dd61
DA
3948 }
3949
aade37d7 3950 community_free(&no_export);
2721dd61 3951
9a706b42 3952 bgp_attr_set_community(attr, new);
2721dd61
DA
3953}
3954
46dbf9d0
DA
3955static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3956 struct attr *attr, const struct prefix *prefix,
3957 int *sub_type)
3958{
3959 struct listnode *node, *nnode;
3960 struct bgp *bgp;
3961 bool accept_own_found = false;
3962
3963 if (safi != SAFI_MPLS_VPN)
3964 return false;
3965
3966 /* Processing of the ACCEPT_OWN community is enabled by configuration */
3967 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3968 return false;
3969
3970 /* The route in question carries the ACCEPT_OWN community */
3971 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3972 struct community *comm = bgp_attr_get_community(attr);
3973
3974 if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3975 accept_own_found = true;
3976 }
3977
3978 /* The route in question is targeted to one or more destination VRFs
3979 * on the router (as determined by inspecting the Route Target(s)).
3980 */
3981 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3982 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3983 continue;
3984
3985 if (accept_own_found &&
3986 ecommunity_include(
3987 bgp->vpn_policy[afi]
3988 .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3989 bgp_attr_get_ecommunity(attr))) {
3990 if (bgp_debug_update(peer, prefix, NULL, 1))
3991 zlog_debug(
3992 "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3993 peer, prefix);
3994
3995 /* Treat this route as imported, because it's leaked
3996 * already from another VRF, and we got an updated
3997 * version from route-reflector with ACCEPT_OWN
3998 * community.
3999 */
4000 *sub_type = BGP_ROUTE_IMPORTED;
4001
4002 return true;
4003 }
4004 }
4005
4006 return false;
4007}
4008
5a1ae2c2 4009int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4010 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4011 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4012 uint32_t num_labels, int soft_reconfig,
a4d82a8a 4013 struct bgp_route_evpn *evpn)
d62a17ae 4014{
4015 int ret;
4016 int aspath_loop_count = 0;
9bcb3eef 4017 struct bgp_dest *dest;
d62a17ae 4018 struct bgp *bgp;
4019 struct attr new_attr;
4020 struct attr *attr_new;
40381db7 4021 struct bgp_path_info *pi;
4b7e6066
DS
4022 struct bgp_path_info *new;
4023 struct bgp_path_info_extra *extra;
d62a17ae 4024 const char *reason;
4025 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 4026 int connected = 0;
4027 int do_loop_check = 1;
4028 int has_valid_label = 0;
7c312383 4029 afi_t nh_afi;
9146341f 4030 bool force_evpn_import = false;
907707db 4031 safi_t orig_safi = safi;
a486300b 4032 bool leak_success = true;
b2ac1d0d 4033 int allowas_in = 0;
949b0f24 4034
c7bb4f00 4035 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
4036 char pfxprint[PREFIX2STR_BUFFER];
4037
4038 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
4039 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
4040 afi, safi, attr);
6401252f
QY
4041 }
4042
49e5a4a0 4043#ifdef ENABLE_BGP_VNC
d62a17ae 4044 int vnc_implicit_withdraw = 0;
65efcfce 4045#endif
d62a17ae 4046 int same_attr = 0;
718e3744 4047
907707db
MS
4048 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4049 if (orig_safi == SAFI_LABELED_UNICAST)
4050 safi = SAFI_UNICAST;
4051
6006b807 4052 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4053 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4054 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4055
d62a17ae 4056 bgp = peer->bgp;
9bcb3eef 4057 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4058 /* TODO: Check to see if we can get rid of "is_valid_label" */
4059 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4060 has_valid_label = (num_labels > 0) ? 1 : 0;
4061 else
4062 has_valid_label = bgp_is_valid_label(label);
718e3744 4063
28f66de2
MS
4064 if (has_valid_label)
4065 assert(label != NULL);
4066
66ff6089
AD
4067 /* Update overlay index of the attribute */
4068 if (afi == AFI_L2VPN && evpn)
4069 memcpy(&attr->evpn_overlay, evpn,
4070 sizeof(struct bgp_route_evpn));
4071
d62a17ae 4072 /* When peer's soft reconfiguration enabled. Record input packet in
4073 Adj-RIBs-In. */
4074 if (!soft_reconfig
4075 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4076 && peer != bgp->peer_self)
9bcb3eef 4077 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4078
b2ac1d0d
MS
4079 /* Update permitted loop count */
4080 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4081 allowas_in = peer->allowas_in[afi][safi];
4082
d62a17ae 4083 /* Check previously received route. */
9bcb3eef 4084 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4085 if (pi->peer == peer && pi->type == type
4086 && pi->sub_type == sub_type
4087 && pi->addpath_rx_id == addpath_id)
d62a17ae 4088 break;
4089
4090 /* AS path local-as loop check. */
4091 if (peer->change_local_as) {
b2ac1d0d
MS
4092 if (allowas_in)
4093 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4094 else if (!CHECK_FLAG(peer->flags,
4095 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4096 aspath_loop_count = 1;
4097
4098 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4099 > aspath_loop_count) {
b4d46cc9 4100 peer->stat_pfx_aspath_loop++;
692174a1 4101 reason = "as-path contains our own AS;";
d62a17ae 4102 goto filtered;
4103 }
718e3744 4104 }
718e3744 4105
d62a17ae 4106 /* If the peer is configured for "allowas-in origin" and the last ASN in
4107 * the
4108 * as-path is our ASN then we do not need to call aspath_loop_check
4109 */
4110 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4111 if (aspath_get_last_as(attr->aspath) == bgp->as)
4112 do_loop_check = 0;
4113
4114 /* AS path loop check. */
4115 if (do_loop_check) {
b2ac1d0d
MS
4116 if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
4117 (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
4118 (aspath_loop_check(attr->aspath, bgp->confed_id) >
4119 allowas_in))) {
b4d46cc9 4120 peer->stat_pfx_aspath_loop++;
d62a17ae 4121 reason = "as-path contains our own AS;";
4122 goto filtered;
4123 }
4124 }
aac9ef6c 4125
46dbf9d0
DA
4126 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4127 * enabled, then take care of that too.
4128 */
4129 bool accept_own = false;
4130
d62a17ae 4131 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4132 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4133 accept_own =
4134 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4135 if (!accept_own) {
4136 peer->stat_pfx_originator_loop++;
4137 reason = "originator is us;";
4138 goto filtered;
4139 }
d62a17ae 4140 }
718e3744 4141
d62a17ae 4142 /* Route reflector cluster ID check. */
4143 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4144 peer->stat_pfx_cluster_loop++;
d62a17ae 4145 reason = "reflected from the same cluster;";
4146 goto filtered;
4147 }
718e3744 4148
d62a17ae 4149 /* Apply incoming filter. */
907707db 4150 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4151 peer->stat_pfx_filter++;
d62a17ae 4152 reason = "filter;";
4153 goto filtered;
4154 }
718e3744 4155
a8b72dc6
DA
4156 /* RFC 8212 to prevent route leaks.
4157 * This specification intends to improve this situation by requiring the
4158 * explicit configuration of both BGP Import and Export Policies for any
4159 * External BGP (EBGP) session such as customers, peers, or
4160 * confederation boundaries for all enabled address families. Through
4161 * codification of the aforementioned requirement, operators will
4162 * benefit from consistent behavior across different BGP
4163 * implementations.
4164 */
1d3fdccf 4165 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4166 if (!bgp_inbound_policy_exists(peer,
4167 &peer->filter[afi][safi])) {
4168 reason = "inbound policy missing";
b17826b7
DS
4169 if (monotime_since(&bgp->ebgprequirespolicywarning,
4170 NULL) > FIFTEENMINUTE2USEC ||
4171 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4172 zlog_warn(
4173 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4174 monotime(&bgp->ebgprequirespolicywarning);
4175 }
a8b72dc6
DA
4176 goto filtered;
4177 }
4178
fb29348a
DA
4179 /* draft-ietf-idr-deprecate-as-set-confed-set
4180 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4181 * Eventually, This document (if approved) updates RFC 4271
4182 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4183 * and obsoletes RFC 6472.
4184 */
7f972cd8 4185 if (peer->bgp->reject_as_sets)
fb29348a
DA
4186 if (aspath_check_as_sets(attr->aspath)) {
4187 reason =
4188 "as-path contains AS_SET or AS_CONFED_SET type;";
4189 goto filtered;
4190 }
4191
6f4f49b2 4192 new_attr = *attr;
d62a17ae 4193
4194 /* Apply incoming route-map.
4195 * NB: new_attr may now contain newly allocated values from route-map
4196 * "set"
4197 * commands, so we need bgp_attr_flush in the error paths, until we
4198 * intern
4199 * the attr (which takes over the memory references) */
907707db 4200 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4201 num_labels, dest)
4202 == RMAP_DENY) {
b4d46cc9 4203 peer->stat_pfx_filter++;
d62a17ae 4204 reason = "route-map;";
4205 bgp_attr_flush(&new_attr);
4206 goto filtered;
4207 }
718e3744 4208
05864da7 4209 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4210 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4211 /* remove from RIB previous entry */
4212 bgp_zebra_withdraw(p, pi, bgp, safi);
4213 }
4214
7f323236
DW
4215 if (peer->sort == BGP_PEER_EBGP) {
4216
2721dd61
DA
4217 /* rfc7999:
4218 * A BGP speaker receiving an announcement tagged with the
4219 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4220 * NO_EXPORT community as defined in RFC1997, or a
4221 * similar community, to prevent propagation of the
4222 * prefix outside the local AS. The community to prevent
4223 * propagation SHOULD be chosen according to the operator's
4224 * routing policy.
4225 */
9a706b42
DA
4226 if (bgp_attr_get_community(&new_attr) &&
4227 community_include(bgp_attr_get_community(&new_attr),
4228 COMMUNITY_BLACKHOLE))
aade37d7 4229 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4230
a4d82a8a
PZ
4231 /* If we receive the graceful-shutdown community from an eBGP
4232 * peer we must lower local-preference */
9a706b42
DA
4233 if (bgp_attr_get_community(&new_attr) &&
4234 community_include(bgp_attr_get_community(&new_attr),
4235 COMMUNITY_GSHUT)) {
7f323236
DW
4236 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4237 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4238
a4d82a8a
PZ
4239 /* If graceful-shutdown is configured then add the GSHUT
4240 * community to all paths received from eBGP peers */
637e5ba4 4241 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4242 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4243 }
4244
d62a17ae 4245 /* next hop check. */
860ad3f9
DS
4246 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4247 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4248 &new_attr, dest)) {
b4d46cc9 4249 peer->stat_pfx_nh_invalid++;
d62a17ae 4250 reason = "martian or self next-hop;";
4251 bgp_attr_flush(&new_attr);
4252 goto filtered;
4253 }
718e3744 4254
5c14a191 4255 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4256 peer->stat_pfx_nh_invalid++;
4e802e66 4257 reason = "self mac;";
4dbf2038 4258 bgp_attr_flush(&new_attr);
4e802e66
DS
4259 goto filtered;
4260 }
4261
5a78f2bc
EB
4262 if (bgp_check_role_applicability(afi, safi) &&
4263 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4264 reason = "failing otc validation";
4265 bgp_attr_flush(&new_attr);
4266 goto filtered;
4267 }
a1b773e2
DS
4268 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4269 * condition :
4270 * Suppress fib is enabled
4271 * BGP_OPT_NO_FIB is not enabled
4272 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4273 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4274 */
4275 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4276 && (sub_type == BGP_ROUTE_NORMAL)
4277 && (!bgp_option_check(BGP_OPT_NO_FIB))
4278 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4279 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4280
9cbd06e0
DA
4281 /* If maximum prefix count is configured and current prefix
4282 * count exeed it.
4283 */
4dbf2038
IR
4284 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4285 bgp_attr_flush(&new_attr);
9cbd06e0 4286 return -1;
4dbf2038
IR
4287 }
4288
01da2d26
DA
4289 /* If neighbor soo is configured, tag all incoming routes with
4290 * this SoO tag and then filter out advertisements in
4291 * subgroup_announce_check() if it matches the configured SoO
4292 * on the other peer.
4293 */
4294 if (peer->soo[afi][safi]) {
4295 struct ecommunity *old_ecomm =
4296 bgp_attr_get_ecommunity(&new_attr);
4297 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4298 struct ecommunity *new_ecomm;
4299
4300 if (old_ecomm) {
4301 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4302 ecomm_soo);
4303
4304 if (!old_ecomm->refcnt)
4305 ecommunity_free(&old_ecomm);
4306 } else {
4307 new_ecomm = ecommunity_dup(ecomm_soo);
4308 }
4309
4310 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4311 }
4312
4dbf2038 4313 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4314
d62a17ae 4315 /* If the update is implicit withdraw. */
40381db7 4316 if (pi) {
083ec940 4317 pi->uptime = monotime(NULL);
40381db7 4318 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4319
9bcb3eef 4320 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4321
d62a17ae 4322 /* Same attribute comes in. */
40381db7 4323 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4324 && same_attr
d62a17ae 4325 && (!has_valid_label
40381db7 4326 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4327 num_labels * sizeof(mpls_label_t))
66ff6089 4328 == 0)) {
b4f7f45b
IR
4329 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4330 BGP_CONFIG_DAMPENING)
d62a17ae 4331 && peer->sort == BGP_PEER_EBGP
40381db7 4332 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4333 if (bgp_debug_update(peer, p, NULL, 1)) {
4334 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4335 afi, safi, prd, p, label,
4336 num_labels, addpath_id ? 1 : 0,
66ff6089 4337 addpath_id, evpn, pfx_buf,
a4d82a8a 4338 sizeof(pfx_buf));
f70c91dc 4339 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4340 pfx_buf);
4341 }
4342
9bcb3eef 4343 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4344 != BGP_DAMP_SUPPRESSED) {
40381db7 4345 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4346 safi);
9bcb3eef 4347 bgp_process(bgp, dest, afi, safi);
d62a17ae 4348 }
4349 } else /* Duplicate - odd */
4350 {
4351 if (bgp_debug_update(peer, p, NULL, 1)) {
4352 if (!peer->rcvd_attr_printed) {
4353 zlog_debug(
f70c91dc
DA
4354 "%pBP rcvd UPDATE w/ attr: %s",
4355 peer,
d62a17ae 4356 peer->rcvd_attr_str);
4357 peer->rcvd_attr_printed = 1;
4358 }
4359
4360 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4361 afi, safi, prd, p, label,
4362 num_labels, addpath_id ? 1 : 0,
66ff6089 4363 addpath_id, evpn, pfx_buf,
a4d82a8a 4364 sizeof(pfx_buf));
d62a17ae 4365 zlog_debug(
f70c91dc
DA
4366 "%pBP rcvd %s...duplicate ignored",
4367 peer, pfx_buf);
d62a17ae 4368 }
4369
4370 /* graceful restart STALE flag unset. */
40381db7 4371 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4372 bgp_path_info_unset_flag(
9bcb3eef
DS
4373 dest, pi, BGP_PATH_STALE);
4374 bgp_dest_set_defer_flag(dest, false);
4375 bgp_process(bgp, dest, afi, safi);
d62a17ae 4376 }
4377 }
4378
9bcb3eef 4379 bgp_dest_unlock_node(dest);
d62a17ae 4380 bgp_attr_unintern(&attr_new);
4381
4382 return 0;
4383 }
718e3744 4384
d62a17ae 4385 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4386 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4387 if (bgp_debug_update(peer, p, NULL, 1)) {
4388 bgp_debug_rdpfxpath2str(
a4d82a8a 4389 afi, safi, prd, p, label, num_labels,
66ff6089 4390 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4391 pfx_buf, sizeof(pfx_buf));
d62a17ae 4392 zlog_debug(
f70c91dc
DA
4393 "%pBP rcvd %s, flapped quicker than processing",
4394 peer, pfx_buf);
d62a17ae 4395 }
4396
9bcb3eef 4397 bgp_path_info_restore(dest, pi);
9146341f 4398
4399 /*
4400 * If the BGP_PATH_REMOVED flag is set, then EVPN
4401 * routes would have been unimported already when a
4402 * prior BGP withdraw processing happened. Such routes
4403 * need to be imported again, so flag accordingly.
4404 */
4405 force_evpn_import = true;
d62a17ae 4406 }
718e3744 4407
d62a17ae 4408 /* Received Logging. */
4409 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4410 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4411 num_labels, addpath_id ? 1 : 0,
66ff6089 4412 addpath_id, evpn, pfx_buf,
a4d82a8a 4413 sizeof(pfx_buf));
f70c91dc 4414 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4415 }
718e3744 4416
d62a17ae 4417 /* graceful restart STALE flag unset. */
f009ff26 4418 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4419 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4420 bgp_dest_set_defer_flag(dest, false);
f009ff26 4421 }
d62a17ae 4422
4423 /* The attribute is changed. */
9bcb3eef 4424 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4425
4426 /* implicit withdraw, decrement aggregate and pcount here.
4427 * only if update is accepted, they'll increment below.
4428 */
40381db7 4429 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4430
4431 /* Update bgp route dampening information. */
b4f7f45b 4432 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4433 && peer->sort == BGP_PEER_EBGP) {
4434 /* This is implicit withdraw so we should update
b4f7f45b
IR
4435 dampening
4436 information. */
40381db7 4437 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4438 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4439 }
49e5a4a0 4440#ifdef ENABLE_BGP_VNC
d62a17ae 4441 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4442 struct bgp_dest *pdest = NULL;
d62a17ae 4443 struct bgp_table *table = NULL;
4444
9bcb3eef
DS
4445 pdest = bgp_node_get(bgp->rib[afi][safi],
4446 (struct prefix *)prd);
4447 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4448 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4449
4450 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4451 bgp, prd, table, p, pi);
d62a17ae 4452 }
9bcb3eef 4453 bgp_dest_unlock_node(pdest);
d62a17ae 4454 }
4455 if ((afi == AFI_IP || afi == AFI_IP6)
4456 && (safi == SAFI_UNICAST)) {
40381db7 4457 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4458 /*
4459 * Implicit withdraw case.
4460 */
4461 ++vnc_implicit_withdraw;
40381db7
DS
4462 vnc_import_bgp_del_route(bgp, p, pi);
4463 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4464 }
4465 }
65efcfce 4466#endif
128ea8ab 4467
d62a17ae 4468 /* Special handling for EVPN update of an existing route. If the
4469 * extended community attribute has changed, we need to
4470 * un-import
4471 * the route using its existing extended community. It will be
4472 * subsequently processed for import with the new extended
4473 * community.
4474 */
6f8c9c11
PR
4475 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4476 && !same_attr) {
40381db7 4477 if ((pi->attr->flag
d62a17ae 4478 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4479 && (attr_new->flag
4480 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4481 int cmp;
4482
b53e67a3
DA
4483 cmp = ecommunity_cmp(
4484 bgp_attr_get_ecommunity(pi->attr),
4485 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4486 if (!cmp) {
4487 if (bgp_debug_update(peer, p, NULL, 1))
4488 zlog_debug(
4489 "Change in EXT-COMM, existing %s new %s",
4490 ecommunity_str(
b53e67a3
DA
4491 bgp_attr_get_ecommunity(
4492 pi->attr)),
d62a17ae 4493 ecommunity_str(
b53e67a3
DA
4494 bgp_attr_get_ecommunity(
4495 attr_new)));
6f8c9c11
PR
4496 if (safi == SAFI_EVPN)
4497 bgp_evpn_unimport_route(
4498 bgp, afi, safi, p, pi);
4499 else /* SAFI_MPLS_VPN */
4500 vpn_leak_to_vrf_withdraw(bgp,
4501 pi);
d62a17ae 4502 }
4503 }
4504 }
718e3744 4505
d62a17ae 4506 /* Update to new attribute. */
40381db7
DS
4507 bgp_attr_unintern(&pi->attr);
4508 pi->attr = attr_new;
d62a17ae 4509
4510 /* Update MPLS label */
4511 if (has_valid_label) {
40381db7 4512 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4513 if (extra->label != label) {
4514 memcpy(&extra->label, label,
dbd587da 4515 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4516 extra->num_labels = num_labels;
4517 }
b57ba6d2
MK
4518 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4519 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4520 }
718e3744 4521
e496b420
HS
4522 /* Update SRv6 SID */
4523 if (attr->srv6_l3vpn) {
4524 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4525 if (sid_diff(&extra->sid[0].sid,
4526 &attr->srv6_l3vpn->sid)) {
4527 sid_copy(&extra->sid[0].sid,
e496b420
HS
4528 &attr->srv6_l3vpn->sid);
4529 extra->num_sids = 1;
cc8f05df 4530
16f3db2d
RS
4531 extra->sid[0].loc_block_len = 0;
4532 extra->sid[0].loc_node_len = 0;
4533 extra->sid[0].func_len = 0;
4534 extra->sid[0].arg_len = 0;
ea7cd161
RS
4535 extra->sid[0].transposition_len = 0;
4536 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4537
4538 if (attr->srv6_l3vpn->loc_block_len != 0) {
4539 extra->sid[0].loc_block_len =
4540 attr->srv6_l3vpn->loc_block_len;
4541 extra->sid[0].loc_node_len =
4542 attr->srv6_l3vpn->loc_node_len;
4543 extra->sid[0].func_len =
4544 attr->srv6_l3vpn->func_len;
4545 extra->sid[0].arg_len =
4546 attr->srv6_l3vpn->arg_len;
ea7cd161 4547 extra->sid[0].transposition_len =
cc8f05df 4548 attr->srv6_l3vpn
ea7cd161
RS
4549 ->transposition_len;
4550 extra->sid[0].transposition_offset =
cc8f05df 4551 attr->srv6_l3vpn
ea7cd161
RS
4552 ->transposition_offset;
4553 }
e496b420
HS
4554 }
4555 } else if (attr->srv6_vpn) {
4556 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4557 if (sid_diff(&extra->sid[0].sid,
4558 &attr->srv6_vpn->sid)) {
4559 sid_copy(&extra->sid[0].sid,
4560 &attr->srv6_vpn->sid);
e496b420
HS
4561 extra->num_sids = 1;
4562 }
4563 }
4564
49e5a4a0 4565#ifdef ENABLE_BGP_VNC
d62a17ae 4566 if ((afi == AFI_IP || afi == AFI_IP6)
4567 && (safi == SAFI_UNICAST)) {
4568 if (vnc_implicit_withdraw) {
4569 /*
4570 * Add back the route with its new attributes
4571 * (e.g., nexthop).
4572 * The route is still selected, until the route
4573 * selection
4574 * queued by bgp_process actually runs. We have
4575 * to make this
4576 * update to the VNC side immediately to avoid
4577 * racing against
4578 * configuration changes (e.g., route-map
4579 * changes) which
4580 * trigger re-importation of the entire RIB.
4581 */
40381db7
DS
4582 vnc_import_bgp_add_route(bgp, p, pi);
4583 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4584 }
4585 }
65efcfce
LB
4586#endif
4587
d62a17ae 4588 /* Update bgp route dampening information. */
b4f7f45b 4589 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4590 && peer->sort == BGP_PEER_EBGP) {
4591 /* Now we do normal update dampening. */
9bcb3eef 4592 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4593 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4594 bgp_dest_unlock_node(dest);
d62a17ae 4595 return 0;
4596 }
4597 }
128ea8ab 4598
d62a17ae 4599 /* Nexthop reachability check - for unicast and
4600 * labeled-unicast.. */
7c312383
AD
4601 if (((afi == AFI_IP || afi == AFI_IP6)
4602 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4603 || (safi == SAFI_EVPN &&
4604 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4605 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4606 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4607 && !CHECK_FLAG(peer->flags,
4608 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4609 && !CHECK_FLAG(bgp->flags,
4610 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4611 connected = 1;
4612 else
4613 connected = 0;
4614
960035b2
PZ
4615 struct bgp *bgp_nexthop = bgp;
4616
40381db7
DS
4617 if (pi->extra && pi->extra->bgp_orig)
4618 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4619
7c312383
AD
4620 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4621
4622 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4623 safi, pi, NULL, connected,
4624 p)
a4d82a8a 4625 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4626 bgp_path_info_set_flag(dest, pi,
4627 BGP_PATH_VALID);
d62a17ae 4628 else {
4629 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4630 zlog_debug("%s(%pI4): NH unresolved",
4631 __func__,
4632 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4633 }
9bcb3eef 4634 bgp_path_info_unset_flag(dest, pi,
18ee8310 4635 BGP_PATH_VALID);
d62a17ae 4636 }
46dbf9d0
DA
4637 } else {
4638 if (accept_own)
4639 bgp_path_info_set_flag(dest, pi,
4640 BGP_PATH_ACCEPT_OWN);
4641
9bcb3eef 4642 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4643 }
d62a17ae 4644
49e5a4a0 4645#ifdef ENABLE_BGP_VNC
d62a17ae 4646 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4647 struct bgp_dest *pdest = NULL;
d62a17ae 4648 struct bgp_table *table = NULL;
4649
9bcb3eef
DS
4650 pdest = bgp_node_get(bgp->rib[afi][safi],
4651 (struct prefix *)prd);
4652 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4653 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4654
4655 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4656 bgp, prd, table, p, pi);
d62a17ae 4657 }
9bcb3eef 4658 bgp_dest_unlock_node(pdest);
d62a17ae 4659 }
4660#endif
718e3744 4661
d62a17ae 4662 /* If this is an EVPN route and some attribute has changed,
9146341f 4663 * or we are explicitly told to perform a route import, process
d62a17ae 4664 * route for import. If the extended community has changed, we
4665 * would
4666 * have done the un-import earlier and the import would result
4667 * in the
4668 * route getting injected into appropriate L2 VNIs. If it is
4669 * just
4670 * some other attribute change, the import will result in
4671 * updating
4672 * the attributes for the route in the VNI(s).
4673 */
9146341f 4674 if (safi == SAFI_EVPN &&
4675 (!same_attr || force_evpn_import) &&
7c312383 4676 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4677 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4678
4679 /* Process change. */
40381db7 4680 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4681
9bcb3eef
DS
4682 bgp_process(bgp, dest, afi, safi);
4683 bgp_dest_unlock_node(dest);
558d1fec 4684
ddb5b488
PZ
4685 if (SAFI_UNICAST == safi
4686 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4687 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4688
40381db7 4689 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4690 }
4691 if ((SAFI_MPLS_VPN == safi)
4692 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4693 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4694 }
4695
49e5a4a0 4696#ifdef ENABLE_BGP_VNC
d62a17ae 4697 if (SAFI_MPLS_VPN == safi) {
4698 mpls_label_t label_decoded = decode_label(label);
28070ee3 4699
d62a17ae 4700 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4701 type, sub_type, &label_decoded);
4702 }
4703 if (SAFI_ENCAP == safi) {
4704 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4705 type, sub_type, NULL);
4706 }
28070ee3 4707#endif
a486300b
PG
4708 if ((safi == SAFI_MPLS_VPN) &&
4709 !CHECK_FLAG(bgp->af_flags[afi][safi],
4710 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4711 !leak_success) {
4712 bgp_unlink_nexthop(pi);
4713 bgp_path_info_delete(dest, pi);
4714 }
d62a17ae 4715 return 0;
4716 } // End of implicit withdraw
718e3744 4717
d62a17ae 4718 /* Received Logging. */
4719 if (bgp_debug_update(peer, p, NULL, 1)) {
4720 if (!peer->rcvd_attr_printed) {
f70c91dc 4721 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4722 peer->rcvd_attr_str);
4723 peer->rcvd_attr_printed = 1;
4724 }
718e3744 4725
a4d82a8a 4726 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4727 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4728 pfx_buf, sizeof(pfx_buf));
f70c91dc 4729 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4730 }
718e3744 4731
d62a17ae 4732 /* Make new BGP info. */
9bcb3eef 4733 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4734
d62a17ae 4735 /* Update MPLS label */
4736 if (has_valid_label) {
18ee8310 4737 extra = bgp_path_info_extra_get(new);
8ba71050 4738 if (extra->label != label) {
dbd587da
QY
4739 memcpy(&extra->label, label,
4740 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4741 extra->num_labels = num_labels;
4742 }
b57ba6d2
MK
4743 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4744 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4745 }
718e3744 4746
e496b420
HS
4747 /* Update SRv6 SID */
4748 if (safi == SAFI_MPLS_VPN) {
4749 extra = bgp_path_info_extra_get(new);
4750 if (attr->srv6_l3vpn) {
16f3db2d 4751 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4752 extra->num_sids = 1;
cc8f05df 4753
16f3db2d
RS
4754 extra->sid[0].loc_block_len =
4755 attr->srv6_l3vpn->loc_block_len;
4756 extra->sid[0].loc_node_len =
4757 attr->srv6_l3vpn->loc_node_len;
4758 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4759 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4760 extra->sid[0].transposition_len =
4761 attr->srv6_l3vpn->transposition_len;
4762 extra->sid[0].transposition_offset =
4763 attr->srv6_l3vpn->transposition_offset;
e496b420 4764 } else if (attr->srv6_vpn) {
16f3db2d 4765 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4766 extra->num_sids = 1;
4767 }
4768 }
4769
d62a17ae 4770 /* Nexthop reachability check. */
7c312383
AD
4771 if (((afi == AFI_IP || afi == AFI_IP6)
4772 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4773 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4774 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4775 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4776 && !CHECK_FLAG(peer->flags,
4777 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4778 && !CHECK_FLAG(bgp->flags,
4779 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4780 connected = 1;
4781 else
4782 connected = 0;
4783
7c312383
AD
4784 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4785
4053e952 4786 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4787 connected, p)
a4d82a8a 4788 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4789 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4790 else {
4791 if (BGP_DEBUG(nht, NHT)) {
4792 char buf1[INET6_ADDRSTRLEN];
4793 inet_ntop(AF_INET,
4794 (const void *)&attr_new->nexthop,
4795 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4796 zlog_debug("%s(%s): NH unresolved", __func__,
4797 buf1);
d62a17ae 4798 }
9bcb3eef 4799 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4800 }
46dbf9d0
DA
4801 } else {
4802 if (accept_own)
4803 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4804
9bcb3eef 4805 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4806 }
a82478b9 4807
d62a17ae 4808 /* Addpath ID */
4809 new->addpath_rx_id = addpath_id;
4810
4811 /* Increment prefix */
4812 bgp_aggregate_increment(bgp, p, new, afi, safi);
4813
4814 /* Register new BGP information. */
9bcb3eef 4815 bgp_path_info_add(dest, new);
d62a17ae 4816
4817 /* route_node_get lock */
9bcb3eef 4818 bgp_dest_unlock_node(dest);
558d1fec 4819
49e5a4a0 4820#ifdef ENABLE_BGP_VNC
d62a17ae 4821 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4822 struct bgp_dest *pdest = NULL;
d62a17ae 4823 struct bgp_table *table = NULL;
4824
9bcb3eef
DS
4825 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4826 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4827 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4828
4829 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4830 bgp, prd, table, p, new);
4831 }
9bcb3eef 4832 bgp_dest_unlock_node(pdest);
d62a17ae 4833 }
65efcfce
LB
4834#endif
4835
d62a17ae 4836 /* If this is an EVPN route, process for import. */
7c312383 4837 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4838 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4839
9bcb3eef 4840 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4841
d62a17ae 4842 /* Process change. */
9bcb3eef 4843 bgp_process(bgp, dest, afi, safi);
718e3744 4844
ddb5b488
PZ
4845 if (SAFI_UNICAST == safi
4846 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4847 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4848 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4849 }
4850 if ((SAFI_MPLS_VPN == safi)
4851 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4852 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4853 }
49e5a4a0 4854#ifdef ENABLE_BGP_VNC
d62a17ae 4855 if (SAFI_MPLS_VPN == safi) {
4856 mpls_label_t label_decoded = decode_label(label);
28070ee3 4857
d62a17ae 4858 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4859 sub_type, &label_decoded);
4860 }
4861 if (SAFI_ENCAP == safi) {
4862 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4863 sub_type, NULL);
4864 }
28070ee3 4865#endif
a486300b
PG
4866 if ((safi == SAFI_MPLS_VPN) &&
4867 !CHECK_FLAG(bgp->af_flags[afi][safi],
4868 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4869 !leak_success) {
4870 bgp_unlink_nexthop(new);
4871 bgp_path_info_delete(dest, new);
4872 }
28070ee3 4873
d62a17ae 4874 return 0;
718e3744 4875
d62a17ae 4876/* This BGP update is filtered. Log the reason then update BGP
4877 entry. */
4878filtered:
9bcb3eef 4879 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4880
d62a17ae 4881 if (bgp_debug_update(peer, p, NULL, 1)) {
4882 if (!peer->rcvd_attr_printed) {
f70c91dc 4883 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4884 peer->rcvd_attr_str);
4885 peer->rcvd_attr_printed = 1;
4886 }
718e3744 4887
a4d82a8a 4888 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4889 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4890 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4891 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4892 peer, pfx_buf, reason);
d62a17ae 4893 }
128ea8ab 4894
40381db7 4895 if (pi) {
d62a17ae 4896 /* If this is an EVPN route, un-import it as it is now filtered.
4897 */
4898 if (safi == SAFI_EVPN)
40381db7 4899 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4900
ddb5b488
PZ
4901 if (SAFI_UNICAST == safi
4902 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4903 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4904
40381db7 4905 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4906 }
4907 if ((SAFI_MPLS_VPN == safi)
4908 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4909
40381db7 4910 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4911 }
4912
9bcb3eef 4913 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4914 }
4915
9bcb3eef 4916 bgp_dest_unlock_node(dest);
558d1fec 4917
49e5a4a0 4918#ifdef ENABLE_BGP_VNC
d62a17ae 4919 /*
4920 * Filtered update is treated as an implicit withdrawal (see
4921 * bgp_rib_remove()
4922 * a few lines above)
4923 */
4924 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4925 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4926 0);
4927 }
97736e32
PZ
4928#endif
4929
d62a17ae 4930 return 0;
718e3744 4931}
4932
26a3ffd6 4933int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4934 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4935 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4936 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4937{
d62a17ae 4938 struct bgp *bgp;
4939 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4940 struct bgp_dest *dest;
40381db7 4941 struct bgp_path_info *pi;
718e3744 4942
49e5a4a0 4943#ifdef ENABLE_BGP_VNC
d62a17ae 4944 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4945 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4946 0);
4947 }
28070ee3
PZ
4948#endif
4949
d62a17ae 4950 bgp = peer->bgp;
4951
4952 /* Lookup node. */
9bcb3eef 4953 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4954
4955 /* If peer is soft reconfiguration enabled. Record input packet for
4956 * further calculation.
4957 *
4958 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4959 * routes that are filtered. This tanks out Quagga RS pretty badly due
4960 * to
4961 * the iteration over all RS clients.
4962 * Since we need to remove the entry from adj_in anyway, do that first
4963 * and
4964 * if there was no entry, we don't need to do anything more.
4965 */
4966 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4967 && peer != bgp->peer_self)
9bcb3eef 4968 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4969 peer->stat_pfx_dup_withdraw++;
4970
d62a17ae 4971 if (bgp_debug_update(peer, p, NULL, 1)) {
4972 bgp_debug_rdpfxpath2str(
a4d82a8a 4973 afi, safi, prd, p, label, num_labels,
6c995628
AD
4974 addpath_id ? 1 : 0, addpath_id, NULL,
4975 pfx_buf, sizeof(pfx_buf));
d62a17ae 4976 zlog_debug(
4977 "%s withdrawing route %s not in adj-in",
4978 peer->host, pfx_buf);
4979 }
9bcb3eef 4980 bgp_dest_unlock_node(dest);
d62a17ae 4981 return 0;
4982 }
cd808e74 4983
d62a17ae 4984 /* Lookup withdrawn route. */
9bcb3eef 4985 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4986 if (pi->peer == peer && pi->type == type
4987 && pi->sub_type == sub_type
4988 && pi->addpath_rx_id == addpath_id)
d62a17ae 4989 break;
4990
4991 /* Logging. */
4992 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4993 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4994 addpath_id ? 1 : 0, addpath_id, NULL,
4995 pfx_buf, sizeof(pfx_buf));
f70c91dc 4996 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4997 pfx_buf);
4998 }
718e3744 4999
d62a17ae 5000 /* Withdraw specified route from routing table. */
40381db7 5001 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5002 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5003 if (SAFI_UNICAST == safi
5004 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5005 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5006 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5007 }
5008 if ((SAFI_MPLS_VPN == safi)
5009 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5010
40381db7 5011 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
5012 }
5013 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5014 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5015 addpath_id ? 1 : 0, addpath_id, NULL,
5016 pfx_buf, sizeof(pfx_buf));
d62a17ae 5017 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5018 }
718e3744 5019
d62a17ae 5020 /* Unlock bgp_node_get() lock. */
9bcb3eef 5021 bgp_dest_unlock_node(dest);
d62a17ae 5022
5023 return 0;
718e3744 5024}
6b0655a2 5025
d62a17ae 5026void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5027 int withdraw)
718e3744 5028{
d62a17ae 5029 struct update_subgroup *subgrp;
5030 subgrp = peer_subgroup(peer, afi, safi);
5031 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5032}
6182d65b 5033
718e3744 5034
3f9c7369
DS
5035/*
5036 * bgp_stop_announce_route_timer
5037 */
d62a17ae 5038void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5039{
d62a17ae 5040 if (!paf->t_announce_route)
5041 return;
5042
c3aaa89a 5043 THREAD_OFF(paf->t_announce_route);
718e3744 5044}
6b0655a2 5045
3f9c7369
DS
5046/*
5047 * bgp_announce_route_timer_expired
5048 *
5049 * Callback that is invoked when the route announcement timer for a
5050 * peer_af expires.
5051 */
cc9f21da 5052static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5053{
d62a17ae 5054 struct peer_af *paf;
5055 struct peer *peer;
558d1fec 5056
d62a17ae 5057 paf = THREAD_ARG(t);
5058 peer = paf->peer;
718e3744 5059
feb17238 5060 if (!peer_established(peer))
cc9f21da 5061 return;
3f9c7369 5062
d62a17ae 5063 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5064 return;
3f9c7369 5065
d62a17ae 5066 peer_af_announce_route(paf, 1);
c5aec50b
MK
5067
5068 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5069 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5070}
5071
3f9c7369
DS
5072/*
5073 * bgp_announce_route
5074 *
5075 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5076 *
5077 * if force is true we will force an update even if the update
5078 * limiting code is attempted to kick in.
3f9c7369 5079 */
e1a32ec1 5080void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5081{
5082 struct peer_af *paf;
5083 struct update_subgroup *subgrp;
5084
5085 paf = peer_af_find(peer, afi, safi);
5086 if (!paf)
5087 return;
5088 subgrp = PAF_SUBGRP(paf);
5089
5090 /*
5091 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5092 * or a refresh has already been triggered.
5093 */
5094 if (!subgrp || paf->t_announce_route)
5095 return;
5096
e1a32ec1
DS
5097 if (force)
5098 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5099
d62a17ae 5100 /*
5101 * Start a timer to stagger/delay the announce. This serves
5102 * two purposes - announcement can potentially be combined for
5103 * multiple peers and the announcement doesn't happen in the
5104 * vty context.
5105 */
5106 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5107 (subgrp->peer_count == 1)
5108 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5109 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5110 &paf->t_announce_route);
3f9c7369
DS
5111}
5112
5113/*
5114 * Announce routes from all AF tables to a peer.
5115 *
5116 * This should ONLY be called when there is a need to refresh the
5117 * routes to the peer based on a policy change for this peer alone
5118 * or a route refresh request received from the peer.
5119 * The operation will result in splitting the peer from its existing
5120 * subgroups and putting it in new subgroups.
5121 */
d62a17ae 5122void bgp_announce_route_all(struct peer *peer)
718e3744 5123{
d62a17ae 5124 afi_t afi;
5125 safi_t safi;
5126
05c7a1cc 5127 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5128 bgp_announce_route(peer, afi, safi, false);
718e3744 5129}
6b0655a2 5130
46aeabed
LS
5131/* Flag or unflag bgp_dest to determine whether it should be treated by
5132 * bgp_soft_reconfig_table_task.
5133 * Flag if flag is true. Unflag if flag is false.
5134 */
5135static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5136{
5137 struct bgp_dest *dest;
5138 struct bgp_adj_in *ain;
5139
5140 if (!table)
5141 return;
5142
5143 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5144 for (ain = dest->adj_in; ain; ain = ain->next) {
5145 if (ain->peer != NULL)
5146 break;
5147 }
5148 if (flag && ain != NULL && ain->peer != NULL)
5149 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5150 else
5151 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5152 }
5153}
5154
5155static int bgp_soft_reconfig_table_update(struct peer *peer,
5156 struct bgp_dest *dest,
5157 struct bgp_adj_in *ain, afi_t afi,
5158 safi_t safi, struct prefix_rd *prd)
5159{
5160 struct bgp_path_info *pi;
5161 uint32_t num_labels = 0;
5162 mpls_label_t *label_pnt = NULL;
5163 struct bgp_route_evpn evpn;
5164
5165 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5166 if (pi->peer == peer)
5167 break;
5168
5169 if (pi && pi->extra)
5170 num_labels = pi->extra->num_labels;
5171 if (num_labels)
5172 label_pnt = &pi->extra->label[0];
5173 if (pi)
5174 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5175 sizeof(evpn));
5176 else
5177 memset(&evpn, 0, sizeof(evpn));
5178
5179 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5180 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
5181 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
5182 &evpn);
5183}
5184
d62a17ae 5185static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5186 struct bgp_table *table,
5187 struct prefix_rd *prd)
718e3744 5188{
d62a17ae 5189 int ret;
9bcb3eef 5190 struct bgp_dest *dest;
d62a17ae 5191 struct bgp_adj_in *ain;
718e3744 5192
d62a17ae 5193 if (!table)
5194 table = peer->bgp->rib[afi][safi];
718e3744 5195
9bcb3eef
DS
5196 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5197 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5198 if (ain->peer != peer)
5199 continue;
8692c506 5200
46aeabed
LS
5201 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5202 afi, safi, prd);
ea47320b
DL
5203
5204 if (ret < 0) {
9bcb3eef 5205 bgp_dest_unlock_node(dest);
ea47320b 5206 return;
d62a17ae 5207 }
5208 }
718e3744 5209}
5210
46aeabed
LS
5211/* Do soft reconfig table per bgp table.
5212 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5213 * when BGP_NODE_SOFT_RECONFIG is set,
5214 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5215 * Schedule a new thread to continue the job.
5216 * Without splitting the full job into several part,
5217 * vtysh waits for the job to finish before responding to a BGP command
5218 */
cc9f21da 5219static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5220{
5221 uint32_t iter, max_iter;
5222 int ret;
5223 struct bgp_dest *dest;
5224 struct bgp_adj_in *ain;
5225 struct peer *peer;
5226 struct bgp_table *table;
5227 struct prefix_rd *prd;
5228 struct listnode *node, *nnode;
5229
5230 table = THREAD_ARG(thread);
5231 prd = NULL;
5232
5233 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5234 if (table->soft_reconfig_init) {
5235 /* first call of the function with a new srta structure.
5236 * Don't do any treatment this time on nodes
5237 * in order vtysh to respond quickly
5238 */
5239 max_iter = 0;
5240 }
5241
5242 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5243 dest = bgp_route_next(dest)) {
5244 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5245 continue;
5246
5247 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5248
5249 for (ain = dest->adj_in; ain; ain = ain->next) {
5250 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5251 nnode, peer)) {
5252 if (ain->peer != peer)
5253 continue;
5254
5255 ret = bgp_soft_reconfig_table_update(
5256 peer, dest, ain, table->afi,
5257 table->safi, prd);
5258 iter++;
5259
5260 if (ret < 0) {
5261 bgp_dest_unlock_node(dest);
5262 listnode_delete(
5263 table->soft_reconfig_peers,
5264 peer);
5265 bgp_announce_route(peer, table->afi,
e1a32ec1 5266 table->safi, false);
46aeabed
LS
5267 if (list_isempty(
5268 table->soft_reconfig_peers)) {
5269 list_delete(
5270 &table->soft_reconfig_peers);
5271 bgp_soft_reconfig_table_flag(
5272 table, false);
cc9f21da 5273 return;
46aeabed
LS
5274 }
5275 }
5276 }
5277 }
5278 }
5279
5280 /* we're either starting the initial iteration,
5281 * or we're going to continue an ongoing iteration
5282 */
5283 if (dest || table->soft_reconfig_init) {
5284 table->soft_reconfig_init = false;
5285 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5286 table, 0, &table->soft_reconfig_thread);
cc9f21da 5287 return;
46aeabed
LS
5288 }
5289 /* we're done, clean up the background iteration context info and
5290 schedule route annoucement
5291 */
5292 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5293 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5294 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5295 }
5296
5297 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5298}
5299
5300
5301/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5302 * and peer.
5303 * - bgp cannot be NULL
5304 * - if table and peer are NULL, cancel all threads within the bgp instance
5305 * - if table is NULL and peer is not,
5306 * remove peer in all threads within the bgp instance
5307 * - if peer is NULL, cancel all threads matching table within the bgp instance
5308 */
5309void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5310 const struct bgp_table *table,
5311 const struct peer *peer)
5312{
5313 struct peer *npeer;
5314 struct listnode *node, *nnode;
5315 int afi, safi;
5316 struct bgp_table *ntable;
5317
5318 if (!bgp)
5319 return;
5320
5321 FOREACH_AFI_SAFI (afi, safi) {
5322 ntable = bgp->rib[afi][safi];
5323 if (!ntable)
5324 continue;
5325 if (table && table != ntable)
5326 continue;
5327
5328 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5329 npeer)) {
5330 if (peer && peer != npeer)
5331 continue;
5332 listnode_delete(ntable->soft_reconfig_peers, npeer);
5333 }
5334
5335 if (!ntable->soft_reconfig_peers
5336 || !list_isempty(ntable->soft_reconfig_peers))
5337 continue;
5338
5339 list_delete(&ntable->soft_reconfig_peers);
5340 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5341 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5342 }
5343}
5344
89c73443
DS
5345/*
5346 * Returns false if the peer is not configured for soft reconfig in
5347 */
5348bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5349{
9bcb3eef 5350 struct bgp_dest *dest;
d62a17ae 5351 struct bgp_table *table;
46aeabed
LS
5352 struct listnode *node, *nnode;
5353 struct peer *npeer;
5354 struct peer_af *paf;
718e3744 5355
89c73443
DS
5356 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5357 return false;
718e3744 5358
d62a17ae 5359 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5360 && (safi != SAFI_EVPN)) {
5361 table = peer->bgp->rib[afi][safi];
5362 if (!table)
89c73443 5363 return true;
46aeabed
LS
5364
5365 table->soft_reconfig_init = true;
5366
5367 if (!table->soft_reconfig_peers)
5368 table->soft_reconfig_peers = list_new();
5369 npeer = NULL;
5370 /* add peer to the table soft_reconfig_peers if not already
5371 * there
5372 */
5373 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5374 npeer)) {
5375 if (peer == npeer)
5376 break;
5377 }
5378 if (peer != npeer)
5379 listnode_add(table->soft_reconfig_peers, peer);
5380
5381 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5382 * on table would start back at the beginning.
5383 */
5384 bgp_soft_reconfig_table_flag(table, true);
5385
5386 if (!table->soft_reconfig_thread)
5387 thread_add_event(bm->master,
5388 bgp_soft_reconfig_table_task, table, 0,
5389 &table->soft_reconfig_thread);
5390 /* Cancel bgp_announce_route_timer_expired threads.
5391 * bgp_announce_route_timer_expired threads have been scheduled
5392 * to announce routes as soon as the soft_reconfigure process
5393 * finishes.
5394 * In this case, soft_reconfigure is also scheduled by using
5395 * a thread but is planned after the
5396 * bgp_announce_route_timer_expired threads. It means that,
5397 * without cancelling the threads, the route announcement task
5398 * would run before the soft reconfiguration one. That would
5399 * useless and would block vtysh during several seconds. Route
5400 * announcements are rescheduled as soon as the soft_reconfigure
5401 * process finishes.
5402 */
5403 paf = peer_af_find(peer, afi, safi);
5404 if (paf)
5405 bgp_stop_announce_route_timer(paf);
5406 } else
9bcb3eef
DS
5407 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5408 dest = bgp_route_next(dest)) {
5409 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5410
b54892e0
DS
5411 if (table == NULL)
5412 continue;
8692c506 5413
9bcb3eef 5414 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5415 struct prefix_rd prd;
5416
5417 prd.family = AF_UNSPEC;
5418 prd.prefixlen = 64;
5419 memcpy(&prd.val, p->u.val, 8);
5420
5421 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5422 }
89c73443
DS
5423
5424 return true;
718e3744 5425}
6b0655a2 5426
228da428 5427
d62a17ae 5428struct bgp_clear_node_queue {
9bcb3eef 5429 struct bgp_dest *dest;
228da428
CC
5430};
5431
d62a17ae 5432static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5433{
d62a17ae 5434 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5435 struct bgp_dest *dest = cnq->dest;
d62a17ae 5436 struct peer *peer = wq->spec.data;
40381db7 5437 struct bgp_path_info *pi;
3103e8d2 5438 struct bgp *bgp;
9bcb3eef
DS
5439 afi_t afi = bgp_dest_table(dest)->afi;
5440 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5441
9bcb3eef 5442 assert(dest && peer);
3103e8d2 5443 bgp = peer->bgp;
d62a17ae 5444
5445 /* It is possible that we have multiple paths for a prefix from a peer
5446 * if that peer is using AddPath.
5447 */
9bcb3eef 5448 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5449 if (pi->peer != peer)
ea47320b
DL
5450 continue;
5451
5452 /* graceful restart STALE flag set. */
9af52ccf
DA
5453 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5454 && peer->nsf[afi][safi])
5455 || CHECK_FLAG(peer->af_sflags[afi][safi],
5456 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5457 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5458 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5459 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5460 else {
5461 /* If this is an EVPN route, process for
5462 * un-import. */
5463 if (safi == SAFI_EVPN)
9bcb3eef
DS
5464 bgp_evpn_unimport_route(
5465 bgp, afi, safi,
5466 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5467 /* Handle withdraw for VRF route-leaking and L3VPN */
5468 if (SAFI_UNICAST == safi
5469 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5470 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5471 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5472 bgp, pi);
960035b2 5473 }
3103e8d2 5474 if (SAFI_MPLS_VPN == safi &&
960035b2 5475 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5476 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5477 }
3103e8d2 5478
9bcb3eef 5479 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5480 }
ea47320b 5481 }
d62a17ae 5482 return WQ_SUCCESS;
200df115 5483}
5484
d62a17ae 5485static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5486{
d62a17ae 5487 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5488 struct bgp_dest *dest = cnq->dest;
5489 struct bgp_table *table = bgp_dest_table(dest);
228da428 5490
9bcb3eef 5491 bgp_dest_unlock_node(dest);
d62a17ae 5492 bgp_table_unlock(table);
5493 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5494}
5495
d62a17ae 5496static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5497{
d62a17ae 5498 struct peer *peer = wq->spec.data;
64e580a7 5499
d62a17ae 5500 /* Tickle FSM to start moving again */
5501 BGP_EVENT_ADD(peer, Clearing_Completed);
5502
5503 peer_unlock(peer); /* bgp_clear_route */
200df115 5504}
718e3744 5505
d62a17ae 5506static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5507{
d62a17ae 5508 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5509
5510 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5511#undef CLEAR_QUEUE_NAME_LEN
5512
0ce1ca80 5513 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5514 peer->clear_node_queue->spec.hold = 10;
5515 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5516 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5517 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5518 peer->clear_node_queue->spec.max_retries = 0;
5519
5520 /* we only 'lock' this peer reference when the queue is actually active
5521 */
5522 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5523}
5524
d62a17ae 5525static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5526 struct bgp_table *table)
65ca75e0 5527{
9bcb3eef 5528 struct bgp_dest *dest;
b6c386bb 5529 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5530
d62a17ae 5531 if (!table)
5532 table = peer->bgp->rib[afi][safi];
dc83d712 5533
d62a17ae 5534 /* If still no table => afi/safi isn't configured at all or smth. */
5535 if (!table)
5536 return;
dc83d712 5537
9bcb3eef 5538 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5539 struct bgp_path_info *pi, *next;
d62a17ae 5540 struct bgp_adj_in *ain;
5541 struct bgp_adj_in *ain_next;
5542
5543 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5544 * queued for every clearing peer, regardless of whether it is
5545 * relevant to the peer at hand.
5546 *
5547 * Overview: There are 3 different indices which need to be
5548 * scrubbed, potentially, when a peer is removed:
5549 *
5550 * 1 peer's routes visible via the RIB (ie accepted routes)
5551 * 2 peer's routes visible by the (optional) peer's adj-in index
5552 * 3 other routes visible by the peer's adj-out index
5553 *
5554 * 3 there is no hurry in scrubbing, once the struct peer is
5555 * removed from bgp->peer, we could just GC such deleted peer's
5556 * adj-outs at our leisure.
5557 *
5558 * 1 and 2 must be 'scrubbed' in some way, at least made
5559 * invisible via RIB index before peer session is allowed to be
5560 * brought back up. So one needs to know when such a 'search' is
5561 * complete.
5562 *
5563 * Ideally:
5564 *
5565 * - there'd be a single global queue or a single RIB walker
5566 * - rather than tracking which route_nodes still need to be
5567 * examined on a peer basis, we'd track which peers still
5568 * aren't cleared
5569 *
5570 * Given that our per-peer prefix-counts now should be reliable,
5571 * this may actually be achievable. It doesn't seem to be a huge
5572 * problem at this time,
5573 *
5574 * It is possible that we have multiple paths for a prefix from
5575 * a peer
5576 * if that peer is using AddPath.
5577 */
9bcb3eef 5578 ain = dest->adj_in;
d62a17ae 5579 while (ain) {
5580 ain_next = ain->next;
5581
6a840fd9 5582 if (ain->peer == peer)
9bcb3eef 5583 bgp_adj_in_remove(dest, ain);
d62a17ae 5584
5585 ain = ain_next;
5586 }
5587
9bcb3eef 5588 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5589 next = pi->next;
5590 if (pi->peer != peer)
d62a17ae 5591 continue;
5592
5593 if (force)
9bcb3eef 5594 bgp_path_info_reap(dest, pi);
d62a17ae 5595 else {
5596 struct bgp_clear_node_queue *cnq;
5597
5598 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5599 bgp_table_lock(bgp_dest_table(dest));
5600 bgp_dest_lock_node(dest);
d62a17ae 5601 cnq = XCALLOC(
5602 MTYPE_BGP_CLEAR_NODE_QUEUE,
5603 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5604 cnq->dest = dest;
d62a17ae 5605 work_queue_add(peer->clear_node_queue, cnq);
5606 break;
5607 }
5608 }
5609 }
5610 return;
5611}
5612
5613void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5614{
9bcb3eef 5615 struct bgp_dest *dest;
d62a17ae 5616 struct bgp_table *table;
5617
5618 if (peer->clear_node_queue == NULL)
5619 bgp_clear_node_queue_init(peer);
5620
5621 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5622 * Idle until it receives a Clearing_Completed event. This protects
5623 * against peers which flap faster than we can we clear, which could
5624 * lead to:
5625 *
5626 * a) race with routes from the new session being installed before
5627 * clear_route_node visits the node (to delete the route of that
5628 * peer)
5629 * b) resource exhaustion, clear_route_node likely leads to an entry
5630 * on the process_main queue. Fast-flapping could cause that queue
5631 * to grow and grow.
5632 */
5633
5634 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5635 * the unlock will happen upon work-queue completion; other wise, the
5636 * unlock happens at the end of this function.
5637 */
5638 if (!peer->clear_node_queue->thread)
5639 peer_lock(peer);
5640
5641 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5642 bgp_clear_route_table(peer, afi, safi, NULL);
5643 else
9bcb3eef
DS
5644 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5645 dest = bgp_route_next(dest)) {
5646 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5647 if (!table)
5648 continue;
5649
5650 bgp_clear_route_table(peer, afi, safi, table);
5651 }
d62a17ae 5652
5653 /* unlock if no nodes got added to the clear-node-queue. */
5654 if (!peer->clear_node_queue->thread)
5655 peer_unlock(peer);
718e3744 5656}
d62a17ae 5657
5658void bgp_clear_route_all(struct peer *peer)
718e3744 5659{
d62a17ae 5660 afi_t afi;
5661 safi_t safi;
718e3744 5662
05c7a1cc
QY
5663 FOREACH_AFI_SAFI (afi, safi)
5664 bgp_clear_route(peer, afi, safi);
65efcfce 5665
49e5a4a0 5666#ifdef ENABLE_BGP_VNC
d62a17ae 5667 rfapiProcessPeerDown(peer);
65efcfce 5668#endif
718e3744 5669}
5670
d62a17ae 5671void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5672{
d62a17ae 5673 struct bgp_table *table;
9bcb3eef 5674 struct bgp_dest *dest;
d62a17ae 5675 struct bgp_adj_in *ain;
5676 struct bgp_adj_in *ain_next;
718e3744 5677
d62a17ae 5678 table = peer->bgp->rib[afi][safi];
718e3744 5679
d62a17ae 5680 /* It is possible that we have multiple paths for a prefix from a peer
5681 * if that peer is using AddPath.
5682 */
9bcb3eef
DS
5683 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5684 ain = dest->adj_in;
43143c8f 5685
d62a17ae 5686 while (ain) {
5687 ain_next = ain->next;
43143c8f 5688
6a840fd9 5689 if (ain->peer == peer)
9bcb3eef 5690 bgp_adj_in_remove(dest, ain);
43143c8f 5691
d62a17ae 5692 ain = ain_next;
5693 }
5694 }
718e3744 5695}
93406d87 5696
1479ed2f
DA
5697/* If any of the routes from the peer have been marked with the NO_LLGR
5698 * community, either as sent by the peer, or as the result of a configured
5699 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5700 * operation of [RFC4271].
5701 */
d62a17ae 5702void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5703{
9bcb3eef 5704 struct bgp_dest *dest;
40381db7 5705 struct bgp_path_info *pi;
d62a17ae 5706 struct bgp_table *table;
5707
9af52ccf 5708 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5709 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5710 dest = bgp_route_next(dest)) {
5711 struct bgp_dest *rm;
d62a17ae 5712
5713 /* look for neighbor in tables */
9bcb3eef 5714 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5715 if (!table)
ea47320b
DL
5716 continue;
5717
5718 for (rm = bgp_table_top(table); rm;
5719 rm = bgp_route_next(rm))
9bcb3eef 5720 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5721 pi = pi->next) {
40381db7 5722 if (pi->peer != peer)
ea47320b 5723 continue;
1479ed2f
DA
5724 if (CHECK_FLAG(
5725 peer->af_sflags[afi][safi],
5726 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5727 bgp_attr_get_community(pi->attr) &&
1479ed2f 5728 !community_include(
9a706b42
DA
5729 bgp_attr_get_community(
5730 pi->attr),
1479ed2f 5731 COMMUNITY_NO_LLGR))
e3015d91 5732 continue;
40381db7 5733 if (!CHECK_FLAG(pi->flags,
1defdda8 5734 BGP_PATH_STALE))
e3015d91 5735 continue;
ea47320b 5736
641065d4
KM
5737 /*
5738 * If this is VRF leaked route
5739 * process for withdraw.
5740 */
5741 if (pi->sub_type ==
5742 BGP_ROUTE_IMPORTED &&
5743 peer->bgp->inst_type ==
5744 BGP_INSTANCE_TYPE_DEFAULT)
5745 vpn_leak_to_vrf_withdraw(
5746 peer->bgp, pi);
5747
40381db7 5748 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5749 break;
5750 }
d62a17ae 5751 }
5752 } else {
9bcb3eef
DS
5753 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5754 dest = bgp_route_next(dest))
5755 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5756 pi = pi->next) {
40381db7 5757 if (pi->peer != peer)
ea47320b 5758 continue;
1479ed2f
DA
5759 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5760 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5761 bgp_attr_get_community(pi->attr) &&
5762 !community_include(
5763 bgp_attr_get_community(pi->attr),
5764 COMMUNITY_NO_LLGR))
e3015d91 5765 continue;
40381db7 5766 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5767 continue;
641065d4
KM
5768 if (safi == SAFI_UNICAST &&
5769 (peer->bgp->inst_type ==
5770 BGP_INSTANCE_TYPE_VRF ||
5771 peer->bgp->inst_type ==
5772 BGP_INSTANCE_TYPE_DEFAULT))
5773 vpn_leak_from_vrf_withdraw(
5774 bgp_get_default(), peer->bgp,
5775 pi);
5776
9bcb3eef 5777 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5778 break;
5779 }
d62a17ae 5780 }
93406d87 5781}
6b0655a2 5782
9af52ccf
DA
5783void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5784{
5785 struct bgp_dest *dest, *ndest;
5786 struct bgp_path_info *pi;
5787 struct bgp_table *table;
5788
5789 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5790 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5791 dest = bgp_route_next(dest)) {
5792 table = bgp_dest_get_bgp_table_info(dest);
5793 if (!table)
5794 continue;
5795
5796 for (ndest = bgp_table_top(table); ndest;
5797 ndest = bgp_route_next(ndest)) {
5798 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5799 pi = pi->next) {
5800 if (pi->peer != peer)
5801 continue;
5802
5803 if ((CHECK_FLAG(
5804 peer->af_sflags[afi][safi],
5805 PEER_STATUS_ENHANCED_REFRESH))
5806 && !CHECK_FLAG(pi->flags,
5807 BGP_PATH_STALE)
5808 && !CHECK_FLAG(
5809 pi->flags,
5810 BGP_PATH_UNUSEABLE)) {
5811 if (bgp_debug_neighbor_events(
5812 peer))
5813 zlog_debug(
58e111f6
DA
5814 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5815 peer,
9af52ccf
DA
5816 afi2str(afi),
5817 safi2str(safi),
5818 bgp_dest_get_prefix(
5819 ndest));
5820
5821 bgp_path_info_set_flag(
5822 ndest, pi,
5823 BGP_PATH_STALE);
5824 }
5825 }
5826 }
5827 }
5828 } else {
5829 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5830 dest = bgp_route_next(dest)) {
5831 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5832 pi = pi->next) {
5833 if (pi->peer != peer)
5834 continue;
5835
5836 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5837 PEER_STATUS_ENHANCED_REFRESH))
5838 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5839 && !CHECK_FLAG(pi->flags,
5840 BGP_PATH_UNUSEABLE)) {
5841 if (bgp_debug_neighbor_events(peer))
5842 zlog_debug(
58e111f6
DA
5843 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5844 peer, afi2str(afi),
9af52ccf
DA
5845 safi2str(safi),
5846 bgp_dest_get_prefix(
5847 dest));
5848
5849 bgp_path_info_set_flag(dest, pi,
5850 BGP_PATH_STALE);
5851 }
5852 }
5853 }
5854 }
5855}
5856
3dc339cd 5857bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5858{
e0df4c04 5859 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5860 return true;
e0df4c04 5861
9dac9fc8
DA
5862 if (peer->sort == BGP_PEER_EBGP
5863 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5864 || FILTER_LIST_OUT_NAME(filter)
5865 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5866 return true;
5867 return false;
9dac9fc8
DA
5868}
5869
3dc339cd 5870bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5871{
e0df4c04 5872 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5873 return true;
e0df4c04 5874
9dac9fc8
DA
5875 if (peer->sort == BGP_PEER_EBGP
5876 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5877 || FILTER_LIST_IN_NAME(filter)
5878 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5879 return true;
5880 return false;
9dac9fc8
DA
5881}
5882
568e10ca 5883static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5884 safi_t safi)
bb86c601 5885{
9bcb3eef 5886 struct bgp_dest *dest;
40381db7 5887 struct bgp_path_info *pi;
4b7e6066 5888 struct bgp_path_info *next;
bb86c601 5889
9bcb3eef
DS
5890 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5891 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5892 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5893
40381db7 5894 next = pi->next;
1b7bb747
CS
5895
5896 /* Unimport EVPN routes from VRFs */
5897 if (safi == SAFI_EVPN)
5898 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5899 SAFI_EVPN, p, pi);
1b7bb747 5900
40381db7
DS
5901 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5902 && pi->type == ZEBRA_ROUTE_BGP
5903 && (pi->sub_type == BGP_ROUTE_NORMAL
5904 || pi->sub_type == BGP_ROUTE_AGGREGATE
5905 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5906
d62a17ae 5907 if (bgp_fibupd_safi(safi))
b54892e0 5908 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5909 }
9514b37d 5910
9bcb3eef 5911 bgp_path_info_reap(dest, pi);
d62a17ae 5912 }
bb86c601
LB
5913}
5914
718e3744 5915/* Delete all kernel routes. */
d62a17ae 5916void bgp_cleanup_routes(struct bgp *bgp)
5917{
5918 afi_t afi;
9bcb3eef 5919 struct bgp_dest *dest;
67009e22 5920 struct bgp_table *table;
d62a17ae 5921
5922 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5923 if (afi == AFI_L2VPN)
5924 continue;
568e10ca 5925 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5926 SAFI_UNICAST);
d62a17ae 5927 /*
5928 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5929 */
5930 if (afi != AFI_L2VPN) {
5931 safi_t safi;
5932 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5933 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5934 dest = bgp_route_next(dest)) {
5935 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5936 if (table != NULL) {
5937 bgp_cleanup_table(bgp, table, safi);
5938 bgp_table_finish(&table);
9bcb3eef
DS
5939 bgp_dest_set_bgp_table_info(dest, NULL);
5940 bgp_dest_unlock_node(dest);
d62a17ae 5941 }
5942 }
5943 safi = SAFI_ENCAP;
9bcb3eef
DS
5944 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5945 dest = bgp_route_next(dest)) {
5946 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5947 if (table != NULL) {
5948 bgp_cleanup_table(bgp, table, safi);
5949 bgp_table_finish(&table);
9bcb3eef
DS
5950 bgp_dest_set_bgp_table_info(dest, NULL);
5951 bgp_dest_unlock_node(dest);
d62a17ae 5952 }
5953 }
5954 }
5955 }
9bcb3eef
DS
5956 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5957 dest = bgp_route_next(dest)) {
5958 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5959 if (table != NULL) {
5960 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5961 bgp_table_finish(&table);
9bcb3eef
DS
5962 bgp_dest_set_bgp_table_info(dest, NULL);
5963 bgp_dest_unlock_node(dest);
d62a17ae 5964 }
bb86c601 5965 }
718e3744 5966}
5967
d62a17ae 5968void bgp_reset(void)
718e3744 5969{
d62a17ae 5970 vty_reset();
5971 bgp_zclient_reset();
5972 access_list_reset();
5973 prefix_list_reset();
718e3744 5974}
6b0655a2 5975
be92fc9f 5976bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5977{
d62a17ae 5978 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5979 && CHECK_FLAG(peer->af_cap[afi][safi],
5980 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5981}
5982
718e3744 5983/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5984 value. */
d62a17ae 5985int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5986 struct bgp_nlri *packet)
5987{
d7c0a89a
QY
5988 uint8_t *pnt;
5989 uint8_t *lim;
d62a17ae 5990 struct prefix p;
5991 int psize;
5992 int ret;
5993 afi_t afi;
5994 safi_t safi;
be92fc9f 5995 bool addpath_capable;
d7c0a89a 5996 uint32_t addpath_id;
d62a17ae 5997
d62a17ae 5998 pnt = packet->nlri;
5999 lim = pnt + packet->length;
6000 afi = packet->afi;
6001 safi = packet->safi;
6002 addpath_id = 0;
be92fc9f 6003 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 6004
6005 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6006 syntactic validity. If the field is syntactically incorrect,
6007 then the Error Subcode is set to Invalid Network Field. */
6008 for (; pnt < lim; pnt += psize) {
6009 /* Clear prefix structure. */
6006b807 6010 memset(&p, 0, sizeof(p));
d62a17ae 6011
be92fc9f 6012 if (addpath_capable) {
d62a17ae 6013
6014 /* When packet overflow occurs return immediately. */
761ed665 6015 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6016 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6017
a3a850a1 6018 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6019 addpath_id = ntohl(addpath_id);
d62a17ae 6020 pnt += BGP_ADDPATH_ID_LEN;
6021 }
718e3744 6022
d62a17ae 6023 /* Fetch prefix length. */
6024 p.prefixlen = *pnt++;
6025 /* afi/safi validity already verified by caller,
6026 * bgp_update_receive */
6027 p.family = afi2family(afi);
6028
6029 /* Prefix length check. */
6030 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6031 flog_err(
e50f7cfd 6032 EC_BGP_UPDATE_RCV,
14454c9f 6033 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6034 peer->host, p.prefixlen, packet->afi);
513386b5 6035 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6036 }
6b0655a2 6037
d62a17ae 6038 /* Packet size overflow check. */
6039 psize = PSIZE(p.prefixlen);
6040
6041 /* When packet overflow occur return immediately. */
6042 if (pnt + psize > lim) {
af4c2728 6043 flog_err(
e50f7cfd 6044 EC_BGP_UPDATE_RCV,
d62a17ae 6045 "%s [Error] Update packet error (prefix length %d overflows packet)",
6046 peer->host, p.prefixlen);
513386b5 6047 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6048 }
6049
6050 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6051 * prefix for the v4 and v6 afi's and unicast/multicast */
6052 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6053 flog_err(
e50f7cfd 6054 EC_BGP_UPDATE_RCV,
d62a17ae 6055 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6056 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6057 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6058 }
6059
6060 /* Fetch prefix from NLRI packet. */
a85297a7 6061 memcpy(p.u.val, pnt, psize);
d62a17ae 6062
6063 /* Check address. */
6064 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6065 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6066 /* From RFC4271 Section 6.3:
6067 *
6068 * If a prefix in the NLRI field is semantically
6069 * incorrect
6070 * (e.g., an unexpected multicast IP address),
6071 * an error SHOULD
6072 * be logged locally, and the prefix SHOULD be
6073 * ignored.
a4d82a8a 6074 */
af4c2728 6075 flog_err(
e50f7cfd 6076 EC_BGP_UPDATE_RCV,
23d0a753
DA
6077 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6078 peer->host, &p.u.prefix4);
d62a17ae 6079 continue;
6080 }
6081 }
6082
6083 /* Check address. */
6084 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6085 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6086 flog_err(
e50f7cfd 6087 EC_BGP_UPDATE_RCV,
c0d72166
DS
6088 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6089 peer->host, &p.u.prefix6);
d62a17ae 6090
6091 continue;
6092 }
6093 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6094 flog_err(
e50f7cfd 6095 EC_BGP_UPDATE_RCV,
c0d72166
DS
6096 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6097 peer->host, &p.u.prefix6);
d62a17ae 6098
6099 continue;
6100 }
6101 }
6102
6103 /* Normal process. */
6104 if (attr)
6105 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
6106 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 6107 NULL, NULL, 0, 0, NULL);
d62a17ae 6108 else
6109 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
6110 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
6111 BGP_ROUTE_NORMAL, NULL, NULL, 0,
6112 NULL);
d62a17ae 6113
513386b5
DA
6114 /* Do not send BGP notification twice when maximum-prefix count
6115 * overflow. */
6116 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6117 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6118
6119 /* Address family configuration mismatch. */
d62a17ae 6120 if (ret < 0)
513386b5 6121 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 6122 }
6123
6124 /* Packet length consistency check. */
6125 if (pnt != lim) {
af4c2728 6126 flog_err(
e50f7cfd 6127 EC_BGP_UPDATE_RCV,
d62a17ae 6128 "%s [Error] Update packet error (prefix length mismatch with total length)",
6129 peer->host);
513386b5 6130 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6131 }
6b0655a2 6132
513386b5 6133 return BGP_NLRI_PARSE_OK;
718e3744 6134}
6135
d62a17ae 6136static struct bgp_static *bgp_static_new(void)
718e3744 6137{
d62a17ae 6138 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6139}
6140
d62a17ae 6141static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6142{
0a22ddfb 6143 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6144 route_map_counter_decrement(bgp_static->rmap.map);
6145
0a22ddfb 6146 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6147 XFREE(MTYPE_BGP_STATIC, bgp_static);
6148}
6149
5f040085 6150void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6151 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6152{
9bcb3eef 6153 struct bgp_dest *dest;
40381db7 6154 struct bgp_path_info *pi;
4b7e6066 6155 struct bgp_path_info *new;
40381db7 6156 struct bgp_path_info rmap_path;
d62a17ae 6157 struct attr attr;
6158 struct attr *attr_new;
b68885f9 6159 route_map_result_t ret;
49e5a4a0 6160#ifdef ENABLE_BGP_VNC
d62a17ae 6161 int vnc_implicit_withdraw = 0;
65efcfce 6162#endif
fee0f4c6 6163
d62a17ae 6164 assert(bgp_static);
dd8103a9 6165
9bcb3eef 6166 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6167
0f05ea43 6168 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6169
d62a17ae 6170 attr.nexthop = bgp_static->igpnexthop;
6171 attr.med = bgp_static->igpmetric;
6172 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6173
7226bc40
TA
6174 if (afi == AFI_IP)
6175 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6176
97a52c82
DA
6177 if (bgp_static->igpmetric)
6178 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6179
d62a17ae 6180 if (bgp_static->atomic)
6181 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6182
d62a17ae 6183 /* Store label index, if required. */
6184 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6185 attr.label_index = bgp_static->label_index;
6186 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6187 }
718e3744 6188
d62a17ae 6189 /* Apply route-map. */
6190 if (bgp_static->rmap.name) {
6191 struct attr attr_tmp = attr;
80ced710 6192
6006b807 6193 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6194 rmap_path.peer = bgp->peer_self;
6195 rmap_path.attr = &attr_tmp;
fee0f4c6 6196
d62a17ae 6197 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6198
1782514f 6199 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6200
d62a17ae 6201 bgp->peer_self->rmap_type = 0;
718e3744 6202
d62a17ae 6203 if (ret == RMAP_DENYMATCH) {
6204 /* Free uninterned attribute. */
6205 bgp_attr_flush(&attr_tmp);
718e3744 6206
d62a17ae 6207 /* Unintern original. */
6208 aspath_unintern(&attr.aspath);
6209 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6210 bgp_dest_unlock_node(dest);
d62a17ae 6211 return;
6212 }
7f323236 6213
637e5ba4 6214 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6215 bgp_attr_add_gshut_community(&attr_tmp);
6216
d62a17ae 6217 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6218 } else {
6219
637e5ba4 6220 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6221 bgp_attr_add_gshut_community(&attr);
6222
d62a17ae 6223 attr_new = bgp_attr_intern(&attr);
7f323236 6224 }
718e3744 6225
9bcb3eef 6226 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6227 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6228 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6229 break;
6230
40381db7
DS
6231 if (pi) {
6232 if (attrhash_cmp(pi->attr, attr_new)
6233 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6234 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6235 bgp_dest_unlock_node(dest);
d62a17ae 6236 bgp_attr_unintern(&attr_new);
6237 aspath_unintern(&attr.aspath);
6238 return;
6239 } else {
6240 /* The attribute is changed. */
9bcb3eef 6241 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6242
6243 /* Rewrite BGP route information. */
40381db7 6244 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6245 bgp_path_info_restore(dest, pi);
d62a17ae 6246 else
40381db7 6247 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6248#ifdef ENABLE_BGP_VNC
d62a17ae 6249 if ((afi == AFI_IP || afi == AFI_IP6)
6250 && (safi == SAFI_UNICAST)) {
40381db7 6251 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6252 /*
6253 * Implicit withdraw case.
40381db7 6254 * We have to do this before pi is
d62a17ae 6255 * changed
6256 */
6257 ++vnc_implicit_withdraw;
40381db7 6258 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6259 vnc_import_bgp_exterior_del_route(
40381db7 6260 bgp, p, pi);
d62a17ae 6261 }
6262 }
65efcfce 6263#endif
40381db7
DS
6264 bgp_attr_unintern(&pi->attr);
6265 pi->attr = attr_new;
083ec940 6266 pi->uptime = monotime(NULL);
49e5a4a0 6267#ifdef ENABLE_BGP_VNC
d62a17ae 6268 if ((afi == AFI_IP || afi == AFI_IP6)
6269 && (safi == SAFI_UNICAST)) {
6270 if (vnc_implicit_withdraw) {
40381db7 6271 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6272 vnc_import_bgp_exterior_add_route(
40381db7 6273 bgp, p, pi);
d62a17ae 6274 }
6275 }
65efcfce 6276#endif
718e3744 6277
d62a17ae 6278 /* Nexthop reachability check. */
892fedb6 6279 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6280 && (safi == SAFI_UNICAST
6281 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6282
6283 struct bgp *bgp_nexthop = bgp;
6284
40381db7
DS
6285 if (pi->extra && pi->extra->bgp_orig)
6286 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6287
6288 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6289 afi, safi, pi, NULL,
654a5978 6290 0, p))
9bcb3eef 6291 bgp_path_info_set_flag(dest, pi,
18ee8310 6292 BGP_PATH_VALID);
d62a17ae 6293 else {
6294 if (BGP_DEBUG(nht, NHT)) {
6295 char buf1[INET6_ADDRSTRLEN];
6296 inet_ntop(p->family,
6297 &p->u.prefix, buf1,
6298 INET6_ADDRSTRLEN);
6299 zlog_debug(
6300 "%s(%s): Route not in table, not advertising",
15569c58 6301 __func__, buf1);
d62a17ae 6302 }
18ee8310 6303 bgp_path_info_unset_flag(
9bcb3eef 6304 dest, pi, BGP_PATH_VALID);
d62a17ae 6305 }
6306 } else {
6307 /* Delete the NHT structure if any, if we're
6308 * toggling between
6309 * enabling/disabling import check. We
6310 * deregister the route
6311 * from NHT to avoid overloading NHT and the
6312 * process interaction
6313 */
40381db7 6314 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6315 bgp_path_info_set_flag(dest, pi,
6316 BGP_PATH_VALID);
d62a17ae 6317 }
6318 /* Process change. */
40381db7 6319 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6320 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6321
6322 if (SAFI_UNICAST == safi
6323 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6324 || bgp->inst_type
6325 == BGP_INSTANCE_TYPE_DEFAULT)) {
6326 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6327 pi);
ddb5b488
PZ
6328 }
6329
9bcb3eef 6330 bgp_dest_unlock_node(dest);
d62a17ae 6331 aspath_unintern(&attr.aspath);
6332 return;
6333 }
718e3744 6334 }
718e3744 6335
d62a17ae 6336 /* Make new BGP info. */
6337 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6338 attr_new, dest);
d62a17ae 6339 /* Nexthop reachability check. */
892fedb6 6340 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6341 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6342 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6343 p))
9bcb3eef 6344 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6345 else {
6346 if (BGP_DEBUG(nht, NHT)) {
6347 char buf1[INET6_ADDRSTRLEN];
6348 inet_ntop(p->family, &p->u.prefix, buf1,
6349 INET6_ADDRSTRLEN);
6350 zlog_debug(
6351 "%s(%s): Route not in table, not advertising",
15569c58 6352 __func__, buf1);
d62a17ae 6353 }
9bcb3eef 6354 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6355 }
6356 } else {
6357 /* Delete the NHT structure if any, if we're toggling between
6358 * enabling/disabling import check. We deregister the route
6359 * from NHT to avoid overloading NHT and the process interaction
6360 */
6361 bgp_unlink_nexthop(new);
6362
9bcb3eef 6363 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6364 }
078430f6 6365
d62a17ae 6366 /* Aggregate address increment. */
6367 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6368
d62a17ae 6369 /* Register new BGP information. */
9bcb3eef 6370 bgp_path_info_add(dest, new);
718e3744 6371
d62a17ae 6372 /* route_node_get lock */
9bcb3eef 6373 bgp_dest_unlock_node(dest);
d62a17ae 6374
6375 /* Process change. */
9bcb3eef 6376 bgp_process(bgp, dest, afi, safi);
d62a17ae 6377
ddb5b488
PZ
6378 if (SAFI_UNICAST == safi
6379 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6380 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6381 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6382 }
6383
d62a17ae 6384 /* Unintern original. */
6385 aspath_unintern(&attr.aspath);
718e3744 6386}
6387
5f040085 6388void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6389 safi_t safi)
718e3744 6390{
9bcb3eef 6391 struct bgp_dest *dest;
40381db7 6392 struct bgp_path_info *pi;
718e3744 6393
9bcb3eef 6394 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6395
d62a17ae 6396 /* Check selected route and self inserted route. */
9bcb3eef 6397 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6398 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6399 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6400 break;
6401
6402 /* Withdraw static BGP route from routing table. */
40381db7 6403 if (pi) {
ddb5b488
PZ
6404 if (SAFI_UNICAST == safi
6405 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6406 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6407 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6408 }
40381db7
DS
6409 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6410 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6411 bgp_path_info_delete(dest, pi);
6412 bgp_process(bgp, dest, afi, safi);
d62a17ae 6413 }
718e3744 6414
d62a17ae 6415 /* Unlock bgp_node_lookup. */
9bcb3eef 6416 bgp_dest_unlock_node(dest);
718e3744 6417}
6418
137446f9
LB
6419/*
6420 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6421 */
5f040085 6422static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6423 afi_t afi, safi_t safi,
6424 struct prefix_rd *prd)
718e3744 6425{
9bcb3eef 6426 struct bgp_dest *dest;
40381db7 6427 struct bgp_path_info *pi;
718e3744 6428
9bcb3eef 6429 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6430
d62a17ae 6431 /* Check selected route and self inserted route. */
9bcb3eef 6432 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6433 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6434 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6435 break;
718e3744 6436
d62a17ae 6437 /* Withdraw static BGP route from routing table. */
40381db7 6438 if (pi) {
49e5a4a0 6439#ifdef ENABLE_BGP_VNC
d62a17ae 6440 rfapiProcessWithdraw(
40381db7 6441 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6442 1); /* Kill, since it is an administrative change */
65efcfce 6443#endif
ddb5b488
PZ
6444 if (SAFI_MPLS_VPN == safi
6445 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6446 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6447 }
40381db7 6448 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6449 bgp_path_info_delete(dest, pi);
6450 bgp_process(bgp, dest, afi, safi);
d62a17ae 6451 }
718e3744 6452
d62a17ae 6453 /* Unlock bgp_node_lookup. */
9bcb3eef 6454 bgp_dest_unlock_node(dest);
718e3744 6455}
6456
5f040085 6457static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6458 struct bgp_static *bgp_static, afi_t afi,
6459 safi_t safi)
137446f9 6460{
9bcb3eef 6461 struct bgp_dest *dest;
4b7e6066 6462 struct bgp_path_info *new;
d62a17ae 6463 struct attr *attr_new;
6464 struct attr attr = {0};
40381db7 6465 struct bgp_path_info *pi;
49e5a4a0 6466#ifdef ENABLE_BGP_VNC
d62a17ae 6467 mpls_label_t label = 0;
65efcfce 6468#endif
d7c0a89a 6469 uint32_t num_labels = 0;
137446f9 6470
d62a17ae 6471 assert(bgp_static);
137446f9 6472
b57ba6d2
MK
6473 if (bgp_static->label != MPLS_INVALID_LABEL)
6474 num_labels = 1;
9bcb3eef
DS
6475 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6476 &bgp_static->prd);
137446f9 6477
0f05ea43 6478 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6479
d62a17ae 6480 attr.nexthop = bgp_static->igpnexthop;
6481 attr.med = bgp_static->igpmetric;
6482 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6483
d62a17ae 6484 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6485 || (safi == SAFI_ENCAP)) {
6486 if (afi == AFI_IP) {
6487 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6488 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6489 }
6490 }
6491 if (afi == AFI_L2VPN) {
b04c1e99
IR
6492 if (bgp_static->gatewayIp.family == AF_INET) {
6493 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6494 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6495 &bgp_static->gatewayIp.u.prefix4,
6496 IPV4_MAX_BYTELEN);
b04c1e99
IR
6497 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6498 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6499 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6500 &bgp_static->gatewayIp.u.prefix6,
6501 IPV6_MAX_BYTELEN);
b04c1e99 6502 }
0a50c248 6503 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6504 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6505 struct bgp_encap_type_vxlan bet;
6006b807 6506 memset(&bet, 0, sizeof(bet));
3714a385 6507 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6508 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6509 }
6510 if (bgp_static->router_mac) {
6511 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6512 }
6513 }
6514 /* Apply route-map. */
6515 if (bgp_static->rmap.name) {
6516 struct attr attr_tmp = attr;
40381db7 6517 struct bgp_path_info rmap_path;
b68885f9 6518 route_map_result_t ret;
137446f9 6519
40381db7
DS
6520 rmap_path.peer = bgp->peer_self;
6521 rmap_path.attr = &attr_tmp;
137446f9 6522
d62a17ae 6523 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6524
1782514f 6525 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6526
d62a17ae 6527 bgp->peer_self->rmap_type = 0;
137446f9 6528
d62a17ae 6529 if (ret == RMAP_DENYMATCH) {
6530 /* Free uninterned attribute. */
6531 bgp_attr_flush(&attr_tmp);
137446f9 6532
d62a17ae 6533 /* Unintern original. */
6534 aspath_unintern(&attr.aspath);
6535 bgp_static_withdraw_safi(bgp, p, afi, safi,
6536 &bgp_static->prd);
bbc52106 6537 bgp_dest_unlock_node(dest);
d62a17ae 6538 return;
6539 }
137446f9 6540
d62a17ae 6541 attr_new = bgp_attr_intern(&attr_tmp);
6542 } else {
6543 attr_new = bgp_attr_intern(&attr);
6544 }
137446f9 6545
9bcb3eef 6546 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6547 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6548 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6549 break;
6550
40381db7 6551 if (pi) {
40381db7 6552 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6553 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6554 bgp_dest_unlock_node(dest);
d62a17ae 6555 bgp_attr_unintern(&attr_new);
6556 aspath_unintern(&attr.aspath);
6557 return;
6558 } else {
6559 /* The attribute is changed. */
9bcb3eef 6560 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6561
6562 /* Rewrite BGP route information. */
40381db7 6563 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6564 bgp_path_info_restore(dest, pi);
d62a17ae 6565 else
40381db7
DS
6566 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6567 bgp_attr_unintern(&pi->attr);
6568 pi->attr = attr_new;
083ec940 6569 pi->uptime = monotime(NULL);
49e5a4a0 6570#ifdef ENABLE_BGP_VNC
40381db7
DS
6571 if (pi->extra)
6572 label = decode_label(&pi->extra->label[0]);
65efcfce 6573#endif
137446f9 6574
d62a17ae 6575 /* Process change. */
40381db7 6576 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6577 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6578
6579 if (SAFI_MPLS_VPN == safi
6580 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6581 vpn_leak_to_vrf_update(bgp, pi,
6582 &bgp_static->prd);
ddb5b488 6583 }
49e5a4a0 6584#ifdef ENABLE_BGP_VNC
40381db7
DS
6585 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6586 pi->attr, afi, safi, pi->type,
6587 pi->sub_type, &label);
65efcfce 6588#endif
9bcb3eef 6589 bgp_dest_unlock_node(dest);
d62a17ae 6590 aspath_unintern(&attr.aspath);
6591 return;
6592 }
6593 }
137446f9
LB
6594
6595
d62a17ae 6596 /* Make new BGP info. */
6597 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6598 attr_new, dest);
1defdda8 6599 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6600 bgp_path_info_extra_get(new);
b57ba6d2
MK
6601 if (num_labels) {
6602 new->extra->label[0] = bgp_static->label;
6603 new->extra->num_labels = num_labels;
6604 }
49e5a4a0 6605#ifdef ENABLE_BGP_VNC
d62a17ae 6606 label = decode_label(&bgp_static->label);
65efcfce 6607#endif
137446f9 6608
d62a17ae 6609 /* Aggregate address increment. */
6610 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6611
d62a17ae 6612 /* Register new BGP information. */
9bcb3eef 6613 bgp_path_info_add(dest, new);
d62a17ae 6614 /* route_node_get lock */
9bcb3eef 6615 bgp_dest_unlock_node(dest);
137446f9 6616
d62a17ae 6617 /* Process change. */
9bcb3eef 6618 bgp_process(bgp, dest, afi, safi);
137446f9 6619
ddb5b488
PZ
6620 if (SAFI_MPLS_VPN == safi
6621 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6622 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6623 }
49e5a4a0 6624#ifdef ENABLE_BGP_VNC
d62a17ae 6625 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6626 safi, new->type, new->sub_type, &label);
65efcfce
LB
6627#endif
6628
d62a17ae 6629 /* Unintern original. */
6630 aspath_unintern(&attr.aspath);
137446f9
LB
6631}
6632
718e3744 6633/* Configure static BGP network. When user don't run zebra, static
6634 route should be installed as valid. */
585f1adc
IR
6635static int bgp_static_set(struct vty *vty, const char *negate,
6636 const char *ip_str, afi_t afi, safi_t safi,
6637 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6638{
585f1adc
IR
6639 VTY_DECLVAR_CONTEXT(bgp, bgp);
6640 int ret;
d62a17ae 6641 struct prefix p;
6642 struct bgp_static *bgp_static;
9bcb3eef 6643 struct bgp_dest *dest;
d7c0a89a 6644 uint8_t need_update = 0;
d62a17ae 6645
585f1adc
IR
6646 /* Convert IP prefix string to struct prefix. */
6647 ret = str2prefix(ip_str, &p);
6648 if (!ret) {
6649 vty_out(vty, "%% Malformed prefix\n");
6650 return CMD_WARNING_CONFIG_FAILED;
6651 }
6652 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6653 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6654 return CMD_WARNING_CONFIG_FAILED;
6655 }
6656
d62a17ae 6657 apply_mask(&p);
718e3744 6658
e2a86ad9 6659 if (negate) {
718e3744 6660
e2a86ad9 6661 /* Set BGP static route configuration. */
9bcb3eef 6662 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6663
9bcb3eef 6664 if (!dest) {
585f1adc
IR
6665 vty_out(vty, "%% Can't find static route specified\n");
6666 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6667 }
6668
9bcb3eef 6669 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6670
e2a86ad9
DS
6671 if ((label_index != BGP_INVALID_LABEL_INDEX)
6672 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6673 vty_out(vty,
6674 "%% label-index doesn't match static route\n");
70d9b134 6675 bgp_dest_unlock_node(dest);
585f1adc 6676 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6677 }
d62a17ae 6678
e2a86ad9
DS
6679 if ((rmap && bgp_static->rmap.name)
6680 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6681 vty_out(vty,
6682 "%% route-map name doesn't match static route\n");
70d9b134 6683 bgp_dest_unlock_node(dest);
585f1adc 6684 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6685 }
718e3744 6686
e2a86ad9
DS
6687 /* Update BGP RIB. */
6688 if (!bgp_static->backdoor)
6689 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6690
e2a86ad9
DS
6691 /* Clear configuration. */
6692 bgp_static_free(bgp_static);
9bcb3eef
DS
6693 bgp_dest_set_bgp_static_info(dest, NULL);
6694 bgp_dest_unlock_node(dest);
6695 bgp_dest_unlock_node(dest);
e2a86ad9 6696 } else {
718e3744 6697
e2a86ad9 6698 /* Set BGP static route configuration. */
9bcb3eef
DS
6699 dest = bgp_node_get(bgp->route[afi][safi], &p);
6700 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6701 if (bgp_static) {
e2a86ad9 6702 /* Configuration change. */
e2a86ad9
DS
6703 /* Label index cannot be changed. */
6704 if (bgp_static->label_index != label_index) {
585f1adc 6705 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6706 bgp_dest_unlock_node(dest);
585f1adc 6707 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6708 }
d62a17ae 6709
e2a86ad9 6710 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6711 if (bgp_static->valid
6712 && bgp_static->backdoor != backdoor)
e2a86ad9 6713 need_update = 1;
718e3744 6714
e2a86ad9 6715 bgp_static->backdoor = backdoor;
718e3744 6716
e2a86ad9 6717 if (rmap) {
0a22ddfb
QY
6718 XFREE(MTYPE_ROUTE_MAP_NAME,
6719 bgp_static->rmap.name);
b4897fa5 6720 route_map_counter_decrement(
6721 bgp_static->rmap.map);
e2a86ad9
DS
6722 bgp_static->rmap.name =
6723 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6724 bgp_static->rmap.map =
6725 route_map_lookup_by_name(rmap);
b4897fa5 6726 route_map_counter_increment(
6727 bgp_static->rmap.map);
e2a86ad9 6728 } else {
0a22ddfb
QY
6729 XFREE(MTYPE_ROUTE_MAP_NAME,
6730 bgp_static->rmap.name);
b4897fa5 6731 route_map_counter_decrement(
6732 bgp_static->rmap.map);
e2a86ad9
DS
6733 bgp_static->rmap.map = NULL;
6734 bgp_static->valid = 0;
6735 }
9bcb3eef 6736 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6737 } else {
6738 /* New configuration. */
6739 bgp_static = bgp_static_new();
6740 bgp_static->backdoor = backdoor;
6741 bgp_static->valid = 0;
6742 bgp_static->igpmetric = 0;
975a328e 6743 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6744 bgp_static->label_index = label_index;
718e3744 6745
e2a86ad9 6746 if (rmap) {
0a22ddfb
QY
6747 XFREE(MTYPE_ROUTE_MAP_NAME,
6748 bgp_static->rmap.name);
b4897fa5 6749 route_map_counter_decrement(
6750 bgp_static->rmap.map);
e2a86ad9
DS
6751 bgp_static->rmap.name =
6752 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6753 bgp_static->rmap.map =
6754 route_map_lookup_by_name(rmap);
b4897fa5 6755 route_map_counter_increment(
6756 bgp_static->rmap.map);
e2a86ad9 6757 }
9bcb3eef 6758 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6759 }
d62a17ae 6760
e2a86ad9
DS
6761 bgp_static->valid = 1;
6762 if (need_update)
6763 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6764
e2a86ad9
DS
6765 if (!bgp_static->backdoor)
6766 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6767 }
d62a17ae 6768
585f1adc 6769 return CMD_SUCCESS;
d62a17ae 6770}
6771
6772void bgp_static_add(struct bgp *bgp)
6773{
6774 afi_t afi;
6775 safi_t safi;
9bcb3eef
DS
6776 struct bgp_dest *dest;
6777 struct bgp_dest *rm;
d62a17ae 6778 struct bgp_table *table;
6779 struct bgp_static *bgp_static;
6780
47fc6261 6781 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6782 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6783 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6784 dest = bgp_route_next(dest)) {
6785 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6786 continue;
ea47320b 6787
05c7a1cc
QY
6788 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6789 || (safi == SAFI_EVPN)) {
9bcb3eef 6790 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6791
6792 for (rm = bgp_table_top(table); rm;
6793 rm = bgp_route_next(rm)) {
a78beeb5 6794 bgp_static =
9bcb3eef 6795 bgp_dest_get_bgp_static_info(
5a8ba9fc 6796 rm);
9bcb3eef
DS
6797 bgp_static_update_safi(
6798 bgp, bgp_dest_get_prefix(rm),
6799 bgp_static, afi, safi);
d62a17ae 6800 }
05c7a1cc 6801 } else {
5a8ba9fc 6802 bgp_static_update(
9bcb3eef
DS
6803 bgp, bgp_dest_get_prefix(dest),
6804 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6805 safi);
ea47320b 6806 }
05c7a1cc 6807 }
47fc6261 6808 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6809}
6810
718e3744 6811/* Called from bgp_delete(). Delete all static routes from the BGP
6812 instance. */
d62a17ae 6813void bgp_static_delete(struct bgp *bgp)
6814{
6815 afi_t afi;
6816 safi_t safi;
9bcb3eef
DS
6817 struct bgp_dest *dest;
6818 struct bgp_dest *rm;
d62a17ae 6819 struct bgp_table *table;
6820 struct bgp_static *bgp_static;
6821
05c7a1cc 6822 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6823 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6824 dest = bgp_route_next(dest)) {
6825 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6826 continue;
ea47320b 6827
05c7a1cc
QY
6828 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6829 || (safi == SAFI_EVPN)) {
9bcb3eef 6830 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6831
6832 for (rm = bgp_table_top(table); rm;
6833 rm = bgp_route_next(rm)) {
a78beeb5 6834 bgp_static =
9bcb3eef 6835 bgp_dest_get_bgp_static_info(
5a8ba9fc 6836 rm);
c7d14ba6
PG
6837 if (!bgp_static)
6838 continue;
6839
05c7a1cc 6840 bgp_static_withdraw_safi(
9bcb3eef 6841 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6842 AFI_IP, safi,
6843 (struct prefix_rd *)
9bcb3eef
DS
6844 bgp_dest_get_prefix(
6845 dest));
ea47320b 6846 bgp_static_free(bgp_static);
811c6797 6847 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6848 NULL);
811c6797 6849 bgp_dest_unlock_node(rm);
d62a17ae 6850 }
05c7a1cc 6851 } else {
9bcb3eef 6852 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6853 bgp_static_withdraw(bgp,
9bcb3eef 6854 bgp_dest_get_prefix(dest),
b54892e0 6855 afi, safi);
05c7a1cc 6856 bgp_static_free(bgp_static);
9bcb3eef
DS
6857 bgp_dest_set_bgp_static_info(dest, NULL);
6858 bgp_dest_unlock_node(dest);
ea47320b 6859 }
05c7a1cc 6860 }
d62a17ae 6861}
6862
6863void bgp_static_redo_import_check(struct bgp *bgp)
6864{
6865 afi_t afi;
6866 safi_t safi;
9bcb3eef
DS
6867 struct bgp_dest *dest;
6868 struct bgp_dest *rm;
d62a17ae 6869 struct bgp_table *table;
6870 struct bgp_static *bgp_static;
6871
6872 /* Use this flag to force reprocessing of the route */
892fedb6 6873 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6874 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6875 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6876 dest = bgp_route_next(dest)) {
6877 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6878 continue;
ea47320b 6879
05c7a1cc
QY
6880 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6881 || (safi == SAFI_EVPN)) {
9bcb3eef 6882 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6883
6884 for (rm = bgp_table_top(table); rm;
6885 rm = bgp_route_next(rm)) {
a78beeb5 6886 bgp_static =
9bcb3eef 6887 bgp_dest_get_bgp_static_info(
5a8ba9fc 6888 rm);
9bcb3eef
DS
6889 bgp_static_update_safi(
6890 bgp, bgp_dest_get_prefix(rm),
6891 bgp_static, afi, safi);
d62a17ae 6892 }
05c7a1cc 6893 } else {
9bcb3eef
DS
6894 bgp_static = bgp_dest_get_bgp_static_info(dest);
6895 bgp_static_update(bgp,
6896 bgp_dest_get_prefix(dest),
6897 bgp_static, afi, safi);
ea47320b 6898 }
05c7a1cc
QY
6899 }
6900 }
892fedb6 6901 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6902}
6903
6904static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6905 safi_t safi)
6906{
6907 struct bgp_table *table;
9bcb3eef 6908 struct bgp_dest *dest;
40381db7 6909 struct bgp_path_info *pi;
d62a17ae 6910
dfb6fd1d
NT
6911 /* Do not install the aggregate route if BGP is in the
6912 * process of termination.
6913 */
892fedb6
DA
6914 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6915 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6916 return;
6917
d62a17ae 6918 table = bgp->rib[afi][safi];
9bcb3eef
DS
6919 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6920 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6921 if (pi->peer == bgp->peer_self
6922 && ((pi->type == ZEBRA_ROUTE_BGP
6923 && pi->sub_type == BGP_ROUTE_STATIC)
6924 || (pi->type != ZEBRA_ROUTE_BGP
6925 && pi->sub_type
d62a17ae 6926 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6927 bgp_aggregate_decrement(
6928 bgp, bgp_dest_get_prefix(dest), pi, afi,
6929 safi);
40381db7 6930 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6931 bgp_path_info_delete(dest, pi);
6932 bgp_process(bgp, dest, afi, safi);
d62a17ae 6933 }
6934 }
6935 }
ad4cbda1 6936}
6937
6938/*
6939 * Purge all networks and redistributed routes from routing table.
6940 * Invoked upon the instance going down.
6941 */
d62a17ae 6942void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6943{
d62a17ae 6944 afi_t afi;
6945 safi_t safi;
ad4cbda1 6946
05c7a1cc
QY
6947 FOREACH_AFI_SAFI (afi, safi)
6948 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6949}
6950
137446f9
LB
6951/*
6952 * gpz 110624
6953 * Currently this is used to set static routes for VPN and ENCAP.
6954 * I think it can probably be factored with bgp_static_set.
6955 */
d62a17ae 6956int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6957 const char *ip_str, const char *rd_str,
6958 const char *label_str, const char *rmap_str,
6959 int evpn_type, const char *esi, const char *gwip,
6960 const char *ethtag, const char *routermac)
6961{
6962 VTY_DECLVAR_CONTEXT(bgp, bgp);
6963 int ret;
6964 struct prefix p;
6965 struct prefix_rd prd;
9bcb3eef
DS
6966 struct bgp_dest *pdest;
6967 struct bgp_dest *dest;
d62a17ae 6968 struct bgp_table *table;
6969 struct bgp_static *bgp_static;
6970 mpls_label_t label = MPLS_INVALID_LABEL;
6971 struct prefix gw_ip;
6972
6973 /* validate ip prefix */
6974 ret = str2prefix(ip_str, &p);
6975 if (!ret) {
6976 vty_out(vty, "%% Malformed prefix\n");
6977 return CMD_WARNING_CONFIG_FAILED;
6978 }
6979 apply_mask(&p);
6980 if ((afi == AFI_L2VPN)
6981 && (bgp_build_evpn_prefix(evpn_type,
6982 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6983 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6984 return CMD_WARNING_CONFIG_FAILED;
6985 }
718e3744 6986
d62a17ae 6987 ret = str2prefix_rd(rd_str, &prd);
6988 if (!ret) {
6989 vty_out(vty, "%% Malformed rd\n");
6990 return CMD_WARNING_CONFIG_FAILED;
6991 }
718e3744 6992
d62a17ae 6993 if (label_str) {
6994 unsigned long label_val;
6995 label_val = strtoul(label_str, NULL, 10);
6996 encode_label(label_val, &label);
6997 }
9bedbb1e 6998
d62a17ae 6999 if (safi == SAFI_EVPN) {
7000 if (esi && str2esi(esi, NULL) == 0) {
7001 vty_out(vty, "%% Malformed ESI\n");
7002 return CMD_WARNING_CONFIG_FAILED;
7003 }
7004 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7005 vty_out(vty, "%% Malformed Router MAC\n");
7006 return CMD_WARNING_CONFIG_FAILED;
7007 }
7008 if (gwip) {
6006b807 7009 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7010 ret = str2prefix(gwip, &gw_ip);
7011 if (!ret) {
7012 vty_out(vty, "%% Malformed GatewayIp\n");
7013 return CMD_WARNING_CONFIG_FAILED;
7014 }
7015 if ((gw_ip.family == AF_INET
3714a385 7016 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7017 (struct prefix_evpn *)&p))
7018 || (gw_ip.family == AF_INET6
3714a385 7019 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7020 (struct prefix_evpn *)&p))) {
7021 vty_out(vty,
7022 "%% GatewayIp family differs with IP prefix\n");
7023 return CMD_WARNING_CONFIG_FAILED;
7024 }
7025 }
7026 }
9bcb3eef
DS
7027 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7028 if (!bgp_dest_has_bgp_path_info_data(pdest))
7029 bgp_dest_set_bgp_table_info(pdest,
67009e22 7030 bgp_table_init(bgp, afi, safi));
9bcb3eef 7031 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7032
9bcb3eef 7033 dest = bgp_node_get(table, &p);
d62a17ae 7034
9bcb3eef 7035 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7036 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7037 bgp_dest_unlock_node(dest);
d62a17ae 7038 } else {
7039 /* New configuration. */
7040 bgp_static = bgp_static_new();
7041 bgp_static->backdoor = 0;
7042 bgp_static->valid = 0;
7043 bgp_static->igpmetric = 0;
975a328e 7044 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7045 bgp_static->label = label;
7046 bgp_static->prd = prd;
7047
7048 if (rmap_str) {
0a22ddfb 7049 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7050 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7051 bgp_static->rmap.name =
7052 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7053 bgp_static->rmap.map =
7054 route_map_lookup_by_name(rmap_str);
b4897fa5 7055 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7056 }
718e3744 7057
d62a17ae 7058 if (safi == SAFI_EVPN) {
7059 if (esi) {
7060 bgp_static->eth_s_id =
7061 XCALLOC(MTYPE_ATTR,
0a50c248 7062 sizeof(esi_t));
d62a17ae 7063 str2esi(esi, bgp_static->eth_s_id);
7064 }
7065 if (routermac) {
7066 bgp_static->router_mac =
28328ea9 7067 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7068 (void)prefix_str2mac(routermac,
7069 bgp_static->router_mac);
d62a17ae 7070 }
7071 if (gwip)
7072 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7073 }
9bcb3eef 7074 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7075
d62a17ae 7076 bgp_static->valid = 1;
7077 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7078 }
718e3744 7079
d62a17ae 7080 return CMD_SUCCESS;
718e3744 7081}
7082
7083/* Configure static BGP network. */
d62a17ae 7084int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7085 const char *ip_str, const char *rd_str,
7086 const char *label_str, int evpn_type, const char *esi,
7087 const char *gwip, const char *ethtag)
7088{
7089 VTY_DECLVAR_CONTEXT(bgp, bgp);
7090 int ret;
7091 struct prefix p;
7092 struct prefix_rd prd;
9bcb3eef
DS
7093 struct bgp_dest *pdest;
7094 struct bgp_dest *dest;
d62a17ae 7095 struct bgp_table *table;
7096 struct bgp_static *bgp_static;
7097 mpls_label_t label = MPLS_INVALID_LABEL;
7098
7099 /* Convert IP prefix string to struct prefix. */
7100 ret = str2prefix(ip_str, &p);
7101 if (!ret) {
7102 vty_out(vty, "%% Malformed prefix\n");
7103 return CMD_WARNING_CONFIG_FAILED;
7104 }
7105 apply_mask(&p);
7106 if ((afi == AFI_L2VPN)
7107 && (bgp_build_evpn_prefix(evpn_type,
7108 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7109 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7110 return CMD_WARNING_CONFIG_FAILED;
7111 }
7112 ret = str2prefix_rd(rd_str, &prd);
7113 if (!ret) {
7114 vty_out(vty, "%% Malformed rd\n");
7115 return CMD_WARNING_CONFIG_FAILED;
7116 }
718e3744 7117
d62a17ae 7118 if (label_str) {
7119 unsigned long label_val;
7120 label_val = strtoul(label_str, NULL, 10);
7121 encode_label(label_val, &label);
7122 }
718e3744 7123
9bcb3eef
DS
7124 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7125 if (!bgp_dest_has_bgp_path_info_data(pdest))
7126 bgp_dest_set_bgp_table_info(pdest,
67009e22 7127 bgp_table_init(bgp, afi, safi));
d62a17ae 7128 else
9bcb3eef
DS
7129 bgp_dest_unlock_node(pdest);
7130 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7131
9bcb3eef 7132 dest = bgp_node_lookup(table, &p);
6b0655a2 7133
9bcb3eef 7134 if (dest) {
d62a17ae 7135 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7136
9bcb3eef 7137 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7138 bgp_static_free(bgp_static);
9bcb3eef
DS
7139 bgp_dest_set_bgp_static_info(dest, NULL);
7140 bgp_dest_unlock_node(dest);
7141 bgp_dest_unlock_node(dest);
d62a17ae 7142 } else
7143 vty_out(vty, "%% Can't find the route\n");
7144
7145 return CMD_SUCCESS;
7146}
7147
7148static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7149 const char *rmap_name)
7150{
7151 VTY_DECLVAR_CONTEXT(bgp, bgp);
7152 struct bgp_rmap *rmap;
7153
7154 rmap = &bgp->table_map[afi][safi];
7155 if (rmap_name) {
0a22ddfb 7156 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7157 route_map_counter_decrement(rmap->map);
d62a17ae 7158 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7159 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7160 route_map_counter_increment(rmap->map);
d62a17ae 7161 } else {
0a22ddfb 7162 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7163 route_map_counter_decrement(rmap->map);
d62a17ae 7164 rmap->map = NULL;
7165 }
73ac8160 7166
d62a17ae 7167 if (bgp_fibupd_safi(safi))
7168 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7169
d62a17ae 7170 return CMD_SUCCESS;
73ac8160
DS
7171}
7172
d62a17ae 7173static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7174 const char *rmap_name)
73ac8160 7175{
d62a17ae 7176 VTY_DECLVAR_CONTEXT(bgp, bgp);
7177 struct bgp_rmap *rmap;
73ac8160 7178
d62a17ae 7179 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7180 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7181 route_map_counter_decrement(rmap->map);
d62a17ae 7182 rmap->map = NULL;
73ac8160 7183
d62a17ae 7184 if (bgp_fibupd_safi(safi))
7185 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7186
d62a17ae 7187 return CMD_SUCCESS;
73ac8160
DS
7188}
7189
2b791107 7190void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7191 safi_t safi)
73ac8160 7192{
d62a17ae 7193 if (bgp->table_map[afi][safi].name) {
d62a17ae 7194 vty_out(vty, " table-map %s\n",
7195 bgp->table_map[afi][safi].name);
7196 }
73ac8160
DS
7197}
7198
73ac8160
DS
7199DEFUN (bgp_table_map,
7200 bgp_table_map_cmd,
7201 "table-map WORD",
7202 "BGP table to RIB route download filter\n"
7203 "Name of the route map\n")
7204{
d62a17ae 7205 int idx_word = 1;
7206 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7207 argv[idx_word]->arg);
73ac8160
DS
7208}
7209DEFUN (no_bgp_table_map,
7210 no_bgp_table_map_cmd,
7211 "no table-map WORD",
3a2d747c 7212 NO_STR
73ac8160
DS
7213 "BGP table to RIB route download filter\n"
7214 "Name of the route map\n")
7215{
d62a17ae 7216 int idx_word = 2;
7217 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7218 argv[idx_word]->arg);
73ac8160
DS
7219}
7220
585f1adc
IR
7221DEFPY(bgp_network,
7222 bgp_network_cmd,
7223 "[no] network \
7224 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7225 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7226 backdoor$backdoor}]",
7227 NO_STR
7228 "Specify a network to announce via BGP\n"
7229 "IPv4 prefix\n"
7230 "Network number\n"
7231 "Network mask\n"
7232 "Network mask\n"
7233 "Route-map to modify the attributes\n"
7234 "Name of the route map\n"
7235 "Label index to associate with the prefix\n"
7236 "Label index value\n"
7237 "Specify a BGP backdoor route\n")
7238{
7239 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7240
7241 if (address_str) {
7242 int ret;
718e3744 7243
e2a86ad9 7244 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7245 addr_prefix_str,
7246 sizeof(addr_prefix_str));
e2a86ad9
DS
7247 if (!ret) {
7248 vty_out(vty, "%% Inconsistent address and mask\n");
7249 return CMD_WARNING_CONFIG_FAILED;
7250 }
d62a17ae 7251 }
718e3744 7252
585f1adc
IR
7253 return bgp_static_set(
7254 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7255 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7256 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7257}
7258
585f1adc
IR
7259DEFPY(ipv6_bgp_network,
7260 ipv6_bgp_network_cmd,
7261 "[no] network X:X::X:X/M$prefix \
70dd370f 7262 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7263 NO_STR
7264 "Specify a network to announce via BGP\n"
7265 "IPv6 prefix\n"
7266 "Route-map to modify the attributes\n"
7267 "Name of the route map\n"
7268 "Label index to associate with the prefix\n"
7269 "Label index value\n")
37a87b8f 7270{
585f1adc
IR
7271 return bgp_static_set(
7272 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7273 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7274}
7275
d62a17ae 7276static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7277{
d62a17ae 7278 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7279}
7280
d62a17ae 7281static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7282{
365ab2e7
RZ
7283 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7284 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7285 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7286 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7287 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7288}
718e3744 7289
365ab2e7
RZ
7290/**
7291 * Helper function to avoid repeated code: prepare variables for a
7292 * `route_map_apply` call.
7293 *
7294 * \returns `true` on route map match, otherwise `false`.
7295 */
7296static bool aggr_suppress_map_test(struct bgp *bgp,
7297 struct bgp_aggregate *aggregate,
7298 struct bgp_path_info *pi)
7299{
7300 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7301 route_map_result_t rmr = RMAP_DENYMATCH;
7302 struct bgp_path_info rmap_path = {};
7303 struct attr attr = {};
7304
7305 /* No route map entries created, just don't match. */
7306 if (aggregate->suppress_map == NULL)
7307 return false;
7308
7309 /* Call route map matching and return result. */
7310 attr.aspath = aspath_empty();
7311 rmap_path.peer = bgp->peer_self;
7312 rmap_path.attr = &attr;
7313
7314 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7315 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7316 bgp->peer_self->rmap_type = 0;
7317
7318 bgp_attr_flush(&attr);
afb254d7 7319 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7320
7321 return rmr == RMAP_PERMITMATCH;
7322}
7323
4056a5f6
RZ
7324/** Test whether the aggregation has suppressed this path or not. */
7325static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7326 struct bgp_path_info *pi)
7327{
7328 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7329 return false;
7330
7331 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7332}
7333
7334/**
7335 * Suppress this path and keep the reference.
7336 *
7337 * \returns `true` if needs processing otherwise `false`.
7338 */
7339static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7340 struct bgp_path_info *pi)
7341{
7342 struct bgp_path_info_extra *pie;
7343
7344 /* Path is already suppressed by this aggregation. */
7345 if (aggr_suppress_exists(aggregate, pi))
7346 return false;
7347
7348 pie = bgp_path_info_extra_get(pi);
7349
7350 /* This is the first suppression, allocate memory and list it. */
7351 if (pie->aggr_suppressors == NULL)
7352 pie->aggr_suppressors = list_new();
7353
7354 listnode_add(pie->aggr_suppressors, aggregate);
7355
7356 /* Only mark for processing if suppressed. */
7357 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7358 if (BGP_DEBUG(update, UPDATE_OUT))
7359 zlog_debug("aggregate-address suppressing: %pFX",
7360 bgp_dest_get_prefix(pi->net));
7361
4056a5f6
RZ
7362 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7363 return true;
7364 }
7365
7366 return false;
7367}
7368
7369/**
7370 * Unsuppress this path and remove the reference.
7371 *
7372 * \returns `true` if needs processing otherwise `false`.
7373 */
7374static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7375 struct bgp_path_info *pi)
7376{
7377 /* Path wasn't suppressed. */
7378 if (!aggr_suppress_exists(aggregate, pi))
7379 return false;
7380
7381 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7382
7383 /* Unsuppress and free extra memory if last item. */
7384 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7385 if (BGP_DEBUG(update, UPDATE_OUT))
7386 zlog_debug("aggregate-address unsuppressing: %pFX",
7387 bgp_dest_get_prefix(pi->net));
7388
4056a5f6
RZ
7389 list_delete(&pi->extra->aggr_suppressors);
7390 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7391 return true;
7392 }
7393
7394 return false;
7395}
7396
3dc339cd
DA
7397static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7398 struct aspath *aspath,
7399 struct community *comm,
7400 struct ecommunity *ecomm,
7401 struct lcommunity *lcomm)
eaaf8adb
DS
7402{
7403 static struct aspath *ae = NULL;
7404
7405 if (!ae)
7406 ae = aspath_empty();
7407
40381db7 7408 if (!pi)
3dc339cd 7409 return false;
eaaf8adb 7410
40381db7 7411 if (origin != pi->attr->origin)
3dc339cd 7412 return false;
eaaf8adb 7413
40381db7 7414 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7415 return false;
29f7d023 7416
9a706b42 7417 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7418 return false;
eaaf8adb 7419
b53e67a3 7420 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7421 return false;
eaaf8adb 7422
1bcf3a96 7423 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7424 return false;
dd18c5a9 7425
40381db7 7426 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7427 return false;
7ce8a8e0 7428
3dc339cd 7429 return true;
eaaf8adb
DS
7430}
7431
5f040085
DS
7432static void bgp_aggregate_install(
7433 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7434 uint8_t origin, struct aspath *aspath, struct community *community,
7435 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7436 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7437{
9bcb3eef 7438 struct bgp_dest *dest;
c701010e 7439 struct bgp_table *table;
6f94b685 7440 struct bgp_path_info *pi, *orig, *new;
20894f50 7441 struct attr *attr;
c701010e
DS
7442
7443 table = bgp->rib[afi][safi];
7444
9bcb3eef 7445 dest = bgp_node_get(table, p);
eaaf8adb 7446
9bcb3eef 7447 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7448 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7449 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7450 break;
7451
6aabb15d
RZ
7452 /*
7453 * If we have paths with different MEDs, then don't install
7454 * (or uninstall) the aggregate route.
7455 */
7456 if (aggregate->match_med && aggregate->med_mismatched)
7457 goto uninstall_aggregate_route;
7458
c701010e 7459 if (aggregate->count > 0) {
eaaf8adb
DS
7460 /*
7461 * If the aggregate information has not changed
7462 * no need to re-install it again.
7463 */
6f94b685 7464 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7465 ecommunity, lcommunity)) {
9bcb3eef 7466 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7467
7468 if (aspath)
7469 aspath_free(aspath);
7470 if (community)
3c1f53de 7471 community_free(&community);
3da2cc32
DS
7472 if (ecommunity)
7473 ecommunity_free(&ecommunity);
dd18c5a9
DS
7474 if (lcommunity)
7475 lcommunity_free(&lcommunity);
eaaf8adb
DS
7476
7477 return;
7478 }
7479
7480 /*
7481 * Mark the old as unusable
7482 */
40381db7 7483 if (pi)
9bcb3eef 7484 bgp_path_info_delete(dest, pi);
eaaf8adb 7485
20894f50
DA
7486 attr = bgp_attr_aggregate_intern(
7487 bgp, origin, aspath, community, ecommunity, lcommunity,
7488 aggregate, atomic_aggregate, p);
7489
7490 if (!attr) {
8c0044f3 7491 bgp_dest_unlock_node(dest);
20894f50 7492 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7493 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7494 zlog_debug("%s: %pFX null attribute", __func__,
7495 p);
20894f50
DA
7496 return;
7497 }
7498
3da2cc32 7499 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7500 bgp->peer_self, attr, dest);
20894f50 7501
1defdda8 7502 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7503
9bcb3eef
DS
7504 bgp_path_info_add(dest, new);
7505 bgp_process(bgp, dest, afi, safi);
c701010e 7506 } else {
6aabb15d 7507 uninstall_aggregate_route:
6f94b685 7508 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7509 if (pi->peer == bgp->peer_self
7510 && pi->type == ZEBRA_ROUTE_BGP
7511 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7512 break;
7513
7514 /* Withdraw static BGP route from routing table. */
40381db7 7515 if (pi) {
9bcb3eef
DS
7516 bgp_path_info_delete(dest, pi);
7517 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7518 }
7519 }
7520
9bcb3eef 7521 bgp_dest_unlock_node(dest);
c701010e
DS
7522}
7523
6aabb15d
RZ
7524/**
7525 * Check if the current path has different MED than other known paths.
7526 *
7527 * \returns `true` if the MED matched the others else `false`.
7528 */
7529static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7530 struct bgp *bgp, struct bgp_path_info *pi)
7531{
7532 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7533
7534 /* This is the first route being analyzed. */
7535 if (!aggregate->med_initialized) {
7536 aggregate->med_initialized = true;
7537 aggregate->med_mismatched = false;
7538 aggregate->med_matched_value = cur_med;
7539 } else {
7540 /* Check if routes with different MED showed up. */
7541 if (cur_med != aggregate->med_matched_value)
7542 aggregate->med_mismatched = true;
7543 }
7544
7545 return !aggregate->med_mismatched;
7546}
7547
7548/**
7549 * Initializes and tests all routes in the aggregate address path for MED
7550 * values.
7551 *
7552 * \returns `true` if all MEDs are the same otherwise `false`.
7553 */
7554static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7555 struct bgp *bgp, const struct prefix *p,
7556 afi_t afi, safi_t safi)
7557{
7558 struct bgp_table *table = bgp->rib[afi][safi];
7559 const struct prefix *dest_p;
7560 struct bgp_dest *dest, *top;
7561 struct bgp_path_info *pi;
7562 bool med_matched = true;
7563
7564 aggregate->med_initialized = false;
7565
7566 top = bgp_node_get(table, p);
7567 for (dest = bgp_node_get(table, p); dest;
7568 dest = bgp_route_next_until(dest, top)) {
7569 dest_p = bgp_dest_get_prefix(dest);
7570 if (dest_p->prefixlen <= p->prefixlen)
7571 continue;
7572
7573 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7574 if (BGP_PATH_HOLDDOWN(pi))
7575 continue;
7576 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7577 continue;
7578 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7579 med_matched = false;
7580 break;
7581 }
7582 }
7583 if (!med_matched)
7584 break;
7585 }
7586 bgp_dest_unlock_node(top);
7587
7588 return med_matched;
7589}
7590
7591/**
7592 * Toggles the route suppression status for this aggregate address
7593 * configuration.
7594 */
4056a5f6
RZ
7595void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7596 struct bgp *bgp, const struct prefix *p,
7597 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7598{
7599 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7600 const struct prefix *dest_p;
7601 struct bgp_dest *dest, *top;
7602 struct bgp_path_info *pi;
7603 bool toggle_suppression;
7604
7605 /* We've found a different MED we must revert any suppressed routes. */
7606 top = bgp_node_get(table, p);
7607 for (dest = bgp_node_get(table, p); dest;
7608 dest = bgp_route_next_until(dest, top)) {
7609 dest_p = bgp_dest_get_prefix(dest);
7610 if (dest_p->prefixlen <= p->prefixlen)
7611 continue;
7612
7613 toggle_suppression = false;
7614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7615 if (BGP_PATH_HOLDDOWN(pi))
7616 continue;
7617 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7618 continue;
7619
6aabb15d
RZ
7620 /* We are toggling suppression back. */
7621 if (suppress) {
6aabb15d 7622 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7623 if (aggr_suppress_path(aggregate, pi))
7624 toggle_suppression = true;
6aabb15d
RZ
7625 continue;
7626 }
7627
6aabb15d 7628 /* Install route if there is no more suppression. */
4056a5f6 7629 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7630 toggle_suppression = true;
6aabb15d
RZ
7631 }
7632
7633 if (toggle_suppression)
7634 bgp_process(bgp, dest, afi, safi);
7635 }
7636 bgp_dest_unlock_node(top);
7637}
7638
7639/**
7640 * Aggregate address MED matching incremental test: this function is called
7641 * when the initial aggregation occurred and we are only testing a single
7642 * new path.
7643 *
7644 * In addition to testing and setting the MED validity it also installs back
7645 * suppressed routes (if summary is configured).
7646 *
7647 * Must not be called in `bgp_aggregate_route`.
7648 */
7649static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7650 struct bgp *bgp, const struct prefix *p,
7651 afi_t afi, safi_t safi,
f66624f5 7652 struct bgp_path_info *pi)
6aabb15d
RZ
7653{
7654 /* MED matching disabled. */
7655 if (!aggregate->match_med)
7656 return;
7657
f66624f5
DA
7658 /* Aggregation with different MED, recheck if we have got equal MEDs
7659 * now.
6aabb15d 7660 */
f66624f5
DA
7661 if (aggregate->med_mismatched &&
7662 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7663 aggregate->summary_only)
7664 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7665 true);
7666 else
6aabb15d
RZ
7667 bgp_aggregate_med_match(aggregate, bgp, pi);
7668
7669 /* No mismatches, just quit. */
7670 if (!aggregate->med_mismatched)
7671 return;
7672
7673 /* Route summarization is disabled. */
7674 if (!aggregate->summary_only)
7675 return;
7676
7677 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7678}
7679
b5d58c32 7680/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7681void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7682 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7683{
7684 struct bgp_table *table;
9bcb3eef
DS
7685 struct bgp_dest *top;
7686 struct bgp_dest *dest;
d7c0a89a 7687 uint8_t origin;
d62a17ae 7688 struct aspath *aspath = NULL;
d62a17ae 7689 struct community *community = NULL;
3da2cc32 7690 struct ecommunity *ecommunity = NULL;
dd18c5a9 7691 struct lcommunity *lcommunity = NULL;
40381db7 7692 struct bgp_path_info *pi;
d62a17ae 7693 unsigned long match = 0;
d7c0a89a 7694 uint8_t atomic_aggregate = 0;
d62a17ae 7695
9f822fa2
S
7696 /* If the bgp instance is being deleted or self peer is deleted
7697 * then do not create aggregate route
7698 */
892fedb6
DA
7699 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7700 || (bgp->peer_self == NULL))
9f822fa2
S
7701 return;
7702
6aabb15d
RZ
7703 /* Initialize and test routes for MED difference. */
7704 if (aggregate->match_med)
7705 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7706
4056a5f6
RZ
7707 /*
7708 * Reset aggregate count: we might've been called from route map
7709 * update so in that case we must retest all more specific routes.
7710 *
7711 * \see `bgp_route_map_process_update`.
7712 */
7713 aggregate->count = 0;
7714 aggregate->incomplete_origin_count = 0;
7715 aggregate->incomplete_origin_count = 0;
7716 aggregate->egp_origin_count = 0;
7717
d62a17ae 7718 /* ORIGIN attribute: If at least one route among routes that are
7719 aggregated has ORIGIN with the value INCOMPLETE, then the
7720 aggregated route must have the ORIGIN attribute with the value
7721 INCOMPLETE. Otherwise, if at least one route among routes that
7722 are aggregated has ORIGIN with the value EGP, then the aggregated
7723 route must have the origin attribute with the value EGP. In all
7724 other case the value of the ORIGIN attribute of the aggregated
7725 route is INTERNAL. */
7726 origin = BGP_ORIGIN_IGP;
718e3744 7727
d62a17ae 7728 table = bgp->rib[afi][safi];
718e3744 7729
d62a17ae 7730 top = bgp_node_get(table, p);
9bcb3eef
DS
7731 for (dest = bgp_node_get(table, p); dest;
7732 dest = bgp_route_next_until(dest, top)) {
7733 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7734
9bcb3eef 7735 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7736 continue;
d62a17ae 7737
a77e2f4b
S
7738 /* If suppress fib is enabled and route not installed
7739 * in FIB, skip the route
7740 */
7741 if (!bgp_check_advertise(bgp, dest))
7742 continue;
7743
c2ff8b3e 7744 match = 0;
d62a17ae 7745
9bcb3eef 7746 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7747 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7748 continue;
718e3744 7749
40381db7 7750 if (pi->attr->flag
c2ff8b3e
DS
7751 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7752 atomic_aggregate = 1;
d62a17ae 7753
40381db7 7754 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7755 continue;
d62a17ae 7756
f273fef1
DS
7757 /*
7758 * summary-only aggregate route suppress
7759 * aggregated route announcements.
6aabb15d
RZ
7760 *
7761 * MED matching:
7762 * Don't create summaries if MED didn't match
7763 * otherwise neither the specific routes and the
7764 * aggregation will be announced.
f273fef1 7765 */
6aabb15d
RZ
7766 if (aggregate->summary_only
7767 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7768 if (aggr_suppress_path(aggregate, pi))
7769 match++;
d62a17ae 7770 }
c2ff8b3e 7771
365ab2e7
RZ
7772 /*
7773 * Suppress more specific routes that match the route
7774 * map results.
7775 *
7776 * MED matching:
7777 * Don't suppress routes if MED matching is enabled and
7778 * it mismatched otherwise we might end up with no
7779 * routes for this path.
7780 */
7781 if (aggregate->suppress_map_name
7782 && AGGREGATE_MED_VALID(aggregate)
7783 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7784 if (aggr_suppress_path(aggregate, pi))
7785 match++;
d62a17ae 7786 }
c2ff8b3e
DS
7787
7788 aggregate->count++;
7789
f273fef1
DS
7790 /*
7791 * If at least one route among routes that are
7792 * aggregated has ORIGIN with the value INCOMPLETE,
7793 * then the aggregated route MUST have the ORIGIN
7794 * attribute with the value INCOMPLETE. Otherwise, if
7795 * at least one route among routes that are aggregated
7796 * has ORIGIN with the value EGP, then the aggregated
7797 * route MUST have the ORIGIN attribute with the value
7798 * EGP.
7799 */
fc968841
NT
7800 switch (pi->attr->origin) {
7801 case BGP_ORIGIN_INCOMPLETE:
7802 aggregate->incomplete_origin_count++;
7803 break;
7804 case BGP_ORIGIN_EGP:
7805 aggregate->egp_origin_count++;
7806 break;
7807 default:
7808 /*Do nothing.
7809 */
7810 break;
7811 }
c2ff8b3e
DS
7812
7813 if (!aggregate->as_set)
7814 continue;
7815
f273fef1
DS
7816 /*
7817 * as-set aggregate route generate origin, as path,
7818 * and community aggregation.
7819 */
fc968841
NT
7820 /* Compute aggregate route's as-path.
7821 */
ef51a7d8 7822 bgp_compute_aggregate_aspath_hash(aggregate,
7823 pi->attr->aspath);
c2ff8b3e 7824
fc968841
NT
7825 /* Compute aggregate route's community.
7826 */
9a706b42 7827 if (bgp_attr_get_community(pi->attr))
21fec674 7828 bgp_compute_aggregate_community_hash(
9a706b42
DA
7829 aggregate,
7830 bgp_attr_get_community(pi->attr));
dd18c5a9 7831
fc968841
NT
7832 /* Compute aggregate route's extended community.
7833 */
b53e67a3 7834 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7835 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7836 aggregate,
7837 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7838
7839 /* Compute aggregate route's large community.
7840 */
1bcf3a96 7841 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7842 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7843 aggregate,
7844 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7845 }
c2ff8b3e 7846 if (match)
9bcb3eef 7847 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7848 }
21fec674 7849 if (aggregate->as_set) {
ef51a7d8 7850 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7851 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7852 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7853 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7854 }
7855
f1eb1f05 7856
9bcb3eef 7857 bgp_dest_unlock_node(top);
718e3744 7858
718e3744 7859
fc968841
NT
7860 if (aggregate->incomplete_origin_count > 0)
7861 origin = BGP_ORIGIN_INCOMPLETE;
7862 else if (aggregate->egp_origin_count > 0)
7863 origin = BGP_ORIGIN_EGP;
d62a17ae 7864
229757f1
DA
7865 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7866 origin = aggregate->origin;
7867
fc968841
NT
7868 if (aggregate->as_set) {
7869 if (aggregate->aspath)
7870 /* Retrieve aggregate route's as-path.
7871 */
7872 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7873
fc968841
NT
7874 if (aggregate->community)
7875 /* Retrieve aggregate route's community.
7876 */
7877 community = community_dup(aggregate->community);
3da2cc32 7878
fc968841
NT
7879 if (aggregate->ecommunity)
7880 /* Retrieve aggregate route's ecommunity.
7881 */
7882 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7883
fc968841
NT
7884 if (aggregate->lcommunity)
7885 /* Retrieve aggregate route's lcommunity.
7886 */
7887 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7888 }
718e3744 7889
c701010e 7890 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7891 ecommunity, lcommunity, atomic_aggregate,
7892 aggregate);
718e3744 7893}
7894
5f040085
DS
7895void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7896 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7897{
7898 struct bgp_table *table;
9bcb3eef
DS
7899 struct bgp_dest *top;
7900 struct bgp_dest *dest;
40381db7 7901 struct bgp_path_info *pi;
3b7db173
DS
7902 unsigned long match;
7903
7904 table = bgp->rib[afi][safi];
7905
7906 /* If routes exists below this node, generate aggregate routes. */
7907 top = bgp_node_get(table, p);
9bcb3eef
DS
7908 for (dest = bgp_node_get(table, p); dest;
7909 dest = bgp_route_next_until(dest, top)) {
7910 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7911
9bcb3eef 7912 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7913 continue;
7914 match = 0;
7915
9bcb3eef 7916 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7917 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7918 continue;
7919
40381db7 7920 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7921 continue;
7922
92b175bd
RZ
7923 /*
7924 * This route is suppressed: attempt to unsuppress it.
7925 *
7926 * `aggr_unsuppress_path` will fail if this particular
7927 * aggregate route was not the suppressor.
7928 */
7929 if (pi->extra && pi->extra->aggr_suppressors &&
7930 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7931 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7932 match++;
3b7db173 7933 }
365ab2e7 7934
3b7db173 7935 aggregate->count--;
fc968841
NT
7936
7937 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7938 aggregate->incomplete_origin_count--;
7939 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7940 aggregate->egp_origin_count--;
7941
7942 if (aggregate->as_set) {
7943 /* Remove as-path from aggregate.
7944 */
ef51a7d8 7945 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7946 aggregate,
7947 pi->attr->aspath);
7948
9a706b42 7949 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7950 /* Remove community from aggregate.
7951 */
21fec674 7952 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7953 aggregate,
7954 bgp_attr_get_community(
7955 pi->attr));
fc968841 7956
b53e67a3 7957 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7958 /* Remove ecommunity from aggregate.
7959 */
4edd83f9 7960 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7961 aggregate,
7962 bgp_attr_get_ecommunity(
7963 pi->attr));
fc968841 7964
1bcf3a96 7965 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7966 /* Remove lcommunity from aggregate.
7967 */
f1eb1f05 7968 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7969 aggregate,
7970 bgp_attr_get_lcommunity(
7971 pi->attr));
fc968841 7972 }
3b7db173
DS
7973 }
7974
7975 /* If this node was suppressed, process the change. */
7976 if (match)
9bcb3eef 7977 bgp_process(bgp, dest, afi, safi);
3b7db173 7978 }
f1eb1f05 7979 if (aggregate->as_set) {
ef51a7d8 7980 aspath_free(aggregate->aspath);
7981 aggregate->aspath = NULL;
21fec674 7982 if (aggregate->community)
7983 community_free(&aggregate->community);
4edd83f9 7984 if (aggregate->ecommunity)
7985 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7986 if (aggregate->lcommunity)
7987 lcommunity_free(&aggregate->lcommunity);
7988 }
7989
9bcb3eef 7990 bgp_dest_unlock_node(top);
3b7db173 7991}
718e3744 7992
5f040085
DS
7993static void bgp_add_route_to_aggregate(struct bgp *bgp,
7994 const struct prefix *aggr_p,
fc968841
NT
7995 struct bgp_path_info *pinew, afi_t afi,
7996 safi_t safi,
7997 struct bgp_aggregate *aggregate)
7998{
7999 uint8_t origin;
8000 struct aspath *aspath = NULL;
8001 uint8_t atomic_aggregate = 0;
8002 struct community *community = NULL;
8003 struct ecommunity *ecommunity = NULL;
8004 struct lcommunity *lcommunity = NULL;
8005
a4559740 8006 /* If the bgp instance is being deleted or self peer is deleted
8007 * then do not create aggregate route
8008 */
8009 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8010 || (bgp->peer_self == NULL))
8011 return;
8012
fc968841
NT
8013 /* ORIGIN attribute: If at least one route among routes that are
8014 * aggregated has ORIGIN with the value INCOMPLETE, then the
8015 * aggregated route must have the ORIGIN attribute with the value
8016 * INCOMPLETE. Otherwise, if at least one route among routes that
8017 * are aggregated has ORIGIN with the value EGP, then the aggregated
8018 * route must have the origin attribute with the value EGP. In all
8019 * other case the value of the ORIGIN attribute of the aggregated
8020 * route is INTERNAL.
8021 */
8022 origin = BGP_ORIGIN_IGP;
8023
8024 aggregate->count++;
8025
6aabb15d
RZ
8026 /*
8027 * This must be called before `summary` check to avoid
8028 * "suppressing" twice.
8029 */
8030 if (aggregate->match_med)
8031 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8032 pinew);
6aabb15d
RZ
8033
8034 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8035 aggr_suppress_path(aggregate, pinew);
fc968841 8036
365ab2e7
RZ
8037 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8038 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8039 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8040
8041 switch (pinew->attr->origin) {
8042 case BGP_ORIGIN_INCOMPLETE:
8043 aggregate->incomplete_origin_count++;
8044 break;
8045 case BGP_ORIGIN_EGP:
8046 aggregate->egp_origin_count++;
8047 break;
8048 default:
8049 /* Do nothing.
8050 */
8051 break;
8052 }
8053
8054 if (aggregate->incomplete_origin_count > 0)
8055 origin = BGP_ORIGIN_INCOMPLETE;
8056 else if (aggregate->egp_origin_count > 0)
8057 origin = BGP_ORIGIN_EGP;
8058
229757f1
DA
8059 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8060 origin = aggregate->origin;
8061
fc968841
NT
8062 if (aggregate->as_set) {
8063 /* Compute aggregate route's as-path.
8064 */
8065 bgp_compute_aggregate_aspath(aggregate,
8066 pinew->attr->aspath);
8067
8068 /* Compute aggregate route's community.
8069 */
9a706b42 8070 if (bgp_attr_get_community(pinew->attr))
fc968841 8071 bgp_compute_aggregate_community(
9a706b42 8072 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8073
8074 /* Compute aggregate route's extended community.
8075 */
b53e67a3 8076 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8077 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8078 aggregate,
8079 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8080
8081 /* Compute aggregate route's large community.
8082 */
1bcf3a96 8083 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8084 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8085 aggregate,
8086 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8087
8088 /* Retrieve aggregate route's as-path.
8089 */
8090 if (aggregate->aspath)
8091 aspath = aspath_dup(aggregate->aspath);
8092
8093 /* Retrieve aggregate route's community.
8094 */
8095 if (aggregate->community)
8096 community = community_dup(aggregate->community);
8097
8098 /* Retrieve aggregate route's ecommunity.
8099 */
8100 if (aggregate->ecommunity)
8101 ecommunity = ecommunity_dup(aggregate->ecommunity);
8102
8103 /* Retrieve aggregate route's lcommunity.
8104 */
8105 if (aggregate->lcommunity)
8106 lcommunity = lcommunity_dup(aggregate->lcommunity);
8107 }
8108
8109 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8110 aspath, community, ecommunity,
8111 lcommunity, atomic_aggregate, aggregate);
8112}
8113
8114static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8115 safi_t safi,
8116 struct bgp_path_info *pi,
8117 struct bgp_aggregate *aggregate,
5f040085 8118 const struct prefix *aggr_p)
fc968841
NT
8119{
8120 uint8_t origin;
8121 struct aspath *aspath = NULL;
8122 uint8_t atomic_aggregate = 0;
8123 struct community *community = NULL;
8124 struct ecommunity *ecommunity = NULL;
8125 struct lcommunity *lcommunity = NULL;
8126 unsigned long match = 0;
8127
a4559740 8128 /* If the bgp instance is being deleted or self peer is deleted
8129 * then do not create aggregate route
8130 */
8131 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8132 || (bgp->peer_self == NULL))
8133 return;
8134
fc968841
NT
8135 if (BGP_PATH_HOLDDOWN(pi))
8136 return;
8137
8138 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8139 return;
8140
4056a5f6
RZ
8141 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8142 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8143 match++;
fc968841 8144
365ab2e7 8145 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8146 && aggr_suppress_map_test(bgp, aggregate, pi))
8147 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8148 match++;
fc968841 8149
6aabb15d 8150 /*
365ab2e7 8151 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8152 * "unsuppressing" twice.
8153 */
8154 if (aggregate->match_med)
f66624f5 8155 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8156
fc968841
NT
8157 if (aggregate->count > 0)
8158 aggregate->count--;
8159
8160 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8161 aggregate->incomplete_origin_count--;
8162 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8163 aggregate->egp_origin_count--;
8164
8165 if (aggregate->as_set) {
8166 /* Remove as-path from aggregate.
8167 */
8168 bgp_remove_aspath_from_aggregate(aggregate,
8169 pi->attr->aspath);
8170
9a706b42 8171 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8172 /* Remove community from aggregate.
8173 */
8174 bgp_remove_community_from_aggregate(
9a706b42 8175 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8176
b53e67a3 8177 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8178 /* Remove ecommunity from aggregate.
8179 */
8180 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8181 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8182
1bcf3a96 8183 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8184 /* Remove lcommunity from aggregate.
8185 */
8186 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8187 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8188 }
8189
8190 /* If this node was suppressed, process the change. */
8191 if (match)
8192 bgp_process(bgp, pi->net, afi, safi);
8193
8194 origin = BGP_ORIGIN_IGP;
8195 if (aggregate->incomplete_origin_count > 0)
8196 origin = BGP_ORIGIN_INCOMPLETE;
8197 else if (aggregate->egp_origin_count > 0)
8198 origin = BGP_ORIGIN_EGP;
8199
229757f1
DA
8200 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8201 origin = aggregate->origin;
8202
fc968841
NT
8203 if (aggregate->as_set) {
8204 /* Retrieve aggregate route's as-path.
8205 */
8206 if (aggregate->aspath)
8207 aspath = aspath_dup(aggregate->aspath);
8208
8209 /* Retrieve aggregate route's community.
8210 */
8211 if (aggregate->community)
8212 community = community_dup(aggregate->community);
8213
8214 /* Retrieve aggregate route's ecommunity.
8215 */
8216 if (aggregate->ecommunity)
8217 ecommunity = ecommunity_dup(aggregate->ecommunity);
8218
8219 /* Retrieve aggregate route's lcommunity.
8220 */
8221 if (aggregate->lcommunity)
8222 lcommunity = lcommunity_dup(aggregate->lcommunity);
8223 }
8224
8225 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8226 aspath, community, ecommunity,
8227 lcommunity, atomic_aggregate, aggregate);
8228}
8229
5a1ae2c2 8230void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8231 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8232{
9bcb3eef
DS
8233 struct bgp_dest *child;
8234 struct bgp_dest *dest;
d62a17ae 8235 struct bgp_aggregate *aggregate;
8236 struct bgp_table *table;
718e3744 8237
d62a17ae 8238 table = bgp->aggregate[afi][safi];
f018db83 8239
d62a17ae 8240 /* No aggregates configured. */
8241 if (bgp_table_top_nolock(table) == NULL)
8242 return;
f018db83 8243
d62a17ae 8244 if (p->prefixlen == 0)
8245 return;
718e3744 8246
40381db7 8247 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8248 return;
718e3744 8249
a77e2f4b
S
8250 /* If suppress fib is enabled and route not installed
8251 * in FIB, do not update the aggregate route
8252 */
8253 if (!bgp_check_advertise(bgp, pi->net))
8254 return;
8255
d62a17ae 8256 child = bgp_node_get(table, p);
718e3744 8257
d62a17ae 8258 /* Aggregate address configuration check. */
9bcb3eef
DS
8259 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8260 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8261
9bcb3eef
DS
8262 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8263 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8264 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8265 aggregate);
d62a17ae 8266 }
b1e62edd 8267 }
9bcb3eef 8268 bgp_dest_unlock_node(child);
718e3744 8269}
8270
5a1ae2c2 8271void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8272 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8273{
9bcb3eef
DS
8274 struct bgp_dest *child;
8275 struct bgp_dest *dest;
d62a17ae 8276 struct bgp_aggregate *aggregate;
8277 struct bgp_table *table;
718e3744 8278
d62a17ae 8279 table = bgp->aggregate[afi][safi];
718e3744 8280
d62a17ae 8281 /* No aggregates configured. */
8282 if (bgp_table_top_nolock(table) == NULL)
8283 return;
718e3744 8284
d62a17ae 8285 if (p->prefixlen == 0)
8286 return;
718e3744 8287
d62a17ae 8288 child = bgp_node_get(table, p);
718e3744 8289
d62a17ae 8290 /* Aggregate address configuration check. */
9bcb3eef
DS
8291 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8292 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8293
9bcb3eef
DS
8294 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8295 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8296 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8297 aggregate, dest_p);
d62a17ae 8298 }
b1e62edd 8299 }
9bcb3eef 8300 bgp_dest_unlock_node(child);
d62a17ae 8301}
718e3744 8302
718e3744 8303/* Aggregate route attribute. */
8304#define AGGREGATE_SUMMARY_ONLY 1
8305#define AGGREGATE_AS_SET 1
fb29348a 8306#define AGGREGATE_AS_UNSET 0
718e3744 8307
229757f1
DA
8308static const char *bgp_origin2str(uint8_t origin)
8309{
8310 switch (origin) {
8311 case BGP_ORIGIN_IGP:
8312 return "igp";
8313 case BGP_ORIGIN_EGP:
8314 return "egp";
8315 case BGP_ORIGIN_INCOMPLETE:
8316 return "incomplete";
8317 }
8318 return "n/a";
8319}
8320
fdeb5a81 8321static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8322{
8323 switch (v_state) {
fdeb5a81
DS
8324 case RPKI_NOT_BEING_USED:
8325 return "not used";
8326 case RPKI_VALID:
b5b99af8 8327 return "valid";
fdeb5a81 8328 case RPKI_NOTFOUND:
b5b99af8 8329 return "not found";
fdeb5a81 8330 case RPKI_INVALID:
b5b99af8 8331 return "invalid";
b5b99af8 8332 }
fdeb5a81
DS
8333
8334 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8335 return "ERROR";
8336}
8337
585f1adc
IR
8338static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8339 afi_t afi, safi_t safi)
718e3744 8340{
585f1adc
IR
8341 VTY_DECLVAR_CONTEXT(bgp, bgp);
8342 int ret;
8343 struct prefix p;
9bcb3eef 8344 struct bgp_dest *dest;
d62a17ae 8345 struct bgp_aggregate *aggregate;
718e3744 8346
585f1adc
IR
8347 /* Convert string to prefix structure. */
8348 ret = str2prefix(prefix_str, &p);
8349 if (!ret) {
8350 vty_out(vty, "Malformed prefix\n");
8351 return CMD_WARNING_CONFIG_FAILED;
8352 }
8353 apply_mask(&p);
a4559740 8354
d62a17ae 8355 /* Old configuration check. */
585f1adc 8356 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8357 if (!dest) {
585f1adc
IR
8358 vty_out(vty,
8359 "%% There is no aggregate-address configuration.\n");
8360 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8361 }
f6269b4f 8362
9bcb3eef 8363 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8364 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8365 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8366 NULL, NULL, 0, aggregate);
d62a17ae 8367
8368 /* Unlock aggregate address configuration. */
9bcb3eef 8369 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8370
8371 if (aggregate->community)
8372 community_free(&aggregate->community);
8373
8374 if (aggregate->community_hash) {
8375 /* Delete all communities in the hash.
8376 */
8377 hash_clean(aggregate->community_hash,
8378 bgp_aggr_community_remove);
8379 /* Free up the community_hash.
8380 */
8381 hash_free(aggregate->community_hash);
8382 }
8383
8384 if (aggregate->ecommunity)
8385 ecommunity_free(&aggregate->ecommunity);
8386
8387 if (aggregate->ecommunity_hash) {
8388 /* Delete all ecommunities in the hash.
8389 */
8390 hash_clean(aggregate->ecommunity_hash,
8391 bgp_aggr_ecommunity_remove);
8392 /* Free up the ecommunity_hash.
8393 */
8394 hash_free(aggregate->ecommunity_hash);
8395 }
8396
8397 if (aggregate->lcommunity)
8398 lcommunity_free(&aggregate->lcommunity);
8399
8400 if (aggregate->lcommunity_hash) {
8401 /* Delete all lcommunities in the hash.
8402 */
8403 hash_clean(aggregate->lcommunity_hash,
8404 bgp_aggr_lcommunity_remove);
8405 /* Free up the lcommunity_hash.
8406 */
8407 hash_free(aggregate->lcommunity_hash);
8408 }
8409
8410 if (aggregate->aspath)
8411 aspath_free(aggregate->aspath);
8412
8413 if (aggregate->aspath_hash) {
8414 /* Delete all as-paths in the hash.
8415 */
8416 hash_clean(aggregate->aspath_hash,
8417 bgp_aggr_aspath_remove);
8418 /* Free up the aspath_hash.
8419 */
8420 hash_free(aggregate->aspath_hash);
8421 }
8422
d62a17ae 8423 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8424 bgp_dest_unlock_node(dest);
8425 bgp_dest_unlock_node(dest);
d62a17ae 8426
585f1adc 8427 return CMD_SUCCESS;
d62a17ae 8428}
8429
585f1adc
IR
8430static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8431 safi_t safi, const char *rmap,
8432 uint8_t summary_only, uint8_t as_set,
8433 uint8_t origin, bool match_med,
8434 const char *suppress_map)
d62a17ae 8435{
585f1adc 8436 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8437 int ret;
585f1adc 8438 struct prefix p;
9bcb3eef 8439 struct bgp_dest *dest;
d62a17ae 8440 struct bgp_aggregate *aggregate;
fb29348a 8441 uint8_t as_set_new = as_set;
d62a17ae 8442
365ab2e7 8443 if (suppress_map && summary_only) {
585f1adc 8444 vty_out(vty,
365ab2e7 8445 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8446 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8447 }
8448
585f1adc
IR
8449 /* Convert string to prefix structure. */
8450 ret = str2prefix(prefix_str, &p);
8451 if (!ret) {
8452 vty_out(vty, "Malformed prefix\n");
8453 return CMD_WARNING_CONFIG_FAILED;
8454 }
8455 apply_mask(&p);
d62a17ae 8456
585f1adc
IR
8457 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8458 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8459 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8460 prefix_str);
8461 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8462 }
8463
d62a17ae 8464 /* Old configuration check. */
585f1adc 8465 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8466 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8467
20894f50 8468 if (aggregate) {
585f1adc 8469 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8470 /* try to remove the old entry */
585f1adc 8471 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8472 if (ret) {
585f1adc 8473 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8474 bgp_dest_unlock_node(dest);
585f1adc 8475 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8476 }
8477 }
718e3744 8478
d62a17ae 8479 /* Make aggregate address structure. */
8480 aggregate = bgp_aggregate_new();
8481 aggregate->summary_only = summary_only;
6aabb15d 8482 aggregate->match_med = match_med;
fb29348a
DA
8483
8484 /* Network operators MUST NOT locally generate any new
8485 * announcements containing AS_SET or AS_CONFED_SET. If they have
8486 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8487 * SHOULD withdraw those routes and re-announce routes for the
8488 * aggregate or component prefixes (i.e., the more-specific routes
8489 * subsumed by the previously aggregated route) without AS_SET
8490 * or AS_CONFED_SET in the updates.
8491 */
7f972cd8 8492 if (bgp->reject_as_sets) {
fb29348a
DA
8493 if (as_set == AGGREGATE_AS_SET) {
8494 as_set_new = AGGREGATE_AS_UNSET;
8495 zlog_warn(
63efca0e 8496 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8497 __func__);
585f1adc 8498 vty_out(vty,
fb29348a
DA
8499 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8500 }
8501 }
8502
8503 aggregate->as_set = as_set_new;
d62a17ae 8504 aggregate->safi = safi;
229757f1
DA
8505 /* Override ORIGIN attribute if defined.
8506 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8507 * to IGP which is not what rfc4271 says.
8508 * This enables the same behavior, optionally.
8509 */
8510 aggregate->origin = origin;
20894f50
DA
8511
8512 if (rmap) {
8513 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8514 route_map_counter_decrement(aggregate->rmap.map);
8515 aggregate->rmap.name =
8516 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8517 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8518 route_map_counter_increment(aggregate->rmap.map);
8519 }
365ab2e7
RZ
8520
8521 if (suppress_map) {
8522 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8523 route_map_counter_decrement(aggregate->suppress_map);
8524
8525 aggregate->suppress_map_name =
8526 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8527 aggregate->suppress_map =
8528 route_map_lookup_by_name(aggregate->suppress_map_name);
8529 route_map_counter_increment(aggregate->suppress_map);
8530 }
8531
9bcb3eef 8532 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8533
d62a17ae 8534 /* Aggregate address insert into BGP routing table. */
585f1adc 8535 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8536
585f1adc 8537 return CMD_SUCCESS;
718e3744 8538}
8539
585f1adc
IR
8540DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8541 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8542 "as-set$as_set_s"
8543 "|summary-only$summary_only"
cacba915 8544 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8545 "|origin <egp|igp|incomplete>$origin_s"
8546 "|matching-MED-only$match_med"
cacba915 8547 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8548 "}]",
8549 NO_STR
8550 "Configure BGP aggregate entries\n"
764402fe
DA
8551 "Aggregate prefix\n"
8552 "Aggregate address\n"
8553 "Aggregate mask\n"
585f1adc
IR
8554 "Generate AS set path information\n"
8555 "Filter more specific routes from updates\n"
8556 "Apply route map to aggregate network\n"
8557 "Route map name\n"
8558 "BGP origin code\n"
8559 "Remote EGP\n"
8560 "Local IGP\n"
8561 "Unknown heritage\n"
8562 "Only aggregate routes with matching MED\n"
8563 "Suppress the selected more specific routes\n"
8564 "Route map with the route selectors\n")
8565{
8566 const char *prefix_s = NULL;
554b3b10 8567 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8568 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8569 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8570 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8571
554b3b10 8572 if (addr_str) {
7533cad7
QY
8573 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8574 sizeof(prefix_buf))
554b3b10
RZ
8575 == 0) {
8576 vty_out(vty, "%% Inconsistent address and mask\n");
8577 return CMD_WARNING_CONFIG_FAILED;
8578 }
585f1adc
IR
8579 prefix_s = prefix_buf;
8580 } else
8581 prefix_s = prefix_str;
37a87b8f 8582
585f1adc
IR
8583 if (origin_s) {
8584 if (strcmp(origin_s, "egp") == 0)
8585 origin = BGP_ORIGIN_EGP;
8586 else if (strcmp(origin_s, "igp") == 0)
8587 origin = BGP_ORIGIN_IGP;
8588 else if (strcmp(origin_s, "incomplete") == 0)
8589 origin = BGP_ORIGIN_INCOMPLETE;
8590 }
90e21f35 8591
585f1adc
IR
8592 if (as_set_s)
8593 as_set = AGGREGATE_AS_SET;
554b3b10 8594
585f1adc 8595 /* Handle configuration removal, otherwise installation. */
554b3b10 8596 if (no)
585f1adc
IR
8597 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8598
8599 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8600 summary_only != NULL, as_set, origin,
8601 match_med != NULL, suppress_map);
8602}
8603
8604DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8605 "[no] aggregate-address X:X::X:X/M$prefix [{"
8606 "as-set$as_set_s"
8607 "|summary-only$summary_only"
cacba915 8608 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8609 "|origin <egp|igp|incomplete>$origin_s"
8610 "|matching-MED-only$match_med"
cacba915 8611 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8612 "}]",
8613 NO_STR
8614 "Configure BGP aggregate entries\n"
8615 "Aggregate prefix\n"
8616 "Generate AS set path information\n"
8617 "Filter more specific routes from updates\n"
8618 "Apply route map to aggregate network\n"
8619 "Route map name\n"
8620 "BGP origin code\n"
8621 "Remote EGP\n"
8622 "Local IGP\n"
8623 "Unknown heritage\n"
8624 "Only aggregate routes with matching MED\n"
8625 "Suppress the selected more specific routes\n"
8626 "Route map with the route selectors\n")
8627{
8628 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8629 int as_set = AGGREGATE_AS_UNSET;
8630
8631 if (origin_s) {
8632 if (strcmp(origin_s, "egp") == 0)
8633 origin = BGP_ORIGIN_EGP;
8634 else if (strcmp(origin_s, "igp") == 0)
8635 origin = BGP_ORIGIN_IGP;
8636 else if (strcmp(origin_s, "incomplete") == 0)
8637 origin = BGP_ORIGIN_INCOMPLETE;
8638 }
8639
8640 if (as_set_s)
8641 as_set = AGGREGATE_AS_SET;
8642
8643 /* Handle configuration removal, otherwise installation. */
554b3b10 8644 if (no)
585f1adc
IR
8645 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8646 SAFI_UNICAST);
554b3b10 8647
585f1adc
IR
8648 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8649 rmap_name, summary_only != NULL, as_set,
8650 origin, match_med != NULL, suppress_map);
718e3744 8651}
8652
718e3744 8653/* Redistribute route treatment. */
d62a17ae 8654void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8655 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8656 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8657 enum blackhole_type bhtype, uint32_t metric,
8658 uint8_t type, unsigned short instance,
8659 route_tag_t tag)
d62a17ae 8660{
4b7e6066 8661 struct bgp_path_info *new;
40381db7
DS
8662 struct bgp_path_info *bpi;
8663 struct bgp_path_info rmap_path;
9bcb3eef 8664 struct bgp_dest *bn;
d62a17ae 8665 struct attr attr;
8666 struct attr *new_attr;
8667 afi_t afi;
b68885f9 8668 route_map_result_t ret;
d62a17ae 8669 struct bgp_redist *red;
8670
8671 /* Make default attribute. */
0f05ea43 8672 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8673 /*
8674 * This must not be NULL to satisfy Coverity SA
8675 */
8676 assert(attr.aspath);
9de1f7ff 8677
a4d82a8a 8678 switch (nhtype) {
9de1f7ff 8679 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8680 switch (p->family) {
8681 case AF_INET:
8682 attr.nexthop.s_addr = INADDR_ANY;
8683 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8684 break;
8685 case AF_INET6:
8686 memset(&attr.mp_nexthop_global, 0,
8687 sizeof(attr.mp_nexthop_global));
8688 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8689 break;
8690 }
9de1f7ff
DS
8691 break;
8692 case NEXTHOP_TYPE_IPV4:
8693 case NEXTHOP_TYPE_IPV4_IFINDEX:
8694 attr.nexthop = nexthop->ipv4;
7226bc40 8695 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8696 break;
8697 case NEXTHOP_TYPE_IPV6:
8698 case NEXTHOP_TYPE_IPV6_IFINDEX:
8699 attr.mp_nexthop_global = nexthop->ipv6;
8700 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8701 break;
8702 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8703 switch (p->family) {
8704 case AF_INET:
9de1f7ff 8705 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8706 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8707 break;
8708 case AF_INET6:
9de1f7ff
DS
8709 memset(&attr.mp_nexthop_global, 0,
8710 sizeof(attr.mp_nexthop_global));
74489921 8711 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8712 break;
74489921 8713 }
0789eb69 8714 attr.bh_type = bhtype;
9de1f7ff 8715 break;
d62a17ae 8716 }
0789eb69 8717 attr.nh_type = nhtype;
74489921 8718 attr.nh_ifindex = ifindex;
f04a80a5 8719
d62a17ae 8720 attr.med = metric;
957f74c3 8721 attr.distance = distance;
d62a17ae 8722 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8723 attr.tag = tag;
718e3744 8724
97a52c82
DA
8725 if (metric)
8726 bgp_attr_set_aigp_metric(&attr, metric);
8727
d62a17ae 8728 afi = family2afi(p->family);
6aeb9e78 8729
d62a17ae 8730 red = bgp_redist_lookup(bgp, afi, type, instance);
8731 if (red) {
8732 struct attr attr_new;
718e3744 8733
d62a17ae 8734 /* Copy attribute for modification. */
6f4f49b2 8735 attr_new = attr;
718e3744 8736
97a52c82 8737 if (red->redist_metric_flag) {
d62a17ae 8738 attr_new.med = red->redist_metric;
97a52c82
DA
8739 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8740 }
718e3744 8741
d62a17ae 8742 /* Apply route-map. */
8743 if (red->rmap.name) {
6006b807 8744 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8745 rmap_path.peer = bgp->peer_self;
8746 rmap_path.attr = &attr_new;
718e3744 8747
d62a17ae 8748 SET_FLAG(bgp->peer_self->rmap_type,
8749 PEER_RMAP_TYPE_REDISTRIBUTE);
8750
1782514f 8751 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8752
8753 bgp->peer_self->rmap_type = 0;
8754
8755 if (ret == RMAP_DENYMATCH) {
8756 /* Free uninterned attribute. */
8757 bgp_attr_flush(&attr_new);
8758
8759 /* Unintern original. */
8760 aspath_unintern(&attr.aspath);
8761 bgp_redistribute_delete(bgp, p, type, instance);
8762 return;
8763 }
8764 }
8765
637e5ba4 8766 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8767 bgp_attr_add_gshut_community(&attr_new);
8768
d62a17ae 8769 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8770 SAFI_UNICAST, p, NULL);
8771
8772 new_attr = bgp_attr_intern(&attr_new);
8773
9bcb3eef 8774 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8775 if (bpi->peer == bgp->peer_self
8776 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8777 break;
8778
40381db7 8779 if (bpi) {
d62a17ae 8780 /* Ensure the (source route) type is updated. */
40381db7
DS
8781 bpi->type = type;
8782 if (attrhash_cmp(bpi->attr, new_attr)
8783 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8784 bgp_attr_unintern(&new_attr);
8785 aspath_unintern(&attr.aspath);
9bcb3eef 8786 bgp_dest_unlock_node(bn);
d62a17ae 8787 return;
8788 } else {
8789 /* The attribute is changed. */
40381db7 8790 bgp_path_info_set_flag(bn, bpi,
18ee8310 8791 BGP_PATH_ATTR_CHANGED);
d62a17ae 8792
8793 /* Rewrite BGP route information. */
40381db7
DS
8794 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8795 bgp_path_info_restore(bn, bpi);
d62a17ae 8796 else
40381db7
DS
8797 bgp_aggregate_decrement(
8798 bgp, p, bpi, afi, SAFI_UNICAST);
8799 bgp_attr_unintern(&bpi->attr);
8800 bpi->attr = new_attr;
083ec940 8801 bpi->uptime = monotime(NULL);
d62a17ae 8802
8803 /* Process change. */
40381db7 8804 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8805 SAFI_UNICAST);
8806 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8807 bgp_dest_unlock_node(bn);
d62a17ae 8808 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8809
8810 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8811 || (bgp->inst_type
8812 == BGP_INSTANCE_TYPE_DEFAULT)) {
8813
8814 vpn_leak_from_vrf_update(
40381db7 8815 bgp_get_default(), bgp, bpi);
ddb5b488 8816 }
d62a17ae 8817 return;
8818 }
8819 }
8820
8821 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8822 bgp->peer_self, new_attr, bn);
1defdda8 8823 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8824
8825 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8826 bgp_path_info_add(bn, new);
9bcb3eef 8827 bgp_dest_unlock_node(bn);
be785e35 8828 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8829 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8830
8831 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8832 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8833
8834 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8835 }
d62a17ae 8836 }
8837
8838 /* Unintern original. */
8839 aspath_unintern(&attr.aspath);
718e3744 8840}
8841
d7c0a89a
QY
8842void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8843 unsigned short instance)
718e3744 8844{
d62a17ae 8845 afi_t afi;
9bcb3eef 8846 struct bgp_dest *dest;
40381db7 8847 struct bgp_path_info *pi;
d62a17ae 8848 struct bgp_redist *red;
718e3744 8849
d62a17ae 8850 afi = family2afi(p->family);
718e3744 8851
d62a17ae 8852 red = bgp_redist_lookup(bgp, afi, type, instance);
8853 if (red) {
9bcb3eef
DS
8854 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8855 SAFI_UNICAST, p, NULL);
d62a17ae 8856
9bcb3eef 8857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8858 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8859 break;
8860
40381db7 8861 if (pi) {
ddb5b488
PZ
8862 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8863 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8864
8865 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8866 bgp, pi);
ddb5b488 8867 }
40381db7 8868 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8869 bgp_path_info_delete(dest, pi);
8870 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8871 }
9bcb3eef 8872 bgp_dest_unlock_node(dest);
d62a17ae 8873 }
8874}
8875
8876/* Withdraw specified route type's route. */
8877void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8878 unsigned short instance)
d62a17ae 8879{
9bcb3eef 8880 struct bgp_dest *dest;
40381db7 8881 struct bgp_path_info *pi;
d62a17ae 8882 struct bgp_table *table;
8883
8884 table = bgp->rib[afi][SAFI_UNICAST];
8885
9bcb3eef
DS
8886 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8887 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8888 if (pi->peer == bgp->peer_self && pi->type == type
8889 && pi->instance == instance)
d62a17ae 8890 break;
8891
40381db7 8892 if (pi) {
ddb5b488
PZ
8893 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8894 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8895
8896 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8897 bgp, pi);
ddb5b488 8898 }
9bcb3eef 8899 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8900 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8901 bgp_path_info_delete(dest, pi);
8902 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8903 }
718e3744 8904 }
718e3744 8905}
6b0655a2 8906
718e3744 8907/* Static function to display route. */
7d3cae70
DA
8908static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8909 struct vty *vty, json_object *json, bool wide)
718e3744 8910{
be054588 8911 int len = 0;
d62a17ae 8912 char buf[BUFSIZ];
718e3744 8913
d62a17ae 8914 if (p->family == AF_INET) {
c6462ff4 8915 if (!json) {
8228a9a7 8916 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8917 } else {
8918 json_object_string_add(json, "prefix",
8919 inet_ntop(p->family,
8920 &p->u.prefix, buf,
8921 BUFSIZ));
8922 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8923 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8924 json_object_int_add(json, "version", dest->version);
c6462ff4 8925 }
d62a17ae 8926 } else if (p->family == AF_ETHERNET) {
8228a9a7 8927 len = vty_out(vty, "%pFX", p);
b03b8898 8928 } else if (p->family == AF_EVPN) {
57f7feb6 8929 if (!json)
2dbe669b 8930 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8931 else
60466a63 8932 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8933 } else if (p->family == AF_FLOWSPEC) {
8934 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8935 json ?
8936 NLRI_STRING_FORMAT_JSON_SIMPLE :
8937 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8938 } else {
c6462ff4 8939 if (!json)
8228a9a7 8940 len = vty_out(vty, "%pFX", p);
50e05855
AD
8941 else {
8942 json_object_string_add(json, "prefix",
8943 inet_ntop(p->family,
8944 &p->u.prefix, buf,
8945 BUFSIZ));
8946 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8947 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8948 json_object_int_add(json, "version", dest->version);
37d4e0df 8949 }
9c92b5f7 8950 }
d62a17ae 8951
9c92b5f7 8952 if (!json) {
ae248832 8953 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8954 if (len < 1)
8955 vty_out(vty, "\n%*s", 20, " ");
8956 else
8957 vty_out(vty, "%*s", len, " ");
8958 }
718e3744 8959}
8960
d62a17ae 8961enum bgp_display_type {
8962 normal_list,
718e3744 8963};
8964
1d7260a1 8965const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8966{
8967 switch (reason) {
8968 case bgp_path_selection_none:
8969 return "Nothing to Select";
8970 case bgp_path_selection_first:
8971 return "First path received";
8972 case bgp_path_selection_evpn_sticky_mac:
8973 return "EVPN Sticky Mac";
8974 case bgp_path_selection_evpn_seq:
8975 return "EVPN sequence number";
8976 case bgp_path_selection_evpn_lower_ip:
8977 return "EVPN lower IP";
8978 case bgp_path_selection_evpn_local_path:
8979 return "EVPN local ES path";
8980 case bgp_path_selection_evpn_non_proxy:
8981 return "EVPN non proxy";
8982 case bgp_path_selection_weight:
8983 return "Weight";
8984 case bgp_path_selection_local_pref:
8985 return "Local Pref";
46dbf9d0
DA
8986 case bgp_path_selection_accept_own:
8987 return "Accept Own";
bbb46eb5
DA
8988 case bgp_path_selection_local_route:
8989 return "Local Route";
97a52c82
DA
8990 case bgp_path_selection_aigp:
8991 return "AIGP";
bbb46eb5
DA
8992 case bgp_path_selection_confed_as_path:
8993 return "Confederation based AS Path";
8994 case bgp_path_selection_as_path:
8995 return "AS Path";
8996 case bgp_path_selection_origin:
8997 return "Origin";
8998 case bgp_path_selection_med:
8999 return "MED";
9000 case bgp_path_selection_peer:
9001 return "Peer Type";
9002 case bgp_path_selection_confed:
9003 return "Confed Peer Type";
9004 case bgp_path_selection_igp_metric:
9005 return "IGP Metric";
9006 case bgp_path_selection_older:
9007 return "Older Path";
9008 case bgp_path_selection_router_id:
9009 return "Router ID";
9010 case bgp_path_selection_cluster_length:
bcab253c 9011 return "Cluster length";
bbb46eb5
DA
9012 case bgp_path_selection_stale:
9013 return "Path Staleness";
9014 case bgp_path_selection_local_configured:
9015 return "Locally configured route";
9016 case bgp_path_selection_neighbor_ip:
9017 return "Neighbor IP";
9018 case bgp_path_selection_default:
9019 return "Nothing left to compare";
9020 }
9021 return "Invalid (internal error)";
9022}
9023
18ee8310 9024/* Print the short form route status for a bgp_path_info */
4b7e6066 9025static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9026 struct bgp_path_info *path,
82c298be 9027 const struct prefix *p,
d62a17ae 9028 json_object *json_path)
718e3744 9029{
82c298be
DA
9030 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9031
d62a17ae 9032 if (json_path) {
b05a1c8b 9033
d62a17ae 9034 /* Route status display. */
9b6d8fcf 9035 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9036 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9037
9b6d8fcf 9038 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9039 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9040
4056a5f6 9041 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9042 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9043
9b6d8fcf
DS
9044 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9045 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9046 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9047
d62a17ae 9048 /* Selected */
9b6d8fcf 9049 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9050 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9051
9b6d8fcf 9052 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9053 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9054
bbb46eb5 9055 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9056 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9057 json_object_string_add(json_path, "selectionReason",
9058 bgp_path_selection_reason2str(
9059 path->net->reason));
9060 }
b05a1c8b 9061
9b6d8fcf 9062 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9063 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9064
d62a17ae 9065 /* Internal route. */
9b6d8fcf
DS
9066 if ((path->peer->as)
9067 && (path->peer->as == path->peer->local_as))
d62a17ae 9068 json_object_string_add(json_path, "pathFrom",
9069 "internal");
9070 else
9071 json_object_string_add(json_path, "pathFrom",
9072 "external");
b05a1c8b 9073
d62a17ae 9074 return;
9075 }
b05a1c8b 9076
82c298be
DA
9077 /* RPKI validation state */
9078 rpki_state =
9079 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9080
9081 if (rpki_state == RPKI_VALID)
9082 vty_out(vty, "V");
9083 else if (rpki_state == RPKI_INVALID)
9084 vty_out(vty, "I");
9085 else if (rpki_state == RPKI_NOTFOUND)
9086 vty_out(vty, "N");
eaeba5e8
WM
9087 else
9088 vty_out(vty, " ");
82c298be 9089
d62a17ae 9090 /* Route status display. */
9b6d8fcf 9091 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9092 vty_out(vty, "R");
9b6d8fcf 9093 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9094 vty_out(vty, "S");
4056a5f6 9095 else if (bgp_path_suppressed(path))
d62a17ae 9096 vty_out(vty, "s");
9b6d8fcf
DS
9097 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9098 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9099 vty_out(vty, "*");
9100 else
9101 vty_out(vty, " ");
9102
9103 /* Selected */
9b6d8fcf 9104 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9105 vty_out(vty, "h");
9b6d8fcf 9106 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9107 vty_out(vty, "d");
9b6d8fcf 9108 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9109 vty_out(vty, ">");
9b6d8fcf 9110 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9111 vty_out(vty, "=");
9112 else
9113 vty_out(vty, " ");
718e3744 9114
d62a17ae 9115 /* Internal route. */
9b6d8fcf
DS
9116 if (path->peer && (path->peer->as)
9117 && (path->peer->as == path->peer->local_as))
d62a17ae 9118 vty_out(vty, "i");
9119 else
9120 vty_out(vty, " ");
b40d939b 9121}
9122
2ba93fd6
DA
9123static char *bgp_nexthop_hostname(struct peer *peer,
9124 struct bgp_nexthop_cache *bnc)
25b5da8d 9125{
892fedb6 9126 if (peer->hostname
aef999a2 9127 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9128 return peer->hostname;
9129 return NULL;
9130}
9131
b40d939b 9132/* called from terminal list command */
bd494ec5 9133void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9134 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9135 json_object *json_paths, bool wide)
d62a17ae 9136{
aef999a2 9137 int len;
515c2602 9138 struct attr *attr = path->attr;
d62a17ae 9139 json_object *json_path = NULL;
9140 json_object *json_nexthops = NULL;
9141 json_object *json_nexthop_global = NULL;
9142 json_object *json_nexthop_ll = NULL;
6f214dd3 9143 json_object *json_ext_community = NULL;
9df8b37c 9144 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9145 bool nexthop_self =
9b6d8fcf 9146 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9147 bool nexthop_othervrf = false;
43089216 9148 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9149 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9150 char *nexthop_hostname =
9151 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9152 char esi_buf[ESI_STR_LEN];
d62a17ae 9153
9154 if (json_paths)
9155 json_path = json_object_new_object();
9156
9157 /* short status lead text */
82c298be 9158 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9159
9160 if (!json_paths) {
9161 /* print prefix and mask */
9162 if (!display)
7d3cae70 9163 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9164 else
ae248832 9165 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9166 } else {
7d3cae70 9167 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9168 }
47fc97cc 9169
9df8b37c
PZ
9170 /*
9171 * If vrf id of nexthop is different from that of prefix,
9172 * set up printable string to append
9173 */
9b6d8fcf 9174 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9175 const char *self = "";
9176
9177 if (nexthop_self)
9178 self = "<";
9179
9180 nexthop_othervrf = true;
9b6d8fcf 9181 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9182
9b6d8fcf 9183 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9184 snprintf(vrf_id_str, sizeof(vrf_id_str),
9185 "@%s%s", VRFID_NONE_STR, self);
9186 else
9187 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9188 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9189
9b6d8fcf
DS
9190 if (path->extra->bgp_orig->inst_type
9191 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9192
9b6d8fcf 9193 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9194 } else {
9195 const char *self = "";
9196
9197 if (nexthop_self)
9198 self = "<";
9199
9200 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9201 }
9202
445c2480
DS
9203 /*
9204 * For ENCAP and EVPN routes, nexthop address family is not
9205 * neccessarily the same as the prefix address family.
9206 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9207 * EVPN routes are also exchanged with a MP nexthop. Currently,
9208 * this
9209 * is only IPv4, the value will be present in either
9210 * attr->nexthop or
9211 * attr->mp_nexthop_global_in
9212 */
9213 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9214 char buf[BUFSIZ];
9215 char nexthop[128];
9216 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9217
9218 switch (af) {
9219 case AF_INET:
772270f3
QY
9220 snprintf(nexthop, sizeof(nexthop), "%s",
9221 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
9222 BUFSIZ));
445c2480
DS
9223 break;
9224 case AF_INET6:
772270f3
QY
9225 snprintf(nexthop, sizeof(nexthop), "%s",
9226 inet_ntop(af, &attr->mp_nexthop_global, buf,
9227 BUFSIZ));
445c2480
DS
9228 break;
9229 default:
772270f3 9230 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9231 break;
d62a17ae 9232 }
d62a17ae 9233
445c2480
DS
9234 if (json_paths) {
9235 json_nexthop_global = json_object_new_object();
9236
515c2602
DA
9237 json_object_string_add(json_nexthop_global, "ip",
9238 nexthop);
9239
939a97f4 9240 if (path->peer->hostname)
515c2602
DA
9241 json_object_string_add(json_nexthop_global,
9242 "hostname",
939a97f4 9243 path->peer->hostname);
515c2602
DA
9244
9245 json_object_string_add(json_nexthop_global, "afi",
9246 (af == AF_INET) ? "ipv4"
9247 : "ipv6");
445c2480
DS
9248 json_object_boolean_true_add(json_nexthop_global,
9249 "used");
aef999a2
DA
9250 } else {
9251 if (nexthop_hostname)
9252 len = vty_out(vty, "%s(%s)%s", nexthop,
9253 nexthop_hostname, vrf_id_str);
9254 else
9255 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9256
ae248832 9257 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9258 if (len < 1)
9259 vty_out(vty, "\n%*s", 36, " ");
9260 else
9261 vty_out(vty, "%*s", len, " ");
9262 }
445c2480
DS
9263 } else if (safi == SAFI_EVPN) {
9264 if (json_paths) {
9265 json_nexthop_global = json_object_new_object();
9266
c949c771 9267 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9268 "%pI4",
9269 &attr->mp_nexthop_global_in);
515c2602 9270
939a97f4 9271 if (path->peer->hostname)
515c2602
DA
9272 json_object_string_add(json_nexthop_global,
9273 "hostname",
939a97f4 9274 path->peer->hostname);
515c2602 9275
a4d82a8a
PZ
9276 json_object_string_add(json_nexthop_global, "afi",
9277 "ipv4");
445c2480
DS
9278 json_object_boolean_true_add(json_nexthop_global,
9279 "used");
aef999a2
DA
9280 } else {
9281 if (nexthop_hostname)
7226bc40
TA
9282 len = vty_out(vty, "%pI4(%s)%s",
9283 &attr->mp_nexthop_global_in,
aef999a2
DA
9284 nexthop_hostname, vrf_id_str);
9285 else
7226bc40
TA
9286 len = vty_out(vty, "%pI4%s",
9287 &attr->mp_nexthop_global_in,
aef999a2
DA
9288 vrf_id_str);
9289
ae248832 9290 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9291 if (len < 1)
9292 vty_out(vty, "\n%*s", 36, " ");
9293 else
9294 vty_out(vty, "%*s", len, " ");
9295 }
d33fc23b 9296 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9297 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9298 if (json_paths) {
9299 json_nexthop_global = json_object_new_object();
515c2602 9300
026b914a
PG
9301 json_object_string_add(json_nexthop_global,
9302 "afi", "ipv4");
c949c771
DA
9303 json_object_string_addf(json_nexthop_global,
9304 "ip", "%pI4",
9305 &attr->nexthop);
515c2602 9306
939a97f4 9307 if (path->peer->hostname)
515c2602
DA
9308 json_object_string_add(
9309 json_nexthop_global, "hostname",
939a97f4 9310 path->peer->hostname);
515c2602 9311
50e05855
AD
9312 json_object_boolean_true_add(
9313 json_nexthop_global,
026b914a
PG
9314 "used");
9315 } else {
aef999a2
DA
9316 if (nexthop_hostname)
9317 len = vty_out(vty, "%pI4(%s)%s",
9318 &attr->nexthop,
9319 nexthop_hostname,
9320 vrf_id_str);
9321 else
9322 len = vty_out(vty, "%pI4%s",
9323 &attr->nexthop,
9324 vrf_id_str);
9325
ae248832 9326 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9327 if (len < 1)
9328 vty_out(vty, "\n%*s", 36, " ");
9329 else
9330 vty_out(vty, "%*s", len, " ");
026b914a
PG
9331 }
9332 }
7226bc40 9333 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9334 if (json_paths) {
9335 json_nexthop_global = json_object_new_object();
d62a17ae 9336
c949c771
DA
9337 json_object_string_addf(json_nexthop_global, "ip",
9338 "%pI4", &attr->nexthop);
515c2602 9339
939a97f4 9340 if (path->peer->hostname)
515c2602
DA
9341 json_object_string_add(json_nexthop_global,
9342 "hostname",
939a97f4 9343 path->peer->hostname);
445c2480 9344
a4d82a8a
PZ
9345 json_object_string_add(json_nexthop_global, "afi",
9346 "ipv4");
445c2480
DS
9347 json_object_boolean_true_add(json_nexthop_global,
9348 "used");
9349 } else {
aef999a2
DA
9350 if (nexthop_hostname)
9351 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9352 nexthop_hostname, vrf_id_str);
9353 else
9354 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9355 vrf_id_str);
9df8b37c 9356
ae248832 9357 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9358 if (len < 1)
9359 vty_out(vty, "\n%*s", 36, " ");
9360 else
9361 vty_out(vty, "%*s", len, " ");
d62a17ae 9362 }
445c2480 9363 }
b05a1c8b 9364
445c2480 9365 /* IPv6 Next Hop */
7226bc40 9366 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9367 if (json_paths) {
9368 json_nexthop_global = json_object_new_object();
c949c771
DA
9369 json_object_string_addf(json_nexthop_global, "ip",
9370 "%pI6",
9371 &attr->mp_nexthop_global);
515c2602 9372
939a97f4 9373 if (path->peer->hostname)
515c2602
DA
9374 json_object_string_add(json_nexthop_global,
9375 "hostname",
939a97f4 9376 path->peer->hostname);
515c2602 9377
a4d82a8a
PZ
9378 json_object_string_add(json_nexthop_global, "afi",
9379 "ipv6");
9380 json_object_string_add(json_nexthop_global, "scope",
9381 "global");
445c2480
DS
9382
9383 /* We display both LL & GL if both have been
9384 * received */
0606039c
DA
9385 if ((attr->mp_nexthop_len
9386 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9387 || (path->peer->conf_if)) {
a4d82a8a 9388 json_nexthop_ll = json_object_new_object();
c949c771
DA
9389 json_object_string_addf(
9390 json_nexthop_ll, "ip", "%pI6",
9391 &attr->mp_nexthop_local);
515c2602 9392
939a97f4 9393 if (path->peer->hostname)
515c2602
DA
9394 json_object_string_add(
9395 json_nexthop_ll, "hostname",
939a97f4 9396 path->peer->hostname);
515c2602 9397
a4d82a8a
PZ
9398 json_object_string_add(json_nexthop_ll, "afi",
9399 "ipv6");
9400 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9401 "link-local");
d62a17ae 9402
a4d82a8a
PZ
9403 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9404 &attr->mp_nexthop_local)
445c2480
DS
9405 != 0)
9406 && !attr->mp_nexthop_prefer_global)
d62a17ae 9407 json_object_boolean_true_add(
a4d82a8a 9408 json_nexthop_ll, "used");
445c2480
DS
9409 else
9410 json_object_boolean_true_add(
a4d82a8a 9411 json_nexthop_global, "used");
445c2480
DS
9412 } else
9413 json_object_boolean_true_add(
9414 json_nexthop_global, "used");
9415 } else {
9416 /* Display LL if LL/Global both in table unless
9417 * prefer-global is set */
0606039c
DA
9418 if (((attr->mp_nexthop_len
9419 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9420 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9421 || (path->peer->conf_if)) {
9422 if (path->peer->conf_if) {
a4d82a8a 9423 len = vty_out(vty, "%s",
9b6d8fcf 9424 path->peer->conf_if);
ae248832
MK
9425 /* len of IPv6 addr + max len of def
9426 * ifname */
9427 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9428
9429 if (len < 1)
a4d82a8a 9430 vty_out(vty, "\n%*s", 36, " ");
445c2480 9431 else
a4d82a8a 9432 vty_out(vty, "%*s", len, " ");
d62a17ae 9433 } else {
aef999a2
DA
9434 if (nexthop_hostname)
9435 len = vty_out(
9436 vty, "%pI6(%s)%s",
9437 &attr->mp_nexthop_local,
9438 nexthop_hostname,
9439 vrf_id_str);
9440 else
9441 len = vty_out(
9442 vty, "%pI6%s",
9443 &attr->mp_nexthop_local,
9444 vrf_id_str);
9445
ae248832 9446 len = wide ? (41 - len) : (16 - len);
d62a17ae 9447
9448 if (len < 1)
a4d82a8a 9449 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9450 else
a4d82a8a 9451 vty_out(vty, "%*s", len, " ");
d62a17ae 9452 }
445c2480 9453 } else {
aef999a2
DA
9454 if (nexthop_hostname)
9455 len = vty_out(vty, "%pI6(%s)%s",
9456 &attr->mp_nexthop_global,
9457 nexthop_hostname,
9458 vrf_id_str);
9459 else
9460 len = vty_out(vty, "%pI6%s",
9461 &attr->mp_nexthop_global,
9462 vrf_id_str);
9463
ae248832 9464 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9465
9466 if (len < 1)
9467 vty_out(vty, "\n%*s", 36, " ");
9468 else
9469 vty_out(vty, "%*s", len, " ");
d62a17ae 9470 }
9471 }
445c2480 9472 }
718e3744 9473
445c2480
DS
9474 /* MED/Metric */
9475 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9476 if (json_paths)
50e05855 9477 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9478 else if (wide)
9479 vty_out(vty, "%7u", attr->med);
0fbac0b4 9480 else
445c2480 9481 vty_out(vty, "%10u", attr->med);
ae248832
MK
9482 else if (!json_paths) {
9483 if (wide)
9484 vty_out(vty, "%*s", 7, " ");
9485 else
9486 vty_out(vty, "%*s", 10, " ");
9487 }
d62a17ae 9488
445c2480
DS
9489 /* Local Pref */
9490 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9491 if (json_paths)
50e05855 9492 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9493 attr->local_pref);
9494 else
445c2480
DS
9495 vty_out(vty, "%7u", attr->local_pref);
9496 else if (!json_paths)
9497 vty_out(vty, " ");
d62a17ae 9498
445c2480
DS
9499 if (json_paths)
9500 json_object_int_add(json_path, "weight", attr->weight);
9501 else
9502 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9503
47e12884
DA
9504 if (json_paths)
9505 json_object_string_addf(json_path, "peerId", "%pSU",
9506 &path->peer->su);
b05a1c8b 9507
445c2480
DS
9508 /* Print aspath */
9509 if (attr->aspath) {
0fbac0b4 9510 if (json_paths)
50e05855 9511 json_object_string_add(json_path, "path",
0fbac0b4
DA
9512 attr->aspath->str);
9513 else
445c2480 9514 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9515 }
f1aa5d8a 9516
445c2480
DS
9517 /* Print origin */
9518 if (json_paths)
a4d82a8a
PZ
9519 json_object_string_add(json_path, "origin",
9520 bgp_origin_long_str[attr->origin]);
445c2480
DS
9521 else
9522 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9523
9df8b37c 9524 if (json_paths) {
d071f237 9525 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9526 json_object_string_add(json_path, "esi",
9527 esi_to_str(&attr->esi,
9528 esi_buf, sizeof(esi_buf)));
9529 }
6f214dd3
CS
9530 if (safi == SAFI_EVPN &&
9531 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9532 json_ext_community = json_object_new_object();
b53e67a3
DA
9533 json_object_string_add(
9534 json_ext_community, "string",
9535 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9536 json_object_object_add(json_path,
9537 "extendedCommunity",
9538 json_ext_community);
9539 }
9540
9df8b37c
PZ
9541 if (nexthop_self)
9542 json_object_boolean_true_add(json_path,
9543 "announceNexthopSelf");
9544 if (nexthop_othervrf) {
9545 json_object_string_add(json_path, "nhVrfName",
9546 nexthop_vrfname);
9547
9548 json_object_int_add(json_path, "nhVrfId",
9549 ((nexthop_vrfid == VRF_UNKNOWN)
9550 ? -1
9551 : (int)nexthop_vrfid));
9552 }
9553 }
9554
d62a17ae 9555 if (json_paths) {
9556 if (json_nexthop_global || json_nexthop_ll) {
9557 json_nexthops = json_object_new_array();
f1aa5d8a 9558
d62a17ae 9559 if (json_nexthop_global)
9560 json_object_array_add(json_nexthops,
9561 json_nexthop_global);
f1aa5d8a 9562
d62a17ae 9563 if (json_nexthop_ll)
9564 json_object_array_add(json_nexthops,
9565 json_nexthop_ll);
f1aa5d8a 9566
d62a17ae 9567 json_object_object_add(json_path, "nexthops",
9568 json_nexthops);
9569 }
9570
9571 json_object_array_add(json_paths, json_path);
9572 } else {
9573 vty_out(vty, "\n");
6f214dd3 9574
b5e140c8 9575 if (safi == SAFI_EVPN) {
d071f237 9576 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9577 /* XXX - add these params to the json out */
b5e140c8 9578 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9579 vty_out(vty, "ESI:%s",
9580 esi_to_str(&attr->esi, esi_buf,
9581 sizeof(esi_buf)));
60605cbc 9582
229587fb 9583 vty_out(vty, "\n");
b5e140c8
AK
9584 }
9585 if (attr->flag &
9586 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9587 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9588 vty_out(vty, "%s\n",
9589 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9590 }
6f214dd3
CS
9591 }
9592
49e5a4a0 9593#ifdef ENABLE_BGP_VNC
d62a17ae 9594 /* prints an additional line, indented, with VNC info, if
9595 * present */
9596 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9597 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9598#endif
d62a17ae 9599 }
9600}
718e3744 9601
9602/* called from terminal list command */
7d3cae70
DA
9603void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9604 const struct prefix *p, struct attr *attr, safi_t safi,
9605 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9606{
9607 json_object *json_status = NULL;
9608 json_object *json_net = NULL;
aef999a2 9609 int len;
d62a17ae 9610 char buff[BUFSIZ];
dc387b0f 9611
d62a17ae 9612 /* Route status display. */
9613 if (use_json) {
9614 json_status = json_object_new_object();
9615 json_net = json_object_new_object();
9616 } else {
9617 vty_out(vty, "*");
9618 vty_out(vty, ">");
9619 vty_out(vty, " ");
9620 }
718e3744 9621
d62a17ae 9622 /* print prefix and mask */
50e05855 9623 if (use_json) {
dc387b0f
LK
9624 if (safi == SAFI_EVPN)
9625 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9626 else if (p->family == AF_INET || p->family == AF_INET6) {
9627 json_object_string_add(
9628 json_net, "addrPrefix",
9629 inet_ntop(p->family, &p->u.prefix, buff,
9630 BUFSIZ));
9631 json_object_int_add(json_net, "prefixLen",
9632 p->prefixlen);
67d7e256 9633 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9634 }
50e05855 9635 } else
7d3cae70 9636 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9637
9638 /* Print attribute */
9639 if (attr) {
9640 if (use_json) {
7226bc40
TA
9641 if (p->family == AF_INET &&
9642 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9643 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9644 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9645 json_object_string_addf(
9646 json_net, "nextHop", "%pI4",
9647 &attr->mp_nexthop_global_in);
d62a17ae 9648 else
c949c771
DA
9649 json_object_string_addf(
9650 json_net, "nextHop", "%pI4",
9651 &attr->nexthop);
7226bc40
TA
9652 } else if (p->family == AF_INET6 ||
9653 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9654 json_object_string_addf(
9655 json_net, "nextHopGlobal", "%pI6",
9656 &attr->mp_nexthop_global);
7226bc40
TA
9657 } else if (p->family == AF_EVPN &&
9658 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9659 json_object_string_addf(
9660 json_net, "nextHop", "%pI4",
9661 &attr->mp_nexthop_global_in);
23d0a753 9662 }
d62a17ae 9663
9664 if (attr->flag
9665 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9666 json_object_int_add(json_net, "metric",
9667 attr->med);
9668
0fbac0b4 9669 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9670 json_object_int_add(json_net, "locPrf",
0fbac0b4 9671 attr->local_pref);
d62a17ae 9672
9673 json_object_int_add(json_net, "weight", attr->weight);
9674
9675 /* Print aspath */
0fbac0b4 9676 if (attr->aspath)
50e05855 9677 json_object_string_add(json_net, "path",
0fbac0b4 9678 attr->aspath->str);
d62a17ae 9679
9680 /* Print origin */
9681 json_object_string_add(json_net, "bgpOriginCode",
9682 bgp_origin_str[attr->origin]);
9683 } else {
7226bc40
TA
9684 if (p->family == AF_INET &&
9685 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9686 safi == SAFI_EVPN ||
9687 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9688 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9689 || safi == SAFI_EVPN)
23d0a753
DA
9690 vty_out(vty, "%-16pI4",
9691 &attr->mp_nexthop_global_in);
ae248832 9692 else if (wide)
23d0a753 9693 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9694 else
23d0a753 9695 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9696 } else if (p->family == AF_INET6 ||
9697 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9698 char buf[BUFSIZ];
9699
9700 len = vty_out(
9701 vty, "%s",
9702 inet_ntop(AF_INET6,
9703 &attr->mp_nexthop_global, buf,
9704 BUFSIZ));
ae248832 9705 len = wide ? (41 - len) : (16 - len);
d62a17ae 9706 if (len < 1)
9707 vty_out(vty, "\n%*s", 36, " ");
9708 else
9709 vty_out(vty, "%*s", len, " ");
9710 }
9711 if (attr->flag
9712 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9713 if (wide)
9714 vty_out(vty, "%7u", attr->med);
9715 else
9716 vty_out(vty, "%10u", attr->med);
9717 else if (wide)
9718 vty_out(vty, " ");
d62a17ae 9719 else
9720 vty_out(vty, " ");
718e3744 9721
d62a17ae 9722 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9723 vty_out(vty, "%7u", attr->local_pref);
9724 else
9725 vty_out(vty, " ");
9726
9727 vty_out(vty, "%7u ", attr->weight);
9728
9729 /* Print aspath */
9730 if (attr->aspath)
9731 aspath_print_vty(vty, "%s", attr->aspath, " ");
9732
9733 /* Print origin */
9734 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9735 }
9736 }
9737 if (use_json) {
9738 json_object_boolean_true_add(json_status, "*");
9739 json_object_boolean_true_add(json_status, ">");
9740 json_object_object_add(json_net, "appliedStatusSymbols",
9741 json_status);
511211bf 9742 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9743 } else
9744 vty_out(vty, "\n");
9745}
9746
bd494ec5 9747void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9748 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9749 json_object *json)
9750{
9751 json_object *json_out = NULL;
9752 struct attr *attr;
9753 mpls_label_t label = MPLS_INVALID_LABEL;
9754
9b6d8fcf 9755 if (!path->extra)
d62a17ae 9756 return;
9757
9758 if (json)
9759 json_out = json_object_new_object();
9760
9761 /* short status lead text */
82c298be 9762 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9763
9764 /* print prefix and mask */
9765 if (json == NULL) {
9766 if (!display)
7d3cae70 9767 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9768 else
9769 vty_out(vty, "%*s", 17, " ");
9770 }
9771
9772 /* Print attribute */
9b6d8fcf 9773 attr = path->attr;
7226bc40
TA
9774 if (((p->family == AF_INET) &&
9775 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9776 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9777 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9778 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9779 || safi == SAFI_EVPN) {
9780 if (json)
c949c771
DA
9781 json_object_string_addf(
9782 json_out, "mpNexthopGlobalIn", "%pI4",
9783 &attr->mp_nexthop_global_in);
05864da7 9784 else
23d0a753
DA
9785 vty_out(vty, "%-16pI4",
9786 &attr->mp_nexthop_global_in);
05864da7
DS
9787 } else {
9788 if (json)
c949c771
DA
9789 json_object_string_addf(json_out, "nexthop",
9790 "%pI4", &attr->nexthop);
05864da7 9791 else
23d0a753 9792 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9793 }
7226bc40
TA
9794 } else if (((p->family == AF_INET6) &&
9795 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9796 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9797 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9798 char buf_a[512];
9799
9800 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9801 if (json)
c949c771
DA
9802 json_object_string_addf(
9803 json_out, "mpNexthopGlobalIn", "%pI6",
9804 &attr->mp_nexthop_global);
05864da7
DS
9805 else
9806 vty_out(vty, "%s",
9807 inet_ntop(AF_INET6,
9808 &attr->mp_nexthop_global,
9809 buf_a, sizeof(buf_a)));
9810 } else if (attr->mp_nexthop_len
9811 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9812 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9813 &attr->mp_nexthop_global,
9814 &attr->mp_nexthop_local);
9815 if (json)
9816 json_object_string_add(json_out,
9817 "mpNexthopGlobalLocal",
9818 buf_a);
9819 else
9820 vty_out(vty, "%s", buf_a);
d62a17ae 9821 }
9822 }
9823
9b6d8fcf 9824 label = decode_label(&path->extra->label[0]);
d62a17ae 9825
9826 if (bgp_is_valid_label(&label)) {
9827 if (json) {
9828 json_object_int_add(json_out, "notag", label);
9829 json_object_array_add(json, json_out);
9830 } else {
9831 vty_out(vty, "notag/%d", label);
9832 vty_out(vty, "\n");
9833 }
700ddfed
PG
9834 } else if (!json)
9835 vty_out(vty, "\n");
d62a17ae 9836}
718e3744 9837
bd494ec5 9838void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9839 struct bgp_path_info *path, int display,
d62a17ae 9840 json_object *json_paths)
718e3744 9841{
d62a17ae 9842 struct attr *attr;
d62a17ae 9843 json_object *json_path = NULL;
14f51eba
LK
9844 json_object *json_nexthop = NULL;
9845 json_object *json_overlay = NULL;
856ca177 9846
9b6d8fcf 9847 if (!path->extra)
d62a17ae 9848 return;
718e3744 9849
14f51eba
LK
9850 if (json_paths) {
9851 json_path = json_object_new_object();
9852 json_overlay = json_object_new_object();
9853 json_nexthop = json_object_new_object();
9854 }
9855
d62a17ae 9856 /* short status lead text */
82c298be 9857 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9858
d62a17ae 9859 /* print prefix and mask */
9860 if (!display)
7d3cae70 9861 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9862 else
9863 vty_out(vty, "%*s", 17, " ");
9864
9865 /* Print attribute */
9b6d8fcf 9866 attr = path->attr;
05864da7 9867 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9868
05864da7
DS
9869 switch (af) {
9870 case AF_INET:
05864da7 9871 if (!json_path) {
db66cf7c 9872 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9873 } else {
db66cf7c
DA
9874 json_object_string_addf(json_nexthop, "ip", "%pI4",
9875 &attr->mp_nexthop_global_in);
14f51eba 9876
05864da7 9877 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9878
05864da7
DS
9879 json_object_object_add(json_path, "nexthop",
9880 json_nexthop);
9881 }
9882 break;
9883 case AF_INET6:
05864da7 9884 if (!json_path) {
db66cf7c
DA
9885 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9886 &attr->mp_nexthop_local);
05864da7 9887 } else {
db66cf7c
DA
9888 json_object_string_addf(json_nexthop, "ipv6Global",
9889 "%pI6",
9890 &attr->mp_nexthop_global);
14f51eba 9891
db66cf7c
DA
9892 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9893 "%pI6",
9894 &attr->mp_nexthop_local);
14f51eba 9895
05864da7 9896 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9897
05864da7
DS
9898 json_object_object_add(json_path, "nexthop",
9899 json_nexthop);
9900 }
9901 break;
9902 default:
9903 if (!json_path) {
9904 vty_out(vty, "?");
9905 } else {
9906 json_object_string_add(json_nexthop, "Error",
9907 "Unsupported address-family");
77a2f8e5
DA
9908 json_object_string_add(json_nexthop, "error",
9909 "Unsupported address-family");
d62a17ae 9910 }
05864da7 9911 }
988258b4 9912
6c924775
DS
9913 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9914
05864da7 9915 if (!json_path)
db66cf7c 9916 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9917 else
db66cf7c 9918 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9919
b53e67a3 9920 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9921 char *mac = NULL;
9922 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9923 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9924 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9925
9926 if (routermac)
9927 mac = ecom_mac2str((char *)routermac->val);
9928 if (mac) {
9929 if (!json_path) {
c4efd0f4 9930 vty_out(vty, "/%s", mac);
05864da7
DS
9931 } else {
9932 json_object_string_add(json_overlay, "rmac",
9933 mac);
988258b4 9934 }
05864da7 9935 XFREE(MTYPE_TMP, mac);
988258b4 9936 }
05864da7 9937 }
718e3744 9938
05864da7
DS
9939 if (!json_path) {
9940 vty_out(vty, "\n");
9941 } else {
9942 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9943
05864da7 9944 json_object_array_add(json_paths, json_path);
14f51eba 9945 }
d62a17ae 9946}
718e3744 9947
d62a17ae 9948/* dampening route */
5f040085
DS
9949static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9950 struct bgp_path_info *path, int display,
9951 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9952 json_object *json_paths)
d62a17ae 9953{
e5be8c1d 9954 struct attr *attr = path->attr;
d62a17ae 9955 int len;
9956 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9957 json_object *json_path = NULL;
9958
9959 if (use_json)
9960 json_path = json_object_new_object();
d62a17ae 9961
9962 /* short status lead text */
e5be8c1d 9963 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9964
9965 /* print prefix and mask */
9966 if (!use_json) {
9967 if (!display)
7d3cae70 9968 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9969 else
9970 vty_out(vty, "%*s", 17, " ");
d62a17ae 9971
e5be8c1d
DA
9972 len = vty_out(vty, "%s", path->peer->host);
9973 len = 17 - len;
9974
9975 if (len < 1)
d62a17ae 9976 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9977 else
9978 vty_out(vty, "%*s", len, " ");
d62a17ae 9979
9b6d8fcf
DS
9980 vty_out(vty, "%s ",
9981 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9982 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9983 use_json, NULL));
d62a17ae 9984
e5be8c1d 9985 if (attr->aspath)
05864da7 9986 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9987
05864da7
DS
9988 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9989
d62a17ae 9990 vty_out(vty, "\n");
e5be8c1d
DA
9991 } else {
9992 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9993 safi, use_json, json_path);
9994
9995 if (attr->aspath)
9996 json_object_string_add(json_path, "asPath",
9997 attr->aspath->str);
9998
9999 json_object_string_add(json_path, "origin",
10000 bgp_origin_str[attr->origin]);
10001 json_object_string_add(json_path, "peerHost", path->peer->host);
10002
10003 json_object_array_add(json_paths, json_path);
10004 }
d62a17ae 10005}
718e3744 10006
d62a17ae 10007/* flap route */
5f040085
DS
10008static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10009 struct bgp_path_info *path, int display,
10010 afi_t afi, safi_t safi, bool use_json,
31258046 10011 json_object *json_paths)
784d3a42 10012{
31258046 10013 struct attr *attr = path->attr;
d62a17ae 10014 struct bgp_damp_info *bdi;
10015 char timebuf[BGP_UPTIME_LEN];
10016 int len;
31258046 10017 json_object *json_path = NULL;
784d3a42 10018
9b6d8fcf 10019 if (!path->extra)
d62a17ae 10020 return;
784d3a42 10021
31258046
DA
10022 if (use_json)
10023 json_path = json_object_new_object();
10024
9b6d8fcf 10025 bdi = path->extra->damp_info;
784d3a42 10026
d62a17ae 10027 /* short status lead text */
31258046 10028 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10029
d62a17ae 10030 if (!use_json) {
10031 if (!display)
7d3cae70 10032 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10033 else
10034 vty_out(vty, "%*s", 17, " ");
784d3a42 10035
31258046
DA
10036 len = vty_out(vty, "%s", path->peer->host);
10037 len = 16 - len;
10038 if (len < 1)
d62a17ae 10039 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10040 else
10041 vty_out(vty, "%*s", len, " ");
784d3a42 10042
31258046
DA
10043 len = vty_out(vty, "%d", bdi->flap);
10044 len = 5 - len;
10045 if (len < 1)
d62a17ae 10046 vty_out(vty, " ");
d62a17ae 10047 else
10048 vty_out(vty, "%*s", len, " ");
d62a17ae 10049
996c9314
LB
10050 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10051 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10052
31258046
DA
10053 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10054 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10055 vty_out(vty, "%s ",
9b6d8fcf 10056 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10057 BGP_UPTIME_LEN, afi,
31258046
DA
10058 safi, use_json, NULL));
10059 else
d62a17ae 10060 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10061
31258046 10062 if (attr->aspath)
05864da7 10063 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10064
05864da7
DS
10065 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10066
d62a17ae 10067 vty_out(vty, "\n");
31258046
DA
10068 } else {
10069 json_object_string_add(json_path, "peerHost", path->peer->host);
10070 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10071
10072 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10073 json_path);
10074
10075 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10076 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10077 bgp_damp_reuse_time_vty(vty, path, timebuf,
10078 BGP_UPTIME_LEN, afi, safi,
10079 use_json, json_path);
10080
10081 if (attr->aspath)
10082 json_object_string_add(json_path, "asPath",
10083 attr->aspath->str);
10084
10085 json_object_string_add(json_path, "origin",
10086 bgp_origin_str[attr->origin]);
10087
10088 json_object_array_add(json_paths, json_path);
10089 }
d62a17ae 10090}
10091
10092static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10093 int *first, const char *header,
10094 json_object *json_adv_to)
10095{
d62a17ae 10096 json_object *json_peer = NULL;
10097
10098 if (json_adv_to) {
10099 /* 'advertised-to' is a dictionary of peers we have advertised
10100 * this
10101 * prefix too. The key is the peer's IP or swpX, the value is
10102 * the
10103 * hostname if we know it and "" if not.
10104 */
10105 json_peer = json_object_new_object();
10106
10107 if (peer->hostname)
10108 json_object_string_add(json_peer, "hostname",
10109 peer->hostname);
10110
10111 if (peer->conf_if)
10112 json_object_object_add(json_adv_to, peer->conf_if,
10113 json_peer);
10114 else
47e12884
DA
10115 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10116 &peer->su);
d62a17ae 10117 } else {
10118 if (*first) {
10119 vty_out(vty, "%s", header);
10120 *first = 0;
10121 }
10122
10123 if (peer->hostname
892fedb6 10124 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10125 if (peer->conf_if)
10126 vty_out(vty, " %s(%s)", peer->hostname,
10127 peer->conf_if);
10128 else
47e12884
DA
10129 vty_out(vty, " %s(%pSU)", peer->hostname,
10130 &peer->su);
d62a17ae 10131 } else {
10132 if (peer->conf_if)
10133 vty_out(vty, " %s", peer->conf_if);
10134 else
47e12884 10135 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10136 }
10137 }
784d3a42
PG
10138}
10139
dcc68b5e
MS
10140static void route_vty_out_tx_ids(struct vty *vty,
10141 struct bgp_addpath_info_data *d)
10142{
10143 int i;
10144
10145 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10146 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10147 d->addpath_tx_id[i],
10148 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10149 }
10150}
10151
5e4d4c8a 10152static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10153 struct bgp_path_info *pi,
10154 struct attr *attr,
10155 json_object *json_path)
5e4d4c8a
AK
10156{
10157 char esi_buf[ESI_STR_LEN];
10158 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10159 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10160 ATTR_ES_PEER_ROUTER);
10161 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10162 ATTR_ES_PEER_ACTIVE);
10163 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10164 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10165 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10166 if (json_path) {
10167 json_object *json_es_info = NULL;
10168
10169 json_object_string_add(
10170 json_path, "esi",
10171 esi_buf);
10172 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10173 json_es_info = json_object_new_object();
10174 if (es_local)
10175 json_object_boolean_true_add(
10176 json_es_info, "localEs");
10177 if (peer_active)
10178 json_object_boolean_true_add(
10179 json_es_info, "peerActive");
10180 if (peer_proxy)
10181 json_object_boolean_true_add(
10182 json_es_info, "peerProxy");
10183 if (peer_router)
10184 json_object_boolean_true_add(
10185 json_es_info, "peerRouter");
10186 if (attr->mm_sync_seqnum)
10187 json_object_int_add(
10188 json_es_info, "peerSeq",
10189 attr->mm_sync_seqnum);
10190 json_object_object_add(
10191 json_path, "es_info",
10192 json_es_info);
10193 }
10194 } else {
10195 if (bgp_evpn_attr_is_sync(attr))
10196 vty_out(vty,
10197 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10198 esi_buf,
10199 es_local ? "local-es":"",
10200 peer_proxy ? "proxy " : "",
10201 peer_active ? "active ":"",
10202 peer_router ? "router ":"",
10203 attr->mm_sync_seqnum);
10204 else
10205 vty_out(vty, " ESI %s %s\n",
10206 esi_buf,
10207 es_local ? "local-es":"");
10208 }
10209}
10210
4933eaaf
DS
10211void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
10212 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
10213 enum rpki_states rpki_curr_state,
10214 json_object *json_paths)
d62a17ae 10215{
10216 char buf[INET6_ADDRSTRLEN];
10217 char buf1[BUFSIZ];
515c2602 10218 struct attr *attr = path->attr;
d62a17ae 10219 time_t tbuf;
10220 json_object *json_bestpath = NULL;
10221 json_object *json_cluster_list = NULL;
10222 json_object *json_cluster_list_list = NULL;
10223 json_object *json_ext_community = NULL;
10224 json_object *json_last_update = NULL;
7fd077aa 10225 json_object *json_pmsi = NULL;
d62a17ae 10226 json_object *json_nexthop_global = NULL;
10227 json_object *json_nexthop_ll = NULL;
10228 json_object *json_nexthops = NULL;
10229 json_object *json_path = NULL;
10230 json_object *json_peer = NULL;
10231 json_object *json_string = NULL;
10232 json_object *json_adv_to = NULL;
10233 int first = 0;
10234 struct listnode *node, *nnode;
10235 struct peer *peer;
be92fc9f 10236 bool addpath_capable;
d62a17ae 10237 int has_adj;
10238 unsigned int first_as;
1defdda8 10239 bool nexthop_self =
9b6d8fcf 10240 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10241 int i;
2ba93fd6
DA
10242 char *nexthop_hostname =
10243 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10244 uint32_t ttl = 0;
10245 uint32_t bos = 0;
10246 uint32_t exp = 0;
10247 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 10248
10249 if (json_paths) {
10250 json_path = json_object_new_object();
10251 json_peer = json_object_new_object();
10252 json_nexthop_global = json_object_new_object();
10253 }
10254
8304dabf
AD
10255 if (safi == SAFI_EVPN) {
10256 if (!json_paths)
10257 vty_out(vty, " Route %pRN", bn);
10258 }
10259
44c69747 10260 if (path->extra) {
b57ba6d2 10261 char tag_buf[30];
d62a17ae 10262
d62a17ae 10263 tag_buf[0] = '\0';
9b6d8fcf
DS
10264 if (path->extra && path->extra->num_labels) {
10265 bgp_evpn_label2str(path->extra->label,
10266 path->extra->num_labels, tag_buf,
a4d82a8a 10267 sizeof(tag_buf));
d62a17ae 10268 }
d7325ee7 10269 if (safi == SAFI_EVPN) {
44c69747 10270 if (!json_paths) {
44c69747
LK
10271 if (tag_buf[0] != '\0')
10272 vty_out(vty, " VNI %s", tag_buf);
44c69747 10273 } else {
77a2f8e5 10274 if (tag_buf[0]) {
44c69747
LK
10275 json_object_string_add(json_path, "VNI",
10276 tag_buf);
77a2f8e5
DA
10277 json_object_string_add(json_path, "vni",
10278 tag_buf);
10279 }
44c69747 10280 }
d7325ee7
DD
10281 }
10282
44c69747 10283 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10284 struct bgp_path_info *parent_ri;
9bcb3eef 10285 struct bgp_dest *dest, *pdest;
d62a17ae 10286
9b6d8fcf 10287 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10288 dest = parent_ri->net;
10289 if (dest && dest->pdest) {
10290 pdest = dest->pdest;
d7325ee7 10291 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10292 vty_out(vty,
c4f64ea9
DA
10293 " Imported from %pRD:%pFX, VNI %s",
10294 (struct prefix_rd *)
10295 bgp_dest_get_prefix(
10296 pdest),
2dbe669b
DA
10297 (struct prefix_evpn *)
10298 bgp_dest_get_prefix(
10299 dest),
10300 tag_buf);
58bff4d1
AK
10301 if (attr->es_flags & ATTR_ES_L3_NHG)
10302 vty_out(vty, ", L3NHG %s",
10303 (attr->es_flags
10304 & ATTR_ES_L3_NHG_ACTIVE)
10305 ? "active"
10306 : "inactive");
10307 vty_out(vty, "\n");
10308
d7325ee7 10309 } else
2dbe669b 10310 vty_out(vty,
c4f64ea9
DA
10311 " Imported from %pRD:%pFX\n",
10312 (struct prefix_rd *)
10313 bgp_dest_get_prefix(
10314 pdest),
2dbe669b
DA
10315 (struct prefix_evpn *)
10316 bgp_dest_get_prefix(
10317 dest));
d62a17ae 10318 }
10319 }
10320 }
d62a17ae 10321
8304dabf
AD
10322 if (safi == SAFI_EVPN
10323 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10324 char gwip_buf[INET6_ADDRSTRLEN];
10325
860e740b
IR
10326 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10327 sizeof(gwip_buf));
8304dabf
AD
10328
10329 if (json_paths)
10330 json_object_string_add(json_path, "gatewayIP",
10331 gwip_buf);
10332 else
10333 vty_out(vty, " Gateway IP %s", gwip_buf);
10334 }
10335
2bf9780b 10336 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10337 vty_out(vty, "\n");
10338
05864da7
DS
10339 /* Line1 display AS-path, Aggregator */
10340 if (attr->aspath) {
10341 if (json_paths) {
10342 if (!attr->aspath->json)
10343 aspath_str_update(attr->aspath, true);
10344 json_object_lock(attr->aspath->json);
10345 json_object_object_add(json_path, "aspath",
10346 attr->aspath->json);
10347 } else {
10348 if (attr->aspath->segments)
10349 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10350 else
05864da7 10351 vty_out(vty, " Local");
d62a17ae 10352 }
05864da7 10353 }
d62a17ae 10354
05864da7
DS
10355 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10356 if (json_paths)
10357 json_object_boolean_true_add(json_path, "removed");
10358 else
10359 vty_out(vty, ", (removed)");
10360 }
d62a17ae 10361
05864da7
DS
10362 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10363 if (json_paths)
10364 json_object_boolean_true_add(json_path, "stale");
10365 else
10366 vty_out(vty, ", (stale)");
10367 }
d62a17ae 10368
05864da7
DS
10369 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10370 if (json_paths) {
10371 json_object_int_add(json_path, "aggregatorAs",
10372 attr->aggregator_as);
c949c771
DA
10373 json_object_string_addf(json_path, "aggregatorId",
10374 "%pI4", &attr->aggregator_addr);
05864da7 10375 } else {
88d495a9
DA
10376 vty_out(vty, ", (aggregated by %u %pI4)",
10377 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10378 }
05864da7 10379 }
d62a17ae 10380
05864da7
DS
10381 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10382 PEER_FLAG_REFLECTOR_CLIENT)) {
10383 if (json_paths)
10384 json_object_boolean_true_add(json_path,
10385 "rxedFromRrClient");
10386 else
10387 vty_out(vty, ", (Received from a RR-client)");
10388 }
d62a17ae 10389
05864da7
DS
10390 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10391 PEER_FLAG_RSERVER_CLIENT)) {
10392 if (json_paths)
10393 json_object_boolean_true_add(json_path,
10394 "rxedFromRsClient");
10395 else
10396 vty_out(vty, ", (Received from a RS-client)");
10397 }
d62a17ae 10398
05864da7
DS
10399 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10400 if (json_paths)
10401 json_object_boolean_true_add(json_path,
10402 "dampeningHistoryEntry");
10403 else
10404 vty_out(vty, ", (history entry)");
10405 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10406 if (json_paths)
10407 json_object_boolean_true_add(json_path,
10408 "dampeningSuppressed");
10409 else
10410 vty_out(vty, ", (suppressed due to dampening)");
10411 }
d62a17ae 10412
05864da7
DS
10413 if (!json_paths)
10414 vty_out(vty, "\n");
d62a17ae 10415
05864da7
DS
10416 /* Line2 display Next-hop, Neighbor, Router-id */
10417 /* Display the nexthop */
9bcb3eef 10418 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10419
7226bc40
TA
10420 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10421 bn_p->family == AF_EVPN) &&
10422 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10423 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10424 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10425 || safi == SAFI_EVPN) {
515c2602 10426 if (json_paths) {
c949c771
DA
10427 json_object_string_addf(
10428 json_nexthop_global, "ip", "%pI4",
10429 &attr->mp_nexthop_global_in);
515c2602 10430
939a97f4 10431 if (path->peer->hostname)
515c2602
DA
10432 json_object_string_add(
10433 json_nexthop_global, "hostname",
939a97f4 10434 path->peer->hostname);
aef999a2
DA
10435 } else {
10436 if (nexthop_hostname)
10437 vty_out(vty, " %pI4(%s)",
10438 &attr->mp_nexthop_global_in,
10439 nexthop_hostname);
10440 else
10441 vty_out(vty, " %pI4",
10442 &attr->mp_nexthop_global_in);
10443 }
d62a17ae 10444 } else {
515c2602 10445 if (json_paths) {
c949c771
DA
10446 json_object_string_addf(json_nexthop_global,
10447 "ip", "%pI4",
10448 &attr->nexthop);
515c2602 10449
939a97f4 10450 if (path->peer->hostname)
515c2602
DA
10451 json_object_string_add(
10452 json_nexthop_global, "hostname",
939a97f4 10453 path->peer->hostname);
aef999a2
DA
10454 } else {
10455 if (nexthop_hostname)
10456 vty_out(vty, " %pI4(%s)",
10457 &attr->nexthop,
10458 nexthop_hostname);
10459 else
10460 vty_out(vty, " %pI4",
10461 &attr->nexthop);
10462 }
d62a17ae 10463 }
10464
05864da7
DS
10465 if (json_paths)
10466 json_object_string_add(json_nexthop_global, "afi",
10467 "ipv4");
10468 } else {
10469 if (json_paths) {
c949c771
DA
10470 json_object_string_addf(json_nexthop_global, "ip",
10471 "%pI6",
10472 &attr->mp_nexthop_global);
515c2602 10473
939a97f4 10474 if (path->peer->hostname)
515c2602
DA
10475 json_object_string_add(json_nexthop_global,
10476 "hostname",
939a97f4 10477 path->peer->hostname);
515c2602 10478
05864da7
DS
10479 json_object_string_add(json_nexthop_global, "afi",
10480 "ipv6");
10481 json_object_string_add(json_nexthop_global, "scope",
10482 "global");
10483 } else {
aef999a2
DA
10484 if (nexthop_hostname)
10485 vty_out(vty, " %pI6(%s)",
10486 &attr->mp_nexthop_global,
10487 nexthop_hostname);
10488 else
10489 vty_out(vty, " %pI6",
10490 &attr->mp_nexthop_global);
d62a17ae 10491 }
05864da7 10492 }
d62a17ae 10493
05864da7
DS
10494 /* Display the IGP cost or 'inaccessible' */
10495 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10496 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10497
10498 if (json_paths) {
05864da7
DS
10499 json_object_boolean_false_add(json_nexthop_global,
10500 "accessible");
95ba22d5
DA
10501 json_object_boolean_add(json_nexthop_global,
10502 "importCheckEnabled", import);
10503 } else {
10504 vty_out(vty, " (inaccessible%s)",
10505 import ? ", import-check enabled" : "");
10506 }
05864da7
DS
10507 } else {
10508 if (path->extra && path->extra->igpmetric) {
d62a17ae 10509 if (json_paths)
05864da7
DS
10510 json_object_int_add(json_nexthop_global,
10511 "metric",
10512 path->extra->igpmetric);
d62a17ae 10513 else
05864da7
DS
10514 vty_out(vty, " (metric %u)",
10515 path->extra->igpmetric);
d62a17ae 10516 }
10517
05864da7 10518 /* IGP cost is 0, display this only for json */
d62a17ae 10519 else {
d62a17ae 10520 if (json_paths)
05864da7
DS
10521 json_object_int_add(json_nexthop_global,
10522 "metric", 0);
d62a17ae 10523 }
d62a17ae 10524
05864da7
DS
10525 if (json_paths)
10526 json_object_boolean_true_add(json_nexthop_global,
10527 "accessible");
10528 }
d62a17ae 10529
05864da7
DS
10530 /* Display peer "from" output */
10531 /* This path was originated locally */
10532 if (path->peer == bgp->peer_self) {
d62a17ae 10533
7226bc40
TA
10534 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10535 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10536 if (json_paths)
05864da7
DS
10537 json_object_string_add(json_peer, "peerId",
10538 "0.0.0.0");
d62a17ae 10539 else
05864da7
DS
10540 vty_out(vty, " from 0.0.0.0 ");
10541 } else {
d62a17ae 10542 if (json_paths)
05864da7
DS
10543 json_object_string_add(json_peer, "peerId",
10544 "::");
d62a17ae 10545 else
05864da7 10546 vty_out(vty, " from :: ");
d62a17ae 10547 }
d62a17ae 10548
4e9a9863 10549 if (json_paths)
c949c771
DA
10550 json_object_string_addf(json_peer, "routerId", "%pI4",
10551 &bgp->router_id);
4e9a9863 10552 else
23d0a753 10553 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10554 }
d62a17ae 10555
05864da7
DS
10556 /* We RXed this path from one of our peers */
10557 else {
10558
10559 if (json_paths) {
47e12884
DA
10560 json_object_string_addf(json_peer, "peerId", "%pSU",
10561 &path->peer->su);
c949c771
DA
10562 json_object_string_addf(json_peer, "routerId", "%pI4",
10563 &path->peer->remote_id);
05864da7
DS
10564
10565 if (path->peer->hostname)
10566 json_object_string_add(json_peer, "hostname",
10567 path->peer->hostname);
10568
10569 if (path->peer->domainname)
10570 json_object_string_add(json_peer, "domainname",
10571 path->peer->domainname);
10572
10573 if (path->peer->conf_if)
10574 json_object_string_add(json_peer, "interface",
10575 path->peer->conf_if);
10576 } else {
10577 if (path->peer->conf_if) {
10578 if (path->peer->hostname
892fedb6
DA
10579 && CHECK_FLAG(path->peer->bgp->flags,
10580 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10581 vty_out(vty, " from %s(%s)",
10582 path->peer->hostname,
10583 path->peer->conf_if);
d62a17ae 10584 else
05864da7 10585 vty_out(vty, " from %s",
9b6d8fcf 10586 path->peer->conf_if);
d62a17ae 10587 } else {
05864da7 10588 if (path->peer->hostname
892fedb6
DA
10589 && CHECK_FLAG(path->peer->bgp->flags,
10590 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10591 vty_out(vty, " from %s(%s)",
10592 path->peer->hostname,
10593 path->peer->host);
d62a17ae 10594 else
47e12884
DA
10595 vty_out(vty, " from %pSU",
10596 &path->peer->su);
d62a17ae 10597 }
d62a17ae 10598
05864da7 10599 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10600 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10601 else
10602 vty_out(vty, " (%s)",
10603 inet_ntop(AF_INET,
10604 &path->peer->remote_id, buf1,
10605 sizeof(buf1)));
d62a17ae 10606 }
05864da7 10607 }
9df8b37c 10608
05864da7
DS
10609 /*
10610 * Note when vrfid of nexthop is different from that of prefix
10611 */
10612 if (path->extra && path->extra->bgp_orig) {
10613 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10614
05864da7
DS
10615 if (json_paths) {
10616 const char *vn;
9df8b37c 10617
05864da7
DS
10618 if (path->extra->bgp_orig->inst_type
10619 == BGP_INSTANCE_TYPE_DEFAULT)
10620 vn = VRF_DEFAULT_NAME;
10621 else
10622 vn = path->extra->bgp_orig->name;
9df8b37c 10623
05864da7 10624 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10625
05864da7
DS
10626 if (nexthop_vrfid == VRF_UNKNOWN) {
10627 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10628 } else {
05864da7
DS
10629 json_object_int_add(json_path, "nhVrfId",
10630 (int)nexthop_vrfid);
9df8b37c 10631 }
05864da7
DS
10632 } else {
10633 if (nexthop_vrfid == VRF_UNKNOWN)
10634 vty_out(vty, " vrf ?");
137147c6
DS
10635 else {
10636 struct vrf *vrf;
10637
10638 vrf = vrf_lookup_by_id(nexthop_vrfid);
10639 vty_out(vty, " vrf %s(%u)",
10640 VRF_LOGNAME(vrf), nexthop_vrfid);
10641 }
9df8b37c 10642 }
05864da7 10643 }
9df8b37c 10644
05864da7
DS
10645 if (nexthop_self) {
10646 if (json_paths) {
10647 json_object_boolean_true_add(json_path,
10648 "announceNexthopSelf");
10649 } else {
10650 vty_out(vty, " announce-nh-self");
9df8b37c 10651 }
05864da7 10652 }
9df8b37c 10653
05864da7
DS
10654 if (!json_paths)
10655 vty_out(vty, "\n");
d62a17ae 10656
05864da7
DS
10657 /* display the link-local nexthop */
10658 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10659 if (json_paths) {
10660 json_nexthop_ll = json_object_new_object();
c949c771
DA
10661 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10662 &attr->mp_nexthop_local);
515c2602 10663
939a97f4 10664 if (path->peer->hostname)
515c2602
DA
10665 json_object_string_add(json_nexthop_ll,
10666 "hostname",
939a97f4 10667 path->peer->hostname);
515c2602 10668
05864da7
DS
10669 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10670 json_object_string_add(json_nexthop_ll, "scope",
10671 "link-local");
d62a17ae 10672
05864da7
DS
10673 json_object_boolean_true_add(json_nexthop_ll,
10674 "accessible");
d62a17ae 10675
05864da7 10676 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10677 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10678 "used");
10679 else
10680 json_object_boolean_true_add(
10681 json_nexthop_global, "used");
10682 } else {
10683 vty_out(vty, " (%s) %s\n",
10684 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10685 buf, INET6_ADDRSTRLEN),
10686 attr->mp_nexthop_prefer_global
10687 ? "(prefer-global)"
10688 : "(used)");
d62a17ae 10689 }
05864da7
DS
10690 }
10691 /* If we do not have a link-local nexthop then we must flag the
10692 global as "used" */
10693 else {
10694 if (json_paths)
10695 json_object_boolean_true_add(json_nexthop_global,
10696 "used");
10697 }
d62a17ae 10698
b5e140c8 10699 if (safi == SAFI_EVPN &&
5e4d4c8a 10700 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10701 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10702 }
10703
05864da7
DS
10704 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10705 * Int/Ext/Local, Atomic, best */
10706 if (json_paths)
10707 json_object_string_add(json_path, "origin",
10708 bgp_origin_long_str[attr->origin]);
10709 else
10710 vty_out(vty, " Origin %s",
10711 bgp_origin_long_str[attr->origin]);
9df8b37c 10712
05864da7 10713 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10714 if (json_paths)
05864da7 10715 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10716 else
05864da7
DS
10717 vty_out(vty, ", metric %u", attr->med);
10718 }
9df8b37c 10719
05864da7
DS
10720 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10721 if (json_paths)
0fbac0b4 10722 json_object_int_add(json_path, "locPrf",
05864da7
DS
10723 attr->local_pref);
10724 else
10725 vty_out(vty, ", localpref %u", attr->local_pref);
10726 }
9df8b37c 10727
97a52c82
DA
10728 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10729 if (json_paths)
10730 json_object_int_add(json_path, "aigpMetric",
10731 bgp_attr_get_aigp_metric(attr));
10732 else
10733 vty_out(vty, ", aigp-metric %" PRIu64,
10734 bgp_attr_get_aigp_metric(attr));
10735 }
10736
05864da7
DS
10737 if (attr->weight != 0) {
10738 if (json_paths)
10739 json_object_int_add(json_path, "weight", attr->weight);
10740 else
10741 vty_out(vty, ", weight %u", attr->weight);
10742 }
9df8b37c 10743
05864da7
DS
10744 if (attr->tag != 0) {
10745 if (json_paths)
10746 json_object_int_add(json_path, "tag", attr->tag);
10747 else
10748 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10749 }
9df8b37c 10750
05864da7
DS
10751 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10752 if (json_paths)
10753 json_object_boolean_false_add(json_path, "valid");
10754 else
10755 vty_out(vty, ", invalid");
10756 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10757 if (json_paths)
10758 json_object_boolean_true_add(json_path, "valid");
10759 else
10760 vty_out(vty, ", valid");
10761 }
9df8b37c 10762
7d3cae70
DA
10763 if (json_paths)
10764 json_object_int_add(json_path, "version", bn->version);
10765
05864da7
DS
10766 if (path->peer != bgp->peer_self) {
10767 if (path->peer->as == path->peer->local_as) {
10768 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10769 if (json_paths)
10770 json_object_string_add(
10771 json_peer, "type",
10772 "confed-internal");
d62a17ae 10773 else
05864da7 10774 vty_out(vty, ", confed-internal");
d62a17ae 10775 } else {
05864da7
DS
10776 if (json_paths)
10777 json_object_string_add(
10778 json_peer, "type", "internal");
10779 else
10780 vty_out(vty, ", internal");
9df8b37c 10781 }
05864da7
DS
10782 } else {
10783 if (bgp_confederation_peers_check(bgp,
10784 path->peer->as)) {
10785 if (json_paths)
10786 json_object_string_add(
10787 json_peer, "type",
10788 "confed-external");
d62a17ae 10789 else
05864da7 10790 vty_out(vty, ", confed-external");
d62a17ae 10791 } else {
05864da7
DS
10792 if (json_paths)
10793 json_object_string_add(
10794 json_peer, "type", "external");
10795 else
10796 vty_out(vty, ", external");
d62a17ae 10797 }
10798 }
05864da7
DS
10799 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10800 if (json_paths) {
10801 json_object_boolean_true_add(json_path, "aggregated");
10802 json_object_boolean_true_add(json_path, "local");
10803 } else {
10804 vty_out(vty, ", aggregated, local");
10805 }
10806 } else if (path->type != ZEBRA_ROUTE_BGP) {
10807 if (json_paths)
10808 json_object_boolean_true_add(json_path, "sourced");
10809 else
10810 vty_out(vty, ", sourced");
10811 } else {
10812 if (json_paths) {
10813 json_object_boolean_true_add(json_path, "sourced");
10814 json_object_boolean_true_add(json_path, "local");
10815 } else {
10816 vty_out(vty, ", sourced, local");
d62a17ae 10817 }
05864da7 10818 }
718e3744 10819
05864da7 10820 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10821 if (json_paths)
05864da7
DS
10822 json_object_boolean_true_add(json_path,
10823 "atomicAggregate");
d62a17ae 10824 else
05864da7
DS
10825 vty_out(vty, ", atomic-aggregate");
10826 }
d62a17ae 10827
d864dd9e
EB
10828 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10829 if (json_paths)
10830 json_object_int_add(json_path, "otc", attr->otc);
10831 else
10832 vty_out(vty, ", otc %u", attr->otc);
10833 }
10834
05864da7
DS
10835 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10836 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10837 && bgp_path_info_mpath_count(path))) {
10838 if (json_paths)
10839 json_object_boolean_true_add(json_path, "multipath");
10840 else
10841 vty_out(vty, ", multipath");
10842 }
50e05855 10843
05864da7
DS
10844 // Mark the bestpath(s)
10845 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10846 first_as = aspath_get_first_as(attr->aspath);
718e3744 10847
05864da7
DS
10848 if (json_paths) {
10849 if (!json_bestpath)
10850 json_bestpath = json_object_new_object();
10851 json_object_int_add(json_bestpath, "bestpathFromAs",
10852 first_as);
10853 } else {
10854 if (first_as)
10855 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10856 else
05864da7 10857 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10858 }
05864da7 10859 }
718e3744 10860
05864da7
DS
10861 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10862 if (json_paths) {
10863 if (!json_bestpath)
10864 json_bestpath = json_object_new_object();
10865 json_object_boolean_true_add(json_bestpath, "overall");
10866 json_object_string_add(
10867 json_bestpath, "selectionReason",
10868 bgp_path_selection_reason2str(bn->reason));
10869 } else {
10870 vty_out(vty, ", best");
10871 vty_out(vty, " (%s)",
10872 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10873 }
05864da7 10874 }
718e3744 10875
4027d19b 10876 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10877 if (json_paths)
10878 json_object_string_add(
10879 json_path, "rpkiValidationState",
4027d19b 10880 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10881 else
1d327209 10882 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10883 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10884 }
10885
05864da7
DS
10886 if (json_bestpath)
10887 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10888
05864da7
DS
10889 if (!json_paths)
10890 vty_out(vty, "\n");
10891
10892 /* Line 4 display Community */
29e72930 10893 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10894 if (json_paths) {
9a706b42
DA
10895 if (!bgp_attr_get_community(attr)->json)
10896 community_str(bgp_attr_get_community(attr),
c0945b78 10897 true, true);
9a706b42
DA
10898 json_object_lock(bgp_attr_get_community(attr)->json);
10899 json_object_object_add(
10900 json_path, "community",
10901 bgp_attr_get_community(attr)->json);
05864da7
DS
10902 } else {
10903 vty_out(vty, " Community: %s\n",
9a706b42 10904 bgp_attr_get_community(attr)->str);
d62a17ae 10905 }
05864da7 10906 }
718e3744 10907
05864da7
DS
10908 /* Line 5 display Extended-community */
10909 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10910 if (json_paths) {
10911 json_ext_community = json_object_new_object();
b53e67a3
DA
10912 json_object_string_add(
10913 json_ext_community, "string",
10914 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10915 json_object_object_add(json_path, "extendedCommunity",
10916 json_ext_community);
d62a17ae 10917 } else {
05864da7 10918 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10919 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10920 }
05864da7 10921 }
718e3744 10922
05864da7
DS
10923 /* Line 6 display Large community */
10924 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10925 if (json_paths) {
1bcf3a96
DA
10926 if (!bgp_attr_get_lcommunity(attr)->json)
10927 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10928 true, true);
1bcf3a96
DA
10929 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10930 json_object_object_add(
10931 json_path, "largeCommunity",
10932 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10933 } else {
10934 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10935 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10936 }
05864da7 10937 }
718e3744 10938
05864da7
DS
10939 /* Line 7 display Originator, Cluster-id */
10940 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10941 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10942 char buf[BUFSIZ] = {0};
10943
05864da7 10944 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10945 if (json_paths)
c949c771
DA
10946 json_object_string_addf(json_path,
10947 "originatorId", "%pI4",
10948 &attr->originator_id);
d62a17ae 10949 else
23d0a753
DA
10950 vty_out(vty, " Originator: %pI4",
10951 &attr->originator_id);
d62a17ae 10952 }
856ca177 10953
05864da7 10954 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10955 struct cluster_list *cluster =
10956 bgp_attr_get_cluster(attr);
05864da7 10957 int i;
d62a17ae 10958
10959 if (json_paths) {
05864da7
DS
10960 json_cluster_list = json_object_new_object();
10961 json_cluster_list_list =
10962 json_object_new_array();
10963
779fee93 10964 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10965 json_string = json_object_new_string(
779fee93
DS
10966 inet_ntop(AF_INET,
10967 &cluster->list[i],
10968 buf, sizeof(buf)));
05864da7
DS
10969 json_object_array_add(
10970 json_cluster_list_list,
10971 json_string);
10972 }
718e3744 10973
05864da7
DS
10974 /*
10975 * struct cluster_list does not have
10976 * "str" variable like aspath and community
10977 * do. Add this someday if someone asks
10978 * for it.
10979 * json_object_string_add(json_cluster_list,
779fee93 10980 * "string", cluster->str);
05864da7
DS
10981 */
10982 json_object_object_add(json_cluster_list,
10983 "list",
10984 json_cluster_list_list);
10985 json_object_object_add(json_path, "clusterList",
10986 json_cluster_list);
0dc8ee70 10987 } else {
05864da7
DS
10988 vty_out(vty, ", Cluster list: ");
10989
779fee93 10990 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10991 vty_out(vty, "%pI4 ",
779fee93 10992 &cluster->list[i]);
05864da7 10993 }
0dc8ee70 10994 }
d62a17ae 10995 }
718e3744 10996
d62a17ae 10997 if (!json_paths)
10998 vty_out(vty, "\n");
05864da7 10999 }
d62a17ae 11000
05864da7 11001 if (path->extra && path->extra->damp_info)
b4f7f45b 11002 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 11003
05864da7
DS
11004 /* Remote Label */
11005 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
11006 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
11007 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
11008 &bos);
d62a17ae 11009
05864da7
DS
11010 if (json_paths)
11011 json_object_int_add(json_path, "remoteLabel", label);
11012 else
11013 vty_out(vty, " Remote label: %d\n", label);
11014 }
d62a17ae 11015
e496b420
HS
11016 /* Remote SID */
11017 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 11018 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
11019 if (json_paths)
11020 json_object_string_add(json_path, "remoteSid", buf);
11021 else
11022 vty_out(vty, " Remote SID: %s\n", buf);
11023 }
11024
05864da7
DS
11025 /* Label Index */
11026 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11027 if (json_paths)
11028 json_object_int_add(json_path, "labelIndex",
11029 attr->label_index);
11030 else
11031 vty_out(vty, " Label Index: %d\n",
11032 attr->label_index);
11033 }
d62a17ae 11034
05864da7
DS
11035 /* Line 8 display Addpath IDs */
11036 if (path->addpath_rx_id
11037 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11038 if (json_paths) {
11039 json_object_int_add(json_path, "addpathRxId",
11040 path->addpath_rx_id);
d62a17ae 11041
05864da7
DS
11042 /* Keep backwards compatibility with the old API
11043 * by putting TX All's ID in the old field
11044 */
11045 json_object_int_add(
11046 json_path, "addpathTxId",
11047 path->tx_addpath
11048 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11049
05864da7
DS
11050 /* ... but create a specific field for each
11051 * strategy
11052 */
11053 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11054 json_object_int_add(
11055 json_path,
11056 bgp_addpath_names(i)->id_json_name,
11057 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11058 }
05864da7
DS
11059 } else {
11060 vty_out(vty, " AddPath ID: RX %u, ",
11061 path->addpath_rx_id);
d62a17ae 11062
05864da7 11063 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11064 }
05864da7 11065 }
520d5d76 11066
05864da7
DS
11067 /* If we used addpath to TX a non-bestpath we need to display
11068 * "Advertised to" on a path-by-path basis
11069 */
11070 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11071 first = 1;
dcc68b5e 11072
05864da7
DS
11073 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11074 addpath_capable =
11075 bgp_addpath_encode_tx(peer, afi, safi);
11076 has_adj = bgp_adj_out_lookup(
11077 peer, path->net,
11078 bgp_addpath_id_for_peer(peer, afi, safi,
11079 &path->tx_addpath));
11080
11081 if ((addpath_capable && has_adj)
11082 || (!addpath_capable && has_adj
11083 && CHECK_FLAG(path->flags,
11084 BGP_PATH_SELECTED))) {
11085 if (json_path && !json_adv_to)
11086 json_adv_to = json_object_new_object();
dcc68b5e 11087
05864da7
DS
11088 route_vty_out_advertised_to(
11089 vty, peer, &first,
11090 " Advertised to:", json_adv_to);
d62a17ae 11091 }
11092 }
718e3744 11093
05864da7
DS
11094 if (json_path) {
11095 if (json_adv_to) {
11096 json_object_object_add(
11097 json_path, "advertisedTo", json_adv_to);
d62a17ae 11098 }
05864da7
DS
11099 } else {
11100 if (!first) {
11101 vty_out(vty, "\n");
d62a17ae 11102 }
11103 }
05864da7 11104 }
b05a1c8b 11105
05864da7 11106 /* Line 9 display Uptime */
083ec940 11107 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11108 if (json_paths) {
11109 json_last_update = json_object_new_object();
11110 json_object_int_add(json_last_update, "epoch", tbuf);
11111 json_object_string_add(json_last_update, "string",
11112 ctime(&tbuf));
11113 json_object_object_add(json_path, "lastUpdate",
11114 json_last_update);
11115 } else
11116 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11117
05864da7
DS
11118 /* Line 10 display PMSI tunnel attribute, if present */
11119 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11120 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11121 bgp_attr_get_pmsi_tnl_type(attr),
11122 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11123
05864da7
DS
11124 if (json_paths) {
11125 json_pmsi = json_object_new_object();
11126 json_object_string_add(json_pmsi, "tunnelType", str);
11127 json_object_int_add(json_pmsi, "label",
11128 label2vni(&attr->label));
11129 json_object_object_add(json_path, "pmsi", json_pmsi);
11130 } else
11131 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11132 str, label2vni(&attr->label));
d62a17ae 11133 }
f1aa5d8a 11134
848e8cf6
DA
11135 if (path->peer->t_gr_restart &&
11136 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11137 unsigned long gr_remaining =
11138 thread_timer_remain_second(path->peer->t_gr_restart);
11139
11140 if (json_paths) {
11141 json_object_int_add(json_path,
11142 "gracefulRestartSecondsRemaining",
11143 gr_remaining);
11144 } else
11145 vty_out(vty,
11146 " Time until Graceful Restart stale route deleted: %lu\n",
11147 gr_remaining);
11148 }
11149
9a706b42
DA
11150 if (path->peer->t_llgr_stale[afi][safi] &&
11151 bgp_attr_get_community(attr) &&
11152 community_include(bgp_attr_get_community(attr),
11153 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11154 unsigned long llgr_remaining = thread_timer_remain_second(
11155 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11156
48ebba04
DA
11157 if (json_paths) {
11158 json_object_int_add(json_path, "llgrSecondsRemaining",
11159 llgr_remaining);
11160 } else
11161 vty_out(vty,
11162 " Time until Long-lived stale route deleted: %lu\n",
11163 llgr_remaining);
11164 }
11165
92269aa2
DS
11166 /* Output some debug about internal state of the dest flags */
11167 if (json_paths) {
11168 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11169 json_object_boolean_true_add(json_path, "processScheduled");
11170 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11171 json_object_boolean_true_add(json_path, "userCleared");
11172 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11173 json_object_boolean_true_add(json_path, "labelChanged");
11174 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11175 json_object_boolean_true_add(json_path, "registeredForLabel");
11176 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11177 json_object_boolean_true_add(json_path, "selectDefered");
11178 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11179 json_object_boolean_true_add(json_path, "fibInstalled");
11180 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11181 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11182
d62a17ae 11183 if (json_nexthop_global || json_nexthop_ll) {
11184 json_nexthops = json_object_new_array();
f1aa5d8a 11185
d62a17ae 11186 if (json_nexthop_global)
11187 json_object_array_add(json_nexthops,
11188 json_nexthop_global);
f1aa5d8a 11189
d62a17ae 11190 if (json_nexthop_ll)
11191 json_object_array_add(json_nexthops,
11192 json_nexthop_ll);
f1aa5d8a 11193
d62a17ae 11194 json_object_object_add(json_path, "nexthops",
11195 json_nexthops);
11196 }
11197
11198 json_object_object_add(json_path, "peer", json_peer);
11199 json_object_array_add(json_paths, json_path);
05864da7 11200 }
b366b518
BB
11201}
11202
96ade3ed 11203#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11204#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11205#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11206
a4d82a8a 11207static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11208 afi_t afi, safi_t safi, enum bgp_show_type type,
11209 bool use_json);
7f323236
DW
11210static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11211 const char *comstr, int exact, afi_t afi,
96c81f66 11212 safi_t safi, uint16_t show_flags);
d62a17ae 11213
1ae44dfc 11214static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11215 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11216 void *output_arg, const char *rd, int is_last,
96f3485c 11217 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11218 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11219 enum rpki_states rpki_target_state)
d62a17ae 11220{
40381db7 11221 struct bgp_path_info *pi;
9bcb3eef 11222 struct bgp_dest *dest;
2aad8c42
MS
11223 bool header = true;
11224 bool json_detail_header = false;
d62a17ae 11225 int display;
1ae44dfc
LB
11226 unsigned long output_count = 0;
11227 unsigned long total_count = 0;
d62a17ae 11228 struct prefix *p;
d62a17ae 11229 json_object *json_paths = NULL;
11230 int first = 1;
96f3485c
MK
11231 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11232 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11233 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11234
1ae44dfc 11235 if (output_cum && *output_cum != 0)
2aad8c42 11236 header = false;
1ae44dfc 11237
9386b588 11238 if (use_json && !*json_header_depth) {
96f3485c
MK
11239 if (all)
11240 *json_header_depth = 1;
11241 else {
11242 vty_out(vty, "{\n");
11243 *json_header_depth = 2;
11244 }
11245
d62a17ae 11246 vty_out(vty,
23d0a753
DA
11247 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11248 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11249 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11250 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11251 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11252 ? VRF_DEFAULT_NAME
11253 : bgp->name,
11254 table->version, &bgp->router_id,
01eced22 11255 bgp->default_local_pref, bgp->as);
9386b588 11256 if (rd) {
445c2480 11257 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11258 ++*json_header_depth;
11259 }
d62a17ae 11260 }
718e3744 11261
445c2480
DS
11262 if (use_json && rd) {
11263 vty_out(vty, " \"%s\" : { ", rd);
11264 }
11265
2aad8c42
MS
11266 /* Check for 'json detail', where we need header output once per dest */
11267 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11268 type != bgp_show_type_dampend_paths &&
11269 type != bgp_show_type_damp_neighbor &&
11270 type != bgp_show_type_flap_statistics &&
11271 type != bgp_show_type_flap_neighbor)
11272 json_detail_header = true;
11273
d62a17ae 11274 /* Start processing of routes. */
9bcb3eef
DS
11275 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11276 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11277 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11278 bool json_detail = json_detail_header;
b54892e0 11279
9bcb3eef 11280 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11281 if (pi == NULL)
98ce9a06 11282 continue;
d62a17ae 11283
98ce9a06 11284 display = 0;
98ce9a06
DS
11285 if (use_json)
11286 json_paths = json_object_new_array();
11287 else
11288 json_paths = NULL;
d62a17ae 11289
6f94b685 11290 for (; pi; pi = pi->next) {
9a706b42
DA
11291 struct community *picomm = NULL;
11292
11293 picomm = bgp_attr_get_community(pi->attr);
11294
98ce9a06 11295 total_count++;
1e2ce4f1 11296
7d3cae70
DA
11297 if (type == bgp_show_type_prefix_version) {
11298 uint32_t version =
11299 strtoul(output_arg, NULL, 10);
11300 if (dest->version < version)
11301 continue;
11302 }
11303
a70a28a5
DA
11304 if (type == bgp_show_type_community_alias) {
11305 char *alias = output_arg;
11306 char **communities;
11307 int num;
11308 bool found = false;
11309
9a706b42
DA
11310 if (picomm) {
11311 frrstr_split(picomm->str, " ",
11312 &communities, &num);
a70a28a5
DA
11313 for (int i = 0; i < num; i++) {
11314 const char *com2alias =
11315 bgp_community2alias(
11316 communities[i]);
cd9cc0e6
IR
11317 if (!found
11318 && strcmp(alias, com2alias)
11319 == 0)
a70a28a5 11320 found = true;
cd9cc0e6
IR
11321 XFREE(MTYPE_TMP,
11322 communities[i]);
a70a28a5 11323 }
cd9cc0e6 11324 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11325 }
11326
1bcf3a96
DA
11327 if (!found &&
11328 bgp_attr_get_lcommunity(pi->attr)) {
11329 frrstr_split(bgp_attr_get_lcommunity(
11330 pi->attr)
11331 ->str,
a70a28a5
DA
11332 " ", &communities, &num);
11333 for (int i = 0; i < num; i++) {
11334 const char *com2alias =
11335 bgp_community2alias(
11336 communities[i]);
cd9cc0e6
IR
11337 if (!found
11338 && strcmp(alias, com2alias)
11339 == 0)
a70a28a5 11340 found = true;
cd9cc0e6
IR
11341 XFREE(MTYPE_TMP,
11342 communities[i]);
a70a28a5 11343 }
cd9cc0e6 11344 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11345 }
11346
11347 if (!found)
11348 continue;
11349 }
11350
1e2ce4f1
DS
11351 if (type == bgp_show_type_rpki) {
11352 if (dest_p->family == AF_INET
11353 || dest_p->family == AF_INET6)
4027d19b 11354 rpki_curr_state = hook_call(
1e2ce4f1
DS
11355 bgp_rpki_prefix_status,
11356 pi->peer, pi->attr, dest_p);
4027d19b
DS
11357 if (rpki_target_state != RPKI_NOT_BEING_USED
11358 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11359 continue;
11360 }
11361
98ce9a06
DS
11362 if (type == bgp_show_type_flap_statistics
11363 || type == bgp_show_type_flap_neighbor
11364 || type == bgp_show_type_dampend_paths
11365 || type == bgp_show_type_damp_neighbor) {
40381db7 11366 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11367 continue;
11368 }
11369 if (type == bgp_show_type_regexp) {
11370 regex_t *regex = output_arg;
d62a17ae 11371
40381db7 11372 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11373 == REG_NOMATCH)
11374 continue;
11375 }
11376 if (type == bgp_show_type_prefix_list) {
11377 struct prefix_list *plist = output_arg;
d62a17ae 11378
9bcb3eef 11379 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11380 != PREFIX_PERMIT)
11381 continue;
11382 }
ed126382
DA
11383 if (type == bgp_show_type_access_list) {
11384 struct access_list *alist = output_arg;
11385
11386 if (access_list_apply(alist, dest_p) !=
11387 FILTER_PERMIT)
11388 continue;
11389 }
98ce9a06
DS
11390 if (type == bgp_show_type_filter_list) {
11391 struct as_list *as_list = output_arg;
d62a17ae 11392
40381db7 11393 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11394 != AS_FILTER_PERMIT)
11395 continue;
11396 }
11397 if (type == bgp_show_type_route_map) {
11398 struct route_map *rmap = output_arg;
9b6d8fcf 11399 struct bgp_path_info path;
636632c3
DA
11400 struct bgp_path_info_extra extra;
11401 struct attr dummy_attr = {};
b68885f9 11402 route_map_result_t ret;
d62a17ae 11403
6f4f49b2 11404 dummy_attr = *pi->attr;
d62a17ae 11405
636632c3
DA
11406 prep_for_rmap_apply(&path, &extra, dest, pi,
11407 pi->peer, &dummy_attr);
d62a17ae 11408
1782514f 11409 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11410 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11411 if (ret == RMAP_DENYMATCH)
11412 continue;
11413 }
11414 if (type == bgp_show_type_neighbor
11415 || type == bgp_show_type_flap_neighbor
11416 || type == bgp_show_type_damp_neighbor) {
11417 union sockunion *su = output_arg;
11418
40381db7
DS
11419 if (pi->peer == NULL
11420 || pi->peer->su_remote == NULL
11421 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11422 continue;
11423 }
11424 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11425 uint32_t destination;
d62a17ae 11426
9bcb3eef 11427 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11428 if (IN_CLASSC(destination)
9bcb3eef 11429 && dest_p->prefixlen == 24)
98ce9a06
DS
11430 continue;
11431 if (IN_CLASSB(destination)
9bcb3eef 11432 && dest_p->prefixlen == 16)
98ce9a06
DS
11433 continue;
11434 if (IN_CLASSA(destination)
9bcb3eef 11435 && dest_p->prefixlen == 8)
98ce9a06
DS
11436 continue;
11437 }
11438 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11439 p = output_arg;
9bcb3eef 11440 if (!prefix_match(p, dest_p))
98ce9a06
DS
11441 continue;
11442 }
11443 if (type == bgp_show_type_community_all) {
9a706b42 11444 if (!picomm)
98ce9a06
DS
11445 continue;
11446 }
11447 if (type == bgp_show_type_community) {
11448 struct community *com = output_arg;
d62a17ae 11449
9a706b42 11450 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11451 continue;
11452 }
11453 if (type == bgp_show_type_community_exact) {
11454 struct community *com = output_arg;
d62a17ae 11455
9a706b42 11456 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11457 continue;
11458 }
11459 if (type == bgp_show_type_community_list) {
11460 struct community_list *list = output_arg;
d62a17ae 11461
9a706b42 11462 if (!community_list_match(picomm, list))
98ce9a06
DS
11463 continue;
11464 }
a4d82a8a 11465 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11466 struct community_list *list = output_arg;
d62a17ae 11467
9a706b42 11468 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11469 continue;
11470 }
11471 if (type == bgp_show_type_lcommunity) {
11472 struct lcommunity *lcom = output_arg;
d62a17ae 11473
1bcf3a96
DA
11474 if (!bgp_attr_get_lcommunity(pi->attr) ||
11475 !lcommunity_match(
11476 bgp_attr_get_lcommunity(pi->attr),
11477 lcom))
98ce9a06
DS
11478 continue;
11479 }
36a206db 11480
11481 if (type == bgp_show_type_lcommunity_exact) {
11482 struct lcommunity *lcom = output_arg;
11483
1bcf3a96
DA
11484 if (!bgp_attr_get_lcommunity(pi->attr) ||
11485 !lcommunity_cmp(
11486 bgp_attr_get_lcommunity(pi->attr),
11487 lcom))
36a206db 11488 continue;
11489 }
98ce9a06
DS
11490 if (type == bgp_show_type_lcommunity_list) {
11491 struct community_list *list = output_arg;
d62a17ae 11492
1bcf3a96
DA
11493 if (!lcommunity_list_match(
11494 bgp_attr_get_lcommunity(pi->attr),
11495 list))
98ce9a06
DS
11496 continue;
11497 }
36a206db 11498 if (type
11499 == bgp_show_type_lcommunity_list_exact) {
11500 struct community_list *list = output_arg;
11501
11502 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11503 bgp_attr_get_lcommunity(pi->attr),
11504 list))
36a206db 11505 continue;
11506 }
98ce9a06 11507 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11508 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11509 continue;
11510 }
11511 if (type == bgp_show_type_dampend_paths
11512 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11513 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11514 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11515 continue;
11516 }
11517
11518 if (!use_json && header) {
23d0a753
DA
11519 vty_out(vty,
11520 "BGP table version is %" PRIu64
11521 ", local router ID is %pI4, vrf id ",
11522 table->version, &bgp->router_id);
9df8b37c
PZ
11523 if (bgp->vrf_id == VRF_UNKNOWN)
11524 vty_out(vty, "%s", VRFID_NONE_STR);
11525 else
11526 vty_out(vty, "%u", bgp->vrf_id);
11527 vty_out(vty, "\n");
01eced22
AD
11528 vty_out(vty, "Default local pref %u, ",
11529 bgp->default_local_pref);
11530 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11531 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11532 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11533 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11534 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11535 if (type == bgp_show_type_dampend_paths
11536 || type == bgp_show_type_damp_neighbor)
98ce9a06 11537 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11538 else if (type == bgp_show_type_flap_statistics
11539 || type == bgp_show_type_flap_neighbor)
98ce9a06 11540 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11541 else
ae248832
MK
11542 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11543 : BGP_SHOW_HEADER));
2aad8c42
MS
11544 header = false;
11545
11546 } else if (json_detail && json_paths != NULL) {
11547 const struct prefix_rd *prd;
11548 json_object *jtemp;
11549
11550 /* Use common detail header, for most types;
11551 * need a json 'object'.
11552 */
11553
11554 jtemp = json_object_new_object();
11555 prd = bgp_rd_from_dest(dest, safi);
11556
11557 route_vty_out_detail_header(
11558 vty, bgp, dest, prd, table->afi,
11559 safi, jtemp);
11560
11561 json_object_array_add(json_paths, jtemp);
11562
11563 json_detail = false;
d62a17ae 11564 }
2aad8c42 11565
98ce9a06
DS
11566 if (rd != NULL && !display && !output_count) {
11567 if (!use_json)
11568 vty_out(vty,
11569 "Route Distinguisher: %s\n",
11570 rd);
d62a17ae 11571 }
98ce9a06
DS
11572 if (type == bgp_show_type_dampend_paths
11573 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11574 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11575 AFI_IP, safi, use_json,
11576 json_paths);
98ce9a06
DS
11577 else if (type == bgp_show_type_flap_statistics
11578 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11579 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11580 AFI_IP, safi, use_json,
11581 json_paths);
f280c93b
DA
11582 else {
11583 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11584 route_vty_out_detail(
11585 vty, bgp, dest, pi,
11586 family2afi(dest_p->family),
11587 safi, RPKI_NOT_BEING_USED,
11588 json_paths);
11589 else
11590 route_vty_out(vty, dest_p, pi, display,
11591 safi, json_paths, wide);
11592 }
98ce9a06 11593 display++;
d62a17ae 11594 }
11595
98ce9a06
DS
11596 if (display) {
11597 output_count++;
11598 if (!use_json)
11599 continue;
11600
625d2931 11601 /* encode prefix */
9bcb3eef 11602 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11603 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11604
1840384b 11605
b54892e0
DS
11606 bgp_fs_nlri_get_string(
11607 (unsigned char *)
9bcb3eef
DS
11608 dest_p->u.prefix_flowspec.ptr,
11609 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11610 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11611 family2afi(dest_p->u
11612 .prefix_flowspec.family));
625d2931 11613 if (first)
b54892e0 11614 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11615 dest_p->u.prefix_flowspec
b54892e0 11616 .prefixlen);
625d2931 11617 else
b54892e0 11618 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11619 dest_p->u.prefix_flowspec
b54892e0 11620 .prefixlen);
625d2931 11621 } else {
625d2931 11622 if (first)
1b78780b 11623 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11624 else
1b78780b 11625 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11626 }
3757f964 11627 vty_json(vty, json_paths);
449feb8e 11628 json_paths = NULL;
98ce9a06 11629 first = 0;
1f83ed02
DS
11630 } else
11631 json_object_free(json_paths);
98ce9a06
DS
11632 }
11633
1ae44dfc
LB
11634 if (output_cum) {
11635 output_count += *output_cum;
11636 *output_cum = output_count;
11637 }
11638 if (total_cum) {
11639 total_count += *total_cum;
11640 *total_cum = total_count;
11641 }
d62a17ae 11642 if (use_json) {
9386b588 11643 if (rd) {
a4d82a8a 11644 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11645 }
11646 if (is_last) {
a4d82a8a
PZ
11647 unsigned long i;
11648 for (i = 0; i < *json_header_depth; ++i)
11649 vty_out(vty, " } ");
96f3485c
MK
11650 if (!all)
11651 vty_out(vty, "\n");
9386b588 11652 }
d62a17ae 11653 } else {
1ae44dfc
LB
11654 if (is_last) {
11655 /* No route is displayed */
11656 if (output_count == 0) {
11657 if (type == bgp_show_type_normal)
11658 vty_out(vty,
11659 "No BGP prefixes displayed, %ld exist\n",
11660 total_count);
11661 } else
d62a17ae 11662 vty_out(vty,
1ae44dfc
LB
11663 "\nDisplayed %ld routes and %ld total paths\n",
11664 output_count, total_count);
11665 }
d62a17ae 11666 }
718e3744 11667
d62a17ae 11668 return CMD_SUCCESS;
718e3744 11669}
11670
1ae44dfc
LB
11671int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11672 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11673 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11674{
9bcb3eef 11675 struct bgp_dest *dest, *next;
1ae44dfc
LB
11676 unsigned long output_cum = 0;
11677 unsigned long total_cum = 0;
9386b588 11678 unsigned long json_header_depth = 0;
67009e22 11679 struct bgp_table *itable;
0136788c 11680 bool show_msg;
96c81f66 11681 uint16_t show_flags = 0;
0136788c
LB
11682
11683 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11684
96f3485c
MK
11685 if (use_json)
11686 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11687
9bcb3eef
DS
11688 for (dest = bgp_table_top(table); dest; dest = next) {
11689 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11690
9bcb3eef
DS
11691 next = bgp_route_next(dest);
11692 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11693 continue;
67009e22 11694
9bcb3eef 11695 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11696 if (itable != NULL) {
1ae44dfc 11697 struct prefix_rd prd;
06b9f471 11698 char rd[RD_ADDRSTRLEN];
1ae44dfc 11699
9bcb3eef 11700 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11701 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11702 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11703 rd, next == NULL, &output_cum,
11704 &total_cum, &json_header_depth,
1e2ce4f1 11705 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11706 if (next == NULL)
11707 show_msg = false;
1ae44dfc
LB
11708 }
11709 }
0136788c
LB
11710 if (show_msg) {
11711 if (output_cum == 0)
11712 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11713 total_cum);
11714 else
11715 vty_out(vty,
11716 "\nDisplayed %ld routes and %ld total paths\n",
11717 output_cum, total_cum);
11718 }
1ae44dfc
LB
11719 return CMD_SUCCESS;
11720}
2aad8c42 11721
d62a17ae 11722static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11723 enum bgp_show_type type, void *output_arg,
96c81f66 11724 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11725{
d62a17ae 11726 struct bgp_table *table;
9386b588 11727 unsigned long json_header_depth = 0;
96f3485c 11728 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11729
d62a17ae 11730 if (bgp == NULL) {
11731 bgp = bgp_get_default();
11732 }
fee0f4c6 11733
d62a17ae 11734 if (bgp == NULL) {
11735 if (!use_json)
11736 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11737 else
11738 vty_out(vty, "{}\n");
d62a17ae 11739 return CMD_WARNING;
11740 }
4dd6177e 11741
cd8c2a27
MS
11742 /* Labeled-unicast routes live in the unicast table. */
11743 if (safi == SAFI_LABELED_UNICAST)
11744 safi = SAFI_UNICAST;
11745
1ae44dfc 11746 table = bgp->rib[afi][safi];
d62a17ae 11747 /* use MPLS and ENCAP specific shows until they are merged */
11748 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11749 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11750 output_arg, use_json);
d62a17ae 11751 }
dba3c1d3
PG
11752
11753 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11754 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11755 output_arg, use_json,
11756 1, NULL, NULL);
11757 }
fee0f4c6 11758
96f3485c 11759 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11760 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11761 rpki_target_state);
fee0f4c6 11762}
11763
d62a17ae 11764static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11765 safi_t safi, uint16_t show_flags)
f186de26 11766{
d62a17ae 11767 struct listnode *node, *nnode;
11768 struct bgp *bgp;
11769 int is_first = 1;
9f049418 11770 bool route_output = false;
96f3485c 11771 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11772
d62a17ae 11773 if (use_json)
11774 vty_out(vty, "{\n");
9f689658 11775
d62a17ae 11776 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11777 route_output = true;
d62a17ae 11778 if (use_json) {
11779 if (!is_first)
11780 vty_out(vty, ",\n");
11781 else
11782 is_first = 0;
11783
11784 vty_out(vty, "\"%s\":",
11785 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11786 ? VRF_DEFAULT_NAME
d62a17ae 11787 : bgp->name);
11788 } else {
11789 vty_out(vty, "\nInstance %s:\n",
11790 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11791 ? VRF_DEFAULT_NAME
d62a17ae 11792 : bgp->name);
11793 }
11794 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11795 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11796 }
9f689658 11797
d62a17ae 11798 if (use_json)
11799 vty_out(vty, "}\n");
9f049418
DS
11800 else if (!route_output)
11801 vty_out(vty, "%% BGP instance not found\n");
f186de26 11802}
11803
718e3744 11804/* Header of detailed BGP route information */
d62a17ae 11805void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11806 struct bgp_dest *dest,
11807 const struct prefix_rd *prd,
d62a17ae 11808 afi_t afi, safi_t safi, json_object *json)
11809{
40381db7 11810 struct bgp_path_info *pi;
b54892e0 11811 const struct prefix *p;
d62a17ae 11812 struct peer *peer;
11813 struct listnode *node, *nnode;
06b9f471 11814 char buf1[RD_ADDRSTRLEN];
d62a17ae 11815 int count = 0;
11816 int best = 0;
11817 int suppress = 0;
c5f1e1b2
C
11818 int accept_own = 0;
11819 int route_filter_translated_v4 = 0;
11820 int route_filter_v4 = 0;
11821 int route_filter_translated_v6 = 0;
11822 int route_filter_v6 = 0;
11823 int llgr_stale = 0;
11824 int no_llgr = 0;
11825 int accept_own_nexthop = 0;
11826 int blackhole = 0;
d62a17ae 11827 int no_export = 0;
11828 int no_advertise = 0;
11829 int local_as = 0;
c5f1e1b2 11830 int no_peer = 0;
d62a17ae 11831 int first = 1;
11832 int has_valid_label = 0;
11833 mpls_label_t label = 0;
11834 json_object *json_adv_to = NULL;
67f67ba4
DA
11835 uint32_t ttl = 0;
11836 uint32_t bos = 0;
11837 uint32_t exp = 0;
9bedbb1e 11838
67f67ba4 11839 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11840
67f67ba4
DA
11841 p = bgp_dest_get_prefix(dest);
11842 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11843
44c69747 11844 if (safi == SAFI_EVPN) {
44c69747 11845 if (!json) {
2dbe669b 11846 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11847 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11848 : "",
2dbe669b 11849 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11850 } else {
11851 json_object_string_add(json, "rd",
11852 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11853 "");
11854 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11855 }
11856 } else {
11857 if (!json) {
9119ef3a
DA
11858 vty_out(vty,
11859 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11860 "\n",
d62a17ae 11861 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11862 ? prefix_rd2str(prd, buf1,
11863 sizeof(buf1))
11864 : ""),
9119ef3a
DA
11865 safi == SAFI_MPLS_VPN ? ":" : "", p,
11866 dest->version);
cd1964ff 11867
9119ef3a 11868 } else {
67d7e256 11869 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11870 json_object_int_add(json, "version", dest->version);
11871
11872 }
44c69747
LK
11873 }
11874
11875 if (has_valid_label) {
11876 if (json)
11877 json_object_int_add(json, "localLabel", label);
11878 else
d62a17ae 11879 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11880 }
11881
11882 if (!json)
d62a17ae 11883 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11884 vty_out(vty, "not allocated\n");
718e3744 11885
9bcb3eef 11886 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11887 struct community *picomm = NULL;
11888
11889 picomm = bgp_attr_get_community(pi->attr);
11890
d62a17ae 11891 count++;
40381db7 11892 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11893 best = count;
4056a5f6 11894 if (bgp_path_suppressed(pi))
d62a17ae 11895 suppress = 1;
cee9c031 11896
9a706b42 11897 if (!picomm)
cee9c031
QY
11898 continue;
11899
11900 no_advertise += community_include(
9a706b42
DA
11901 picomm, COMMUNITY_NO_ADVERTISE);
11902 no_export +=
11903 community_include(picomm, COMMUNITY_NO_EXPORT);
11904 local_as +=
11905 community_include(picomm, COMMUNITY_LOCAL_AS);
11906 accept_own +=
11907 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11908 route_filter_translated_v4 += community_include(
9a706b42 11909 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11910 route_filter_translated_v6 += community_include(
9a706b42 11911 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11912 route_filter_v4 += community_include(
9a706b42 11913 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11914 route_filter_v6 += community_include(
9a706b42
DA
11915 picomm, COMMUNITY_ROUTE_FILTER_v6);
11916 llgr_stale +=
11917 community_include(picomm, COMMUNITY_LLGR_STALE);
11918 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11919 accept_own_nexthop += community_include(
11920 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11921 blackhole +=
11922 community_include(picomm, COMMUNITY_BLACKHOLE);
11923 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11924 }
718e3744 11925 }
718e3744 11926
d62a17ae 11927 if (!json) {
11928 vty_out(vty, "Paths: (%d available", count);
11929 if (best) {
11930 vty_out(vty, ", best #%d", best);
b84060bb
PG
11931 if (safi == SAFI_UNICAST) {
11932 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11933 vty_out(vty, ", table %s",
11934 VRF_DEFAULT_NAME);
11935 else
11936 vty_out(vty, ", vrf %s",
11937 bgp->name);
11938 }
d62a17ae 11939 } else
11940 vty_out(vty, ", no best path");
11941
c5f1e1b2
C
11942 if (accept_own)
11943 vty_out(vty,
11944 ", accept own local route exported and imported in different VRF");
11945 else if (route_filter_translated_v4)
11946 vty_out(vty,
11947 ", mark translated RTs for VPNv4 route filtering");
11948 else if (route_filter_v4)
11949 vty_out(vty,
11950 ", attach RT as-is for VPNv4 route filtering");
11951 else if (route_filter_translated_v6)
11952 vty_out(vty,
11953 ", mark translated RTs for VPNv6 route filtering");
11954 else if (route_filter_v6)
11955 vty_out(vty,
11956 ", attach RT as-is for VPNv6 route filtering");
11957 else if (llgr_stale)
11958 vty_out(vty,
1479ed2f 11959 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11960 else if (no_llgr)
11961 vty_out(vty,
11962 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11963 else if (accept_own_nexthop)
11964 vty_out(vty,
11965 ", accept local nexthop");
11966 else if (blackhole)
11967 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11968 else if (no_export)
11969 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11970 else if (no_advertise)
11971 vty_out(vty, ", not advertised to any peer");
d62a17ae 11972 else if (local_as)
11973 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11974 else if (no_peer)
11975 vty_out(vty,
11976 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11977
11978 if (suppress)
11979 vty_out(vty,
11980 ", Advertisements suppressed by an aggregate.");
11981 vty_out(vty, ")\n");
11982 }
718e3744 11983
d62a17ae 11984 /* If we are not using addpath then we can display Advertised to and
11985 * that will
11986 * show what peers we advertised the bestpath to. If we are using
11987 * addpath
11988 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11989 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11990 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11991 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11992 if (json && !json_adv_to)
11993 json_adv_to = json_object_new_object();
11994
11995 route_vty_out_advertised_to(
11996 vty, peer, &first,
11997 " Advertised to non peer-group peers:\n ",
11998 json_adv_to);
11999 }
12000 }
12001
12002 if (json) {
12003 if (json_adv_to) {
12004 json_object_object_add(json, "advertisedTo",
12005 json_adv_to);
12006 }
12007 } else {
12008 if (first)
12009 vty_out(vty, " Not advertised to any peer");
12010 vty_out(vty, "\n");
12011 }
12012 }
718e3744 12013}
12014
edfee30d 12015static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12016 struct bgp_dest *bgp_node, struct vty *vty,
12017 struct bgp *bgp, afi_t afi, safi_t safi,
12018 json_object *json, enum bgp_path_type pathtype,
4027d19b 12019 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12020{
12021 struct bgp_path_info *pi;
12022 int header = 1;
44c69747
LK
12023 json_object *json_header = NULL;
12024 json_object *json_paths = NULL;
4933eaaf 12025 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12026
9bcb3eef 12027 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12028 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12029
12030 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12031 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12032 pi->peer, pi->attr, p);
4933eaaf 12033
4027d19b
DS
12034 if (rpki_target_state != RPKI_NOT_BEING_USED
12035 && rpki_curr_state != rpki_target_state)
4933eaaf 12036 continue;
44c69747
LK
12037
12038 if (json && !json_paths) {
12039 /* Instantiate json_paths only if path is valid */
12040 json_paths = json_object_new_array();
c4f64ea9 12041 if (pfx_rd)
44c69747 12042 json_header = json_object_new_object();
c4f64ea9 12043 else
44c69747
LK
12044 json_header = json;
12045 }
12046
12047 if (header) {
12048 route_vty_out_detail_header(
12049 vty, bgp, bgp_node, pfx_rd,
12050 AFI_IP, safi, json_header);
12051 header = 0;
12052 }
12053 (*display)++;
12054
12055 if (pathtype == BGP_PATH_SHOW_ALL
12056 || (pathtype == BGP_PATH_SHOW_BESTPATH
12057 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12058 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12059 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12060 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 12061 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 12062 safi, rpki_curr_state, json_paths);
44c69747
LK
12063 }
12064
12065 if (json && json_paths) {
12066 json_object_object_add(json_header, "paths", json_paths);
12067
12068 if (pfx_rd)
c4f64ea9
DA
12069 json_object_object_addf(json, json_header, "%pRD",
12070 pfx_rd);
44c69747
LK
12071 }
12072}
12073
2aad8c42
MS
12074/*
12075 * Return rd based on safi
12076 */
46dbf9d0
DA
12077const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12078 safi_t safi)
2aad8c42
MS
12079{
12080 switch (safi) {
12081 case SAFI_MPLS_VPN:
12082 case SAFI_ENCAP:
12083 case SAFI_EVPN:
12084 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12085 default:
12086 return NULL;
2aad8c42
MS
12087 }
12088}
12089
718e3744 12090/* Display specified route of BGP table. */
d62a17ae 12091static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12092 struct bgp_table *rib, const char *ip_str,
12093 afi_t afi, safi_t safi,
4027d19b 12094 enum rpki_states rpki_target_state,
d62a17ae 12095 struct prefix_rd *prd, int prefix_check,
9f049418 12096 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12097{
12098 int ret;
d62a17ae 12099 int display = 0;
12100 struct prefix match;
9bcb3eef
DS
12101 struct bgp_dest *dest;
12102 struct bgp_dest *rm;
d62a17ae 12103 struct bgp_table *table;
12104 json_object *json = NULL;
12105 json_object *json_paths = NULL;
12106
12107 /* Check IP address argument. */
12108 ret = str2prefix(ip_str, &match);
12109 if (!ret) {
12110 vty_out(vty, "address is malformed\n");
12111 return CMD_WARNING;
12112 }
718e3744 12113
d62a17ae 12114 match.family = afi2family(afi);
b05a1c8b 12115
44c69747 12116 if (use_json)
d62a17ae 12117 json = json_object_new_object();
718e3744 12118
44c69747 12119 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12120 for (dest = bgp_table_top(rib); dest;
12121 dest = bgp_route_next(dest)) {
12122 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12123
9bcb3eef 12124 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12125 continue;
9bcb3eef 12126 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12127 if (!table)
ea47320b 12128 continue;
d62a17ae 12129
4953391b
DA
12130 rm = bgp_node_match(table, &match);
12131 if (rm == NULL)
ea47320b 12132 continue;
d62a17ae 12133
9bcb3eef 12134 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12135 if (prefix_check
b54892e0 12136 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12137 bgp_dest_unlock_node(rm);
ea47320b
DL
12138 continue;
12139 }
d62a17ae 12140
9bcb3eef 12141 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12142 bgp, afi, safi, json, pathtype,
4027d19b 12143 &display, rpki_target_state);
44c69747 12144
9bcb3eef 12145 bgp_dest_unlock_node(rm);
44c69747
LK
12146 }
12147 } else if (safi == SAFI_EVPN) {
9bcb3eef 12148 struct bgp_dest *longest_pfx;
cded3b72 12149 bool is_exact_pfxlen_match = false;
44c69747 12150
9bcb3eef
DS
12151 for (dest = bgp_table_top(rib); dest;
12152 dest = bgp_route_next(dest)) {
12153 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12154
9bcb3eef 12155 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12156 continue;
9bcb3eef 12157 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12158 if (!table)
12159 continue;
12160
12161 longest_pfx = NULL;
cded3b72 12162 is_exact_pfxlen_match = false;
44c69747
LK
12163 /*
12164 * Search through all the prefixes for a match. The
12165 * pfx's are enumerated in ascending order of pfxlens.
12166 * So, the last pfx match is the longest match. Set
12167 * is_exact_pfxlen_match when we get exact pfxlen match
12168 */
12169 for (rm = bgp_table_top(table); rm;
12170 rm = bgp_route_next(rm)) {
b54892e0 12171 const struct prefix *rm_p =
9bcb3eef 12172 bgp_dest_get_prefix(rm);
44c69747
LK
12173 /*
12174 * Get prefixlen of the ip-prefix within type5
12175 * evpn route
12176 */
b54892e0
DS
12177 if (evpn_type5_prefix_match(rm_p, &match)
12178 && rm->info) {
44c69747
LK
12179 longest_pfx = rm;
12180 int type5_pfxlen =
b54892e0
DS
12181 bgp_evpn_get_type5_prefixlen(
12182 rm_p);
44c69747 12183 if (type5_pfxlen == match.prefixlen) {
cded3b72 12184 is_exact_pfxlen_match = true;
9bcb3eef 12185 bgp_dest_unlock_node(rm);
44c69747
LK
12186 break;
12187 }
d62a17ae 12188 }
12189 }
ea47320b 12190
44c69747
LK
12191 if (!longest_pfx)
12192 continue;
12193
12194 if (prefix_check && !is_exact_pfxlen_match)
12195 continue;
12196
12197 rm = longest_pfx;
9bcb3eef 12198 bgp_dest_lock_node(rm);
44c69747 12199
9bcb3eef 12200 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12201 bgp, afi, safi, json, pathtype,
4027d19b 12202 &display, rpki_target_state);
44c69747 12203
9bcb3eef 12204 bgp_dest_unlock_node(rm);
d62a17ae 12205 }
98a9dbc7 12206 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12207 if (use_json)
12208 json_paths = json_object_new_array();
12209
63a0b7a9
PG
12210 display = bgp_flowspec_display_match_per_ip(afi, rib,
12211 &match, prefix_check,
12212 vty,
12213 use_json,
12214 json_paths);
d5f20468
SP
12215 if (use_json) {
12216 if (display)
12217 json_object_object_add(json, "paths",
12218 json_paths);
12219 else
12220 json_object_free(json_paths);
12221 }
d62a17ae 12222 } else {
4953391b
DA
12223 dest = bgp_node_match(rib, &match);
12224 if (dest != NULL) {
9bcb3eef 12225 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12226 if (!prefix_check
9bcb3eef
DS
12227 || dest_p->prefixlen == match.prefixlen) {
12228 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12229 safi, json, pathtype,
4027d19b 12230 &display, rpki_target_state);
d62a17ae 12231 }
12232
9bcb3eef 12233 bgp_dest_unlock_node(dest);
d62a17ae 12234 }
12235 }
e5eee9af 12236
d62a17ae 12237 if (use_json) {
75eeda93 12238 vty_json(vty, json);
d62a17ae 12239 } else {
12240 if (!display) {
12241 vty_out(vty, "%% Network not in table\n");
12242 return CMD_WARNING;
12243 }
12244 }
b05a1c8b 12245
d62a17ae 12246 return CMD_SUCCESS;
718e3744 12247}
12248
fee0f4c6 12249/* Display specified route of Main RIB */
d62a17ae 12250static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12251 afi_t afi, safi_t safi, struct prefix_rd *prd,
12252 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12253 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12254{
9b86009a 12255 if (!bgp) {
d62a17ae 12256 bgp = bgp_get_default();
9b86009a
RW
12257 if (!bgp) {
12258 if (!use_json)
12259 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12260 else
12261 vty_out(vty, "{}\n");
9b86009a
RW
12262 return CMD_WARNING;
12263 }
12264 }
d62a17ae 12265
12266 /* labeled-unicast routes live in the unicast table */
12267 if (safi == SAFI_LABELED_UNICAST)
12268 safi = SAFI_UNICAST;
12269
12270 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12271 afi, safi, rpki_target_state, prd,
8aa22bbb 12272 prefix_check, pathtype, use_json);
d62a17ae 12273}
12274
12275static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12276 struct cmd_token **argv, bool exact, afi_t afi,
12277 safi_t safi, bool uj)
d62a17ae 12278{
12279 struct lcommunity *lcom;
12280 struct buffer *b;
12281 int i;
12282 char *str;
12283 int first = 0;
96c81f66 12284 uint16_t show_flags = 0;
4f28b2b5 12285 int ret;
96f3485c
MK
12286
12287 if (uj)
12288 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12289
12290 b = buffer_new(1024);
12291 for (i = 0; i < argc; i++) {
12292 if (first)
12293 buffer_putc(b, ' ');
12294 else {
12295 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12296 first = 1;
12297 buffer_putstr(b, argv[i]->arg);
12298 }
12299 }
12300 }
12301 buffer_putc(b, '\0');
57d187bc 12302
d62a17ae 12303 str = buffer_getstr(b);
12304 buffer_free(b);
57d187bc 12305
d62a17ae 12306 lcom = lcommunity_str2com(str);
12307 XFREE(MTYPE_TMP, str);
12308 if (!lcom) {
12309 vty_out(vty, "%% Large-community malformed\n");
12310 return CMD_WARNING;
12311 }
57d187bc 12312
4f28b2b5 12313 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12314 (exact ? bgp_show_type_lcommunity_exact
12315 : bgp_show_type_lcommunity),
12316 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12317
12318 lcommunity_free(&lcom);
12319 return ret;
57d187bc
JS
12320}
12321
d62a17ae 12322static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12323 const char *lcom, bool exact, afi_t afi,
12324 safi_t safi, bool uj)
57d187bc 12325{
d62a17ae 12326 struct community_list *list;
96c81f66 12327 uint16_t show_flags = 0;
96f3485c
MK
12328
12329 if (uj)
12330 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12331
57d187bc 12332
e237b0d2 12333 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12334 LARGE_COMMUNITY_LIST_MASTER);
12335 if (list == NULL) {
12336 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12337 lcom);
12338 return CMD_WARNING;
12339 }
57d187bc 12340
36a206db 12341 return bgp_show(vty, bgp, afi, safi,
12342 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12343 : bgp_show_type_lcommunity_list),
1e2ce4f1 12344 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12345}
12346
52951b63
DS
12347DEFUN (show_ip_bgp_large_community_list,
12348 show_ip_bgp_large_community_list_cmd,
77a3a95e 12349 "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
12350 SHOW_STR
12351 IP_STR
12352 BGP_STR
12353 BGP_INSTANCE_HELP_STR
9bedbb1e 12354 BGP_AFI_HELP_STR
4dd6177e 12355 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12356 "Display routes matching the large-community-list\n"
12357 "large-community-list number\n"
12358 "large-community-list name\n"
36a206db 12359 "Exact match of the large-communities\n"
52951b63
DS
12360 JSON_STR)
12361{
d62a17ae 12362 afi_t afi = AFI_IP6;
12363 safi_t safi = SAFI_UNICAST;
12364 int idx = 0;
36a206db 12365 bool exact_match = 0;
4d678463 12366 struct bgp *bgp = NULL;
9f049418 12367 bool uj = use_json(argc, argv);
d62a17ae 12368
ef3364f0
DA
12369 if (uj)
12370 argc--;
4d678463 12371
ef3364f0
DA
12372 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12373 &bgp, uj);
12374 if (!idx)
12375 return CMD_WARNING;
d62a17ae 12376
12377 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12378
12379 const char *clist_number_or_name = argv[++idx]->arg;
12380
12381 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12382 exact_match = 1;
12383
12384 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12385 exact_match, afi, safi, uj);
52951b63
DS
12386}
12387DEFUN (show_ip_bgp_large_community,
12388 show_ip_bgp_large_community_cmd,
36a206db 12389 "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
12390 SHOW_STR
12391 IP_STR
12392 BGP_STR
12393 BGP_INSTANCE_HELP_STR
9bedbb1e 12394 BGP_AFI_HELP_STR
4dd6177e 12395 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12396 "Display routes matching the large-communities\n"
12397 "List of large-community numbers\n"
36a206db 12398 "Exact match of the large-communities\n"
52951b63
DS
12399 JSON_STR)
12400{
d62a17ae 12401 afi_t afi = AFI_IP6;
12402 safi_t safi = SAFI_UNICAST;
12403 int idx = 0;
36a206db 12404 bool exact_match = 0;
4d678463 12405 struct bgp *bgp = NULL;
9f049418 12406 bool uj = use_json(argc, argv);
96c81f66 12407 uint16_t show_flags = 0;
d62a17ae 12408
96f3485c
MK
12409 if (uj) {
12410 argc--;
12411 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12412 }
4d678463 12413
96f3485c
MK
12414 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12415 &bgp, uj);
12416 if (!idx)
12417 return CMD_WARNING;
d62a17ae 12418
36a206db 12419 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12420 if (argv_find(argv, argc, "exact-match", &idx)) {
12421 argc--;
36a206db 12422 exact_match = 1;
1857760c 12423 }
36a206db 12424 return bgp_show_lcommunity(vty, bgp, argc, argv,
12425 exact_match, afi, safi, uj);
12426 } else
d62a17ae 12427 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12428 bgp_show_type_lcommunity_all, NULL, show_flags,
12429 RPKI_NOT_BEING_USED);
52951b63
DS
12430}
12431
71f1613a
DA
12432static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12433 safi_t safi, struct json_object *json_array);
d62a17ae 12434static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12435 safi_t safi, struct json_object *json);
e01ca200 12436
7b2ff250 12437
9ab0cf58
PG
12438DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12440 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12441 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12442{
12443 bool uj = use_json(argc, argv);
12444 struct bgp *bgp = NULL;
ec76a1d1
DA
12445 safi_t safi = SAFI_UNICAST;
12446 afi_t afi = AFI_IP6;
4265b261 12447 int idx = 0;
6c9d22e2
PG
12448 struct json_object *json_all = NULL;
12449 struct json_object *json_afi_safi = NULL;
4265b261
PG
12450
12451 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12452 &bgp, false);
71f1613a 12453 if (!idx)
4265b261 12454 return CMD_WARNING;
6c9d22e2 12455
4265b261 12456 if (uj)
6c9d22e2 12457 json_all = json_object_new_object();
4265b261 12458
9ab0cf58
PG
12459 FOREACH_AFI_SAFI (afi, safi) {
12460 /*
12461 * So limit output to those afi/safi pairs that
12462 * actually have something interesting in them
12463 */
12464 if (strmatch(get_afi_safi_str(afi, safi, true),
12465 "Unknown")) {
12466 continue;
12467 }
12468 if (uj) {
12469 json_afi_safi = json_object_new_array();
12470 json_object_object_add(
12471 json_all,
12472 get_afi_safi_str(afi, safi, true),
12473 json_afi_safi);
12474 } else {
12475 json_afi_safi = NULL;
6c9d22e2 12476 }
9ab0cf58
PG
12477
12478 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12479 }
6c9d22e2 12480
3757f964
DA
12481 if (uj)
12482 vty_json(vty, json_all);
6c9d22e2 12483
4265b261
PG
12484 return CMD_SUCCESS;
12485}
12486
7b2ff250 12487/* BGP route print out function without JSON */
14718643
PG
12488DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12489 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12490 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12491 SHOW_STR
12492 IP_STR
12493 BGP_STR
12494 BGP_INSTANCE_HELP_STR
12495 L2VPN_HELP_STR
12496 EVPN_HELP_STR
12497 "BGP RIB advertisement statistics\n"
12498 JSON_STR)
12499{
ec76a1d1
DA
12500 afi_t afi = AFI_IP6;
12501 safi_t safi = SAFI_UNICAST;
14718643
PG
12502 struct bgp *bgp = NULL;
12503 int idx = 0, ret;
12504 bool uj = use_json(argc, argv);
12505 struct json_object *json_afi_safi = NULL, *json = NULL;
12506
12507 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12508 &bgp, false);
12509 if (!idx)
12510 return CMD_WARNING;
12511
12512 if (uj)
12513 json_afi_safi = json_object_new_array();
12514 else
12515 json_afi_safi = NULL;
12516
12517 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12518
12519 if (uj) {
12520 json = json_object_new_object();
12521 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12522 json_afi_safi);
3757f964 12523 vty_json(vty, json);
14718643
PG
12524 }
12525 return ret;
12526}
12527
893cccd0 12528/* BGP route print out function without JSON */
9ab0cf58
PG
12529DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12530 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12531 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12532 "]]\
893cccd0 12533 statistics [json]",
9ab0cf58
PG
12534 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12535 BGP_SAFI_WITH_LABEL_HELP_STR
12536 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12537{
ec76a1d1
DA
12538 afi_t afi = AFI_IP6;
12539 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12540 struct bgp *bgp = NULL;
12541 int idx = 0, ret;
12542 bool uj = use_json(argc, argv);
6c9d22e2 12543 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12544
12545 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12546 &bgp, false);
12547 if (!idx)
12548 return CMD_WARNING;
6c9d22e2 12549
893cccd0 12550 if (uj)
6c9d22e2
PG
12551 json_afi_safi = json_object_new_array();
12552 else
12553 json_afi_safi = NULL;
12554
12555 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12556
12557 if (uj) {
12558 json = json_object_new_object();
12559 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12560 json_afi_safi);
3757f964 12561 vty_json(vty, json);
893cccd0
PG
12562 }
12563 return ret;
893cccd0 12564}
7b2ff250 12565
fe0f234d 12566DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12567 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12568 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12569 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12570 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12571 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12572 "Display the entries for all address families\n"
9ab0cf58
PG
12573 "Display detailed information about dampening\n"
12574 "Display detail of configured dampening parameters\n"
fe0f234d 12575 JSON_STR)
718e3744 12576{
d62a17ae 12577 afi_t afi = AFI_IP6;
12578 safi_t safi = SAFI_UNICAST;
d62a17ae 12579 struct bgp *bgp = NULL;
12580 int idx = 0;
96c81f66 12581 uint16_t show_flags = 0;
fe0f234d
RW
12582 bool uj = use_json(argc, argv);
12583
12584 if (uj) {
12585 argc--;
12586 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12587 }
96f3485c
MK
12588
12589 /* [<ipv4|ipv6> [all]] */
12590 if (all) {
12591 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12592 if (argv_find(argv, argc, "ipv4", &idx))
12593 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12594
12595 if (argv_find(argv, argc, "ipv6", &idx))
12596 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12597 }
d62a17ae 12598
12599 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12600 &bgp, false);
d62a17ae 12601 if (!idx)
12602 return CMD_WARNING;
12603
fe0f234d 12604 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12605}
12606
fe0f234d
RW
12607/* BGP route print out function */
12608DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12609 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12610 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12611 "]]\
96f3485c 12612 [all$all]\
cf4898bc
QY
12613 [cidr-only\
12614 |dampening <flap-statistics|dampened-paths>\
12615 |community [AA:NN|local-AS|no-advertise|no-export\
12616 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12617 |accept-own|accept-own-nexthop|route-filter-v6\
12618 |route-filter-v4|route-filter-translated-v6\
12619 |route-filter-translated-v4] [exact-match]\
70799983 12620 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12621 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12622 |prefix-list WORD\
ed126382 12623 |access-list ACCESSLIST_NAME\
70dd370f 12624 |route-map RMAP_NAME\
1e2ce4f1 12625 |rpki <invalid|valid|notfound>\
7d3cae70 12626 |version (1-4294967295)\
b4ad2fae 12627 |alias ALIAS_NAME\
39c3c736
RW
12628 |A.B.C.D/M longer-prefixes\
12629 |X:X::X:X/M longer-prefixes\
70cd87ca 12630 |optimal-route-reflection [WORD$orr_group_name]\
f280c93b 12631 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12632 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12633 BGP_SAFI_WITH_LABEL_HELP_STR
12634 "Display the entries for all address families\n"
12635 "Display only routes with non-natural netmasks\n"
12636 "Display detailed information about dampening\n"
12637 "Display flap statistics of routes\n"
12638 "Display paths suppressed due to dampening\n"
12639 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12640 "Do not send outside local AS (well-known community)\n"
12641 "Do not advertise to any peer (well-known community)\n"
12642 "Do not export to next AS (well-known community)\n"
12643 "Graceful shutdown (well-known community)\n"
12644 "Do not export to any peer (well-known community)\n"
12645 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12646 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12647 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12648 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12649 "Should accept VPN route with local nexthop (well-known community)\n"
12650 "RT VPNv6 route filtering (well-known community)\n"
12651 "RT VPNv4 route filtering (well-known community)\n"
12652 "RT translated VPNv6 route filtering (well-known community)\n"
12653 "RT translated VPNv4 route filtering (well-known community)\n"
12654 "Exact match of the communities\n"
70799983
RW
12655 "Community-list number\n"
12656 "Community-list name\n"
12657 "Display routes matching the community-list\n"
12658 "Exact match of the communities\n"
a7129347
RW
12659 "Display routes conforming to the filter-list\n"
12660 "Regular expression access list name\n"
6deaf579
RW
12661 "Display routes conforming to the prefix-list\n"
12662 "Prefix-list name\n"
ed126382
DA
12663 "Display routes conforming to the access-list\n"
12664 "Access-list name\n"
bf1a944a
RW
12665 "Display routes matching the route-map\n"
12666 "A route-map to match on\n"
a70a28a5
DA
12667 "RPKI route types\n"
12668 "A valid path as determined by rpki\n"
12669 "A invalid path as determined by rpki\n"
12670 "A path that has no rpki data\n"
12671 "Display prefixes with matching version numbers\n"
12672 "Version number and above\n"
12673 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12674 "BGP community alias\n"
12675 "IPv4 prefix\n"
12676 "Display route and more specific routes\n"
12677 "IPv6 prefix\n"
12678 "Display route and more specific routes\n"
70cd87ca
MK
12679 "Display Optimal Route Reflection RR Clients\n"
12680 "ORR Group name\n"
39c3c736 12681 JSON_STR
a70a28a5
DA
12682 "Display detailed version of JSON output\n"
12683 "Increase table width for longer prefixes\n")
7b2ff250
DW
12684{
12685 afi_t afi = AFI_IP6;
12686 safi_t safi = SAFI_UNICAST;
12687 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12688 void *output_arg = NULL;
7b2ff250
DW
12689 struct bgp *bgp = NULL;
12690 int idx = 0;
d0086e8e 12691 int exact_match = 0;
96f3485c
MK
12692 char *community = NULL;
12693 bool first = true;
96c81f66 12694 uint16_t show_flags = 0;
4027d19b 12695 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12696 struct prefix p;
70cd87ca 12697 bool orr_group = false;
96f3485c
MK
12698
12699 if (uj) {
9f049418 12700 argc--;
96f3485c
MK
12701 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12702 }
12703
f280c93b
DA
12704 if (detail)
12705 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12706
96f3485c
MK
12707 /* [<ipv4|ipv6> [all]] */
12708 if (all) {
12709 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12710
12711 if (argv_find(argv, argc, "ipv4", &idx))
12712 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12713
12714 if (argv_find(argv, argc, "ipv6", &idx))
12715 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12716 }
12717
12718 if (wide)
12719 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12720
12721 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12722 &bgp, uj);
7b2ff250
DW
12723 if (!idx)
12724 return CMD_WARNING;
12725
7b2ff250 12726 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12727 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12728
12729 if (argv_find(argv, argc, "dampening", &idx)) {
12730 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12731 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12732 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12733 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12734 }
12735
12736 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12737 char *maybecomm = NULL;
d0086e8e 12738
79bc257a
RW
12739 if (idx + 1 < argc) {
12740 if (argv[idx + 1]->type == VARIABLE_TKN)
12741 maybecomm = argv[idx + 1]->arg;
12742 else
12743 maybecomm = argv[idx + 1]->text;
12744 }
12745
cf4898bc
QY
12746 if (maybecomm && !strmatch(maybecomm, "json")
12747 && !strmatch(maybecomm, "exact-match"))
12748 community = maybecomm;
d0086e8e 12749
cf4898bc
QY
12750 if (argv_find(argv, argc, "exact-match", &idx))
12751 exact_match = 1;
d0086e8e 12752
96f3485c
MK
12753 if (!community)
12754 sh_type = bgp_show_type_community_all;
12755 }
12756
70799983
RW
12757 if (argv_find(argv, argc, "community-list", &idx)) {
12758 const char *clist_number_or_name = argv[++idx]->arg;
12759 struct community_list *list;
12760
12761 if (argv_find(argv, argc, "exact-match", &idx))
12762 exact_match = 1;
12763
12764 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12765 COMMUNITY_LIST_MASTER);
12766 if (list == NULL) {
606d49a4 12767 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12768 clist_number_or_name);
12769 return CMD_WARNING;
12770 }
12771
12772 if (exact_match)
12773 sh_type = bgp_show_type_community_list_exact;
12774 else
12775 sh_type = bgp_show_type_community_list;
12776 output_arg = list;
12777 }
12778
a7129347
RW
12779 if (argv_find(argv, argc, "filter-list", &idx)) {
12780 const char *filter = argv[++idx]->arg;
12781 struct as_list *as_list;
12782
12783 as_list = as_list_lookup(filter);
12784 if (as_list == NULL) {
606d49a4 12785 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12786 filter);
12787 return CMD_WARNING;
12788 }
12789
12790 sh_type = bgp_show_type_filter_list;
12791 output_arg = as_list;
12792 }
12793
6deaf579
RW
12794 if (argv_find(argv, argc, "prefix-list", &idx)) {
12795 const char *prefix_list_str = argv[++idx]->arg;
12796 struct prefix_list *plist;
12797
12798 plist = prefix_list_lookup(afi, prefix_list_str);
12799 if (plist == NULL) {
606d49a4 12800 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12801 prefix_list_str);
12802 return CMD_WARNING;
12803 }
12804
12805 sh_type = bgp_show_type_prefix_list;
12806 output_arg = plist;
12807 }
12808
ed126382
DA
12809 if (argv_find(argv, argc, "access-list", &idx)) {
12810 const char *access_list_str = argv[++idx]->arg;
12811 struct access_list *alist;
12812
12813 alist = access_list_lookup(afi, access_list_str);
12814 if (!alist) {
606d49a4 12815 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12816 access_list_str);
12817 return CMD_WARNING;
12818 }
12819
12820 sh_type = bgp_show_type_access_list;
12821 output_arg = alist;
12822 }
12823
bf1a944a
RW
12824 if (argv_find(argv, argc, "route-map", &idx)) {
12825 const char *rmap_str = argv[++idx]->arg;
12826 struct route_map *rmap;
12827
12828 rmap = route_map_lookup_by_name(rmap_str);
12829 if (!rmap) {
606d49a4 12830 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12831 return CMD_WARNING;
12832 }
12833
12834 sh_type = bgp_show_type_route_map;
12835 output_arg = rmap;
12836 }
12837
1e2ce4f1
DS
12838 if (argv_find(argv, argc, "rpki", &idx)) {
12839 sh_type = bgp_show_type_rpki;
12840 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12841 rpki_target_state = RPKI_VALID;
1e2ce4f1 12842 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12843 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12844 }
12845
7d3cae70
DA
12846 /* Display prefixes with matching version numbers */
12847 if (argv_find(argv, argc, "version", &idx)) {
12848 sh_type = bgp_show_type_prefix_version;
2391833e 12849 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12850 }
12851
a70a28a5
DA
12852 /* Display prefixes with matching BGP community alias */
12853 if (argv_find(argv, argc, "alias", &idx)) {
12854 sh_type = bgp_show_type_community_alias;
2391833e 12855 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12856 }
12857
39c3c736
RW
12858 /* prefix-longer */
12859 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12860 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12861 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12862
12863 if (!str2prefix(prefix_str, &p)) {
12864 vty_out(vty, "%% Malformed Prefix\n");
12865 return CMD_WARNING;
12866 }
12867
12868 sh_type = bgp_show_type_prefix_longer;
12869 output_arg = &p;
a70a28a5
DA
12870 }
12871
70cd87ca
MK
12872 if (argv_find(argv, argc, "optimal-route-reflection", &idx))
12873 orr_group = true;
12874
96f3485c
MK
12875 if (!all) {
12876 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12877 if (community)
12878 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12879 exact_match, afi, safi,
12880 show_flags);
70cd87ca
MK
12881 else if (orr_group)
12882 return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
12883 show_flags);
2391833e 12884 else
a70a28a5 12885 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12886 output_arg, show_flags,
a70a28a5 12887 rpki_target_state);
96f3485c 12888 } else {
fa5ac378
DA
12889 struct listnode *node;
12890 struct bgp *abgp;
96f3485c
MK
12891 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12892 * AFI_IP6 */
12893
12894 if (uj)
12895 vty_out(vty, "{\n");
12896
12897 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12898 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12899 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12900 ? AFI_IP
12901 : AFI_IP6;
fa5ac378
DA
12902 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12903 FOREACH_SAFI (safi) {
12904 if (!bgp_afi_safi_peer_exists(abgp, afi,
12905 safi))
12906 continue;
96f3485c 12907
fa5ac378
DA
12908 if (uj) {
12909 if (first)
12910 first = false;
12911 else
12912 vty_out(vty, ",\n");
12913 vty_out(vty, "\"%s\":{\n",
12914 get_afi_safi_str(afi,
12915 safi,
12916 true));
12917 } else
12918 vty_out(vty,
12919 "\nFor address family: %s\n",
12920 get_afi_safi_str(
12921 afi, safi,
12922 false));
12923
12924 if (community)
12925 bgp_show_community(
12926 vty, abgp, community,
12927 exact_match, afi, safi,
12928 show_flags);
70cd87ca
MK
12929 else if (orr_group)
12930 bgp_show_orr(vty, bgp, afi,
12931 safi,
12932 orr_group_name,
12933 show_flags);
96f3485c 12934 else
fa5ac378
DA
12935 bgp_show(vty, abgp, afi, safi,
12936 sh_type, output_arg,
12937 show_flags,
12938 rpki_target_state);
12939 if (uj)
12940 vty_out(vty, "}\n");
12941 }
96f3485c
MK
12942 }
12943 } else {
12944 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12945 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12946 FOREACH_AFI_SAFI (afi, safi) {
12947 if (!bgp_afi_safi_peer_exists(abgp, afi,
12948 safi))
12949 continue;
96f3485c 12950
fa5ac378
DA
12951 if (uj) {
12952 if (first)
12953 first = false;
12954 else
12955 vty_out(vty, ",\n");
12956
12957 vty_out(vty, "\"%s\":{\n",
12958 get_afi_safi_str(afi,
12959 safi,
12960 true));
12961 } else
12962 vty_out(vty,
12963 "\nFor address family: %s\n",
12964 get_afi_safi_str(
12965 afi, safi,
12966 false));
12967
12968 if (community)
12969 bgp_show_community(
12970 vty, abgp, community,
12971 exact_match, afi, safi,
12972 show_flags);
70cd87ca
MK
12973 else if (orr_group)
12974 bgp_show_orr(vty, bgp, afi,
12975 safi,
12976 orr_group_name,
12977 show_flags);
96f3485c 12978 else
fa5ac378
DA
12979 bgp_show(vty, abgp, afi, safi,
12980 sh_type, output_arg,
12981 show_flags,
12982 rpki_target_state);
12983 if (uj)
12984 vty_out(vty, "}\n");
12985 }
96f3485c
MK
12986 }
12987 }
12988 if (uj)
12989 vty_out(vty, "}\n");
12990 }
12991 return CMD_SUCCESS;
a636c635 12992}
47fc97cc 12993
718e3744 12994DEFUN (show_ip_bgp_route,
12995 show_ip_bgp_route_cmd,
8aa22bbb 12996 "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 12997 SHOW_STR
12998 IP_STR
12999 BGP_STR
a636c635 13000 BGP_INSTANCE_HELP_STR
4f280b15 13001 BGP_AFI_HELP_STR
4dd6177e 13002 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13003 "Network in the BGP routing table to display\n"
0c7b1b01 13004 "IPv4 prefix\n"
8c3deaae 13005 "Network in the BGP routing table to display\n"
0c7b1b01 13006 "IPv6 prefix\n"
4092b06c 13007 "Display only the bestpath\n"
b05a1c8b 13008 "Display only multipaths\n"
8aa22bbb
DS
13009 "Display only paths that match the specified rpki state\n"
13010 "A valid path as determined by rpki\n"
13011 "A invalid path as determined by rpki\n"
13012 "A path that has no rpki data\n"
9973d184 13013 JSON_STR)
4092b06c 13014{
d62a17ae 13015 int prefix_check = 0;
ae19d7dd 13016
d62a17ae 13017 afi_t afi = AFI_IP6;
13018 safi_t safi = SAFI_UNICAST;
13019 char *prefix = NULL;
13020 struct bgp *bgp = NULL;
13021 enum bgp_path_type path_type;
9f049418 13022 bool uj = use_json(argc, argv);
b05a1c8b 13023
d62a17ae 13024 int idx = 0;
ae19d7dd 13025
d62a17ae 13026 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13027 &bgp, uj);
d62a17ae 13028 if (!idx)
13029 return CMD_WARNING;
c41247f5 13030
d62a17ae 13031 if (!bgp) {
13032 vty_out(vty,
13033 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13034 return CMD_WARNING;
13035 }
a636c635 13036
d62a17ae 13037 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13038 if (argv_find(argv, argc, "A.B.C.D", &idx)
13039 || argv_find(argv, argc, "X:X::X:X", &idx))
13040 prefix_check = 0;
13041 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13042 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13043 prefix_check = 1;
13044
13045 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13046 && afi != AFI_IP6) {
13047 vty_out(vty,
13048 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13049 return CMD_WARNING;
13050 }
13051 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13052 && afi != AFI_IP) {
13053 vty_out(vty,
13054 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13055 return CMD_WARNING;
13056 }
13057
13058 prefix = argv[idx]->arg;
13059
13060 /* [<bestpath|multipath>] */
13061 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13062 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13063 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13064 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13065 else
360660c6 13066 path_type = BGP_PATH_SHOW_ALL;
a636c635 13067
d62a17ae 13068 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13069 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13070}
13071
8c3deaae
QY
13072DEFUN (show_ip_bgp_regexp,
13073 show_ip_bgp_regexp_cmd,
3e5b31b3 13074 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13075 SHOW_STR
13076 IP_STR
13077 BGP_STR
b00b230a 13078 BGP_INSTANCE_HELP_STR
4f280b15 13079 BGP_AFI_HELP_STR
4dd6177e 13080 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13081 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13082 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13083 JSON_STR)
8c3deaae 13084{
d62a17ae 13085 afi_t afi = AFI_IP6;
13086 safi_t safi = SAFI_UNICAST;
13087 struct bgp *bgp = NULL;
3e5b31b3
DA
13088 bool uj = use_json(argc, argv);
13089 char *regstr = NULL;
8c3deaae 13090
d62a17ae 13091 int idx = 0;
13092 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13093 &bgp, false);
d62a17ae 13094 if (!idx)
13095 return CMD_WARNING;
8c3deaae 13096
d62a17ae 13097 // get index of regex
3e5b31b3
DA
13098 if (argv_find(argv, argc, "REGEX", &idx))
13099 regstr = argv[idx]->arg;
8c3deaae 13100
5f71d11c 13101 assert(regstr);
3e5b31b3
DA
13102 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13103 bgp_show_type_regexp, uj);
8c3deaae
QY
13104}
13105
ae248832 13106DEFPY (show_ip_bgp_instance_all,
a636c635 13107 show_ip_bgp_instance_all_cmd,
ae248832 13108 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13109 SHOW_STR
a636c635 13110 IP_STR
4092b06c 13111 BGP_STR
a636c635 13112 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13113 BGP_AFI_HELP_STR
4dd6177e 13114 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13115 JSON_STR
13116 "Increase table width for longer prefixes\n")
4092b06c 13117{
54d05dea 13118 afi_t afi = AFI_IP6;
d62a17ae 13119 safi_t safi = SAFI_UNICAST;
13120 struct bgp *bgp = NULL;
d62a17ae 13121 int idx = 0;
96c81f66 13122 uint16_t show_flags = 0;
ae19d7dd 13123
96f3485c 13124 if (uj) {
d62a17ae 13125 argc--;
96f3485c
MK
13126 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13127 }
13128
13129 if (wide)
13130 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13131
9f049418
DS
13132 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13133 &bgp, uj);
13134 if (!idx)
13135 return CMD_WARNING;
13136
96f3485c 13137 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13138 return CMD_SUCCESS;
e3e29b32
LB
13139}
13140
a4d82a8a 13141static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13142 afi_t afi, safi_t safi, enum bgp_show_type type,
13143 bool use_json)
718e3744 13144{
d62a17ae 13145 regex_t *regex;
13146 int rc;
96c81f66 13147 uint16_t show_flags = 0;
96f3485c
MK
13148
13149 if (use_json)
13150 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13151
c3900853 13152 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13153 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13154 regstr);
13155 return CMD_WARNING_CONFIG_FAILED;
13156 }
13157
d62a17ae 13158 regex = bgp_regcomp(regstr);
13159 if (!regex) {
13160 vty_out(vty, "Can't compile regexp %s\n", regstr);
13161 return CMD_WARNING;
13162 }
a636c635 13163
1e2ce4f1
DS
13164 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13165 RPKI_NOT_BEING_USED);
d62a17ae 13166 bgp_regex_free(regex);
13167 return rc;
e3e29b32
LB
13168}
13169
7f323236
DW
13170static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13171 const char *comstr, int exact, afi_t afi,
96c81f66 13172 safi_t safi, uint16_t show_flags)
d62a17ae 13173{
13174 struct community *com;
d62a17ae 13175 int ret = 0;
13176
7f323236 13177 com = community_str2com(comstr);
d62a17ae 13178 if (!com) {
7f323236 13179 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13180 return CMD_WARNING;
13181 }
13182
13183 ret = bgp_show(vty, bgp, afi, safi,
13184 (exact ? bgp_show_type_community_exact
13185 : bgp_show_type_community),
1e2ce4f1 13186 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13187 community_free(&com);
46c3ce83 13188
d62a17ae 13189 return ret;
718e3744 13190}
13191
d62a17ae 13192enum bgp_stats {
13193 BGP_STATS_MAXBITLEN = 0,
13194 BGP_STATS_RIB,
13195 BGP_STATS_PREFIXES,
13196 BGP_STATS_TOTPLEN,
13197 BGP_STATS_UNAGGREGATEABLE,
13198 BGP_STATS_MAX_AGGREGATEABLE,
13199 BGP_STATS_AGGREGATES,
13200 BGP_STATS_SPACE,
13201 BGP_STATS_ASPATH_COUNT,
13202 BGP_STATS_ASPATH_MAXHOPS,
13203 BGP_STATS_ASPATH_TOTHOPS,
13204 BGP_STATS_ASPATH_MAXSIZE,
13205 BGP_STATS_ASPATH_TOTSIZE,
13206 BGP_STATS_ASN_HIGHEST,
13207 BGP_STATS_MAX,
a636c635 13208};
2815e61f 13209
9ab0cf58 13210#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13211#define TABLE_STATS_IDX_JSON 1
13212
13213static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13214 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13215 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13216 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13217 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13218 "unaggregateablePrefixes"},
13219 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13220 "maximumAggregateablePrefixes"},
13221 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13222 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13223 [BGP_STATS_SPACE] = {"Address space advertised",
13224 "addressSpaceAdvertised"},
9ab0cf58
PG
13225 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13226 "advertisementsWithPaths"},
13227 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13228 "longestAsPath"},
13229 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13230 "largestAsPath"},
13231 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13232 "averageAsPathLengthHops"},
13233 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13234 "averageAsPathSizeBytes"},
13235 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13236 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13237};
2815e61f 13238
d62a17ae 13239struct bgp_table_stats {
13240 struct bgp_table *table;
13241 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13242
13243 unsigned long long
13244 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13245 1];
13246
8d0ab76d 13247 double total_space;
ff7924f6
PJ
13248};
13249
9bcb3eef 13250static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13251 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13252{
9bcb3eef 13253 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13254 struct bgp_path_info *pi;
b54892e0 13255 const struct prefix *rn_p;
d62a17ae 13256
9bcb3eef 13257 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13258 return;
d62a17ae 13259
9bcb3eef 13260 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13261 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13262 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13263
0747643e 13264 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13265 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13266 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13267 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13268
9bcb3eef 13269 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13270 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13271 /* announced address space */
13272 if (space)
b54892e0 13273 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13274 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13275 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13276
9c14ec72 13277
9bcb3eef 13278 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13279 ts->counts[BGP_STATS_RIB]++;
13280
05864da7
DS
13281 if (CHECK_FLAG(pi->attr->flag,
13282 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13283 ts->counts[BGP_STATS_AGGREGATES]++;
13284
13285 /* as-path stats */
05864da7 13286 if (pi->attr->aspath) {
9c14ec72
RW
13287 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13288 unsigned int size = aspath_size(pi->attr->aspath);
13289 as_t highest = aspath_highest(pi->attr->aspath);
13290
13291 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13292
13293 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13294 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13295
13296 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13297 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13298
13299 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13300 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13301 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13302 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13303 }
13304 }
13305}
13306
cc9f21da 13307static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13308{
9bcb3eef
DS
13309 struct bgp_dest *dest, *ndest;
13310 struct bgp_dest *top;
9c14ec72
RW
13311 struct bgp_table_stats *ts = THREAD_ARG(t);
13312 unsigned int space = 0;
13313
13314 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13315 return;
9c14ec72
RW
13316
13317 switch (ts->table->afi) {
13318 case AFI_IP:
13319 space = IPV4_MAX_BITLEN;
13320 break;
13321 case AFI_IP6:
13322 space = IPV6_MAX_BITLEN;
13323 break;
3ba7b4af
TA
13324 case AFI_L2VPN:
13325 space = EVPN_ROUTE_PREFIXLEN;
13326 break;
9c14ec72 13327 default:
cc9f21da 13328 return;
9c14ec72
RW
13329 }
13330
13331 ts->counts[BGP_STATS_MAXBITLEN] = space;
13332
9bcb3eef 13333 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13334 if (ts->table->safi == SAFI_MPLS_VPN
13335 || ts->table->safi == SAFI_ENCAP
13336 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13337 struct bgp_table *table;
13338
9bcb3eef 13339 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13340 if (!table)
13341 continue;
13342
13343 top = bgp_table_top(table);
9bcb3eef
DS
13344 for (ndest = bgp_table_top(table); ndest;
13345 ndest = bgp_route_next(ndest))
13346 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13347 } else {
9bcb3eef 13348 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13349 }
13350 }
2815e61f 13351}
ff7924f6 13352
71f1613a
DA
13353static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13354 struct json_object *json_array)
13355{
13356 struct listnode *node, *nnode;
13357 struct bgp *bgp;
13358
13359 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13360 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13361}
13362
13363static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13364 safi_t safi, struct json_object *json_array)
2815e61f 13365{
d62a17ae 13366 struct bgp_table_stats ts;
13367 unsigned int i;
893cccd0
PG
13368 int ret = CMD_SUCCESS;
13369 char temp_buf[20];
6c9d22e2 13370 struct json_object *json = NULL;
0747643e
AQ
13371 uint32_t bitlen = 0;
13372 struct json_object *json_bitlen;
6c9d22e2
PG
13373
13374 if (json_array)
13375 json = json_object_new_object();
019386c2 13376
d62a17ae 13377 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13378 char warning_msg[50];
13379
13380 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13381 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13382 safi);
6c9d22e2
PG
13383
13384 if (!json)
893cccd0
PG
13385 vty_out(vty, "%s\n", warning_msg);
13386 else
9ab0cf58 13387 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13388
893cccd0
PG
13389 ret = CMD_WARNING;
13390 goto end_table_stats;
d62a17ae 13391 }
019386c2 13392
893cccd0 13393 if (!json)
5290ceab
DA
13394 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13395 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13396 else
13397 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13398
d62a17ae 13399 /* labeled-unicast routes live in the unicast table */
13400 if (safi == SAFI_LABELED_UNICAST)
13401 safi = SAFI_UNICAST;
019386c2 13402
d62a17ae 13403 memset(&ts, 0, sizeof(ts));
13404 ts.table = bgp->rib[afi][safi];
13405 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13406
d62a17ae 13407 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13408 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13409 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13410 continue;
13411
13412 switch (i) {
d62a17ae 13413 case BGP_STATS_ASPATH_TOTHOPS:
13414 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13415 if (!json) {
9ab0cf58
PG
13416 snprintf(
13417 temp_buf, sizeof(temp_buf), "%12.2f",
13418 ts.counts[i]
13419 ? (float)ts.counts[i]
13420 / (float)ts.counts
13421 [BGP_STATS_ASPATH_COUNT]
13422 : 0);
893cccd0 13423 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13424 table_stats_strs[i]
13425 [TABLE_STATS_IDX_VTY],
893cccd0 13426 temp_buf);
9ab0cf58
PG
13427 } else {
13428 json_object_double_add(
13429 json,
13430 table_stats_strs[i]
13431 [TABLE_STATS_IDX_JSON],
13432 ts.counts[i]
13433 ? (double)ts.counts[i]
13434 / (double)ts.counts
d62a17ae 13435 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13436 : 0);
13437 }
d62a17ae 13438 break;
13439 case BGP_STATS_TOTPLEN:
6c9d22e2 13440 if (!json) {
9ab0cf58
PG
13441 snprintf(
13442 temp_buf, sizeof(temp_buf), "%12.2f",
13443 ts.counts[i]
13444 ? (float)ts.counts[i]
13445 / (float)ts.counts
13446 [BGP_STATS_PREFIXES]
13447 : 0);
893cccd0 13448 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13449 table_stats_strs[i]
13450 [TABLE_STATS_IDX_VTY],
893cccd0 13451 temp_buf);
9ab0cf58
PG
13452 } else {
13453 json_object_double_add(
13454 json,
13455 table_stats_strs[i]
13456 [TABLE_STATS_IDX_JSON],
13457 ts.counts[i]
13458 ? (double)ts.counts[i]
13459 / (double)ts.counts
d62a17ae 13460 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13461 : 0);
13462 }
d62a17ae 13463 break;
13464 case BGP_STATS_SPACE:
6c9d22e2
PG
13465 if (!json) {
13466 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13467 ts.total_space);
893cccd0 13468 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13469 table_stats_strs[i]
13470 [TABLE_STATS_IDX_VTY],
893cccd0 13471 temp_buf);
9ab0cf58
PG
13472 } else {
13473 json_object_double_add(
13474 json,
13475 table_stats_strs[i]
13476 [TABLE_STATS_IDX_JSON],
13477 (double)ts.total_space);
13478 }
8d0ab76d 13479 if (afi == AFI_IP6) {
6c9d22e2
PG
13480 if (!json) {
13481 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13482 "%12g",
13483 ts.total_space
13484 * pow(2.0, -128 + 32));
6c9d22e2
PG
13485 vty_out(vty, "%30s: %s\n",
13486 "/32 equivalent %s\n",
13487 temp_buf);
9ab0cf58
PG
13488 } else {
13489 json_object_double_add(
13490 json, "/32equivalent",
13491 (double)(ts.total_space
13492 * pow(2.0,
13493 -128 + 32)));
13494 }
6c9d22e2
PG
13495 if (!json) {
13496 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13497 "%12g",
13498 ts.total_space
13499 * pow(2.0, -128 + 48));
6c9d22e2
PG
13500 vty_out(vty, "%30s: %s\n",
13501 "/48 equivalent %s\n",
13502 temp_buf);
9ab0cf58
PG
13503 } else {
13504 json_object_double_add(
13505 json, "/48equivalent",
13506 (double)(ts.total_space
13507 * pow(2.0,
13508 -128 + 48)));
13509 }
8d0ab76d 13510 } else {
6c9d22e2
PG
13511 if (!json) {
13512 snprintf(temp_buf, sizeof(temp_buf),
13513 "%12.2f",
9ab0cf58
PG
13514 ts.total_space * 100.
13515 * pow(2.0, -32));
6c9d22e2 13516 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13517 "% announced ", temp_buf);
13518 } else {
13519 json_object_double_add(
13520 json, "%announced",
13521 (double)(ts.total_space * 100.
13522 * pow(2.0, -32)));
13523 }
6c9d22e2
PG
13524 if (!json) {
13525 snprintf(temp_buf, sizeof(temp_buf),
13526 "%12.2f",
9ab0cf58
PG
13527 ts.total_space
13528 * pow(2.0, -32 + 8));
6c9d22e2
PG
13529 vty_out(vty, "%30s: %s\n",
13530 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13531 } else {
13532 json_object_double_add(
13533 json, "/8equivalent",
13534 (double)(ts.total_space
13535 * pow(2.0, -32 + 8)));
13536 }
6c9d22e2
PG
13537 if (!json) {
13538 snprintf(temp_buf, sizeof(temp_buf),
13539 "%12.2f",
9ab0cf58
PG
13540 ts.total_space
13541 * pow(2.0, -32 + 24));
6c9d22e2 13542 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13543 "/24 equivalent ", temp_buf);
13544 } else {
13545 json_object_double_add(
13546 json, "/24equivalent",
13547 (double)(ts.total_space
13548 * pow(2.0, -32 + 24)));
13549 }
8d0ab76d 13550 }
d62a17ae 13551 break;
13552 default:
6c9d22e2
PG
13553 if (!json) {
13554 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13555 ts.counts[i]);
893cccd0 13556 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13557 table_stats_strs[i]
13558 [TABLE_STATS_IDX_VTY],
13559 temp_buf);
13560 } else {
13561 json_object_int_add(
13562 json,
13563 table_stats_strs[i]
13564 [TABLE_STATS_IDX_JSON],
13565 ts.counts[i]);
13566 }
d62a17ae 13567 }
893cccd0
PG
13568 if (!json)
13569 vty_out(vty, "\n");
d62a17ae 13570 }
0747643e
AQ
13571
13572 switch (afi) {
13573 case AFI_IP:
13574 bitlen = IPV4_MAX_BITLEN;
13575 break;
13576 case AFI_IP6:
13577 bitlen = IPV6_MAX_BITLEN;
13578 break;
13579 case AFI_L2VPN:
13580 bitlen = EVPN_ROUTE_PREFIXLEN;
13581 break;
13582 default:
13583 break;
13584 }
13585
13586 if (json) {
13587 json_bitlen = json_object_new_array();
13588
13589 for (i = 0; i <= bitlen; i++) {
13590 struct json_object *ind_bit = json_object_new_object();
13591
13592 if (!ts.prefix_len_count[i])
13593 continue;
13594
13595 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13596 json_object_int_add(ind_bit, temp_buf,
13597 ts.prefix_len_count[i]);
13598 json_object_array_add(json_bitlen, ind_bit);
13599 }
13600 json_object_object_add(json, "prefixLength", json_bitlen);
13601 }
13602
9ab0cf58 13603end_table_stats:
6c9d22e2
PG
13604 if (json)
13605 json_object_array_add(json_array, json);
893cccd0 13606 return ret;
d62a17ae 13607}
13608
71f1613a
DA
13609static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13610 safi_t safi, struct json_object *json_array)
13611{
13612 if (!bgp) {
13613 bgp_table_stats_all(vty, afi, safi, json_array);
13614 return CMD_SUCCESS;
13615 }
13616
13617 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13618}
13619
d62a17ae 13620enum bgp_pcounts {
13621 PCOUNT_ADJ_IN = 0,
13622 PCOUNT_DAMPED,
13623 PCOUNT_REMOVED,
13624 PCOUNT_HISTORY,
13625 PCOUNT_STALE,
13626 PCOUNT_VALID,
13627 PCOUNT_ALL,
13628 PCOUNT_COUNTED,
7e3d9632 13629 PCOUNT_BPATH_SELECTED,
d62a17ae 13630 PCOUNT_PFCNT, /* the figure we display to users */
13631 PCOUNT_MAX,
a636c635 13632};
718e3744 13633
2b64873d 13634static const char *const pcount_strs[] = {
9d303b37
DL
13635 [PCOUNT_ADJ_IN] = "Adj-in",
13636 [PCOUNT_DAMPED] = "Damped",
13637 [PCOUNT_REMOVED] = "Removed",
13638 [PCOUNT_HISTORY] = "History",
13639 [PCOUNT_STALE] = "Stale",
13640 [PCOUNT_VALID] = "Valid",
13641 [PCOUNT_ALL] = "All RIB",
13642 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13643 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13644 [PCOUNT_PFCNT] = "Useable",
13645 [PCOUNT_MAX] = NULL,
a636c635 13646};
718e3744 13647
d62a17ae 13648struct peer_pcounts {
13649 unsigned int count[PCOUNT_MAX];
13650 const struct peer *peer;
13651 const struct bgp_table *table;
54317cba 13652 safi_t safi;
a636c635 13653};
47fc97cc 13654
9bcb3eef 13655static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13656{
54317cba
JW
13657 const struct bgp_adj_in *ain;
13658 const struct bgp_path_info *pi;
d62a17ae 13659 const struct peer *peer = pc->peer;
13660
54317cba
JW
13661 for (ain = rn->adj_in; ain; ain = ain->next)
13662 if (ain->peer == peer)
13663 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13664
9bcb3eef 13665 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13666
54317cba
JW
13667 if (pi->peer != peer)
13668 continue;
d62a17ae 13669
54317cba 13670 pc->count[PCOUNT_ALL]++;
d62a17ae 13671
54317cba
JW
13672 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13673 pc->count[PCOUNT_DAMPED]++;
13674 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13675 pc->count[PCOUNT_HISTORY]++;
13676 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13677 pc->count[PCOUNT_REMOVED]++;
13678 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13679 pc->count[PCOUNT_STALE]++;
13680 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13681 pc->count[PCOUNT_VALID]++;
13682 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13683 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13684 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13685 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13686
13687 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13688 pc->count[PCOUNT_COUNTED]++;
13689 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13690 flog_err(
13691 EC_LIB_DEVELOPMENT,
13692 "Attempting to count but flags say it is unusable");
13693 } else {
40381db7 13694 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13695 flog_err(
13696 EC_LIB_DEVELOPMENT,
13697 "Not counted but flags say we should");
d62a17ae 13698 }
13699 }
54317cba
JW
13700}
13701
cc9f21da 13702static void bgp_peer_count_walker(struct thread *t)
54317cba 13703{
9bcb3eef 13704 struct bgp_dest *rn, *rm;
54317cba
JW
13705 const struct bgp_table *table;
13706 struct peer_pcounts *pc = THREAD_ARG(t);
13707
13708 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13709 || pc->safi == SAFI_EVPN) {
13710 /* Special handling for 2-level routing tables. */
13711 for (rn = bgp_table_top(pc->table); rn;
13712 rn = bgp_route_next(rn)) {
9bcb3eef 13713 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13714 if (table != NULL)
13715 for (rm = bgp_table_top(table); rm;
13716 rm = bgp_route_next(rm))
13717 bgp_peer_count_proc(rm, pc);
13718 }
13719 } else
13720 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13721 bgp_peer_count_proc(rn, pc);
718e3744 13722}
13723
d62a17ae 13724static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13725 safi_t safi, bool use_json)
856ca177 13726{
d62a17ae 13727 struct peer_pcounts pcounts = {.peer = peer};
13728 unsigned int i;
13729 json_object *json = NULL;
13730 json_object *json_loop = NULL;
856ca177 13731
d62a17ae 13732 if (use_json) {
13733 json = json_object_new_object();
13734 json_loop = json_object_new_object();
13735 }
718e3744 13736
d62a17ae 13737 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13738 || !peer->bgp->rib[afi][safi]) {
13739 if (use_json) {
13740 json_object_string_add(
13741 json, "warning",
13742 "No such neighbor or address family");
13743 vty_out(vty, "%s\n", json_object_to_json_string(json));
13744 json_object_free(json);
d5f20468 13745 json_object_free(json_loop);
d62a17ae 13746 } else
13747 vty_out(vty, "%% No such neighbor or address family\n");
13748
13749 return CMD_WARNING;
13750 }
2a71e9ce 13751
d62a17ae 13752 memset(&pcounts, 0, sizeof(pcounts));
13753 pcounts.peer = peer;
13754 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13755 pcounts.safi = safi;
d62a17ae 13756
13757 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13758 * stats for the thread-walk (i.e. ensure this can't be blamed on
13759 * on just vty_read()).
13760 */
d62a17ae 13761 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13762
13763 if (use_json) {
13764 json_object_string_add(json, "prefixCountsFor", peer->host);
13765 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13766 get_afi_safi_str(afi, safi, true));
d62a17ae 13767 json_object_int_add(json, "pfxCounter",
13768 peer->pcount[afi][safi]);
13769
13770 for (i = 0; i < PCOUNT_MAX; i++)
13771 json_object_int_add(json_loop, pcount_strs[i],
13772 pcounts.count[i]);
13773
13774 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13775
13776 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13777 json_object_string_add(json, "pfxctDriftFor",
13778 peer->host);
13779 json_object_string_add(
13780 json, "recommended",
13781 "Please report this bug, with the above command output");
13782 }
75eeda93 13783 vty_json(vty, json);
d62a17ae 13784 } else {
13785
13786 if (peer->hostname
892fedb6 13787 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13788 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13789 peer->hostname, peer->host,
5cb5f4d0 13790 get_afi_safi_str(afi, safi, false));
d62a17ae 13791 } else {
13792 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13793 get_afi_safi_str(afi, safi, false));
d62a17ae 13794 }
13795
6cde4b45 13796 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13797 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13798
13799 for (i = 0; i < PCOUNT_MAX; i++)
13800 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13801 pcounts.count[i]);
13802
13803 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13804 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13805 vty_out(vty,
13806 "Please report this bug, with the above command output\n");
13807 }
13808 }
13809
13810 return CMD_SUCCESS;
718e3744 13811}
13812
a636c635
DW
13813DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13814 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13815 "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 13816 SHOW_STR
13817 IP_STR
13818 BGP_STR
8386ac43 13819 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13820 BGP_AFI_HELP_STR
13821 BGP_SAFI_HELP_STR
0b16f239
DS
13822 "Detailed information on TCP and BGP neighbor connections\n"
13823 "Neighbor to display information about\n"
13824 "Neighbor to display information about\n"
91d37724 13825 "Neighbor on BGP configured interface\n"
a636c635 13826 "Display detailed prefix count information\n"
9973d184 13827 JSON_STR)
0b16f239 13828{
d62a17ae 13829 afi_t afi = AFI_IP6;
13830 safi_t safi = SAFI_UNICAST;
13831 struct peer *peer;
13832 int idx = 0;
13833 struct bgp *bgp = NULL;
9f049418
DS
13834 bool uj = use_json(argc, argv);
13835
13836 if (uj)
13837 argc--;
856ca177 13838
d62a17ae 13839 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13840 &bgp, uj);
d62a17ae 13841 if (!idx)
13842 return CMD_WARNING;
0b16f239 13843
d62a17ae 13844 argv_find(argv, argc, "neighbors", &idx);
13845 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13846 if (!peer)
13847 return CMD_WARNING;
bb46e94f 13848
29c8d9da 13849 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13850}
0b16f239 13851
d6902373
PG
13852#ifdef KEEP_OLD_VPN_COMMANDS
13853DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13854 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13855 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13856 SHOW_STR
13857 IP_STR
13858 BGP_STR
d6902373 13859 BGP_VPNVX_HELP_STR
91d37724 13860 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13861 "Detailed information on TCP and BGP neighbor connections\n"
13862 "Neighbor to display information about\n"
13863 "Neighbor to display information about\n"
91d37724 13864 "Neighbor on BGP configured interface\n"
a636c635 13865 "Display detailed prefix count information\n"
9973d184 13866 JSON_STR)
a636c635 13867{
d62a17ae 13868 int idx_peer = 6;
13869 struct peer *peer;
9f049418 13870 bool uj = use_json(argc, argv);
a636c635 13871
d62a17ae 13872 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13873 if (!peer)
13874 return CMD_WARNING;
13875
13876 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13877}
13878
d6902373
PG
13879DEFUN (show_ip_bgp_vpn_all_route_prefix,
13880 show_ip_bgp_vpn_all_route_prefix_cmd,
13881 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13882 SHOW_STR
13883 IP_STR
13884 BGP_STR
d6902373 13885 BGP_VPNVX_HELP_STR
91d37724
QY
13886 "Display information about all VPNv4 NLRIs\n"
13887 "Network in the BGP routing table to display\n"
3a2d747c 13888 "Network in the BGP routing table to display\n"
9973d184 13889 JSON_STR)
91d37724 13890{
d62a17ae 13891 int idx = 0;
13892 char *network = NULL;
13893 struct bgp *bgp = bgp_get_default();
13894 if (!bgp) {
13895 vty_out(vty, "Can't find default instance\n");
13896 return CMD_WARNING;
13897 }
87e34b58 13898
d62a17ae 13899 if (argv_find(argv, argc, "A.B.C.D", &idx))
13900 network = argv[idx]->arg;
13901 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13902 network = argv[idx]->arg;
13903 else {
13904 vty_out(vty, "Unable to figure out Network\n");
13905 return CMD_WARNING;
13906 }
87e34b58 13907
d62a17ae 13908 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13909 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13910 use_json(argc, argv));
91d37724 13911}
d6902373 13912#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13913
44c69747
LK
13914DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13915 show_bgp_l2vpn_evpn_route_prefix_cmd,
13916 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13917 SHOW_STR
4c63a661
PG
13918 BGP_STR
13919 L2VPN_HELP_STR
13920 EVPN_HELP_STR
44c69747
LK
13921 "Network in the BGP routing table to display\n"
13922 "Network in the BGP routing table to display\n"
4c63a661
PG
13923 "Network in the BGP routing table to display\n"
13924 "Network in the BGP routing table to display\n"
13925 JSON_STR)
13926{
d62a17ae 13927 int idx = 0;
13928 char *network = NULL;
44c69747 13929 int prefix_check = 0;
a636c635 13930
44c69747
LK
13931 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13932 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13933 network = argv[idx]->arg;
44c69747 13934 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13935 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13936 network = argv[idx]->arg;
44c69747
LK
13937 prefix_check = 1;
13938 } else {
d62a17ae 13939 vty_out(vty, "Unable to figure out Network\n");
13940 return CMD_WARNING;
13941 }
44c69747
LK
13942 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13943 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13944 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13945}
13946
114fc229 13947static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13948 struct bgp_table *table, int *header1,
13949 int *header2, json_object *json,
13950 json_object *json_scode,
13951 json_object *json_ocode, bool wide)
13952{
13953 uint64_t version = table ? table->version : 0;
13954
13955 if (*header1) {
13956 if (json) {
13957 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13958 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13959 "%pI4", &peer->bgp->router_id);
2f9bc755 13960 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13961 peer->bgp->default_local_pref);
13962 json_object_int_add(json, "localAS",
13963 peer->change_local_as
13964 ? peer->change_local_as
13965 : peer->local_as);
2f9bc755
DS
13966 json_object_object_add(json, "bgpStatusCodes",
13967 json_scode);
13968 json_object_object_add(json, "bgpOriginCodes",
13969 json_ocode);
13970 } else {
13971 vty_out(vty,
23d0a753
DA
13972 "BGP table version is %" PRIu64
13973 ", local router ID is %pI4, vrf id ",
114fc229
DA
13974 version, &peer->bgp->router_id);
13975 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13976 vty_out(vty, "%s", VRFID_NONE_STR);
13977 else
114fc229 13978 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13979 vty_out(vty, "\n");
13980 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13981 peer->bgp->default_local_pref);
13982 vty_out(vty, "local AS %u\n",
13983 peer->change_local_as ? peer->change_local_as
13984 : peer->local_as);
2f9bc755
DS
13985 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13986 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13987 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13988 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13989 }
13990 *header1 = 0;
13991 }
13992 if (*header2) {
13993 if (!json)
13994 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13995 : BGP_SHOW_HEADER));
13996 *header2 = 0;
13997 }
13998}
13999
d9478df0
TA
14000static void
14001show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14002 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14003 const char *rmap_name, json_object *json, json_object *json_ar,
14004 json_object *json_scode, json_object *json_ocode,
96c81f66 14005 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 14006 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 14007{
d62a17ae 14008 struct bgp_adj_in *ain;
14009 struct bgp_adj_out *adj;
9bcb3eef 14010 struct bgp_dest *dest;
d62a17ae 14011 struct bgp *bgp;
d62a17ae 14012 struct attr attr;
14013 int ret;
14014 struct update_subgroup *subgrp;
d62a17ae 14015 struct peer_af *paf;
f99def61 14016 bool route_filtered;
96f3485c
MK
14017 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14018 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14019 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14020 || (safi == SAFI_EVPN))
14021 ? true
14022 : false;
a636c635 14023
d62a17ae 14024 bgp = peer->bgp;
a636c635 14025
d62a17ae 14026 subgrp = peer_subgroup(peer, afi, safi);
14027
6392aaa6 14028 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14029 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14030 if (use_json) {
14031 json_object_int_add(json, "bgpTableVersion",
14032 table->version);
c949c771
DA
14033 json_object_string_addf(json, "bgpLocalRouterId",
14034 "%pI4", &bgp->router_id);
01eced22
AD
14035 json_object_int_add(json, "defaultLocPrf",
14036 bgp->default_local_pref);
114fc229
DA
14037 json_object_int_add(json, "localAS",
14038 peer->change_local_as
14039 ? peer->change_local_as
14040 : peer->local_as);
d62a17ae 14041 json_object_object_add(json, "bgpStatusCodes",
14042 json_scode);
14043 json_object_object_add(json, "bgpOriginCodes",
14044 json_ocode);
07d0c4ed
DA
14045 json_object_string_add(
14046 json, "bgpOriginatingDefaultNetwork",
14047 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14048 } else {
23d0a753
DA
14049 vty_out(vty,
14050 "BGP table version is %" PRIu64
14051 ", local router ID is %pI4, vrf id ",
14052 table->version, &bgp->router_id);
9df8b37c
PZ
14053 if (bgp->vrf_id == VRF_UNKNOWN)
14054 vty_out(vty, "%s", VRFID_NONE_STR);
14055 else
14056 vty_out(vty, "%u", bgp->vrf_id);
14057 vty_out(vty, "\n");
01eced22
AD
14058 vty_out(vty, "Default local pref %u, ",
14059 bgp->default_local_pref);
114fc229
DA
14060 vty_out(vty, "local AS %u\n",
14061 peer->change_local_as ? peer->change_local_as
14062 : peer->local_as);
d62a17ae 14063 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 14064 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 14065 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14066 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 14067
07d0c4ed
DA
14068 vty_out(vty, "Originating default network %s\n\n",
14069 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14070 }
d9478df0 14071 *header1 = 0;
d62a17ae 14072 }
a636c635 14073
9bcb3eef 14074 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14075 if (type == bgp_show_adj_route_received
14076 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14077 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14078 if (ain->peer != peer)
ea47320b 14079 continue;
6392aaa6 14080
114fc229 14081 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
14082 header2, json, json_scode,
14083 json_ocode, wide);
14084
14085 if ((safi == SAFI_MPLS_VPN)
14086 || (safi == SAFI_ENCAP)
14087 || (safi == SAFI_EVPN)) {
14088 if (use_json)
14089 json_object_string_add(
14090 json_ar, "rd", rd_str);
14091 else if (show_rd && rd_str) {
14092 vty_out(vty,
14093 "Route Distinguisher: %s\n",
14094 rd_str);
14095 show_rd = false;
14096 }
14097 }
6392aaa6 14098
6f4f49b2 14099 attr = *ain->attr;
f99def61
AD
14100 route_filtered = false;
14101
14102 /* Filter prefix using distribute list,
14103 * filter list or prefix list
14104 */
b54892e0 14105 const struct prefix *rn_p =
9bcb3eef 14106 bgp_dest_get_prefix(dest);
b54892e0
DS
14107 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14108 safi))
14109 == FILTER_DENY)
f99def61
AD
14110 route_filtered = true;
14111
14112 /* Filter prefix using route-map */
b54892e0
DS
14113 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14114 safi, rmap_name, NULL,
14115 0, NULL);
6392aaa6 14116
13c8e163
AD
14117 if (type == bgp_show_adj_route_filtered &&
14118 !route_filtered && ret != RMAP_DENY) {
d498917e 14119 bgp_attr_flush(&attr);
6392aaa6 14120 continue;
d62a17ae 14121 }
6392aaa6 14122
d9478df0
TA
14123 if (type == bgp_show_adj_route_received
14124 && (route_filtered || ret == RMAP_DENY))
14125 (*filtered_count)++;
6392aaa6 14126
7d3cae70 14127 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 14128 use_json, json_ar, wide);
d498917e 14129 bgp_attr_flush(&attr);
d9478df0 14130 (*output_count)++;
d62a17ae 14131 }
6392aaa6 14132 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14133 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14134 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14135 if (paf->peer != peer || !adj->attr)
924c3f6a 14136 continue;
d62a17ae 14137
114fc229 14138 show_adj_route_header(vty, peer, table,
d9478df0
TA
14139 header1, header2,
14140 json, json_scode,
14141 json_ocode, wide);
d62a17ae 14142
b54892e0 14143 const struct prefix *rn_p =
9bcb3eef 14144 bgp_dest_get_prefix(dest);
b54892e0 14145
6f4f49b2 14146 attr = *adj->attr;
b755861b 14147 ret = bgp_output_modifier(
b54892e0 14148 peer, rn_p, &attr, afi, safi,
b755861b 14149 rmap_name);
f46d8e1e 14150
b755861b 14151 if (ret != RMAP_DENY) {
d9478df0
TA
14152 if ((safi == SAFI_MPLS_VPN)
14153 || (safi == SAFI_ENCAP)
14154 || (safi == SAFI_EVPN)) {
14155 if (use_json)
14156 json_object_string_add(
14157 json_ar,
14158 "rd",
14159 rd_str);
14160 else if (show_rd
14161 && rd_str) {
14162 vty_out(vty,
14163 "Route Distinguisher: %s\n",
14164 rd_str);
14165 show_rd = false;
14166 }
14167 }
b54892e0 14168 route_vty_out_tmp(
7d3cae70
DA
14169 vty, dest, rn_p, &attr,
14170 safi, use_json, json_ar,
ae248832 14171 wide);
d9478df0 14172 (*output_count)++;
b755861b 14173 } else {
d9478df0 14174 (*filtered_count)++;
a2addae8 14175 }
b755861b 14176
d498917e 14177 bgp_attr_flush(&attr);
924c3f6a 14178 }
f20ce998
DS
14179 } else if (type == bgp_show_adj_route_bestpath) {
14180 struct bgp_path_info *pi;
14181
114fc229
DA
14182 show_adj_route_header(vty, peer, table, header1,
14183 header2, json, json_scode,
14184 json_ocode, wide);
f20ce998
DS
14185
14186 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14187 pi = pi->next) {
14188 if (pi->peer != peer)
14189 continue;
14190
14191 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14192 continue;
14193
7d3cae70 14194 route_vty_out_tmp(vty, dest,
f20ce998
DS
14195 bgp_dest_get_prefix(dest),
14196 pi->attr, safi, use_json,
14197 json_ar, wide);
d9478df0 14198 (*output_count)++;
f20ce998 14199 }
d62a17ae 14200 }
14201 }
a636c635 14202}
2a71e9ce 14203
d62a17ae 14204static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14205 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14206 const char *rmap_name, uint16_t show_flags)
0b16f239 14207{
d9478df0
TA
14208 struct bgp *bgp;
14209 struct bgp_table *table;
d62a17ae 14210 json_object *json = NULL;
d9478df0
TA
14211 json_object *json_scode = NULL;
14212 json_object *json_ocode = NULL;
14213 json_object *json_ar = NULL;
96f3485c 14214 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14215
d9478df0
TA
14216 /* Init BGP headers here so they're only displayed once
14217 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14218 */
14219 int header1 = 1;
14220 int header2 = 1;
14221
14222 /*
14223 * Initialize variables for each RD
14224 * All prefixes under an RD is aggregated within "json_routes"
14225 */
14226 char rd_str[BUFSIZ] = {0};
14227 json_object *json_routes = NULL;
14228
14229
14230 /* For 2-tier tables, prefix counts need to be
14231 * maintained across multiple runs of show_adj_route()
14232 */
14233 unsigned long output_count_per_rd;
14234 unsigned long filtered_count_per_rd;
14235 unsigned long output_count = 0;
14236 unsigned long filtered_count = 0;
14237
14238 if (use_json) {
d62a17ae 14239 json = json_object_new_object();
d9478df0
TA
14240 json_ar = json_object_new_object();
14241 json_scode = json_object_new_object();
14242 json_ocode = json_object_new_object();
14243
14244 json_object_string_add(json_scode, "suppressed", "s");
14245 json_object_string_add(json_scode, "damped", "d");
14246 json_object_string_add(json_scode, "history", "h");
14247 json_object_string_add(json_scode, "valid", "*");
14248 json_object_string_add(json_scode, "best", ">");
14249 json_object_string_add(json_scode, "multipath", "=");
14250 json_object_string_add(json_scode, "internal", "i");
14251 json_object_string_add(json_scode, "ribFailure", "r");
14252 json_object_string_add(json_scode, "stale", "S");
14253 json_object_string_add(json_scode, "removed", "R");
14254
14255 json_object_string_add(json_ocode, "igp", "i");
14256 json_object_string_add(json_ocode, "egp", "e");
14257 json_object_string_add(json_ocode, "incomplete", "?");
14258 }
0b16f239 14259
d62a17ae 14260 if (!peer || !peer->afc[afi][safi]) {
14261 if (use_json) {
14262 json_object_string_add(
14263 json, "warning",
14264 "No such neighbor or address family");
14265 vty_out(vty, "%s\n", json_object_to_json_string(json));
14266 json_object_free(json);
690c3134
MW
14267 json_object_free(json_ar);
14268 json_object_free(json_scode);
14269 json_object_free(json_ocode);
d62a17ae 14270 } else
14271 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14272
d62a17ae 14273 return CMD_WARNING;
14274 }
14275
6392aaa6
PM
14276 if ((type == bgp_show_adj_route_received
14277 || type == bgp_show_adj_route_filtered)
d62a17ae 14278 && !CHECK_FLAG(peer->af_flags[afi][safi],
14279 PEER_FLAG_SOFT_RECONFIG)) {
14280 if (use_json) {
14281 json_object_string_add(
14282 json, "warning",
14283 "Inbound soft reconfiguration not enabled");
14284 vty_out(vty, "%s\n", json_object_to_json_string(json));
14285 json_object_free(json);
690c3134
MW
14286 json_object_free(json_ar);
14287 json_object_free(json_scode);
14288 json_object_free(json_ocode);
d62a17ae 14289 } else
14290 vty_out(vty,
14291 "%% Inbound soft reconfiguration not enabled\n");
14292
14293 return CMD_WARNING;
14294 }
0b16f239 14295
d9478df0
TA
14296 bgp = peer->bgp;
14297
14298 /* labeled-unicast routes live in the unicast table */
14299 if (safi == SAFI_LABELED_UNICAST)
14300 table = bgp->rib[afi][SAFI_UNICAST];
14301 else
14302 table = bgp->rib[afi][safi];
14303
14304 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14305 || (safi == SAFI_EVPN)) {
14306
14307 struct bgp_dest *dest;
14308
14309 for (dest = bgp_table_top(table); dest;
14310 dest = bgp_route_next(dest)) {
14311 table = bgp_dest_get_bgp_table_info(dest);
14312 if (!table)
14313 continue;
14314
14315 output_count_per_rd = 0;
14316 filtered_count_per_rd = 0;
14317
14318 if (use_json)
14319 json_routes = json_object_new_object();
14320
14321 const struct prefix_rd *prd;
14322 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14323 dest);
14324
14325 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14326
14327 show_adj_route(vty, peer, table, afi, safi, type,
14328 rmap_name, json, json_routes, json_scode,
14329 json_ocode, show_flags, &header1,
14330 &header2, rd_str, &output_count_per_rd,
14331 &filtered_count_per_rd);
14332
14333 /* Don't include an empty RD in the output! */
14334 if (json_routes && (output_count_per_rd > 0))
14335 json_object_object_add(json_ar, rd_str,
14336 json_routes);
14337
14338 output_count += output_count_per_rd;
14339 filtered_count += filtered_count_per_rd;
14340 }
14341 } else
14342 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14343 json, json_ar, json_scode, json_ocode,
14344 show_flags, &header1, &header2, rd_str,
14345 &output_count, &filtered_count);
14346
14347 if (use_json) {
c1984955
TA
14348 if (type == bgp_show_adj_route_advertised)
14349 json_object_object_add(json, "advertisedRoutes",
14350 json_ar);
14351 else
14352 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14353 json_object_int_add(json, "totalPrefixCounter", output_count);
14354 json_object_int_add(json, "filteredPrefixCounter",
14355 filtered_count);
14356
690c3134
MW
14357 /*
14358 * These fields only give up ownership to `json` when `header1`
14359 * is used (set to zero). See code in `show_adj_route` and
14360 * `show_adj_route_header`.
14361 */
14362 if (header1 == 1) {
d9478df0
TA
14363 json_object_free(json_scode);
14364 json_object_free(json_ocode);
14365 }
14366
75eeda93 14367 vty_json(vty, json);
d9478df0
TA
14368 } else if (output_count > 0) {
14369 if (filtered_count > 0)
14370 vty_out(vty,
14371 "\nTotal number of prefixes %ld (%ld filtered)\n",
14372 output_count, filtered_count);
14373 else
14374 vty_out(vty, "\nTotal number of prefixes %ld\n",
14375 output_count);
14376 }
0b16f239 14377
d62a17ae 14378 return CMD_SUCCESS;
a636c635 14379}
50ef26d4 14380
f20ce998
DS
14381DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14382 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14383 "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]",
14384 SHOW_STR
14385 IP_STR
14386 BGP_STR
14387 BGP_INSTANCE_HELP_STR
14388 BGP_AFI_HELP_STR
14389 BGP_SAFI_WITH_LABEL_HELP_STR
14390 "Detailed information on TCP and BGP neighbor connections\n"
14391 "Neighbor to display information about\n"
14392 "Neighbor to display information about\n"
14393 "Neighbor on BGP configured interface\n"
14394 "Display the routes selected by best path\n"
14395 JSON_STR
14396 "Increase table width for longer prefixes\n")
14397{
14398 afi_t afi = AFI_IP6;
14399 safi_t safi = SAFI_UNICAST;
14400 char *rmap_name = NULL;
14401 char *peerstr = NULL;
14402 struct bgp *bgp = NULL;
14403 struct peer *peer;
14404 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14405 int idx = 0;
96c81f66 14406 uint16_t show_flags = 0;
96f3485c
MK
14407
14408 if (uj)
14409 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14410
14411 if (wide)
14412 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14413
14414 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14415 &bgp, uj);
14416
14417 if (!idx)
14418 return CMD_WARNING;
14419
14420 argv_find(argv, argc, "neighbors", &idx);
14421 peerstr = argv[++idx]->arg;
14422
14423 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14424 if (!peer)
14425 return CMD_WARNING;
14426
96f3485c
MK
14427 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14428 show_flags);
f20ce998
DS
14429}
14430
ae248832 14431DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14432 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14433 "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 14434 SHOW_STR
14435 IP_STR
14436 BGP_STR
a636c635 14437 BGP_INSTANCE_HELP_STR
7395a2c9 14438 BGP_AFI_HELP_STR
4dd6177e 14439 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14440 "Display the entries for all address families\n"
718e3744 14441 "Detailed information on TCP and BGP neighbor connections\n"
14442 "Neighbor to display information about\n"
14443 "Neighbor to display information about\n"
91d37724 14444 "Neighbor on BGP configured interface\n"
a636c635 14445 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14446 "Display the received routes from neighbor\n"
14447 "Display the filtered routes received from neighbor\n"
a636c635
DW
14448 "Route-map to modify the attributes\n"
14449 "Name of the route map\n"
ae248832
MK
14450 JSON_STR
14451 "Increase table width for longer prefixes\n")
718e3744 14452{
d62a17ae 14453 afi_t afi = AFI_IP6;
14454 safi_t safi = SAFI_UNICAST;
d62a17ae 14455 char *peerstr = NULL;
d62a17ae 14456 struct bgp *bgp = NULL;
14457 struct peer *peer;
6392aaa6 14458 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14459 int idx = 0;
96f3485c 14460 bool first = true;
96c81f66 14461 uint16_t show_flags = 0;
75ce3b14
DA
14462 struct listnode *node;
14463 struct bgp *abgp;
6392aaa6 14464
96f3485c 14465 if (uj) {
d62a17ae 14466 argc--;
96f3485c
MK
14467 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14468 }
14469
14470 if (all) {
14471 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14472 if (argv_find(argv, argc, "ipv4", &idx))
14473 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14474
14475 if (argv_find(argv, argc, "ipv6", &idx))
14476 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14477 }
14478
14479 if (wide)
14480 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14481
9f049418
DS
14482 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14483 &bgp, uj);
14484 if (!idx)
14485 return CMD_WARNING;
14486
d62a17ae 14487 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14488 argv_find(argv, argc, "neighbors", &idx);
14489 peerstr = argv[++idx]->arg;
8c3deaae 14490
d62a17ae 14491 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14492 if (!peer)
14493 return CMD_WARNING;
856ca177 14494
d62a17ae 14495 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14496 type = bgp_show_adj_route_advertised;
14497 else if (argv_find(argv, argc, "received-routes", &idx))
14498 type = bgp_show_adj_route_received;
14499 else if (argv_find(argv, argc, "filtered-routes", &idx))
14500 type = bgp_show_adj_route_filtered;
14501
96f3485c 14502 if (!all)
70dd370f 14503 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14504 show_flags);
14505 if (uj)
14506 vty_out(vty, "{\n");
14507
14508 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14509 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14510 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14511 : AFI_IP6;
75ce3b14
DA
14512 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14513 FOREACH_SAFI (safi) {
14514 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14515 continue;
96f3485c 14516
75ce3b14
DA
14517 if (uj) {
14518 if (first)
14519 first = false;
14520 else
14521 vty_out(vty, ",\n");
14522 vty_out(vty, "\"%s\":",
14523 get_afi_safi_str(afi, safi,
14524 true));
14525 } else
14526 vty_out(vty,
14527 "\nFor address family: %s\n",
14528 get_afi_safi_str(afi, safi,
14529 false));
96f3485c 14530
75ce3b14 14531 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14532 route_map, show_flags);
75ce3b14 14533 }
96f3485c
MK
14534 }
14535 } else {
75ce3b14
DA
14536 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14537 FOREACH_AFI_SAFI (afi, safi) {
14538 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14539 continue;
96f3485c 14540
75ce3b14
DA
14541 if (uj) {
14542 if (first)
14543 first = false;
14544 else
14545 vty_out(vty, ",\n");
14546 vty_out(vty, "\"%s\":",
14547 get_afi_safi_str(afi, safi,
14548 true));
14549 } else
14550 vty_out(vty,
14551 "\nFor address family: %s\n",
14552 get_afi_safi_str(afi, safi,
14553 false));
96f3485c 14554
75ce3b14 14555 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14556 route_map, show_flags);
75ce3b14 14557 }
96f3485c
MK
14558 }
14559 }
14560 if (uj)
14561 vty_out(vty, "}\n");
14562
14563 return CMD_SUCCESS;
95cbbd2a
ML
14564}
14565
718e3744 14566DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14567 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14568 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14569 SHOW_STR
14570 IP_STR
14571 BGP_STR
d3120452 14572 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14573 BGP_AF_STR
14574 BGP_AF_STR
14575 BGP_AF_MODIFIER_STR
718e3744 14576 "Detailed information on TCP and BGP neighbor connections\n"
14577 "Neighbor to display information about\n"
14578 "Neighbor to display information about\n"
91d37724 14579 "Neighbor on BGP configured interface\n"
718e3744 14580 "Display information received from a BGP neighbor\n"
856ca177 14581 "Display the prefixlist filter\n"
9973d184 14582 JSON_STR)
718e3744 14583{
d62a17ae 14584 afi_t afi = AFI_IP6;
14585 safi_t safi = SAFI_UNICAST;
14586 char *peerstr = NULL;
d62a17ae 14587 char name[BUFSIZ];
d62a17ae 14588 struct peer *peer;
d3120452 14589 int count;
d62a17ae 14590 int idx = 0;
d3120452
IR
14591 struct bgp *bgp = NULL;
14592 bool uj = use_json(argc, argv);
14593
14594 if (uj)
14595 argc--;
14596
14597 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14598 &bgp, uj);
14599 if (!idx)
14600 return CMD_WARNING;
d62a17ae 14601
d62a17ae 14602 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14603 argv_find(argv, argc, "neighbors", &idx);
14604 peerstr = argv[++idx]->arg;
14605
d3120452
IR
14606 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14607 if (!peer)
14608 return CMD_WARNING;
718e3744 14609
4ced1a2c 14610 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14611 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14612 if (count) {
14613 if (!uj)
14614 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14615 get_afi_safi_str(afi, safi, false));
d62a17ae 14616 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14617 } else {
14618 if (uj)
14619 vty_out(vty, "{}\n");
14620 else
14621 vty_out(vty, "No functional output\n");
14622 }
718e3744 14623
d62a17ae 14624 return CMD_SUCCESS;
14625}
14626
14627static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14628 afi_t afi, safi_t safi,
9f049418 14629 enum bgp_show_type type, bool use_json)
d62a17ae 14630{
96c81f66 14631 uint16_t show_flags = 0;
96f3485c
MK
14632
14633 if (use_json)
14634 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14635
d62a17ae 14636 if (!peer || !peer->afc[afi][safi]) {
14637 if (use_json) {
14638 json_object *json_no = NULL;
14639 json_no = json_object_new_object();
14640 json_object_string_add(
14641 json_no, "warning",
14642 "No such neighbor or address family");
14643 vty_out(vty, "%s\n",
14644 json_object_to_json_string(json_no));
14645 json_object_free(json_no);
14646 } else
14647 vty_out(vty, "%% No such neighbor or address family\n");
14648 return CMD_WARNING;
14649 }
47fc97cc 14650
7daf25a3
TA
14651 /* labeled-unicast routes live in the unicast table */
14652 if (safi == SAFI_LABELED_UNICAST)
14653 safi = SAFI_UNICAST;
14654
1e2ce4f1
DS
14655 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14656 RPKI_NOT_BEING_USED);
718e3744 14657}
14658
dba3c1d3
PG
14659DEFUN (show_ip_bgp_flowspec_routes_detailed,
14660 show_ip_bgp_flowspec_routes_detailed_cmd,
14661 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14662 SHOW_STR
14663 IP_STR
14664 BGP_STR
14665 BGP_INSTANCE_HELP_STR
14666 BGP_AFI_HELP_STR
14667 "SAFI Flowspec\n"
14668 "Detailed information on flowspec entries\n"
14669 JSON_STR)
14670{
458c1475 14671 afi_t afi = AFI_IP6;
dba3c1d3
PG
14672 safi_t safi = SAFI_UNICAST;
14673 struct bgp *bgp = NULL;
14674 int idx = 0;
9f049418 14675 bool uj = use_json(argc, argv);
5be6fa9b 14676 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14677
96f3485c 14678 if (uj) {
9f049418 14679 argc--;
96f3485c
MK
14680 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14681 }
dba3c1d3
PG
14682
14683 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14684 &bgp, uj);
dba3c1d3
PG
14685 if (!idx)
14686 return CMD_WARNING;
14687
96f3485c 14688 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14689 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14690}
14691
718e3744 14692DEFUN (show_ip_bgp_neighbor_routes,
14693 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14694 "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 14695 SHOW_STR
14696 IP_STR
14697 BGP_STR
8386ac43 14698 BGP_INSTANCE_HELP_STR
4f280b15 14699 BGP_AFI_HELP_STR
4dd6177e 14700 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14701 "Detailed information on TCP and BGP neighbor connections\n"
14702 "Neighbor to display information about\n"
14703 "Neighbor to display information about\n"
91d37724 14704 "Neighbor on BGP configured interface\n"
2525cf39 14705 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14706 "Display the dampened routes received from neighbor\n"
14707 "Display routes learned from neighbor\n"
9973d184 14708 JSON_STR)
718e3744 14709{
d62a17ae 14710 char *peerstr = NULL;
14711 struct bgp *bgp = NULL;
14712 afi_t afi = AFI_IP6;
14713 safi_t safi = SAFI_UNICAST;
14714 struct peer *peer;
14715 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14716 int idx = 0;
9f049418
DS
14717 bool uj = use_json(argc, argv);
14718
14719 if (uj)
14720 argc--;
bb46e94f 14721
d62a17ae 14722 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14723 &bgp, uj);
d62a17ae 14724 if (!idx)
14725 return CMD_WARNING;
c493f2d8 14726
d62a17ae 14727 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14728 argv_find(argv, argc, "neighbors", &idx);
14729 peerstr = argv[++idx]->arg;
8c3deaae 14730
d62a17ae 14731 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14732 if (!peer)
d62a17ae 14733 return CMD_WARNING;
bb46e94f 14734
d62a17ae 14735 if (argv_find(argv, argc, "flap-statistics", &idx))
14736 sh_type = bgp_show_type_flap_neighbor;
14737 else if (argv_find(argv, argc, "dampened-routes", &idx))
14738 sh_type = bgp_show_type_damp_neighbor;
14739 else if (argv_find(argv, argc, "routes", &idx))
14740 sh_type = bgp_show_type_neighbor;
2525cf39 14741
d62a17ae 14742 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14743}
6b0655a2 14744
734b349e 14745struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14746
d62a17ae 14747struct bgp_distance {
14748 /* Distance value for the IP source prefix. */
d7c0a89a 14749 uint8_t distance;
718e3744 14750
d62a17ae 14751 /* Name of the access-list to be matched. */
14752 char *access_list;
718e3744 14753};
14754
4f280b15
LB
14755DEFUN (show_bgp_afi_vpn_rd_route,
14756 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14757 "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
14758 SHOW_STR
14759 BGP_STR
14760 BGP_AFI_HELP_STR
00e6edb9 14761 BGP_AF_MODIFIER_STR
4f280b15
LB
14762 "Display information for a route distinguisher\n"
14763 "Route Distinguisher\n"
a111dd97 14764 "All Route Distinguishers\n"
7395a2c9
DS
14765 "Network in the BGP routing table to display\n"
14766 "Network in the BGP routing table to display\n"
14767 JSON_STR)
4f280b15 14768{
d62a17ae 14769 int ret;
14770 struct prefix_rd prd;
14771 afi_t afi = AFI_MAX;
14772 int idx = 0;
4f280b15 14773
ff6566f3
DS
14774 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14775 vty_out(vty, "%% Malformed Address Family\n");
14776 return CMD_WARNING;
14777 }
14778
a111dd97
TA
14779 if (!strcmp(argv[5]->arg, "all"))
14780 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14781 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14782 RPKI_NOT_BEING_USED,
14783 use_json(argc, argv));
14784
d62a17ae 14785 ret = str2prefix_rd(argv[5]->arg, &prd);
14786 if (!ret) {
14787 vty_out(vty, "%% Malformed Route Distinguisher\n");
14788 return CMD_WARNING;
14789 }
ff6566f3 14790
d62a17ae 14791 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14792 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14793 use_json(argc, argv));
4f280b15
LB
14794}
14795
d62a17ae 14796static struct bgp_distance *bgp_distance_new(void)
718e3744 14797{
d62a17ae 14798 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14799}
14800
d62a17ae 14801static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14802{
d62a17ae 14803 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14804}
14805
585f1adc
IR
14806static int bgp_distance_set(struct vty *vty, const char *distance_str,
14807 const char *ip_str, const char *access_list_str)
718e3744 14808{
d62a17ae 14809 int ret;
585f1adc
IR
14810 afi_t afi;
14811 safi_t safi;
d62a17ae 14812 struct prefix p;
585f1adc 14813 uint8_t distance;
9bcb3eef 14814 struct bgp_dest *dest;
d62a17ae 14815 struct bgp_distance *bdistance;
718e3744 14816
585f1adc
IR
14817 afi = bgp_node_afi(vty);
14818 safi = bgp_node_safi(vty);
14819
d62a17ae 14820 ret = str2prefix(ip_str, &p);
14821 if (ret == 0) {
585f1adc 14822 vty_out(vty, "Malformed prefix\n");
d62a17ae 14823 return CMD_WARNING_CONFIG_FAILED;
14824 }
718e3744 14825
585f1adc
IR
14826 distance = atoi(distance_str);
14827
d62a17ae 14828 /* Get BGP distance node. */
9bcb3eef
DS
14829 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14830 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14831 if (bdistance)
9bcb3eef 14832 bgp_dest_unlock_node(dest);
ca2e160d 14833 else {
d62a17ae 14834 bdistance = bgp_distance_new();
9bcb3eef 14835 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14836 }
718e3744 14837
d62a17ae 14838 /* Set distance value. */
14839 bdistance->distance = distance;
718e3744 14840
d62a17ae 14841 /* Reset access-list configuration. */
e1b36e13 14842 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14843 if (access_list_str)
14844 bdistance->access_list =
14845 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14846
d62a17ae 14847 return CMD_SUCCESS;
718e3744 14848}
14849
585f1adc
IR
14850static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14851 const char *ip_str, const char *access_list_str)
718e3744 14852{
d62a17ae 14853 int ret;
585f1adc
IR
14854 afi_t afi;
14855 safi_t safi;
d62a17ae 14856 struct prefix p;
585f1adc 14857 int distance;
9bcb3eef 14858 struct bgp_dest *dest;
d62a17ae 14859 struct bgp_distance *bdistance;
718e3744 14860
585f1adc
IR
14861 afi = bgp_node_afi(vty);
14862 safi = bgp_node_safi(vty);
14863
d62a17ae 14864 ret = str2prefix(ip_str, &p);
14865 if (ret == 0) {
585f1adc 14866 vty_out(vty, "Malformed prefix\n");
d62a17ae 14867 return CMD_WARNING_CONFIG_FAILED;
14868 }
718e3744 14869
9bcb3eef
DS
14870 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14871 if (!dest) {
585f1adc 14872 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14873 return CMD_WARNING_CONFIG_FAILED;
14874 }
718e3744 14875
9bcb3eef 14876 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14877 distance = atoi(distance_str);
1f9a9fff 14878
d62a17ae 14879 if (bdistance->distance != distance) {
585f1adc 14880 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14881 bgp_dest_unlock_node(dest);
d62a17ae 14882 return CMD_WARNING_CONFIG_FAILED;
14883 }
718e3744 14884
0a22ddfb 14885 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14886 bgp_distance_free(bdistance);
718e3744 14887
9bcb3eef
DS
14888 bgp_dest_set_bgp_path_info(dest, NULL);
14889 bgp_dest_unlock_node(dest);
14890 bgp_dest_unlock_node(dest);
718e3744 14891
d62a17ae 14892 return CMD_SUCCESS;
718e3744 14893}
14894
718e3744 14895/* Apply BGP information to distance method. */
b8685f9b 14896uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14897 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14898{
9bcb3eef 14899 struct bgp_dest *dest;
801bb996 14900 struct prefix q = {0};
d62a17ae 14901 struct peer *peer;
14902 struct bgp_distance *bdistance;
14903 struct access_list *alist;
14904 struct bgp_static *bgp_static;
14905
14906 if (!bgp)
14907 return 0;
14908
40381db7 14909 peer = pinfo->peer;
d62a17ae 14910
7b7d48e5
DS
14911 if (pinfo->attr->distance)
14912 return pinfo->attr->distance;
14913
801bb996
CS
14914 /* Check source address.
14915 * Note: for aggregate route, peer can have unspec af type.
14916 */
14917 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14918 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14919 return 0;
14920
9bcb3eef
DS
14921 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14922 if (dest) {
14923 bdistance = bgp_dest_get_bgp_distance_info(dest);
14924 bgp_dest_unlock_node(dest);
d62a17ae 14925
14926 if (bdistance->access_list) {
14927 alist = access_list_lookup(afi, bdistance->access_list);
14928 if (alist
14929 && access_list_apply(alist, p) == FILTER_PERMIT)
14930 return bdistance->distance;
14931 } else
14932 return bdistance->distance;
718e3744 14933 }
718e3744 14934
d62a17ae 14935 /* Backdoor check. */
9bcb3eef
DS
14936 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14937 if (dest) {
14938 bgp_static = bgp_dest_get_bgp_static_info(dest);
14939 bgp_dest_unlock_node(dest);
718e3744 14940
d62a17ae 14941 if (bgp_static->backdoor) {
14942 if (bgp->distance_local[afi][safi])
14943 return bgp->distance_local[afi][safi];
14944 else
14945 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14946 }
718e3744 14947 }
718e3744 14948
d62a17ae 14949 if (peer->sort == BGP_PEER_EBGP) {
14950 if (bgp->distance_ebgp[afi][safi])
14951 return bgp->distance_ebgp[afi][safi];
14952 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14953 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14954 if (bgp->distance_ibgp[afi][safi])
14955 return bgp->distance_ibgp[afi][safi];
14956 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14957 } else {
14958 if (bgp->distance_local[afi][safi])
14959 return bgp->distance_local[afi][safi];
14960 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14961 }
718e3744 14962}
14963
a612fb77
DA
14964/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14965 * we should tell ZEBRA update the routes for a specific
14966 * AFI/SAFI to reflect changes in RIB.
14967 */
585f1adc
IR
14968static void bgp_announce_routes_distance_update(struct bgp *bgp,
14969 afi_t update_afi,
14970 safi_t update_safi)
a612fb77
DA
14971{
14972 afi_t afi;
14973 safi_t safi;
14974
14975 FOREACH_AFI_SAFI (afi, safi) {
14976 if (!bgp_fibupd_safi(safi))
14977 continue;
14978
8b54bc30
DA
14979 if (afi != update_afi && safi != update_safi)
14980 continue;
14981
14982 if (BGP_DEBUG(zebra, ZEBRA))
14983 zlog_debug(
14984 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14985 __func__, afi, safi);
14986 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14987 }
14988}
14989
585f1adc
IR
14990DEFUN (bgp_distance,
14991 bgp_distance_cmd,
14992 "distance bgp (1-255) (1-255) (1-255)",
14993 "Define an administrative distance\n"
14994 "BGP distance\n"
14995 "Distance for routes external to the AS\n"
14996 "Distance for routes internal to the AS\n"
14997 "Distance for local routes\n")
718e3744 14998{
585f1adc 14999 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15000 int idx_number = 2;
15001 int idx_number_2 = 3;
15002 int idx_number_3 = 4;
585f1adc
IR
15003 int distance_ebgp = atoi(argv[idx_number]->arg);
15004 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15005 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15006 afi_t afi;
15007 safi_t safi;
718e3744 15008
d62a17ae 15009 afi = bgp_node_afi(vty);
15010 safi = bgp_node_safi(vty);
718e3744 15011
585f1adc
IR
15012 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15013 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15014 || bgp->distance_local[afi][safi] != distance_local) {
15015 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15016 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15017 bgp->distance_local[afi][safi] = distance_local;
15018 bgp_announce_routes_distance_update(bgp, afi, safi);
15019 }
15020 return CMD_SUCCESS;
15021}
37a87b8f 15022
585f1adc
IR
15023DEFUN (no_bgp_distance,
15024 no_bgp_distance_cmd,
15025 "no distance bgp [(1-255) (1-255) (1-255)]",
15026 NO_STR
15027 "Define an administrative distance\n"
15028 "BGP distance\n"
15029 "Distance for routes external to the AS\n"
15030 "Distance for routes internal to the AS\n"
15031 "Distance for local routes\n")
718e3744 15032{
585f1adc 15033 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15034 afi_t afi;
15035 safi_t safi;
37a87b8f
CS
15036
15037 afi = bgp_node_afi(vty);
15038 safi = bgp_node_safi(vty);
15039
585f1adc
IR
15040 if (bgp->distance_ebgp[afi][safi] != 0
15041 || bgp->distance_ibgp[afi][safi] != 0
15042 || bgp->distance_local[afi][safi] != 0) {
15043 bgp->distance_ebgp[afi][safi] = 0;
15044 bgp->distance_ibgp[afi][safi] = 0;
15045 bgp->distance_local[afi][safi] = 0;
15046 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15047 }
585f1adc
IR
15048 return CMD_SUCCESS;
15049}
37a87b8f 15050
37a87b8f 15051
585f1adc
IR
15052DEFUN (bgp_distance_source,
15053 bgp_distance_source_cmd,
15054 "distance (1-255) A.B.C.D/M",
15055 "Define an administrative distance\n"
15056 "Administrative distance\n"
15057 "IP source prefix\n")
15058{
15059 int idx_number = 1;
15060 int idx_ipv4_prefixlen = 2;
15061 bgp_distance_set(vty, argv[idx_number]->arg,
15062 argv[idx_ipv4_prefixlen]->arg, NULL);
15063 return CMD_SUCCESS;
734b349e
MZ
15064}
15065
585f1adc
IR
15066DEFUN (no_bgp_distance_source,
15067 no_bgp_distance_source_cmd,
15068 "no distance (1-255) A.B.C.D/M",
15069 NO_STR
15070 "Define an administrative distance\n"
15071 "Administrative distance\n"
15072 "IP source prefix\n")
37a87b8f 15073{
585f1adc
IR
15074 int idx_number = 2;
15075 int idx_ipv4_prefixlen = 3;
15076 bgp_distance_unset(vty, argv[idx_number]->arg,
15077 argv[idx_ipv4_prefixlen]->arg, NULL);
15078 return CMD_SUCCESS;
37a87b8f
CS
15079}
15080
585f1adc
IR
15081DEFUN (bgp_distance_source_access_list,
15082 bgp_distance_source_access_list_cmd,
15083 "distance (1-255) A.B.C.D/M WORD",
15084 "Define an administrative distance\n"
15085 "Administrative distance\n"
15086 "IP source prefix\n"
15087 "Access list name\n")
37a87b8f 15088{
585f1adc
IR
15089 int idx_number = 1;
15090 int idx_ipv4_prefixlen = 2;
15091 int idx_word = 3;
15092 bgp_distance_set(vty, argv[idx_number]->arg,
15093 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15094 return CMD_SUCCESS;
15095}
718e3744 15096
585f1adc
IR
15097DEFUN (no_bgp_distance_source_access_list,
15098 no_bgp_distance_source_access_list_cmd,
15099 "no distance (1-255) A.B.C.D/M WORD",
15100 NO_STR
15101 "Define an administrative distance\n"
15102 "Administrative distance\n"
15103 "IP source prefix\n"
15104 "Access list name\n")
15105{
15106 int idx_number = 2;
15107 int idx_ipv4_prefixlen = 3;
15108 int idx_word = 4;
15109 bgp_distance_unset(vty, argv[idx_number]->arg,
15110 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15111 return CMD_SUCCESS;
15112}
37a87b8f 15113
585f1adc
IR
15114DEFUN (ipv6_bgp_distance_source,
15115 ipv6_bgp_distance_source_cmd,
15116 "distance (1-255) X:X::X:X/M",
15117 "Define an administrative distance\n"
15118 "Administrative distance\n"
15119 "IP source prefix\n")
15120{
15121 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15122 return CMD_SUCCESS;
15123}
7ebe9748 15124
585f1adc
IR
15125DEFUN (no_ipv6_bgp_distance_source,
15126 no_ipv6_bgp_distance_source_cmd,
15127 "no distance (1-255) X:X::X:X/M",
15128 NO_STR
15129 "Define an administrative distance\n"
15130 "Administrative distance\n"
15131 "IP source prefix\n")
15132{
15133 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15134 return CMD_SUCCESS;
15135}
37a87b8f 15136
585f1adc
IR
15137DEFUN (ipv6_bgp_distance_source_access_list,
15138 ipv6_bgp_distance_source_access_list_cmd,
15139 "distance (1-255) X:X::X:X/M WORD",
15140 "Define an administrative distance\n"
15141 "Administrative distance\n"
15142 "IP source prefix\n"
15143 "Access list name\n")
15144{
15145 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15146 return CMD_SUCCESS;
718e3744 15147}
15148
585f1adc
IR
15149DEFUN (no_ipv6_bgp_distance_source_access_list,
15150 no_ipv6_bgp_distance_source_access_list_cmd,
15151 "no distance (1-255) X:X::X:X/M WORD",
15152 NO_STR
15153 "Define an administrative distance\n"
15154 "Administrative distance\n"
15155 "IP source prefix\n"
15156 "Access list name\n")
718e3744 15157{
585f1adc
IR
15158 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15159 return CMD_SUCCESS;
15160}
37a87b8f 15161
585f1adc
IR
15162DEFUN (bgp_damp_set,
15163 bgp_damp_set_cmd,
a30fec23 15164 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15165 "BGP Specific commands\n"
15166 "Enable route-flap dampening\n"
15167 "Half-life time for the penalty\n"
15168 "Value to start reusing a route\n"
15169 "Value to start suppressing a route\n"
15170 "Maximum duration to suppress a stable route\n")
15171{
15172 VTY_DECLVAR_CONTEXT(bgp, bgp);
15173 int idx_half_life = 2;
15174 int idx_reuse = 3;
15175 int idx_suppress = 4;
15176 int idx_max_suppress = 5;
37a87b8f
CS
15177 int half = DEFAULT_HALF_LIFE * 60;
15178 int reuse = DEFAULT_REUSE;
15179 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15180 int max = 4 * half;
15181
15182 if (argc == 6) {
15183 half = atoi(argv[idx_half_life]->arg) * 60;
15184 reuse = atoi(argv[idx_reuse]->arg);
15185 suppress = atoi(argv[idx_suppress]->arg);
15186 max = atoi(argv[idx_max_suppress]->arg) * 60;
15187 } else if (argc == 3) {
15188 half = atoi(argv[idx_half_life]->arg) * 60;
15189 max = 4 * half;
15190 }
15191
15192 /*
15193 * These can't be 0 but our SA doesn't understand the
15194 * way our cli is constructed
15195 */
15196 assert(reuse);
15197 assert(half);
15198 if (suppress < reuse) {
15199 vty_out(vty,
15200 "Suppress value cannot be less than reuse value \n");
15201 return 0;
15202 }
15203
15204 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15205 reuse, suppress, max);
15206}
15207
15208DEFUN (bgp_damp_unset,
15209 bgp_damp_unset_cmd,
a30fec23 15210 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15211 NO_STR
15212 "BGP Specific commands\n"
15213 "Enable route-flap dampening\n"
15214 "Half-life time for the penalty\n"
15215 "Value to start reusing a route\n"
15216 "Value to start suppressing a route\n"
15217 "Maximum duration to suppress a stable route\n")
15218{
15219 VTY_DECLVAR_CONTEXT(bgp, bgp);
15220 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15221}
15222
718e3744 15223/* Display specified route of BGP table. */
d62a17ae 15224static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15225 const char *ip_str, afi_t afi, safi_t safi,
15226 struct prefix_rd *prd, int prefix_check)
15227{
15228 int ret;
15229 struct prefix match;
9bcb3eef
DS
15230 struct bgp_dest *dest;
15231 struct bgp_dest *rm;
40381db7
DS
15232 struct bgp_path_info *pi;
15233 struct bgp_path_info *pi_temp;
d62a17ae 15234 struct bgp *bgp;
15235 struct bgp_table *table;
15236
15237 /* BGP structure lookup. */
15238 if (view_name) {
15239 bgp = bgp_lookup_by_name(view_name);
15240 if (bgp == NULL) {
15241 vty_out(vty, "%% Can't find BGP instance %s\n",
15242 view_name);
15243 return CMD_WARNING;
15244 }
15245 } else {
15246 bgp = bgp_get_default();
15247 if (bgp == NULL) {
15248 vty_out(vty, "%% No BGP process is configured\n");
15249 return CMD_WARNING;
15250 }
718e3744 15251 }
718e3744 15252
d62a17ae 15253 /* Check IP address argument. */
15254 ret = str2prefix(ip_str, &match);
15255 if (!ret) {
15256 vty_out(vty, "%% address is malformed\n");
15257 return CMD_WARNING;
15258 }
718e3744 15259
d62a17ae 15260 match.family = afi2family(afi);
15261
15262 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15263 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15264 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15265 dest = bgp_route_next(dest)) {
15266 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15267
9bcb3eef 15268 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15269 continue;
9bcb3eef 15270 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15271 if (!table)
ea47320b 15272 continue;
4953391b
DA
15273 rm = bgp_node_match(table, &match);
15274 if (rm == NULL)
ea47320b 15275 continue;
d62a17ae 15276
9bcb3eef 15277 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15278
ea47320b 15279 if (!prefix_check
b54892e0 15280 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15281 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15282 while (pi) {
15283 if (pi->extra && pi->extra->damp_info) {
15284 pi_temp = pi->next;
ea47320b 15285 bgp_damp_info_free(
19971c9a 15286 pi->extra->damp_info,
5c8846f6 15287 1, afi, safi);
40381db7 15288 pi = pi_temp;
ea47320b 15289 } else
40381db7 15290 pi = pi->next;
d62a17ae 15291 }
ea47320b
DL
15292 }
15293
9bcb3eef 15294 bgp_dest_unlock_node(rm);
d62a17ae 15295 }
15296 } else {
4953391b
DA
15297 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15298 if (dest != NULL) {
9bcb3eef 15299 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15300
d62a17ae 15301 if (!prefix_check
9bcb3eef
DS
15302 || dest_p->prefixlen == match.prefixlen) {
15303 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15304 while (pi) {
15305 if (pi->extra && pi->extra->damp_info) {
15306 pi_temp = pi->next;
d62a17ae 15307 bgp_damp_info_free(
19971c9a 15308 pi->extra->damp_info,
5c8846f6 15309 1, afi, safi);
40381db7 15310 pi = pi_temp;
d62a17ae 15311 } else
40381db7 15312 pi = pi->next;
d62a17ae 15313 }
15314 }
15315
9bcb3eef 15316 bgp_dest_unlock_node(dest);
d62a17ae 15317 }
15318 }
718e3744 15319
d62a17ae 15320 return CMD_SUCCESS;
718e3744 15321}
15322
15323DEFUN (clear_ip_bgp_dampening,
15324 clear_ip_bgp_dampening_cmd,
15325 "clear ip bgp dampening",
15326 CLEAR_STR
15327 IP_STR
15328 BGP_STR
15329 "Clear route flap dampening information\n")
15330{
b4f7f45b 15331 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15332 return CMD_SUCCESS;
718e3744 15333}
15334
15335DEFUN (clear_ip_bgp_dampening_prefix,
15336 clear_ip_bgp_dampening_prefix_cmd,
15337 "clear ip bgp dampening A.B.C.D/M",
15338 CLEAR_STR
15339 IP_STR
15340 BGP_STR
15341 "Clear route flap dampening information\n"
0c7b1b01 15342 "IPv4 prefix\n")
718e3744 15343{
d62a17ae 15344 int idx_ipv4_prefixlen = 4;
15345 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15346 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15347}
15348
15349DEFUN (clear_ip_bgp_dampening_address,
15350 clear_ip_bgp_dampening_address_cmd,
15351 "clear ip bgp dampening A.B.C.D",
15352 CLEAR_STR
15353 IP_STR
15354 BGP_STR
15355 "Clear route flap dampening information\n"
15356 "Network to clear damping information\n")
15357{
d62a17ae 15358 int idx_ipv4 = 4;
15359 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15360 SAFI_UNICAST, NULL, 0);
718e3744 15361}
15362
15363DEFUN (clear_ip_bgp_dampening_address_mask,
15364 clear_ip_bgp_dampening_address_mask_cmd,
15365 "clear ip bgp dampening A.B.C.D A.B.C.D",
15366 CLEAR_STR
15367 IP_STR
15368 BGP_STR
15369 "Clear route flap dampening information\n"
15370 "Network to clear damping information\n"
15371 "Network mask\n")
15372{
d62a17ae 15373 int idx_ipv4 = 4;
15374 int idx_ipv4_2 = 5;
15375 int ret;
15376 char prefix_str[BUFSIZ];
718e3744 15377
d62a17ae 15378 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15379 prefix_str, sizeof(prefix_str));
d62a17ae 15380 if (!ret) {
15381 vty_out(vty, "%% Inconsistent address and mask\n");
15382 return CMD_WARNING;
15383 }
718e3744 15384
d62a17ae 15385 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15386 NULL, 0);
718e3744 15387}
6b0655a2 15388
e3b78da8 15389static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15390{
15391 struct vty *vty = arg;
e3b78da8 15392 struct peer *peer = bucket->data;
825d9834 15393
47e12884 15394 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15395}
15396
2a0e69ae
DS
15397DEFUN (show_bgp_listeners,
15398 show_bgp_listeners_cmd,
15399 "show bgp listeners",
15400 SHOW_STR
15401 BGP_STR
15402 "Display Listen Sockets and who created them\n")
15403{
15404 bgp_dump_listener_info(vty);
15405
15406 return CMD_SUCCESS;
15407}
15408
825d9834
DS
15409DEFUN (show_bgp_peerhash,
15410 show_bgp_peerhash_cmd,
15411 "show bgp peerhash",
15412 SHOW_STR
15413 BGP_STR
15414 "Display information about the BGP peerhash\n")
15415{
15416 struct list *instances = bm->bgp;
15417 struct listnode *node;
15418 struct bgp *bgp;
15419
15420 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15421 vty_out(vty, "BGP: %s\n", bgp->name);
15422 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15423 vty);
15424 }
15425
15426 return CMD_SUCCESS;
15427}
15428
587ff0fd 15429/* also used for encap safi */
2b791107
DL
15430static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15431 afi_t afi, safi_t safi)
d62a17ae 15432{
9bcb3eef
DS
15433 struct bgp_dest *pdest;
15434 struct bgp_dest *dest;
d62a17ae 15435 struct bgp_table *table;
b54892e0
DS
15436 const struct prefix *p;
15437 const struct prefix_rd *prd;
d62a17ae 15438 struct bgp_static *bgp_static;
15439 mpls_label_t label;
d62a17ae 15440
15441 /* Network configuration. */
9bcb3eef
DS
15442 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15443 pdest = bgp_route_next(pdest)) {
15444 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15445 if (!table)
ea47320b 15446 continue;
d62a17ae 15447
9bcb3eef
DS
15448 for (dest = bgp_table_top(table); dest;
15449 dest = bgp_route_next(dest)) {
15450 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15451 if (bgp_static == NULL)
ea47320b 15452 continue;
d62a17ae 15453
9bcb3eef
DS
15454 p = bgp_dest_get_prefix(dest);
15455 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15456 pdest);
d62a17ae 15457
ea47320b 15458 /* "network" configuration display. */
ea47320b
DL
15459 label = decode_label(&bgp_static->label);
15460
c4f64ea9 15461 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15462 if (safi == SAFI_MPLS_VPN)
15463 vty_out(vty, " label %u", label);
15464
15465 if (bgp_static->rmap.name)
15466 vty_out(vty, " route-map %s",
15467 bgp_static->rmap.name);
e2a86ad9
DS
15468
15469 if (bgp_static->backdoor)
15470 vty_out(vty, " backdoor");
15471
ea47320b
DL
15472 vty_out(vty, "\n");
15473 }
15474 }
d62a17ae 15475}
15476
2b791107
DL
15477static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15478 afi_t afi, safi_t safi)
d62a17ae 15479{
9bcb3eef
DS
15480 struct bgp_dest *pdest;
15481 struct bgp_dest *dest;
d62a17ae 15482 struct bgp_table *table;
b54892e0
DS
15483 const struct prefix *p;
15484 const struct prefix_rd *prd;
d62a17ae 15485 struct bgp_static *bgp_static;
ff44f570 15486 char buf[PREFIX_STRLEN * 2];
d62a17ae 15487 char buf2[SU_ADDRSTRLEN];
5f933e1e 15488 char esi_buf[ESI_STR_LEN];
d62a17ae 15489
15490 /* Network configuration. */
9bcb3eef
DS
15491 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15492 pdest = bgp_route_next(pdest)) {
15493 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15494 if (!table)
ea47320b 15495 continue;
d62a17ae 15496
9bcb3eef
DS
15497 for (dest = bgp_table_top(table); dest;
15498 dest = bgp_route_next(dest)) {
15499 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15500 if (bgp_static == NULL)
ea47320b 15501 continue;
d62a17ae 15502
ea47320b 15503 char *macrouter = NULL;
d62a17ae 15504
ea47320b
DL
15505 if (bgp_static->router_mac)
15506 macrouter = prefix_mac2str(
15507 bgp_static->router_mac, NULL, 0);
15508 if (bgp_static->eth_s_id)
0a50c248
AK
15509 esi_to_str(bgp_static->eth_s_id,
15510 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15511 p = bgp_dest_get_prefix(dest);
15512 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15513
ea47320b 15514 /* "network" configuration display. */
197cb530
PG
15515 if (p->u.prefix_evpn.route_type == 5) {
15516 char local_buf[PREFIX_STRLEN];
3714a385 15517 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15518 struct prefix_evpn *)p)
15519 ? AF_INET
15520 : AF_INET6;
3714a385 15521 inet_ntop(family,
15522 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15523 local_buf, PREFIX_STRLEN);
772270f3
QY
15524 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15525 p->u.prefix_evpn.prefix_addr
15526 .ip_prefix_length);
197cb530
PG
15527 } else {
15528 prefix2str(p, buf, sizeof(buf));
15529 }
ea47320b 15530
a4d82a8a
PZ
15531 if (bgp_static->gatewayIp.family == AF_INET
15532 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15533 inet_ntop(bgp_static->gatewayIp.family,
15534 &bgp_static->gatewayIp.u.prefix, buf2,
15535 sizeof(buf2));
ea47320b 15536 vty_out(vty,
c4f64ea9
DA
15537 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15538 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15539 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15540 macrouter);
15541
0a22ddfb 15542 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15543 }
15544 }
3da6fcd5
PG
15545}
15546
718e3744 15547/* Configuration of static route announcement and aggregate
15548 information. */
2b791107
DL
15549void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15550 safi_t safi)
d62a17ae 15551{
9bcb3eef 15552 struct bgp_dest *dest;
b54892e0 15553 const struct prefix *p;
d62a17ae 15554 struct bgp_static *bgp_static;
15555 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15556
2b791107
DL
15557 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15558 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15559 return;
15560 }
d62a17ae 15561
2b791107
DL
15562 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15563 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15564 return;
15565 }
d62a17ae 15566
15567 /* Network configuration. */
9bcb3eef
DS
15568 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15569 dest = bgp_route_next(dest)) {
15570 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15571 if (bgp_static == NULL)
ea47320b 15572 continue;
d62a17ae 15573
9bcb3eef 15574 p = bgp_dest_get_prefix(dest);
d62a17ae 15575
8228a9a7 15576 vty_out(vty, " network %pFX", p);
d62a17ae 15577
ea47320b
DL
15578 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15579 vty_out(vty, " label-index %u",
15580 bgp_static->label_index);
d62a17ae 15581
ea47320b
DL
15582 if (bgp_static->rmap.name)
15583 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15584
15585 if (bgp_static->backdoor)
15586 vty_out(vty, " backdoor");
718e3744 15587
ea47320b
DL
15588 vty_out(vty, "\n");
15589 }
15590
d62a17ae 15591 /* Aggregate-address configuration. */
9bcb3eef
DS
15592 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15593 dest = bgp_route_next(dest)) {
15594 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15595 if (bgp_aggregate == NULL)
ea47320b 15596 continue;
d62a17ae 15597
9bcb3eef 15598 p = bgp_dest_get_prefix(dest);
d62a17ae 15599
8228a9a7 15600 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15601
ea47320b
DL
15602 if (bgp_aggregate->as_set)
15603 vty_out(vty, " as-set");
d62a17ae 15604
ea47320b
DL
15605 if (bgp_aggregate->summary_only)
15606 vty_out(vty, " summary-only");
718e3744 15607
20894f50
DA
15608 if (bgp_aggregate->rmap.name)
15609 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15610
229757f1
DA
15611 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15612 vty_out(vty, " origin %s",
15613 bgp_origin2str(bgp_aggregate->origin));
15614
6aabb15d
RZ
15615 if (bgp_aggregate->match_med)
15616 vty_out(vty, " matching-MED-only");
15617
365ab2e7
RZ
15618 if (bgp_aggregate->suppress_map_name)
15619 vty_out(vty, " suppress-map %s",
15620 bgp_aggregate->suppress_map_name);
15621
ea47320b
DL
15622 vty_out(vty, "\n");
15623 }
d62a17ae 15624}
734b349e 15625
2b791107 15626void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15627 safi_t safi)
d62a17ae 15628{
9bcb3eef 15629 struct bgp_dest *dest;
d62a17ae 15630 struct bgp_distance *bdistance;
15631
15632 /* Distance configuration. */
15633 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15634 && bgp->distance_local[afi][safi]
15635 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15636 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15637 || bgp->distance_local[afi][safi]
15638 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15639 vty_out(vty, " distance bgp %d %d %d\n",
15640 bgp->distance_ebgp[afi][safi],
15641 bgp->distance_ibgp[afi][safi],
15642 bgp->distance_local[afi][safi]);
15643 }
734b349e 15644
9bcb3eef
DS
15645 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15646 dest = bgp_route_next(dest)) {
15647 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15648 if (bdistance != NULL)
56ca3b5b 15649 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15650 bdistance->distance, dest,
d62a17ae 15651 bdistance->access_list ? bdistance->access_list
15652 : "");
ca2e160d 15653 }
718e3744 15654}
15655
15656/* Allocate routing table structure and install commands. */
d62a17ae 15657void bgp_route_init(void)
15658{
15659 afi_t afi;
15660 safi_t safi;
15661
15662 /* Init BGP distance table. */
05c7a1cc 15663 FOREACH_AFI_SAFI (afi, safi)
960035b2 15664 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15665
15666 /* IPv4 BGP commands. */
15667 install_element(BGP_NODE, &bgp_table_map_cmd);
15668 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15669 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15670
554b3b10 15671 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15672
15673 /* IPv4 unicast configuration. */
15674 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15675 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15676 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15677
554b3b10 15678 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15679
15680 /* IPv4 multicast configuration. */
15681 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15682 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15683 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15684 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15685
15686 /* IPv4 labeled-unicast configuration. */
fb985e0c 15687 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15688 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15689
d62a17ae 15690 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15691 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15692 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15693 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15694 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15695 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15696 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15697 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15698
15699 install_element(VIEW_NODE,
15700 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15701 install_element(VIEW_NODE,
15702 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15703 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15704 install_element(VIEW_NODE,
15705 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15706#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15707 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15708#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15709 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15710 install_element(VIEW_NODE,
44c69747 15711 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15712
d62a17ae 15713 /* BGP dampening clear commands */
15714 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15715 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15716
d62a17ae 15717 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15718 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15719
15720 /* prefix count */
15721 install_element(ENABLE_NODE,
15722 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15723#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15724 install_element(ENABLE_NODE,
15725 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15726#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15727
d62a17ae 15728 /* New config IPv6 BGP commands. */
15729 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15730 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15731 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15732
554b3b10 15733 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15734
15735 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15736
fb985e0c
DA
15737 /* IPv6 labeled unicast address family. */
15738 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15739 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15740
d62a17ae 15741 install_element(BGP_NODE, &bgp_distance_cmd);
15742 install_element(BGP_NODE, &no_bgp_distance_cmd);
15743 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15744 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15745 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15746 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15747 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15748 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15749 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15750 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15751 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15752 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15753 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15754 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15755 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15756 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15757 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15758 install_element(BGP_IPV4M_NODE,
15759 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15760 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15761 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15762 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15763 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15764 install_element(BGP_IPV6_NODE,
15765 &ipv6_bgp_distance_source_access_list_cmd);
15766 install_element(BGP_IPV6_NODE,
15767 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15768 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15769 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15770 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15771 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15772 install_element(BGP_IPV6M_NODE,
15773 &ipv6_bgp_distance_source_access_list_cmd);
15774 install_element(BGP_IPV6M_NODE,
15775 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15776
ef5f4b23 15777 /* BGP dampening */
585f1adc
IR
15778 install_element(BGP_NODE, &bgp_damp_set_cmd);
15779 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15780 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15781 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15782 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15783 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15784 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15785 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15786 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15787 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15788 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15789 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15790 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15791 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15792
15793 /* Large Communities */
15794 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15795 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15796
15797 /* show bgp ipv4 flowspec detailed */
15798 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15799
2a0e69ae 15800 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15801 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15802}
15803
15804void bgp_route_finish(void)
15805{
15806 afi_t afi;
15807 safi_t safi;
15808
05c7a1cc
QY
15809 FOREACH_AFI_SAFI (afi, safi) {
15810 bgp_table_unlock(bgp_distance_table[afi][safi]);
15811 bgp_distance_table[afi][safi] = NULL;
15812 }
228da428 15813}