]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Print prefix in logs messages with BGP_PATH_ANNC_NH_SELF
[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(
6cf8a4bf
DA
2586 "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2587 __func__, p, family2str(family));
960035b2 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;
f8745525 4047 const struct prefix *bgp_nht_param_prefix;
718e3744 4048
907707db
MS
4049 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4050 if (orig_safi == SAFI_LABELED_UNICAST)
4051 safi = SAFI_UNICAST;
4052
6006b807 4053 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 4054 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4055 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 4056
d62a17ae 4057 bgp = peer->bgp;
9bcb3eef 4058 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
4059 /* TODO: Check to see if we can get rid of "is_valid_label" */
4060 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4061 has_valid_label = (num_labels > 0) ? 1 : 0;
4062 else
4063 has_valid_label = bgp_is_valid_label(label);
718e3744 4064
28f66de2
MS
4065 if (has_valid_label)
4066 assert(label != NULL);
4067
66ff6089
AD
4068 /* Update overlay index of the attribute */
4069 if (afi == AFI_L2VPN && evpn)
4070 memcpy(&attr->evpn_overlay, evpn,
4071 sizeof(struct bgp_route_evpn));
4072
d62a17ae 4073 /* When peer's soft reconfiguration enabled. Record input packet in
4074 Adj-RIBs-In. */
4075 if (!soft_reconfig
4076 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4077 && peer != bgp->peer_self)
9bcb3eef 4078 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 4079
b2ac1d0d
MS
4080 /* Update permitted loop count */
4081 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4082 allowas_in = peer->allowas_in[afi][safi];
4083
d62a17ae 4084 /* Check previously received route. */
9bcb3eef 4085 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4086 if (pi->peer == peer && pi->type == type
4087 && pi->sub_type == sub_type
4088 && pi->addpath_rx_id == addpath_id)
d62a17ae 4089 break;
4090
4091 /* AS path local-as loop check. */
4092 if (peer->change_local_as) {
b2ac1d0d
MS
4093 if (allowas_in)
4094 aspath_loop_count = allowas_in;
a4d82a8a
PZ
4095 else if (!CHECK_FLAG(peer->flags,
4096 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 4097 aspath_loop_count = 1;
4098
4099 if (aspath_loop_check(attr->aspath, peer->change_local_as)
4100 > aspath_loop_count) {
b4d46cc9 4101 peer->stat_pfx_aspath_loop++;
692174a1 4102 reason = "as-path contains our own AS;";
d62a17ae 4103 goto filtered;
4104 }
718e3744 4105 }
718e3744 4106
d62a17ae 4107 /* If the peer is configured for "allowas-in origin" and the last ASN in
4108 * the
4109 * as-path is our ASN then we do not need to call aspath_loop_check
4110 */
4111 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4112 if (aspath_get_last_as(attr->aspath) == bgp->as)
4113 do_loop_check = 0;
4114
f8745525
PG
4115 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4116 bgp_nht_param_prefix = NULL;
4117 else
4118 bgp_nht_param_prefix = p;
4119
d62a17ae 4120 /* AS path loop check. */
4121 if (do_loop_check) {
b2ac1d0d
MS
4122 if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
4123 (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
4124 (aspath_loop_check(attr->aspath, bgp->confed_id) >
4125 allowas_in))) {
b4d46cc9 4126 peer->stat_pfx_aspath_loop++;
d62a17ae 4127 reason = "as-path contains our own AS;";
4128 goto filtered;
4129 }
4130 }
aac9ef6c 4131
46dbf9d0
DA
4132 /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4133 * enabled, then take care of that too.
4134 */
4135 bool accept_own = false;
4136
d62a17ae 4137 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4138 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
46dbf9d0
DA
4139 accept_own =
4140 bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4141 if (!accept_own) {
4142 peer->stat_pfx_originator_loop++;
4143 reason = "originator is us;";
4144 goto filtered;
4145 }
d62a17ae 4146 }
718e3744 4147
d62a17ae 4148 /* Route reflector cluster ID check. */
4149 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 4150 peer->stat_pfx_cluster_loop++;
d62a17ae 4151 reason = "reflected from the same cluster;";
4152 goto filtered;
4153 }
718e3744 4154
d62a17ae 4155 /* Apply incoming filter. */
907707db 4156 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 4157 peer->stat_pfx_filter++;
d62a17ae 4158 reason = "filter;";
4159 goto filtered;
4160 }
718e3744 4161
a8b72dc6
DA
4162 /* RFC 8212 to prevent route leaks.
4163 * This specification intends to improve this situation by requiring the
4164 * explicit configuration of both BGP Import and Export Policies for any
4165 * External BGP (EBGP) session such as customers, peers, or
4166 * confederation boundaries for all enabled address families. Through
4167 * codification of the aforementioned requirement, operators will
4168 * benefit from consistent behavior across different BGP
4169 * implementations.
4170 */
1d3fdccf 4171 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
4172 if (!bgp_inbound_policy_exists(peer,
4173 &peer->filter[afi][safi])) {
4174 reason = "inbound policy missing";
b17826b7
DS
4175 if (monotime_since(&bgp->ebgprequirespolicywarning,
4176 NULL) > FIFTEENMINUTE2USEC ||
4177 bgp->ebgprequirespolicywarning.tv_sec == 0) {
4178 zlog_warn(
4179 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4180 monotime(&bgp->ebgprequirespolicywarning);
4181 }
a8b72dc6
DA
4182 goto filtered;
4183 }
4184
fb29348a
DA
4185 /* draft-ietf-idr-deprecate-as-set-confed-set
4186 * Filter routes having AS_SET or AS_CONFED_SET in the path.
4187 * Eventually, This document (if approved) updates RFC 4271
4188 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4189 * and obsoletes RFC 6472.
4190 */
7f972cd8 4191 if (peer->bgp->reject_as_sets)
fb29348a
DA
4192 if (aspath_check_as_sets(attr->aspath)) {
4193 reason =
4194 "as-path contains AS_SET or AS_CONFED_SET type;";
4195 goto filtered;
4196 }
4197
6f4f49b2 4198 new_attr = *attr;
d62a17ae 4199
4200 /* Apply incoming route-map.
4201 * NB: new_attr may now contain newly allocated values from route-map
4202 * "set"
4203 * commands, so we need bgp_attr_flush in the error paths, until we
4204 * intern
4205 * the attr (which takes over the memory references) */
907707db 4206 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4207 num_labels, dest)
4208 == RMAP_DENY) {
b4d46cc9 4209 peer->stat_pfx_filter++;
d62a17ae 4210 reason = "route-map;";
4211 bgp_attr_flush(&new_attr);
4212 goto filtered;
4213 }
718e3744 4214
05864da7 4215 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4216 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4217 /* remove from RIB previous entry */
4218 bgp_zebra_withdraw(p, pi, bgp, safi);
4219 }
4220
7f323236
DW
4221 if (peer->sort == BGP_PEER_EBGP) {
4222
2721dd61
DA
4223 /* rfc7999:
4224 * A BGP speaker receiving an announcement tagged with the
4225 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4226 * NO_EXPORT community as defined in RFC1997, or a
4227 * similar community, to prevent propagation of the
4228 * prefix outside the local AS. The community to prevent
4229 * propagation SHOULD be chosen according to the operator's
4230 * routing policy.
4231 */
9a706b42
DA
4232 if (bgp_attr_get_community(&new_attr) &&
4233 community_include(bgp_attr_get_community(&new_attr),
4234 COMMUNITY_BLACKHOLE))
aade37d7 4235 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4236
a4d82a8a
PZ
4237 /* If we receive the graceful-shutdown community from an eBGP
4238 * peer we must lower local-preference */
9a706b42
DA
4239 if (bgp_attr_get_community(&new_attr) &&
4240 community_include(bgp_attr_get_community(&new_attr),
4241 COMMUNITY_GSHUT)) {
7f323236
DW
4242 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4243 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4244
a4d82a8a
PZ
4245 /* If graceful-shutdown is configured then add the GSHUT
4246 * community to all paths received from eBGP peers */
637e5ba4 4247 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4248 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4249 }
4250
d62a17ae 4251 /* next hop check. */
860ad3f9
DS
4252 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4253 bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4254 &new_attr, dest)) {
b4d46cc9 4255 peer->stat_pfx_nh_invalid++;
d62a17ae 4256 reason = "martian or self next-hop;";
4257 bgp_attr_flush(&new_attr);
4258 goto filtered;
4259 }
718e3744 4260
5c14a191 4261 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4262 peer->stat_pfx_nh_invalid++;
4e802e66 4263 reason = "self mac;";
4dbf2038 4264 bgp_attr_flush(&new_attr);
4e802e66
DS
4265 goto filtered;
4266 }
4267
5a78f2bc
EB
4268 if (bgp_check_role_applicability(afi, safi) &&
4269 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4270 reason = "failing otc validation";
4271 bgp_attr_flush(&new_attr);
4272 goto filtered;
4273 }
a1b773e2
DS
4274 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4275 * condition :
4276 * Suppress fib is enabled
4277 * BGP_OPT_NO_FIB is not enabled
4278 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4279 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4280 */
4281 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4282 && (sub_type == BGP_ROUTE_NORMAL)
4283 && (!bgp_option_check(BGP_OPT_NO_FIB))
4284 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4285 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4286
9cbd06e0
DA
4287 /* If maximum prefix count is configured and current prefix
4288 * count exeed it.
4289 */
4dbf2038
IR
4290 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4291 bgp_attr_flush(&new_attr);
9cbd06e0 4292 return -1;
4dbf2038
IR
4293 }
4294
01da2d26
DA
4295 /* If neighbor soo is configured, tag all incoming routes with
4296 * this SoO tag and then filter out advertisements in
4297 * subgroup_announce_check() if it matches the configured SoO
4298 * on the other peer.
4299 */
4300 if (peer->soo[afi][safi]) {
4301 struct ecommunity *old_ecomm =
4302 bgp_attr_get_ecommunity(&new_attr);
4303 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4304 struct ecommunity *new_ecomm;
4305
4306 if (old_ecomm) {
4307 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4308 ecomm_soo);
4309
4310 if (!old_ecomm->refcnt)
4311 ecommunity_free(&old_ecomm);
4312 } else {
4313 new_ecomm = ecommunity_dup(ecomm_soo);
4314 }
4315
4316 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4317 }
4318
4dbf2038 4319 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4320
d62a17ae 4321 /* If the update is implicit withdraw. */
40381db7 4322 if (pi) {
083ec940 4323 pi->uptime = monotime(NULL);
40381db7 4324 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4325
9bcb3eef 4326 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4327
d62a17ae 4328 /* Same attribute comes in. */
40381db7 4329 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4330 && same_attr
d62a17ae 4331 && (!has_valid_label
40381db7 4332 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4333 num_labels * sizeof(mpls_label_t))
66ff6089 4334 == 0)) {
b4f7f45b
IR
4335 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4336 BGP_CONFIG_DAMPENING)
d62a17ae 4337 && peer->sort == BGP_PEER_EBGP
40381db7 4338 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4339 if (bgp_debug_update(peer, p, NULL, 1)) {
4340 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4341 afi, safi, prd, p, label,
4342 num_labels, addpath_id ? 1 : 0,
66ff6089 4343 addpath_id, evpn, pfx_buf,
a4d82a8a 4344 sizeof(pfx_buf));
f70c91dc 4345 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4346 pfx_buf);
4347 }
4348
9bcb3eef 4349 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4350 != BGP_DAMP_SUPPRESSED) {
40381db7 4351 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4352 safi);
9bcb3eef 4353 bgp_process(bgp, dest, afi, safi);
d62a17ae 4354 }
4355 } else /* Duplicate - odd */
4356 {
4357 if (bgp_debug_update(peer, p, NULL, 1)) {
4358 if (!peer->rcvd_attr_printed) {
4359 zlog_debug(
f70c91dc
DA
4360 "%pBP rcvd UPDATE w/ attr: %s",
4361 peer,
d62a17ae 4362 peer->rcvd_attr_str);
4363 peer->rcvd_attr_printed = 1;
4364 }
4365
4366 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4367 afi, safi, prd, p, label,
4368 num_labels, addpath_id ? 1 : 0,
66ff6089 4369 addpath_id, evpn, pfx_buf,
a4d82a8a 4370 sizeof(pfx_buf));
d62a17ae 4371 zlog_debug(
f70c91dc
DA
4372 "%pBP rcvd %s...duplicate ignored",
4373 peer, pfx_buf);
d62a17ae 4374 }
4375
4376 /* graceful restart STALE flag unset. */
40381db7 4377 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4378 bgp_path_info_unset_flag(
9bcb3eef
DS
4379 dest, pi, BGP_PATH_STALE);
4380 bgp_dest_set_defer_flag(dest, false);
4381 bgp_process(bgp, dest, afi, safi);
d62a17ae 4382 }
4383 }
4384
9bcb3eef 4385 bgp_dest_unlock_node(dest);
d62a17ae 4386 bgp_attr_unintern(&attr_new);
4387
4388 return 0;
4389 }
718e3744 4390
d62a17ae 4391 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4392 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4393 if (bgp_debug_update(peer, p, NULL, 1)) {
4394 bgp_debug_rdpfxpath2str(
a4d82a8a 4395 afi, safi, prd, p, label, num_labels,
66ff6089 4396 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4397 pfx_buf, sizeof(pfx_buf));
d62a17ae 4398 zlog_debug(
f70c91dc
DA
4399 "%pBP rcvd %s, flapped quicker than processing",
4400 peer, pfx_buf);
d62a17ae 4401 }
4402
9bcb3eef 4403 bgp_path_info_restore(dest, pi);
9146341f 4404
4405 /*
4406 * If the BGP_PATH_REMOVED flag is set, then EVPN
4407 * routes would have been unimported already when a
4408 * prior BGP withdraw processing happened. Such routes
4409 * need to be imported again, so flag accordingly.
4410 */
4411 force_evpn_import = true;
d62a17ae 4412 }
718e3744 4413
d62a17ae 4414 /* Received Logging. */
4415 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4416 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4417 num_labels, addpath_id ? 1 : 0,
66ff6089 4418 addpath_id, evpn, pfx_buf,
a4d82a8a 4419 sizeof(pfx_buf));
f70c91dc 4420 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4421 }
718e3744 4422
d62a17ae 4423 /* graceful restart STALE flag unset. */
f009ff26 4424 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4425 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4426 bgp_dest_set_defer_flag(dest, false);
f009ff26 4427 }
d62a17ae 4428
4429 /* The attribute is changed. */
9bcb3eef 4430 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4431
4432 /* implicit withdraw, decrement aggregate and pcount here.
4433 * only if update is accepted, they'll increment below.
4434 */
40381db7 4435 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4436
4437 /* Update bgp route dampening information. */
b4f7f45b 4438 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4439 && peer->sort == BGP_PEER_EBGP) {
4440 /* This is implicit withdraw so we should update
b4f7f45b
IR
4441 dampening
4442 information. */
40381db7 4443 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4444 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4445 }
49e5a4a0 4446#ifdef ENABLE_BGP_VNC
d62a17ae 4447 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4448 struct bgp_dest *pdest = NULL;
d62a17ae 4449 struct bgp_table *table = NULL;
4450
9bcb3eef
DS
4451 pdest = bgp_node_get(bgp->rib[afi][safi],
4452 (struct prefix *)prd);
4453 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4454 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4455
4456 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4457 bgp, prd, table, p, pi);
d62a17ae 4458 }
9bcb3eef 4459 bgp_dest_unlock_node(pdest);
d62a17ae 4460 }
4461 if ((afi == AFI_IP || afi == AFI_IP6)
4462 && (safi == SAFI_UNICAST)) {
40381db7 4463 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4464 /*
4465 * Implicit withdraw case.
4466 */
4467 ++vnc_implicit_withdraw;
40381db7
DS
4468 vnc_import_bgp_del_route(bgp, p, pi);
4469 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4470 }
4471 }
65efcfce 4472#endif
128ea8ab 4473
d62a17ae 4474 /* Special handling for EVPN update of an existing route. If the
4475 * extended community attribute has changed, we need to
4476 * un-import
4477 * the route using its existing extended community. It will be
4478 * subsequently processed for import with the new extended
4479 * community.
4480 */
6f8c9c11
PR
4481 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4482 && !same_attr) {
40381db7 4483 if ((pi->attr->flag
d62a17ae 4484 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4485 && (attr_new->flag
4486 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4487 int cmp;
4488
b53e67a3
DA
4489 cmp = ecommunity_cmp(
4490 bgp_attr_get_ecommunity(pi->attr),
4491 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4492 if (!cmp) {
4493 if (bgp_debug_update(peer, p, NULL, 1))
4494 zlog_debug(
4495 "Change in EXT-COMM, existing %s new %s",
4496 ecommunity_str(
b53e67a3
DA
4497 bgp_attr_get_ecommunity(
4498 pi->attr)),
d62a17ae 4499 ecommunity_str(
b53e67a3
DA
4500 bgp_attr_get_ecommunity(
4501 attr_new)));
6f8c9c11
PR
4502 if (safi == SAFI_EVPN)
4503 bgp_evpn_unimport_route(
4504 bgp, afi, safi, p, pi);
4505 else /* SAFI_MPLS_VPN */
4506 vpn_leak_to_vrf_withdraw(bgp,
4507 pi);
d62a17ae 4508 }
4509 }
4510 }
718e3744 4511
d62a17ae 4512 /* Update to new attribute. */
40381db7
DS
4513 bgp_attr_unintern(&pi->attr);
4514 pi->attr = attr_new;
d62a17ae 4515
4516 /* Update MPLS label */
4517 if (has_valid_label) {
40381db7 4518 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4519 if (extra->label != label) {
4520 memcpy(&extra->label, label,
dbd587da 4521 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4522 extra->num_labels = num_labels;
4523 }
b57ba6d2
MK
4524 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4525 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4526 }
718e3744 4527
e496b420
HS
4528 /* Update SRv6 SID */
4529 if (attr->srv6_l3vpn) {
4530 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4531 if (sid_diff(&extra->sid[0].sid,
4532 &attr->srv6_l3vpn->sid)) {
4533 sid_copy(&extra->sid[0].sid,
e496b420
HS
4534 &attr->srv6_l3vpn->sid);
4535 extra->num_sids = 1;
cc8f05df 4536
16f3db2d
RS
4537 extra->sid[0].loc_block_len = 0;
4538 extra->sid[0].loc_node_len = 0;
4539 extra->sid[0].func_len = 0;
4540 extra->sid[0].arg_len = 0;
ea7cd161
RS
4541 extra->sid[0].transposition_len = 0;
4542 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4543
4544 if (attr->srv6_l3vpn->loc_block_len != 0) {
4545 extra->sid[0].loc_block_len =
4546 attr->srv6_l3vpn->loc_block_len;
4547 extra->sid[0].loc_node_len =
4548 attr->srv6_l3vpn->loc_node_len;
4549 extra->sid[0].func_len =
4550 attr->srv6_l3vpn->func_len;
4551 extra->sid[0].arg_len =
4552 attr->srv6_l3vpn->arg_len;
ea7cd161 4553 extra->sid[0].transposition_len =
cc8f05df 4554 attr->srv6_l3vpn
ea7cd161
RS
4555 ->transposition_len;
4556 extra->sid[0].transposition_offset =
cc8f05df 4557 attr->srv6_l3vpn
ea7cd161
RS
4558 ->transposition_offset;
4559 }
e496b420
HS
4560 }
4561 } else if (attr->srv6_vpn) {
4562 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4563 if (sid_diff(&extra->sid[0].sid,
4564 &attr->srv6_vpn->sid)) {
4565 sid_copy(&extra->sid[0].sid,
4566 &attr->srv6_vpn->sid);
e496b420
HS
4567 extra->num_sids = 1;
4568 }
4569 }
4570
49e5a4a0 4571#ifdef ENABLE_BGP_VNC
d62a17ae 4572 if ((afi == AFI_IP || afi == AFI_IP6)
4573 && (safi == SAFI_UNICAST)) {
4574 if (vnc_implicit_withdraw) {
4575 /*
4576 * Add back the route with its new attributes
4577 * (e.g., nexthop).
4578 * The route is still selected, until the route
4579 * selection
4580 * queued by bgp_process actually runs. We have
4581 * to make this
4582 * update to the VNC side immediately to avoid
4583 * racing against
4584 * configuration changes (e.g., route-map
4585 * changes) which
4586 * trigger re-importation of the entire RIB.
4587 */
40381db7
DS
4588 vnc_import_bgp_add_route(bgp, p, pi);
4589 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4590 }
4591 }
65efcfce
LB
4592#endif
4593
d62a17ae 4594 /* Update bgp route dampening information. */
b4f7f45b 4595 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4596 && peer->sort == BGP_PEER_EBGP) {
4597 /* Now we do normal update dampening. */
9bcb3eef 4598 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4599 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4600 bgp_dest_unlock_node(dest);
d62a17ae 4601 return 0;
4602 }
4603 }
128ea8ab 4604
d62a17ae 4605 /* Nexthop reachability check - for unicast and
4606 * labeled-unicast.. */
7c312383
AD
4607 if (((afi == AFI_IP || afi == AFI_IP6)
4608 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4609 || (safi == SAFI_EVPN &&
4610 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4611 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4612 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4613 && !CHECK_FLAG(peer->flags,
4614 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4615 && !CHECK_FLAG(bgp->flags,
4616 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4617 connected = 1;
4618 else
4619 connected = 0;
4620
960035b2
PZ
4621 struct bgp *bgp_nexthop = bgp;
4622
40381db7
DS
4623 if (pi->extra && pi->extra->bgp_orig)
4624 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4625
7c312383
AD
4626 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4627
4628 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978 4629 safi, pi, NULL, connected,
f8745525
PG
4630 bgp_nht_param_prefix) ||
4631 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4632 bgp_path_info_set_flag(dest, pi,
4633 BGP_PATH_VALID);
d62a17ae 4634 else {
4635 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4636 zlog_debug("%s(%pI4): NH unresolved",
4637 __func__,
4638 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4639 }
9bcb3eef 4640 bgp_path_info_unset_flag(dest, pi,
18ee8310 4641 BGP_PATH_VALID);
d62a17ae 4642 }
46dbf9d0
DA
4643 } else {
4644 if (accept_own)
4645 bgp_path_info_set_flag(dest, pi,
4646 BGP_PATH_ACCEPT_OWN);
4647
9bcb3eef 4648 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
46dbf9d0 4649 }
d62a17ae 4650
49e5a4a0 4651#ifdef ENABLE_BGP_VNC
d62a17ae 4652 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4653 struct bgp_dest *pdest = NULL;
d62a17ae 4654 struct bgp_table *table = NULL;
4655
9bcb3eef
DS
4656 pdest = bgp_node_get(bgp->rib[afi][safi],
4657 (struct prefix *)prd);
4658 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4659 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4660
4661 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4662 bgp, prd, table, p, pi);
d62a17ae 4663 }
9bcb3eef 4664 bgp_dest_unlock_node(pdest);
d62a17ae 4665 }
4666#endif
718e3744 4667
d62a17ae 4668 /* If this is an EVPN route and some attribute has changed,
9146341f 4669 * or we are explicitly told to perform a route import, process
d62a17ae 4670 * route for import. If the extended community has changed, we
4671 * would
4672 * have done the un-import earlier and the import would result
4673 * in the
4674 * route getting injected into appropriate L2 VNIs. If it is
4675 * just
4676 * some other attribute change, the import will result in
4677 * updating
4678 * the attributes for the route in the VNI(s).
4679 */
9146341f 4680 if (safi == SAFI_EVPN &&
4681 (!same_attr || force_evpn_import) &&
7c312383 4682 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4683 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4684
4685 /* Process change. */
40381db7 4686 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4687
9bcb3eef
DS
4688 bgp_process(bgp, dest, afi, safi);
4689 bgp_dest_unlock_node(dest);
558d1fec 4690
ddb5b488
PZ
4691 if (SAFI_UNICAST == safi
4692 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4693 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4694
40381db7 4695 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4696 }
4697 if ((SAFI_MPLS_VPN == safi)
4698 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4699 leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
ddb5b488
PZ
4700 }
4701
49e5a4a0 4702#ifdef ENABLE_BGP_VNC
d62a17ae 4703 if (SAFI_MPLS_VPN == safi) {
4704 mpls_label_t label_decoded = decode_label(label);
28070ee3 4705
d62a17ae 4706 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4707 type, sub_type, &label_decoded);
4708 }
4709 if (SAFI_ENCAP == safi) {
4710 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4711 type, sub_type, NULL);
4712 }
28070ee3 4713#endif
a486300b
PG
4714 if ((safi == SAFI_MPLS_VPN) &&
4715 !CHECK_FLAG(bgp->af_flags[afi][safi],
4716 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4717 !leak_success) {
4718 bgp_unlink_nexthop(pi);
4719 bgp_path_info_delete(dest, pi);
4720 }
d62a17ae 4721 return 0;
4722 } // End of implicit withdraw
718e3744 4723
d62a17ae 4724 /* Received Logging. */
4725 if (bgp_debug_update(peer, p, NULL, 1)) {
4726 if (!peer->rcvd_attr_printed) {
f70c91dc 4727 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4728 peer->rcvd_attr_str);
4729 peer->rcvd_attr_printed = 1;
4730 }
718e3744 4731
a4d82a8a 4732 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4733 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4734 pfx_buf, sizeof(pfx_buf));
f70c91dc 4735 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4736 }
718e3744 4737
d62a17ae 4738 /* Make new BGP info. */
9bcb3eef 4739 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4740
d62a17ae 4741 /* Update MPLS label */
4742 if (has_valid_label) {
18ee8310 4743 extra = bgp_path_info_extra_get(new);
8ba71050 4744 if (extra->label != label) {
dbd587da
QY
4745 memcpy(&extra->label, label,
4746 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4747 extra->num_labels = num_labels;
4748 }
b57ba6d2
MK
4749 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4750 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4751 }
718e3744 4752
e496b420
HS
4753 /* Update SRv6 SID */
4754 if (safi == SAFI_MPLS_VPN) {
4755 extra = bgp_path_info_extra_get(new);
4756 if (attr->srv6_l3vpn) {
16f3db2d 4757 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4758 extra->num_sids = 1;
cc8f05df 4759
16f3db2d
RS
4760 extra->sid[0].loc_block_len =
4761 attr->srv6_l3vpn->loc_block_len;
4762 extra->sid[0].loc_node_len =
4763 attr->srv6_l3vpn->loc_node_len;
4764 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4765 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4766 extra->sid[0].transposition_len =
4767 attr->srv6_l3vpn->transposition_len;
4768 extra->sid[0].transposition_offset =
4769 attr->srv6_l3vpn->transposition_offset;
e496b420 4770 } else if (attr->srv6_vpn) {
16f3db2d 4771 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4772 extra->num_sids = 1;
4773 }
4774 }
4775
d62a17ae 4776 /* Nexthop reachability check. */
7c312383
AD
4777 if (((afi == AFI_IP || afi == AFI_IP6)
4778 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4779 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4780 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4781 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4782 && !CHECK_FLAG(peer->flags,
4783 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4784 && !CHECK_FLAG(bgp->flags,
4785 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4786 connected = 1;
4787 else
4788 connected = 0;
4789
7c312383
AD
4790 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4791
4053e952 4792 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
f8745525
PG
4793 connected, bgp_nht_param_prefix) ||
4794 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4795 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4796 else {
4797 if (BGP_DEBUG(nht, NHT)) {
4798 char buf1[INET6_ADDRSTRLEN];
4799 inet_ntop(AF_INET,
4800 (const void *)&attr_new->nexthop,
4801 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4802 zlog_debug("%s(%s): NH unresolved", __func__,
4803 buf1);
d62a17ae 4804 }
9bcb3eef 4805 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4806 }
46dbf9d0
DA
4807 } else {
4808 if (accept_own)
4809 bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4810
9bcb3eef 4811 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
46dbf9d0 4812 }
a82478b9 4813
d62a17ae 4814 /* Addpath ID */
4815 new->addpath_rx_id = addpath_id;
4816
4817 /* Increment prefix */
4818 bgp_aggregate_increment(bgp, p, new, afi, safi);
4819
4820 /* Register new BGP information. */
9bcb3eef 4821 bgp_path_info_add(dest, new);
d62a17ae 4822
4823 /* route_node_get lock */
9bcb3eef 4824 bgp_dest_unlock_node(dest);
558d1fec 4825
49e5a4a0 4826#ifdef ENABLE_BGP_VNC
d62a17ae 4827 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4828 struct bgp_dest *pdest = NULL;
d62a17ae 4829 struct bgp_table *table = NULL;
4830
9bcb3eef
DS
4831 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4832 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4833 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4834
4835 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4836 bgp, prd, table, p, new);
4837 }
9bcb3eef 4838 bgp_dest_unlock_node(pdest);
d62a17ae 4839 }
65efcfce
LB
4840#endif
4841
d62a17ae 4842 /* If this is an EVPN route, process for import. */
7c312383 4843 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4844 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4845
9bcb3eef 4846 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4847
d62a17ae 4848 /* Process change. */
9bcb3eef 4849 bgp_process(bgp, dest, afi, safi);
718e3744 4850
ddb5b488
PZ
4851 if (SAFI_UNICAST == safi
4852 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4853 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4854 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4855 }
4856 if ((SAFI_MPLS_VPN == safi)
4857 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
46dbf9d0 4858 leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
ddb5b488 4859 }
49e5a4a0 4860#ifdef ENABLE_BGP_VNC
d62a17ae 4861 if (SAFI_MPLS_VPN == safi) {
4862 mpls_label_t label_decoded = decode_label(label);
28070ee3 4863
d62a17ae 4864 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4865 sub_type, &label_decoded);
4866 }
4867 if (SAFI_ENCAP == safi) {
4868 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4869 sub_type, NULL);
4870 }
28070ee3 4871#endif
a486300b
PG
4872 if ((safi == SAFI_MPLS_VPN) &&
4873 !CHECK_FLAG(bgp->af_flags[afi][safi],
4874 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4875 !leak_success) {
4876 bgp_unlink_nexthop(new);
4877 bgp_path_info_delete(dest, new);
4878 }
28070ee3 4879
d62a17ae 4880 return 0;
718e3744 4881
d62a17ae 4882/* This BGP update is filtered. Log the reason then update BGP
4883 entry. */
4884filtered:
9bcb3eef 4885 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4886
d62a17ae 4887 if (bgp_debug_update(peer, p, NULL, 1)) {
4888 if (!peer->rcvd_attr_printed) {
f70c91dc 4889 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4890 peer->rcvd_attr_str);
4891 peer->rcvd_attr_printed = 1;
4892 }
718e3744 4893
a4d82a8a 4894 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4895 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4896 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4897 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4898 peer, pfx_buf, reason);
d62a17ae 4899 }
128ea8ab 4900
40381db7 4901 if (pi) {
d62a17ae 4902 /* If this is an EVPN route, un-import it as it is now filtered.
4903 */
4904 if (safi == SAFI_EVPN)
40381db7 4905 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4906
ddb5b488
PZ
4907 if (SAFI_UNICAST == safi
4908 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4909 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4910
40381db7 4911 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4912 }
4913 if ((SAFI_MPLS_VPN == safi)
4914 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4915
40381db7 4916 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4917 }
4918
9bcb3eef 4919 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4920 }
4921
9bcb3eef 4922 bgp_dest_unlock_node(dest);
558d1fec 4923
49e5a4a0 4924#ifdef ENABLE_BGP_VNC
d62a17ae 4925 /*
4926 * Filtered update is treated as an implicit withdrawal (see
4927 * bgp_rib_remove()
4928 * a few lines above)
4929 */
4930 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4931 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4932 0);
4933 }
97736e32
PZ
4934#endif
4935
d62a17ae 4936 return 0;
718e3744 4937}
4938
26a3ffd6 4939int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4940 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4941 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4942 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4943{
d62a17ae 4944 struct bgp *bgp;
4945 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4946 struct bgp_dest *dest;
40381db7 4947 struct bgp_path_info *pi;
718e3744 4948
49e5a4a0 4949#ifdef ENABLE_BGP_VNC
d62a17ae 4950 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4951 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4952 0);
4953 }
28070ee3
PZ
4954#endif
4955
d62a17ae 4956 bgp = peer->bgp;
4957
4958 /* Lookup node. */
9bcb3eef 4959 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4960
4961 /* If peer is soft reconfiguration enabled. Record input packet for
4962 * further calculation.
4963 *
4964 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4965 * routes that are filtered. This tanks out Quagga RS pretty badly due
4966 * to
4967 * the iteration over all RS clients.
4968 * Since we need to remove the entry from adj_in anyway, do that first
4969 * and
4970 * if there was no entry, we don't need to do anything more.
4971 */
4972 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4973 && peer != bgp->peer_self)
9bcb3eef 4974 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4975 peer->stat_pfx_dup_withdraw++;
4976
d62a17ae 4977 if (bgp_debug_update(peer, p, NULL, 1)) {
4978 bgp_debug_rdpfxpath2str(
a4d82a8a 4979 afi, safi, prd, p, label, num_labels,
6c995628
AD
4980 addpath_id ? 1 : 0, addpath_id, NULL,
4981 pfx_buf, sizeof(pfx_buf));
d62a17ae 4982 zlog_debug(
4983 "%s withdrawing route %s not in adj-in",
4984 peer->host, pfx_buf);
4985 }
9bcb3eef 4986 bgp_dest_unlock_node(dest);
d62a17ae 4987 return 0;
4988 }
cd808e74 4989
d62a17ae 4990 /* Lookup withdrawn route. */
9bcb3eef 4991 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4992 if (pi->peer == peer && pi->type == type
4993 && pi->sub_type == sub_type
4994 && pi->addpath_rx_id == addpath_id)
d62a17ae 4995 break;
4996
4997 /* Logging. */
4998 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4999 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5000 addpath_id ? 1 : 0, addpath_id, NULL,
5001 pfx_buf, sizeof(pfx_buf));
f70c91dc 5002 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 5003 pfx_buf);
5004 }
718e3744 5005
d62a17ae 5006 /* Withdraw specified route from routing table. */
40381db7 5007 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 5008 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
5009 if (SAFI_UNICAST == safi
5010 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5011 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5012 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
5013 }
5014 if ((SAFI_MPLS_VPN == safi)
5015 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5016
40381db7 5017 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
5018 }
5019 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 5020 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
5021 addpath_id ? 1 : 0, addpath_id, NULL,
5022 pfx_buf, sizeof(pfx_buf));
d62a17ae 5023 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
5024 }
718e3744 5025
d62a17ae 5026 /* Unlock bgp_node_get() lock. */
9bcb3eef 5027 bgp_dest_unlock_node(dest);
d62a17ae 5028
5029 return 0;
718e3744 5030}
6b0655a2 5031
d62a17ae 5032void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
5033 int withdraw)
718e3744 5034{
d62a17ae 5035 struct update_subgroup *subgrp;
5036 subgrp = peer_subgroup(peer, afi, safi);
5037 subgroup_default_originate(subgrp, withdraw);
3f9c7369 5038}
6182d65b 5039
718e3744 5040
3f9c7369
DS
5041/*
5042 * bgp_stop_announce_route_timer
5043 */
d62a17ae 5044void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 5045{
d62a17ae 5046 if (!paf->t_announce_route)
5047 return;
5048
c3aaa89a 5049 THREAD_OFF(paf->t_announce_route);
718e3744 5050}
6b0655a2 5051
3f9c7369
DS
5052/*
5053 * bgp_announce_route_timer_expired
5054 *
5055 * Callback that is invoked when the route announcement timer for a
5056 * peer_af expires.
5057 */
cc9f21da 5058static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 5059{
d62a17ae 5060 struct peer_af *paf;
5061 struct peer *peer;
558d1fec 5062
d62a17ae 5063 paf = THREAD_ARG(t);
5064 peer = paf->peer;
718e3744 5065
feb17238 5066 if (!peer_established(peer))
cc9f21da 5067 return;
3f9c7369 5068
d62a17ae 5069 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 5070 return;
3f9c7369 5071
d62a17ae 5072 peer_af_announce_route(paf, 1);
c5aec50b
MK
5073
5074 /* Notify BGP conditional advertisement scanner percess */
c385f82a 5075 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 5076}
5077
3f9c7369
DS
5078/*
5079 * bgp_announce_route
5080 *
5081 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
5082 *
5083 * if force is true we will force an update even if the update
5084 * limiting code is attempted to kick in.
3f9c7369 5085 */
e1a32ec1 5086void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 5087{
5088 struct peer_af *paf;
5089 struct update_subgroup *subgrp;
5090
5091 paf = peer_af_find(peer, afi, safi);
5092 if (!paf)
5093 return;
5094 subgrp = PAF_SUBGRP(paf);
5095
5096 /*
5097 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5098 * or a refresh has already been triggered.
5099 */
5100 if (!subgrp || paf->t_announce_route)
5101 return;
5102
e1a32ec1
DS
5103 if (force)
5104 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5105
d62a17ae 5106 /*
5107 * Start a timer to stagger/delay the announce. This serves
5108 * two purposes - announcement can potentially be combined for
5109 * multiple peers and the announcement doesn't happen in the
5110 * vty context.
5111 */
5112 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5113 (subgrp->peer_count == 1)
5114 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5115 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5116 &paf->t_announce_route);
3f9c7369
DS
5117}
5118
5119/*
5120 * Announce routes from all AF tables to a peer.
5121 *
5122 * This should ONLY be called when there is a need to refresh the
5123 * routes to the peer based on a policy change for this peer alone
5124 * or a route refresh request received from the peer.
5125 * The operation will result in splitting the peer from its existing
5126 * subgroups and putting it in new subgroups.
5127 */
d62a17ae 5128void bgp_announce_route_all(struct peer *peer)
718e3744 5129{
d62a17ae 5130 afi_t afi;
5131 safi_t safi;
5132
05c7a1cc 5133 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 5134 bgp_announce_route(peer, afi, safi, false);
718e3744 5135}
6b0655a2 5136
46aeabed
LS
5137/* Flag or unflag bgp_dest to determine whether it should be treated by
5138 * bgp_soft_reconfig_table_task.
5139 * Flag if flag is true. Unflag if flag is false.
5140 */
5141static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5142{
5143 struct bgp_dest *dest;
5144 struct bgp_adj_in *ain;
5145
5146 if (!table)
5147 return;
5148
5149 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5150 for (ain = dest->adj_in; ain; ain = ain->next) {
5151 if (ain->peer != NULL)
5152 break;
5153 }
5154 if (flag && ain != NULL && ain->peer != NULL)
5155 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5156 else
5157 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5158 }
5159}
5160
5161static int bgp_soft_reconfig_table_update(struct peer *peer,
5162 struct bgp_dest *dest,
5163 struct bgp_adj_in *ain, afi_t afi,
5164 safi_t safi, struct prefix_rd *prd)
5165{
5166 struct bgp_path_info *pi;
5167 uint32_t num_labels = 0;
5168 mpls_label_t *label_pnt = NULL;
5169 struct bgp_route_evpn evpn;
5170
5171 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5172 if (pi->peer == peer)
5173 break;
5174
5175 if (pi && pi->extra)
5176 num_labels = pi->extra->num_labels;
5177 if (num_labels)
5178 label_pnt = &pi->extra->label[0];
5179 if (pi)
5180 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5181 sizeof(evpn));
5182 else
5183 memset(&evpn, 0, sizeof(evpn));
5184
5185 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5186 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
5187 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
5188 &evpn);
5189}
5190
d62a17ae 5191static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5192 struct bgp_table *table,
5193 struct prefix_rd *prd)
718e3744 5194{
d62a17ae 5195 int ret;
9bcb3eef 5196 struct bgp_dest *dest;
d62a17ae 5197 struct bgp_adj_in *ain;
718e3744 5198
d62a17ae 5199 if (!table)
5200 table = peer->bgp->rib[afi][safi];
718e3744 5201
9bcb3eef
DS
5202 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5203 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5204 if (ain->peer != peer)
5205 continue;
8692c506 5206
46aeabed
LS
5207 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5208 afi, safi, prd);
ea47320b
DL
5209
5210 if (ret < 0) {
9bcb3eef 5211 bgp_dest_unlock_node(dest);
ea47320b 5212 return;
d62a17ae 5213 }
5214 }
718e3744 5215}
5216
46aeabed
LS
5217/* Do soft reconfig table per bgp table.
5218 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5219 * when BGP_NODE_SOFT_RECONFIG is set,
5220 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5221 * Schedule a new thread to continue the job.
5222 * Without splitting the full job into several part,
5223 * vtysh waits for the job to finish before responding to a BGP command
5224 */
cc9f21da 5225static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5226{
5227 uint32_t iter, max_iter;
5228 int ret;
5229 struct bgp_dest *dest;
5230 struct bgp_adj_in *ain;
5231 struct peer *peer;
5232 struct bgp_table *table;
5233 struct prefix_rd *prd;
5234 struct listnode *node, *nnode;
5235
5236 table = THREAD_ARG(thread);
5237 prd = NULL;
5238
5239 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5240 if (table->soft_reconfig_init) {
5241 /* first call of the function with a new srta structure.
5242 * Don't do any treatment this time on nodes
5243 * in order vtysh to respond quickly
5244 */
5245 max_iter = 0;
5246 }
5247
5248 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5249 dest = bgp_route_next(dest)) {
5250 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5251 continue;
5252
5253 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5254
5255 for (ain = dest->adj_in; ain; ain = ain->next) {
5256 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5257 nnode, peer)) {
5258 if (ain->peer != peer)
5259 continue;
5260
5261 ret = bgp_soft_reconfig_table_update(
5262 peer, dest, ain, table->afi,
5263 table->safi, prd);
5264 iter++;
5265
5266 if (ret < 0) {
5267 bgp_dest_unlock_node(dest);
5268 listnode_delete(
5269 table->soft_reconfig_peers,
5270 peer);
5271 bgp_announce_route(peer, table->afi,
e1a32ec1 5272 table->safi, false);
46aeabed
LS
5273 if (list_isempty(
5274 table->soft_reconfig_peers)) {
5275 list_delete(
5276 &table->soft_reconfig_peers);
5277 bgp_soft_reconfig_table_flag(
5278 table, false);
cc9f21da 5279 return;
46aeabed
LS
5280 }
5281 }
5282 }
5283 }
5284 }
5285
5286 /* we're either starting the initial iteration,
5287 * or we're going to continue an ongoing iteration
5288 */
5289 if (dest || table->soft_reconfig_init) {
5290 table->soft_reconfig_init = false;
5291 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5292 table, 0, &table->soft_reconfig_thread);
cc9f21da 5293 return;
46aeabed
LS
5294 }
5295 /* we're done, clean up the background iteration context info and
5296 schedule route annoucement
5297 */
5298 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5299 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5300 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5301 }
5302
5303 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5304}
5305
5306
5307/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5308 * and peer.
5309 * - bgp cannot be NULL
5310 * - if table and peer are NULL, cancel all threads within the bgp instance
5311 * - if table is NULL and peer is not,
5312 * remove peer in all threads within the bgp instance
5313 * - if peer is NULL, cancel all threads matching table within the bgp instance
5314 */
5315void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5316 const struct bgp_table *table,
5317 const struct peer *peer)
5318{
5319 struct peer *npeer;
5320 struct listnode *node, *nnode;
5321 int afi, safi;
5322 struct bgp_table *ntable;
5323
5324 if (!bgp)
5325 return;
5326
5327 FOREACH_AFI_SAFI (afi, safi) {
5328 ntable = bgp->rib[afi][safi];
5329 if (!ntable)
5330 continue;
5331 if (table && table != ntable)
5332 continue;
5333
5334 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5335 npeer)) {
5336 if (peer && peer != npeer)
5337 continue;
5338 listnode_delete(ntable->soft_reconfig_peers, npeer);
5339 }
5340
5341 if (!ntable->soft_reconfig_peers
5342 || !list_isempty(ntable->soft_reconfig_peers))
5343 continue;
5344
5345 list_delete(&ntable->soft_reconfig_peers);
5346 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5347 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5348 }
5349}
5350
89c73443
DS
5351/*
5352 * Returns false if the peer is not configured for soft reconfig in
5353 */
5354bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5355{
9bcb3eef 5356 struct bgp_dest *dest;
d62a17ae 5357 struct bgp_table *table;
46aeabed
LS
5358 struct listnode *node, *nnode;
5359 struct peer *npeer;
5360 struct peer_af *paf;
718e3744 5361
89c73443
DS
5362 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5363 return false;
718e3744 5364
d62a17ae 5365 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5366 && (safi != SAFI_EVPN)) {
5367 table = peer->bgp->rib[afi][safi];
5368 if (!table)
89c73443 5369 return true;
46aeabed
LS
5370
5371 table->soft_reconfig_init = true;
5372
5373 if (!table->soft_reconfig_peers)
5374 table->soft_reconfig_peers = list_new();
5375 npeer = NULL;
5376 /* add peer to the table soft_reconfig_peers if not already
5377 * there
5378 */
5379 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5380 npeer)) {
5381 if (peer == npeer)
5382 break;
5383 }
5384 if (peer != npeer)
5385 listnode_add(table->soft_reconfig_peers, peer);
5386
5387 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5388 * on table would start back at the beginning.
5389 */
5390 bgp_soft_reconfig_table_flag(table, true);
5391
5392 if (!table->soft_reconfig_thread)
5393 thread_add_event(bm->master,
5394 bgp_soft_reconfig_table_task, table, 0,
5395 &table->soft_reconfig_thread);
5396 /* Cancel bgp_announce_route_timer_expired threads.
5397 * bgp_announce_route_timer_expired threads have been scheduled
5398 * to announce routes as soon as the soft_reconfigure process
5399 * finishes.
5400 * In this case, soft_reconfigure is also scheduled by using
5401 * a thread but is planned after the
5402 * bgp_announce_route_timer_expired threads. It means that,
5403 * without cancelling the threads, the route announcement task
5404 * would run before the soft reconfiguration one. That would
5405 * useless and would block vtysh during several seconds. Route
5406 * announcements are rescheduled as soon as the soft_reconfigure
5407 * process finishes.
5408 */
5409 paf = peer_af_find(peer, afi, safi);
5410 if (paf)
5411 bgp_stop_announce_route_timer(paf);
5412 } else
9bcb3eef
DS
5413 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5414 dest = bgp_route_next(dest)) {
5415 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5416
b54892e0
DS
5417 if (table == NULL)
5418 continue;
8692c506 5419
9bcb3eef 5420 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5421 struct prefix_rd prd;
5422
5423 prd.family = AF_UNSPEC;
5424 prd.prefixlen = 64;
5425 memcpy(&prd.val, p->u.val, 8);
5426
5427 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5428 }
89c73443
DS
5429
5430 return true;
718e3744 5431}
6b0655a2 5432
228da428 5433
d62a17ae 5434struct bgp_clear_node_queue {
9bcb3eef 5435 struct bgp_dest *dest;
228da428
CC
5436};
5437
d62a17ae 5438static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5439{
d62a17ae 5440 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5441 struct bgp_dest *dest = cnq->dest;
d62a17ae 5442 struct peer *peer = wq->spec.data;
40381db7 5443 struct bgp_path_info *pi;
3103e8d2 5444 struct bgp *bgp;
9bcb3eef
DS
5445 afi_t afi = bgp_dest_table(dest)->afi;
5446 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5447
9bcb3eef 5448 assert(dest && peer);
3103e8d2 5449 bgp = peer->bgp;
d62a17ae 5450
5451 /* It is possible that we have multiple paths for a prefix from a peer
5452 * if that peer is using AddPath.
5453 */
9bcb3eef 5454 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5455 if (pi->peer != peer)
ea47320b
DL
5456 continue;
5457
5458 /* graceful restart STALE flag set. */
9af52ccf
DA
5459 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5460 && peer->nsf[afi][safi])
5461 || CHECK_FLAG(peer->af_sflags[afi][safi],
5462 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5463 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5464 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5465 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5466 else {
5467 /* If this is an EVPN route, process for
5468 * un-import. */
5469 if (safi == SAFI_EVPN)
9bcb3eef
DS
5470 bgp_evpn_unimport_route(
5471 bgp, afi, safi,
5472 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5473 /* Handle withdraw for VRF route-leaking and L3VPN */
5474 if (SAFI_UNICAST == safi
5475 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5476 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5477 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5478 bgp, pi);
960035b2 5479 }
3103e8d2 5480 if (SAFI_MPLS_VPN == safi &&
960035b2 5481 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5482 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5483 }
3103e8d2 5484
9bcb3eef 5485 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5486 }
ea47320b 5487 }
d62a17ae 5488 return WQ_SUCCESS;
200df115 5489}
5490
d62a17ae 5491static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5492{
d62a17ae 5493 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5494 struct bgp_dest *dest = cnq->dest;
5495 struct bgp_table *table = bgp_dest_table(dest);
228da428 5496
9bcb3eef 5497 bgp_dest_unlock_node(dest);
d62a17ae 5498 bgp_table_unlock(table);
5499 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5500}
5501
d62a17ae 5502static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5503{
d62a17ae 5504 struct peer *peer = wq->spec.data;
64e580a7 5505
d62a17ae 5506 /* Tickle FSM to start moving again */
5507 BGP_EVENT_ADD(peer, Clearing_Completed);
5508
5509 peer_unlock(peer); /* bgp_clear_route */
200df115 5510}
718e3744 5511
d62a17ae 5512static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5513{
d62a17ae 5514 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5515
5516 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5517#undef CLEAR_QUEUE_NAME_LEN
5518
0ce1ca80 5519 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5520 peer->clear_node_queue->spec.hold = 10;
5521 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5522 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5523 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5524 peer->clear_node_queue->spec.max_retries = 0;
5525
5526 /* we only 'lock' this peer reference when the queue is actually active
5527 */
5528 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5529}
5530
d62a17ae 5531static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5532 struct bgp_table *table)
65ca75e0 5533{
9bcb3eef 5534 struct bgp_dest *dest;
b6c386bb 5535 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5536
d62a17ae 5537 if (!table)
5538 table = peer->bgp->rib[afi][safi];
dc83d712 5539
d62a17ae 5540 /* If still no table => afi/safi isn't configured at all or smth. */
5541 if (!table)
5542 return;
dc83d712 5543
9bcb3eef 5544 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5545 struct bgp_path_info *pi, *next;
d62a17ae 5546 struct bgp_adj_in *ain;
5547 struct bgp_adj_in *ain_next;
5548
5549 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5550 * queued for every clearing peer, regardless of whether it is
5551 * relevant to the peer at hand.
5552 *
5553 * Overview: There are 3 different indices which need to be
5554 * scrubbed, potentially, when a peer is removed:
5555 *
5556 * 1 peer's routes visible via the RIB (ie accepted routes)
5557 * 2 peer's routes visible by the (optional) peer's adj-in index
5558 * 3 other routes visible by the peer's adj-out index
5559 *
5560 * 3 there is no hurry in scrubbing, once the struct peer is
5561 * removed from bgp->peer, we could just GC such deleted peer's
5562 * adj-outs at our leisure.
5563 *
5564 * 1 and 2 must be 'scrubbed' in some way, at least made
5565 * invisible via RIB index before peer session is allowed to be
5566 * brought back up. So one needs to know when such a 'search' is
5567 * complete.
5568 *
5569 * Ideally:
5570 *
5571 * - there'd be a single global queue or a single RIB walker
5572 * - rather than tracking which route_nodes still need to be
5573 * examined on a peer basis, we'd track which peers still
5574 * aren't cleared
5575 *
5576 * Given that our per-peer prefix-counts now should be reliable,
5577 * this may actually be achievable. It doesn't seem to be a huge
5578 * problem at this time,
5579 *
5580 * It is possible that we have multiple paths for a prefix from
5581 * a peer
5582 * if that peer is using AddPath.
5583 */
9bcb3eef 5584 ain = dest->adj_in;
d62a17ae 5585 while (ain) {
5586 ain_next = ain->next;
5587
6a840fd9 5588 if (ain->peer == peer)
9bcb3eef 5589 bgp_adj_in_remove(dest, ain);
d62a17ae 5590
5591 ain = ain_next;
5592 }
5593
9bcb3eef 5594 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5595 next = pi->next;
5596 if (pi->peer != peer)
d62a17ae 5597 continue;
5598
5599 if (force)
9bcb3eef 5600 bgp_path_info_reap(dest, pi);
d62a17ae 5601 else {
5602 struct bgp_clear_node_queue *cnq;
5603
5604 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5605 bgp_table_lock(bgp_dest_table(dest));
5606 bgp_dest_lock_node(dest);
d62a17ae 5607 cnq = XCALLOC(
5608 MTYPE_BGP_CLEAR_NODE_QUEUE,
5609 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5610 cnq->dest = dest;
d62a17ae 5611 work_queue_add(peer->clear_node_queue, cnq);
5612 break;
5613 }
5614 }
5615 }
5616 return;
5617}
5618
5619void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5620{
9bcb3eef 5621 struct bgp_dest *dest;
d62a17ae 5622 struct bgp_table *table;
5623
5624 if (peer->clear_node_queue == NULL)
5625 bgp_clear_node_queue_init(peer);
5626
5627 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5628 * Idle until it receives a Clearing_Completed event. This protects
5629 * against peers which flap faster than we can we clear, which could
5630 * lead to:
5631 *
5632 * a) race with routes from the new session being installed before
5633 * clear_route_node visits the node (to delete the route of that
5634 * peer)
5635 * b) resource exhaustion, clear_route_node likely leads to an entry
5636 * on the process_main queue. Fast-flapping could cause that queue
5637 * to grow and grow.
5638 */
5639
5640 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5641 * the unlock will happen upon work-queue completion; other wise, the
5642 * unlock happens at the end of this function.
5643 */
5644 if (!peer->clear_node_queue->thread)
5645 peer_lock(peer);
5646
5647 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5648 bgp_clear_route_table(peer, afi, safi, NULL);
5649 else
9bcb3eef
DS
5650 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5651 dest = bgp_route_next(dest)) {
5652 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5653 if (!table)
5654 continue;
5655
5656 bgp_clear_route_table(peer, afi, safi, table);
5657 }
d62a17ae 5658
5659 /* unlock if no nodes got added to the clear-node-queue. */
5660 if (!peer->clear_node_queue->thread)
5661 peer_unlock(peer);
718e3744 5662}
d62a17ae 5663
5664void bgp_clear_route_all(struct peer *peer)
718e3744 5665{
d62a17ae 5666 afi_t afi;
5667 safi_t safi;
718e3744 5668
05c7a1cc
QY
5669 FOREACH_AFI_SAFI (afi, safi)
5670 bgp_clear_route(peer, afi, safi);
65efcfce 5671
49e5a4a0 5672#ifdef ENABLE_BGP_VNC
d62a17ae 5673 rfapiProcessPeerDown(peer);
65efcfce 5674#endif
718e3744 5675}
5676
d62a17ae 5677void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5678{
d62a17ae 5679 struct bgp_table *table;
9bcb3eef 5680 struct bgp_dest *dest;
d62a17ae 5681 struct bgp_adj_in *ain;
5682 struct bgp_adj_in *ain_next;
718e3744 5683
d62a17ae 5684 table = peer->bgp->rib[afi][safi];
718e3744 5685
d62a17ae 5686 /* It is possible that we have multiple paths for a prefix from a peer
5687 * if that peer is using AddPath.
5688 */
9bcb3eef
DS
5689 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5690 ain = dest->adj_in;
43143c8f 5691
d62a17ae 5692 while (ain) {
5693 ain_next = ain->next;
43143c8f 5694
6a840fd9 5695 if (ain->peer == peer)
9bcb3eef 5696 bgp_adj_in_remove(dest, ain);
43143c8f 5697
d62a17ae 5698 ain = ain_next;
5699 }
5700 }
718e3744 5701}
93406d87 5702
1479ed2f
DA
5703/* If any of the routes from the peer have been marked with the NO_LLGR
5704 * community, either as sent by the peer, or as the result of a configured
5705 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5706 * operation of [RFC4271].
5707 */
d62a17ae 5708void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5709{
9bcb3eef 5710 struct bgp_dest *dest;
40381db7 5711 struct bgp_path_info *pi;
d62a17ae 5712 struct bgp_table *table;
5713
9af52ccf 5714 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5715 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5716 dest = bgp_route_next(dest)) {
5717 struct bgp_dest *rm;
d62a17ae 5718
5719 /* look for neighbor in tables */
9bcb3eef 5720 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5721 if (!table)
ea47320b
DL
5722 continue;
5723
5724 for (rm = bgp_table_top(table); rm;
5725 rm = bgp_route_next(rm))
9bcb3eef 5726 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5727 pi = pi->next) {
40381db7 5728 if (pi->peer != peer)
ea47320b 5729 continue;
1479ed2f
DA
5730 if (CHECK_FLAG(
5731 peer->af_sflags[afi][safi],
5732 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5733 bgp_attr_get_community(pi->attr) &&
1479ed2f 5734 !community_include(
9a706b42
DA
5735 bgp_attr_get_community(
5736 pi->attr),
1479ed2f 5737 COMMUNITY_NO_LLGR))
e3015d91 5738 continue;
40381db7 5739 if (!CHECK_FLAG(pi->flags,
1defdda8 5740 BGP_PATH_STALE))
e3015d91 5741 continue;
ea47320b 5742
641065d4
KM
5743 /*
5744 * If this is VRF leaked route
5745 * process for withdraw.
5746 */
5747 if (pi->sub_type ==
5748 BGP_ROUTE_IMPORTED &&
5749 peer->bgp->inst_type ==
5750 BGP_INSTANCE_TYPE_DEFAULT)
5751 vpn_leak_to_vrf_withdraw(
5752 peer->bgp, pi);
5753
40381db7 5754 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5755 break;
5756 }
d62a17ae 5757 }
5758 } else {
9bcb3eef
DS
5759 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5760 dest = bgp_route_next(dest))
5761 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5762 pi = pi->next) {
40381db7 5763 if (pi->peer != peer)
ea47320b 5764 continue;
1479ed2f
DA
5765 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5766 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5767 bgp_attr_get_community(pi->attr) &&
5768 !community_include(
5769 bgp_attr_get_community(pi->attr),
5770 COMMUNITY_NO_LLGR))
e3015d91 5771 continue;
40381db7 5772 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5773 continue;
641065d4
KM
5774 if (safi == SAFI_UNICAST &&
5775 (peer->bgp->inst_type ==
5776 BGP_INSTANCE_TYPE_VRF ||
5777 peer->bgp->inst_type ==
5778 BGP_INSTANCE_TYPE_DEFAULT))
5779 vpn_leak_from_vrf_withdraw(
5780 bgp_get_default(), peer->bgp,
5781 pi);
5782
9bcb3eef 5783 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5784 break;
5785 }
d62a17ae 5786 }
93406d87 5787}
6b0655a2 5788
9af52ccf
DA
5789void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5790{
5791 struct bgp_dest *dest, *ndest;
5792 struct bgp_path_info *pi;
5793 struct bgp_table *table;
5794
5795 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5796 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5797 dest = bgp_route_next(dest)) {
5798 table = bgp_dest_get_bgp_table_info(dest);
5799 if (!table)
5800 continue;
5801
5802 for (ndest = bgp_table_top(table); ndest;
5803 ndest = bgp_route_next(ndest)) {
5804 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5805 pi = pi->next) {
5806 if (pi->peer != peer)
5807 continue;
5808
5809 if ((CHECK_FLAG(
5810 peer->af_sflags[afi][safi],
5811 PEER_STATUS_ENHANCED_REFRESH))
5812 && !CHECK_FLAG(pi->flags,
5813 BGP_PATH_STALE)
5814 && !CHECK_FLAG(
5815 pi->flags,
5816 BGP_PATH_UNUSEABLE)) {
5817 if (bgp_debug_neighbor_events(
5818 peer))
5819 zlog_debug(
58e111f6
DA
5820 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5821 peer,
9af52ccf
DA
5822 afi2str(afi),
5823 safi2str(safi),
5824 bgp_dest_get_prefix(
5825 ndest));
5826
5827 bgp_path_info_set_flag(
5828 ndest, pi,
5829 BGP_PATH_STALE);
5830 }
5831 }
5832 }
5833 }
5834 } else {
5835 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5836 dest = bgp_route_next(dest)) {
5837 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5838 pi = pi->next) {
5839 if (pi->peer != peer)
5840 continue;
5841
5842 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5843 PEER_STATUS_ENHANCED_REFRESH))
5844 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5845 && !CHECK_FLAG(pi->flags,
5846 BGP_PATH_UNUSEABLE)) {
5847 if (bgp_debug_neighbor_events(peer))
5848 zlog_debug(
58e111f6
DA
5849 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5850 peer, afi2str(afi),
9af52ccf
DA
5851 safi2str(safi),
5852 bgp_dest_get_prefix(
5853 dest));
5854
5855 bgp_path_info_set_flag(dest, pi,
5856 BGP_PATH_STALE);
5857 }
5858 }
5859 }
5860 }
5861}
5862
3dc339cd 5863bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5864{
e0df4c04 5865 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5866 return true;
e0df4c04 5867
9dac9fc8
DA
5868 if (peer->sort == BGP_PEER_EBGP
5869 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5870 || FILTER_LIST_OUT_NAME(filter)
5871 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5872 return true;
5873 return false;
9dac9fc8
DA
5874}
5875
3dc339cd 5876bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5877{
e0df4c04 5878 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5879 return true;
e0df4c04 5880
9dac9fc8
DA
5881 if (peer->sort == BGP_PEER_EBGP
5882 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5883 || FILTER_LIST_IN_NAME(filter)
5884 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5885 return true;
5886 return false;
9dac9fc8
DA
5887}
5888
568e10ca 5889static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5890 safi_t safi)
bb86c601 5891{
9bcb3eef 5892 struct bgp_dest *dest;
40381db7 5893 struct bgp_path_info *pi;
4b7e6066 5894 struct bgp_path_info *next;
bb86c601 5895
9bcb3eef
DS
5896 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5897 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5898 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5899
40381db7 5900 next = pi->next;
1b7bb747
CS
5901
5902 /* Unimport EVPN routes from VRFs */
5903 if (safi == SAFI_EVPN)
5904 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5905 SAFI_EVPN, p, pi);
1b7bb747 5906
40381db7
DS
5907 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5908 && pi->type == ZEBRA_ROUTE_BGP
5909 && (pi->sub_type == BGP_ROUTE_NORMAL
5910 || pi->sub_type == BGP_ROUTE_AGGREGATE
5911 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5912
d62a17ae 5913 if (bgp_fibupd_safi(safi))
b54892e0 5914 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5915 }
9514b37d 5916
9bcb3eef 5917 bgp_path_info_reap(dest, pi);
d62a17ae 5918 }
bb86c601
LB
5919}
5920
718e3744 5921/* Delete all kernel routes. */
d62a17ae 5922void bgp_cleanup_routes(struct bgp *bgp)
5923{
5924 afi_t afi;
9bcb3eef 5925 struct bgp_dest *dest;
67009e22 5926 struct bgp_table *table;
d62a17ae 5927
5928 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5929 if (afi == AFI_L2VPN)
5930 continue;
568e10ca 5931 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5932 SAFI_UNICAST);
d62a17ae 5933 /*
5934 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5935 */
5936 if (afi != AFI_L2VPN) {
5937 safi_t safi;
5938 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5939 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5940 dest = bgp_route_next(dest)) {
5941 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5942 if (table != NULL) {
5943 bgp_cleanup_table(bgp, table, safi);
5944 bgp_table_finish(&table);
9bcb3eef
DS
5945 bgp_dest_set_bgp_table_info(dest, NULL);
5946 bgp_dest_unlock_node(dest);
d62a17ae 5947 }
5948 }
5949 safi = SAFI_ENCAP;
9bcb3eef
DS
5950 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5951 dest = bgp_route_next(dest)) {
5952 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5953 if (table != NULL) {
5954 bgp_cleanup_table(bgp, table, safi);
5955 bgp_table_finish(&table);
9bcb3eef
DS
5956 bgp_dest_set_bgp_table_info(dest, NULL);
5957 bgp_dest_unlock_node(dest);
d62a17ae 5958 }
5959 }
5960 }
5961 }
9bcb3eef
DS
5962 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5963 dest = bgp_route_next(dest)) {
5964 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5965 if (table != NULL) {
5966 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5967 bgp_table_finish(&table);
9bcb3eef
DS
5968 bgp_dest_set_bgp_table_info(dest, NULL);
5969 bgp_dest_unlock_node(dest);
d62a17ae 5970 }
bb86c601 5971 }
718e3744 5972}
5973
d62a17ae 5974void bgp_reset(void)
718e3744 5975{
d62a17ae 5976 vty_reset();
5977 bgp_zclient_reset();
5978 access_list_reset();
5979 prefix_list_reset();
718e3744 5980}
6b0655a2 5981
be92fc9f 5982bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5983{
d62a17ae 5984 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5985 && CHECK_FLAG(peer->af_cap[afi][safi],
5986 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5987}
5988
718e3744 5989/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5990 value. */
d62a17ae 5991int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5992 struct bgp_nlri *packet)
5993{
d7c0a89a
QY
5994 uint8_t *pnt;
5995 uint8_t *lim;
d62a17ae 5996 struct prefix p;
5997 int psize;
5998 int ret;
5999 afi_t afi;
6000 safi_t safi;
be92fc9f 6001 bool addpath_capable;
d7c0a89a 6002 uint32_t addpath_id;
d62a17ae 6003
d62a17ae 6004 pnt = packet->nlri;
6005 lim = pnt + packet->length;
6006 afi = packet->afi;
6007 safi = packet->safi;
6008 addpath_id = 0;
be92fc9f 6009 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 6010
6011 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
6012 syntactic validity. If the field is syntactically incorrect,
6013 then the Error Subcode is set to Invalid Network Field. */
6014 for (; pnt < lim; pnt += psize) {
6015 /* Clear prefix structure. */
6006b807 6016 memset(&p, 0, sizeof(p));
d62a17ae 6017
be92fc9f 6018 if (addpath_capable) {
d62a17ae 6019
6020 /* When packet overflow occurs return immediately. */
761ed665 6021 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 6022 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6023
a3a850a1 6024 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 6025 addpath_id = ntohl(addpath_id);
d62a17ae 6026 pnt += BGP_ADDPATH_ID_LEN;
6027 }
718e3744 6028
d62a17ae 6029 /* Fetch prefix length. */
6030 p.prefixlen = *pnt++;
6031 /* afi/safi validity already verified by caller,
6032 * bgp_update_receive */
6033 p.family = afi2family(afi);
6034
6035 /* Prefix length check. */
6036 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 6037 flog_err(
e50f7cfd 6038 EC_BGP_UPDATE_RCV,
14454c9f 6039 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 6040 peer->host, p.prefixlen, packet->afi);
513386b5 6041 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 6042 }
6b0655a2 6043
d62a17ae 6044 /* Packet size overflow check. */
6045 psize = PSIZE(p.prefixlen);
6046
6047 /* When packet overflow occur return immediately. */
6048 if (pnt + psize > lim) {
af4c2728 6049 flog_err(
e50f7cfd 6050 EC_BGP_UPDATE_RCV,
d62a17ae 6051 "%s [Error] Update packet error (prefix length %d overflows packet)",
6052 peer->host, p.prefixlen);
513386b5 6053 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 6054 }
6055
6056 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
6057 * prefix for the v4 and v6 afi's and unicast/multicast */
6058 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 6059 flog_err(
e50f7cfd 6060 EC_BGP_UPDATE_RCV,
d62a17ae 6061 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 6062 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 6063 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6064 }
6065
6066 /* Fetch prefix from NLRI packet. */
a85297a7 6067 memcpy(p.u.val, pnt, psize);
d62a17ae 6068
6069 /* Check address. */
6070 if (afi == AFI_IP && safi == SAFI_UNICAST) {
6071 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6072 /* From RFC4271 Section 6.3:
6073 *
6074 * If a prefix in the NLRI field is semantically
6075 * incorrect
6076 * (e.g., an unexpected multicast IP address),
6077 * an error SHOULD
6078 * be logged locally, and the prefix SHOULD be
6079 * ignored.
a4d82a8a 6080 */
af4c2728 6081 flog_err(
e50f7cfd 6082 EC_BGP_UPDATE_RCV,
23d0a753
DA
6083 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6084 peer->host, &p.u.prefix4);
d62a17ae 6085 continue;
6086 }
6087 }
6088
6089 /* Check address. */
6090 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6091 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 6092 flog_err(
e50f7cfd 6093 EC_BGP_UPDATE_RCV,
c0d72166
DS
6094 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6095 peer->host, &p.u.prefix6);
d62a17ae 6096
6097 continue;
6098 }
6099 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 6100 flog_err(
e50f7cfd 6101 EC_BGP_UPDATE_RCV,
c0d72166
DS
6102 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6103 peer->host, &p.u.prefix6);
d62a17ae 6104
6105 continue;
6106 }
6107 }
6108
6109 /* Normal process. */
6110 if (attr)
6111 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
6112 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 6113 NULL, NULL, 0, 0, NULL);
d62a17ae 6114 else
6115 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
6116 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
6117 BGP_ROUTE_NORMAL, NULL, NULL, 0,
6118 NULL);
d62a17ae 6119
513386b5
DA
6120 /* Do not send BGP notification twice when maximum-prefix count
6121 * overflow. */
6122 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6123 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6124
6125 /* Address family configuration mismatch. */
d62a17ae 6126 if (ret < 0)
513386b5 6127 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 6128 }
6129
6130 /* Packet length consistency check. */
6131 if (pnt != lim) {
af4c2728 6132 flog_err(
e50f7cfd 6133 EC_BGP_UPDATE_RCV,
d62a17ae 6134 "%s [Error] Update packet error (prefix length mismatch with total length)",
6135 peer->host);
513386b5 6136 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 6137 }
6b0655a2 6138
513386b5 6139 return BGP_NLRI_PARSE_OK;
718e3744 6140}
6141
d62a17ae 6142static struct bgp_static *bgp_static_new(void)
718e3744 6143{
d62a17ae 6144 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 6145}
6146
d62a17ae 6147static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 6148{
0a22ddfb 6149 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6150 route_map_counter_decrement(bgp_static->rmap.map);
6151
0a22ddfb 6152 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 6153 XFREE(MTYPE_BGP_STATIC, bgp_static);
6154}
6155
5f040085 6156void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 6157 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6158{
9bcb3eef 6159 struct bgp_dest *dest;
40381db7 6160 struct bgp_path_info *pi;
4b7e6066 6161 struct bgp_path_info *new;
40381db7 6162 struct bgp_path_info rmap_path;
d62a17ae 6163 struct attr attr;
6164 struct attr *attr_new;
b68885f9 6165 route_map_result_t ret;
49e5a4a0 6166#ifdef ENABLE_BGP_VNC
d62a17ae 6167 int vnc_implicit_withdraw = 0;
65efcfce 6168#endif
fee0f4c6 6169
d62a17ae 6170 assert(bgp_static);
dd8103a9 6171
9bcb3eef 6172 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6173
0f05ea43 6174 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 6175
d62a17ae 6176 attr.nexthop = bgp_static->igpnexthop;
6177 attr.med = bgp_static->igpmetric;
6178 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 6179
7226bc40
TA
6180 if (afi == AFI_IP)
6181 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6182
97a52c82
DA
6183 if (bgp_static->igpmetric)
6184 bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6185
d62a17ae 6186 if (bgp_static->atomic)
6187 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 6188
d62a17ae 6189 /* Store label index, if required. */
6190 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6191 attr.label_index = bgp_static->label_index;
6192 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6193 }
718e3744 6194
d62a17ae 6195 /* Apply route-map. */
6196 if (bgp_static->rmap.name) {
6197 struct attr attr_tmp = attr;
80ced710 6198
6006b807 6199 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6200 rmap_path.peer = bgp->peer_self;
6201 rmap_path.attr = &attr_tmp;
fee0f4c6 6202
d62a17ae 6203 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6204
1782514f 6205 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6206
d62a17ae 6207 bgp->peer_self->rmap_type = 0;
718e3744 6208
d62a17ae 6209 if (ret == RMAP_DENYMATCH) {
6210 /* Free uninterned attribute. */
6211 bgp_attr_flush(&attr_tmp);
718e3744 6212
d62a17ae 6213 /* Unintern original. */
6214 aspath_unintern(&attr.aspath);
6215 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6216 bgp_dest_unlock_node(dest);
d62a17ae 6217 return;
6218 }
7f323236 6219
637e5ba4 6220 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6221 bgp_attr_add_gshut_community(&attr_tmp);
6222
d62a17ae 6223 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6224 } else {
6225
637e5ba4 6226 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6227 bgp_attr_add_gshut_community(&attr);
6228
d62a17ae 6229 attr_new = bgp_attr_intern(&attr);
7f323236 6230 }
718e3744 6231
9bcb3eef 6232 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6233 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6234 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6235 break;
6236
40381db7
DS
6237 if (pi) {
6238 if (attrhash_cmp(pi->attr, attr_new)
6239 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6240 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6241 bgp_dest_unlock_node(dest);
d62a17ae 6242 bgp_attr_unintern(&attr_new);
6243 aspath_unintern(&attr.aspath);
6244 return;
6245 } else {
6246 /* The attribute is changed. */
9bcb3eef 6247 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6248
6249 /* Rewrite BGP route information. */
40381db7 6250 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6251 bgp_path_info_restore(dest, pi);
d62a17ae 6252 else
40381db7 6253 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6254#ifdef ENABLE_BGP_VNC
d62a17ae 6255 if ((afi == AFI_IP || afi == AFI_IP6)
6256 && (safi == SAFI_UNICAST)) {
40381db7 6257 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6258 /*
6259 * Implicit withdraw case.
40381db7 6260 * We have to do this before pi is
d62a17ae 6261 * changed
6262 */
6263 ++vnc_implicit_withdraw;
40381db7 6264 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6265 vnc_import_bgp_exterior_del_route(
40381db7 6266 bgp, p, pi);
d62a17ae 6267 }
6268 }
65efcfce 6269#endif
40381db7
DS
6270 bgp_attr_unintern(&pi->attr);
6271 pi->attr = attr_new;
083ec940 6272 pi->uptime = monotime(NULL);
49e5a4a0 6273#ifdef ENABLE_BGP_VNC
d62a17ae 6274 if ((afi == AFI_IP || afi == AFI_IP6)
6275 && (safi == SAFI_UNICAST)) {
6276 if (vnc_implicit_withdraw) {
40381db7 6277 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6278 vnc_import_bgp_exterior_add_route(
40381db7 6279 bgp, p, pi);
d62a17ae 6280 }
6281 }
65efcfce 6282#endif
718e3744 6283
d62a17ae 6284 /* Nexthop reachability check. */
892fedb6 6285 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6286 && (safi == SAFI_UNICAST
6287 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6288
6289 struct bgp *bgp_nexthop = bgp;
6290
40381db7
DS
6291 if (pi->extra && pi->extra->bgp_orig)
6292 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6293
6294 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6295 afi, safi, pi, NULL,
654a5978 6296 0, p))
9bcb3eef 6297 bgp_path_info_set_flag(dest, pi,
18ee8310 6298 BGP_PATH_VALID);
d62a17ae 6299 else {
6300 if (BGP_DEBUG(nht, NHT)) {
6301 char buf1[INET6_ADDRSTRLEN];
6302 inet_ntop(p->family,
6303 &p->u.prefix, buf1,
6304 INET6_ADDRSTRLEN);
6305 zlog_debug(
6306 "%s(%s): Route not in table, not advertising",
15569c58 6307 __func__, buf1);
d62a17ae 6308 }
18ee8310 6309 bgp_path_info_unset_flag(
9bcb3eef 6310 dest, pi, BGP_PATH_VALID);
d62a17ae 6311 }
6312 } else {
6313 /* Delete the NHT structure if any, if we're
6314 * toggling between
6315 * enabling/disabling import check. We
6316 * deregister the route
6317 * from NHT to avoid overloading NHT and the
6318 * process interaction
6319 */
40381db7 6320 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6321 bgp_path_info_set_flag(dest, pi,
6322 BGP_PATH_VALID);
d62a17ae 6323 }
6324 /* Process change. */
40381db7 6325 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6326 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6327
6328 if (SAFI_UNICAST == safi
6329 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6330 || bgp->inst_type
6331 == BGP_INSTANCE_TYPE_DEFAULT)) {
6332 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6333 pi);
ddb5b488
PZ
6334 }
6335
9bcb3eef 6336 bgp_dest_unlock_node(dest);
d62a17ae 6337 aspath_unintern(&attr.aspath);
6338 return;
6339 }
718e3744 6340 }
718e3744 6341
d62a17ae 6342 /* Make new BGP info. */
6343 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6344 attr_new, dest);
d62a17ae 6345 /* Nexthop reachability check. */
892fedb6 6346 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6347 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6348 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6349 p))
9bcb3eef 6350 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6351 else {
6352 if (BGP_DEBUG(nht, NHT)) {
6353 char buf1[INET6_ADDRSTRLEN];
6354 inet_ntop(p->family, &p->u.prefix, buf1,
6355 INET6_ADDRSTRLEN);
6356 zlog_debug(
6357 "%s(%s): Route not in table, not advertising",
15569c58 6358 __func__, buf1);
d62a17ae 6359 }
9bcb3eef 6360 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6361 }
6362 } else {
6363 /* Delete the NHT structure if any, if we're toggling between
6364 * enabling/disabling import check. We deregister the route
6365 * from NHT to avoid overloading NHT and the process interaction
6366 */
6367 bgp_unlink_nexthop(new);
6368
9bcb3eef 6369 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6370 }
078430f6 6371
d62a17ae 6372 /* Aggregate address increment. */
6373 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6374
d62a17ae 6375 /* Register new BGP information. */
9bcb3eef 6376 bgp_path_info_add(dest, new);
718e3744 6377
d62a17ae 6378 /* route_node_get lock */
9bcb3eef 6379 bgp_dest_unlock_node(dest);
d62a17ae 6380
6381 /* Process change. */
9bcb3eef 6382 bgp_process(bgp, dest, afi, safi);
d62a17ae 6383
ddb5b488
PZ
6384 if (SAFI_UNICAST == safi
6385 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6386 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6387 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6388 }
6389
d62a17ae 6390 /* Unintern original. */
6391 aspath_unintern(&attr.aspath);
718e3744 6392}
6393
5f040085 6394void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6395 safi_t safi)
718e3744 6396{
9bcb3eef 6397 struct bgp_dest *dest;
40381db7 6398 struct bgp_path_info *pi;
718e3744 6399
9bcb3eef 6400 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6401
d62a17ae 6402 /* Check selected route and self inserted route. */
9bcb3eef 6403 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6404 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6405 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6406 break;
6407
6408 /* Withdraw static BGP route from routing table. */
40381db7 6409 if (pi) {
ddb5b488
PZ
6410 if (SAFI_UNICAST == safi
6411 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6412 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6413 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6414 }
40381db7
DS
6415 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6416 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6417 bgp_path_info_delete(dest, pi);
6418 bgp_process(bgp, dest, afi, safi);
d62a17ae 6419 }
718e3744 6420
d62a17ae 6421 /* Unlock bgp_node_lookup. */
9bcb3eef 6422 bgp_dest_unlock_node(dest);
718e3744 6423}
6424
137446f9
LB
6425/*
6426 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6427 */
5f040085 6428static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6429 afi_t afi, safi_t safi,
6430 struct prefix_rd *prd)
718e3744 6431{
9bcb3eef 6432 struct bgp_dest *dest;
40381db7 6433 struct bgp_path_info *pi;
718e3744 6434
9bcb3eef 6435 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6436
d62a17ae 6437 /* Check selected route and self inserted route. */
9bcb3eef 6438 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6439 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6440 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6441 break;
718e3744 6442
d62a17ae 6443 /* Withdraw static BGP route from routing table. */
40381db7 6444 if (pi) {
49e5a4a0 6445#ifdef ENABLE_BGP_VNC
d62a17ae 6446 rfapiProcessWithdraw(
40381db7 6447 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6448 1); /* Kill, since it is an administrative change */
65efcfce 6449#endif
ddb5b488
PZ
6450 if (SAFI_MPLS_VPN == safi
6451 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6452 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6453 }
40381db7 6454 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6455 bgp_path_info_delete(dest, pi);
6456 bgp_process(bgp, dest, afi, safi);
d62a17ae 6457 }
718e3744 6458
d62a17ae 6459 /* Unlock bgp_node_lookup. */
9bcb3eef 6460 bgp_dest_unlock_node(dest);
718e3744 6461}
6462
5f040085 6463static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6464 struct bgp_static *bgp_static, afi_t afi,
6465 safi_t safi)
137446f9 6466{
9bcb3eef 6467 struct bgp_dest *dest;
4b7e6066 6468 struct bgp_path_info *new;
d62a17ae 6469 struct attr *attr_new;
6470 struct attr attr = {0};
40381db7 6471 struct bgp_path_info *pi;
49e5a4a0 6472#ifdef ENABLE_BGP_VNC
d62a17ae 6473 mpls_label_t label = 0;
65efcfce 6474#endif
d7c0a89a 6475 uint32_t num_labels = 0;
137446f9 6476
d62a17ae 6477 assert(bgp_static);
137446f9 6478
b57ba6d2
MK
6479 if (bgp_static->label != MPLS_INVALID_LABEL)
6480 num_labels = 1;
9bcb3eef
DS
6481 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6482 &bgp_static->prd);
137446f9 6483
0f05ea43 6484 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6485
d62a17ae 6486 attr.nexthop = bgp_static->igpnexthop;
6487 attr.med = bgp_static->igpmetric;
6488 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6489
d62a17ae 6490 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6491 || (safi == SAFI_ENCAP)) {
6492 if (afi == AFI_IP) {
6493 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6494 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6495 }
6496 }
6497 if (afi == AFI_L2VPN) {
b04c1e99
IR
6498 if (bgp_static->gatewayIp.family == AF_INET) {
6499 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6500 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6501 &bgp_static->gatewayIp.u.prefix4,
6502 IPV4_MAX_BYTELEN);
b04c1e99
IR
6503 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6504 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6505 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6506 &bgp_static->gatewayIp.u.prefix6,
6507 IPV6_MAX_BYTELEN);
b04c1e99 6508 }
0a50c248 6509 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6510 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6511 struct bgp_encap_type_vxlan bet;
6006b807 6512 memset(&bet, 0, sizeof(bet));
3714a385 6513 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6514 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6515 }
6516 if (bgp_static->router_mac) {
6517 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6518 }
6519 }
6520 /* Apply route-map. */
6521 if (bgp_static->rmap.name) {
6522 struct attr attr_tmp = attr;
40381db7 6523 struct bgp_path_info rmap_path;
b68885f9 6524 route_map_result_t ret;
137446f9 6525
40381db7
DS
6526 rmap_path.peer = bgp->peer_self;
6527 rmap_path.attr = &attr_tmp;
137446f9 6528
d62a17ae 6529 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6530
1782514f 6531 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6532
d62a17ae 6533 bgp->peer_self->rmap_type = 0;
137446f9 6534
d62a17ae 6535 if (ret == RMAP_DENYMATCH) {
6536 /* Free uninterned attribute. */
6537 bgp_attr_flush(&attr_tmp);
137446f9 6538
d62a17ae 6539 /* Unintern original. */
6540 aspath_unintern(&attr.aspath);
6541 bgp_static_withdraw_safi(bgp, p, afi, safi,
6542 &bgp_static->prd);
bbc52106 6543 bgp_dest_unlock_node(dest);
d62a17ae 6544 return;
6545 }
137446f9 6546
d62a17ae 6547 attr_new = bgp_attr_intern(&attr_tmp);
6548 } else {
6549 attr_new = bgp_attr_intern(&attr);
6550 }
137446f9 6551
9bcb3eef 6552 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6553 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6554 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6555 break;
6556
40381db7 6557 if (pi) {
40381db7 6558 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6559 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6560 bgp_dest_unlock_node(dest);
d62a17ae 6561 bgp_attr_unintern(&attr_new);
6562 aspath_unintern(&attr.aspath);
6563 return;
6564 } else {
6565 /* The attribute is changed. */
9bcb3eef 6566 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6567
6568 /* Rewrite BGP route information. */
40381db7 6569 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6570 bgp_path_info_restore(dest, pi);
d62a17ae 6571 else
40381db7
DS
6572 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6573 bgp_attr_unintern(&pi->attr);
6574 pi->attr = attr_new;
083ec940 6575 pi->uptime = monotime(NULL);
49e5a4a0 6576#ifdef ENABLE_BGP_VNC
40381db7
DS
6577 if (pi->extra)
6578 label = decode_label(&pi->extra->label[0]);
65efcfce 6579#endif
137446f9 6580
d62a17ae 6581 /* Process change. */
40381db7 6582 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6583 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6584
6585 if (SAFI_MPLS_VPN == safi
6586 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0
DA
6587 vpn_leak_to_vrf_update(bgp, pi,
6588 &bgp_static->prd);
ddb5b488 6589 }
49e5a4a0 6590#ifdef ENABLE_BGP_VNC
40381db7
DS
6591 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6592 pi->attr, afi, safi, pi->type,
6593 pi->sub_type, &label);
65efcfce 6594#endif
9bcb3eef 6595 bgp_dest_unlock_node(dest);
d62a17ae 6596 aspath_unintern(&attr.aspath);
6597 return;
6598 }
6599 }
137446f9
LB
6600
6601
d62a17ae 6602 /* Make new BGP info. */
6603 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6604 attr_new, dest);
1defdda8 6605 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6606 bgp_path_info_extra_get(new);
b57ba6d2
MK
6607 if (num_labels) {
6608 new->extra->label[0] = bgp_static->label;
6609 new->extra->num_labels = num_labels;
6610 }
49e5a4a0 6611#ifdef ENABLE_BGP_VNC
d62a17ae 6612 label = decode_label(&bgp_static->label);
65efcfce 6613#endif
137446f9 6614
d62a17ae 6615 /* Aggregate address increment. */
6616 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6617
d62a17ae 6618 /* Register new BGP information. */
9bcb3eef 6619 bgp_path_info_add(dest, new);
d62a17ae 6620 /* route_node_get lock */
9bcb3eef 6621 bgp_dest_unlock_node(dest);
137446f9 6622
d62a17ae 6623 /* Process change. */
9bcb3eef 6624 bgp_process(bgp, dest, afi, safi);
137446f9 6625
ddb5b488
PZ
6626 if (SAFI_MPLS_VPN == safi
6627 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
46dbf9d0 6628 vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
ddb5b488 6629 }
49e5a4a0 6630#ifdef ENABLE_BGP_VNC
d62a17ae 6631 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6632 safi, new->type, new->sub_type, &label);
65efcfce
LB
6633#endif
6634
d62a17ae 6635 /* Unintern original. */
6636 aspath_unintern(&attr.aspath);
137446f9
LB
6637}
6638
718e3744 6639/* Configure static BGP network. When user don't run zebra, static
6640 route should be installed as valid. */
585f1adc
IR
6641static int bgp_static_set(struct vty *vty, const char *negate,
6642 const char *ip_str, afi_t afi, safi_t safi,
6643 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6644{
585f1adc
IR
6645 VTY_DECLVAR_CONTEXT(bgp, bgp);
6646 int ret;
d62a17ae 6647 struct prefix p;
6648 struct bgp_static *bgp_static;
9bcb3eef 6649 struct bgp_dest *dest;
d7c0a89a 6650 uint8_t need_update = 0;
d62a17ae 6651
585f1adc
IR
6652 /* Convert IP prefix string to struct prefix. */
6653 ret = str2prefix(ip_str, &p);
6654 if (!ret) {
6655 vty_out(vty, "%% Malformed prefix\n");
6656 return CMD_WARNING_CONFIG_FAILED;
6657 }
6658 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6659 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6660 return CMD_WARNING_CONFIG_FAILED;
6661 }
6662
d62a17ae 6663 apply_mask(&p);
718e3744 6664
e2a86ad9 6665 if (negate) {
718e3744 6666
e2a86ad9 6667 /* Set BGP static route configuration. */
9bcb3eef 6668 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6669
9bcb3eef 6670 if (!dest) {
585f1adc
IR
6671 vty_out(vty, "%% Can't find static route specified\n");
6672 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6673 }
6674
9bcb3eef 6675 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6676
e2a86ad9
DS
6677 if ((label_index != BGP_INVALID_LABEL_INDEX)
6678 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6679 vty_out(vty,
6680 "%% label-index doesn't match static route\n");
70d9b134 6681 bgp_dest_unlock_node(dest);
585f1adc 6682 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6683 }
d62a17ae 6684
e2a86ad9
DS
6685 if ((rmap && bgp_static->rmap.name)
6686 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6687 vty_out(vty,
6688 "%% route-map name doesn't match static route\n");
70d9b134 6689 bgp_dest_unlock_node(dest);
585f1adc 6690 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6691 }
718e3744 6692
e2a86ad9
DS
6693 /* Update BGP RIB. */
6694 if (!bgp_static->backdoor)
6695 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6696
e2a86ad9
DS
6697 /* Clear configuration. */
6698 bgp_static_free(bgp_static);
9bcb3eef
DS
6699 bgp_dest_set_bgp_static_info(dest, NULL);
6700 bgp_dest_unlock_node(dest);
6701 bgp_dest_unlock_node(dest);
e2a86ad9 6702 } else {
718e3744 6703
e2a86ad9 6704 /* Set BGP static route configuration. */
9bcb3eef
DS
6705 dest = bgp_node_get(bgp->route[afi][safi], &p);
6706 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6707 if (bgp_static) {
e2a86ad9 6708 /* Configuration change. */
e2a86ad9
DS
6709 /* Label index cannot be changed. */
6710 if (bgp_static->label_index != label_index) {
585f1adc 6711 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6712 bgp_dest_unlock_node(dest);
585f1adc 6713 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6714 }
d62a17ae 6715
e2a86ad9 6716 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6717 if (bgp_static->valid
6718 && bgp_static->backdoor != backdoor)
e2a86ad9 6719 need_update = 1;
718e3744 6720
e2a86ad9 6721 bgp_static->backdoor = backdoor;
718e3744 6722
e2a86ad9 6723 if (rmap) {
0a22ddfb
QY
6724 XFREE(MTYPE_ROUTE_MAP_NAME,
6725 bgp_static->rmap.name);
b4897fa5 6726 route_map_counter_decrement(
6727 bgp_static->rmap.map);
e2a86ad9
DS
6728 bgp_static->rmap.name =
6729 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6730 bgp_static->rmap.map =
6731 route_map_lookup_by_name(rmap);
b4897fa5 6732 route_map_counter_increment(
6733 bgp_static->rmap.map);
e2a86ad9 6734 } else {
0a22ddfb
QY
6735 XFREE(MTYPE_ROUTE_MAP_NAME,
6736 bgp_static->rmap.name);
b4897fa5 6737 route_map_counter_decrement(
6738 bgp_static->rmap.map);
e2a86ad9
DS
6739 bgp_static->rmap.map = NULL;
6740 bgp_static->valid = 0;
6741 }
9bcb3eef 6742 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6743 } else {
6744 /* New configuration. */
6745 bgp_static = bgp_static_new();
6746 bgp_static->backdoor = backdoor;
6747 bgp_static->valid = 0;
6748 bgp_static->igpmetric = 0;
975a328e 6749 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6750 bgp_static->label_index = label_index;
718e3744 6751
e2a86ad9 6752 if (rmap) {
0a22ddfb
QY
6753 XFREE(MTYPE_ROUTE_MAP_NAME,
6754 bgp_static->rmap.name);
b4897fa5 6755 route_map_counter_decrement(
6756 bgp_static->rmap.map);
e2a86ad9
DS
6757 bgp_static->rmap.name =
6758 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6759 bgp_static->rmap.map =
6760 route_map_lookup_by_name(rmap);
b4897fa5 6761 route_map_counter_increment(
6762 bgp_static->rmap.map);
e2a86ad9 6763 }
9bcb3eef 6764 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6765 }
d62a17ae 6766
e2a86ad9
DS
6767 bgp_static->valid = 1;
6768 if (need_update)
6769 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6770
e2a86ad9
DS
6771 if (!bgp_static->backdoor)
6772 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6773 }
d62a17ae 6774
585f1adc 6775 return CMD_SUCCESS;
d62a17ae 6776}
6777
6778void bgp_static_add(struct bgp *bgp)
6779{
6780 afi_t afi;
6781 safi_t safi;
9bcb3eef
DS
6782 struct bgp_dest *dest;
6783 struct bgp_dest *rm;
d62a17ae 6784 struct bgp_table *table;
6785 struct bgp_static *bgp_static;
6786
47fc6261 6787 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6788 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6789 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6790 dest = bgp_route_next(dest)) {
6791 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6792 continue;
ea47320b 6793
05c7a1cc
QY
6794 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6795 || (safi == SAFI_EVPN)) {
9bcb3eef 6796 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6797
6798 for (rm = bgp_table_top(table); rm;
6799 rm = bgp_route_next(rm)) {
a78beeb5 6800 bgp_static =
9bcb3eef 6801 bgp_dest_get_bgp_static_info(
5a8ba9fc 6802 rm);
9bcb3eef
DS
6803 bgp_static_update_safi(
6804 bgp, bgp_dest_get_prefix(rm),
6805 bgp_static, afi, safi);
d62a17ae 6806 }
05c7a1cc 6807 } else {
5a8ba9fc 6808 bgp_static_update(
9bcb3eef
DS
6809 bgp, bgp_dest_get_prefix(dest),
6810 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6811 safi);
ea47320b 6812 }
05c7a1cc 6813 }
47fc6261 6814 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6815}
6816
718e3744 6817/* Called from bgp_delete(). Delete all static routes from the BGP
6818 instance. */
d62a17ae 6819void bgp_static_delete(struct bgp *bgp)
6820{
6821 afi_t afi;
6822 safi_t safi;
9bcb3eef
DS
6823 struct bgp_dest *dest;
6824 struct bgp_dest *rm;
d62a17ae 6825 struct bgp_table *table;
6826 struct bgp_static *bgp_static;
6827
05c7a1cc 6828 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6829 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6830 dest = bgp_route_next(dest)) {
6831 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6832 continue;
ea47320b 6833
05c7a1cc
QY
6834 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6835 || (safi == SAFI_EVPN)) {
9bcb3eef 6836 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6837
6838 for (rm = bgp_table_top(table); rm;
6839 rm = bgp_route_next(rm)) {
a78beeb5 6840 bgp_static =
9bcb3eef 6841 bgp_dest_get_bgp_static_info(
5a8ba9fc 6842 rm);
c7d14ba6
PG
6843 if (!bgp_static)
6844 continue;
6845
05c7a1cc 6846 bgp_static_withdraw_safi(
9bcb3eef 6847 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6848 AFI_IP, safi,
6849 (struct prefix_rd *)
9bcb3eef
DS
6850 bgp_dest_get_prefix(
6851 dest));
ea47320b 6852 bgp_static_free(bgp_static);
811c6797 6853 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6854 NULL);
811c6797 6855 bgp_dest_unlock_node(rm);
d62a17ae 6856 }
05c7a1cc 6857 } else {
9bcb3eef 6858 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6859 bgp_static_withdraw(bgp,
9bcb3eef 6860 bgp_dest_get_prefix(dest),
b54892e0 6861 afi, safi);
05c7a1cc 6862 bgp_static_free(bgp_static);
9bcb3eef
DS
6863 bgp_dest_set_bgp_static_info(dest, NULL);
6864 bgp_dest_unlock_node(dest);
ea47320b 6865 }
05c7a1cc 6866 }
d62a17ae 6867}
6868
6869void bgp_static_redo_import_check(struct bgp *bgp)
6870{
6871 afi_t afi;
6872 safi_t safi;
9bcb3eef
DS
6873 struct bgp_dest *dest;
6874 struct bgp_dest *rm;
d62a17ae 6875 struct bgp_table *table;
6876 struct bgp_static *bgp_static;
6877
6878 /* Use this flag to force reprocessing of the route */
892fedb6 6879 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6880 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6881 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6882 dest = bgp_route_next(dest)) {
6883 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6884 continue;
ea47320b 6885
05c7a1cc
QY
6886 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6887 || (safi == SAFI_EVPN)) {
9bcb3eef 6888 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6889
6890 for (rm = bgp_table_top(table); rm;
6891 rm = bgp_route_next(rm)) {
a78beeb5 6892 bgp_static =
9bcb3eef 6893 bgp_dest_get_bgp_static_info(
5a8ba9fc 6894 rm);
9bcb3eef
DS
6895 bgp_static_update_safi(
6896 bgp, bgp_dest_get_prefix(rm),
6897 bgp_static, afi, safi);
d62a17ae 6898 }
05c7a1cc 6899 } else {
9bcb3eef
DS
6900 bgp_static = bgp_dest_get_bgp_static_info(dest);
6901 bgp_static_update(bgp,
6902 bgp_dest_get_prefix(dest),
6903 bgp_static, afi, safi);
ea47320b 6904 }
05c7a1cc
QY
6905 }
6906 }
892fedb6 6907 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6908}
6909
6910static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6911 safi_t safi)
6912{
6913 struct bgp_table *table;
9bcb3eef 6914 struct bgp_dest *dest;
40381db7 6915 struct bgp_path_info *pi;
d62a17ae 6916
dfb6fd1d
NT
6917 /* Do not install the aggregate route if BGP is in the
6918 * process of termination.
6919 */
892fedb6
DA
6920 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6921 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6922 return;
6923
d62a17ae 6924 table = bgp->rib[afi][safi];
9bcb3eef
DS
6925 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6926 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6927 if (pi->peer == bgp->peer_self
6928 && ((pi->type == ZEBRA_ROUTE_BGP
6929 && pi->sub_type == BGP_ROUTE_STATIC)
6930 || (pi->type != ZEBRA_ROUTE_BGP
6931 && pi->sub_type
d62a17ae 6932 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6933 bgp_aggregate_decrement(
6934 bgp, bgp_dest_get_prefix(dest), pi, afi,
6935 safi);
40381db7 6936 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6937 bgp_path_info_delete(dest, pi);
6938 bgp_process(bgp, dest, afi, safi);
d62a17ae 6939 }
6940 }
6941 }
ad4cbda1 6942}
6943
6944/*
6945 * Purge all networks and redistributed routes from routing table.
6946 * Invoked upon the instance going down.
6947 */
d62a17ae 6948void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6949{
d62a17ae 6950 afi_t afi;
6951 safi_t safi;
ad4cbda1 6952
05c7a1cc
QY
6953 FOREACH_AFI_SAFI (afi, safi)
6954 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6955}
6956
137446f9
LB
6957/*
6958 * gpz 110624
6959 * Currently this is used to set static routes for VPN and ENCAP.
6960 * I think it can probably be factored with bgp_static_set.
6961 */
d62a17ae 6962int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6963 const char *ip_str, const char *rd_str,
6964 const char *label_str, const char *rmap_str,
6965 int evpn_type, const char *esi, const char *gwip,
6966 const char *ethtag, const char *routermac)
6967{
6968 VTY_DECLVAR_CONTEXT(bgp, bgp);
6969 int ret;
6970 struct prefix p;
6971 struct prefix_rd prd;
9bcb3eef
DS
6972 struct bgp_dest *pdest;
6973 struct bgp_dest *dest;
d62a17ae 6974 struct bgp_table *table;
6975 struct bgp_static *bgp_static;
6976 mpls_label_t label = MPLS_INVALID_LABEL;
6977 struct prefix gw_ip;
6978
6979 /* validate ip prefix */
6980 ret = str2prefix(ip_str, &p);
6981 if (!ret) {
6982 vty_out(vty, "%% Malformed prefix\n");
6983 return CMD_WARNING_CONFIG_FAILED;
6984 }
6985 apply_mask(&p);
6986 if ((afi == AFI_L2VPN)
6987 && (bgp_build_evpn_prefix(evpn_type,
6988 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6989 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6990 return CMD_WARNING_CONFIG_FAILED;
6991 }
718e3744 6992
d62a17ae 6993 ret = str2prefix_rd(rd_str, &prd);
6994 if (!ret) {
6995 vty_out(vty, "%% Malformed rd\n");
6996 return CMD_WARNING_CONFIG_FAILED;
6997 }
718e3744 6998
d62a17ae 6999 if (label_str) {
7000 unsigned long label_val;
7001 label_val = strtoul(label_str, NULL, 10);
7002 encode_label(label_val, &label);
7003 }
9bedbb1e 7004
d62a17ae 7005 if (safi == SAFI_EVPN) {
7006 if (esi && str2esi(esi, NULL) == 0) {
7007 vty_out(vty, "%% Malformed ESI\n");
7008 return CMD_WARNING_CONFIG_FAILED;
7009 }
7010 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
7011 vty_out(vty, "%% Malformed Router MAC\n");
7012 return CMD_WARNING_CONFIG_FAILED;
7013 }
7014 if (gwip) {
6006b807 7015 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 7016 ret = str2prefix(gwip, &gw_ip);
7017 if (!ret) {
7018 vty_out(vty, "%% Malformed GatewayIp\n");
7019 return CMD_WARNING_CONFIG_FAILED;
7020 }
7021 if ((gw_ip.family == AF_INET
3714a385 7022 && is_evpn_prefix_ipaddr_v6(
d62a17ae 7023 (struct prefix_evpn *)&p))
7024 || (gw_ip.family == AF_INET6
3714a385 7025 && is_evpn_prefix_ipaddr_v4(
d62a17ae 7026 (struct prefix_evpn *)&p))) {
7027 vty_out(vty,
7028 "%% GatewayIp family differs with IP prefix\n");
7029 return CMD_WARNING_CONFIG_FAILED;
7030 }
7031 }
7032 }
9bcb3eef
DS
7033 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7034 if (!bgp_dest_has_bgp_path_info_data(pdest))
7035 bgp_dest_set_bgp_table_info(pdest,
67009e22 7036 bgp_table_init(bgp, afi, safi));
9bcb3eef 7037 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 7038
9bcb3eef 7039 dest = bgp_node_get(table, &p);
d62a17ae 7040
9bcb3eef 7041 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 7042 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 7043 bgp_dest_unlock_node(dest);
d62a17ae 7044 } else {
7045 /* New configuration. */
7046 bgp_static = bgp_static_new();
7047 bgp_static->backdoor = 0;
7048 bgp_static->valid = 0;
7049 bgp_static->igpmetric = 0;
975a328e 7050 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 7051 bgp_static->label = label;
7052 bgp_static->prd = prd;
7053
7054 if (rmap_str) {
0a22ddfb 7055 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 7056 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 7057 bgp_static->rmap.name =
7058 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
7059 bgp_static->rmap.map =
7060 route_map_lookup_by_name(rmap_str);
b4897fa5 7061 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 7062 }
718e3744 7063
d62a17ae 7064 if (safi == SAFI_EVPN) {
7065 if (esi) {
7066 bgp_static->eth_s_id =
7067 XCALLOC(MTYPE_ATTR,
0a50c248 7068 sizeof(esi_t));
d62a17ae 7069 str2esi(esi, bgp_static->eth_s_id);
7070 }
7071 if (routermac) {
7072 bgp_static->router_mac =
28328ea9 7073 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
7074 (void)prefix_str2mac(routermac,
7075 bgp_static->router_mac);
d62a17ae 7076 }
7077 if (gwip)
7078 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7079 }
9bcb3eef 7080 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 7081
d62a17ae 7082 bgp_static->valid = 1;
7083 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7084 }
718e3744 7085
d62a17ae 7086 return CMD_SUCCESS;
718e3744 7087}
7088
7089/* Configure static BGP network. */
d62a17ae 7090int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7091 const char *ip_str, const char *rd_str,
7092 const char *label_str, int evpn_type, const char *esi,
7093 const char *gwip, const char *ethtag)
7094{
7095 VTY_DECLVAR_CONTEXT(bgp, bgp);
7096 int ret;
7097 struct prefix p;
7098 struct prefix_rd prd;
9bcb3eef
DS
7099 struct bgp_dest *pdest;
7100 struct bgp_dest *dest;
d62a17ae 7101 struct bgp_table *table;
7102 struct bgp_static *bgp_static;
7103 mpls_label_t label = MPLS_INVALID_LABEL;
7104
7105 /* Convert IP prefix string to struct prefix. */
7106 ret = str2prefix(ip_str, &p);
7107 if (!ret) {
7108 vty_out(vty, "%% Malformed prefix\n");
7109 return CMD_WARNING_CONFIG_FAILED;
7110 }
7111 apply_mask(&p);
7112 if ((afi == AFI_L2VPN)
7113 && (bgp_build_evpn_prefix(evpn_type,
7114 ethtag != NULL ? atol(ethtag) : 0, &p))) {
7115 vty_out(vty, "%% L2VPN prefix could not be forged\n");
7116 return CMD_WARNING_CONFIG_FAILED;
7117 }
7118 ret = str2prefix_rd(rd_str, &prd);
7119 if (!ret) {
7120 vty_out(vty, "%% Malformed rd\n");
7121 return CMD_WARNING_CONFIG_FAILED;
7122 }
718e3744 7123
d62a17ae 7124 if (label_str) {
7125 unsigned long label_val;
7126 label_val = strtoul(label_str, NULL, 10);
7127 encode_label(label_val, &label);
7128 }
718e3744 7129
9bcb3eef
DS
7130 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7131 if (!bgp_dest_has_bgp_path_info_data(pdest))
7132 bgp_dest_set_bgp_table_info(pdest,
67009e22 7133 bgp_table_init(bgp, afi, safi));
d62a17ae 7134 else
9bcb3eef
DS
7135 bgp_dest_unlock_node(pdest);
7136 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 7137
9bcb3eef 7138 dest = bgp_node_lookup(table, &p);
6b0655a2 7139
9bcb3eef 7140 if (dest) {
d62a17ae 7141 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 7142
9bcb3eef 7143 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 7144 bgp_static_free(bgp_static);
9bcb3eef
DS
7145 bgp_dest_set_bgp_static_info(dest, NULL);
7146 bgp_dest_unlock_node(dest);
7147 bgp_dest_unlock_node(dest);
d62a17ae 7148 } else
7149 vty_out(vty, "%% Can't find the route\n");
7150
7151 return CMD_SUCCESS;
7152}
7153
7154static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7155 const char *rmap_name)
7156{
7157 VTY_DECLVAR_CONTEXT(bgp, bgp);
7158 struct bgp_rmap *rmap;
7159
7160 rmap = &bgp->table_map[afi][safi];
7161 if (rmap_name) {
0a22ddfb 7162 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7163 route_map_counter_decrement(rmap->map);
d62a17ae 7164 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7165 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 7166 route_map_counter_increment(rmap->map);
d62a17ae 7167 } else {
0a22ddfb 7168 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7169 route_map_counter_decrement(rmap->map);
d62a17ae 7170 rmap->map = NULL;
7171 }
73ac8160 7172
d62a17ae 7173 if (bgp_fibupd_safi(safi))
7174 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7175
d62a17ae 7176 return CMD_SUCCESS;
73ac8160
DS
7177}
7178
d62a17ae 7179static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7180 const char *rmap_name)
73ac8160 7181{
d62a17ae 7182 VTY_DECLVAR_CONTEXT(bgp, bgp);
7183 struct bgp_rmap *rmap;
73ac8160 7184
d62a17ae 7185 rmap = &bgp->table_map[afi][safi];
0a22ddfb 7186 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 7187 route_map_counter_decrement(rmap->map);
d62a17ae 7188 rmap->map = NULL;
73ac8160 7189
d62a17ae 7190 if (bgp_fibupd_safi(safi))
7191 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 7192
d62a17ae 7193 return CMD_SUCCESS;
73ac8160
DS
7194}
7195
2b791107 7196void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 7197 safi_t safi)
73ac8160 7198{
d62a17ae 7199 if (bgp->table_map[afi][safi].name) {
d62a17ae 7200 vty_out(vty, " table-map %s\n",
7201 bgp->table_map[afi][safi].name);
7202 }
73ac8160
DS
7203}
7204
73ac8160
DS
7205DEFUN (bgp_table_map,
7206 bgp_table_map_cmd,
7207 "table-map WORD",
7208 "BGP table to RIB route download filter\n"
7209 "Name of the route map\n")
7210{
d62a17ae 7211 int idx_word = 1;
7212 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7213 argv[idx_word]->arg);
73ac8160
DS
7214}
7215DEFUN (no_bgp_table_map,
7216 no_bgp_table_map_cmd,
7217 "no table-map WORD",
3a2d747c 7218 NO_STR
73ac8160
DS
7219 "BGP table to RIB route download filter\n"
7220 "Name of the route map\n")
7221{
d62a17ae 7222 int idx_word = 2;
7223 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7224 argv[idx_word]->arg);
73ac8160
DS
7225}
7226
585f1adc
IR
7227DEFPY(bgp_network,
7228 bgp_network_cmd,
7229 "[no] network \
7230 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7231 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7232 backdoor$backdoor}]",
7233 NO_STR
7234 "Specify a network to announce via BGP\n"
7235 "IPv4 prefix\n"
7236 "Network number\n"
7237 "Network mask\n"
7238 "Network mask\n"
7239 "Route-map to modify the attributes\n"
7240 "Name of the route map\n"
7241 "Label index to associate with the prefix\n"
7242 "Label index value\n"
7243 "Specify a BGP backdoor route\n")
7244{
7245 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7246
7247 if (address_str) {
7248 int ret;
718e3744 7249
e2a86ad9 7250 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7251 addr_prefix_str,
7252 sizeof(addr_prefix_str));
e2a86ad9
DS
7253 if (!ret) {
7254 vty_out(vty, "%% Inconsistent address and mask\n");
7255 return CMD_WARNING_CONFIG_FAILED;
7256 }
d62a17ae 7257 }
718e3744 7258
585f1adc
IR
7259 return bgp_static_set(
7260 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7261 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7262 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7263}
7264
585f1adc
IR
7265DEFPY(ipv6_bgp_network,
7266 ipv6_bgp_network_cmd,
7267 "[no] network X:X::X:X/M$prefix \
70dd370f 7268 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7269 NO_STR
7270 "Specify a network to announce via BGP\n"
7271 "IPv6 prefix\n"
7272 "Route-map to modify the attributes\n"
7273 "Name of the route map\n"
7274 "Label index to associate with the prefix\n"
7275 "Label index value\n")
37a87b8f 7276{
585f1adc
IR
7277 return bgp_static_set(
7278 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7279 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7280}
7281
d62a17ae 7282static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7283{
d62a17ae 7284 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7285}
7286
d62a17ae 7287static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7288{
365ab2e7
RZ
7289 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7290 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7291 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7292 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7293 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7294}
718e3744 7295
365ab2e7
RZ
7296/**
7297 * Helper function to avoid repeated code: prepare variables for a
7298 * `route_map_apply` call.
7299 *
7300 * \returns `true` on route map match, otherwise `false`.
7301 */
7302static bool aggr_suppress_map_test(struct bgp *bgp,
7303 struct bgp_aggregate *aggregate,
7304 struct bgp_path_info *pi)
7305{
7306 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7307 route_map_result_t rmr = RMAP_DENYMATCH;
7308 struct bgp_path_info rmap_path = {};
7309 struct attr attr = {};
7310
7311 /* No route map entries created, just don't match. */
7312 if (aggregate->suppress_map == NULL)
7313 return false;
7314
7315 /* Call route map matching and return result. */
7316 attr.aspath = aspath_empty();
7317 rmap_path.peer = bgp->peer_self;
7318 rmap_path.attr = &attr;
7319
7320 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7321 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7322 bgp->peer_self->rmap_type = 0;
7323
7324 bgp_attr_flush(&attr);
afb254d7 7325 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7326
7327 return rmr == RMAP_PERMITMATCH;
7328}
7329
4056a5f6
RZ
7330/** Test whether the aggregation has suppressed this path or not. */
7331static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7332 struct bgp_path_info *pi)
7333{
7334 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7335 return false;
7336
7337 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7338}
7339
7340/**
7341 * Suppress this path and keep the reference.
7342 *
7343 * \returns `true` if needs processing otherwise `false`.
7344 */
7345static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7346 struct bgp_path_info *pi)
7347{
7348 struct bgp_path_info_extra *pie;
7349
7350 /* Path is already suppressed by this aggregation. */
7351 if (aggr_suppress_exists(aggregate, pi))
7352 return false;
7353
7354 pie = bgp_path_info_extra_get(pi);
7355
7356 /* This is the first suppression, allocate memory and list it. */
7357 if (pie->aggr_suppressors == NULL)
7358 pie->aggr_suppressors = list_new();
7359
7360 listnode_add(pie->aggr_suppressors, aggregate);
7361
7362 /* Only mark for processing if suppressed. */
7363 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7364 if (BGP_DEBUG(update, UPDATE_OUT))
7365 zlog_debug("aggregate-address suppressing: %pFX",
7366 bgp_dest_get_prefix(pi->net));
7367
4056a5f6
RZ
7368 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7369 return true;
7370 }
7371
7372 return false;
7373}
7374
7375/**
7376 * Unsuppress this path and remove the reference.
7377 *
7378 * \returns `true` if needs processing otherwise `false`.
7379 */
7380static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7381 struct bgp_path_info *pi)
7382{
7383 /* Path wasn't suppressed. */
7384 if (!aggr_suppress_exists(aggregate, pi))
7385 return false;
7386
7387 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7388
7389 /* Unsuppress and free extra memory if last item. */
7390 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7391 if (BGP_DEBUG(update, UPDATE_OUT))
7392 zlog_debug("aggregate-address unsuppressing: %pFX",
7393 bgp_dest_get_prefix(pi->net));
7394
4056a5f6
RZ
7395 list_delete(&pi->extra->aggr_suppressors);
7396 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7397 return true;
7398 }
7399
7400 return false;
7401}
7402
3dc339cd
DA
7403static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7404 struct aspath *aspath,
7405 struct community *comm,
7406 struct ecommunity *ecomm,
7407 struct lcommunity *lcomm)
eaaf8adb
DS
7408{
7409 static struct aspath *ae = NULL;
7410
7411 if (!ae)
7412 ae = aspath_empty();
7413
40381db7 7414 if (!pi)
3dc339cd 7415 return false;
eaaf8adb 7416
40381db7 7417 if (origin != pi->attr->origin)
3dc339cd 7418 return false;
eaaf8adb 7419
40381db7 7420 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7421 return false;
29f7d023 7422
9a706b42 7423 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7424 return false;
eaaf8adb 7425
b53e67a3 7426 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7427 return false;
eaaf8adb 7428
1bcf3a96 7429 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7430 return false;
dd18c5a9 7431
40381db7 7432 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7433 return false;
7ce8a8e0 7434
3dc339cd 7435 return true;
eaaf8adb
DS
7436}
7437
5f040085
DS
7438static void bgp_aggregate_install(
7439 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7440 uint8_t origin, struct aspath *aspath, struct community *community,
7441 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7442 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7443{
9bcb3eef 7444 struct bgp_dest *dest;
c701010e 7445 struct bgp_table *table;
6f94b685 7446 struct bgp_path_info *pi, *orig, *new;
20894f50 7447 struct attr *attr;
c701010e
DS
7448
7449 table = bgp->rib[afi][safi];
7450
9bcb3eef 7451 dest = bgp_node_get(table, p);
eaaf8adb 7452
9bcb3eef 7453 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7454 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7455 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7456 break;
7457
6aabb15d
RZ
7458 /*
7459 * If we have paths with different MEDs, then don't install
7460 * (or uninstall) the aggregate route.
7461 */
7462 if (aggregate->match_med && aggregate->med_mismatched)
7463 goto uninstall_aggregate_route;
7464
c701010e 7465 if (aggregate->count > 0) {
eaaf8adb
DS
7466 /*
7467 * If the aggregate information has not changed
7468 * no need to re-install it again.
7469 */
6f94b685 7470 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7471 ecommunity, lcommunity)) {
9bcb3eef 7472 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7473
7474 if (aspath)
7475 aspath_free(aspath);
7476 if (community)
3c1f53de 7477 community_free(&community);
3da2cc32
DS
7478 if (ecommunity)
7479 ecommunity_free(&ecommunity);
dd18c5a9
DS
7480 if (lcommunity)
7481 lcommunity_free(&lcommunity);
eaaf8adb
DS
7482
7483 return;
7484 }
7485
7486 /*
7487 * Mark the old as unusable
7488 */
40381db7 7489 if (pi)
9bcb3eef 7490 bgp_path_info_delete(dest, pi);
eaaf8adb 7491
20894f50
DA
7492 attr = bgp_attr_aggregate_intern(
7493 bgp, origin, aspath, community, ecommunity, lcommunity,
7494 aggregate, atomic_aggregate, p);
7495
7496 if (!attr) {
8c0044f3 7497 bgp_dest_unlock_node(dest);
20894f50 7498 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7499 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7500 zlog_debug("%s: %pFX null attribute", __func__,
7501 p);
20894f50
DA
7502 return;
7503 }
7504
3da2cc32 7505 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7506 bgp->peer_self, attr, dest);
20894f50 7507
1defdda8 7508 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7509
9bcb3eef
DS
7510 bgp_path_info_add(dest, new);
7511 bgp_process(bgp, dest, afi, safi);
c701010e 7512 } else {
6aabb15d 7513 uninstall_aggregate_route:
6f94b685 7514 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7515 if (pi->peer == bgp->peer_self
7516 && pi->type == ZEBRA_ROUTE_BGP
7517 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7518 break;
7519
7520 /* Withdraw static BGP route from routing table. */
40381db7 7521 if (pi) {
9bcb3eef
DS
7522 bgp_path_info_delete(dest, pi);
7523 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7524 }
7525 }
7526
9bcb3eef 7527 bgp_dest_unlock_node(dest);
c701010e
DS
7528}
7529
6aabb15d
RZ
7530/**
7531 * Check if the current path has different MED than other known paths.
7532 *
7533 * \returns `true` if the MED matched the others else `false`.
7534 */
7535static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7536 struct bgp *bgp, struct bgp_path_info *pi)
7537{
7538 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7539
7540 /* This is the first route being analyzed. */
7541 if (!aggregate->med_initialized) {
7542 aggregate->med_initialized = true;
7543 aggregate->med_mismatched = false;
7544 aggregate->med_matched_value = cur_med;
7545 } else {
7546 /* Check if routes with different MED showed up. */
7547 if (cur_med != aggregate->med_matched_value)
7548 aggregate->med_mismatched = true;
7549 }
7550
7551 return !aggregate->med_mismatched;
7552}
7553
7554/**
7555 * Initializes and tests all routes in the aggregate address path for MED
7556 * values.
7557 *
7558 * \returns `true` if all MEDs are the same otherwise `false`.
7559 */
7560static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7561 struct bgp *bgp, const struct prefix *p,
7562 afi_t afi, safi_t safi)
7563{
7564 struct bgp_table *table = bgp->rib[afi][safi];
7565 const struct prefix *dest_p;
7566 struct bgp_dest *dest, *top;
7567 struct bgp_path_info *pi;
7568 bool med_matched = true;
7569
7570 aggregate->med_initialized = false;
7571
7572 top = bgp_node_get(table, p);
7573 for (dest = bgp_node_get(table, p); dest;
7574 dest = bgp_route_next_until(dest, top)) {
7575 dest_p = bgp_dest_get_prefix(dest);
7576 if (dest_p->prefixlen <= p->prefixlen)
7577 continue;
7578
7579 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7580 if (BGP_PATH_HOLDDOWN(pi))
7581 continue;
7582 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7583 continue;
7584 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7585 med_matched = false;
7586 break;
7587 }
7588 }
7589 if (!med_matched)
7590 break;
7591 }
7592 bgp_dest_unlock_node(top);
7593
7594 return med_matched;
7595}
7596
7597/**
7598 * Toggles the route suppression status for this aggregate address
7599 * configuration.
7600 */
4056a5f6
RZ
7601void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7602 struct bgp *bgp, const struct prefix *p,
7603 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7604{
7605 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7606 const struct prefix *dest_p;
7607 struct bgp_dest *dest, *top;
7608 struct bgp_path_info *pi;
7609 bool toggle_suppression;
7610
7611 /* We've found a different MED we must revert any suppressed routes. */
7612 top = bgp_node_get(table, p);
7613 for (dest = bgp_node_get(table, p); dest;
7614 dest = bgp_route_next_until(dest, top)) {
7615 dest_p = bgp_dest_get_prefix(dest);
7616 if (dest_p->prefixlen <= p->prefixlen)
7617 continue;
7618
7619 toggle_suppression = false;
7620 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7621 if (BGP_PATH_HOLDDOWN(pi))
7622 continue;
7623 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7624 continue;
7625
6aabb15d
RZ
7626 /* We are toggling suppression back. */
7627 if (suppress) {
6aabb15d 7628 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7629 if (aggr_suppress_path(aggregate, pi))
7630 toggle_suppression = true;
6aabb15d
RZ
7631 continue;
7632 }
7633
6aabb15d 7634 /* Install route if there is no more suppression. */
4056a5f6 7635 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7636 toggle_suppression = true;
6aabb15d
RZ
7637 }
7638
7639 if (toggle_suppression)
7640 bgp_process(bgp, dest, afi, safi);
7641 }
7642 bgp_dest_unlock_node(top);
7643}
7644
7645/**
7646 * Aggregate address MED matching incremental test: this function is called
7647 * when the initial aggregation occurred and we are only testing a single
7648 * new path.
7649 *
7650 * In addition to testing and setting the MED validity it also installs back
7651 * suppressed routes (if summary is configured).
7652 *
7653 * Must not be called in `bgp_aggregate_route`.
7654 */
7655static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7656 struct bgp *bgp, const struct prefix *p,
7657 afi_t afi, safi_t safi,
f66624f5 7658 struct bgp_path_info *pi)
6aabb15d
RZ
7659{
7660 /* MED matching disabled. */
7661 if (!aggregate->match_med)
7662 return;
7663
f66624f5
DA
7664 /* Aggregation with different MED, recheck if we have got equal MEDs
7665 * now.
6aabb15d 7666 */
f66624f5
DA
7667 if (aggregate->med_mismatched &&
7668 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7669 aggregate->summary_only)
7670 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7671 true);
7672 else
6aabb15d
RZ
7673 bgp_aggregate_med_match(aggregate, bgp, pi);
7674
7675 /* No mismatches, just quit. */
7676 if (!aggregate->med_mismatched)
7677 return;
7678
7679 /* Route summarization is disabled. */
7680 if (!aggregate->summary_only)
7681 return;
7682
7683 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7684}
7685
b5d58c32 7686/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7687void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7688 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7689{
7690 struct bgp_table *table;
9bcb3eef
DS
7691 struct bgp_dest *top;
7692 struct bgp_dest *dest;
d7c0a89a 7693 uint8_t origin;
d62a17ae 7694 struct aspath *aspath = NULL;
d62a17ae 7695 struct community *community = NULL;
3da2cc32 7696 struct ecommunity *ecommunity = NULL;
dd18c5a9 7697 struct lcommunity *lcommunity = NULL;
40381db7 7698 struct bgp_path_info *pi;
d62a17ae 7699 unsigned long match = 0;
d7c0a89a 7700 uint8_t atomic_aggregate = 0;
d62a17ae 7701
9f822fa2
S
7702 /* If the bgp instance is being deleted or self peer is deleted
7703 * then do not create aggregate route
7704 */
892fedb6
DA
7705 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7706 || (bgp->peer_self == NULL))
9f822fa2
S
7707 return;
7708
6aabb15d
RZ
7709 /* Initialize and test routes for MED difference. */
7710 if (aggregate->match_med)
7711 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7712
4056a5f6
RZ
7713 /*
7714 * Reset aggregate count: we might've been called from route map
7715 * update so in that case we must retest all more specific routes.
7716 *
7717 * \see `bgp_route_map_process_update`.
7718 */
7719 aggregate->count = 0;
7720 aggregate->incomplete_origin_count = 0;
7721 aggregate->incomplete_origin_count = 0;
7722 aggregate->egp_origin_count = 0;
7723
d62a17ae 7724 /* ORIGIN attribute: If at least one route among routes that are
7725 aggregated has ORIGIN with the value INCOMPLETE, then the
7726 aggregated route must have the ORIGIN attribute with the value
7727 INCOMPLETE. Otherwise, if at least one route among routes that
7728 are aggregated has ORIGIN with the value EGP, then the aggregated
7729 route must have the origin attribute with the value EGP. In all
7730 other case the value of the ORIGIN attribute of the aggregated
7731 route is INTERNAL. */
7732 origin = BGP_ORIGIN_IGP;
718e3744 7733
d62a17ae 7734 table = bgp->rib[afi][safi];
718e3744 7735
d62a17ae 7736 top = bgp_node_get(table, p);
9bcb3eef
DS
7737 for (dest = bgp_node_get(table, p); dest;
7738 dest = bgp_route_next_until(dest, top)) {
7739 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7740
9bcb3eef 7741 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7742 continue;
d62a17ae 7743
a77e2f4b
S
7744 /* If suppress fib is enabled and route not installed
7745 * in FIB, skip the route
7746 */
7747 if (!bgp_check_advertise(bgp, dest))
7748 continue;
7749
c2ff8b3e 7750 match = 0;
d62a17ae 7751
9bcb3eef 7752 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7753 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7754 continue;
718e3744 7755
40381db7 7756 if (pi->attr->flag
c2ff8b3e
DS
7757 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7758 atomic_aggregate = 1;
d62a17ae 7759
40381db7 7760 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7761 continue;
d62a17ae 7762
f273fef1
DS
7763 /*
7764 * summary-only aggregate route suppress
7765 * aggregated route announcements.
6aabb15d
RZ
7766 *
7767 * MED matching:
7768 * Don't create summaries if MED didn't match
7769 * otherwise neither the specific routes and the
7770 * aggregation will be announced.
f273fef1 7771 */
6aabb15d
RZ
7772 if (aggregate->summary_only
7773 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7774 if (aggr_suppress_path(aggregate, pi))
7775 match++;
d62a17ae 7776 }
c2ff8b3e 7777
365ab2e7
RZ
7778 /*
7779 * Suppress more specific routes that match the route
7780 * map results.
7781 *
7782 * MED matching:
7783 * Don't suppress routes if MED matching is enabled and
7784 * it mismatched otherwise we might end up with no
7785 * routes for this path.
7786 */
7787 if (aggregate->suppress_map_name
7788 && AGGREGATE_MED_VALID(aggregate)
7789 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7790 if (aggr_suppress_path(aggregate, pi))
7791 match++;
d62a17ae 7792 }
c2ff8b3e
DS
7793
7794 aggregate->count++;
7795
f273fef1
DS
7796 /*
7797 * If at least one route among routes that are
7798 * aggregated has ORIGIN with the value INCOMPLETE,
7799 * then the aggregated route MUST have the ORIGIN
7800 * attribute with the value INCOMPLETE. Otherwise, if
7801 * at least one route among routes that are aggregated
7802 * has ORIGIN with the value EGP, then the aggregated
7803 * route MUST have the ORIGIN attribute with the value
7804 * EGP.
7805 */
fc968841
NT
7806 switch (pi->attr->origin) {
7807 case BGP_ORIGIN_INCOMPLETE:
7808 aggregate->incomplete_origin_count++;
7809 break;
7810 case BGP_ORIGIN_EGP:
7811 aggregate->egp_origin_count++;
7812 break;
7813 default:
7814 /*Do nothing.
7815 */
7816 break;
7817 }
c2ff8b3e
DS
7818
7819 if (!aggregate->as_set)
7820 continue;
7821
f273fef1
DS
7822 /*
7823 * as-set aggregate route generate origin, as path,
7824 * and community aggregation.
7825 */
fc968841
NT
7826 /* Compute aggregate route's as-path.
7827 */
ef51a7d8 7828 bgp_compute_aggregate_aspath_hash(aggregate,
7829 pi->attr->aspath);
c2ff8b3e 7830
fc968841
NT
7831 /* Compute aggregate route's community.
7832 */
9a706b42 7833 if (bgp_attr_get_community(pi->attr))
21fec674 7834 bgp_compute_aggregate_community_hash(
9a706b42
DA
7835 aggregate,
7836 bgp_attr_get_community(pi->attr));
dd18c5a9 7837
fc968841
NT
7838 /* Compute aggregate route's extended community.
7839 */
b53e67a3 7840 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7841 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7842 aggregate,
7843 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7844
7845 /* Compute aggregate route's large community.
7846 */
1bcf3a96 7847 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7848 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7849 aggregate,
7850 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7851 }
c2ff8b3e 7852 if (match)
9bcb3eef 7853 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7854 }
21fec674 7855 if (aggregate->as_set) {
ef51a7d8 7856 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7857 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7858 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7859 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7860 }
7861
f1eb1f05 7862
9bcb3eef 7863 bgp_dest_unlock_node(top);
718e3744 7864
718e3744 7865
fc968841
NT
7866 if (aggregate->incomplete_origin_count > 0)
7867 origin = BGP_ORIGIN_INCOMPLETE;
7868 else if (aggregate->egp_origin_count > 0)
7869 origin = BGP_ORIGIN_EGP;
d62a17ae 7870
229757f1
DA
7871 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7872 origin = aggregate->origin;
7873
fc968841
NT
7874 if (aggregate->as_set) {
7875 if (aggregate->aspath)
7876 /* Retrieve aggregate route's as-path.
7877 */
7878 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7879
fc968841
NT
7880 if (aggregate->community)
7881 /* Retrieve aggregate route's community.
7882 */
7883 community = community_dup(aggregate->community);
3da2cc32 7884
fc968841
NT
7885 if (aggregate->ecommunity)
7886 /* Retrieve aggregate route's ecommunity.
7887 */
7888 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7889
fc968841
NT
7890 if (aggregate->lcommunity)
7891 /* Retrieve aggregate route's lcommunity.
7892 */
7893 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7894 }
718e3744 7895
c701010e 7896 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7897 ecommunity, lcommunity, atomic_aggregate,
7898 aggregate);
718e3744 7899}
7900
5f040085
DS
7901void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7902 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7903{
7904 struct bgp_table *table;
9bcb3eef
DS
7905 struct bgp_dest *top;
7906 struct bgp_dest *dest;
40381db7 7907 struct bgp_path_info *pi;
3b7db173
DS
7908 unsigned long match;
7909
7910 table = bgp->rib[afi][safi];
7911
7912 /* If routes exists below this node, generate aggregate routes. */
7913 top = bgp_node_get(table, p);
9bcb3eef
DS
7914 for (dest = bgp_node_get(table, p); dest;
7915 dest = bgp_route_next_until(dest, top)) {
7916 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7917
9bcb3eef 7918 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7919 continue;
7920 match = 0;
7921
9bcb3eef 7922 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7923 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7924 continue;
7925
40381db7 7926 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7927 continue;
7928
92b175bd
RZ
7929 /*
7930 * This route is suppressed: attempt to unsuppress it.
7931 *
7932 * `aggr_unsuppress_path` will fail if this particular
7933 * aggregate route was not the suppressor.
7934 */
7935 if (pi->extra && pi->extra->aggr_suppressors &&
7936 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7937 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7938 match++;
3b7db173 7939 }
365ab2e7 7940
3b7db173 7941 aggregate->count--;
fc968841
NT
7942
7943 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7944 aggregate->incomplete_origin_count--;
7945 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7946 aggregate->egp_origin_count--;
7947
7948 if (aggregate->as_set) {
7949 /* Remove as-path from aggregate.
7950 */
ef51a7d8 7951 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7952 aggregate,
7953 pi->attr->aspath);
7954
9a706b42 7955 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7956 /* Remove community from aggregate.
7957 */
21fec674 7958 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7959 aggregate,
7960 bgp_attr_get_community(
7961 pi->attr));
fc968841 7962
b53e67a3 7963 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7964 /* Remove ecommunity from aggregate.
7965 */
4edd83f9 7966 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7967 aggregate,
7968 bgp_attr_get_ecommunity(
7969 pi->attr));
fc968841 7970
1bcf3a96 7971 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7972 /* Remove lcommunity from aggregate.
7973 */
f1eb1f05 7974 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7975 aggregate,
7976 bgp_attr_get_lcommunity(
7977 pi->attr));
fc968841 7978 }
3b7db173
DS
7979 }
7980
7981 /* If this node was suppressed, process the change. */
7982 if (match)
9bcb3eef 7983 bgp_process(bgp, dest, afi, safi);
3b7db173 7984 }
f1eb1f05 7985 if (aggregate->as_set) {
ef51a7d8 7986 aspath_free(aggregate->aspath);
7987 aggregate->aspath = NULL;
21fec674 7988 if (aggregate->community)
7989 community_free(&aggregate->community);
4edd83f9 7990 if (aggregate->ecommunity)
7991 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7992 if (aggregate->lcommunity)
7993 lcommunity_free(&aggregate->lcommunity);
7994 }
7995
9bcb3eef 7996 bgp_dest_unlock_node(top);
3b7db173 7997}
718e3744 7998
5f040085
DS
7999static void bgp_add_route_to_aggregate(struct bgp *bgp,
8000 const struct prefix *aggr_p,
fc968841
NT
8001 struct bgp_path_info *pinew, afi_t afi,
8002 safi_t safi,
8003 struct bgp_aggregate *aggregate)
8004{
8005 uint8_t origin;
8006 struct aspath *aspath = NULL;
8007 uint8_t atomic_aggregate = 0;
8008 struct community *community = NULL;
8009 struct ecommunity *ecommunity = NULL;
8010 struct lcommunity *lcommunity = NULL;
8011
a4559740 8012 /* If the bgp instance is being deleted or self peer is deleted
8013 * then do not create aggregate route
8014 */
8015 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8016 || (bgp->peer_self == NULL))
8017 return;
8018
fc968841
NT
8019 /* ORIGIN attribute: If at least one route among routes that are
8020 * aggregated has ORIGIN with the value INCOMPLETE, then the
8021 * aggregated route must have the ORIGIN attribute with the value
8022 * INCOMPLETE. Otherwise, if at least one route among routes that
8023 * are aggregated has ORIGIN with the value EGP, then the aggregated
8024 * route must have the origin attribute with the value EGP. In all
8025 * other case the value of the ORIGIN attribute of the aggregated
8026 * route is INTERNAL.
8027 */
8028 origin = BGP_ORIGIN_IGP;
8029
8030 aggregate->count++;
8031
6aabb15d
RZ
8032 /*
8033 * This must be called before `summary` check to avoid
8034 * "suppressing" twice.
8035 */
8036 if (aggregate->match_med)
8037 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 8038 pinew);
6aabb15d
RZ
8039
8040 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 8041 aggr_suppress_path(aggregate, pinew);
fc968841 8042
365ab2e7
RZ
8043 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8044 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 8045 aggr_suppress_path(aggregate, pinew);
fc968841
NT
8046
8047 switch (pinew->attr->origin) {
8048 case BGP_ORIGIN_INCOMPLETE:
8049 aggregate->incomplete_origin_count++;
8050 break;
8051 case BGP_ORIGIN_EGP:
8052 aggregate->egp_origin_count++;
8053 break;
8054 default:
8055 /* Do nothing.
8056 */
8057 break;
8058 }
8059
8060 if (aggregate->incomplete_origin_count > 0)
8061 origin = BGP_ORIGIN_INCOMPLETE;
8062 else if (aggregate->egp_origin_count > 0)
8063 origin = BGP_ORIGIN_EGP;
8064
229757f1
DA
8065 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8066 origin = aggregate->origin;
8067
fc968841
NT
8068 if (aggregate->as_set) {
8069 /* Compute aggregate route's as-path.
8070 */
8071 bgp_compute_aggregate_aspath(aggregate,
8072 pinew->attr->aspath);
8073
8074 /* Compute aggregate route's community.
8075 */
9a706b42 8076 if (bgp_attr_get_community(pinew->attr))
fc968841 8077 bgp_compute_aggregate_community(
9a706b42 8078 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
8079
8080 /* Compute aggregate route's extended community.
8081 */
b53e67a3 8082 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 8083 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
8084 aggregate,
8085 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
8086
8087 /* Compute aggregate route's large community.
8088 */
1bcf3a96 8089 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 8090 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
8091 aggregate,
8092 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
8093
8094 /* Retrieve aggregate route's as-path.
8095 */
8096 if (aggregate->aspath)
8097 aspath = aspath_dup(aggregate->aspath);
8098
8099 /* Retrieve aggregate route's community.
8100 */
8101 if (aggregate->community)
8102 community = community_dup(aggregate->community);
8103
8104 /* Retrieve aggregate route's ecommunity.
8105 */
8106 if (aggregate->ecommunity)
8107 ecommunity = ecommunity_dup(aggregate->ecommunity);
8108
8109 /* Retrieve aggregate route's lcommunity.
8110 */
8111 if (aggregate->lcommunity)
8112 lcommunity = lcommunity_dup(aggregate->lcommunity);
8113 }
8114
8115 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8116 aspath, community, ecommunity,
8117 lcommunity, atomic_aggregate, aggregate);
8118}
8119
8120static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8121 safi_t safi,
8122 struct bgp_path_info *pi,
8123 struct bgp_aggregate *aggregate,
5f040085 8124 const struct prefix *aggr_p)
fc968841
NT
8125{
8126 uint8_t origin;
8127 struct aspath *aspath = NULL;
8128 uint8_t atomic_aggregate = 0;
8129 struct community *community = NULL;
8130 struct ecommunity *ecommunity = NULL;
8131 struct lcommunity *lcommunity = NULL;
8132 unsigned long match = 0;
8133
a4559740 8134 /* If the bgp instance is being deleted or self peer is deleted
8135 * then do not create aggregate route
8136 */
8137 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8138 || (bgp->peer_self == NULL))
8139 return;
8140
fc968841
NT
8141 if (BGP_PATH_HOLDDOWN(pi))
8142 return;
8143
8144 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8145 return;
8146
4056a5f6
RZ
8147 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8148 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8149 match++;
fc968841 8150
365ab2e7 8151 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
8152 && aggr_suppress_map_test(bgp, aggregate, pi))
8153 if (aggr_unsuppress_path(aggregate, pi))
fc968841 8154 match++;
fc968841 8155
6aabb15d 8156 /*
365ab2e7 8157 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
8158 * "unsuppressing" twice.
8159 */
8160 if (aggregate->match_med)
f66624f5 8161 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 8162
fc968841
NT
8163 if (aggregate->count > 0)
8164 aggregate->count--;
8165
8166 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8167 aggregate->incomplete_origin_count--;
8168 else if (pi->attr->origin == BGP_ORIGIN_EGP)
8169 aggregate->egp_origin_count--;
8170
8171 if (aggregate->as_set) {
8172 /* Remove as-path from aggregate.
8173 */
8174 bgp_remove_aspath_from_aggregate(aggregate,
8175 pi->attr->aspath);
8176
9a706b42 8177 if (bgp_attr_get_community(pi->attr))
fc968841
NT
8178 /* Remove community from aggregate.
8179 */
8180 bgp_remove_community_from_aggregate(
9a706b42 8181 aggregate, bgp_attr_get_community(pi->attr));
fc968841 8182
b53e67a3 8183 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
8184 /* Remove ecommunity from aggregate.
8185 */
8186 bgp_remove_ecommunity_from_aggregate(
b53e67a3 8187 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 8188
1bcf3a96 8189 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
8190 /* Remove lcommunity from aggregate.
8191 */
8192 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 8193 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
8194 }
8195
8196 /* If this node was suppressed, process the change. */
8197 if (match)
8198 bgp_process(bgp, pi->net, afi, safi);
8199
8200 origin = BGP_ORIGIN_IGP;
8201 if (aggregate->incomplete_origin_count > 0)
8202 origin = BGP_ORIGIN_INCOMPLETE;
8203 else if (aggregate->egp_origin_count > 0)
8204 origin = BGP_ORIGIN_EGP;
8205
229757f1
DA
8206 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8207 origin = aggregate->origin;
8208
fc968841
NT
8209 if (aggregate->as_set) {
8210 /* Retrieve aggregate route's as-path.
8211 */
8212 if (aggregate->aspath)
8213 aspath = aspath_dup(aggregate->aspath);
8214
8215 /* Retrieve aggregate route's community.
8216 */
8217 if (aggregate->community)
8218 community = community_dup(aggregate->community);
8219
8220 /* Retrieve aggregate route's ecommunity.
8221 */
8222 if (aggregate->ecommunity)
8223 ecommunity = ecommunity_dup(aggregate->ecommunity);
8224
8225 /* Retrieve aggregate route's lcommunity.
8226 */
8227 if (aggregate->lcommunity)
8228 lcommunity = lcommunity_dup(aggregate->lcommunity);
8229 }
8230
8231 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8232 aspath, community, ecommunity,
8233 lcommunity, atomic_aggregate, aggregate);
8234}
8235
5a1ae2c2 8236void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8237 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8238{
9bcb3eef
DS
8239 struct bgp_dest *child;
8240 struct bgp_dest *dest;
d62a17ae 8241 struct bgp_aggregate *aggregate;
8242 struct bgp_table *table;
718e3744 8243
d62a17ae 8244 table = bgp->aggregate[afi][safi];
f018db83 8245
d62a17ae 8246 /* No aggregates configured. */
8247 if (bgp_table_top_nolock(table) == NULL)
8248 return;
f018db83 8249
d62a17ae 8250 if (p->prefixlen == 0)
8251 return;
718e3744 8252
40381db7 8253 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8254 return;
718e3744 8255
a77e2f4b
S
8256 /* If suppress fib is enabled and route not installed
8257 * in FIB, do not update the aggregate route
8258 */
8259 if (!bgp_check_advertise(bgp, pi->net))
8260 return;
8261
d62a17ae 8262 child = bgp_node_get(table, p);
718e3744 8263
d62a17ae 8264 /* Aggregate address configuration check. */
9bcb3eef
DS
8265 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8266 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8267
9bcb3eef
DS
8268 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8269 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8270 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8271 aggregate);
d62a17ae 8272 }
b1e62edd 8273 }
9bcb3eef 8274 bgp_dest_unlock_node(child);
718e3744 8275}
8276
5a1ae2c2 8277void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8278 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8279{
9bcb3eef
DS
8280 struct bgp_dest *child;
8281 struct bgp_dest *dest;
d62a17ae 8282 struct bgp_aggregate *aggregate;
8283 struct bgp_table *table;
718e3744 8284
d62a17ae 8285 table = bgp->aggregate[afi][safi];
718e3744 8286
d62a17ae 8287 /* No aggregates configured. */
8288 if (bgp_table_top_nolock(table) == NULL)
8289 return;
718e3744 8290
d62a17ae 8291 if (p->prefixlen == 0)
8292 return;
718e3744 8293
d62a17ae 8294 child = bgp_node_get(table, p);
718e3744 8295
d62a17ae 8296 /* Aggregate address configuration check. */
9bcb3eef
DS
8297 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8298 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8299
9bcb3eef
DS
8300 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8301 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8302 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8303 aggregate, dest_p);
d62a17ae 8304 }
b1e62edd 8305 }
9bcb3eef 8306 bgp_dest_unlock_node(child);
d62a17ae 8307}
718e3744 8308
718e3744 8309/* Aggregate route attribute. */
8310#define AGGREGATE_SUMMARY_ONLY 1
8311#define AGGREGATE_AS_SET 1
fb29348a 8312#define AGGREGATE_AS_UNSET 0
718e3744 8313
229757f1
DA
8314static const char *bgp_origin2str(uint8_t origin)
8315{
8316 switch (origin) {
8317 case BGP_ORIGIN_IGP:
8318 return "igp";
8319 case BGP_ORIGIN_EGP:
8320 return "egp";
8321 case BGP_ORIGIN_INCOMPLETE:
8322 return "incomplete";
8323 }
8324 return "n/a";
8325}
8326
fdeb5a81 8327static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8328{
8329 switch (v_state) {
fdeb5a81
DS
8330 case RPKI_NOT_BEING_USED:
8331 return "not used";
8332 case RPKI_VALID:
b5b99af8 8333 return "valid";
fdeb5a81 8334 case RPKI_NOTFOUND:
b5b99af8 8335 return "not found";
fdeb5a81 8336 case RPKI_INVALID:
b5b99af8 8337 return "invalid";
b5b99af8 8338 }
fdeb5a81
DS
8339
8340 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8341 return "ERROR";
8342}
8343
585f1adc
IR
8344static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8345 afi_t afi, safi_t safi)
718e3744 8346{
585f1adc
IR
8347 VTY_DECLVAR_CONTEXT(bgp, bgp);
8348 int ret;
8349 struct prefix p;
9bcb3eef 8350 struct bgp_dest *dest;
d62a17ae 8351 struct bgp_aggregate *aggregate;
718e3744 8352
585f1adc
IR
8353 /* Convert string to prefix structure. */
8354 ret = str2prefix(prefix_str, &p);
8355 if (!ret) {
8356 vty_out(vty, "Malformed prefix\n");
8357 return CMD_WARNING_CONFIG_FAILED;
8358 }
8359 apply_mask(&p);
a4559740 8360
d62a17ae 8361 /* Old configuration check. */
585f1adc 8362 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8363 if (!dest) {
585f1adc
IR
8364 vty_out(vty,
8365 "%% There is no aggregate-address configuration.\n");
8366 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8367 }
f6269b4f 8368
9bcb3eef 8369 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8370 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8371 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8372 NULL, NULL, 0, aggregate);
d62a17ae 8373
8374 /* Unlock aggregate address configuration. */
9bcb3eef 8375 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8376
8377 if (aggregate->community)
8378 community_free(&aggregate->community);
8379
8380 if (aggregate->community_hash) {
8381 /* Delete all communities in the hash.
8382 */
8383 hash_clean(aggregate->community_hash,
8384 bgp_aggr_community_remove);
8385 /* Free up the community_hash.
8386 */
8387 hash_free(aggregate->community_hash);
8388 }
8389
8390 if (aggregate->ecommunity)
8391 ecommunity_free(&aggregate->ecommunity);
8392
8393 if (aggregate->ecommunity_hash) {
8394 /* Delete all ecommunities in the hash.
8395 */
8396 hash_clean(aggregate->ecommunity_hash,
8397 bgp_aggr_ecommunity_remove);
8398 /* Free up the ecommunity_hash.
8399 */
8400 hash_free(aggregate->ecommunity_hash);
8401 }
8402
8403 if (aggregate->lcommunity)
8404 lcommunity_free(&aggregate->lcommunity);
8405
8406 if (aggregate->lcommunity_hash) {
8407 /* Delete all lcommunities in the hash.
8408 */
8409 hash_clean(aggregate->lcommunity_hash,
8410 bgp_aggr_lcommunity_remove);
8411 /* Free up the lcommunity_hash.
8412 */
8413 hash_free(aggregate->lcommunity_hash);
8414 }
8415
8416 if (aggregate->aspath)
8417 aspath_free(aggregate->aspath);
8418
8419 if (aggregate->aspath_hash) {
8420 /* Delete all as-paths in the hash.
8421 */
8422 hash_clean(aggregate->aspath_hash,
8423 bgp_aggr_aspath_remove);
8424 /* Free up the aspath_hash.
8425 */
8426 hash_free(aggregate->aspath_hash);
8427 }
8428
d62a17ae 8429 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8430 bgp_dest_unlock_node(dest);
8431 bgp_dest_unlock_node(dest);
d62a17ae 8432
585f1adc 8433 return CMD_SUCCESS;
d62a17ae 8434}
8435
585f1adc
IR
8436static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8437 safi_t safi, const char *rmap,
8438 uint8_t summary_only, uint8_t as_set,
8439 uint8_t origin, bool match_med,
8440 const char *suppress_map)
d62a17ae 8441{
585f1adc 8442 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8443 int ret;
585f1adc 8444 struct prefix p;
9bcb3eef 8445 struct bgp_dest *dest;
d62a17ae 8446 struct bgp_aggregate *aggregate;
fb29348a 8447 uint8_t as_set_new = as_set;
d62a17ae 8448
365ab2e7 8449 if (suppress_map && summary_only) {
585f1adc 8450 vty_out(vty,
365ab2e7 8451 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8452 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8453 }
8454
585f1adc
IR
8455 /* Convert string to prefix structure. */
8456 ret = str2prefix(prefix_str, &p);
8457 if (!ret) {
8458 vty_out(vty, "Malformed prefix\n");
8459 return CMD_WARNING_CONFIG_FAILED;
8460 }
8461 apply_mask(&p);
d62a17ae 8462
585f1adc
IR
8463 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8464 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8465 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8466 prefix_str);
8467 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8468 }
8469
d62a17ae 8470 /* Old configuration check. */
585f1adc 8471 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8472 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8473
20894f50 8474 if (aggregate) {
585f1adc 8475 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8476 /* try to remove the old entry */
585f1adc 8477 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8478 if (ret) {
585f1adc 8479 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8480 bgp_dest_unlock_node(dest);
585f1adc 8481 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8482 }
8483 }
718e3744 8484
d62a17ae 8485 /* Make aggregate address structure. */
8486 aggregate = bgp_aggregate_new();
8487 aggregate->summary_only = summary_only;
6aabb15d 8488 aggregate->match_med = match_med;
fb29348a
DA
8489
8490 /* Network operators MUST NOT locally generate any new
8491 * announcements containing AS_SET or AS_CONFED_SET. If they have
8492 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8493 * SHOULD withdraw those routes and re-announce routes for the
8494 * aggregate or component prefixes (i.e., the more-specific routes
8495 * subsumed by the previously aggregated route) without AS_SET
8496 * or AS_CONFED_SET in the updates.
8497 */
7f972cd8 8498 if (bgp->reject_as_sets) {
fb29348a
DA
8499 if (as_set == AGGREGATE_AS_SET) {
8500 as_set_new = AGGREGATE_AS_UNSET;
8501 zlog_warn(
63efca0e 8502 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8503 __func__);
585f1adc 8504 vty_out(vty,
fb29348a
DA
8505 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8506 }
8507 }
8508
8509 aggregate->as_set = as_set_new;
d62a17ae 8510 aggregate->safi = safi;
229757f1
DA
8511 /* Override ORIGIN attribute if defined.
8512 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8513 * to IGP which is not what rfc4271 says.
8514 * This enables the same behavior, optionally.
8515 */
8516 aggregate->origin = origin;
20894f50
DA
8517
8518 if (rmap) {
8519 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8520 route_map_counter_decrement(aggregate->rmap.map);
8521 aggregate->rmap.name =
8522 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8523 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8524 route_map_counter_increment(aggregate->rmap.map);
8525 }
365ab2e7
RZ
8526
8527 if (suppress_map) {
8528 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8529 route_map_counter_decrement(aggregate->suppress_map);
8530
8531 aggregate->suppress_map_name =
8532 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8533 aggregate->suppress_map =
8534 route_map_lookup_by_name(aggregate->suppress_map_name);
8535 route_map_counter_increment(aggregate->suppress_map);
8536 }
8537
9bcb3eef 8538 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8539
d62a17ae 8540 /* Aggregate address insert into BGP routing table. */
585f1adc 8541 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8542
585f1adc 8543 return CMD_SUCCESS;
718e3744 8544}
8545
585f1adc
IR
8546DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8547 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8548 "as-set$as_set_s"
8549 "|summary-only$summary_only"
cacba915 8550 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8551 "|origin <egp|igp|incomplete>$origin_s"
8552 "|matching-MED-only$match_med"
cacba915 8553 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8554 "}]",
8555 NO_STR
8556 "Configure BGP aggregate entries\n"
764402fe
DA
8557 "Aggregate prefix\n"
8558 "Aggregate address\n"
8559 "Aggregate mask\n"
585f1adc
IR
8560 "Generate AS set path information\n"
8561 "Filter more specific routes from updates\n"
8562 "Apply route map to aggregate network\n"
8563 "Route map name\n"
8564 "BGP origin code\n"
8565 "Remote EGP\n"
8566 "Local IGP\n"
8567 "Unknown heritage\n"
8568 "Only aggregate routes with matching MED\n"
8569 "Suppress the selected more specific routes\n"
8570 "Route map with the route selectors\n")
8571{
8572 const char *prefix_s = NULL;
554b3b10 8573 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8574 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8575 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8576 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8577
554b3b10 8578 if (addr_str) {
7533cad7
QY
8579 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8580 sizeof(prefix_buf))
554b3b10
RZ
8581 == 0) {
8582 vty_out(vty, "%% Inconsistent address and mask\n");
8583 return CMD_WARNING_CONFIG_FAILED;
8584 }
585f1adc
IR
8585 prefix_s = prefix_buf;
8586 } else
8587 prefix_s = prefix_str;
37a87b8f 8588
585f1adc
IR
8589 if (origin_s) {
8590 if (strcmp(origin_s, "egp") == 0)
8591 origin = BGP_ORIGIN_EGP;
8592 else if (strcmp(origin_s, "igp") == 0)
8593 origin = BGP_ORIGIN_IGP;
8594 else if (strcmp(origin_s, "incomplete") == 0)
8595 origin = BGP_ORIGIN_INCOMPLETE;
8596 }
90e21f35 8597
585f1adc
IR
8598 if (as_set_s)
8599 as_set = AGGREGATE_AS_SET;
554b3b10 8600
585f1adc 8601 /* Handle configuration removal, otherwise installation. */
554b3b10 8602 if (no)
585f1adc
IR
8603 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8604
8605 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8606 summary_only != NULL, as_set, origin,
8607 match_med != NULL, suppress_map);
8608}
8609
8610DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8611 "[no] aggregate-address X:X::X:X/M$prefix [{"
8612 "as-set$as_set_s"
8613 "|summary-only$summary_only"
cacba915 8614 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8615 "|origin <egp|igp|incomplete>$origin_s"
8616 "|matching-MED-only$match_med"
cacba915 8617 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8618 "}]",
8619 NO_STR
8620 "Configure BGP aggregate entries\n"
8621 "Aggregate prefix\n"
8622 "Generate AS set path information\n"
8623 "Filter more specific routes from updates\n"
8624 "Apply route map to aggregate network\n"
8625 "Route map name\n"
8626 "BGP origin code\n"
8627 "Remote EGP\n"
8628 "Local IGP\n"
8629 "Unknown heritage\n"
8630 "Only aggregate routes with matching MED\n"
8631 "Suppress the selected more specific routes\n"
8632 "Route map with the route selectors\n")
8633{
8634 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8635 int as_set = AGGREGATE_AS_UNSET;
8636
8637 if (origin_s) {
8638 if (strcmp(origin_s, "egp") == 0)
8639 origin = BGP_ORIGIN_EGP;
8640 else if (strcmp(origin_s, "igp") == 0)
8641 origin = BGP_ORIGIN_IGP;
8642 else if (strcmp(origin_s, "incomplete") == 0)
8643 origin = BGP_ORIGIN_INCOMPLETE;
8644 }
8645
8646 if (as_set_s)
8647 as_set = AGGREGATE_AS_SET;
8648
8649 /* Handle configuration removal, otherwise installation. */
554b3b10 8650 if (no)
585f1adc
IR
8651 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8652 SAFI_UNICAST);
554b3b10 8653
585f1adc
IR
8654 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8655 rmap_name, summary_only != NULL, as_set,
8656 origin, match_med != NULL, suppress_map);
718e3744 8657}
8658
718e3744 8659/* Redistribute route treatment. */
d62a17ae 8660void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8661 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8662 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8663 enum blackhole_type bhtype, uint32_t metric,
8664 uint8_t type, unsigned short instance,
8665 route_tag_t tag)
d62a17ae 8666{
4b7e6066 8667 struct bgp_path_info *new;
40381db7
DS
8668 struct bgp_path_info *bpi;
8669 struct bgp_path_info rmap_path;
9bcb3eef 8670 struct bgp_dest *bn;
d62a17ae 8671 struct attr attr;
8672 struct attr *new_attr;
8673 afi_t afi;
b68885f9 8674 route_map_result_t ret;
d62a17ae 8675 struct bgp_redist *red;
8676
8677 /* Make default attribute. */
0f05ea43 8678 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8679 /*
8680 * This must not be NULL to satisfy Coverity SA
8681 */
8682 assert(attr.aspath);
9de1f7ff 8683
a4d82a8a 8684 switch (nhtype) {
9de1f7ff 8685 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8686 switch (p->family) {
8687 case AF_INET:
8688 attr.nexthop.s_addr = INADDR_ANY;
8689 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8690 break;
8691 case AF_INET6:
8692 memset(&attr.mp_nexthop_global, 0,
8693 sizeof(attr.mp_nexthop_global));
8694 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8695 break;
8696 }
9de1f7ff
DS
8697 break;
8698 case NEXTHOP_TYPE_IPV4:
8699 case NEXTHOP_TYPE_IPV4_IFINDEX:
8700 attr.nexthop = nexthop->ipv4;
7226bc40 8701 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8702 break;
8703 case NEXTHOP_TYPE_IPV6:
8704 case NEXTHOP_TYPE_IPV6_IFINDEX:
8705 attr.mp_nexthop_global = nexthop->ipv6;
8706 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8707 break;
8708 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8709 switch (p->family) {
8710 case AF_INET:
9de1f7ff 8711 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8712 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8713 break;
8714 case AF_INET6:
9de1f7ff
DS
8715 memset(&attr.mp_nexthop_global, 0,
8716 sizeof(attr.mp_nexthop_global));
74489921 8717 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8718 break;
74489921 8719 }
0789eb69 8720 attr.bh_type = bhtype;
9de1f7ff 8721 break;
d62a17ae 8722 }
0789eb69 8723 attr.nh_type = nhtype;
74489921 8724 attr.nh_ifindex = ifindex;
f04a80a5 8725
d62a17ae 8726 attr.med = metric;
957f74c3 8727 attr.distance = distance;
d62a17ae 8728 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8729 attr.tag = tag;
718e3744 8730
97a52c82
DA
8731 if (metric)
8732 bgp_attr_set_aigp_metric(&attr, metric);
8733
d62a17ae 8734 afi = family2afi(p->family);
6aeb9e78 8735
d62a17ae 8736 red = bgp_redist_lookup(bgp, afi, type, instance);
8737 if (red) {
8738 struct attr attr_new;
718e3744 8739
d62a17ae 8740 /* Copy attribute for modification. */
6f4f49b2 8741 attr_new = attr;
718e3744 8742
97a52c82 8743 if (red->redist_metric_flag) {
d62a17ae 8744 attr_new.med = red->redist_metric;
97a52c82
DA
8745 bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8746 }
718e3744 8747
d62a17ae 8748 /* Apply route-map. */
8749 if (red->rmap.name) {
6006b807 8750 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8751 rmap_path.peer = bgp->peer_self;
8752 rmap_path.attr = &attr_new;
718e3744 8753
d62a17ae 8754 SET_FLAG(bgp->peer_self->rmap_type,
8755 PEER_RMAP_TYPE_REDISTRIBUTE);
8756
1782514f 8757 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8758
8759 bgp->peer_self->rmap_type = 0;
8760
8761 if (ret == RMAP_DENYMATCH) {
8762 /* Free uninterned attribute. */
8763 bgp_attr_flush(&attr_new);
8764
8765 /* Unintern original. */
8766 aspath_unintern(&attr.aspath);
8767 bgp_redistribute_delete(bgp, p, type, instance);
8768 return;
8769 }
8770 }
8771
637e5ba4 8772 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8773 bgp_attr_add_gshut_community(&attr_new);
8774
d62a17ae 8775 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8776 SAFI_UNICAST, p, NULL);
8777
8778 new_attr = bgp_attr_intern(&attr_new);
8779
9bcb3eef 8780 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8781 if (bpi->peer == bgp->peer_self
8782 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8783 break;
8784
40381db7 8785 if (bpi) {
d62a17ae 8786 /* Ensure the (source route) type is updated. */
40381db7
DS
8787 bpi->type = type;
8788 if (attrhash_cmp(bpi->attr, new_attr)
8789 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8790 bgp_attr_unintern(&new_attr);
8791 aspath_unintern(&attr.aspath);
9bcb3eef 8792 bgp_dest_unlock_node(bn);
d62a17ae 8793 return;
8794 } else {
8795 /* The attribute is changed. */
40381db7 8796 bgp_path_info_set_flag(bn, bpi,
18ee8310 8797 BGP_PATH_ATTR_CHANGED);
d62a17ae 8798
8799 /* Rewrite BGP route information. */
40381db7
DS
8800 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8801 bgp_path_info_restore(bn, bpi);
d62a17ae 8802 else
40381db7
DS
8803 bgp_aggregate_decrement(
8804 bgp, p, bpi, afi, SAFI_UNICAST);
8805 bgp_attr_unintern(&bpi->attr);
8806 bpi->attr = new_attr;
083ec940 8807 bpi->uptime = monotime(NULL);
d62a17ae 8808
8809 /* Process change. */
40381db7 8810 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8811 SAFI_UNICAST);
8812 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8813 bgp_dest_unlock_node(bn);
d62a17ae 8814 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8815
8816 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8817 || (bgp->inst_type
8818 == BGP_INSTANCE_TYPE_DEFAULT)) {
8819
8820 vpn_leak_from_vrf_update(
40381db7 8821 bgp_get_default(), bgp, bpi);
ddb5b488 8822 }
d62a17ae 8823 return;
8824 }
8825 }
8826
8827 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8828 bgp->peer_self, new_attr, bn);
1defdda8 8829 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8830
8831 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8832 bgp_path_info_add(bn, new);
9bcb3eef 8833 bgp_dest_unlock_node(bn);
be785e35 8834 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8835 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8836
8837 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8838 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8839
8840 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8841 }
d62a17ae 8842 }
8843
8844 /* Unintern original. */
8845 aspath_unintern(&attr.aspath);
718e3744 8846}
8847
d7c0a89a
QY
8848void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8849 unsigned short instance)
718e3744 8850{
d62a17ae 8851 afi_t afi;
9bcb3eef 8852 struct bgp_dest *dest;
40381db7 8853 struct bgp_path_info *pi;
d62a17ae 8854 struct bgp_redist *red;
718e3744 8855
d62a17ae 8856 afi = family2afi(p->family);
718e3744 8857
d62a17ae 8858 red = bgp_redist_lookup(bgp, afi, type, instance);
8859 if (red) {
9bcb3eef
DS
8860 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8861 SAFI_UNICAST, p, NULL);
d62a17ae 8862
9bcb3eef 8863 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8864 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8865 break;
8866
40381db7 8867 if (pi) {
ddb5b488
PZ
8868 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8869 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8870
8871 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8872 bgp, pi);
ddb5b488 8873 }
40381db7 8874 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8875 bgp_path_info_delete(dest, pi);
8876 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8877 }
9bcb3eef 8878 bgp_dest_unlock_node(dest);
d62a17ae 8879 }
8880}
8881
8882/* Withdraw specified route type's route. */
8883void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8884 unsigned short instance)
d62a17ae 8885{
9bcb3eef 8886 struct bgp_dest *dest;
40381db7 8887 struct bgp_path_info *pi;
d62a17ae 8888 struct bgp_table *table;
8889
8890 table = bgp->rib[afi][SAFI_UNICAST];
8891
9bcb3eef
DS
8892 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8893 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8894 if (pi->peer == bgp->peer_self && pi->type == type
8895 && pi->instance == instance)
d62a17ae 8896 break;
8897
40381db7 8898 if (pi) {
ddb5b488
PZ
8899 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8900 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8901
8902 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8903 bgp, pi);
ddb5b488 8904 }
9bcb3eef 8905 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8906 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8907 bgp_path_info_delete(dest, pi);
8908 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8909 }
718e3744 8910 }
718e3744 8911}
6b0655a2 8912
718e3744 8913/* Static function to display route. */
7d3cae70
DA
8914static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8915 struct vty *vty, json_object *json, bool wide)
718e3744 8916{
be054588 8917 int len = 0;
d62a17ae 8918 char buf[BUFSIZ];
718e3744 8919
d62a17ae 8920 if (p->family == AF_INET) {
c6462ff4 8921 if (!json) {
8228a9a7 8922 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8923 } else {
8924 json_object_string_add(json, "prefix",
8925 inet_ntop(p->family,
8926 &p->u.prefix, buf,
8927 BUFSIZ));
8928 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8929 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8930 json_object_int_add(json, "version", dest->version);
c6462ff4 8931 }
d62a17ae 8932 } else if (p->family == AF_ETHERNET) {
8228a9a7 8933 len = vty_out(vty, "%pFX", p);
b03b8898 8934 } else if (p->family == AF_EVPN) {
57f7feb6 8935 if (!json)
2dbe669b 8936 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8937 else
60466a63 8938 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8939 } else if (p->family == AF_FLOWSPEC) {
8940 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8941 json ?
8942 NLRI_STRING_FORMAT_JSON_SIMPLE :
8943 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8944 } else {
c6462ff4 8945 if (!json)
8228a9a7 8946 len = vty_out(vty, "%pFX", p);
50e05855
AD
8947 else {
8948 json_object_string_add(json, "prefix",
8949 inet_ntop(p->family,
8950 &p->u.prefix, buf,
8951 BUFSIZ));
8952 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8953 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8954 json_object_int_add(json, "version", dest->version);
37d4e0df 8955 }
9c92b5f7 8956 }
d62a17ae 8957
9c92b5f7 8958 if (!json) {
ae248832 8959 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8960 if (len < 1)
8961 vty_out(vty, "\n%*s", 20, " ");
8962 else
8963 vty_out(vty, "%*s", len, " ");
8964 }
718e3744 8965}
8966
d62a17ae 8967enum bgp_display_type {
8968 normal_list,
718e3744 8969};
8970
1d7260a1 8971const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8972{
8973 switch (reason) {
8974 case bgp_path_selection_none:
8975 return "Nothing to Select";
8976 case bgp_path_selection_first:
8977 return "First path received";
8978 case bgp_path_selection_evpn_sticky_mac:
8979 return "EVPN Sticky Mac";
8980 case bgp_path_selection_evpn_seq:
8981 return "EVPN sequence number";
8982 case bgp_path_selection_evpn_lower_ip:
8983 return "EVPN lower IP";
8984 case bgp_path_selection_evpn_local_path:
8985 return "EVPN local ES path";
8986 case bgp_path_selection_evpn_non_proxy:
8987 return "EVPN non proxy";
8988 case bgp_path_selection_weight:
8989 return "Weight";
8990 case bgp_path_selection_local_pref:
8991 return "Local Pref";
46dbf9d0
DA
8992 case bgp_path_selection_accept_own:
8993 return "Accept Own";
bbb46eb5
DA
8994 case bgp_path_selection_local_route:
8995 return "Local Route";
97a52c82
DA
8996 case bgp_path_selection_aigp:
8997 return "AIGP";
bbb46eb5
DA
8998 case bgp_path_selection_confed_as_path:
8999 return "Confederation based AS Path";
9000 case bgp_path_selection_as_path:
9001 return "AS Path";
9002 case bgp_path_selection_origin:
9003 return "Origin";
9004 case bgp_path_selection_med:
9005 return "MED";
9006 case bgp_path_selection_peer:
9007 return "Peer Type";
9008 case bgp_path_selection_confed:
9009 return "Confed Peer Type";
9010 case bgp_path_selection_igp_metric:
9011 return "IGP Metric";
9012 case bgp_path_selection_older:
9013 return "Older Path";
9014 case bgp_path_selection_router_id:
9015 return "Router ID";
9016 case bgp_path_selection_cluster_length:
bcab253c 9017 return "Cluster length";
bbb46eb5
DA
9018 case bgp_path_selection_stale:
9019 return "Path Staleness";
9020 case bgp_path_selection_local_configured:
9021 return "Locally configured route";
9022 case bgp_path_selection_neighbor_ip:
9023 return "Neighbor IP";
9024 case bgp_path_selection_default:
9025 return "Nothing left to compare";
9026 }
9027 return "Invalid (internal error)";
9028}
9029
18ee8310 9030/* Print the short form route status for a bgp_path_info */
4b7e6066 9031static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 9032 struct bgp_path_info *path,
82c298be 9033 const struct prefix *p,
d62a17ae 9034 json_object *json_path)
718e3744 9035{
82c298be
DA
9036 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
9037
d62a17ae 9038 if (json_path) {
b05a1c8b 9039
d62a17ae 9040 /* Route status display. */
9b6d8fcf 9041 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9042 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 9043
9b6d8fcf 9044 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9045 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 9046
4056a5f6 9047 if (path->extra && bgp_path_suppressed(path))
d62a17ae 9048 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 9049
9b6d8fcf
DS
9050 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9051 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9052 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 9053
d62a17ae 9054 /* Selected */
9b6d8fcf 9055 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9056 json_object_boolean_true_add(json_path, "history");
b05a1c8b 9057
9b6d8fcf 9058 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9059 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 9060
bbb46eb5 9061 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 9062 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
9063 json_object_string_add(json_path, "selectionReason",
9064 bgp_path_selection_reason2str(
9065 path->net->reason));
9066 }
b05a1c8b 9067
9b6d8fcf 9068 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9069 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 9070
d62a17ae 9071 /* Internal route. */
9b6d8fcf
DS
9072 if ((path->peer->as)
9073 && (path->peer->as == path->peer->local_as))
d62a17ae 9074 json_object_string_add(json_path, "pathFrom",
9075 "internal");
9076 else
9077 json_object_string_add(json_path, "pathFrom",
9078 "external");
b05a1c8b 9079
d62a17ae 9080 return;
9081 }
b05a1c8b 9082
82c298be
DA
9083 /* RPKI validation state */
9084 rpki_state =
9085 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9086
9087 if (rpki_state == RPKI_VALID)
9088 vty_out(vty, "V");
9089 else if (rpki_state == RPKI_INVALID)
9090 vty_out(vty, "I");
9091 else if (rpki_state == RPKI_NOTFOUND)
9092 vty_out(vty, "N");
eaeba5e8
WM
9093 else
9094 vty_out(vty, " ");
82c298be 9095
d62a17ae 9096 /* Route status display. */
9b6d8fcf 9097 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 9098 vty_out(vty, "R");
9b6d8fcf 9099 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 9100 vty_out(vty, "S");
4056a5f6 9101 else if (bgp_path_suppressed(path))
d62a17ae 9102 vty_out(vty, "s");
9b6d8fcf
DS
9103 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9104 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9105 vty_out(vty, "*");
9106 else
9107 vty_out(vty, " ");
9108
9109 /* Selected */
9b6d8fcf 9110 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9111 vty_out(vty, "h");
9b6d8fcf 9112 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 9113 vty_out(vty, "d");
9b6d8fcf 9114 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 9115 vty_out(vty, ">");
9b6d8fcf 9116 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 9117 vty_out(vty, "=");
9118 else
9119 vty_out(vty, " ");
718e3744 9120
d62a17ae 9121 /* Internal route. */
9b6d8fcf
DS
9122 if (path->peer && (path->peer->as)
9123 && (path->peer->as == path->peer->local_as))
d62a17ae 9124 vty_out(vty, "i");
9125 else
9126 vty_out(vty, " ");
b40d939b 9127}
9128
2ba93fd6
DA
9129static char *bgp_nexthop_hostname(struct peer *peer,
9130 struct bgp_nexthop_cache *bnc)
25b5da8d 9131{
892fedb6 9132 if (peer->hostname
aef999a2 9133 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
9134 return peer->hostname;
9135 return NULL;
9136}
9137
b40d939b 9138/* called from terminal list command */
bd494ec5 9139void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 9140 struct bgp_path_info *path, int display, safi_t safi,
ae248832 9141 json_object *json_paths, bool wide)
d62a17ae 9142{
aef999a2 9143 int len;
515c2602 9144 struct attr *attr = path->attr;
d62a17ae 9145 json_object *json_path = NULL;
9146 json_object *json_nexthops = NULL;
9147 json_object *json_nexthop_global = NULL;
9148 json_object *json_nexthop_ll = NULL;
6f214dd3 9149 json_object *json_ext_community = NULL;
9df8b37c 9150 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 9151 bool nexthop_self =
9b6d8fcf 9152 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 9153 bool nexthop_othervrf = false;
43089216 9154 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 9155 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
9156 char *nexthop_hostname =
9157 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 9158 char esi_buf[ESI_STR_LEN];
d62a17ae 9159
9160 if (json_paths)
9161 json_path = json_object_new_object();
9162
9163 /* short status lead text */
82c298be 9164 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9165
9166 if (!json_paths) {
9167 /* print prefix and mask */
9168 if (!display)
7d3cae70 9169 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9170 else
ae248832 9171 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 9172 } else {
7d3cae70 9173 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 9174 }
47fc97cc 9175
9df8b37c
PZ
9176 /*
9177 * If vrf id of nexthop is different from that of prefix,
9178 * set up printable string to append
9179 */
9b6d8fcf 9180 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
9181 const char *self = "";
9182
9183 if (nexthop_self)
9184 self = "<";
9185
9186 nexthop_othervrf = true;
9b6d8fcf 9187 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9188
9b6d8fcf 9189 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
9190 snprintf(vrf_id_str, sizeof(vrf_id_str),
9191 "@%s%s", VRFID_NONE_STR, self);
9192 else
9193 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 9194 path->extra->bgp_orig->vrf_id, self);
9df8b37c 9195
9b6d8fcf
DS
9196 if (path->extra->bgp_orig->inst_type
9197 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 9198
9b6d8fcf 9199 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
9200 } else {
9201 const char *self = "";
9202
9203 if (nexthop_self)
9204 self = "<";
9205
9206 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9207 }
9208
445c2480
DS
9209 /*
9210 * For ENCAP and EVPN routes, nexthop address family is not
9211 * neccessarily the same as the prefix address family.
9212 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9213 * EVPN routes are also exchanged with a MP nexthop. Currently,
9214 * this
9215 * is only IPv4, the value will be present in either
9216 * attr->nexthop or
9217 * attr->mp_nexthop_global_in
9218 */
9219 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9220 char buf[BUFSIZ];
9221 char nexthop[128];
9222 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9223
9224 switch (af) {
9225 case AF_INET:
772270f3
QY
9226 snprintf(nexthop, sizeof(nexthop), "%s",
9227 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
9228 BUFSIZ));
445c2480
DS
9229 break;
9230 case AF_INET6:
772270f3
QY
9231 snprintf(nexthop, sizeof(nexthop), "%s",
9232 inet_ntop(af, &attr->mp_nexthop_global, buf,
9233 BUFSIZ));
445c2480
DS
9234 break;
9235 default:
772270f3 9236 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9237 break;
d62a17ae 9238 }
d62a17ae 9239
445c2480
DS
9240 if (json_paths) {
9241 json_nexthop_global = json_object_new_object();
9242
515c2602
DA
9243 json_object_string_add(json_nexthop_global, "ip",
9244 nexthop);
9245
939a97f4 9246 if (path->peer->hostname)
515c2602
DA
9247 json_object_string_add(json_nexthop_global,
9248 "hostname",
939a97f4 9249 path->peer->hostname);
515c2602
DA
9250
9251 json_object_string_add(json_nexthop_global, "afi",
9252 (af == AF_INET) ? "ipv4"
9253 : "ipv6");
445c2480
DS
9254 json_object_boolean_true_add(json_nexthop_global,
9255 "used");
aef999a2
DA
9256 } else {
9257 if (nexthop_hostname)
9258 len = vty_out(vty, "%s(%s)%s", nexthop,
9259 nexthop_hostname, vrf_id_str);
9260 else
9261 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9262
ae248832 9263 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9264 if (len < 1)
9265 vty_out(vty, "\n%*s", 36, " ");
9266 else
9267 vty_out(vty, "%*s", len, " ");
9268 }
445c2480
DS
9269 } else if (safi == SAFI_EVPN) {
9270 if (json_paths) {
9271 json_nexthop_global = json_object_new_object();
9272
c949c771 9273 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9274 "%pI4",
9275 &attr->mp_nexthop_global_in);
515c2602 9276
939a97f4 9277 if (path->peer->hostname)
515c2602
DA
9278 json_object_string_add(json_nexthop_global,
9279 "hostname",
939a97f4 9280 path->peer->hostname);
515c2602 9281
a4d82a8a
PZ
9282 json_object_string_add(json_nexthop_global, "afi",
9283 "ipv4");
445c2480
DS
9284 json_object_boolean_true_add(json_nexthop_global,
9285 "used");
aef999a2
DA
9286 } else {
9287 if (nexthop_hostname)
7226bc40
TA
9288 len = vty_out(vty, "%pI4(%s)%s",
9289 &attr->mp_nexthop_global_in,
aef999a2
DA
9290 nexthop_hostname, vrf_id_str);
9291 else
7226bc40
TA
9292 len = vty_out(vty, "%pI4%s",
9293 &attr->mp_nexthop_global_in,
aef999a2
DA
9294 vrf_id_str);
9295
ae248832 9296 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9297 if (len < 1)
9298 vty_out(vty, "\n%*s", 36, " ");
9299 else
9300 vty_out(vty, "%*s", len, " ");
9301 }
d33fc23b 9302 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9303 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9304 if (json_paths) {
9305 json_nexthop_global = json_object_new_object();
515c2602 9306
026b914a
PG
9307 json_object_string_add(json_nexthop_global,
9308 "afi", "ipv4");
c949c771
DA
9309 json_object_string_addf(json_nexthop_global,
9310 "ip", "%pI4",
9311 &attr->nexthop);
515c2602 9312
939a97f4 9313 if (path->peer->hostname)
515c2602
DA
9314 json_object_string_add(
9315 json_nexthop_global, "hostname",
939a97f4 9316 path->peer->hostname);
515c2602 9317
50e05855
AD
9318 json_object_boolean_true_add(
9319 json_nexthop_global,
026b914a
PG
9320 "used");
9321 } else {
aef999a2
DA
9322 if (nexthop_hostname)
9323 len = vty_out(vty, "%pI4(%s)%s",
9324 &attr->nexthop,
9325 nexthop_hostname,
9326 vrf_id_str);
9327 else
9328 len = vty_out(vty, "%pI4%s",
9329 &attr->nexthop,
9330 vrf_id_str);
9331
ae248832 9332 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9333 if (len < 1)
9334 vty_out(vty, "\n%*s", 36, " ");
9335 else
9336 vty_out(vty, "%*s", len, " ");
026b914a
PG
9337 }
9338 }
7226bc40 9339 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9340 if (json_paths) {
9341 json_nexthop_global = json_object_new_object();
d62a17ae 9342
c949c771
DA
9343 json_object_string_addf(json_nexthop_global, "ip",
9344 "%pI4", &attr->nexthop);
515c2602 9345
939a97f4 9346 if (path->peer->hostname)
515c2602
DA
9347 json_object_string_add(json_nexthop_global,
9348 "hostname",
939a97f4 9349 path->peer->hostname);
445c2480 9350
a4d82a8a
PZ
9351 json_object_string_add(json_nexthop_global, "afi",
9352 "ipv4");
445c2480
DS
9353 json_object_boolean_true_add(json_nexthop_global,
9354 "used");
9355 } else {
aef999a2
DA
9356 if (nexthop_hostname)
9357 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9358 nexthop_hostname, vrf_id_str);
9359 else
9360 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9361 vrf_id_str);
9df8b37c 9362
ae248832 9363 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9364 if (len < 1)
9365 vty_out(vty, "\n%*s", 36, " ");
9366 else
9367 vty_out(vty, "%*s", len, " ");
d62a17ae 9368 }
445c2480 9369 }
b05a1c8b 9370
445c2480 9371 /* IPv6 Next Hop */
7226bc40 9372 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9373 if (json_paths) {
9374 json_nexthop_global = json_object_new_object();
c949c771
DA
9375 json_object_string_addf(json_nexthop_global, "ip",
9376 "%pI6",
9377 &attr->mp_nexthop_global);
515c2602 9378
939a97f4 9379 if (path->peer->hostname)
515c2602
DA
9380 json_object_string_add(json_nexthop_global,
9381 "hostname",
939a97f4 9382 path->peer->hostname);
515c2602 9383
a4d82a8a
PZ
9384 json_object_string_add(json_nexthop_global, "afi",
9385 "ipv6");
9386 json_object_string_add(json_nexthop_global, "scope",
9387 "global");
445c2480
DS
9388
9389 /* We display both LL & GL if both have been
9390 * received */
0606039c
DA
9391 if ((attr->mp_nexthop_len
9392 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9393 || (path->peer->conf_if)) {
a4d82a8a 9394 json_nexthop_ll = json_object_new_object();
c949c771
DA
9395 json_object_string_addf(
9396 json_nexthop_ll, "ip", "%pI6",
9397 &attr->mp_nexthop_local);
515c2602 9398
939a97f4 9399 if (path->peer->hostname)
515c2602
DA
9400 json_object_string_add(
9401 json_nexthop_ll, "hostname",
939a97f4 9402 path->peer->hostname);
515c2602 9403
a4d82a8a
PZ
9404 json_object_string_add(json_nexthop_ll, "afi",
9405 "ipv6");
9406 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9407 "link-local");
d62a17ae 9408
a4d82a8a
PZ
9409 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9410 &attr->mp_nexthop_local)
445c2480
DS
9411 != 0)
9412 && !attr->mp_nexthop_prefer_global)
d62a17ae 9413 json_object_boolean_true_add(
a4d82a8a 9414 json_nexthop_ll, "used");
445c2480
DS
9415 else
9416 json_object_boolean_true_add(
a4d82a8a 9417 json_nexthop_global, "used");
445c2480
DS
9418 } else
9419 json_object_boolean_true_add(
9420 json_nexthop_global, "used");
9421 } else {
9422 /* Display LL if LL/Global both in table unless
9423 * prefer-global is set */
0606039c
DA
9424 if (((attr->mp_nexthop_len
9425 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9426 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9427 || (path->peer->conf_if)) {
9428 if (path->peer->conf_if) {
a4d82a8a 9429 len = vty_out(vty, "%s",
9b6d8fcf 9430 path->peer->conf_if);
ae248832
MK
9431 /* len of IPv6 addr + max len of def
9432 * ifname */
9433 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9434
9435 if (len < 1)
a4d82a8a 9436 vty_out(vty, "\n%*s", 36, " ");
445c2480 9437 else
a4d82a8a 9438 vty_out(vty, "%*s", len, " ");
d62a17ae 9439 } else {
aef999a2
DA
9440 if (nexthop_hostname)
9441 len = vty_out(
9442 vty, "%pI6(%s)%s",
9443 &attr->mp_nexthop_local,
9444 nexthop_hostname,
9445 vrf_id_str);
9446 else
9447 len = vty_out(
9448 vty, "%pI6%s",
9449 &attr->mp_nexthop_local,
9450 vrf_id_str);
9451
ae248832 9452 len = wide ? (41 - len) : (16 - len);
d62a17ae 9453
9454 if (len < 1)
a4d82a8a 9455 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9456 else
a4d82a8a 9457 vty_out(vty, "%*s", len, " ");
d62a17ae 9458 }
445c2480 9459 } else {
aef999a2
DA
9460 if (nexthop_hostname)
9461 len = vty_out(vty, "%pI6(%s)%s",
9462 &attr->mp_nexthop_global,
9463 nexthop_hostname,
9464 vrf_id_str);
9465 else
9466 len = vty_out(vty, "%pI6%s",
9467 &attr->mp_nexthop_global,
9468 vrf_id_str);
9469
ae248832 9470 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9471
9472 if (len < 1)
9473 vty_out(vty, "\n%*s", 36, " ");
9474 else
9475 vty_out(vty, "%*s", len, " ");
d62a17ae 9476 }
9477 }
445c2480 9478 }
718e3744 9479
445c2480
DS
9480 /* MED/Metric */
9481 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9482 if (json_paths)
50e05855 9483 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9484 else if (wide)
9485 vty_out(vty, "%7u", attr->med);
0fbac0b4 9486 else
445c2480 9487 vty_out(vty, "%10u", attr->med);
ae248832
MK
9488 else if (!json_paths) {
9489 if (wide)
9490 vty_out(vty, "%*s", 7, " ");
9491 else
9492 vty_out(vty, "%*s", 10, " ");
9493 }
d62a17ae 9494
445c2480
DS
9495 /* Local Pref */
9496 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9497 if (json_paths)
50e05855 9498 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9499 attr->local_pref);
9500 else
445c2480
DS
9501 vty_out(vty, "%7u", attr->local_pref);
9502 else if (!json_paths)
9503 vty_out(vty, " ");
d62a17ae 9504
445c2480
DS
9505 if (json_paths)
9506 json_object_int_add(json_path, "weight", attr->weight);
9507 else
9508 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9509
47e12884
DA
9510 if (json_paths)
9511 json_object_string_addf(json_path, "peerId", "%pSU",
9512 &path->peer->su);
b05a1c8b 9513
445c2480
DS
9514 /* Print aspath */
9515 if (attr->aspath) {
0fbac0b4 9516 if (json_paths)
50e05855 9517 json_object_string_add(json_path, "path",
0fbac0b4
DA
9518 attr->aspath->str);
9519 else
445c2480 9520 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9521 }
f1aa5d8a 9522
445c2480
DS
9523 /* Print origin */
9524 if (json_paths)
a4d82a8a
PZ
9525 json_object_string_add(json_path, "origin",
9526 bgp_origin_long_str[attr->origin]);
445c2480
DS
9527 else
9528 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9529
9df8b37c 9530 if (json_paths) {
d071f237 9531 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9532 json_object_string_add(json_path, "esi",
9533 esi_to_str(&attr->esi,
9534 esi_buf, sizeof(esi_buf)));
9535 }
6f214dd3
CS
9536 if (safi == SAFI_EVPN &&
9537 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9538 json_ext_community = json_object_new_object();
b53e67a3
DA
9539 json_object_string_add(
9540 json_ext_community, "string",
9541 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9542 json_object_object_add(json_path,
9543 "extendedCommunity",
9544 json_ext_community);
9545 }
9546
9df8b37c
PZ
9547 if (nexthop_self)
9548 json_object_boolean_true_add(json_path,
9549 "announceNexthopSelf");
9550 if (nexthop_othervrf) {
9551 json_object_string_add(json_path, "nhVrfName",
9552 nexthop_vrfname);
9553
9554 json_object_int_add(json_path, "nhVrfId",
9555 ((nexthop_vrfid == VRF_UNKNOWN)
9556 ? -1
9557 : (int)nexthop_vrfid));
9558 }
9559 }
9560
d62a17ae 9561 if (json_paths) {
9562 if (json_nexthop_global || json_nexthop_ll) {
9563 json_nexthops = json_object_new_array();
f1aa5d8a 9564
d62a17ae 9565 if (json_nexthop_global)
9566 json_object_array_add(json_nexthops,
9567 json_nexthop_global);
f1aa5d8a 9568
d62a17ae 9569 if (json_nexthop_ll)
9570 json_object_array_add(json_nexthops,
9571 json_nexthop_ll);
f1aa5d8a 9572
d62a17ae 9573 json_object_object_add(json_path, "nexthops",
9574 json_nexthops);
9575 }
9576
9577 json_object_array_add(json_paths, json_path);
9578 } else {
9579 vty_out(vty, "\n");
6f214dd3 9580
b5e140c8 9581 if (safi == SAFI_EVPN) {
d071f237 9582 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9583 /* XXX - add these params to the json out */
b5e140c8 9584 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9585 vty_out(vty, "ESI:%s",
9586 esi_to_str(&attr->esi, esi_buf,
9587 sizeof(esi_buf)));
60605cbc 9588
229587fb 9589 vty_out(vty, "\n");
b5e140c8
AK
9590 }
9591 if (attr->flag &
9592 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9593 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9594 vty_out(vty, "%s\n",
9595 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9596 }
6f214dd3
CS
9597 }
9598
49e5a4a0 9599#ifdef ENABLE_BGP_VNC
d62a17ae 9600 /* prints an additional line, indented, with VNC info, if
9601 * present */
9602 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9603 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9604#endif
d62a17ae 9605 }
9606}
718e3744 9607
9608/* called from terminal list command */
7d3cae70
DA
9609void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9610 const struct prefix *p, struct attr *attr, safi_t safi,
9611 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9612{
9613 json_object *json_status = NULL;
9614 json_object *json_net = NULL;
aef999a2 9615 int len;
d62a17ae 9616 char buff[BUFSIZ];
dc387b0f 9617
d62a17ae 9618 /* Route status display. */
9619 if (use_json) {
9620 json_status = json_object_new_object();
9621 json_net = json_object_new_object();
9622 } else {
9623 vty_out(vty, "*");
9624 vty_out(vty, ">");
9625 vty_out(vty, " ");
9626 }
718e3744 9627
d62a17ae 9628 /* print prefix and mask */
50e05855 9629 if (use_json) {
dc387b0f
LK
9630 if (safi == SAFI_EVPN)
9631 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9632 else if (p->family == AF_INET || p->family == AF_INET6) {
9633 json_object_string_add(
9634 json_net, "addrPrefix",
9635 inet_ntop(p->family, &p->u.prefix, buff,
9636 BUFSIZ));
9637 json_object_int_add(json_net, "prefixLen",
9638 p->prefixlen);
67d7e256 9639 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9640 }
50e05855 9641 } else
7d3cae70 9642 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9643
9644 /* Print attribute */
9645 if (attr) {
9646 if (use_json) {
7226bc40
TA
9647 if (p->family == AF_INET &&
9648 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9649 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9650 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9651 json_object_string_addf(
9652 json_net, "nextHop", "%pI4",
9653 &attr->mp_nexthop_global_in);
d62a17ae 9654 else
c949c771
DA
9655 json_object_string_addf(
9656 json_net, "nextHop", "%pI4",
9657 &attr->nexthop);
7226bc40
TA
9658 } else if (p->family == AF_INET6 ||
9659 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9660 json_object_string_addf(
9661 json_net, "nextHopGlobal", "%pI6",
9662 &attr->mp_nexthop_global);
7226bc40
TA
9663 } else if (p->family == AF_EVPN &&
9664 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9665 json_object_string_addf(
9666 json_net, "nextHop", "%pI4",
9667 &attr->mp_nexthop_global_in);
23d0a753 9668 }
d62a17ae 9669
9670 if (attr->flag
9671 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9672 json_object_int_add(json_net, "metric",
9673 attr->med);
9674
0fbac0b4 9675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9676 json_object_int_add(json_net, "locPrf",
0fbac0b4 9677 attr->local_pref);
d62a17ae 9678
9679 json_object_int_add(json_net, "weight", attr->weight);
9680
9681 /* Print aspath */
0fbac0b4 9682 if (attr->aspath)
50e05855 9683 json_object_string_add(json_net, "path",
0fbac0b4 9684 attr->aspath->str);
d62a17ae 9685
9686 /* Print origin */
9687 json_object_string_add(json_net, "bgpOriginCode",
9688 bgp_origin_str[attr->origin]);
9689 } else {
7226bc40
TA
9690 if (p->family == AF_INET &&
9691 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9692 safi == SAFI_EVPN ||
9693 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9694 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9695 || safi == SAFI_EVPN)
23d0a753
DA
9696 vty_out(vty, "%-16pI4",
9697 &attr->mp_nexthop_global_in);
ae248832 9698 else if (wide)
23d0a753 9699 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9700 else
23d0a753 9701 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9702 } else if (p->family == AF_INET6 ||
9703 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9704 char buf[BUFSIZ];
9705
9706 len = vty_out(
9707 vty, "%s",
9708 inet_ntop(AF_INET6,
9709 &attr->mp_nexthop_global, buf,
9710 BUFSIZ));
ae248832 9711 len = wide ? (41 - len) : (16 - len);
d62a17ae 9712 if (len < 1)
9713 vty_out(vty, "\n%*s", 36, " ");
9714 else
9715 vty_out(vty, "%*s", len, " ");
9716 }
9717 if (attr->flag
9718 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9719 if (wide)
9720 vty_out(vty, "%7u", attr->med);
9721 else
9722 vty_out(vty, "%10u", attr->med);
9723 else if (wide)
9724 vty_out(vty, " ");
d62a17ae 9725 else
9726 vty_out(vty, " ");
718e3744 9727
d62a17ae 9728 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9729 vty_out(vty, "%7u", attr->local_pref);
9730 else
9731 vty_out(vty, " ");
9732
9733 vty_out(vty, "%7u ", attr->weight);
9734
9735 /* Print aspath */
9736 if (attr->aspath)
9737 aspath_print_vty(vty, "%s", attr->aspath, " ");
9738
9739 /* Print origin */
9740 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9741 }
9742 }
9743 if (use_json) {
9744 json_object_boolean_true_add(json_status, "*");
9745 json_object_boolean_true_add(json_status, ">");
9746 json_object_object_add(json_net, "appliedStatusSymbols",
9747 json_status);
511211bf 9748 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9749 } else
9750 vty_out(vty, "\n");
9751}
9752
bd494ec5 9753void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9754 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9755 json_object *json)
9756{
9757 json_object *json_out = NULL;
9758 struct attr *attr;
9759 mpls_label_t label = MPLS_INVALID_LABEL;
9760
9b6d8fcf 9761 if (!path->extra)
d62a17ae 9762 return;
9763
9764 if (json)
9765 json_out = json_object_new_object();
9766
9767 /* short status lead text */
82c298be 9768 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9769
9770 /* print prefix and mask */
9771 if (json == NULL) {
9772 if (!display)
7d3cae70 9773 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9774 else
9775 vty_out(vty, "%*s", 17, " ");
9776 }
9777
9778 /* Print attribute */
9b6d8fcf 9779 attr = path->attr;
7226bc40
TA
9780 if (((p->family == AF_INET) &&
9781 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9782 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9783 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9784 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9785 || safi == SAFI_EVPN) {
9786 if (json)
c949c771
DA
9787 json_object_string_addf(
9788 json_out, "mpNexthopGlobalIn", "%pI4",
9789 &attr->mp_nexthop_global_in);
05864da7 9790 else
23d0a753
DA
9791 vty_out(vty, "%-16pI4",
9792 &attr->mp_nexthop_global_in);
05864da7
DS
9793 } else {
9794 if (json)
c949c771
DA
9795 json_object_string_addf(json_out, "nexthop",
9796 "%pI4", &attr->nexthop);
05864da7 9797 else
23d0a753 9798 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9799 }
7226bc40
TA
9800 } else if (((p->family == AF_INET6) &&
9801 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9802 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9803 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9804 char buf_a[512];
9805
9806 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9807 if (json)
c949c771
DA
9808 json_object_string_addf(
9809 json_out, "mpNexthopGlobalIn", "%pI6",
9810 &attr->mp_nexthop_global);
05864da7
DS
9811 else
9812 vty_out(vty, "%s",
9813 inet_ntop(AF_INET6,
9814 &attr->mp_nexthop_global,
9815 buf_a, sizeof(buf_a)));
9816 } else if (attr->mp_nexthop_len
9817 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9818 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9819 &attr->mp_nexthop_global,
9820 &attr->mp_nexthop_local);
9821 if (json)
9822 json_object_string_add(json_out,
9823 "mpNexthopGlobalLocal",
9824 buf_a);
9825 else
9826 vty_out(vty, "%s", buf_a);
d62a17ae 9827 }
9828 }
9829
9b6d8fcf 9830 label = decode_label(&path->extra->label[0]);
d62a17ae 9831
9832 if (bgp_is_valid_label(&label)) {
9833 if (json) {
9834 json_object_int_add(json_out, "notag", label);
9835 json_object_array_add(json, json_out);
9836 } else {
9837 vty_out(vty, "notag/%d", label);
9838 vty_out(vty, "\n");
9839 }
700ddfed
PG
9840 } else if (!json)
9841 vty_out(vty, "\n");
d62a17ae 9842}
718e3744 9843
bd494ec5 9844void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9845 struct bgp_path_info *path, int display,
d62a17ae 9846 json_object *json_paths)
718e3744 9847{
d62a17ae 9848 struct attr *attr;
d62a17ae 9849 json_object *json_path = NULL;
14f51eba
LK
9850 json_object *json_nexthop = NULL;
9851 json_object *json_overlay = NULL;
856ca177 9852
9b6d8fcf 9853 if (!path->extra)
d62a17ae 9854 return;
718e3744 9855
14f51eba
LK
9856 if (json_paths) {
9857 json_path = json_object_new_object();
9858 json_overlay = json_object_new_object();
9859 json_nexthop = json_object_new_object();
9860 }
9861
d62a17ae 9862 /* short status lead text */
82c298be 9863 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9864
d62a17ae 9865 /* print prefix and mask */
9866 if (!display)
7d3cae70 9867 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9868 else
9869 vty_out(vty, "%*s", 17, " ");
9870
9871 /* Print attribute */
9b6d8fcf 9872 attr = path->attr;
05864da7 9873 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9874
05864da7
DS
9875 switch (af) {
9876 case AF_INET:
05864da7 9877 if (!json_path) {
db66cf7c 9878 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9879 } else {
db66cf7c
DA
9880 json_object_string_addf(json_nexthop, "ip", "%pI4",
9881 &attr->mp_nexthop_global_in);
14f51eba 9882
05864da7 9883 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9884
05864da7
DS
9885 json_object_object_add(json_path, "nexthop",
9886 json_nexthop);
9887 }
9888 break;
9889 case AF_INET6:
05864da7 9890 if (!json_path) {
db66cf7c
DA
9891 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9892 &attr->mp_nexthop_local);
05864da7 9893 } else {
db66cf7c
DA
9894 json_object_string_addf(json_nexthop, "ipv6Global",
9895 "%pI6",
9896 &attr->mp_nexthop_global);
14f51eba 9897
db66cf7c
DA
9898 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9899 "%pI6",
9900 &attr->mp_nexthop_local);
14f51eba 9901
05864da7 9902 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9903
05864da7
DS
9904 json_object_object_add(json_path, "nexthop",
9905 json_nexthop);
9906 }
9907 break;
9908 default:
9909 if (!json_path) {
9910 vty_out(vty, "?");
9911 } else {
9912 json_object_string_add(json_nexthop, "Error",
9913 "Unsupported address-family");
77a2f8e5
DA
9914 json_object_string_add(json_nexthop, "error",
9915 "Unsupported address-family");
d62a17ae 9916 }
05864da7 9917 }
988258b4 9918
6c924775
DS
9919 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9920
05864da7 9921 if (!json_path)
db66cf7c 9922 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9923 else
db66cf7c 9924 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9925
b53e67a3 9926 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9927 char *mac = NULL;
9928 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9929 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9930 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9931
9932 if (routermac)
9933 mac = ecom_mac2str((char *)routermac->val);
9934 if (mac) {
9935 if (!json_path) {
c4efd0f4 9936 vty_out(vty, "/%s", mac);
05864da7
DS
9937 } else {
9938 json_object_string_add(json_overlay, "rmac",
9939 mac);
988258b4 9940 }
05864da7 9941 XFREE(MTYPE_TMP, mac);
988258b4 9942 }
05864da7 9943 }
718e3744 9944
05864da7
DS
9945 if (!json_path) {
9946 vty_out(vty, "\n");
9947 } else {
9948 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9949
05864da7 9950 json_object_array_add(json_paths, json_path);
14f51eba 9951 }
d62a17ae 9952}
718e3744 9953
d62a17ae 9954/* dampening route */
5f040085
DS
9955static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9956 struct bgp_path_info *path, int display,
9957 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9958 json_object *json_paths)
d62a17ae 9959{
e5be8c1d 9960 struct attr *attr = path->attr;
d62a17ae 9961 int len;
9962 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9963 json_object *json_path = NULL;
9964
9965 if (use_json)
9966 json_path = json_object_new_object();
d62a17ae 9967
9968 /* short status lead text */
e5be8c1d 9969 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9970
9971 /* print prefix and mask */
9972 if (!use_json) {
9973 if (!display)
7d3cae70 9974 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9975 else
9976 vty_out(vty, "%*s", 17, " ");
d62a17ae 9977
e5be8c1d
DA
9978 len = vty_out(vty, "%s", path->peer->host);
9979 len = 17 - len;
9980
9981 if (len < 1)
d62a17ae 9982 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9983 else
9984 vty_out(vty, "%*s", len, " ");
d62a17ae 9985
9b6d8fcf
DS
9986 vty_out(vty, "%s ",
9987 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9988 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9989 use_json, NULL));
d62a17ae 9990
e5be8c1d 9991 if (attr->aspath)
05864da7 9992 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9993
05864da7
DS
9994 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9995
d62a17ae 9996 vty_out(vty, "\n");
e5be8c1d
DA
9997 } else {
9998 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9999 safi, use_json, json_path);
10000
10001 if (attr->aspath)
10002 json_object_string_add(json_path, "asPath",
10003 attr->aspath->str);
10004
10005 json_object_string_add(json_path, "origin",
10006 bgp_origin_str[attr->origin]);
10007 json_object_string_add(json_path, "peerHost", path->peer->host);
10008
10009 json_object_array_add(json_paths, json_path);
10010 }
d62a17ae 10011}
718e3744 10012
d62a17ae 10013/* flap route */
5f040085
DS
10014static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
10015 struct bgp_path_info *path, int display,
10016 afi_t afi, safi_t safi, bool use_json,
31258046 10017 json_object *json_paths)
784d3a42 10018{
31258046 10019 struct attr *attr = path->attr;
d62a17ae 10020 struct bgp_damp_info *bdi;
10021 char timebuf[BGP_UPTIME_LEN];
10022 int len;
31258046 10023 json_object *json_path = NULL;
784d3a42 10024
9b6d8fcf 10025 if (!path->extra)
d62a17ae 10026 return;
784d3a42 10027
31258046
DA
10028 if (use_json)
10029 json_path = json_object_new_object();
10030
9b6d8fcf 10031 bdi = path->extra->damp_info;
784d3a42 10032
d62a17ae 10033 /* short status lead text */
31258046 10034 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 10035
d62a17ae 10036 if (!use_json) {
10037 if (!display)
7d3cae70 10038 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 10039 else
10040 vty_out(vty, "%*s", 17, " ");
784d3a42 10041
31258046
DA
10042 len = vty_out(vty, "%s", path->peer->host);
10043 len = 16 - len;
10044 if (len < 1)
d62a17ae 10045 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 10046 else
10047 vty_out(vty, "%*s", len, " ");
784d3a42 10048
31258046
DA
10049 len = vty_out(vty, "%d", bdi->flap);
10050 len = 5 - len;
10051 if (len < 1)
d62a17ae 10052 vty_out(vty, " ");
d62a17ae 10053 else
10054 vty_out(vty, "%*s", len, " ");
d62a17ae 10055
996c9314
LB
10056 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10057 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 10058
31258046
DA
10059 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10060 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 10061 vty_out(vty, "%s ",
9b6d8fcf 10062 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 10063 BGP_UPTIME_LEN, afi,
31258046
DA
10064 safi, use_json, NULL));
10065 else
d62a17ae 10066 vty_out(vty, "%*s ", 8, " ");
d62a17ae 10067
31258046 10068 if (attr->aspath)
05864da7 10069 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 10070
05864da7
DS
10071 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10072
d62a17ae 10073 vty_out(vty, "\n");
31258046
DA
10074 } else {
10075 json_object_string_add(json_path, "peerHost", path->peer->host);
10076 json_object_int_add(json_path, "bdiFlap", bdi->flap);
10077
10078 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10079 json_path);
10080
10081 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10082 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10083 bgp_damp_reuse_time_vty(vty, path, timebuf,
10084 BGP_UPTIME_LEN, afi, safi,
10085 use_json, json_path);
10086
10087 if (attr->aspath)
10088 json_object_string_add(json_path, "asPath",
10089 attr->aspath->str);
10090
10091 json_object_string_add(json_path, "origin",
10092 bgp_origin_str[attr->origin]);
10093
10094 json_object_array_add(json_paths, json_path);
10095 }
d62a17ae 10096}
10097
10098static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10099 int *first, const char *header,
10100 json_object *json_adv_to)
10101{
d62a17ae 10102 json_object *json_peer = NULL;
10103
10104 if (json_adv_to) {
10105 /* 'advertised-to' is a dictionary of peers we have advertised
10106 * this
10107 * prefix too. The key is the peer's IP or swpX, the value is
10108 * the
10109 * hostname if we know it and "" if not.
10110 */
10111 json_peer = json_object_new_object();
10112
10113 if (peer->hostname)
10114 json_object_string_add(json_peer, "hostname",
10115 peer->hostname);
10116
10117 if (peer->conf_if)
10118 json_object_object_add(json_adv_to, peer->conf_if,
10119 json_peer);
10120 else
47e12884
DA
10121 json_object_object_addf(json_adv_to, json_peer, "%pSU",
10122 &peer->su);
d62a17ae 10123 } else {
10124 if (*first) {
10125 vty_out(vty, "%s", header);
10126 *first = 0;
10127 }
10128
10129 if (peer->hostname
892fedb6 10130 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 10131 if (peer->conf_if)
10132 vty_out(vty, " %s(%s)", peer->hostname,
10133 peer->conf_if);
10134 else
47e12884
DA
10135 vty_out(vty, " %s(%pSU)", peer->hostname,
10136 &peer->su);
d62a17ae 10137 } else {
10138 if (peer->conf_if)
10139 vty_out(vty, " %s", peer->conf_if);
10140 else
47e12884 10141 vty_out(vty, " %pSU", &peer->su);
d62a17ae 10142 }
10143 }
784d3a42
PG
10144}
10145
dcc68b5e
MS
10146static void route_vty_out_tx_ids(struct vty *vty,
10147 struct bgp_addpath_info_data *d)
10148{
10149 int i;
10150
10151 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10152 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10153 d->addpath_tx_id[i],
10154 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10155 }
10156}
10157
5e4d4c8a 10158static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
10159 struct bgp_path_info *pi,
10160 struct attr *attr,
10161 json_object *json_path)
5e4d4c8a
AK
10162{
10163 char esi_buf[ESI_STR_LEN];
10164 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10165 bool peer_router = !!CHECK_FLAG(attr->es_flags,
10166 ATTR_ES_PEER_ROUTER);
10167 bool peer_active = !!CHECK_FLAG(attr->es_flags,
10168 ATTR_ES_PEER_ACTIVE);
10169 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10170 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
10171 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10172 if (json_path) {
10173 json_object *json_es_info = NULL;
10174
10175 json_object_string_add(
10176 json_path, "esi",
10177 esi_buf);
10178 if (es_local || bgp_evpn_attr_is_sync(attr)) {
10179 json_es_info = json_object_new_object();
10180 if (es_local)
10181 json_object_boolean_true_add(
10182 json_es_info, "localEs");
10183 if (peer_active)
10184 json_object_boolean_true_add(
10185 json_es_info, "peerActive");
10186 if (peer_proxy)
10187 json_object_boolean_true_add(
10188 json_es_info, "peerProxy");
10189 if (peer_router)
10190 json_object_boolean_true_add(
10191 json_es_info, "peerRouter");
10192 if (attr->mm_sync_seqnum)
10193 json_object_int_add(
10194 json_es_info, "peerSeq",
10195 attr->mm_sync_seqnum);
10196 json_object_object_add(
10197 json_path, "es_info",
10198 json_es_info);
10199 }
10200 } else {
10201 if (bgp_evpn_attr_is_sync(attr))
10202 vty_out(vty,
10203 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10204 esi_buf,
10205 es_local ? "local-es":"",
10206 peer_proxy ? "proxy " : "",
10207 peer_active ? "active ":"",
10208 peer_router ? "router ":"",
10209 attr->mm_sync_seqnum);
10210 else
10211 vty_out(vty, " ESI %s %s\n",
10212 esi_buf,
10213 es_local ? "local-es":"");
10214 }
10215}
10216
4933eaaf 10217void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
34c7f35f
SW
10218 const struct prefix *p, struct bgp_path_info *path,
10219 afi_t afi, safi_t safi,
4027d19b
DS
10220 enum rpki_states rpki_curr_state,
10221 json_object *json_paths)
d62a17ae 10222{
10223 char buf[INET6_ADDRSTRLEN];
10224 char buf1[BUFSIZ];
100290e4 10225 char tag_buf[30];
515c2602 10226 struct attr *attr = path->attr;
d62a17ae 10227 time_t tbuf;
10228 json_object *json_bestpath = NULL;
10229 json_object *json_cluster_list = NULL;
10230 json_object *json_cluster_list_list = NULL;
10231 json_object *json_ext_community = NULL;
10232 json_object *json_last_update = NULL;
7fd077aa 10233 json_object *json_pmsi = NULL;
d62a17ae 10234 json_object *json_nexthop_global = NULL;
10235 json_object *json_nexthop_ll = NULL;
10236 json_object *json_nexthops = NULL;
10237 json_object *json_path = NULL;
10238 json_object *json_peer = NULL;
10239 json_object *json_string = NULL;
10240 json_object *json_adv_to = NULL;
10241 int first = 0;
10242 struct listnode *node, *nnode;
10243 struct peer *peer;
be92fc9f 10244 bool addpath_capable;
d62a17ae 10245 int has_adj;
10246 unsigned int first_as;
1defdda8 10247 bool nexthop_self =
9b6d8fcf 10248 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10249 int i;
2ba93fd6
DA
10250 char *nexthop_hostname =
10251 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10252 uint32_t ttl = 0;
10253 uint32_t bos = 0;
10254 uint32_t exp = 0;
10255 mpls_label_t label = MPLS_INVALID_LABEL;
100290e4 10256 tag_buf[0] = '\0';
d62a17ae 10257
10258 if (json_paths) {
10259 json_path = json_object_new_object();
10260 json_peer = json_object_new_object();
10261 json_nexthop_global = json_object_new_object();
10262 }
10263
8304dabf
AD
10264 if (safi == SAFI_EVPN) {
10265 if (!json_paths)
34c7f35f 10266 vty_out(vty, " Route %pFX", p);
8304dabf
AD
10267 }
10268
44c69747 10269 if (path->extra) {
9b6d8fcf
DS
10270 if (path->extra && path->extra->num_labels) {
10271 bgp_evpn_label2str(path->extra->label,
10272 path->extra->num_labels, tag_buf,
a4d82a8a 10273 sizeof(tag_buf));
d62a17ae 10274 }
d7325ee7 10275 if (safi == SAFI_EVPN) {
44c69747 10276 if (!json_paths) {
44c69747
LK
10277 if (tag_buf[0] != '\0')
10278 vty_out(vty, " VNI %s", tag_buf);
44c69747 10279 } else {
77a2f8e5 10280 if (tag_buf[0]) {
44c69747
LK
10281 json_object_string_add(json_path, "VNI",
10282 tag_buf);
77a2f8e5
DA
10283 json_object_string_add(json_path, "vni",
10284 tag_buf);
10285 }
44c69747 10286 }
d7325ee7 10287 }
d62a17ae 10288 }
d62a17ae 10289
8304dabf
AD
10290 if (safi == SAFI_EVPN
10291 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10292 char gwip_buf[INET6_ADDRSTRLEN];
10293
860e740b
IR
10294 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10295 sizeof(gwip_buf));
8304dabf
AD
10296
10297 if (json_paths)
10298 json_object_string_add(json_path, "gatewayIP",
10299 gwip_buf);
10300 else
10301 vty_out(vty, " Gateway IP %s", gwip_buf);
10302 }
10303
2bf9780b 10304 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10305 vty_out(vty, "\n");
10306
100290e4
SW
10307
10308 if (path->extra && path->extra->parent && !json_paths) {
10309 struct bgp_path_info *parent_ri;
10310 struct bgp_dest *dest, *pdest;
10311
10312 parent_ri = (struct bgp_path_info *)path->extra->parent;
10313 dest = parent_ri->net;
10314 if (dest && dest->pdest) {
10315 pdest = dest->pdest;
10316 if (is_pi_family_evpn(parent_ri)) {
10317 vty_out(vty,
10318 " Imported from %pRD:%pFX, VNI %s",
10319 (struct prefix_rd *)bgp_dest_get_prefix(
10320 pdest),
10321 (struct prefix_evpn *)
10322 bgp_dest_get_prefix(dest),
10323 tag_buf);
6012963e 10324 if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
100290e4 10325 vty_out(vty, ", L3NHG %s",
6012963e
SW
10326 CHECK_FLAG(
10327 attr->es_flags,
10328 ATTR_ES_L3_NHG_ACTIVE)
100290e4
SW
10329 ? "active"
10330 : "inactive");
10331 vty_out(vty, "\n");
10332
10333 } else
10334 vty_out(vty, " Imported from %pRD:%pFX\n",
10335 (struct prefix_rd *)bgp_dest_get_prefix(
10336 pdest),
10337 (struct prefix_evpn *)
10338 bgp_dest_get_prefix(dest));
10339 }
10340 }
10341
05864da7
DS
10342 /* Line1 display AS-path, Aggregator */
10343 if (attr->aspath) {
10344 if (json_paths) {
10345 if (!attr->aspath->json)
10346 aspath_str_update(attr->aspath, true);
10347 json_object_lock(attr->aspath->json);
10348 json_object_object_add(json_path, "aspath",
10349 attr->aspath->json);
10350 } else {
10351 if (attr->aspath->segments)
10352 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10353 else
05864da7 10354 vty_out(vty, " Local");
d62a17ae 10355 }
05864da7 10356 }
d62a17ae 10357
05864da7
DS
10358 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path, "removed");
10361 else
10362 vty_out(vty, ", (removed)");
10363 }
d62a17ae 10364
05864da7
DS
10365 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10366 if (json_paths)
10367 json_object_boolean_true_add(json_path, "stale");
10368 else
10369 vty_out(vty, ", (stale)");
10370 }
d62a17ae 10371
05864da7
DS
10372 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10373 if (json_paths) {
10374 json_object_int_add(json_path, "aggregatorAs",
10375 attr->aggregator_as);
c949c771
DA
10376 json_object_string_addf(json_path, "aggregatorId",
10377 "%pI4", &attr->aggregator_addr);
05864da7 10378 } else {
88d495a9
DA
10379 vty_out(vty, ", (aggregated by %u %pI4)",
10380 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10381 }
05864da7 10382 }
d62a17ae 10383
05864da7
DS
10384 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10385 PEER_FLAG_REFLECTOR_CLIENT)) {
10386 if (json_paths)
10387 json_object_boolean_true_add(json_path,
10388 "rxedFromRrClient");
10389 else
10390 vty_out(vty, ", (Received from a RR-client)");
10391 }
d62a17ae 10392
05864da7
DS
10393 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10394 PEER_FLAG_RSERVER_CLIENT)) {
10395 if (json_paths)
10396 json_object_boolean_true_add(json_path,
10397 "rxedFromRsClient");
10398 else
10399 vty_out(vty, ", (Received from a RS-client)");
10400 }
d62a17ae 10401
05864da7
DS
10402 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10403 if (json_paths)
10404 json_object_boolean_true_add(json_path,
10405 "dampeningHistoryEntry");
10406 else
10407 vty_out(vty, ", (history entry)");
10408 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10409 if (json_paths)
10410 json_object_boolean_true_add(json_path,
10411 "dampeningSuppressed");
10412 else
10413 vty_out(vty, ", (suppressed due to dampening)");
10414 }
d62a17ae 10415
05864da7
DS
10416 if (!json_paths)
10417 vty_out(vty, "\n");
d62a17ae 10418
05864da7
DS
10419 /* Line2 display Next-hop, Neighbor, Router-id */
10420 /* Display the nexthop */
b54892e0 10421
34c7f35f
SW
10422 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10423 p->family == AF_EVPN) &&
7226bc40
TA
10424 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10425 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10426 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10427 || safi == SAFI_EVPN) {
515c2602 10428 if (json_paths) {
c949c771
DA
10429 json_object_string_addf(
10430 json_nexthop_global, "ip", "%pI4",
10431 &attr->mp_nexthop_global_in);
515c2602 10432
939a97f4 10433 if (path->peer->hostname)
515c2602
DA
10434 json_object_string_add(
10435 json_nexthop_global, "hostname",
939a97f4 10436 path->peer->hostname);
aef999a2
DA
10437 } else {
10438 if (nexthop_hostname)
10439 vty_out(vty, " %pI4(%s)",
10440 &attr->mp_nexthop_global_in,
10441 nexthop_hostname);
10442 else
10443 vty_out(vty, " %pI4",
10444 &attr->mp_nexthop_global_in);
10445 }
d62a17ae 10446 } else {
515c2602 10447 if (json_paths) {
c949c771
DA
10448 json_object_string_addf(json_nexthop_global,
10449 "ip", "%pI4",
10450 &attr->nexthop);
515c2602 10451
939a97f4 10452 if (path->peer->hostname)
515c2602
DA
10453 json_object_string_add(
10454 json_nexthop_global, "hostname",
939a97f4 10455 path->peer->hostname);
aef999a2
DA
10456 } else {
10457 if (nexthop_hostname)
10458 vty_out(vty, " %pI4(%s)",
10459 &attr->nexthop,
10460 nexthop_hostname);
10461 else
10462 vty_out(vty, " %pI4",
10463 &attr->nexthop);
10464 }
d62a17ae 10465 }
10466
05864da7
DS
10467 if (json_paths)
10468 json_object_string_add(json_nexthop_global, "afi",
10469 "ipv4");
10470 } else {
10471 if (json_paths) {
c949c771
DA
10472 json_object_string_addf(json_nexthop_global, "ip",
10473 "%pI6",
10474 &attr->mp_nexthop_global);
515c2602 10475
939a97f4 10476 if (path->peer->hostname)
515c2602
DA
10477 json_object_string_add(json_nexthop_global,
10478 "hostname",
939a97f4 10479 path->peer->hostname);
515c2602 10480
05864da7
DS
10481 json_object_string_add(json_nexthop_global, "afi",
10482 "ipv6");
10483 json_object_string_add(json_nexthop_global, "scope",
10484 "global");
10485 } else {
aef999a2
DA
10486 if (nexthop_hostname)
10487 vty_out(vty, " %pI6(%s)",
10488 &attr->mp_nexthop_global,
10489 nexthop_hostname);
10490 else
10491 vty_out(vty, " %pI6",
10492 &attr->mp_nexthop_global);
d62a17ae 10493 }
05864da7 10494 }
d62a17ae 10495
05864da7
DS
10496 /* Display the IGP cost or 'inaccessible' */
10497 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10498 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10499
10500 if (json_paths) {
05864da7
DS
10501 json_object_boolean_false_add(json_nexthop_global,
10502 "accessible");
95ba22d5
DA
10503 json_object_boolean_add(json_nexthop_global,
10504 "importCheckEnabled", import);
10505 } else {
10506 vty_out(vty, " (inaccessible%s)",
10507 import ? ", import-check enabled" : "");
10508 }
05864da7
DS
10509 } else {
10510 if (path->extra && path->extra->igpmetric) {
d62a17ae 10511 if (json_paths)
05864da7
DS
10512 json_object_int_add(json_nexthop_global,
10513 "metric",
10514 path->extra->igpmetric);
d62a17ae 10515 else
05864da7
DS
10516 vty_out(vty, " (metric %u)",
10517 path->extra->igpmetric);
d62a17ae 10518 }
10519
05864da7 10520 /* IGP cost is 0, display this only for json */
d62a17ae 10521 else {
d62a17ae 10522 if (json_paths)
05864da7
DS
10523 json_object_int_add(json_nexthop_global,
10524 "metric", 0);
d62a17ae 10525 }
d62a17ae 10526
05864da7
DS
10527 if (json_paths)
10528 json_object_boolean_true_add(json_nexthop_global,
10529 "accessible");
10530 }
d62a17ae 10531
05864da7
DS
10532 /* Display peer "from" output */
10533 /* This path was originated locally */
10534 if (path->peer == bgp->peer_self) {
d62a17ae 10535
34c7f35f 10536 if (safi == SAFI_EVPN || (p->family == AF_INET &&
7226bc40 10537 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10538 if (json_paths)
05864da7
DS
10539 json_object_string_add(json_peer, "peerId",
10540 "0.0.0.0");
d62a17ae 10541 else
05864da7
DS
10542 vty_out(vty, " from 0.0.0.0 ");
10543 } else {
d62a17ae 10544 if (json_paths)
05864da7
DS
10545 json_object_string_add(json_peer, "peerId",
10546 "::");
d62a17ae 10547 else
05864da7 10548 vty_out(vty, " from :: ");
d62a17ae 10549 }
d62a17ae 10550
4e9a9863 10551 if (json_paths)
c949c771
DA
10552 json_object_string_addf(json_peer, "routerId", "%pI4",
10553 &bgp->router_id);
4e9a9863 10554 else
23d0a753 10555 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10556 }
d62a17ae 10557
05864da7
DS
10558 /* We RXed this path from one of our peers */
10559 else {
10560
10561 if (json_paths) {
47e12884
DA
10562 json_object_string_addf(json_peer, "peerId", "%pSU",
10563 &path->peer->su);
c949c771
DA
10564 json_object_string_addf(json_peer, "routerId", "%pI4",
10565 &path->peer->remote_id);
05864da7
DS
10566
10567 if (path->peer->hostname)
10568 json_object_string_add(json_peer, "hostname",
10569 path->peer->hostname);
10570
10571 if (path->peer->domainname)
10572 json_object_string_add(json_peer, "domainname",
10573 path->peer->domainname);
10574
10575 if (path->peer->conf_if)
10576 json_object_string_add(json_peer, "interface",
10577 path->peer->conf_if);
10578 } else {
10579 if (path->peer->conf_if) {
10580 if (path->peer->hostname
892fedb6
DA
10581 && CHECK_FLAG(path->peer->bgp->flags,
10582 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10583 vty_out(vty, " from %s(%s)",
10584 path->peer->hostname,
10585 path->peer->conf_if);
d62a17ae 10586 else
05864da7 10587 vty_out(vty, " from %s",
9b6d8fcf 10588 path->peer->conf_if);
d62a17ae 10589 } else {
05864da7 10590 if (path->peer->hostname
892fedb6
DA
10591 && CHECK_FLAG(path->peer->bgp->flags,
10592 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10593 vty_out(vty, " from %s(%s)",
10594 path->peer->hostname,
10595 path->peer->host);
d62a17ae 10596 else
47e12884
DA
10597 vty_out(vty, " from %pSU",
10598 &path->peer->su);
d62a17ae 10599 }
d62a17ae 10600
05864da7 10601 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10602 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10603 else
10604 vty_out(vty, " (%s)",
10605 inet_ntop(AF_INET,
10606 &path->peer->remote_id, buf1,
10607 sizeof(buf1)));
d62a17ae 10608 }
05864da7 10609 }
9df8b37c 10610
05864da7
DS
10611 /*
10612 * Note when vrfid of nexthop is different from that of prefix
10613 */
10614 if (path->extra && path->extra->bgp_orig) {
10615 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10616
05864da7
DS
10617 if (json_paths) {
10618 const char *vn;
9df8b37c 10619
05864da7
DS
10620 if (path->extra->bgp_orig->inst_type
10621 == BGP_INSTANCE_TYPE_DEFAULT)
10622 vn = VRF_DEFAULT_NAME;
10623 else
10624 vn = path->extra->bgp_orig->name;
9df8b37c 10625
05864da7 10626 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10627
05864da7
DS
10628 if (nexthop_vrfid == VRF_UNKNOWN) {
10629 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10630 } else {
05864da7
DS
10631 json_object_int_add(json_path, "nhVrfId",
10632 (int)nexthop_vrfid);
9df8b37c 10633 }
05864da7
DS
10634 } else {
10635 if (nexthop_vrfid == VRF_UNKNOWN)
10636 vty_out(vty, " vrf ?");
137147c6
DS
10637 else {
10638 struct vrf *vrf;
10639
10640 vrf = vrf_lookup_by_id(nexthop_vrfid);
10641 vty_out(vty, " vrf %s(%u)",
10642 VRF_LOGNAME(vrf), nexthop_vrfid);
10643 }
9df8b37c 10644 }
05864da7 10645 }
9df8b37c 10646
05864da7
DS
10647 if (nexthop_self) {
10648 if (json_paths) {
10649 json_object_boolean_true_add(json_path,
10650 "announceNexthopSelf");
10651 } else {
10652 vty_out(vty, " announce-nh-self");
9df8b37c 10653 }
05864da7 10654 }
9df8b37c 10655
05864da7
DS
10656 if (!json_paths)
10657 vty_out(vty, "\n");
d62a17ae 10658
05864da7
DS
10659 /* display the link-local nexthop */
10660 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10661 if (json_paths) {
10662 json_nexthop_ll = json_object_new_object();
c949c771
DA
10663 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10664 &attr->mp_nexthop_local);
515c2602 10665
939a97f4 10666 if (path->peer->hostname)
515c2602
DA
10667 json_object_string_add(json_nexthop_ll,
10668 "hostname",
939a97f4 10669 path->peer->hostname);
515c2602 10670
05864da7
DS
10671 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10672 json_object_string_add(json_nexthop_ll, "scope",
10673 "link-local");
d62a17ae 10674
05864da7
DS
10675 json_object_boolean_true_add(json_nexthop_ll,
10676 "accessible");
d62a17ae 10677
05864da7 10678 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10679 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10680 "used");
10681 else
10682 json_object_boolean_true_add(
10683 json_nexthop_global, "used");
10684 } else {
10685 vty_out(vty, " (%s) %s\n",
10686 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10687 buf, INET6_ADDRSTRLEN),
10688 attr->mp_nexthop_prefer_global
10689 ? "(prefer-global)"
10690 : "(used)");
d62a17ae 10691 }
05864da7
DS
10692 }
10693 /* If we do not have a link-local nexthop then we must flag the
10694 global as "used" */
10695 else {
10696 if (json_paths)
10697 json_object_boolean_true_add(json_nexthop_global,
10698 "used");
10699 }
d62a17ae 10700
b5e140c8 10701 if (safi == SAFI_EVPN &&
5e4d4c8a 10702 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10703 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10704 }
10705
05864da7
DS
10706 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10707 * Int/Ext/Local, Atomic, best */
10708 if (json_paths)
10709 json_object_string_add(json_path, "origin",
10710 bgp_origin_long_str[attr->origin]);
10711 else
10712 vty_out(vty, " Origin %s",
10713 bgp_origin_long_str[attr->origin]);
9df8b37c 10714
05864da7 10715 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10716 if (json_paths)
05864da7 10717 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10718 else
05864da7
DS
10719 vty_out(vty, ", metric %u", attr->med);
10720 }
9df8b37c 10721
05864da7
DS
10722 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10723 if (json_paths)
0fbac0b4 10724 json_object_int_add(json_path, "locPrf",
05864da7
DS
10725 attr->local_pref);
10726 else
10727 vty_out(vty, ", localpref %u", attr->local_pref);
10728 }
9df8b37c 10729
97a52c82
DA
10730 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10731 if (json_paths)
10732 json_object_int_add(json_path, "aigpMetric",
10733 bgp_attr_get_aigp_metric(attr));
10734 else
10735 vty_out(vty, ", aigp-metric %" PRIu64,
10736 bgp_attr_get_aigp_metric(attr));
10737 }
10738
05864da7
DS
10739 if (attr->weight != 0) {
10740 if (json_paths)
10741 json_object_int_add(json_path, "weight", attr->weight);
10742 else
10743 vty_out(vty, ", weight %u", attr->weight);
10744 }
9df8b37c 10745
05864da7
DS
10746 if (attr->tag != 0) {
10747 if (json_paths)
10748 json_object_int_add(json_path, "tag", attr->tag);
10749 else
10750 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10751 }
9df8b37c 10752
05864da7
DS
10753 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10754 if (json_paths)
10755 json_object_boolean_false_add(json_path, "valid");
10756 else
10757 vty_out(vty, ", invalid");
10758 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10759 if (json_paths)
10760 json_object_boolean_true_add(json_path, "valid");
10761 else
10762 vty_out(vty, ", valid");
10763 }
9df8b37c 10764
7d3cae70
DA
10765 if (json_paths)
10766 json_object_int_add(json_path, "version", bn->version);
10767
05864da7
DS
10768 if (path->peer != bgp->peer_self) {
10769 if (path->peer->as == path->peer->local_as) {
10770 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10771 if (json_paths)
10772 json_object_string_add(
10773 json_peer, "type",
10774 "confed-internal");
d62a17ae 10775 else
05864da7 10776 vty_out(vty, ", confed-internal");
d62a17ae 10777 } else {
05864da7
DS
10778 if (json_paths)
10779 json_object_string_add(
10780 json_peer, "type", "internal");
10781 else
10782 vty_out(vty, ", internal");
9df8b37c 10783 }
05864da7
DS
10784 } else {
10785 if (bgp_confederation_peers_check(bgp,
10786 path->peer->as)) {
10787 if (json_paths)
10788 json_object_string_add(
10789 json_peer, "type",
10790 "confed-external");
d62a17ae 10791 else
05864da7 10792 vty_out(vty, ", confed-external");
d62a17ae 10793 } else {
05864da7
DS
10794 if (json_paths)
10795 json_object_string_add(
10796 json_peer, "type", "external");
10797 else
10798 vty_out(vty, ", external");
d62a17ae 10799 }
10800 }
05864da7
DS
10801 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10802 if (json_paths) {
10803 json_object_boolean_true_add(json_path, "aggregated");
10804 json_object_boolean_true_add(json_path, "local");
10805 } else {
10806 vty_out(vty, ", aggregated, local");
10807 }
10808 } else if (path->type != ZEBRA_ROUTE_BGP) {
10809 if (json_paths)
10810 json_object_boolean_true_add(json_path, "sourced");
10811 else
10812 vty_out(vty, ", sourced");
10813 } else {
10814 if (json_paths) {
10815 json_object_boolean_true_add(json_path, "sourced");
10816 json_object_boolean_true_add(json_path, "local");
10817 } else {
10818 vty_out(vty, ", sourced, local");
d62a17ae 10819 }
05864da7 10820 }
718e3744 10821
05864da7 10822 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10823 if (json_paths)
05864da7
DS
10824 json_object_boolean_true_add(json_path,
10825 "atomicAggregate");
d62a17ae 10826 else
05864da7
DS
10827 vty_out(vty, ", atomic-aggregate");
10828 }
d62a17ae 10829
d864dd9e
EB
10830 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10831 if (json_paths)
10832 json_object_int_add(json_path, "otc", attr->otc);
10833 else
10834 vty_out(vty, ", otc %u", attr->otc);
10835 }
10836
05864da7
DS
10837 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10838 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10839 && bgp_path_info_mpath_count(path))) {
10840 if (json_paths)
10841 json_object_boolean_true_add(json_path, "multipath");
10842 else
10843 vty_out(vty, ", multipath");
10844 }
50e05855 10845
05864da7
DS
10846 // Mark the bestpath(s)
10847 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10848 first_as = aspath_get_first_as(attr->aspath);
718e3744 10849
05864da7
DS
10850 if (json_paths) {
10851 if (!json_bestpath)
10852 json_bestpath = json_object_new_object();
10853 json_object_int_add(json_bestpath, "bestpathFromAs",
10854 first_as);
10855 } else {
10856 if (first_as)
10857 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10858 else
05864da7 10859 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10860 }
05864da7 10861 }
718e3744 10862
05864da7
DS
10863 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10864 if (json_paths) {
10865 if (!json_bestpath)
10866 json_bestpath = json_object_new_object();
10867 json_object_boolean_true_add(json_bestpath, "overall");
10868 json_object_string_add(
10869 json_bestpath, "selectionReason",
10870 bgp_path_selection_reason2str(bn->reason));
10871 } else {
10872 vty_out(vty, ", best");
10873 vty_out(vty, " (%s)",
10874 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10875 }
05864da7 10876 }
718e3744 10877
4027d19b 10878 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10879 if (json_paths)
10880 json_object_string_add(
10881 json_path, "rpkiValidationState",
4027d19b 10882 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10883 else
1d327209 10884 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10885 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10886 }
10887
05864da7
DS
10888 if (json_bestpath)
10889 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10890
05864da7
DS
10891 if (!json_paths)
10892 vty_out(vty, "\n");
10893
10894 /* Line 4 display Community */
29e72930 10895 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10896 if (json_paths) {
9a706b42
DA
10897 if (!bgp_attr_get_community(attr)->json)
10898 community_str(bgp_attr_get_community(attr),
c0945b78 10899 true, true);
9a706b42
DA
10900 json_object_lock(bgp_attr_get_community(attr)->json);
10901 json_object_object_add(
10902 json_path, "community",
10903 bgp_attr_get_community(attr)->json);
05864da7
DS
10904 } else {
10905 vty_out(vty, " Community: %s\n",
9a706b42 10906 bgp_attr_get_community(attr)->str);
d62a17ae 10907 }
05864da7 10908 }
718e3744 10909
05864da7
DS
10910 /* Line 5 display Extended-community */
10911 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10912 if (json_paths) {
10913 json_ext_community = json_object_new_object();
b53e67a3
DA
10914 json_object_string_add(
10915 json_ext_community, "string",
10916 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10917 json_object_object_add(json_path, "extendedCommunity",
10918 json_ext_community);
d62a17ae 10919 } else {
05864da7 10920 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10921 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10922 }
05864da7 10923 }
718e3744 10924
05864da7
DS
10925 /* Line 6 display Large community */
10926 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10927 if (json_paths) {
1bcf3a96
DA
10928 if (!bgp_attr_get_lcommunity(attr)->json)
10929 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10930 true, true);
1bcf3a96
DA
10931 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10932 json_object_object_add(
10933 json_path, "largeCommunity",
10934 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10935 } else {
10936 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10937 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10938 }
05864da7 10939 }
718e3744 10940
05864da7
DS
10941 /* Line 7 display Originator, Cluster-id */
10942 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10943 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10944 char buf[BUFSIZ] = {0};
10945
05864da7 10946 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10947 if (json_paths)
c949c771
DA
10948 json_object_string_addf(json_path,
10949 "originatorId", "%pI4",
10950 &attr->originator_id);
d62a17ae 10951 else
23d0a753
DA
10952 vty_out(vty, " Originator: %pI4",
10953 &attr->originator_id);
d62a17ae 10954 }
856ca177 10955
05864da7 10956 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10957 struct cluster_list *cluster =
10958 bgp_attr_get_cluster(attr);
05864da7 10959 int i;
d62a17ae 10960
10961 if (json_paths) {
05864da7
DS
10962 json_cluster_list = json_object_new_object();
10963 json_cluster_list_list =
10964 json_object_new_array();
10965
779fee93 10966 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10967 json_string = json_object_new_string(
779fee93
DS
10968 inet_ntop(AF_INET,
10969 &cluster->list[i],
10970 buf, sizeof(buf)));
05864da7
DS
10971 json_object_array_add(
10972 json_cluster_list_list,
10973 json_string);
10974 }
718e3744 10975
05864da7
DS
10976 /*
10977 * struct cluster_list does not have
10978 * "str" variable like aspath and community
10979 * do. Add this someday if someone asks
10980 * for it.
10981 * json_object_string_add(json_cluster_list,
779fee93 10982 * "string", cluster->str);
05864da7
DS
10983 */
10984 json_object_object_add(json_cluster_list,
10985 "list",
10986 json_cluster_list_list);
10987 json_object_object_add(json_path, "clusterList",
10988 json_cluster_list);
0dc8ee70 10989 } else {
05864da7
DS
10990 vty_out(vty, ", Cluster list: ");
10991
779fee93 10992 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10993 vty_out(vty, "%pI4 ",
779fee93 10994 &cluster->list[i]);
05864da7 10995 }
0dc8ee70 10996 }
d62a17ae 10997 }
718e3744 10998
d62a17ae 10999 if (!json_paths)
11000 vty_out(vty, "\n");
05864da7 11001 }
d62a17ae 11002
05864da7 11003 if (path->extra && path->extra->damp_info)
b4f7f45b 11004 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 11005
05864da7
DS
11006 /* Remote Label */
11007 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
11008 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
11009 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
11010 &bos);
d62a17ae 11011
05864da7
DS
11012 if (json_paths)
11013 json_object_int_add(json_path, "remoteLabel", label);
11014 else
11015 vty_out(vty, " Remote label: %d\n", label);
11016 }
d62a17ae 11017
e496b420
HS
11018 /* Remote SID */
11019 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 11020 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
11021 if (json_paths)
11022 json_object_string_add(json_path, "remoteSid", buf);
11023 else
11024 vty_out(vty, " Remote SID: %s\n", buf);
11025 }
11026
05864da7
DS
11027 /* Label Index */
11028 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
11029 if (json_paths)
11030 json_object_int_add(json_path, "labelIndex",
11031 attr->label_index);
11032 else
11033 vty_out(vty, " Label Index: %d\n",
11034 attr->label_index);
11035 }
d62a17ae 11036
05864da7
DS
11037 /* Line 8 display Addpath IDs */
11038 if (path->addpath_rx_id
11039 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
11040 if (json_paths) {
11041 json_object_int_add(json_path, "addpathRxId",
11042 path->addpath_rx_id);
d62a17ae 11043
05864da7
DS
11044 /* Keep backwards compatibility with the old API
11045 * by putting TX All's ID in the old field
11046 */
11047 json_object_int_add(
11048 json_path, "addpathTxId",
11049 path->tx_addpath
11050 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 11051
05864da7
DS
11052 /* ... but create a specific field for each
11053 * strategy
11054 */
11055 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
11056 json_object_int_add(
11057 json_path,
11058 bgp_addpath_names(i)->id_json_name,
11059 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 11060 }
05864da7
DS
11061 } else {
11062 vty_out(vty, " AddPath ID: RX %u, ",
11063 path->addpath_rx_id);
d62a17ae 11064
05864da7 11065 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 11066 }
05864da7 11067 }
520d5d76 11068
05864da7
DS
11069 /* If we used addpath to TX a non-bestpath we need to display
11070 * "Advertised to" on a path-by-path basis
11071 */
11072 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11073 first = 1;
dcc68b5e 11074
05864da7
DS
11075 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11076 addpath_capable =
11077 bgp_addpath_encode_tx(peer, afi, safi);
11078 has_adj = bgp_adj_out_lookup(
11079 peer, path->net,
11080 bgp_addpath_id_for_peer(peer, afi, safi,
11081 &path->tx_addpath));
11082
11083 if ((addpath_capable && has_adj)
11084 || (!addpath_capable && has_adj
11085 && CHECK_FLAG(path->flags,
11086 BGP_PATH_SELECTED))) {
11087 if (json_path && !json_adv_to)
11088 json_adv_to = json_object_new_object();
dcc68b5e 11089
05864da7
DS
11090 route_vty_out_advertised_to(
11091 vty, peer, &first,
11092 " Advertised to:", json_adv_to);
d62a17ae 11093 }
11094 }
718e3744 11095
05864da7
DS
11096 if (json_path) {
11097 if (json_adv_to) {
11098 json_object_object_add(
11099 json_path, "advertisedTo", json_adv_to);
d62a17ae 11100 }
05864da7
DS
11101 } else {
11102 if (!first) {
11103 vty_out(vty, "\n");
d62a17ae 11104 }
11105 }
05864da7 11106 }
b05a1c8b 11107
05864da7 11108 /* Line 9 display Uptime */
083ec940 11109 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
11110 if (json_paths) {
11111 json_last_update = json_object_new_object();
11112 json_object_int_add(json_last_update, "epoch", tbuf);
11113 json_object_string_add(json_last_update, "string",
11114 ctime(&tbuf));
11115 json_object_object_add(json_path, "lastUpdate",
11116 json_last_update);
11117 } else
11118 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 11119
05864da7
DS
11120 /* Line 10 display PMSI tunnel attribute, if present */
11121 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
11122 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11123 bgp_attr_get_pmsi_tnl_type(attr),
11124 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 11125
05864da7
DS
11126 if (json_paths) {
11127 json_pmsi = json_object_new_object();
11128 json_object_string_add(json_pmsi, "tunnelType", str);
11129 json_object_int_add(json_pmsi, "label",
11130 label2vni(&attr->label));
11131 json_object_object_add(json_path, "pmsi", json_pmsi);
11132 } else
11133 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11134 str, label2vni(&attr->label));
d62a17ae 11135 }
f1aa5d8a 11136
848e8cf6
DA
11137 if (path->peer->t_gr_restart &&
11138 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11139 unsigned long gr_remaining =
11140 thread_timer_remain_second(path->peer->t_gr_restart);
11141
11142 if (json_paths) {
11143 json_object_int_add(json_path,
11144 "gracefulRestartSecondsRemaining",
11145 gr_remaining);
11146 } else
11147 vty_out(vty,
11148 " Time until Graceful Restart stale route deleted: %lu\n",
11149 gr_remaining);
11150 }
11151
9a706b42
DA
11152 if (path->peer->t_llgr_stale[afi][safi] &&
11153 bgp_attr_get_community(attr) &&
11154 community_include(bgp_attr_get_community(attr),
11155 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
11156 unsigned long llgr_remaining = thread_timer_remain_second(
11157 path->peer->t_llgr_stale[afi][safi]);
d92646a4 11158
48ebba04
DA
11159 if (json_paths) {
11160 json_object_int_add(json_path, "llgrSecondsRemaining",
11161 llgr_remaining);
11162 } else
11163 vty_out(vty,
11164 " Time until Long-lived stale route deleted: %lu\n",
11165 llgr_remaining);
11166 }
11167
92269aa2
DS
11168 /* Output some debug about internal state of the dest flags */
11169 if (json_paths) {
11170 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11171 json_object_boolean_true_add(json_path, "processScheduled");
11172 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11173 json_object_boolean_true_add(json_path, "userCleared");
11174 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11175 json_object_boolean_true_add(json_path, "labelChanged");
11176 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11177 json_object_boolean_true_add(json_path, "registeredForLabel");
11178 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11179 json_object_boolean_true_add(json_path, "selectDefered");
11180 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11181 json_object_boolean_true_add(json_path, "fibInstalled");
11182 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11183 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 11184
d62a17ae 11185 if (json_nexthop_global || json_nexthop_ll) {
11186 json_nexthops = json_object_new_array();
f1aa5d8a 11187
d62a17ae 11188 if (json_nexthop_global)
11189 json_object_array_add(json_nexthops,
11190 json_nexthop_global);
f1aa5d8a 11191
d62a17ae 11192 if (json_nexthop_ll)
11193 json_object_array_add(json_nexthops,
11194 json_nexthop_ll);
f1aa5d8a 11195
d62a17ae 11196 json_object_object_add(json_path, "nexthops",
11197 json_nexthops);
11198 }
11199
11200 json_object_object_add(json_path, "peer", json_peer);
11201 json_object_array_add(json_paths, json_path);
05864da7 11202 }
b366b518
BB
11203}
11204
96ade3ed 11205#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
11206#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11207#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 11208
a4d82a8a 11209static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11210 afi_t afi, safi_t safi, enum bgp_show_type type,
11211 bool use_json);
7f323236
DW
11212static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11213 const char *comstr, int exact, afi_t afi,
96c81f66 11214 safi_t safi, uint16_t show_flags);
d62a17ae 11215
1ae44dfc 11216static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11217 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11218 void *output_arg, const char *rd, int is_last,
96f3485c 11219 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11220 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11221 enum rpki_states rpki_target_state)
d62a17ae 11222{
40381db7 11223 struct bgp_path_info *pi;
9bcb3eef 11224 struct bgp_dest *dest;
2aad8c42
MS
11225 bool header = true;
11226 bool json_detail_header = false;
d62a17ae 11227 int display;
1ae44dfc
LB
11228 unsigned long output_count = 0;
11229 unsigned long total_count = 0;
d62a17ae 11230 struct prefix *p;
d62a17ae 11231 json_object *json_paths = NULL;
11232 int first = 1;
96f3485c
MK
11233 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11234 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11235 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11236
1ae44dfc 11237 if (output_cum && *output_cum != 0)
2aad8c42 11238 header = false;
1ae44dfc 11239
9386b588 11240 if (use_json && !*json_header_depth) {
96f3485c
MK
11241 if (all)
11242 *json_header_depth = 1;
11243 else {
11244 vty_out(vty, "{\n");
11245 *json_header_depth = 2;
11246 }
11247
d62a17ae 11248 vty_out(vty,
23d0a753
DA
11249 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11250 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11251 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11252 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11253 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11254 ? VRF_DEFAULT_NAME
11255 : bgp->name,
11256 table->version, &bgp->router_id,
01eced22 11257 bgp->default_local_pref, bgp->as);
9386b588 11258 if (rd) {
445c2480 11259 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11260 ++*json_header_depth;
11261 }
d62a17ae 11262 }
718e3744 11263
445c2480
DS
11264 if (use_json && rd) {
11265 vty_out(vty, " \"%s\" : { ", rd);
11266 }
11267
2aad8c42
MS
11268 /* Check for 'json detail', where we need header output once per dest */
11269 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11270 type != bgp_show_type_dampend_paths &&
11271 type != bgp_show_type_damp_neighbor &&
11272 type != bgp_show_type_flap_statistics &&
11273 type != bgp_show_type_flap_neighbor)
11274 json_detail_header = true;
11275
d62a17ae 11276 /* Start processing of routes. */
9bcb3eef
DS
11277 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11278 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11279 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11280 bool json_detail = json_detail_header;
b54892e0 11281
9bcb3eef 11282 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11283 if (pi == NULL)
98ce9a06 11284 continue;
d62a17ae 11285
98ce9a06 11286 display = 0;
98ce9a06
DS
11287 if (use_json)
11288 json_paths = json_object_new_array();
11289 else
11290 json_paths = NULL;
d62a17ae 11291
6f94b685 11292 for (; pi; pi = pi->next) {
9a706b42
DA
11293 struct community *picomm = NULL;
11294
11295 picomm = bgp_attr_get_community(pi->attr);
11296
98ce9a06 11297 total_count++;
1e2ce4f1 11298
7d3cae70
DA
11299 if (type == bgp_show_type_prefix_version) {
11300 uint32_t version =
11301 strtoul(output_arg, NULL, 10);
11302 if (dest->version < version)
11303 continue;
11304 }
11305
a70a28a5
DA
11306 if (type == bgp_show_type_community_alias) {
11307 char *alias = output_arg;
11308 char **communities;
11309 int num;
11310 bool found = false;
11311
9a706b42
DA
11312 if (picomm) {
11313 frrstr_split(picomm->str, " ",
11314 &communities, &num);
a70a28a5
DA
11315 for (int i = 0; i < num; i++) {
11316 const char *com2alias =
11317 bgp_community2alias(
11318 communities[i]);
cd9cc0e6
IR
11319 if (!found
11320 && strcmp(alias, com2alias)
11321 == 0)
a70a28a5 11322 found = true;
cd9cc0e6
IR
11323 XFREE(MTYPE_TMP,
11324 communities[i]);
a70a28a5 11325 }
cd9cc0e6 11326 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11327 }
11328
1bcf3a96
DA
11329 if (!found &&
11330 bgp_attr_get_lcommunity(pi->attr)) {
11331 frrstr_split(bgp_attr_get_lcommunity(
11332 pi->attr)
11333 ->str,
a70a28a5
DA
11334 " ", &communities, &num);
11335 for (int i = 0; i < num; i++) {
11336 const char *com2alias =
11337 bgp_community2alias(
11338 communities[i]);
cd9cc0e6
IR
11339 if (!found
11340 && strcmp(alias, com2alias)
11341 == 0)
a70a28a5 11342 found = true;
cd9cc0e6
IR
11343 XFREE(MTYPE_TMP,
11344 communities[i]);
a70a28a5 11345 }
cd9cc0e6 11346 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11347 }
11348
11349 if (!found)
11350 continue;
11351 }
11352
1e2ce4f1
DS
11353 if (type == bgp_show_type_rpki) {
11354 if (dest_p->family == AF_INET
11355 || dest_p->family == AF_INET6)
4027d19b 11356 rpki_curr_state = hook_call(
1e2ce4f1
DS
11357 bgp_rpki_prefix_status,
11358 pi->peer, pi->attr, dest_p);
4027d19b
DS
11359 if (rpki_target_state != RPKI_NOT_BEING_USED
11360 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11361 continue;
11362 }
11363
98ce9a06
DS
11364 if (type == bgp_show_type_flap_statistics
11365 || type == bgp_show_type_flap_neighbor
11366 || type == bgp_show_type_dampend_paths
11367 || type == bgp_show_type_damp_neighbor) {
40381db7 11368 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11369 continue;
11370 }
11371 if (type == bgp_show_type_regexp) {
11372 regex_t *regex = output_arg;
d62a17ae 11373
40381db7 11374 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11375 == REG_NOMATCH)
11376 continue;
11377 }
11378 if (type == bgp_show_type_prefix_list) {
11379 struct prefix_list *plist = output_arg;
d62a17ae 11380
9bcb3eef 11381 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11382 != PREFIX_PERMIT)
11383 continue;
11384 }
ed126382
DA
11385 if (type == bgp_show_type_access_list) {
11386 struct access_list *alist = output_arg;
11387
11388 if (access_list_apply(alist, dest_p) !=
11389 FILTER_PERMIT)
11390 continue;
11391 }
98ce9a06
DS
11392 if (type == bgp_show_type_filter_list) {
11393 struct as_list *as_list = output_arg;
d62a17ae 11394
40381db7 11395 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11396 != AS_FILTER_PERMIT)
11397 continue;
11398 }
11399 if (type == bgp_show_type_route_map) {
11400 struct route_map *rmap = output_arg;
9b6d8fcf 11401 struct bgp_path_info path;
636632c3
DA
11402 struct bgp_path_info_extra extra;
11403 struct attr dummy_attr = {};
b68885f9 11404 route_map_result_t ret;
d62a17ae 11405
6f4f49b2 11406 dummy_attr = *pi->attr;
d62a17ae 11407
636632c3
DA
11408 prep_for_rmap_apply(&path, &extra, dest, pi,
11409 pi->peer, &dummy_attr);
d62a17ae 11410
1782514f 11411 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11412 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11413 if (ret == RMAP_DENYMATCH)
11414 continue;
11415 }
11416 if (type == bgp_show_type_neighbor
11417 || type == bgp_show_type_flap_neighbor
11418 || type == bgp_show_type_damp_neighbor) {
11419 union sockunion *su = output_arg;
11420
40381db7
DS
11421 if (pi->peer == NULL
11422 || pi->peer->su_remote == NULL
11423 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11424 continue;
11425 }
11426 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11427 uint32_t destination;
d62a17ae 11428
9bcb3eef 11429 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11430 if (IN_CLASSC(destination)
9bcb3eef 11431 && dest_p->prefixlen == 24)
98ce9a06
DS
11432 continue;
11433 if (IN_CLASSB(destination)
9bcb3eef 11434 && dest_p->prefixlen == 16)
98ce9a06
DS
11435 continue;
11436 if (IN_CLASSA(destination)
9bcb3eef 11437 && dest_p->prefixlen == 8)
98ce9a06
DS
11438 continue;
11439 }
11440 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11441 p = output_arg;
9bcb3eef 11442 if (!prefix_match(p, dest_p))
98ce9a06
DS
11443 continue;
11444 }
11445 if (type == bgp_show_type_community_all) {
9a706b42 11446 if (!picomm)
98ce9a06
DS
11447 continue;
11448 }
11449 if (type == bgp_show_type_community) {
11450 struct community *com = output_arg;
d62a17ae 11451
9a706b42 11452 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11453 continue;
11454 }
11455 if (type == bgp_show_type_community_exact) {
11456 struct community *com = output_arg;
d62a17ae 11457
9a706b42 11458 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11459 continue;
11460 }
11461 if (type == bgp_show_type_community_list) {
11462 struct community_list *list = output_arg;
d62a17ae 11463
9a706b42 11464 if (!community_list_match(picomm, list))
98ce9a06
DS
11465 continue;
11466 }
a4d82a8a 11467 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11468 struct community_list *list = output_arg;
d62a17ae 11469
9a706b42 11470 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11471 continue;
11472 }
11473 if (type == bgp_show_type_lcommunity) {
11474 struct lcommunity *lcom = output_arg;
d62a17ae 11475
1bcf3a96
DA
11476 if (!bgp_attr_get_lcommunity(pi->attr) ||
11477 !lcommunity_match(
11478 bgp_attr_get_lcommunity(pi->attr),
11479 lcom))
98ce9a06
DS
11480 continue;
11481 }
36a206db 11482
11483 if (type == bgp_show_type_lcommunity_exact) {
11484 struct lcommunity *lcom = output_arg;
11485
1bcf3a96
DA
11486 if (!bgp_attr_get_lcommunity(pi->attr) ||
11487 !lcommunity_cmp(
11488 bgp_attr_get_lcommunity(pi->attr),
11489 lcom))
36a206db 11490 continue;
11491 }
98ce9a06
DS
11492 if (type == bgp_show_type_lcommunity_list) {
11493 struct community_list *list = output_arg;
d62a17ae 11494
1bcf3a96
DA
11495 if (!lcommunity_list_match(
11496 bgp_attr_get_lcommunity(pi->attr),
11497 list))
98ce9a06
DS
11498 continue;
11499 }
36a206db 11500 if (type
11501 == bgp_show_type_lcommunity_list_exact) {
11502 struct community_list *list = output_arg;
11503
11504 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11505 bgp_attr_get_lcommunity(pi->attr),
11506 list))
36a206db 11507 continue;
11508 }
98ce9a06 11509 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11510 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11511 continue;
11512 }
11513 if (type == bgp_show_type_dampend_paths
11514 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11515 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11516 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11517 continue;
11518 }
11519
11520 if (!use_json && header) {
23d0a753
DA
11521 vty_out(vty,
11522 "BGP table version is %" PRIu64
11523 ", local router ID is %pI4, vrf id ",
11524 table->version, &bgp->router_id);
9df8b37c
PZ
11525 if (bgp->vrf_id == VRF_UNKNOWN)
11526 vty_out(vty, "%s", VRFID_NONE_STR);
11527 else
11528 vty_out(vty, "%u", bgp->vrf_id);
11529 vty_out(vty, "\n");
01eced22
AD
11530 vty_out(vty, "Default local pref %u, ",
11531 bgp->default_local_pref);
11532 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11533 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11534 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11535 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11536 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11537 if (type == bgp_show_type_dampend_paths
11538 || type == bgp_show_type_damp_neighbor)
98ce9a06 11539 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11540 else if (type == bgp_show_type_flap_statistics
11541 || type == bgp_show_type_flap_neighbor)
98ce9a06 11542 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11543 else
ae248832
MK
11544 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11545 : BGP_SHOW_HEADER));
2aad8c42
MS
11546 header = false;
11547
11548 } else if (json_detail && json_paths != NULL) {
11549 const struct prefix_rd *prd;
11550 json_object *jtemp;
11551
11552 /* Use common detail header, for most types;
11553 * need a json 'object'.
11554 */
11555
11556 jtemp = json_object_new_object();
11557 prd = bgp_rd_from_dest(dest, safi);
11558
11559 route_vty_out_detail_header(
34c7f35f
SW
11560 vty, bgp, dest,
11561 bgp_dest_get_prefix(dest), prd,
11562 table->afi, safi, jtemp);
2aad8c42
MS
11563
11564 json_object_array_add(json_paths, jtemp);
11565
11566 json_detail = false;
d62a17ae 11567 }
2aad8c42 11568
98ce9a06
DS
11569 if (rd != NULL && !display && !output_count) {
11570 if (!use_json)
11571 vty_out(vty,
11572 "Route Distinguisher: %s\n",
11573 rd);
d62a17ae 11574 }
98ce9a06
DS
11575 if (type == bgp_show_type_dampend_paths
11576 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11577 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11578 AFI_IP, safi, use_json,
11579 json_paths);
98ce9a06
DS
11580 else if (type == bgp_show_type_flap_statistics
11581 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11582 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11583 AFI_IP, safi, use_json,
11584 json_paths);
f280c93b
DA
11585 else {
11586 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11587 route_vty_out_detail(
34c7f35f
SW
11588 vty, bgp, dest,
11589 bgp_dest_get_prefix(dest), pi,
f280c93b
DA
11590 family2afi(dest_p->family),
11591 safi, RPKI_NOT_BEING_USED,
11592 json_paths);
11593 else
11594 route_vty_out(vty, dest_p, pi, display,
11595 safi, json_paths, wide);
11596 }
98ce9a06 11597 display++;
d62a17ae 11598 }
11599
98ce9a06
DS
11600 if (display) {
11601 output_count++;
11602 if (!use_json)
11603 continue;
11604
625d2931 11605 /* encode prefix */
9bcb3eef 11606 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11607 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11608
1840384b 11609
b54892e0
DS
11610 bgp_fs_nlri_get_string(
11611 (unsigned char *)
9bcb3eef
DS
11612 dest_p->u.prefix_flowspec.ptr,
11613 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11614 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11615 family2afi(dest_p->u
11616 .prefix_flowspec.family));
625d2931 11617 if (first)
b54892e0 11618 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11619 dest_p->u.prefix_flowspec
b54892e0 11620 .prefixlen);
625d2931 11621 else
b54892e0 11622 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11623 dest_p->u.prefix_flowspec
b54892e0 11624 .prefixlen);
625d2931 11625 } else {
625d2931 11626 if (first)
1b78780b 11627 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11628 else
1b78780b 11629 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11630 }
3757f964 11631 vty_json(vty, json_paths);
449feb8e 11632 json_paths = NULL;
98ce9a06 11633 first = 0;
1f83ed02
DS
11634 } else
11635 json_object_free(json_paths);
98ce9a06
DS
11636 }
11637
1ae44dfc
LB
11638 if (output_cum) {
11639 output_count += *output_cum;
11640 *output_cum = output_count;
11641 }
11642 if (total_cum) {
11643 total_count += *total_cum;
11644 *total_cum = total_count;
11645 }
d62a17ae 11646 if (use_json) {
9386b588 11647 if (rd) {
a4d82a8a 11648 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11649 }
11650 if (is_last) {
a4d82a8a
PZ
11651 unsigned long i;
11652 for (i = 0; i < *json_header_depth; ++i)
11653 vty_out(vty, " } ");
96f3485c
MK
11654 if (!all)
11655 vty_out(vty, "\n");
9386b588 11656 }
d62a17ae 11657 } else {
1ae44dfc
LB
11658 if (is_last) {
11659 /* No route is displayed */
11660 if (output_count == 0) {
11661 if (type == bgp_show_type_normal)
11662 vty_out(vty,
11663 "No BGP prefixes displayed, %ld exist\n",
11664 total_count);
11665 } else
d62a17ae 11666 vty_out(vty,
1ae44dfc
LB
11667 "\nDisplayed %ld routes and %ld total paths\n",
11668 output_count, total_count);
11669 }
d62a17ae 11670 }
718e3744 11671
d62a17ae 11672 return CMD_SUCCESS;
718e3744 11673}
11674
1ae44dfc
LB
11675int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11676 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11677 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11678{
9bcb3eef 11679 struct bgp_dest *dest, *next;
1ae44dfc
LB
11680 unsigned long output_cum = 0;
11681 unsigned long total_cum = 0;
9386b588 11682 unsigned long json_header_depth = 0;
67009e22 11683 struct bgp_table *itable;
0136788c 11684 bool show_msg;
96c81f66 11685 uint16_t show_flags = 0;
0136788c
LB
11686
11687 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11688
96f3485c
MK
11689 if (use_json)
11690 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11691
9bcb3eef
DS
11692 for (dest = bgp_table_top(table); dest; dest = next) {
11693 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11694
9bcb3eef
DS
11695 next = bgp_route_next(dest);
11696 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11697 continue;
67009e22 11698
9bcb3eef 11699 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11700 if (itable != NULL) {
1ae44dfc 11701 struct prefix_rd prd;
06b9f471 11702 char rd[RD_ADDRSTRLEN];
1ae44dfc 11703
9bcb3eef 11704 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11705 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11706 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11707 rd, next == NULL, &output_cum,
11708 &total_cum, &json_header_depth,
1e2ce4f1 11709 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11710 if (next == NULL)
11711 show_msg = false;
1ae44dfc
LB
11712 }
11713 }
0136788c
LB
11714 if (show_msg) {
11715 if (output_cum == 0)
11716 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11717 total_cum);
11718 else
11719 vty_out(vty,
11720 "\nDisplayed %ld routes and %ld total paths\n",
11721 output_cum, total_cum);
11722 }
1ae44dfc
LB
11723 return CMD_SUCCESS;
11724}
2aad8c42 11725
d62a17ae 11726static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11727 enum bgp_show_type type, void *output_arg,
96c81f66 11728 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11729{
d62a17ae 11730 struct bgp_table *table;
9386b588 11731 unsigned long json_header_depth = 0;
96f3485c 11732 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11733
d62a17ae 11734 if (bgp == NULL) {
11735 bgp = bgp_get_default();
11736 }
fee0f4c6 11737
d62a17ae 11738 if (bgp == NULL) {
11739 if (!use_json)
11740 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11741 else
11742 vty_out(vty, "{}\n");
d62a17ae 11743 return CMD_WARNING;
11744 }
4dd6177e 11745
cd8c2a27
MS
11746 /* Labeled-unicast routes live in the unicast table. */
11747 if (safi == SAFI_LABELED_UNICAST)
11748 safi = SAFI_UNICAST;
11749
1ae44dfc 11750 table = bgp->rib[afi][safi];
d62a17ae 11751 /* use MPLS and ENCAP specific shows until they are merged */
11752 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11753 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11754 output_arg, use_json);
d62a17ae 11755 }
dba3c1d3
PG
11756
11757 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11758 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11759 output_arg, use_json,
11760 1, NULL, NULL);
11761 }
fee0f4c6 11762
96f3485c 11763 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11764 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11765 rpki_target_state);
fee0f4c6 11766}
11767
d62a17ae 11768static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11769 safi_t safi, uint16_t show_flags)
f186de26 11770{
d62a17ae 11771 struct listnode *node, *nnode;
11772 struct bgp *bgp;
11773 int is_first = 1;
9f049418 11774 bool route_output = false;
96f3485c 11775 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11776
d62a17ae 11777 if (use_json)
11778 vty_out(vty, "{\n");
9f689658 11779
d62a17ae 11780 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11781 route_output = true;
d62a17ae 11782 if (use_json) {
11783 if (!is_first)
11784 vty_out(vty, ",\n");
11785 else
11786 is_first = 0;
11787
11788 vty_out(vty, "\"%s\":",
11789 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11790 ? VRF_DEFAULT_NAME
d62a17ae 11791 : bgp->name);
11792 } else {
11793 vty_out(vty, "\nInstance %s:\n",
11794 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11795 ? VRF_DEFAULT_NAME
d62a17ae 11796 : bgp->name);
11797 }
11798 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11799 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11800 }
9f689658 11801
d62a17ae 11802 if (use_json)
11803 vty_out(vty, "}\n");
9f049418
DS
11804 else if (!route_output)
11805 vty_out(vty, "%% BGP instance not found\n");
f186de26 11806}
11807
718e3744 11808/* Header of detailed BGP route information */
d62a17ae 11809void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
34c7f35f
SW
11810 struct bgp_dest *dest, const struct prefix *p,
11811 const struct prefix_rd *prd, afi_t afi,
11812 safi_t safi, json_object *json)
d62a17ae 11813{
40381db7 11814 struct bgp_path_info *pi;
d62a17ae 11815 struct peer *peer;
11816 struct listnode *node, *nnode;
06b9f471 11817 char buf1[RD_ADDRSTRLEN];
d62a17ae 11818 int count = 0;
11819 int best = 0;
11820 int suppress = 0;
c5f1e1b2
C
11821 int accept_own = 0;
11822 int route_filter_translated_v4 = 0;
11823 int route_filter_v4 = 0;
11824 int route_filter_translated_v6 = 0;
11825 int route_filter_v6 = 0;
11826 int llgr_stale = 0;
11827 int no_llgr = 0;
11828 int accept_own_nexthop = 0;
11829 int blackhole = 0;
d62a17ae 11830 int no_export = 0;
11831 int no_advertise = 0;
11832 int local_as = 0;
c5f1e1b2 11833 int no_peer = 0;
d62a17ae 11834 int first = 1;
11835 int has_valid_label = 0;
11836 mpls_label_t label = 0;
11837 json_object *json_adv_to = NULL;
67f67ba4
DA
11838 uint32_t ttl = 0;
11839 uint32_t bos = 0;
11840 uint32_t exp = 0;
9bedbb1e 11841
67f67ba4 11842 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11843
67f67ba4 11844 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11845
44c69747 11846 if (safi == SAFI_EVPN) {
44c69747 11847 if (!json) {
2dbe669b 11848 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11849 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11850 : "",
2dbe669b 11851 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11852 } else {
11853 json_object_string_add(json, "rd",
11854 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11855 "");
11856 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11857 }
11858 } else {
11859 if (!json) {
9119ef3a
DA
11860 vty_out(vty,
11861 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11862 "\n",
d62a17ae 11863 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11864 ? prefix_rd2str(prd, buf1,
11865 sizeof(buf1))
11866 : ""),
9119ef3a
DA
11867 safi == SAFI_MPLS_VPN ? ":" : "", p,
11868 dest->version);
cd1964ff 11869
9119ef3a 11870 } else {
67d7e256 11871 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11872 json_object_int_add(json, "version", dest->version);
11873
11874 }
44c69747
LK
11875 }
11876
11877 if (has_valid_label) {
11878 if (json)
11879 json_object_int_add(json, "localLabel", label);
11880 else
d62a17ae 11881 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11882 }
11883
11884 if (!json)
d62a17ae 11885 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11886 vty_out(vty, "not allocated\n");
718e3744 11887
9bcb3eef 11888 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11889 struct community *picomm = NULL;
11890
11891 picomm = bgp_attr_get_community(pi->attr);
11892
d62a17ae 11893 count++;
40381db7 11894 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11895 best = count;
4056a5f6 11896 if (bgp_path_suppressed(pi))
d62a17ae 11897 suppress = 1;
cee9c031 11898
9a706b42 11899 if (!picomm)
cee9c031
QY
11900 continue;
11901
11902 no_advertise += community_include(
9a706b42
DA
11903 picomm, COMMUNITY_NO_ADVERTISE);
11904 no_export +=
11905 community_include(picomm, COMMUNITY_NO_EXPORT);
11906 local_as +=
11907 community_include(picomm, COMMUNITY_LOCAL_AS);
11908 accept_own +=
11909 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11910 route_filter_translated_v4 += community_include(
9a706b42 11911 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11912 route_filter_translated_v6 += community_include(
9a706b42 11913 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11914 route_filter_v4 += community_include(
9a706b42 11915 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11916 route_filter_v6 += community_include(
9a706b42
DA
11917 picomm, COMMUNITY_ROUTE_FILTER_v6);
11918 llgr_stale +=
11919 community_include(picomm, COMMUNITY_LLGR_STALE);
11920 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11921 accept_own_nexthop += community_include(
11922 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11923 blackhole +=
11924 community_include(picomm, COMMUNITY_BLACKHOLE);
11925 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11926 }
718e3744 11927 }
718e3744 11928
d62a17ae 11929 if (!json) {
11930 vty_out(vty, "Paths: (%d available", count);
11931 if (best) {
11932 vty_out(vty, ", best #%d", best);
b84060bb
PG
11933 if (safi == SAFI_UNICAST) {
11934 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11935 vty_out(vty, ", table %s",
11936 VRF_DEFAULT_NAME);
11937 else
11938 vty_out(vty, ", vrf %s",
11939 bgp->name);
11940 }
d62a17ae 11941 } else
11942 vty_out(vty, ", no best path");
11943
c5f1e1b2
C
11944 if (accept_own)
11945 vty_out(vty,
11946 ", accept own local route exported and imported in different VRF");
11947 else if (route_filter_translated_v4)
11948 vty_out(vty,
11949 ", mark translated RTs for VPNv4 route filtering");
11950 else if (route_filter_v4)
11951 vty_out(vty,
11952 ", attach RT as-is for VPNv4 route filtering");
11953 else if (route_filter_translated_v6)
11954 vty_out(vty,
11955 ", mark translated RTs for VPNv6 route filtering");
11956 else if (route_filter_v6)
11957 vty_out(vty,
11958 ", attach RT as-is for VPNv6 route filtering");
11959 else if (llgr_stale)
11960 vty_out(vty,
1479ed2f 11961 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11962 else if (no_llgr)
11963 vty_out(vty,
11964 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11965 else if (accept_own_nexthop)
11966 vty_out(vty,
11967 ", accept local nexthop");
11968 else if (blackhole)
11969 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11970 else if (no_export)
11971 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11972 else if (no_advertise)
11973 vty_out(vty, ", not advertised to any peer");
d62a17ae 11974 else if (local_as)
11975 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11976 else if (no_peer)
11977 vty_out(vty,
11978 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11979
11980 if (suppress)
11981 vty_out(vty,
11982 ", Advertisements suppressed by an aggregate.");
11983 vty_out(vty, ")\n");
11984 }
718e3744 11985
d62a17ae 11986 /* If we are not using addpath then we can display Advertised to and
11987 * that will
11988 * show what peers we advertised the bestpath to. If we are using
11989 * addpath
11990 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11991 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11992 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11993 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11994 if (json && !json_adv_to)
11995 json_adv_to = json_object_new_object();
11996
11997 route_vty_out_advertised_to(
11998 vty, peer, &first,
11999 " Advertised to non peer-group peers:\n ",
12000 json_adv_to);
12001 }
12002 }
12003
12004 if (json) {
12005 if (json_adv_to) {
12006 json_object_object_add(json, "advertisedTo",
12007 json_adv_to);
12008 }
12009 } else {
12010 if (first)
12011 vty_out(vty, " Not advertised to any peer");
12012 vty_out(vty, "\n");
12013 }
12014 }
718e3744 12015}
12016
edfee30d 12017static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
12018 struct bgp_dest *bgp_node, struct vty *vty,
12019 struct bgp *bgp, afi_t afi, safi_t safi,
12020 json_object *json, enum bgp_path_type pathtype,
4027d19b 12021 int *display, enum rpki_states rpki_target_state)
44c69747
LK
12022{
12023 struct bgp_path_info *pi;
12024 int header = 1;
44c69747
LK
12025 json_object *json_header = NULL;
12026 json_object *json_paths = NULL;
4933eaaf 12027 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 12028
9bcb3eef 12029 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 12030 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
12031
12032 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
12033 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12034 pi->peer, pi->attr, p);
4933eaaf 12035
4027d19b
DS
12036 if (rpki_target_state != RPKI_NOT_BEING_USED
12037 && rpki_curr_state != rpki_target_state)
4933eaaf 12038 continue;
44c69747
LK
12039
12040 if (json && !json_paths) {
12041 /* Instantiate json_paths only if path is valid */
12042 json_paths = json_object_new_array();
c4f64ea9 12043 if (pfx_rd)
44c69747 12044 json_header = json_object_new_object();
c4f64ea9 12045 else
44c69747
LK
12046 json_header = json;
12047 }
12048
12049 if (header) {
12050 route_vty_out_detail_header(
34c7f35f
SW
12051 vty, bgp, bgp_node,
12052 bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12053 safi, json_header);
44c69747
LK
12054 header = 0;
12055 }
12056 (*display)++;
12057
12058 if (pathtype == BGP_PATH_SHOW_ALL
12059 || (pathtype == BGP_PATH_SHOW_BESTPATH
12060 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12061 || (pathtype == BGP_PATH_SHOW_MULTIPATH
12062 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12063 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
34c7f35f
SW
12064 route_vty_out_detail(vty, bgp, bgp_node,
12065 bgp_dest_get_prefix(bgp_node), pi,
12066 AFI_IP, safi, rpki_curr_state,
12067 json_paths);
44c69747
LK
12068 }
12069
12070 if (json && json_paths) {
12071 json_object_object_add(json_header, "paths", json_paths);
12072
12073 if (pfx_rd)
c4f64ea9
DA
12074 json_object_object_addf(json, json_header, "%pRD",
12075 pfx_rd);
44c69747
LK
12076 }
12077}
12078
2aad8c42
MS
12079/*
12080 * Return rd based on safi
12081 */
46dbf9d0
DA
12082const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12083 safi_t safi)
2aad8c42
MS
12084{
12085 switch (safi) {
12086 case SAFI_MPLS_VPN:
12087 case SAFI_ENCAP:
12088 case SAFI_EVPN:
12089 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12090 default:
12091 return NULL;
2aad8c42
MS
12092 }
12093}
12094
718e3744 12095/* Display specified route of BGP table. */
d62a17ae 12096static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12097 struct bgp_table *rib, const char *ip_str,
12098 afi_t afi, safi_t safi,
4027d19b 12099 enum rpki_states rpki_target_state,
d62a17ae 12100 struct prefix_rd *prd, int prefix_check,
9f049418 12101 enum bgp_path_type pathtype, bool use_json)
d62a17ae 12102{
12103 int ret;
d62a17ae 12104 int display = 0;
12105 struct prefix match;
9bcb3eef
DS
12106 struct bgp_dest *dest;
12107 struct bgp_dest *rm;
d62a17ae 12108 struct bgp_table *table;
12109 json_object *json = NULL;
12110 json_object *json_paths = NULL;
12111
12112 /* Check IP address argument. */
12113 ret = str2prefix(ip_str, &match);
12114 if (!ret) {
12115 vty_out(vty, "address is malformed\n");
12116 return CMD_WARNING;
12117 }
718e3744 12118
d62a17ae 12119 match.family = afi2family(afi);
b05a1c8b 12120
44c69747 12121 if (use_json)
d62a17ae 12122 json = json_object_new_object();
718e3744 12123
44c69747 12124 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
12125 for (dest = bgp_table_top(rib); dest;
12126 dest = bgp_route_next(dest)) {
12127 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12128
9bcb3eef 12129 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 12130 continue;
9bcb3eef 12131 table = bgp_dest_get_bgp_table_info(dest);
67009e22 12132 if (!table)
ea47320b 12133 continue;
d62a17ae 12134
4953391b
DA
12135 rm = bgp_node_match(table, &match);
12136 if (rm == NULL)
ea47320b 12137 continue;
d62a17ae 12138
9bcb3eef 12139 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 12140 if (prefix_check
b54892e0 12141 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 12142 bgp_dest_unlock_node(rm);
ea47320b
DL
12143 continue;
12144 }
d62a17ae 12145
9bcb3eef 12146 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12147 bgp, afi, safi, json, pathtype,
4027d19b 12148 &display, rpki_target_state);
44c69747 12149
9bcb3eef 12150 bgp_dest_unlock_node(rm);
44c69747
LK
12151 }
12152 } else if (safi == SAFI_EVPN) {
9bcb3eef 12153 struct bgp_dest *longest_pfx;
cded3b72 12154 bool is_exact_pfxlen_match = false;
44c69747 12155
9bcb3eef
DS
12156 for (dest = bgp_table_top(rib); dest;
12157 dest = bgp_route_next(dest)) {
12158 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 12159
9bcb3eef 12160 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 12161 continue;
9bcb3eef 12162 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
12163 if (!table)
12164 continue;
12165
12166 longest_pfx = NULL;
cded3b72 12167 is_exact_pfxlen_match = false;
44c69747
LK
12168 /*
12169 * Search through all the prefixes for a match. The
12170 * pfx's are enumerated in ascending order of pfxlens.
12171 * So, the last pfx match is the longest match. Set
12172 * is_exact_pfxlen_match when we get exact pfxlen match
12173 */
12174 for (rm = bgp_table_top(table); rm;
12175 rm = bgp_route_next(rm)) {
b54892e0 12176 const struct prefix *rm_p =
9bcb3eef 12177 bgp_dest_get_prefix(rm);
44c69747
LK
12178 /*
12179 * Get prefixlen of the ip-prefix within type5
12180 * evpn route
12181 */
b54892e0
DS
12182 if (evpn_type5_prefix_match(rm_p, &match)
12183 && rm->info) {
44c69747
LK
12184 longest_pfx = rm;
12185 int type5_pfxlen =
b54892e0
DS
12186 bgp_evpn_get_type5_prefixlen(
12187 rm_p);
44c69747 12188 if (type5_pfxlen == match.prefixlen) {
cded3b72 12189 is_exact_pfxlen_match = true;
9bcb3eef 12190 bgp_dest_unlock_node(rm);
44c69747
LK
12191 break;
12192 }
d62a17ae 12193 }
12194 }
ea47320b 12195
44c69747
LK
12196 if (!longest_pfx)
12197 continue;
12198
12199 if (prefix_check && !is_exact_pfxlen_match)
12200 continue;
12201
12202 rm = longest_pfx;
9bcb3eef 12203 bgp_dest_lock_node(rm);
44c69747 12204
9bcb3eef 12205 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 12206 bgp, afi, safi, json, pathtype,
4027d19b 12207 &display, rpki_target_state);
44c69747 12208
9bcb3eef 12209 bgp_dest_unlock_node(rm);
d62a17ae 12210 }
98a9dbc7 12211 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
12212 if (use_json)
12213 json_paths = json_object_new_array();
12214
63a0b7a9
PG
12215 display = bgp_flowspec_display_match_per_ip(afi, rib,
12216 &match, prefix_check,
12217 vty,
12218 use_json,
12219 json_paths);
d5f20468
SP
12220 if (use_json) {
12221 if (display)
12222 json_object_object_add(json, "paths",
12223 json_paths);
12224 else
12225 json_object_free(json_paths);
12226 }
d62a17ae 12227 } else {
4953391b
DA
12228 dest = bgp_node_match(rib, &match);
12229 if (dest != NULL) {
9bcb3eef 12230 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12231 if (!prefix_check
9bcb3eef
DS
12232 || dest_p->prefixlen == match.prefixlen) {
12233 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12234 safi, json, pathtype,
4027d19b 12235 &display, rpki_target_state);
d62a17ae 12236 }
12237
9bcb3eef 12238 bgp_dest_unlock_node(dest);
d62a17ae 12239 }
12240 }
e5eee9af 12241
d62a17ae 12242 if (use_json) {
75eeda93 12243 vty_json(vty, json);
d62a17ae 12244 } else {
12245 if (!display) {
12246 vty_out(vty, "%% Network not in table\n");
12247 return CMD_WARNING;
12248 }
12249 }
b05a1c8b 12250
d62a17ae 12251 return CMD_SUCCESS;
718e3744 12252}
12253
fee0f4c6 12254/* Display specified route of Main RIB */
d62a17ae 12255static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12256 afi_t afi, safi_t safi, struct prefix_rd *prd,
12257 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12258 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12259{
9b86009a 12260 if (!bgp) {
d62a17ae 12261 bgp = bgp_get_default();
9b86009a
RW
12262 if (!bgp) {
12263 if (!use_json)
12264 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12265 else
12266 vty_out(vty, "{}\n");
9b86009a
RW
12267 return CMD_WARNING;
12268 }
12269 }
d62a17ae 12270
12271 /* labeled-unicast routes live in the unicast table */
12272 if (safi == SAFI_LABELED_UNICAST)
12273 safi = SAFI_UNICAST;
12274
12275 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12276 afi, safi, rpki_target_state, prd,
8aa22bbb 12277 prefix_check, pathtype, use_json);
d62a17ae 12278}
12279
12280static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12281 struct cmd_token **argv, bool exact, afi_t afi,
12282 safi_t safi, bool uj)
d62a17ae 12283{
12284 struct lcommunity *lcom;
12285 struct buffer *b;
12286 int i;
12287 char *str;
12288 int first = 0;
96c81f66 12289 uint16_t show_flags = 0;
4f28b2b5 12290 int ret;
96f3485c
MK
12291
12292 if (uj)
12293 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12294
12295 b = buffer_new(1024);
12296 for (i = 0; i < argc; i++) {
12297 if (first)
12298 buffer_putc(b, ' ');
12299 else {
12300 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12301 first = 1;
12302 buffer_putstr(b, argv[i]->arg);
12303 }
12304 }
12305 }
12306 buffer_putc(b, '\0');
57d187bc 12307
d62a17ae 12308 str = buffer_getstr(b);
12309 buffer_free(b);
57d187bc 12310
d62a17ae 12311 lcom = lcommunity_str2com(str);
12312 XFREE(MTYPE_TMP, str);
12313 if (!lcom) {
12314 vty_out(vty, "%% Large-community malformed\n");
12315 return CMD_WARNING;
12316 }
57d187bc 12317
4f28b2b5 12318 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12319 (exact ? bgp_show_type_lcommunity_exact
12320 : bgp_show_type_lcommunity),
12321 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12322
12323 lcommunity_free(&lcom);
12324 return ret;
57d187bc
JS
12325}
12326
d62a17ae 12327static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12328 const char *lcom, bool exact, afi_t afi,
12329 safi_t safi, bool uj)
57d187bc 12330{
d62a17ae 12331 struct community_list *list;
96c81f66 12332 uint16_t show_flags = 0;
96f3485c
MK
12333
12334 if (uj)
12335 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12336
57d187bc 12337
e237b0d2 12338 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12339 LARGE_COMMUNITY_LIST_MASTER);
12340 if (list == NULL) {
12341 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12342 lcom);
12343 return CMD_WARNING;
12344 }
57d187bc 12345
36a206db 12346 return bgp_show(vty, bgp, afi, safi,
12347 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12348 : bgp_show_type_lcommunity_list),
1e2ce4f1 12349 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12350}
12351
52951b63
DS
12352DEFUN (show_ip_bgp_large_community_list,
12353 show_ip_bgp_large_community_list_cmd,
77a3a95e 12354 "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
12355 SHOW_STR
12356 IP_STR
12357 BGP_STR
12358 BGP_INSTANCE_HELP_STR
9bedbb1e 12359 BGP_AFI_HELP_STR
4dd6177e 12360 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12361 "Display routes matching the large-community-list\n"
12362 "large-community-list number\n"
12363 "large-community-list name\n"
36a206db 12364 "Exact match of the large-communities\n"
52951b63
DS
12365 JSON_STR)
12366{
d62a17ae 12367 afi_t afi = AFI_IP6;
12368 safi_t safi = SAFI_UNICAST;
12369 int idx = 0;
36a206db 12370 bool exact_match = 0;
4d678463 12371 struct bgp *bgp = NULL;
9f049418 12372 bool uj = use_json(argc, argv);
d62a17ae 12373
ef3364f0
DA
12374 if (uj)
12375 argc--;
4d678463 12376
ef3364f0
DA
12377 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12378 &bgp, uj);
12379 if (!idx)
12380 return CMD_WARNING;
d62a17ae 12381
12382 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12383
12384 const char *clist_number_or_name = argv[++idx]->arg;
12385
12386 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12387 exact_match = 1;
12388
12389 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12390 exact_match, afi, safi, uj);
52951b63
DS
12391}
12392DEFUN (show_ip_bgp_large_community,
12393 show_ip_bgp_large_community_cmd,
36a206db 12394 "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
12395 SHOW_STR
12396 IP_STR
12397 BGP_STR
12398 BGP_INSTANCE_HELP_STR
9bedbb1e 12399 BGP_AFI_HELP_STR
4dd6177e 12400 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12401 "Display routes matching the large-communities\n"
12402 "List of large-community numbers\n"
36a206db 12403 "Exact match of the large-communities\n"
52951b63
DS
12404 JSON_STR)
12405{
d62a17ae 12406 afi_t afi = AFI_IP6;
12407 safi_t safi = SAFI_UNICAST;
12408 int idx = 0;
36a206db 12409 bool exact_match = 0;
4d678463 12410 struct bgp *bgp = NULL;
9f049418 12411 bool uj = use_json(argc, argv);
96c81f66 12412 uint16_t show_flags = 0;
d62a17ae 12413
96f3485c
MK
12414 if (uj) {
12415 argc--;
12416 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12417 }
4d678463 12418
96f3485c
MK
12419 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12420 &bgp, uj);
12421 if (!idx)
12422 return CMD_WARNING;
d62a17ae 12423
36a206db 12424 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
1857760c
YN
12425 if (argv_find(argv, argc, "exact-match", &idx)) {
12426 argc--;
36a206db 12427 exact_match = 1;
1857760c 12428 }
36a206db 12429 return bgp_show_lcommunity(vty, bgp, argc, argv,
12430 exact_match, afi, safi, uj);
12431 } else
d62a17ae 12432 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12433 bgp_show_type_lcommunity_all, NULL, show_flags,
12434 RPKI_NOT_BEING_USED);
52951b63
DS
12435}
12436
71f1613a
DA
12437static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12438 safi_t safi, struct json_object *json_array);
d62a17ae 12439static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12440 safi_t safi, struct json_object *json);
e01ca200 12441
7b2ff250 12442
9ab0cf58
PG
12443DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12444 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12445 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12446 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12447{
12448 bool uj = use_json(argc, argv);
12449 struct bgp *bgp = NULL;
ec76a1d1
DA
12450 safi_t safi = SAFI_UNICAST;
12451 afi_t afi = AFI_IP6;
4265b261 12452 int idx = 0;
6c9d22e2
PG
12453 struct json_object *json_all = NULL;
12454 struct json_object *json_afi_safi = NULL;
4265b261
PG
12455
12456 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12457 &bgp, false);
71f1613a 12458 if (!idx)
4265b261 12459 return CMD_WARNING;
6c9d22e2 12460
4265b261 12461 if (uj)
6c9d22e2 12462 json_all = json_object_new_object();
4265b261 12463
9ab0cf58
PG
12464 FOREACH_AFI_SAFI (afi, safi) {
12465 /*
12466 * So limit output to those afi/safi pairs that
12467 * actually have something interesting in them
12468 */
12469 if (strmatch(get_afi_safi_str(afi, safi, true),
12470 "Unknown")) {
12471 continue;
12472 }
12473 if (uj) {
12474 json_afi_safi = json_object_new_array();
12475 json_object_object_add(
12476 json_all,
12477 get_afi_safi_str(afi, safi, true),
12478 json_afi_safi);
12479 } else {
12480 json_afi_safi = NULL;
6c9d22e2 12481 }
9ab0cf58
PG
12482
12483 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12484 }
6c9d22e2 12485
3757f964
DA
12486 if (uj)
12487 vty_json(vty, json_all);
6c9d22e2 12488
4265b261
PG
12489 return CMD_SUCCESS;
12490}
12491
7b2ff250 12492/* BGP route print out function without JSON */
14718643
PG
12493DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12494 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12495 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12496 SHOW_STR
12497 IP_STR
12498 BGP_STR
12499 BGP_INSTANCE_HELP_STR
12500 L2VPN_HELP_STR
12501 EVPN_HELP_STR
12502 "BGP RIB advertisement statistics\n"
12503 JSON_STR)
12504{
ec76a1d1
DA
12505 afi_t afi = AFI_IP6;
12506 safi_t safi = SAFI_UNICAST;
14718643
PG
12507 struct bgp *bgp = NULL;
12508 int idx = 0, ret;
12509 bool uj = use_json(argc, argv);
12510 struct json_object *json_afi_safi = NULL, *json = NULL;
12511
12512 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12513 &bgp, false);
12514 if (!idx)
12515 return CMD_WARNING;
12516
12517 if (uj)
12518 json_afi_safi = json_object_new_array();
12519 else
12520 json_afi_safi = NULL;
12521
12522 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12523
12524 if (uj) {
12525 json = json_object_new_object();
12526 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12527 json_afi_safi);
3757f964 12528 vty_json(vty, json);
14718643
PG
12529 }
12530 return ret;
12531}
12532
893cccd0 12533/* BGP route print out function without JSON */
9ab0cf58
PG
12534DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12535 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12536 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12537 "]]\
893cccd0 12538 statistics [json]",
9ab0cf58
PG
12539 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12540 BGP_SAFI_WITH_LABEL_HELP_STR
12541 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12542{
ec76a1d1
DA
12543 afi_t afi = AFI_IP6;
12544 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12545 struct bgp *bgp = NULL;
12546 int idx = 0, ret;
12547 bool uj = use_json(argc, argv);
6c9d22e2 12548 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12549
12550 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12551 &bgp, false);
12552 if (!idx)
12553 return CMD_WARNING;
6c9d22e2 12554
893cccd0 12555 if (uj)
6c9d22e2
PG
12556 json_afi_safi = json_object_new_array();
12557 else
12558 json_afi_safi = NULL;
12559
12560 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12561
12562 if (uj) {
12563 json = json_object_new_object();
12564 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12565 json_afi_safi);
3757f964 12566 vty_json(vty, json);
893cccd0
PG
12567 }
12568 return ret;
893cccd0 12569}
7b2ff250 12570
fe0f234d 12571DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12572 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12573 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12574 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12575 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12576 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12577 "Display the entries for all address families\n"
9ab0cf58
PG
12578 "Display detailed information about dampening\n"
12579 "Display detail of configured dampening parameters\n"
fe0f234d 12580 JSON_STR)
718e3744 12581{
d62a17ae 12582 afi_t afi = AFI_IP6;
12583 safi_t safi = SAFI_UNICAST;
d62a17ae 12584 struct bgp *bgp = NULL;
12585 int idx = 0;
96c81f66 12586 uint16_t show_flags = 0;
fe0f234d
RW
12587 bool uj = use_json(argc, argv);
12588
12589 if (uj) {
12590 argc--;
12591 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12592 }
96f3485c
MK
12593
12594 /* [<ipv4|ipv6> [all]] */
12595 if (all) {
12596 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12597 if (argv_find(argv, argc, "ipv4", &idx))
12598 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12599
12600 if (argv_find(argv, argc, "ipv6", &idx))
12601 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12602 }
d62a17ae 12603
12604 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12605 &bgp, false);
d62a17ae 12606 if (!idx)
12607 return CMD_WARNING;
12608
fe0f234d 12609 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12610}
12611
fe0f234d
RW
12612/* BGP route print out function */
12613DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12614 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12615 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12616 "]]\
96f3485c 12617 [all$all]\
cf4898bc
QY
12618 [cidr-only\
12619 |dampening <flap-statistics|dampened-paths>\
12620 |community [AA:NN|local-AS|no-advertise|no-export\
12621 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12622 |accept-own|accept-own-nexthop|route-filter-v6\
12623 |route-filter-v4|route-filter-translated-v6\
12624 |route-filter-translated-v4] [exact-match]\
70799983 12625 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12626 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12627 |prefix-list WORD\
ed126382 12628 |access-list ACCESSLIST_NAME\
70dd370f 12629 |route-map RMAP_NAME\
1e2ce4f1 12630 |rpki <invalid|valid|notfound>\
7d3cae70 12631 |version (1-4294967295)\
b4ad2fae 12632 |alias ALIAS_NAME\
39c3c736
RW
12633 |A.B.C.D/M longer-prefixes\
12634 |X:X::X:X/M longer-prefixes\
70cd87ca 12635 |optimal-route-reflection [WORD$orr_group_name]\
f280c93b 12636 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12637 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12638 BGP_SAFI_WITH_LABEL_HELP_STR
12639 "Display the entries for all address families\n"
12640 "Display only routes with non-natural netmasks\n"
12641 "Display detailed information about dampening\n"
12642 "Display flap statistics of routes\n"
12643 "Display paths suppressed due to dampening\n"
12644 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12645 "Do not send outside local AS (well-known community)\n"
12646 "Do not advertise to any peer (well-known community)\n"
12647 "Do not export to next AS (well-known community)\n"
12648 "Graceful shutdown (well-known community)\n"
12649 "Do not export to any peer (well-known community)\n"
12650 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12651 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12652 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12653 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12654 "Should accept VPN route with local nexthop (well-known community)\n"
12655 "RT VPNv6 route filtering (well-known community)\n"
12656 "RT VPNv4 route filtering (well-known community)\n"
12657 "RT translated VPNv6 route filtering (well-known community)\n"
12658 "RT translated VPNv4 route filtering (well-known community)\n"
12659 "Exact match of the communities\n"
70799983
RW
12660 "Community-list number\n"
12661 "Community-list name\n"
12662 "Display routes matching the community-list\n"
12663 "Exact match of the communities\n"
a7129347
RW
12664 "Display routes conforming to the filter-list\n"
12665 "Regular expression access list name\n"
6deaf579
RW
12666 "Display routes conforming to the prefix-list\n"
12667 "Prefix-list name\n"
ed126382
DA
12668 "Display routes conforming to the access-list\n"
12669 "Access-list name\n"
bf1a944a
RW
12670 "Display routes matching the route-map\n"
12671 "A route-map to match on\n"
a70a28a5
DA
12672 "RPKI route types\n"
12673 "A valid path as determined by rpki\n"
12674 "A invalid path as determined by rpki\n"
12675 "A path that has no rpki data\n"
12676 "Display prefixes with matching version numbers\n"
12677 "Version number and above\n"
12678 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12679 "BGP community alias\n"
12680 "IPv4 prefix\n"
12681 "Display route and more specific routes\n"
12682 "IPv6 prefix\n"
12683 "Display route and more specific routes\n"
70cd87ca
MK
12684 "Display Optimal Route Reflection RR Clients\n"
12685 "ORR Group name\n"
39c3c736 12686 JSON_STR
a70a28a5
DA
12687 "Display detailed version of JSON output\n"
12688 "Increase table width for longer prefixes\n")
7b2ff250
DW
12689{
12690 afi_t afi = AFI_IP6;
12691 safi_t safi = SAFI_UNICAST;
12692 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12693 void *output_arg = NULL;
7b2ff250
DW
12694 struct bgp *bgp = NULL;
12695 int idx = 0;
d0086e8e 12696 int exact_match = 0;
96f3485c
MK
12697 char *community = NULL;
12698 bool first = true;
96c81f66 12699 uint16_t show_flags = 0;
4027d19b 12700 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12701 struct prefix p;
70cd87ca 12702 bool orr_group = false;
96f3485c
MK
12703
12704 if (uj) {
9f049418 12705 argc--;
96f3485c
MK
12706 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12707 }
12708
f280c93b
DA
12709 if (detail)
12710 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12711
96f3485c
MK
12712 /* [<ipv4|ipv6> [all]] */
12713 if (all) {
12714 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12715
12716 if (argv_find(argv, argc, "ipv4", &idx))
12717 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12718
12719 if (argv_find(argv, argc, "ipv6", &idx))
12720 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12721 }
12722
12723 if (wide)
12724 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12725
12726 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12727 &bgp, uj);
7b2ff250
DW
12728 if (!idx)
12729 return CMD_WARNING;
12730
7b2ff250 12731 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12732 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12733
12734 if (argv_find(argv, argc, "dampening", &idx)) {
12735 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12736 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12737 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12738 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12739 }
12740
12741 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12742 char *maybecomm = NULL;
d0086e8e 12743
79bc257a
RW
12744 if (idx + 1 < argc) {
12745 if (argv[idx + 1]->type == VARIABLE_TKN)
12746 maybecomm = argv[idx + 1]->arg;
12747 else
12748 maybecomm = argv[idx + 1]->text;
12749 }
12750
cf4898bc
QY
12751 if (maybecomm && !strmatch(maybecomm, "json")
12752 && !strmatch(maybecomm, "exact-match"))
12753 community = maybecomm;
d0086e8e 12754
cf4898bc
QY
12755 if (argv_find(argv, argc, "exact-match", &idx))
12756 exact_match = 1;
d0086e8e 12757
96f3485c
MK
12758 if (!community)
12759 sh_type = bgp_show_type_community_all;
12760 }
12761
70799983
RW
12762 if (argv_find(argv, argc, "community-list", &idx)) {
12763 const char *clist_number_or_name = argv[++idx]->arg;
12764 struct community_list *list;
12765
12766 if (argv_find(argv, argc, "exact-match", &idx))
12767 exact_match = 1;
12768
12769 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12770 COMMUNITY_LIST_MASTER);
12771 if (list == NULL) {
606d49a4 12772 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12773 clist_number_or_name);
12774 return CMD_WARNING;
12775 }
12776
12777 if (exact_match)
12778 sh_type = bgp_show_type_community_list_exact;
12779 else
12780 sh_type = bgp_show_type_community_list;
12781 output_arg = list;
12782 }
12783
a7129347
RW
12784 if (argv_find(argv, argc, "filter-list", &idx)) {
12785 const char *filter = argv[++idx]->arg;
12786 struct as_list *as_list;
12787
12788 as_list = as_list_lookup(filter);
12789 if (as_list == NULL) {
606d49a4 12790 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12791 filter);
12792 return CMD_WARNING;
12793 }
12794
12795 sh_type = bgp_show_type_filter_list;
12796 output_arg = as_list;
12797 }
12798
6deaf579
RW
12799 if (argv_find(argv, argc, "prefix-list", &idx)) {
12800 const char *prefix_list_str = argv[++idx]->arg;
12801 struct prefix_list *plist;
12802
12803 plist = prefix_list_lookup(afi, prefix_list_str);
12804 if (plist == NULL) {
606d49a4 12805 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12806 prefix_list_str);
12807 return CMD_WARNING;
12808 }
12809
12810 sh_type = bgp_show_type_prefix_list;
12811 output_arg = plist;
12812 }
12813
ed126382
DA
12814 if (argv_find(argv, argc, "access-list", &idx)) {
12815 const char *access_list_str = argv[++idx]->arg;
12816 struct access_list *alist;
12817
12818 alist = access_list_lookup(afi, access_list_str);
12819 if (!alist) {
606d49a4 12820 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12821 access_list_str);
12822 return CMD_WARNING;
12823 }
12824
12825 sh_type = bgp_show_type_access_list;
12826 output_arg = alist;
12827 }
12828
bf1a944a
RW
12829 if (argv_find(argv, argc, "route-map", &idx)) {
12830 const char *rmap_str = argv[++idx]->arg;
12831 struct route_map *rmap;
12832
12833 rmap = route_map_lookup_by_name(rmap_str);
12834 if (!rmap) {
606d49a4 12835 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12836 return CMD_WARNING;
12837 }
12838
12839 sh_type = bgp_show_type_route_map;
12840 output_arg = rmap;
12841 }
12842
1e2ce4f1
DS
12843 if (argv_find(argv, argc, "rpki", &idx)) {
12844 sh_type = bgp_show_type_rpki;
12845 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12846 rpki_target_state = RPKI_VALID;
1e2ce4f1 12847 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12848 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12849 }
12850
7d3cae70
DA
12851 /* Display prefixes with matching version numbers */
12852 if (argv_find(argv, argc, "version", &idx)) {
12853 sh_type = bgp_show_type_prefix_version;
2391833e 12854 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12855 }
12856
a70a28a5
DA
12857 /* Display prefixes with matching BGP community alias */
12858 if (argv_find(argv, argc, "alias", &idx)) {
12859 sh_type = bgp_show_type_community_alias;
2391833e 12860 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12861 }
12862
39c3c736
RW
12863 /* prefix-longer */
12864 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12865 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12866 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12867
12868 if (!str2prefix(prefix_str, &p)) {
12869 vty_out(vty, "%% Malformed Prefix\n");
12870 return CMD_WARNING;
12871 }
12872
12873 sh_type = bgp_show_type_prefix_longer;
12874 output_arg = &p;
a70a28a5
DA
12875 }
12876
70cd87ca
MK
12877 if (argv_find(argv, argc, "optimal-route-reflection", &idx))
12878 orr_group = true;
12879
96f3485c
MK
12880 if (!all) {
12881 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12882 if (community)
12883 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12884 exact_match, afi, safi,
12885 show_flags);
70cd87ca
MK
12886 else if (orr_group)
12887 return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
12888 show_flags);
2391833e 12889 else
a70a28a5 12890 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12891 output_arg, show_flags,
a70a28a5 12892 rpki_target_state);
96f3485c 12893 } else {
fa5ac378
DA
12894 struct listnode *node;
12895 struct bgp *abgp;
96f3485c
MK
12896 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12897 * AFI_IP6 */
12898
12899 if (uj)
12900 vty_out(vty, "{\n");
12901
12902 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12903 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12904 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12905 ? AFI_IP
12906 : AFI_IP6;
fa5ac378
DA
12907 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12908 FOREACH_SAFI (safi) {
12909 if (!bgp_afi_safi_peer_exists(abgp, afi,
12910 safi))
12911 continue;
96f3485c 12912
fa5ac378
DA
12913 if (uj) {
12914 if (first)
12915 first = false;
12916 else
12917 vty_out(vty, ",\n");
12918 vty_out(vty, "\"%s\":{\n",
12919 get_afi_safi_str(afi,
12920 safi,
12921 true));
12922 } else
12923 vty_out(vty,
12924 "\nFor address family: %s\n",
12925 get_afi_safi_str(
12926 afi, safi,
12927 false));
12928
12929 if (community)
12930 bgp_show_community(
12931 vty, abgp, community,
12932 exact_match, afi, safi,
12933 show_flags);
70cd87ca
MK
12934 else if (orr_group)
12935 bgp_show_orr(vty, bgp, afi,
12936 safi,
12937 orr_group_name,
12938 show_flags);
96f3485c 12939 else
fa5ac378
DA
12940 bgp_show(vty, abgp, afi, safi,
12941 sh_type, output_arg,
12942 show_flags,
12943 rpki_target_state);
12944 if (uj)
12945 vty_out(vty, "}\n");
12946 }
96f3485c
MK
12947 }
12948 } else {
12949 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12950 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12951 FOREACH_AFI_SAFI (afi, safi) {
12952 if (!bgp_afi_safi_peer_exists(abgp, afi,
12953 safi))
12954 continue;
96f3485c 12955
fa5ac378
DA
12956 if (uj) {
12957 if (first)
12958 first = false;
12959 else
12960 vty_out(vty, ",\n");
12961
12962 vty_out(vty, "\"%s\":{\n",
12963 get_afi_safi_str(afi,
12964 safi,
12965 true));
12966 } else
12967 vty_out(vty,
12968 "\nFor address family: %s\n",
12969 get_afi_safi_str(
12970 afi, safi,
12971 false));
12972
12973 if (community)
12974 bgp_show_community(
12975 vty, abgp, community,
12976 exact_match, afi, safi,
12977 show_flags);
70cd87ca
MK
12978 else if (orr_group)
12979 bgp_show_orr(vty, bgp, afi,
12980 safi,
12981 orr_group_name,
12982 show_flags);
96f3485c 12983 else
fa5ac378
DA
12984 bgp_show(vty, abgp, afi, safi,
12985 sh_type, output_arg,
12986 show_flags,
12987 rpki_target_state);
12988 if (uj)
12989 vty_out(vty, "}\n");
12990 }
96f3485c
MK
12991 }
12992 }
12993 if (uj)
12994 vty_out(vty, "}\n");
12995 }
12996 return CMD_SUCCESS;
a636c635 12997}
47fc97cc 12998
718e3744 12999DEFUN (show_ip_bgp_route,
13000 show_ip_bgp_route_cmd,
8aa22bbb 13001 "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 13002 SHOW_STR
13003 IP_STR
13004 BGP_STR
a636c635 13005 BGP_INSTANCE_HELP_STR
4f280b15 13006 BGP_AFI_HELP_STR
4dd6177e 13007 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 13008 "Network in the BGP routing table to display\n"
0c7b1b01 13009 "IPv4 prefix\n"
8c3deaae 13010 "Network in the BGP routing table to display\n"
0c7b1b01 13011 "IPv6 prefix\n"
4092b06c 13012 "Display only the bestpath\n"
b05a1c8b 13013 "Display only multipaths\n"
8aa22bbb
DS
13014 "Display only paths that match the specified rpki state\n"
13015 "A valid path as determined by rpki\n"
13016 "A invalid path as determined by rpki\n"
13017 "A path that has no rpki data\n"
9973d184 13018 JSON_STR)
4092b06c 13019{
d62a17ae 13020 int prefix_check = 0;
ae19d7dd 13021
d62a17ae 13022 afi_t afi = AFI_IP6;
13023 safi_t safi = SAFI_UNICAST;
13024 char *prefix = NULL;
13025 struct bgp *bgp = NULL;
13026 enum bgp_path_type path_type;
9f049418 13027 bool uj = use_json(argc, argv);
b05a1c8b 13028
d62a17ae 13029 int idx = 0;
ae19d7dd 13030
d62a17ae 13031 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13032 &bgp, uj);
d62a17ae 13033 if (!idx)
13034 return CMD_WARNING;
c41247f5 13035
d62a17ae 13036 if (!bgp) {
13037 vty_out(vty,
13038 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13039 return CMD_WARNING;
13040 }
a636c635 13041
d62a17ae 13042 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13043 if (argv_find(argv, argc, "A.B.C.D", &idx)
13044 || argv_find(argv, argc, "X:X::X:X", &idx))
13045 prefix_check = 0;
13046 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13047 || argv_find(argv, argc, "X:X::X:X/M", &idx))
13048 prefix_check = 1;
13049
13050 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13051 && afi != AFI_IP6) {
13052 vty_out(vty,
13053 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13054 return CMD_WARNING;
13055 }
13056 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13057 && afi != AFI_IP) {
13058 vty_out(vty,
13059 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13060 return CMD_WARNING;
13061 }
13062
13063 prefix = argv[idx]->arg;
13064
13065 /* [<bestpath|multipath>] */
13066 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 13067 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 13068 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 13069 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 13070 else
360660c6 13071 path_type = BGP_PATH_SHOW_ALL;
a636c635 13072
d62a17ae 13073 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 13074 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
13075}
13076
8c3deaae
QY
13077DEFUN (show_ip_bgp_regexp,
13078 show_ip_bgp_regexp_cmd,
3e5b31b3 13079 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
13080 SHOW_STR
13081 IP_STR
13082 BGP_STR
b00b230a 13083 BGP_INSTANCE_HELP_STR
4f280b15 13084 BGP_AFI_HELP_STR
4dd6177e 13085 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 13086 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
13087 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13088 JSON_STR)
8c3deaae 13089{
d62a17ae 13090 afi_t afi = AFI_IP6;
13091 safi_t safi = SAFI_UNICAST;
13092 struct bgp *bgp = NULL;
3e5b31b3
DA
13093 bool uj = use_json(argc, argv);
13094 char *regstr = NULL;
8c3deaae 13095
d62a17ae 13096 int idx = 0;
13097 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13098 &bgp, false);
d62a17ae 13099 if (!idx)
13100 return CMD_WARNING;
8c3deaae 13101
d62a17ae 13102 // get index of regex
3e5b31b3
DA
13103 if (argv_find(argv, argc, "REGEX", &idx))
13104 regstr = argv[idx]->arg;
8c3deaae 13105
5f71d11c 13106 assert(regstr);
3e5b31b3
DA
13107 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13108 bgp_show_type_regexp, uj);
8c3deaae
QY
13109}
13110
ae248832 13111DEFPY (show_ip_bgp_instance_all,
a636c635 13112 show_ip_bgp_instance_all_cmd,
ae248832 13113 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 13114 SHOW_STR
a636c635 13115 IP_STR
4092b06c 13116 BGP_STR
a636c635 13117 BGP_INSTANCE_ALL_HELP_STR
4f280b15 13118 BGP_AFI_HELP_STR
4dd6177e 13119 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
13120 JSON_STR
13121 "Increase table width for longer prefixes\n")
4092b06c 13122{
54d05dea 13123 afi_t afi = AFI_IP6;
d62a17ae 13124 safi_t safi = SAFI_UNICAST;
13125 struct bgp *bgp = NULL;
d62a17ae 13126 int idx = 0;
96c81f66 13127 uint16_t show_flags = 0;
ae19d7dd 13128
96f3485c 13129 if (uj) {
d62a17ae 13130 argc--;
96f3485c
MK
13131 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13132 }
13133
13134 if (wide)
13135 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 13136
9f049418
DS
13137 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13138 &bgp, uj);
13139 if (!idx)
13140 return CMD_WARNING;
13141
96f3485c 13142 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 13143 return CMD_SUCCESS;
e3e29b32
LB
13144}
13145
a4d82a8a 13146static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
13147 afi_t afi, safi_t safi, enum bgp_show_type type,
13148 bool use_json)
718e3744 13149{
d62a17ae 13150 regex_t *regex;
13151 int rc;
96c81f66 13152 uint16_t show_flags = 0;
96f3485c
MK
13153
13154 if (use_json)
13155 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 13156
c3900853 13157 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 13158 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
13159 regstr);
13160 return CMD_WARNING_CONFIG_FAILED;
13161 }
13162
d62a17ae 13163 regex = bgp_regcomp(regstr);
13164 if (!regex) {
13165 vty_out(vty, "Can't compile regexp %s\n", regstr);
13166 return CMD_WARNING;
13167 }
a636c635 13168
1e2ce4f1
DS
13169 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13170 RPKI_NOT_BEING_USED);
d62a17ae 13171 bgp_regex_free(regex);
13172 return rc;
e3e29b32
LB
13173}
13174
7f323236
DW
13175static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13176 const char *comstr, int exact, afi_t afi,
96c81f66 13177 safi_t safi, uint16_t show_flags)
d62a17ae 13178{
13179 struct community *com;
d62a17ae 13180 int ret = 0;
13181
7f323236 13182 com = community_str2com(comstr);
d62a17ae 13183 if (!com) {
7f323236 13184 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 13185 return CMD_WARNING;
13186 }
13187
13188 ret = bgp_show(vty, bgp, afi, safi,
13189 (exact ? bgp_show_type_community_exact
13190 : bgp_show_type_community),
1e2ce4f1 13191 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 13192 community_free(&com);
46c3ce83 13193
d62a17ae 13194 return ret;
718e3744 13195}
13196
d62a17ae 13197enum bgp_stats {
13198 BGP_STATS_MAXBITLEN = 0,
13199 BGP_STATS_RIB,
13200 BGP_STATS_PREFIXES,
13201 BGP_STATS_TOTPLEN,
13202 BGP_STATS_UNAGGREGATEABLE,
13203 BGP_STATS_MAX_AGGREGATEABLE,
13204 BGP_STATS_AGGREGATES,
13205 BGP_STATS_SPACE,
13206 BGP_STATS_ASPATH_COUNT,
13207 BGP_STATS_ASPATH_MAXHOPS,
13208 BGP_STATS_ASPATH_TOTHOPS,
13209 BGP_STATS_ASPATH_MAXSIZE,
13210 BGP_STATS_ASPATH_TOTSIZE,
13211 BGP_STATS_ASN_HIGHEST,
13212 BGP_STATS_MAX,
a636c635 13213};
2815e61f 13214
9ab0cf58 13215#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
13216#define TABLE_STATS_IDX_JSON 1
13217
13218static const char *table_stats_strs[][2] = {
6c9d22e2
PG
13219 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13220 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13221 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
13222 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13223 "unaggregateablePrefixes"},
13224 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13225 "maximumAggregateablePrefixes"},
13226 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13227 "bgpAggregateAdvertisements"},
6c9d22e2
PG
13228 [BGP_STATS_SPACE] = {"Address space advertised",
13229 "addressSpaceAdvertised"},
9ab0cf58
PG
13230 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13231 "advertisementsWithPaths"},
13232 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13233 "longestAsPath"},
13234 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13235 "largestAsPath"},
13236 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13237 "averageAsPathLengthHops"},
13238 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13239 "averageAsPathSizeBytes"},
13240 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13241 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13242};
2815e61f 13243
d62a17ae 13244struct bgp_table_stats {
13245 struct bgp_table *table;
13246 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13247
13248 unsigned long long
13249 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13250 1];
13251
8d0ab76d 13252 double total_space;
ff7924f6
PJ
13253};
13254
9bcb3eef 13255static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13256 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13257{
9bcb3eef 13258 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13259 struct bgp_path_info *pi;
b54892e0 13260 const struct prefix *rn_p;
d62a17ae 13261
9bcb3eef 13262 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13263 return;
d62a17ae 13264
9bcb3eef 13265 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13266 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13267 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13268
0747643e 13269 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13270 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13271 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13272 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13273
9bcb3eef 13274 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13275 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13276 /* announced address space */
13277 if (space)
b54892e0 13278 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13279 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13280 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13281
9c14ec72 13282
9bcb3eef 13283 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13284 ts->counts[BGP_STATS_RIB]++;
13285
05864da7
DS
13286 if (CHECK_FLAG(pi->attr->flag,
13287 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13288 ts->counts[BGP_STATS_AGGREGATES]++;
13289
13290 /* as-path stats */
05864da7 13291 if (pi->attr->aspath) {
9c14ec72
RW
13292 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13293 unsigned int size = aspath_size(pi->attr->aspath);
13294 as_t highest = aspath_highest(pi->attr->aspath);
13295
13296 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13297
13298 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13299 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13300
13301 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13302 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13303
13304 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13305 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13306 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13307 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13308 }
13309 }
13310}
13311
cc9f21da 13312static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13313{
9bcb3eef
DS
13314 struct bgp_dest *dest, *ndest;
13315 struct bgp_dest *top;
9c14ec72
RW
13316 struct bgp_table_stats *ts = THREAD_ARG(t);
13317 unsigned int space = 0;
13318
13319 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13320 return;
9c14ec72
RW
13321
13322 switch (ts->table->afi) {
13323 case AFI_IP:
13324 space = IPV4_MAX_BITLEN;
13325 break;
13326 case AFI_IP6:
13327 space = IPV6_MAX_BITLEN;
13328 break;
3ba7b4af
TA
13329 case AFI_L2VPN:
13330 space = EVPN_ROUTE_PREFIXLEN;
13331 break;
9c14ec72 13332 default:
cc9f21da 13333 return;
9c14ec72
RW
13334 }
13335
13336 ts->counts[BGP_STATS_MAXBITLEN] = space;
13337
9bcb3eef 13338 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13339 if (ts->table->safi == SAFI_MPLS_VPN
13340 || ts->table->safi == SAFI_ENCAP
13341 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13342 struct bgp_table *table;
13343
9bcb3eef 13344 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13345 if (!table)
13346 continue;
13347
13348 top = bgp_table_top(table);
9bcb3eef
DS
13349 for (ndest = bgp_table_top(table); ndest;
13350 ndest = bgp_route_next(ndest))
13351 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13352 } else {
9bcb3eef 13353 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13354 }
13355 }
2815e61f 13356}
ff7924f6 13357
71f1613a
DA
13358static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13359 struct json_object *json_array)
13360{
13361 struct listnode *node, *nnode;
13362 struct bgp *bgp;
13363
13364 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13365 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13366}
13367
13368static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13369 safi_t safi, struct json_object *json_array)
2815e61f 13370{
d62a17ae 13371 struct bgp_table_stats ts;
13372 unsigned int i;
893cccd0
PG
13373 int ret = CMD_SUCCESS;
13374 char temp_buf[20];
6c9d22e2 13375 struct json_object *json = NULL;
0747643e
AQ
13376 uint32_t bitlen = 0;
13377 struct json_object *json_bitlen;
6c9d22e2
PG
13378
13379 if (json_array)
13380 json = json_object_new_object();
019386c2 13381
d62a17ae 13382 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13383 char warning_msg[50];
13384
13385 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13386 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13387 safi);
6c9d22e2
PG
13388
13389 if (!json)
893cccd0
PG
13390 vty_out(vty, "%s\n", warning_msg);
13391 else
9ab0cf58 13392 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13393
893cccd0
PG
13394 ret = CMD_WARNING;
13395 goto end_table_stats;
d62a17ae 13396 }
019386c2 13397
893cccd0 13398 if (!json)
5290ceab
DA
13399 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13400 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13401 else
13402 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13403
d62a17ae 13404 /* labeled-unicast routes live in the unicast table */
13405 if (safi == SAFI_LABELED_UNICAST)
13406 safi = SAFI_UNICAST;
019386c2 13407
d62a17ae 13408 memset(&ts, 0, sizeof(ts));
13409 ts.table = bgp->rib[afi][safi];
13410 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13411
d62a17ae 13412 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13413 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13414 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13415 continue;
13416
13417 switch (i) {
d62a17ae 13418 case BGP_STATS_ASPATH_TOTHOPS:
13419 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13420 if (!json) {
9ab0cf58
PG
13421 snprintf(
13422 temp_buf, sizeof(temp_buf), "%12.2f",
13423 ts.counts[i]
13424 ? (float)ts.counts[i]
13425 / (float)ts.counts
13426 [BGP_STATS_ASPATH_COUNT]
13427 : 0);
893cccd0 13428 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13429 table_stats_strs[i]
13430 [TABLE_STATS_IDX_VTY],
893cccd0 13431 temp_buf);
9ab0cf58
PG
13432 } else {
13433 json_object_double_add(
13434 json,
13435 table_stats_strs[i]
13436 [TABLE_STATS_IDX_JSON],
13437 ts.counts[i]
13438 ? (double)ts.counts[i]
13439 / (double)ts.counts
d62a17ae 13440 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13441 : 0);
13442 }
d62a17ae 13443 break;
13444 case BGP_STATS_TOTPLEN:
6c9d22e2 13445 if (!json) {
9ab0cf58
PG
13446 snprintf(
13447 temp_buf, sizeof(temp_buf), "%12.2f",
13448 ts.counts[i]
13449 ? (float)ts.counts[i]
13450 / (float)ts.counts
13451 [BGP_STATS_PREFIXES]
13452 : 0);
893cccd0 13453 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13454 table_stats_strs[i]
13455 [TABLE_STATS_IDX_VTY],
893cccd0 13456 temp_buf);
9ab0cf58
PG
13457 } else {
13458 json_object_double_add(
13459 json,
13460 table_stats_strs[i]
13461 [TABLE_STATS_IDX_JSON],
13462 ts.counts[i]
13463 ? (double)ts.counts[i]
13464 / (double)ts.counts
d62a17ae 13465 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13466 : 0);
13467 }
d62a17ae 13468 break;
13469 case BGP_STATS_SPACE:
6c9d22e2
PG
13470 if (!json) {
13471 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13472 ts.total_space);
893cccd0 13473 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13474 table_stats_strs[i]
13475 [TABLE_STATS_IDX_VTY],
893cccd0 13476 temp_buf);
9ab0cf58
PG
13477 } else {
13478 json_object_double_add(
13479 json,
13480 table_stats_strs[i]
13481 [TABLE_STATS_IDX_JSON],
13482 (double)ts.total_space);
13483 }
8d0ab76d 13484 if (afi == AFI_IP6) {
6c9d22e2
PG
13485 if (!json) {
13486 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13487 "%12g",
13488 ts.total_space
13489 * pow(2.0, -128 + 32));
6c9d22e2
PG
13490 vty_out(vty, "%30s: %s\n",
13491 "/32 equivalent %s\n",
13492 temp_buf);
9ab0cf58
PG
13493 } else {
13494 json_object_double_add(
13495 json, "/32equivalent",
13496 (double)(ts.total_space
13497 * pow(2.0,
13498 -128 + 32)));
13499 }
6c9d22e2
PG
13500 if (!json) {
13501 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13502 "%12g",
13503 ts.total_space
13504 * pow(2.0, -128 + 48));
6c9d22e2
PG
13505 vty_out(vty, "%30s: %s\n",
13506 "/48 equivalent %s\n",
13507 temp_buf);
9ab0cf58
PG
13508 } else {
13509 json_object_double_add(
13510 json, "/48equivalent",
13511 (double)(ts.total_space
13512 * pow(2.0,
13513 -128 + 48)));
13514 }
8d0ab76d 13515 } else {
6c9d22e2
PG
13516 if (!json) {
13517 snprintf(temp_buf, sizeof(temp_buf),
13518 "%12.2f",
9ab0cf58
PG
13519 ts.total_space * 100.
13520 * pow(2.0, -32));
6c9d22e2 13521 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13522 "% announced ", temp_buf);
13523 } else {
13524 json_object_double_add(
13525 json, "%announced",
13526 (double)(ts.total_space * 100.
13527 * pow(2.0, -32)));
13528 }
6c9d22e2
PG
13529 if (!json) {
13530 snprintf(temp_buf, sizeof(temp_buf),
13531 "%12.2f",
9ab0cf58
PG
13532 ts.total_space
13533 * pow(2.0, -32 + 8));
6c9d22e2
PG
13534 vty_out(vty, "%30s: %s\n",
13535 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13536 } else {
13537 json_object_double_add(
13538 json, "/8equivalent",
13539 (double)(ts.total_space
13540 * pow(2.0, -32 + 8)));
13541 }
6c9d22e2
PG
13542 if (!json) {
13543 snprintf(temp_buf, sizeof(temp_buf),
13544 "%12.2f",
9ab0cf58
PG
13545 ts.total_space
13546 * pow(2.0, -32 + 24));
6c9d22e2 13547 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13548 "/24 equivalent ", temp_buf);
13549 } else {
13550 json_object_double_add(
13551 json, "/24equivalent",
13552 (double)(ts.total_space
13553 * pow(2.0, -32 + 24)));
13554 }
8d0ab76d 13555 }
d62a17ae 13556 break;
13557 default:
6c9d22e2
PG
13558 if (!json) {
13559 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13560 ts.counts[i]);
893cccd0 13561 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13562 table_stats_strs[i]
13563 [TABLE_STATS_IDX_VTY],
13564 temp_buf);
13565 } else {
13566 json_object_int_add(
13567 json,
13568 table_stats_strs[i]
13569 [TABLE_STATS_IDX_JSON],
13570 ts.counts[i]);
13571 }
d62a17ae 13572 }
893cccd0
PG
13573 if (!json)
13574 vty_out(vty, "\n");
d62a17ae 13575 }
0747643e
AQ
13576
13577 switch (afi) {
13578 case AFI_IP:
13579 bitlen = IPV4_MAX_BITLEN;
13580 break;
13581 case AFI_IP6:
13582 bitlen = IPV6_MAX_BITLEN;
13583 break;
13584 case AFI_L2VPN:
13585 bitlen = EVPN_ROUTE_PREFIXLEN;
13586 break;
13587 default:
13588 break;
13589 }
13590
13591 if (json) {
13592 json_bitlen = json_object_new_array();
13593
13594 for (i = 0; i <= bitlen; i++) {
13595 struct json_object *ind_bit = json_object_new_object();
13596
13597 if (!ts.prefix_len_count[i])
13598 continue;
13599
13600 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13601 json_object_int_add(ind_bit, temp_buf,
13602 ts.prefix_len_count[i]);
13603 json_object_array_add(json_bitlen, ind_bit);
13604 }
13605 json_object_object_add(json, "prefixLength", json_bitlen);
13606 }
13607
9ab0cf58 13608end_table_stats:
6c9d22e2
PG
13609 if (json)
13610 json_object_array_add(json_array, json);
893cccd0 13611 return ret;
d62a17ae 13612}
13613
71f1613a
DA
13614static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13615 safi_t safi, struct json_object *json_array)
13616{
13617 if (!bgp) {
13618 bgp_table_stats_all(vty, afi, safi, json_array);
13619 return CMD_SUCCESS;
13620 }
13621
13622 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13623}
13624
d62a17ae 13625enum bgp_pcounts {
13626 PCOUNT_ADJ_IN = 0,
13627 PCOUNT_DAMPED,
13628 PCOUNT_REMOVED,
13629 PCOUNT_HISTORY,
13630 PCOUNT_STALE,
13631 PCOUNT_VALID,
13632 PCOUNT_ALL,
13633 PCOUNT_COUNTED,
7e3d9632 13634 PCOUNT_BPATH_SELECTED,
d62a17ae 13635 PCOUNT_PFCNT, /* the figure we display to users */
13636 PCOUNT_MAX,
a636c635 13637};
718e3744 13638
2b64873d 13639static const char *const pcount_strs[] = {
9d303b37
DL
13640 [PCOUNT_ADJ_IN] = "Adj-in",
13641 [PCOUNT_DAMPED] = "Damped",
13642 [PCOUNT_REMOVED] = "Removed",
13643 [PCOUNT_HISTORY] = "History",
13644 [PCOUNT_STALE] = "Stale",
13645 [PCOUNT_VALID] = "Valid",
13646 [PCOUNT_ALL] = "All RIB",
13647 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13648 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13649 [PCOUNT_PFCNT] = "Useable",
13650 [PCOUNT_MAX] = NULL,
a636c635 13651};
718e3744 13652
d62a17ae 13653struct peer_pcounts {
13654 unsigned int count[PCOUNT_MAX];
13655 const struct peer *peer;
13656 const struct bgp_table *table;
54317cba 13657 safi_t safi;
a636c635 13658};
47fc97cc 13659
9bcb3eef 13660static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13661{
54317cba
JW
13662 const struct bgp_adj_in *ain;
13663 const struct bgp_path_info *pi;
d62a17ae 13664 const struct peer *peer = pc->peer;
13665
54317cba
JW
13666 for (ain = rn->adj_in; ain; ain = ain->next)
13667 if (ain->peer == peer)
13668 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13669
9bcb3eef 13670 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13671
54317cba
JW
13672 if (pi->peer != peer)
13673 continue;
d62a17ae 13674
54317cba 13675 pc->count[PCOUNT_ALL]++;
d62a17ae 13676
54317cba
JW
13677 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13678 pc->count[PCOUNT_DAMPED]++;
13679 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13680 pc->count[PCOUNT_HISTORY]++;
13681 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13682 pc->count[PCOUNT_REMOVED]++;
13683 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13684 pc->count[PCOUNT_STALE]++;
13685 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13686 pc->count[PCOUNT_VALID]++;
13687 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13688 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13689 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13690 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13691
13692 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13693 pc->count[PCOUNT_COUNTED]++;
13694 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13695 flog_err(
13696 EC_LIB_DEVELOPMENT,
13697 "Attempting to count but flags say it is unusable");
13698 } else {
40381db7 13699 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13700 flog_err(
13701 EC_LIB_DEVELOPMENT,
13702 "Not counted but flags say we should");
d62a17ae 13703 }
13704 }
54317cba
JW
13705}
13706
cc9f21da 13707static void bgp_peer_count_walker(struct thread *t)
54317cba 13708{
9bcb3eef 13709 struct bgp_dest *rn, *rm;
54317cba
JW
13710 const struct bgp_table *table;
13711 struct peer_pcounts *pc = THREAD_ARG(t);
13712
13713 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13714 || pc->safi == SAFI_EVPN) {
13715 /* Special handling for 2-level routing tables. */
13716 for (rn = bgp_table_top(pc->table); rn;
13717 rn = bgp_route_next(rn)) {
9bcb3eef 13718 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13719 if (table != NULL)
13720 for (rm = bgp_table_top(table); rm;
13721 rm = bgp_route_next(rm))
13722 bgp_peer_count_proc(rm, pc);
13723 }
13724 } else
13725 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13726 bgp_peer_count_proc(rn, pc);
718e3744 13727}
13728
d62a17ae 13729static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13730 safi_t safi, bool use_json)
856ca177 13731{
d62a17ae 13732 struct peer_pcounts pcounts = {.peer = peer};
13733 unsigned int i;
13734 json_object *json = NULL;
13735 json_object *json_loop = NULL;
856ca177 13736
d62a17ae 13737 if (use_json) {
13738 json = json_object_new_object();
13739 json_loop = json_object_new_object();
13740 }
718e3744 13741
d62a17ae 13742 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13743 || !peer->bgp->rib[afi][safi]) {
13744 if (use_json) {
13745 json_object_string_add(
13746 json, "warning",
13747 "No such neighbor or address family");
13748 vty_out(vty, "%s\n", json_object_to_json_string(json));
13749 json_object_free(json);
d5f20468 13750 json_object_free(json_loop);
d62a17ae 13751 } else
13752 vty_out(vty, "%% No such neighbor or address family\n");
13753
13754 return CMD_WARNING;
13755 }
2a71e9ce 13756
d62a17ae 13757 memset(&pcounts, 0, sizeof(pcounts));
13758 pcounts.peer = peer;
13759 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13760 pcounts.safi = safi;
d62a17ae 13761
13762 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13763 * stats for the thread-walk (i.e. ensure this can't be blamed on
13764 * on just vty_read()).
13765 */
d62a17ae 13766 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13767
13768 if (use_json) {
13769 json_object_string_add(json, "prefixCountsFor", peer->host);
13770 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13771 get_afi_safi_str(afi, safi, true));
d62a17ae 13772 json_object_int_add(json, "pfxCounter",
13773 peer->pcount[afi][safi]);
13774
13775 for (i = 0; i < PCOUNT_MAX; i++)
13776 json_object_int_add(json_loop, pcount_strs[i],
13777 pcounts.count[i]);
13778
13779 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13780
13781 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13782 json_object_string_add(json, "pfxctDriftFor",
13783 peer->host);
13784 json_object_string_add(
13785 json, "recommended",
13786 "Please report this bug, with the above command output");
13787 }
75eeda93 13788 vty_json(vty, json);
d62a17ae 13789 } else {
13790
13791 if (peer->hostname
892fedb6 13792 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13793 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13794 peer->hostname, peer->host,
5cb5f4d0 13795 get_afi_safi_str(afi, safi, false));
d62a17ae 13796 } else {
13797 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13798 get_afi_safi_str(afi, safi, false));
d62a17ae 13799 }
13800
6cde4b45 13801 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13802 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13803
13804 for (i = 0; i < PCOUNT_MAX; i++)
13805 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13806 pcounts.count[i]);
13807
13808 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13809 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13810 vty_out(vty,
13811 "Please report this bug, with the above command output\n");
13812 }
13813 }
13814
13815 return CMD_SUCCESS;
718e3744 13816}
13817
a636c635
DW
13818DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13819 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13820 "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 13821 SHOW_STR
13822 IP_STR
13823 BGP_STR
8386ac43 13824 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13825 BGP_AFI_HELP_STR
13826 BGP_SAFI_HELP_STR
0b16f239
DS
13827 "Detailed information on TCP and BGP neighbor connections\n"
13828 "Neighbor to display information about\n"
13829 "Neighbor to display information about\n"
91d37724 13830 "Neighbor on BGP configured interface\n"
a636c635 13831 "Display detailed prefix count information\n"
9973d184 13832 JSON_STR)
0b16f239 13833{
d62a17ae 13834 afi_t afi = AFI_IP6;
13835 safi_t safi = SAFI_UNICAST;
13836 struct peer *peer;
13837 int idx = 0;
13838 struct bgp *bgp = NULL;
9f049418
DS
13839 bool uj = use_json(argc, argv);
13840
13841 if (uj)
13842 argc--;
856ca177 13843
d62a17ae 13844 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13845 &bgp, uj);
d62a17ae 13846 if (!idx)
13847 return CMD_WARNING;
0b16f239 13848
d62a17ae 13849 argv_find(argv, argc, "neighbors", &idx);
13850 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13851 if (!peer)
13852 return CMD_WARNING;
bb46e94f 13853
29c8d9da 13854 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13855}
0b16f239 13856
d6902373
PG
13857#ifdef KEEP_OLD_VPN_COMMANDS
13858DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13859 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13860 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13861 SHOW_STR
13862 IP_STR
13863 BGP_STR
d6902373 13864 BGP_VPNVX_HELP_STR
91d37724 13865 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13866 "Detailed information on TCP and BGP neighbor connections\n"
13867 "Neighbor to display information about\n"
13868 "Neighbor to display information about\n"
91d37724 13869 "Neighbor on BGP configured interface\n"
a636c635 13870 "Display detailed prefix count information\n"
9973d184 13871 JSON_STR)
a636c635 13872{
d62a17ae 13873 int idx_peer = 6;
13874 struct peer *peer;
9f049418 13875 bool uj = use_json(argc, argv);
a636c635 13876
d62a17ae 13877 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13878 if (!peer)
13879 return CMD_WARNING;
13880
13881 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13882}
13883
d6902373
PG
13884DEFUN (show_ip_bgp_vpn_all_route_prefix,
13885 show_ip_bgp_vpn_all_route_prefix_cmd,
13886 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13887 SHOW_STR
13888 IP_STR
13889 BGP_STR
d6902373 13890 BGP_VPNVX_HELP_STR
91d37724
QY
13891 "Display information about all VPNv4 NLRIs\n"
13892 "Network in the BGP routing table to display\n"
3a2d747c 13893 "Network in the BGP routing table to display\n"
9973d184 13894 JSON_STR)
91d37724 13895{
d62a17ae 13896 int idx = 0;
13897 char *network = NULL;
13898 struct bgp *bgp = bgp_get_default();
13899 if (!bgp) {
13900 vty_out(vty, "Can't find default instance\n");
13901 return CMD_WARNING;
13902 }
87e34b58 13903
d62a17ae 13904 if (argv_find(argv, argc, "A.B.C.D", &idx))
13905 network = argv[idx]->arg;
13906 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13907 network = argv[idx]->arg;
13908 else {
13909 vty_out(vty, "Unable to figure out Network\n");
13910 return CMD_WARNING;
13911 }
87e34b58 13912
d62a17ae 13913 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13914 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13915 use_json(argc, argv));
91d37724 13916}
d6902373 13917#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13918
44c69747
LK
13919DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13920 show_bgp_l2vpn_evpn_route_prefix_cmd,
13921 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13922 SHOW_STR
4c63a661
PG
13923 BGP_STR
13924 L2VPN_HELP_STR
13925 EVPN_HELP_STR
44c69747
LK
13926 "Network in the BGP routing table to display\n"
13927 "Network in the BGP routing table to display\n"
4c63a661
PG
13928 "Network in the BGP routing table to display\n"
13929 "Network in the BGP routing table to display\n"
13930 JSON_STR)
13931{
d62a17ae 13932 int idx = 0;
13933 char *network = NULL;
44c69747 13934 int prefix_check = 0;
a636c635 13935
44c69747
LK
13936 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13937 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13938 network = argv[idx]->arg;
44c69747 13939 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13940 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13941 network = argv[idx]->arg;
44c69747
LK
13942 prefix_check = 1;
13943 } else {
d62a17ae 13944 vty_out(vty, "Unable to figure out Network\n");
13945 return CMD_WARNING;
13946 }
44c69747
LK
13947 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13948 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13949 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13950}
13951
114fc229 13952static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13953 struct bgp_table *table, int *header1,
13954 int *header2, json_object *json,
13955 json_object *json_scode,
13956 json_object *json_ocode, bool wide)
13957{
13958 uint64_t version = table ? table->version : 0;
13959
13960 if (*header1) {
13961 if (json) {
13962 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13963 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13964 "%pI4", &peer->bgp->router_id);
2f9bc755 13965 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13966 peer->bgp->default_local_pref);
13967 json_object_int_add(json, "localAS",
13968 peer->change_local_as
13969 ? peer->change_local_as
13970 : peer->local_as);
2f9bc755
DS
13971 json_object_object_add(json, "bgpStatusCodes",
13972 json_scode);
13973 json_object_object_add(json, "bgpOriginCodes",
13974 json_ocode);
13975 } else {
13976 vty_out(vty,
23d0a753
DA
13977 "BGP table version is %" PRIu64
13978 ", local router ID is %pI4, vrf id ",
114fc229
DA
13979 version, &peer->bgp->router_id);
13980 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13981 vty_out(vty, "%s", VRFID_NONE_STR);
13982 else
114fc229 13983 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13984 vty_out(vty, "\n");
13985 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13986 peer->bgp->default_local_pref);
13987 vty_out(vty, "local AS %u\n",
13988 peer->change_local_as ? peer->change_local_as
13989 : peer->local_as);
2f9bc755
DS
13990 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13991 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13992 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13993 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13994 }
13995 *header1 = 0;
13996 }
13997 if (*header2) {
13998 if (!json)
13999 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
14000 : BGP_SHOW_HEADER));
14001 *header2 = 0;
14002 }
14003}
14004
d9478df0
TA
14005static void
14006show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
14007 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
14008 const char *rmap_name, json_object *json, json_object *json_ar,
14009 json_object *json_scode, json_object *json_ocode,
96c81f66 14010 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 14011 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 14012{
d62a17ae 14013 struct bgp_adj_in *ain;
14014 struct bgp_adj_out *adj;
9bcb3eef 14015 struct bgp_dest *dest;
d62a17ae 14016 struct bgp *bgp;
d62a17ae 14017 struct attr attr;
14018 int ret;
14019 struct update_subgroup *subgrp;
d62a17ae 14020 struct peer_af *paf;
f99def61 14021 bool route_filtered;
96f3485c
MK
14022 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14023 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
14024 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14025 || (safi == SAFI_EVPN))
14026 ? true
14027 : false;
a636c635 14028
d62a17ae 14029 bgp = peer->bgp;
a636c635 14030
d62a17ae 14031 subgrp = peer_subgroup(peer, afi, safi);
14032
6392aaa6 14033 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 14034 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14035 if (use_json) {
14036 json_object_int_add(json, "bgpTableVersion",
14037 table->version);
c949c771
DA
14038 json_object_string_addf(json, "bgpLocalRouterId",
14039 "%pI4", &bgp->router_id);
01eced22
AD
14040 json_object_int_add(json, "defaultLocPrf",
14041 bgp->default_local_pref);
114fc229
DA
14042 json_object_int_add(json, "localAS",
14043 peer->change_local_as
14044 ? peer->change_local_as
14045 : peer->local_as);
d62a17ae 14046 json_object_object_add(json, "bgpStatusCodes",
14047 json_scode);
14048 json_object_object_add(json, "bgpOriginCodes",
14049 json_ocode);
07d0c4ed
DA
14050 json_object_string_add(
14051 json, "bgpOriginatingDefaultNetwork",
14052 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14053 } else {
23d0a753
DA
14054 vty_out(vty,
14055 "BGP table version is %" PRIu64
14056 ", local router ID is %pI4, vrf id ",
14057 table->version, &bgp->router_id);
9df8b37c
PZ
14058 if (bgp->vrf_id == VRF_UNKNOWN)
14059 vty_out(vty, "%s", VRFID_NONE_STR);
14060 else
14061 vty_out(vty, "%u", bgp->vrf_id);
14062 vty_out(vty, "\n");
01eced22
AD
14063 vty_out(vty, "Default local pref %u, ",
14064 bgp->default_local_pref);
114fc229
DA
14065 vty_out(vty, "local AS %u\n",
14066 peer->change_local_as ? peer->change_local_as
14067 : peer->local_as);
d62a17ae 14068 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 14069 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 14070 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 14071 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 14072
07d0c4ed
DA
14073 vty_out(vty, "Originating default network %s\n\n",
14074 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 14075 }
d9478df0 14076 *header1 = 0;
d62a17ae 14077 }
a636c635 14078
9bcb3eef 14079 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
14080 if (type == bgp_show_adj_route_received
14081 || type == bgp_show_adj_route_filtered) {
9bcb3eef 14082 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 14083 if (ain->peer != peer)
ea47320b 14084 continue;
6392aaa6 14085
114fc229 14086 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
14087 header2, json, json_scode,
14088 json_ocode, wide);
14089
14090 if ((safi == SAFI_MPLS_VPN)
14091 || (safi == SAFI_ENCAP)
14092 || (safi == SAFI_EVPN)) {
14093 if (use_json)
14094 json_object_string_add(
14095 json_ar, "rd", rd_str);
14096 else if (show_rd && rd_str) {
14097 vty_out(vty,
14098 "Route Distinguisher: %s\n",
14099 rd_str);
14100 show_rd = false;
14101 }
14102 }
6392aaa6 14103
6f4f49b2 14104 attr = *ain->attr;
f99def61
AD
14105 route_filtered = false;
14106
14107 /* Filter prefix using distribute list,
14108 * filter list or prefix list
14109 */
b54892e0 14110 const struct prefix *rn_p =
9bcb3eef 14111 bgp_dest_get_prefix(dest);
b54892e0
DS
14112 if ((bgp_input_filter(peer, rn_p, &attr, afi,
14113 safi))
14114 == FILTER_DENY)
f99def61
AD
14115 route_filtered = true;
14116
14117 /* Filter prefix using route-map */
b54892e0
DS
14118 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14119 safi, rmap_name, NULL,
14120 0, NULL);
6392aaa6 14121
13c8e163
AD
14122 if (type == bgp_show_adj_route_filtered &&
14123 !route_filtered && ret != RMAP_DENY) {
d498917e 14124 bgp_attr_flush(&attr);
6392aaa6 14125 continue;
d62a17ae 14126 }
6392aaa6 14127
d9478df0
TA
14128 if (type == bgp_show_adj_route_received
14129 && (route_filtered || ret == RMAP_DENY))
14130 (*filtered_count)++;
6392aaa6 14131
7d3cae70 14132 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 14133 use_json, json_ar, wide);
d498917e 14134 bgp_attr_flush(&attr);
d9478df0 14135 (*output_count)++;
d62a17ae 14136 }
6392aaa6 14137 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 14138 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 14139 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 14140 if (paf->peer != peer || !adj->attr)
924c3f6a 14141 continue;
d62a17ae 14142
114fc229 14143 show_adj_route_header(vty, peer, table,
d9478df0
TA
14144 header1, header2,
14145 json, json_scode,
14146 json_ocode, wide);
d62a17ae 14147
b54892e0 14148 const struct prefix *rn_p =
9bcb3eef 14149 bgp_dest_get_prefix(dest);
b54892e0 14150
6f4f49b2 14151 attr = *adj->attr;
b755861b 14152 ret = bgp_output_modifier(
b54892e0 14153 peer, rn_p, &attr, afi, safi,
b755861b 14154 rmap_name);
f46d8e1e 14155
b755861b 14156 if (ret != RMAP_DENY) {
d9478df0
TA
14157 if ((safi == SAFI_MPLS_VPN)
14158 || (safi == SAFI_ENCAP)
14159 || (safi == SAFI_EVPN)) {
14160 if (use_json)
14161 json_object_string_add(
14162 json_ar,
14163 "rd",
14164 rd_str);
14165 else if (show_rd
14166 && rd_str) {
14167 vty_out(vty,
14168 "Route Distinguisher: %s\n",
14169 rd_str);
14170 show_rd = false;
14171 }
14172 }
b54892e0 14173 route_vty_out_tmp(
7d3cae70
DA
14174 vty, dest, rn_p, &attr,
14175 safi, use_json, json_ar,
ae248832 14176 wide);
d9478df0 14177 (*output_count)++;
b755861b 14178 } else {
d9478df0 14179 (*filtered_count)++;
a2addae8 14180 }
b755861b 14181
d498917e 14182 bgp_attr_flush(&attr);
924c3f6a 14183 }
f20ce998
DS
14184 } else if (type == bgp_show_adj_route_bestpath) {
14185 struct bgp_path_info *pi;
14186
114fc229
DA
14187 show_adj_route_header(vty, peer, table, header1,
14188 header2, json, json_scode,
14189 json_ocode, wide);
f20ce998
DS
14190
14191 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14192 pi = pi->next) {
14193 if (pi->peer != peer)
14194 continue;
14195
14196 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14197 continue;
14198
7d3cae70 14199 route_vty_out_tmp(vty, dest,
f20ce998
DS
14200 bgp_dest_get_prefix(dest),
14201 pi->attr, safi, use_json,
14202 json_ar, wide);
d9478df0 14203 (*output_count)++;
f20ce998 14204 }
d62a17ae 14205 }
14206 }
a636c635 14207}
2a71e9ce 14208
d62a17ae 14209static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 14210 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 14211 const char *rmap_name, uint16_t show_flags)
0b16f239 14212{
d9478df0
TA
14213 struct bgp *bgp;
14214 struct bgp_table *table;
d62a17ae 14215 json_object *json = NULL;
d9478df0
TA
14216 json_object *json_scode = NULL;
14217 json_object *json_ocode = NULL;
14218 json_object *json_ar = NULL;
96f3485c 14219 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 14220
d9478df0
TA
14221 /* Init BGP headers here so they're only displayed once
14222 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14223 */
14224 int header1 = 1;
14225 int header2 = 1;
14226
14227 /*
14228 * Initialize variables for each RD
14229 * All prefixes under an RD is aggregated within "json_routes"
14230 */
14231 char rd_str[BUFSIZ] = {0};
14232 json_object *json_routes = NULL;
14233
14234
14235 /* For 2-tier tables, prefix counts need to be
14236 * maintained across multiple runs of show_adj_route()
14237 */
14238 unsigned long output_count_per_rd;
14239 unsigned long filtered_count_per_rd;
14240 unsigned long output_count = 0;
14241 unsigned long filtered_count = 0;
14242
14243 if (use_json) {
d62a17ae 14244 json = json_object_new_object();
d9478df0
TA
14245 json_ar = json_object_new_object();
14246 json_scode = json_object_new_object();
14247 json_ocode = json_object_new_object();
14248
14249 json_object_string_add(json_scode, "suppressed", "s");
14250 json_object_string_add(json_scode, "damped", "d");
14251 json_object_string_add(json_scode, "history", "h");
14252 json_object_string_add(json_scode, "valid", "*");
14253 json_object_string_add(json_scode, "best", ">");
14254 json_object_string_add(json_scode, "multipath", "=");
14255 json_object_string_add(json_scode, "internal", "i");
14256 json_object_string_add(json_scode, "ribFailure", "r");
14257 json_object_string_add(json_scode, "stale", "S");
14258 json_object_string_add(json_scode, "removed", "R");
14259
14260 json_object_string_add(json_ocode, "igp", "i");
14261 json_object_string_add(json_ocode, "egp", "e");
14262 json_object_string_add(json_ocode, "incomplete", "?");
14263 }
0b16f239 14264
d62a17ae 14265 if (!peer || !peer->afc[afi][safi]) {
14266 if (use_json) {
14267 json_object_string_add(
14268 json, "warning",
14269 "No such neighbor or address family");
14270 vty_out(vty, "%s\n", json_object_to_json_string(json));
14271 json_object_free(json);
690c3134
MW
14272 json_object_free(json_ar);
14273 json_object_free(json_scode);
14274 json_object_free(json_ocode);
d62a17ae 14275 } else
14276 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14277
d62a17ae 14278 return CMD_WARNING;
14279 }
14280
6392aaa6
PM
14281 if ((type == bgp_show_adj_route_received
14282 || type == bgp_show_adj_route_filtered)
d62a17ae 14283 && !CHECK_FLAG(peer->af_flags[afi][safi],
14284 PEER_FLAG_SOFT_RECONFIG)) {
14285 if (use_json) {
14286 json_object_string_add(
14287 json, "warning",
14288 "Inbound soft reconfiguration not enabled");
14289 vty_out(vty, "%s\n", json_object_to_json_string(json));
14290 json_object_free(json);
690c3134
MW
14291 json_object_free(json_ar);
14292 json_object_free(json_scode);
14293 json_object_free(json_ocode);
d62a17ae 14294 } else
14295 vty_out(vty,
14296 "%% Inbound soft reconfiguration not enabled\n");
14297
14298 return CMD_WARNING;
14299 }
0b16f239 14300
d9478df0
TA
14301 bgp = peer->bgp;
14302
14303 /* labeled-unicast routes live in the unicast table */
14304 if (safi == SAFI_LABELED_UNICAST)
14305 table = bgp->rib[afi][SAFI_UNICAST];
14306 else
14307 table = bgp->rib[afi][safi];
14308
14309 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14310 || (safi == SAFI_EVPN)) {
14311
14312 struct bgp_dest *dest;
14313
14314 for (dest = bgp_table_top(table); dest;
14315 dest = bgp_route_next(dest)) {
14316 table = bgp_dest_get_bgp_table_info(dest);
14317 if (!table)
14318 continue;
14319
14320 output_count_per_rd = 0;
14321 filtered_count_per_rd = 0;
14322
14323 if (use_json)
14324 json_routes = json_object_new_object();
14325
14326 const struct prefix_rd *prd;
14327 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14328 dest);
14329
14330 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14331
14332 show_adj_route(vty, peer, table, afi, safi, type,
14333 rmap_name, json, json_routes, json_scode,
14334 json_ocode, show_flags, &header1,
14335 &header2, rd_str, &output_count_per_rd,
14336 &filtered_count_per_rd);
14337
14338 /* Don't include an empty RD in the output! */
14339 if (json_routes && (output_count_per_rd > 0))
14340 json_object_object_add(json_ar, rd_str,
14341 json_routes);
14342
14343 output_count += output_count_per_rd;
14344 filtered_count += filtered_count_per_rd;
14345 }
14346 } else
14347 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14348 json, json_ar, json_scode, json_ocode,
14349 show_flags, &header1, &header2, rd_str,
14350 &output_count, &filtered_count);
14351
14352 if (use_json) {
c1984955
TA
14353 if (type == bgp_show_adj_route_advertised)
14354 json_object_object_add(json, "advertisedRoutes",
14355 json_ar);
14356 else
14357 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14358 json_object_int_add(json, "totalPrefixCounter", output_count);
14359 json_object_int_add(json, "filteredPrefixCounter",
14360 filtered_count);
14361
690c3134
MW
14362 /*
14363 * These fields only give up ownership to `json` when `header1`
14364 * is used (set to zero). See code in `show_adj_route` and
14365 * `show_adj_route_header`.
14366 */
14367 if (header1 == 1) {
d9478df0
TA
14368 json_object_free(json_scode);
14369 json_object_free(json_ocode);
14370 }
14371
75eeda93 14372 vty_json(vty, json);
d9478df0
TA
14373 } else if (output_count > 0) {
14374 if (filtered_count > 0)
14375 vty_out(vty,
14376 "\nTotal number of prefixes %ld (%ld filtered)\n",
14377 output_count, filtered_count);
14378 else
14379 vty_out(vty, "\nTotal number of prefixes %ld\n",
14380 output_count);
14381 }
0b16f239 14382
d62a17ae 14383 return CMD_SUCCESS;
a636c635 14384}
50ef26d4 14385
f20ce998
DS
14386DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14387 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14388 "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]",
14389 SHOW_STR
14390 IP_STR
14391 BGP_STR
14392 BGP_INSTANCE_HELP_STR
14393 BGP_AFI_HELP_STR
14394 BGP_SAFI_WITH_LABEL_HELP_STR
14395 "Detailed information on TCP and BGP neighbor connections\n"
14396 "Neighbor to display information about\n"
14397 "Neighbor to display information about\n"
14398 "Neighbor on BGP configured interface\n"
14399 "Display the routes selected by best path\n"
14400 JSON_STR
14401 "Increase table width for longer prefixes\n")
14402{
14403 afi_t afi = AFI_IP6;
14404 safi_t safi = SAFI_UNICAST;
14405 char *rmap_name = NULL;
14406 char *peerstr = NULL;
14407 struct bgp *bgp = NULL;
14408 struct peer *peer;
14409 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14410 int idx = 0;
96c81f66 14411 uint16_t show_flags = 0;
96f3485c
MK
14412
14413 if (uj)
14414 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14415
14416 if (wide)
14417 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14418
14419 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14420 &bgp, uj);
14421
14422 if (!idx)
14423 return CMD_WARNING;
14424
14425 argv_find(argv, argc, "neighbors", &idx);
14426 peerstr = argv[++idx]->arg;
14427
14428 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14429 if (!peer)
14430 return CMD_WARNING;
14431
96f3485c
MK
14432 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14433 show_flags);
f20ce998
DS
14434}
14435
ae248832 14436DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14437 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14438 "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 14439 SHOW_STR
14440 IP_STR
14441 BGP_STR
a636c635 14442 BGP_INSTANCE_HELP_STR
7395a2c9 14443 BGP_AFI_HELP_STR
4dd6177e 14444 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14445 "Display the entries for all address families\n"
718e3744 14446 "Detailed information on TCP and BGP neighbor connections\n"
14447 "Neighbor to display information about\n"
14448 "Neighbor to display information about\n"
91d37724 14449 "Neighbor on BGP configured interface\n"
a636c635 14450 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14451 "Display the received routes from neighbor\n"
14452 "Display the filtered routes received from neighbor\n"
a636c635
DW
14453 "Route-map to modify the attributes\n"
14454 "Name of the route map\n"
ae248832
MK
14455 JSON_STR
14456 "Increase table width for longer prefixes\n")
718e3744 14457{
d62a17ae 14458 afi_t afi = AFI_IP6;
14459 safi_t safi = SAFI_UNICAST;
d62a17ae 14460 char *peerstr = NULL;
d62a17ae 14461 struct bgp *bgp = NULL;
14462 struct peer *peer;
6392aaa6 14463 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14464 int idx = 0;
96f3485c 14465 bool first = true;
96c81f66 14466 uint16_t show_flags = 0;
75ce3b14
DA
14467 struct listnode *node;
14468 struct bgp *abgp;
6392aaa6 14469
96f3485c 14470 if (uj) {
d62a17ae 14471 argc--;
96f3485c
MK
14472 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14473 }
14474
14475 if (all) {
14476 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14477 if (argv_find(argv, argc, "ipv4", &idx))
14478 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14479
14480 if (argv_find(argv, argc, "ipv6", &idx))
14481 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14482 }
14483
14484 if (wide)
14485 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14486
9f049418
DS
14487 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14488 &bgp, uj);
14489 if (!idx)
14490 return CMD_WARNING;
14491
d62a17ae 14492 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14493 argv_find(argv, argc, "neighbors", &idx);
14494 peerstr = argv[++idx]->arg;
8c3deaae 14495
d62a17ae 14496 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14497 if (!peer)
14498 return CMD_WARNING;
856ca177 14499
d62a17ae 14500 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14501 type = bgp_show_adj_route_advertised;
14502 else if (argv_find(argv, argc, "received-routes", &idx))
14503 type = bgp_show_adj_route_received;
14504 else if (argv_find(argv, argc, "filtered-routes", &idx))
14505 type = bgp_show_adj_route_filtered;
14506
96f3485c 14507 if (!all)
70dd370f 14508 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14509 show_flags);
14510 if (uj)
14511 vty_out(vty, "{\n");
14512
14513 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14514 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14515 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14516 : AFI_IP6;
75ce3b14
DA
14517 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14518 FOREACH_SAFI (safi) {
14519 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14520 continue;
96f3485c 14521
75ce3b14
DA
14522 if (uj) {
14523 if (first)
14524 first = false;
14525 else
14526 vty_out(vty, ",\n");
14527 vty_out(vty, "\"%s\":",
14528 get_afi_safi_str(afi, safi,
14529 true));
14530 } else
14531 vty_out(vty,
14532 "\nFor address family: %s\n",
14533 get_afi_safi_str(afi, safi,
14534 false));
96f3485c 14535
75ce3b14 14536 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14537 route_map, show_flags);
75ce3b14 14538 }
96f3485c
MK
14539 }
14540 } else {
75ce3b14
DA
14541 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14542 FOREACH_AFI_SAFI (afi, safi) {
14543 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14544 continue;
96f3485c 14545
75ce3b14
DA
14546 if (uj) {
14547 if (first)
14548 first = false;
14549 else
14550 vty_out(vty, ",\n");
14551 vty_out(vty, "\"%s\":",
14552 get_afi_safi_str(afi, safi,
14553 true));
14554 } else
14555 vty_out(vty,
14556 "\nFor address family: %s\n",
14557 get_afi_safi_str(afi, safi,
14558 false));
96f3485c 14559
75ce3b14 14560 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14561 route_map, show_flags);
75ce3b14 14562 }
96f3485c
MK
14563 }
14564 }
14565 if (uj)
14566 vty_out(vty, "}\n");
14567
14568 return CMD_SUCCESS;
95cbbd2a
ML
14569}
14570
718e3744 14571DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14572 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14573 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14574 SHOW_STR
14575 IP_STR
14576 BGP_STR
d3120452 14577 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14578 BGP_AF_STR
14579 BGP_AF_STR
14580 BGP_AF_MODIFIER_STR
718e3744 14581 "Detailed information on TCP and BGP neighbor connections\n"
14582 "Neighbor to display information about\n"
14583 "Neighbor to display information about\n"
91d37724 14584 "Neighbor on BGP configured interface\n"
718e3744 14585 "Display information received from a BGP neighbor\n"
856ca177 14586 "Display the prefixlist filter\n"
9973d184 14587 JSON_STR)
718e3744 14588{
d62a17ae 14589 afi_t afi = AFI_IP6;
14590 safi_t safi = SAFI_UNICAST;
14591 char *peerstr = NULL;
d62a17ae 14592 char name[BUFSIZ];
d62a17ae 14593 struct peer *peer;
d3120452 14594 int count;
d62a17ae 14595 int idx = 0;
d3120452
IR
14596 struct bgp *bgp = NULL;
14597 bool uj = use_json(argc, argv);
14598
14599 if (uj)
14600 argc--;
14601
14602 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14603 &bgp, uj);
14604 if (!idx)
14605 return CMD_WARNING;
d62a17ae 14606
d62a17ae 14607 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14608 argv_find(argv, argc, "neighbors", &idx);
14609 peerstr = argv[++idx]->arg;
14610
d3120452
IR
14611 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14612 if (!peer)
14613 return CMD_WARNING;
718e3744 14614
4ced1a2c 14615 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14616 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14617 if (count) {
14618 if (!uj)
14619 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14620 get_afi_safi_str(afi, safi, false));
d62a17ae 14621 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14622 } else {
14623 if (uj)
14624 vty_out(vty, "{}\n");
14625 else
14626 vty_out(vty, "No functional output\n");
14627 }
718e3744 14628
d62a17ae 14629 return CMD_SUCCESS;
14630}
14631
14632static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14633 afi_t afi, safi_t safi,
9f049418 14634 enum bgp_show_type type, bool use_json)
d62a17ae 14635{
96c81f66 14636 uint16_t show_flags = 0;
96f3485c
MK
14637
14638 if (use_json)
14639 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14640
d62a17ae 14641 if (!peer || !peer->afc[afi][safi]) {
14642 if (use_json) {
14643 json_object *json_no = NULL;
14644 json_no = json_object_new_object();
14645 json_object_string_add(
14646 json_no, "warning",
14647 "No such neighbor or address family");
14648 vty_out(vty, "%s\n",
14649 json_object_to_json_string(json_no));
14650 json_object_free(json_no);
14651 } else
14652 vty_out(vty, "%% No such neighbor or address family\n");
14653 return CMD_WARNING;
14654 }
47fc97cc 14655
7daf25a3
TA
14656 /* labeled-unicast routes live in the unicast table */
14657 if (safi == SAFI_LABELED_UNICAST)
14658 safi = SAFI_UNICAST;
14659
1e2ce4f1
DS
14660 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14661 RPKI_NOT_BEING_USED);
718e3744 14662}
14663
dba3c1d3
PG
14664DEFUN (show_ip_bgp_flowspec_routes_detailed,
14665 show_ip_bgp_flowspec_routes_detailed_cmd,
14666 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14667 SHOW_STR
14668 IP_STR
14669 BGP_STR
14670 BGP_INSTANCE_HELP_STR
14671 BGP_AFI_HELP_STR
14672 "SAFI Flowspec\n"
14673 "Detailed information on flowspec entries\n"
14674 JSON_STR)
14675{
458c1475 14676 afi_t afi = AFI_IP6;
dba3c1d3
PG
14677 safi_t safi = SAFI_UNICAST;
14678 struct bgp *bgp = NULL;
14679 int idx = 0;
9f049418 14680 bool uj = use_json(argc, argv);
5be6fa9b 14681 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14682
96f3485c 14683 if (uj) {
9f049418 14684 argc--;
96f3485c
MK
14685 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14686 }
dba3c1d3
PG
14687
14688 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14689 &bgp, uj);
dba3c1d3
PG
14690 if (!idx)
14691 return CMD_WARNING;
14692
96f3485c 14693 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14694 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14695}
14696
718e3744 14697DEFUN (show_ip_bgp_neighbor_routes,
14698 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14699 "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 14700 SHOW_STR
14701 IP_STR
14702 BGP_STR
8386ac43 14703 BGP_INSTANCE_HELP_STR
4f280b15 14704 BGP_AFI_HELP_STR
4dd6177e 14705 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14706 "Detailed information on TCP and BGP neighbor connections\n"
14707 "Neighbor to display information about\n"
14708 "Neighbor to display information about\n"
91d37724 14709 "Neighbor on BGP configured interface\n"
2525cf39 14710 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14711 "Display the dampened routes received from neighbor\n"
14712 "Display routes learned from neighbor\n"
9973d184 14713 JSON_STR)
718e3744 14714{
d62a17ae 14715 char *peerstr = NULL;
14716 struct bgp *bgp = NULL;
14717 afi_t afi = AFI_IP6;
14718 safi_t safi = SAFI_UNICAST;
14719 struct peer *peer;
14720 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14721 int idx = 0;
9f049418
DS
14722 bool uj = use_json(argc, argv);
14723
14724 if (uj)
14725 argc--;
bb46e94f 14726
d62a17ae 14727 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14728 &bgp, uj);
d62a17ae 14729 if (!idx)
14730 return CMD_WARNING;
c493f2d8 14731
d62a17ae 14732 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14733 argv_find(argv, argc, "neighbors", &idx);
14734 peerstr = argv[++idx]->arg;
8c3deaae 14735
d62a17ae 14736 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14737 if (!peer)
d62a17ae 14738 return CMD_WARNING;
bb46e94f 14739
d62a17ae 14740 if (argv_find(argv, argc, "flap-statistics", &idx))
14741 sh_type = bgp_show_type_flap_neighbor;
14742 else if (argv_find(argv, argc, "dampened-routes", &idx))
14743 sh_type = bgp_show_type_damp_neighbor;
14744 else if (argv_find(argv, argc, "routes", &idx))
14745 sh_type = bgp_show_type_neighbor;
2525cf39 14746
d62a17ae 14747 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14748}
6b0655a2 14749
734b349e 14750struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14751
d62a17ae 14752struct bgp_distance {
14753 /* Distance value for the IP source prefix. */
d7c0a89a 14754 uint8_t distance;
718e3744 14755
d62a17ae 14756 /* Name of the access-list to be matched. */
14757 char *access_list;
718e3744 14758};
14759
4f280b15
LB
14760DEFUN (show_bgp_afi_vpn_rd_route,
14761 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14762 "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
14763 SHOW_STR
14764 BGP_STR
14765 BGP_AFI_HELP_STR
00e6edb9 14766 BGP_AF_MODIFIER_STR
4f280b15
LB
14767 "Display information for a route distinguisher\n"
14768 "Route Distinguisher\n"
a111dd97 14769 "All Route Distinguishers\n"
7395a2c9
DS
14770 "Network in the BGP routing table to display\n"
14771 "Network in the BGP routing table to display\n"
14772 JSON_STR)
4f280b15 14773{
d62a17ae 14774 int ret;
14775 struct prefix_rd prd;
14776 afi_t afi = AFI_MAX;
14777 int idx = 0;
4f280b15 14778
ff6566f3
DS
14779 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14780 vty_out(vty, "%% Malformed Address Family\n");
14781 return CMD_WARNING;
14782 }
14783
a111dd97
TA
14784 if (!strcmp(argv[5]->arg, "all"))
14785 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14786 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14787 RPKI_NOT_BEING_USED,
14788 use_json(argc, argv));
14789
d62a17ae 14790 ret = str2prefix_rd(argv[5]->arg, &prd);
14791 if (!ret) {
14792 vty_out(vty, "%% Malformed Route Distinguisher\n");
14793 return CMD_WARNING;
14794 }
ff6566f3 14795
d62a17ae 14796 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14797 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14798 use_json(argc, argv));
4f280b15
LB
14799}
14800
d62a17ae 14801static struct bgp_distance *bgp_distance_new(void)
718e3744 14802{
d62a17ae 14803 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14804}
14805
d62a17ae 14806static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14807{
d62a17ae 14808 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14809}
14810
585f1adc
IR
14811static int bgp_distance_set(struct vty *vty, const char *distance_str,
14812 const char *ip_str, const char *access_list_str)
718e3744 14813{
d62a17ae 14814 int ret;
585f1adc
IR
14815 afi_t afi;
14816 safi_t safi;
d62a17ae 14817 struct prefix p;
585f1adc 14818 uint8_t distance;
9bcb3eef 14819 struct bgp_dest *dest;
d62a17ae 14820 struct bgp_distance *bdistance;
718e3744 14821
585f1adc
IR
14822 afi = bgp_node_afi(vty);
14823 safi = bgp_node_safi(vty);
14824
d62a17ae 14825 ret = str2prefix(ip_str, &p);
14826 if (ret == 0) {
585f1adc 14827 vty_out(vty, "Malformed prefix\n");
d62a17ae 14828 return CMD_WARNING_CONFIG_FAILED;
14829 }
718e3744 14830
585f1adc
IR
14831 distance = atoi(distance_str);
14832
d62a17ae 14833 /* Get BGP distance node. */
9bcb3eef
DS
14834 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14835 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14836 if (bdistance)
9bcb3eef 14837 bgp_dest_unlock_node(dest);
ca2e160d 14838 else {
d62a17ae 14839 bdistance = bgp_distance_new();
9bcb3eef 14840 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14841 }
718e3744 14842
d62a17ae 14843 /* Set distance value. */
14844 bdistance->distance = distance;
718e3744 14845
d62a17ae 14846 /* Reset access-list configuration. */
e1b36e13 14847 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14848 if (access_list_str)
14849 bdistance->access_list =
14850 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14851
d62a17ae 14852 return CMD_SUCCESS;
718e3744 14853}
14854
585f1adc
IR
14855static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14856 const char *ip_str, const char *access_list_str)
718e3744 14857{
d62a17ae 14858 int ret;
585f1adc
IR
14859 afi_t afi;
14860 safi_t safi;
d62a17ae 14861 struct prefix p;
585f1adc 14862 int distance;
9bcb3eef 14863 struct bgp_dest *dest;
d62a17ae 14864 struct bgp_distance *bdistance;
718e3744 14865
585f1adc
IR
14866 afi = bgp_node_afi(vty);
14867 safi = bgp_node_safi(vty);
14868
d62a17ae 14869 ret = str2prefix(ip_str, &p);
14870 if (ret == 0) {
585f1adc 14871 vty_out(vty, "Malformed prefix\n");
d62a17ae 14872 return CMD_WARNING_CONFIG_FAILED;
14873 }
718e3744 14874
9bcb3eef
DS
14875 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14876 if (!dest) {
585f1adc 14877 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14878 return CMD_WARNING_CONFIG_FAILED;
14879 }
718e3744 14880
9bcb3eef 14881 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14882 distance = atoi(distance_str);
1f9a9fff 14883
d62a17ae 14884 if (bdistance->distance != distance) {
585f1adc 14885 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14886 bgp_dest_unlock_node(dest);
d62a17ae 14887 return CMD_WARNING_CONFIG_FAILED;
14888 }
718e3744 14889
0a22ddfb 14890 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14891 bgp_distance_free(bdistance);
718e3744 14892
9bcb3eef
DS
14893 bgp_dest_set_bgp_path_info(dest, NULL);
14894 bgp_dest_unlock_node(dest);
14895 bgp_dest_unlock_node(dest);
718e3744 14896
d62a17ae 14897 return CMD_SUCCESS;
718e3744 14898}
14899
718e3744 14900/* Apply BGP information to distance method. */
b8685f9b 14901uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14902 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14903{
9bcb3eef 14904 struct bgp_dest *dest;
801bb996 14905 struct prefix q = {0};
d62a17ae 14906 struct peer *peer;
14907 struct bgp_distance *bdistance;
14908 struct access_list *alist;
14909 struct bgp_static *bgp_static;
14910
14911 if (!bgp)
14912 return 0;
14913
40381db7 14914 peer = pinfo->peer;
d62a17ae 14915
7b7d48e5
DS
14916 if (pinfo->attr->distance)
14917 return pinfo->attr->distance;
14918
801bb996
CS
14919 /* Check source address.
14920 * Note: for aggregate route, peer can have unspec af type.
14921 */
14922 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14923 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14924 return 0;
14925
9bcb3eef
DS
14926 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14927 if (dest) {
14928 bdistance = bgp_dest_get_bgp_distance_info(dest);
14929 bgp_dest_unlock_node(dest);
d62a17ae 14930
14931 if (bdistance->access_list) {
14932 alist = access_list_lookup(afi, bdistance->access_list);
14933 if (alist
14934 && access_list_apply(alist, p) == FILTER_PERMIT)
14935 return bdistance->distance;
14936 } else
14937 return bdistance->distance;
718e3744 14938 }
718e3744 14939
d62a17ae 14940 /* Backdoor check. */
9bcb3eef
DS
14941 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14942 if (dest) {
14943 bgp_static = bgp_dest_get_bgp_static_info(dest);
14944 bgp_dest_unlock_node(dest);
718e3744 14945
d62a17ae 14946 if (bgp_static->backdoor) {
14947 if (bgp->distance_local[afi][safi])
14948 return bgp->distance_local[afi][safi];
14949 else
14950 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14951 }
718e3744 14952 }
718e3744 14953
d62a17ae 14954 if (peer->sort == BGP_PEER_EBGP) {
14955 if (bgp->distance_ebgp[afi][safi])
14956 return bgp->distance_ebgp[afi][safi];
14957 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14958 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14959 if (bgp->distance_ibgp[afi][safi])
14960 return bgp->distance_ibgp[afi][safi];
14961 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14962 } else {
14963 if (bgp->distance_local[afi][safi])
14964 return bgp->distance_local[afi][safi];
14965 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14966 }
718e3744 14967}
14968
a612fb77
DA
14969/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14970 * we should tell ZEBRA update the routes for a specific
14971 * AFI/SAFI to reflect changes in RIB.
14972 */
585f1adc
IR
14973static void bgp_announce_routes_distance_update(struct bgp *bgp,
14974 afi_t update_afi,
14975 safi_t update_safi)
a612fb77
DA
14976{
14977 afi_t afi;
14978 safi_t safi;
14979
14980 FOREACH_AFI_SAFI (afi, safi) {
14981 if (!bgp_fibupd_safi(safi))
14982 continue;
14983
8b54bc30
DA
14984 if (afi != update_afi && safi != update_safi)
14985 continue;
14986
14987 if (BGP_DEBUG(zebra, ZEBRA))
14988 zlog_debug(
14989 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14990 __func__, afi, safi);
14991 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14992 }
14993}
14994
585f1adc
IR
14995DEFUN (bgp_distance,
14996 bgp_distance_cmd,
14997 "distance bgp (1-255) (1-255) (1-255)",
14998 "Define an administrative distance\n"
14999 "BGP distance\n"
15000 "Distance for routes external to the AS\n"
15001 "Distance for routes internal to the AS\n"
15002 "Distance for local routes\n")
718e3744 15003{
585f1adc 15004 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 15005 int idx_number = 2;
15006 int idx_number_2 = 3;
15007 int idx_number_3 = 4;
585f1adc
IR
15008 int distance_ebgp = atoi(argv[idx_number]->arg);
15009 int distance_ibgp = atoi(argv[idx_number_2]->arg);
15010 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 15011 afi_t afi;
15012 safi_t safi;
718e3744 15013
d62a17ae 15014 afi = bgp_node_afi(vty);
15015 safi = bgp_node_safi(vty);
718e3744 15016
585f1adc
IR
15017 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15018 || bgp->distance_ibgp[afi][safi] != distance_ibgp
15019 || bgp->distance_local[afi][safi] != distance_local) {
15020 bgp->distance_ebgp[afi][safi] = distance_ebgp;
15021 bgp->distance_ibgp[afi][safi] = distance_ibgp;
15022 bgp->distance_local[afi][safi] = distance_local;
15023 bgp_announce_routes_distance_update(bgp, afi, safi);
15024 }
15025 return CMD_SUCCESS;
15026}
37a87b8f 15027
585f1adc
IR
15028DEFUN (no_bgp_distance,
15029 no_bgp_distance_cmd,
15030 "no distance bgp [(1-255) (1-255) (1-255)]",
15031 NO_STR
15032 "Define an administrative distance\n"
15033 "BGP distance\n"
15034 "Distance for routes external to the AS\n"
15035 "Distance for routes internal to the AS\n"
15036 "Distance for local routes\n")
718e3744 15037{
585f1adc 15038 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
15039 afi_t afi;
15040 safi_t safi;
37a87b8f
CS
15041
15042 afi = bgp_node_afi(vty);
15043 safi = bgp_node_safi(vty);
15044
585f1adc
IR
15045 if (bgp->distance_ebgp[afi][safi] != 0
15046 || bgp->distance_ibgp[afi][safi] != 0
15047 || bgp->distance_local[afi][safi] != 0) {
15048 bgp->distance_ebgp[afi][safi] = 0;
15049 bgp->distance_ibgp[afi][safi] = 0;
15050 bgp->distance_local[afi][safi] = 0;
15051 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 15052 }
585f1adc
IR
15053 return CMD_SUCCESS;
15054}
37a87b8f 15055
37a87b8f 15056
585f1adc
IR
15057DEFUN (bgp_distance_source,
15058 bgp_distance_source_cmd,
15059 "distance (1-255) A.B.C.D/M",
15060 "Define an administrative distance\n"
15061 "Administrative distance\n"
15062 "IP source prefix\n")
15063{
15064 int idx_number = 1;
15065 int idx_ipv4_prefixlen = 2;
15066 bgp_distance_set(vty, argv[idx_number]->arg,
15067 argv[idx_ipv4_prefixlen]->arg, NULL);
15068 return CMD_SUCCESS;
734b349e
MZ
15069}
15070
585f1adc
IR
15071DEFUN (no_bgp_distance_source,
15072 no_bgp_distance_source_cmd,
15073 "no distance (1-255) A.B.C.D/M",
15074 NO_STR
15075 "Define an administrative distance\n"
15076 "Administrative distance\n"
15077 "IP source prefix\n")
37a87b8f 15078{
585f1adc
IR
15079 int idx_number = 2;
15080 int idx_ipv4_prefixlen = 3;
15081 bgp_distance_unset(vty, argv[idx_number]->arg,
15082 argv[idx_ipv4_prefixlen]->arg, NULL);
15083 return CMD_SUCCESS;
37a87b8f
CS
15084}
15085
585f1adc
IR
15086DEFUN (bgp_distance_source_access_list,
15087 bgp_distance_source_access_list_cmd,
15088 "distance (1-255) A.B.C.D/M WORD",
15089 "Define an administrative distance\n"
15090 "Administrative distance\n"
15091 "IP source prefix\n"
15092 "Access list name\n")
37a87b8f 15093{
585f1adc
IR
15094 int idx_number = 1;
15095 int idx_ipv4_prefixlen = 2;
15096 int idx_word = 3;
15097 bgp_distance_set(vty, argv[idx_number]->arg,
15098 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15099 return CMD_SUCCESS;
15100}
718e3744 15101
585f1adc
IR
15102DEFUN (no_bgp_distance_source_access_list,
15103 no_bgp_distance_source_access_list_cmd,
15104 "no distance (1-255) A.B.C.D/M WORD",
15105 NO_STR
15106 "Define an administrative distance\n"
15107 "Administrative distance\n"
15108 "IP source prefix\n"
15109 "Access list name\n")
15110{
15111 int idx_number = 2;
15112 int idx_ipv4_prefixlen = 3;
15113 int idx_word = 4;
15114 bgp_distance_unset(vty, argv[idx_number]->arg,
15115 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15116 return CMD_SUCCESS;
15117}
37a87b8f 15118
585f1adc
IR
15119DEFUN (ipv6_bgp_distance_source,
15120 ipv6_bgp_distance_source_cmd,
15121 "distance (1-255) X:X::X:X/M",
15122 "Define an administrative distance\n"
15123 "Administrative distance\n"
15124 "IP source prefix\n")
15125{
15126 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15127 return CMD_SUCCESS;
15128}
7ebe9748 15129
585f1adc
IR
15130DEFUN (no_ipv6_bgp_distance_source,
15131 no_ipv6_bgp_distance_source_cmd,
15132 "no distance (1-255) X:X::X:X/M",
15133 NO_STR
15134 "Define an administrative distance\n"
15135 "Administrative distance\n"
15136 "IP source prefix\n")
15137{
15138 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15139 return CMD_SUCCESS;
15140}
37a87b8f 15141
585f1adc
IR
15142DEFUN (ipv6_bgp_distance_source_access_list,
15143 ipv6_bgp_distance_source_access_list_cmd,
15144 "distance (1-255) X:X::X:X/M WORD",
15145 "Define an administrative distance\n"
15146 "Administrative distance\n"
15147 "IP source prefix\n"
15148 "Access list name\n")
15149{
15150 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15151 return CMD_SUCCESS;
718e3744 15152}
15153
585f1adc
IR
15154DEFUN (no_ipv6_bgp_distance_source_access_list,
15155 no_ipv6_bgp_distance_source_access_list_cmd,
15156 "no distance (1-255) X:X::X:X/M WORD",
15157 NO_STR
15158 "Define an administrative distance\n"
15159 "Administrative distance\n"
15160 "IP source prefix\n"
15161 "Access list name\n")
718e3744 15162{
585f1adc
IR
15163 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15164 return CMD_SUCCESS;
15165}
37a87b8f 15166
585f1adc
IR
15167DEFUN (bgp_damp_set,
15168 bgp_damp_set_cmd,
a30fec23 15169 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15170 "BGP Specific commands\n"
15171 "Enable route-flap dampening\n"
15172 "Half-life time for the penalty\n"
15173 "Value to start reusing a route\n"
15174 "Value to start suppressing a route\n"
15175 "Maximum duration to suppress a stable route\n")
15176{
15177 VTY_DECLVAR_CONTEXT(bgp, bgp);
15178 int idx_half_life = 2;
15179 int idx_reuse = 3;
15180 int idx_suppress = 4;
15181 int idx_max_suppress = 5;
37a87b8f
CS
15182 int half = DEFAULT_HALF_LIFE * 60;
15183 int reuse = DEFAULT_REUSE;
15184 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
15185 int max = 4 * half;
15186
15187 if (argc == 6) {
15188 half = atoi(argv[idx_half_life]->arg) * 60;
15189 reuse = atoi(argv[idx_reuse]->arg);
15190 suppress = atoi(argv[idx_suppress]->arg);
15191 max = atoi(argv[idx_max_suppress]->arg) * 60;
15192 } else if (argc == 3) {
15193 half = atoi(argv[idx_half_life]->arg) * 60;
15194 max = 4 * half;
15195 }
15196
15197 /*
15198 * These can't be 0 but our SA doesn't understand the
15199 * way our cli is constructed
15200 */
15201 assert(reuse);
15202 assert(half);
15203 if (suppress < reuse) {
15204 vty_out(vty,
15205 "Suppress value cannot be less than reuse value \n");
15206 return 0;
15207 }
15208
15209 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15210 reuse, suppress, max);
15211}
15212
15213DEFUN (bgp_damp_unset,
15214 bgp_damp_unset_cmd,
a30fec23 15215 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
15216 NO_STR
15217 "BGP Specific commands\n"
15218 "Enable route-flap dampening\n"
15219 "Half-life time for the penalty\n"
15220 "Value to start reusing a route\n"
15221 "Value to start suppressing a route\n"
15222 "Maximum duration to suppress a stable route\n")
15223{
15224 VTY_DECLVAR_CONTEXT(bgp, bgp);
15225 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 15226}
15227
718e3744 15228/* Display specified route of BGP table. */
d62a17ae 15229static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15230 const char *ip_str, afi_t afi, safi_t safi,
15231 struct prefix_rd *prd, int prefix_check)
15232{
15233 int ret;
15234 struct prefix match;
9bcb3eef
DS
15235 struct bgp_dest *dest;
15236 struct bgp_dest *rm;
40381db7
DS
15237 struct bgp_path_info *pi;
15238 struct bgp_path_info *pi_temp;
d62a17ae 15239 struct bgp *bgp;
15240 struct bgp_table *table;
15241
15242 /* BGP structure lookup. */
15243 if (view_name) {
15244 bgp = bgp_lookup_by_name(view_name);
15245 if (bgp == NULL) {
15246 vty_out(vty, "%% Can't find BGP instance %s\n",
15247 view_name);
15248 return CMD_WARNING;
15249 }
15250 } else {
15251 bgp = bgp_get_default();
15252 if (bgp == NULL) {
15253 vty_out(vty, "%% No BGP process is configured\n");
15254 return CMD_WARNING;
15255 }
718e3744 15256 }
718e3744 15257
d62a17ae 15258 /* Check IP address argument. */
15259 ret = str2prefix(ip_str, &match);
15260 if (!ret) {
15261 vty_out(vty, "%% address is malformed\n");
15262 return CMD_WARNING;
15263 }
718e3744 15264
d62a17ae 15265 match.family = afi2family(afi);
15266
15267 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15268 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15269 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15270 dest = bgp_route_next(dest)) {
15271 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15272
9bcb3eef 15273 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15274 continue;
9bcb3eef 15275 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15276 if (!table)
ea47320b 15277 continue;
4953391b
DA
15278 rm = bgp_node_match(table, &match);
15279 if (rm == NULL)
ea47320b 15280 continue;
d62a17ae 15281
9bcb3eef 15282 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15283
ea47320b 15284 if (!prefix_check
b54892e0 15285 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15286 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15287 while (pi) {
15288 if (pi->extra && pi->extra->damp_info) {
15289 pi_temp = pi->next;
ea47320b 15290 bgp_damp_info_free(
19971c9a 15291 pi->extra->damp_info,
5c8846f6 15292 1, afi, safi);
40381db7 15293 pi = pi_temp;
ea47320b 15294 } else
40381db7 15295 pi = pi->next;
d62a17ae 15296 }
ea47320b
DL
15297 }
15298
9bcb3eef 15299 bgp_dest_unlock_node(rm);
d62a17ae 15300 }
15301 } else {
4953391b
DA
15302 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15303 if (dest != NULL) {
9bcb3eef 15304 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15305
d62a17ae 15306 if (!prefix_check
9bcb3eef
DS
15307 || dest_p->prefixlen == match.prefixlen) {
15308 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15309 while (pi) {
15310 if (pi->extra && pi->extra->damp_info) {
15311 pi_temp = pi->next;
d62a17ae 15312 bgp_damp_info_free(
19971c9a 15313 pi->extra->damp_info,
5c8846f6 15314 1, afi, safi);
40381db7 15315 pi = pi_temp;
d62a17ae 15316 } else
40381db7 15317 pi = pi->next;
d62a17ae 15318 }
15319 }
15320
9bcb3eef 15321 bgp_dest_unlock_node(dest);
d62a17ae 15322 }
15323 }
718e3744 15324
d62a17ae 15325 return CMD_SUCCESS;
718e3744 15326}
15327
15328DEFUN (clear_ip_bgp_dampening,
15329 clear_ip_bgp_dampening_cmd,
15330 "clear ip bgp dampening",
15331 CLEAR_STR
15332 IP_STR
15333 BGP_STR
15334 "Clear route flap dampening information\n")
15335{
b4f7f45b 15336 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15337 return CMD_SUCCESS;
718e3744 15338}
15339
15340DEFUN (clear_ip_bgp_dampening_prefix,
15341 clear_ip_bgp_dampening_prefix_cmd,
15342 "clear ip bgp dampening A.B.C.D/M",
15343 CLEAR_STR
15344 IP_STR
15345 BGP_STR
15346 "Clear route flap dampening information\n"
0c7b1b01 15347 "IPv4 prefix\n")
718e3744 15348{
d62a17ae 15349 int idx_ipv4_prefixlen = 4;
15350 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15351 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15352}
15353
15354DEFUN (clear_ip_bgp_dampening_address,
15355 clear_ip_bgp_dampening_address_cmd,
15356 "clear ip bgp dampening A.B.C.D",
15357 CLEAR_STR
15358 IP_STR
15359 BGP_STR
15360 "Clear route flap dampening information\n"
15361 "Network to clear damping information\n")
15362{
d62a17ae 15363 int idx_ipv4 = 4;
15364 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15365 SAFI_UNICAST, NULL, 0);
718e3744 15366}
15367
15368DEFUN (clear_ip_bgp_dampening_address_mask,
15369 clear_ip_bgp_dampening_address_mask_cmd,
15370 "clear ip bgp dampening A.B.C.D A.B.C.D",
15371 CLEAR_STR
15372 IP_STR
15373 BGP_STR
15374 "Clear route flap dampening information\n"
15375 "Network to clear damping information\n"
15376 "Network mask\n")
15377{
d62a17ae 15378 int idx_ipv4 = 4;
15379 int idx_ipv4_2 = 5;
15380 int ret;
15381 char prefix_str[BUFSIZ];
718e3744 15382
d62a17ae 15383 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15384 prefix_str, sizeof(prefix_str));
d62a17ae 15385 if (!ret) {
15386 vty_out(vty, "%% Inconsistent address and mask\n");
15387 return CMD_WARNING;
15388 }
718e3744 15389
d62a17ae 15390 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15391 NULL, 0);
718e3744 15392}
6b0655a2 15393
e3b78da8 15394static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15395{
15396 struct vty *vty = arg;
e3b78da8 15397 struct peer *peer = bucket->data;
825d9834 15398
47e12884 15399 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15400}
15401
2a0e69ae
DS
15402DEFUN (show_bgp_listeners,
15403 show_bgp_listeners_cmd,
15404 "show bgp listeners",
15405 SHOW_STR
15406 BGP_STR
15407 "Display Listen Sockets and who created them\n")
15408{
15409 bgp_dump_listener_info(vty);
15410
15411 return CMD_SUCCESS;
15412}
15413
825d9834
DS
15414DEFUN (show_bgp_peerhash,
15415 show_bgp_peerhash_cmd,
15416 "show bgp peerhash",
15417 SHOW_STR
15418 BGP_STR
15419 "Display information about the BGP peerhash\n")
15420{
15421 struct list *instances = bm->bgp;
15422 struct listnode *node;
15423 struct bgp *bgp;
15424
15425 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15426 vty_out(vty, "BGP: %s\n", bgp->name);
15427 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15428 vty);
15429 }
15430
15431 return CMD_SUCCESS;
15432}
15433
587ff0fd 15434/* also used for encap safi */
2b791107
DL
15435static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15436 afi_t afi, safi_t safi)
d62a17ae 15437{
9bcb3eef
DS
15438 struct bgp_dest *pdest;
15439 struct bgp_dest *dest;
d62a17ae 15440 struct bgp_table *table;
b54892e0
DS
15441 const struct prefix *p;
15442 const struct prefix_rd *prd;
d62a17ae 15443 struct bgp_static *bgp_static;
15444 mpls_label_t label;
d62a17ae 15445
15446 /* Network configuration. */
9bcb3eef
DS
15447 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15448 pdest = bgp_route_next(pdest)) {
15449 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15450 if (!table)
ea47320b 15451 continue;
d62a17ae 15452
9bcb3eef
DS
15453 for (dest = bgp_table_top(table); dest;
15454 dest = bgp_route_next(dest)) {
15455 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15456 if (bgp_static == NULL)
ea47320b 15457 continue;
d62a17ae 15458
9bcb3eef
DS
15459 p = bgp_dest_get_prefix(dest);
15460 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15461 pdest);
d62a17ae 15462
ea47320b 15463 /* "network" configuration display. */
ea47320b
DL
15464 label = decode_label(&bgp_static->label);
15465
c4f64ea9 15466 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15467 if (safi == SAFI_MPLS_VPN)
15468 vty_out(vty, " label %u", label);
15469
15470 if (bgp_static->rmap.name)
15471 vty_out(vty, " route-map %s",
15472 bgp_static->rmap.name);
e2a86ad9
DS
15473
15474 if (bgp_static->backdoor)
15475 vty_out(vty, " backdoor");
15476
ea47320b
DL
15477 vty_out(vty, "\n");
15478 }
15479 }
d62a17ae 15480}
15481
2b791107
DL
15482static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15483 afi_t afi, safi_t safi)
d62a17ae 15484{
9bcb3eef
DS
15485 struct bgp_dest *pdest;
15486 struct bgp_dest *dest;
d62a17ae 15487 struct bgp_table *table;
b54892e0
DS
15488 const struct prefix *p;
15489 const struct prefix_rd *prd;
d62a17ae 15490 struct bgp_static *bgp_static;
ff44f570 15491 char buf[PREFIX_STRLEN * 2];
d62a17ae 15492 char buf2[SU_ADDRSTRLEN];
5f933e1e 15493 char esi_buf[ESI_STR_LEN];
d62a17ae 15494
15495 /* Network configuration. */
9bcb3eef
DS
15496 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15497 pdest = bgp_route_next(pdest)) {
15498 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15499 if (!table)
ea47320b 15500 continue;
d62a17ae 15501
9bcb3eef
DS
15502 for (dest = bgp_table_top(table); dest;
15503 dest = bgp_route_next(dest)) {
15504 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15505 if (bgp_static == NULL)
ea47320b 15506 continue;
d62a17ae 15507
ea47320b 15508 char *macrouter = NULL;
d62a17ae 15509
ea47320b
DL
15510 if (bgp_static->router_mac)
15511 macrouter = prefix_mac2str(
15512 bgp_static->router_mac, NULL, 0);
15513 if (bgp_static->eth_s_id)
0a50c248
AK
15514 esi_to_str(bgp_static->eth_s_id,
15515 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15516 p = bgp_dest_get_prefix(dest);
15517 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15518
ea47320b 15519 /* "network" configuration display. */
197cb530
PG
15520 if (p->u.prefix_evpn.route_type == 5) {
15521 char local_buf[PREFIX_STRLEN];
3714a385 15522 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15523 struct prefix_evpn *)p)
15524 ? AF_INET
15525 : AF_INET6;
3714a385 15526 inet_ntop(family,
15527 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15528 local_buf, PREFIX_STRLEN);
772270f3
QY
15529 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15530 p->u.prefix_evpn.prefix_addr
15531 .ip_prefix_length);
197cb530
PG
15532 } else {
15533 prefix2str(p, buf, sizeof(buf));
15534 }
ea47320b 15535
a4d82a8a
PZ
15536 if (bgp_static->gatewayIp.family == AF_INET
15537 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15538 inet_ntop(bgp_static->gatewayIp.family,
15539 &bgp_static->gatewayIp.u.prefix, buf2,
15540 sizeof(buf2));
ea47320b 15541 vty_out(vty,
c4f64ea9
DA
15542 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15543 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15544 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15545 macrouter);
15546
0a22ddfb 15547 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15548 }
15549 }
3da6fcd5
PG
15550}
15551
718e3744 15552/* Configuration of static route announcement and aggregate
15553 information. */
2b791107
DL
15554void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15555 safi_t safi)
d62a17ae 15556{
9bcb3eef 15557 struct bgp_dest *dest;
b54892e0 15558 const struct prefix *p;
d62a17ae 15559 struct bgp_static *bgp_static;
15560 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15561
2b791107
DL
15562 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15563 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15564 return;
15565 }
d62a17ae 15566
2b791107
DL
15567 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15568 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15569 return;
15570 }
d62a17ae 15571
15572 /* Network configuration. */
9bcb3eef
DS
15573 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15574 dest = bgp_route_next(dest)) {
15575 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15576 if (bgp_static == NULL)
ea47320b 15577 continue;
d62a17ae 15578
9bcb3eef 15579 p = bgp_dest_get_prefix(dest);
d62a17ae 15580
8228a9a7 15581 vty_out(vty, " network %pFX", p);
d62a17ae 15582
ea47320b
DL
15583 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15584 vty_out(vty, " label-index %u",
15585 bgp_static->label_index);
d62a17ae 15586
ea47320b
DL
15587 if (bgp_static->rmap.name)
15588 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15589
15590 if (bgp_static->backdoor)
15591 vty_out(vty, " backdoor");
718e3744 15592
ea47320b
DL
15593 vty_out(vty, "\n");
15594 }
15595
d62a17ae 15596 /* Aggregate-address configuration. */
9bcb3eef
DS
15597 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15598 dest = bgp_route_next(dest)) {
15599 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15600 if (bgp_aggregate == NULL)
ea47320b 15601 continue;
d62a17ae 15602
9bcb3eef 15603 p = bgp_dest_get_prefix(dest);
d62a17ae 15604
8228a9a7 15605 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15606
ea47320b
DL
15607 if (bgp_aggregate->as_set)
15608 vty_out(vty, " as-set");
d62a17ae 15609
ea47320b
DL
15610 if (bgp_aggregate->summary_only)
15611 vty_out(vty, " summary-only");
718e3744 15612
20894f50
DA
15613 if (bgp_aggregate->rmap.name)
15614 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15615
229757f1
DA
15616 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15617 vty_out(vty, " origin %s",
15618 bgp_origin2str(bgp_aggregate->origin));
15619
6aabb15d
RZ
15620 if (bgp_aggregate->match_med)
15621 vty_out(vty, " matching-MED-only");
15622
365ab2e7
RZ
15623 if (bgp_aggregate->suppress_map_name)
15624 vty_out(vty, " suppress-map %s",
15625 bgp_aggregate->suppress_map_name);
15626
ea47320b
DL
15627 vty_out(vty, "\n");
15628 }
d62a17ae 15629}
734b349e 15630
2b791107 15631void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15632 safi_t safi)
d62a17ae 15633{
9bcb3eef 15634 struct bgp_dest *dest;
d62a17ae 15635 struct bgp_distance *bdistance;
15636
15637 /* Distance configuration. */
15638 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15639 && bgp->distance_local[afi][safi]
15640 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15641 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15642 || bgp->distance_local[afi][safi]
15643 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15644 vty_out(vty, " distance bgp %d %d %d\n",
15645 bgp->distance_ebgp[afi][safi],
15646 bgp->distance_ibgp[afi][safi],
15647 bgp->distance_local[afi][safi]);
15648 }
734b349e 15649
9bcb3eef
DS
15650 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15651 dest = bgp_route_next(dest)) {
15652 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15653 if (bdistance != NULL)
56ca3b5b 15654 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15655 bdistance->distance, dest,
d62a17ae 15656 bdistance->access_list ? bdistance->access_list
15657 : "");
ca2e160d 15658 }
718e3744 15659}
15660
15661/* Allocate routing table structure and install commands. */
d62a17ae 15662void bgp_route_init(void)
15663{
15664 afi_t afi;
15665 safi_t safi;
15666
15667 /* Init BGP distance table. */
05c7a1cc 15668 FOREACH_AFI_SAFI (afi, safi)
960035b2 15669 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15670
15671 /* IPv4 BGP commands. */
15672 install_element(BGP_NODE, &bgp_table_map_cmd);
15673 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15674 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15675
554b3b10 15676 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15677
15678 /* IPv4 unicast configuration. */
15679 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15680 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15681 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15682
554b3b10 15683 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15684
15685 /* IPv4 multicast configuration. */
15686 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15687 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15688 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15689 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15690
15691 /* IPv4 labeled-unicast configuration. */
fb985e0c 15692 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15693 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15694
d62a17ae 15695 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15696 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15697 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15698 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15699 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15700 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15701 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15702 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15703
15704 install_element(VIEW_NODE,
15705 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15706 install_element(VIEW_NODE,
15707 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15708 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15709 install_element(VIEW_NODE,
15710 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15711#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15712 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15713#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15714 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15715 install_element(VIEW_NODE,
44c69747 15716 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15717
d62a17ae 15718 /* BGP dampening clear commands */
15719 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15720 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15721
d62a17ae 15722 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15723 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15724
15725 /* prefix count */
15726 install_element(ENABLE_NODE,
15727 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15728#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15729 install_element(ENABLE_NODE,
15730 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15731#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15732
d62a17ae 15733 /* New config IPv6 BGP commands. */
15734 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15735 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15736 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15737
554b3b10 15738 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15739
15740 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15741
fb985e0c
DA
15742 /* IPv6 labeled unicast address family. */
15743 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15744 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15745
d62a17ae 15746 install_element(BGP_NODE, &bgp_distance_cmd);
15747 install_element(BGP_NODE, &no_bgp_distance_cmd);
15748 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15749 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15750 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15751 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15752 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15753 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15754 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15755 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15756 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15757 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15758 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15759 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15760 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15761 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15762 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15763 install_element(BGP_IPV4M_NODE,
15764 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15765 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15766 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15767 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15768 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15769 install_element(BGP_IPV6_NODE,
15770 &ipv6_bgp_distance_source_access_list_cmd);
15771 install_element(BGP_IPV6_NODE,
15772 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15773 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15774 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15775 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15776 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15777 install_element(BGP_IPV6M_NODE,
15778 &ipv6_bgp_distance_source_access_list_cmd);
15779 install_element(BGP_IPV6M_NODE,
15780 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15781
ef5f4b23 15782 /* BGP dampening */
585f1adc
IR
15783 install_element(BGP_NODE, &bgp_damp_set_cmd);
15784 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15785 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15786 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15787 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15788 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15789 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15790 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15791 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15792 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15793 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15794 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15795 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15796 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15797
15798 /* Large Communities */
15799 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15800 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15801
15802 /* show bgp ipv4 flowspec detailed */
15803 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15804
2a0e69ae 15805 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15806 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15807}
15808
15809void bgp_route_finish(void)
15810{
15811 afi_t afi;
15812 safi_t safi;
15813
05c7a1cc
QY
15814 FOREACH_AFI_SAFI (afi, safi) {
15815 bgp_table_unlock(bgp_distance_table[afi][safi]);
15816 bgp_distance_table[afi][safi] = NULL;
15817 }
228da428 15818}